diff --git a/drift_dev/lib/src/writer/queries/sql_writer.dart b/drift_dev/lib/src/writer/queries/sql_writer.dart index 3ccd5db8..29da9c23 100644 --- a/drift_dev/lib/src/writer/queries/sql_writer.dart +++ b/drift_dev/lib/src/writer/queries/sql_writer.dart @@ -82,6 +82,16 @@ class SqlWriter extends NodeSqlBuilder { return _out.toString(); } + @override + bool isKeyword(String lexeme) { + switch (options.effectiveDialect) { + case SqlDialect.postgres: + return isKeywordLexeme(lexeme) || isPostgresKeywordLexeme(lexeme); + default: + return isKeywordLexeme(lexeme); + } + } + FoundVariable? _findMoorVar(Variable target) { return query!.variables.firstWhereOrNull( (f) => f.variable.resolvedIndex == target.resolvedIndex); diff --git a/drift_dev/pubspec.yaml b/drift_dev/pubspec.yaml index c3beb935..a16db2f9 100644 --- a/drift_dev/pubspec.yaml +++ b/drift_dev/pubspec.yaml @@ -1,6 +1,6 @@ name: drift_dev description: Dev-dependency for users of drift. Contains the generator and development tools. -version: 2.5.1 +version: 2.6.0-dev repository: https://github.com/simolus3/drift homepage: https://drift.simonbinder.eu/ issue_tracker: https://github.com/simolus3/drift/issues @@ -27,7 +27,7 @@ dependencies: # Drift-specific analysis and apis drift: '>=2.5.0 <2.6.0' sqlite3: '>=0.1.6 <2.0.0' - sqlparser: '^0.27.0' + sqlparser: '^0.28.0' # Dart analysis analyzer: ^5.2.0 diff --git a/drift_dev/test/writer/queries/sql_writer_test.dart b/drift_dev/test/writer/queries/sql_writer_test.dart index c7de3dbe..0b603981 100644 --- a/drift_dev/test/writer/queries/sql_writer_test.dart +++ b/drift_dev/test/writer/queries/sql_writer_test.dart @@ -1,3 +1,4 @@ +import 'package:drift/drift.dart'; import 'package:drift_dev/src/analysis/options.dart'; import 'package:drift_dev/src/analysis/results/results.dart'; import 'package:drift_dev/src/writer/queries/sql_writer.dart'; @@ -5,14 +6,14 @@ import 'package:sqlparser/sqlparser.dart'; import 'package:test/test.dart'; void main() { - void check(String sql, String expectedDart) { + void check(String sql, String expectedDart, + {DriftOptions options = const DriftOptions.defaults()}) { final engine = SqlEngine(); final context = engine.analyze(sql); final query = SqlSelectQuery('name', context, context.root, [], [], InferredResultSet(null, []), null, null); - final result = - SqlWriter(const DriftOptions.defaults(), query: query).write(); + final result = SqlWriter(options, query: query).write(); expect(result, expectedDart); } @@ -28,4 +29,11 @@ void main() { test('escapes Dart characters in SQL', () { check(r"SELECT '$hey';", r"'SELECT \'\$hey\''"); }); + + test('escapes postgres keywords', () { + check('SELECT * FROM user', "'SELECT * FROM user'"); + check('SELECT * FROM user', "'SELECT * FROM \"user\"'", + options: DriftOptions.defaults( + dialect: DialectOptions(SqlDialect.postgres, null))); + }); } diff --git a/extras/integration_tests/drift_testcases/lib/database/database.dart b/extras/integration_tests/drift_testcases/lib/database/database.dart index 40d1db76..b285842c 100644 --- a/extras/integration_tests/drift_testcases/lib/database/database.dart +++ b/extras/integration_tests/drift_testcases/lib/database/database.dart @@ -69,7 +69,7 @@ class PreferenceConverter extends NullAwareTypeConverter { 'ORDER BY (SELECT COUNT(*) FROM friendships ' 'WHERE first_user = u.id OR second_user = u.id) DESC LIMIT :amount', 'amountOfGoodFriends': 'SELECT COUNT(*) FROM friendships f WHERE ' - 'f.really_good_friends = 1 AND ' + 'f.really_good_friends = TRUE AND ' '(f.first_user = :user OR f.second_user = :user)', 'friendshipsOf': ''' SELECT f.really_good_friends, "user".** diff --git a/extras/integration_tests/drift_testcases/lib/database/database.g.dart b/extras/integration_tests/drift_testcases/lib/database/database.g.dart index b5689ce6..61310c1b 100644 --- a/extras/integration_tests/drift_testcases/lib/database/database.g.dart +++ b/extras/integration_tests/drift_testcases/lib/database/database.g.dart @@ -555,7 +555,7 @@ abstract class _$Database extends GeneratedDatabase { Selectable amountOfGoodFriends(int user) { return customSelect( - 'SELECT COUNT(*) AS _c0 FROM friendships AS f WHERE f.really_good_friends = 1 AND(f.first_user = @1 OR f.second_user = @1)', + 'SELECT COUNT(*) AS _c0 FROM friendships AS f WHERE f.really_good_friends = TRUE AND(f.first_user = @1 OR f.second_user = @1)', variables: [ Variable(user) ], @@ -566,7 +566,7 @@ abstract class _$Database extends GeneratedDatabase { Selectable friendshipsOf(int user) { return customSelect( - 'SELECT f.really_good_friends,"user"."id" AS "nested_0.id", "user"."name" AS "nested_0.name", "user"."birth_date" AS "nested_0.birth_date", "user"."profile_picture" AS "nested_0.profile_picture", "user"."preferences" AS "nested_0.preferences" FROM friendships AS f INNER JOIN users AS user ON user.id IN (f.first_user, f.second_user) AND user.id != @1 WHERE(f.first_user = @1 OR f.second_user = @1)', + 'SELECT f.really_good_friends,"user"."id" AS "nested_0.id", "user"."name" AS "nested_0.name", "user"."birth_date" AS "nested_0.birth_date", "user"."profile_picture" AS "nested_0.profile_picture", "user"."preferences" AS "nested_0.preferences" FROM friendships AS f INNER JOIN users AS "user" ON "user".id IN (f.first_user, f.second_user) AND "user".id != @1 WHERE(f.first_user = @1 OR f.second_user = @1)', variables: [ Variable(user) ], diff --git a/sqlparser/lib/utils/node_to_text.dart b/sqlparser/lib/utils/node_to_text.dart index 71b393bf..dd2e5f7d 100644 --- a/sqlparser/lib/utils/node_to_text.dart +++ b/sqlparser/lib/utils/node_to_text.dart @@ -24,6 +24,10 @@ class NodeSqlBuilder extends AstVisitor { } } + bool isKeyword(String lexeme) { + return isKeywordLexeme(lexeme); + } + @override void visitAggregateFunctionInvocation( AggregateFunctionInvocation e, void arg) { @@ -1321,7 +1325,7 @@ class NodeSqlBuilder extends AstVisitor { /// Writes an identifier, escaping it if necessary. void identifier(String identifier, {bool spaceBefore = true, bool spaceAfter = true}) { - if (isKeywordLexeme(identifier) || _notAKeywordRegex.hasMatch(identifier)) { + if (isKeyword(identifier) || _notAKeywordRegex.hasMatch(identifier)) { identifier = '"$identifier"'; } diff --git a/sqlparser/pubspec.yaml b/sqlparser/pubspec.yaml index 4db115c8..62cf4bf8 100644 --- a/sqlparser/pubspec.yaml +++ b/sqlparser/pubspec.yaml @@ -1,6 +1,6 @@ name: sqlparser description: Parses sqlite statements and performs static analysis on them -version: 0.27.0 +version: 0.28.0-dev homepage: https://github.com/simolus3/drift/tree/develop/sqlparser repository: https://github.com/simolus3/drift #homepage: https://drift.simonbinder.eu/