mirror of https://github.com/AMT-Cheif/drift.git
Always escape column names
This avoids the performance impact of using a regex in `escapeIfNeeded`. Closes #2071.
This commit is contained in:
parent
be61af5111
commit
28c90b6ffb
|
@ -1,3 +1,8 @@
|
|||
## 2.2.0-dev
|
||||
|
||||
- Always escape column names, avoiding the costs or using a regular expression
|
||||
to check whether they need to be escaped.
|
||||
|
||||
## 2.1.0
|
||||
|
||||
- Improve stack traces when using `watchSingle()` with a stream emitting a non-
|
||||
|
|
|
@ -386,7 +386,7 @@ class $TodoItemsTable extends TodoItems
|
|||
'category_id', aliasedName, false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: true,
|
||||
defaultConstraints: 'REFERENCES todo_categories (id)');
|
||||
defaultConstraints: 'REFERENCES "todo_categories" ("id")');
|
||||
final VerificationMeta _generatedTextMeta =
|
||||
const VerificationMeta('generatedText');
|
||||
@override
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/// Provides utilities around sql keywords, like optional escaping etc.
|
||||
@Deprecated('Drift is no longer using this library and will remove it in the '
|
||||
'next breaking release')
|
||||
library drift.sqlite_keywords;
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
|
|
|
@ -38,8 +38,12 @@ abstract class Column<T extends Object> extends Expression<T> {
|
|||
/// needed.
|
||||
String get name;
|
||||
|
||||
/// [name], but escaped if it's an sql keyword.
|
||||
String get escapedName => escapeIfNeeded(name);
|
||||
/// [name], but wrapped in double quotes to escape it as a a same identifier.
|
||||
///
|
||||
/// In the past, this getter only used to add double-quotes when that is
|
||||
/// really needed (for instance because [name] is also a reserved keyword).
|
||||
/// For performance reasons, we unconditionally escape names now.
|
||||
String get escapedName => '"$name"';
|
||||
}
|
||||
|
||||
/// A column that stores int values.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/sqlite_keywords.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:meta/meta_meta.dart';
|
||||
|
||||
|
|
|
@ -77,4 +77,8 @@ class GenerationContext {
|
|||
|
||||
/// Shortcut to add a single space to the buffer because it's used very often.
|
||||
void writeWhitespace() => buffer.write(' ');
|
||||
|
||||
/// Turns [columnName] into a safe SQL identifier by wrapping it in double
|
||||
/// quotes.
|
||||
String identifier(String columnName) => '"$columnName"';
|
||||
}
|
||||
|
|
|
@ -227,15 +227,16 @@ class Migrator {
|
|||
expr.writeInto(context);
|
||||
first = false;
|
||||
}
|
||||
context.buffer.write(' FROM ${escapeIfNeeded(tableName)};');
|
||||
context.buffer.write(' FROM ${context.identifier(tableName)};');
|
||||
await _issueCustomQuery(context.sql, context.introducedVariables);
|
||||
|
||||
// Step 6: Drop the old table
|
||||
await _issueCustomQuery('DROP TABLE ${escapeIfNeeded(tableName)}');
|
||||
await _issueCustomQuery('DROP TABLE ${context.identifier(tableName)}');
|
||||
|
||||
// Step 7: Rename the new table to the old name
|
||||
await _issueCustomQuery('ALTER TABLE ${escapeIfNeeded(temporaryName)} '
|
||||
'RENAME TO ${escapeIfNeeded(tableName)}');
|
||||
await _issueCustomQuery(
|
||||
'ALTER TABLE ${context.identifier(temporaryName)} '
|
||||
'RENAME TO ${context.identifier(tableName)}');
|
||||
|
||||
// Step 8: Re-create associated indexes, triggers and views
|
||||
for (final stmt in createAffected) {
|
||||
|
@ -253,7 +254,7 @@ class Migrator {
|
|||
|
||||
void _writeCreateTable(TableInfo table, GenerationContext context) {
|
||||
context.buffer.write('CREATE TABLE IF NOT EXISTS '
|
||||
'${escapeIfNeeded(table.aliasedName, context.dialect)} (');
|
||||
'${context.identifier(table.aliasedName)} (');
|
||||
|
||||
var hasAutoIncrement = false;
|
||||
for (var i = 0; i < table.$columns.length; i++) {
|
||||
|
@ -281,7 +282,7 @@ class Migrator {
|
|||
for (var i = 0; i < pkList.length; i++) {
|
||||
final column = pkList[i];
|
||||
|
||||
context.buffer.write(escapeIfNeeded(column.$name));
|
||||
context.buffer.write(column.escapedName);
|
||||
|
||||
if (i != pkList.length - 1) context.buffer.write(', ');
|
||||
}
|
||||
|
@ -295,7 +296,7 @@ class Migrator {
|
|||
for (var i = 0; i < uqList.length; i++) {
|
||||
final column = uqList[i];
|
||||
|
||||
context.buffer.write(escapeIfNeeded(column.name));
|
||||
context.buffer.write(column.escapedName);
|
||||
|
||||
if (i != uqList.length - 1) context.buffer.write(', ');
|
||||
}
|
||||
|
@ -327,7 +328,7 @@ class Migrator {
|
|||
void _writeCreateVirtual(VirtualTableInfo table, GenerationContext context) {
|
||||
context.buffer
|
||||
..write('CREATE VIRTUAL TABLE IF NOT EXISTS ')
|
||||
..write(escapeIfNeeded(table.aliasedName))
|
||||
..write(context.identifier(table.aliasedName))
|
||||
..write(' USING ')
|
||||
..write(table.moduleAndArgs)
|
||||
..write(';');
|
||||
|
@ -353,8 +354,8 @@ class Migrator {
|
|||
final columnNames = view.$columns.map((e) => e.escapedName).join(', ');
|
||||
|
||||
context.generatingForView = view.entityName;
|
||||
context.buffer.write(
|
||||
'CREATE VIEW IF NOT EXISTS ${view.entityName} ($columnNames) AS ');
|
||||
context.buffer.write('CREATE VIEW IF NOT EXISTS '
|
||||
'${context.identifier(view.entityName)} ($columnNames) AS ');
|
||||
view.query!.writeInto(context);
|
||||
await _issueCustomQuery(context.sql, const []);
|
||||
}
|
||||
|
@ -362,7 +363,8 @@ class Migrator {
|
|||
|
||||
/// Drops a table, trigger or index.
|
||||
Future<void> drop(DatabaseSchemaEntity entity) async {
|
||||
final escapedName = escapeIfNeeded(entity.entityName);
|
||||
final context = _createContext();
|
||||
final escapedName = context.identifier(entity.entityName);
|
||||
|
||||
String kind;
|
||||
|
||||
|
@ -385,15 +387,17 @@ class Migrator {
|
|||
/// Deletes the table with the given name. Note that this function does not
|
||||
/// escape the [name] parameter.
|
||||
Future<void> deleteTable(String name) async {
|
||||
return _issueCustomQuery('DROP TABLE IF EXISTS $name;');
|
||||
final context = _createContext();
|
||||
return _issueCustomQuery(
|
||||
'DROP TABLE IF EXISTS ${context.identifier(name)};');
|
||||
}
|
||||
|
||||
/// Adds the given column to the specified table.
|
||||
Future<void> addColumn(TableInfo table, GeneratedColumn column) async {
|
||||
final context = _createContext();
|
||||
|
||||
context.buffer
|
||||
.write('ALTER TABLE ${escapeIfNeeded(table.aliasedName)} ADD COLUMN ');
|
||||
context.buffer.write(
|
||||
'ALTER TABLE ${context.identifier(table.aliasedName)} ADD COLUMN ');
|
||||
column.writeColumnDefinition(context);
|
||||
context.buffer.write(';');
|
||||
|
||||
|
@ -421,8 +425,8 @@ class Migrator {
|
|||
TableInfo table, String oldName, GeneratedColumn column) async {
|
||||
final context = _createContext();
|
||||
context.buffer
|
||||
..write('ALTER TABLE ${escapeIfNeeded(table.aliasedName)} ')
|
||||
..write('RENAME COLUMN ${escapeIfNeeded(oldName)} ')
|
||||
..write('ALTER TABLE ${context.identifier(table.aliasedName)} ')
|
||||
..write('RENAME COLUMN ${context.identifier(oldName)} ')
|
||||
..write('TO ${column.escapedName};');
|
||||
|
||||
return _issueCustomQuery(context.sql);
|
||||
|
@ -436,8 +440,8 @@ class Migrator {
|
|||
/// databases.
|
||||
Future<void> renameTable(TableInfo table, String oldName) async {
|
||||
final context = _createContext();
|
||||
context.buffer.write('ALTER TABLE ${escapeIfNeeded(oldName)} '
|
||||
'RENAME TO ${escapeIfNeeded(table.actualTableName)};');
|
||||
context.buffer.write('ALTER TABLE ${context.identifier(oldName)} '
|
||||
'RENAME TO ${context.identifier(table.actualTableName)};');
|
||||
return _issueCustomQuery(context.sql);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'dart:async';
|
|||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/sqlite_keywords.dart';
|
||||
import 'package:drift/src/runtime/executor/stream_queries.dart';
|
||||
import 'package:drift/src/utils/single_transformer.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
|
|
@ -175,7 +175,7 @@ class GeneratedColumn<T extends Object> extends Column<T> {
|
|||
} else {
|
||||
if (context.hasMultipleTables) {
|
||||
context.buffer
|
||||
..write(tableName)
|
||||
..write(context.identifier(tableName))
|
||||
..write('.');
|
||||
}
|
||||
context.buffer.write(ignoreEscape ? $name : escapedName);
|
||||
|
|
|
@ -140,9 +140,9 @@ extension NameWithAlias on ResultSetImplementation<dynamic, dynamic> {
|
|||
/// for a table called users that has been aliased as "u".
|
||||
String get tableWithAlias {
|
||||
if (aliasedName == entityName) {
|
||||
return entityName;
|
||||
return '"$entityName"';
|
||||
} else {
|
||||
return '$entityName $aliasedName';
|
||||
return '"$entityName" "$aliasedName"';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ class InsertStatement<T extends Table, D> {
|
|||
..write(_insertKeywords[
|
||||
ctx.dialect == SqlDialect.postgres ? InsertMode.insert : mode])
|
||||
..write(' INTO ')
|
||||
..write(table.aliasedName)
|
||||
..write(ctx.identifier(table.aliasedName))
|
||||
..write(' ');
|
||||
|
||||
if (map.isEmpty) {
|
||||
|
@ -210,7 +210,7 @@ class InsertStatement<T extends Table, D> {
|
|||
|
||||
first = true;
|
||||
for (final update in updateSet.entries) {
|
||||
final column = escapeIfNeeded(update.key);
|
||||
final column = ctx.identifier(update.key);
|
||||
|
||||
if (!first) ctx.buffer.write(', ');
|
||||
ctx.buffer.write('$column = ');
|
||||
|
@ -260,7 +260,7 @@ class InsertStatement<T extends Table, D> {
|
|||
/// Writes column names and values from the [map].
|
||||
@internal
|
||||
void writeInsertable(GenerationContext ctx, Map<String, Expression> map) {
|
||||
final columns = map.keys.map(escapeIfNeeded);
|
||||
final columns = map.keys.map(ctx.identifier);
|
||||
|
||||
ctx.buffer
|
||||
..write('(')
|
||||
|
|
|
@ -24,7 +24,7 @@ class UpdateStatement<T extends Table, D> extends Query<T, D>
|
|||
}
|
||||
|
||||
ctx.buffer
|
||||
..write(escapeIfNeeded(columnName))
|
||||
..write(ctx.identifier(columnName))
|
||||
..write(' = ');
|
||||
|
||||
variable.writeInto(ctx);
|
||||
|
|
|
@ -52,12 +52,12 @@ void main() {
|
|||
transaction.runBatched(
|
||||
BatchedStatements(
|
||||
[
|
||||
'INSERT INTO todos (content) VALUES (?)',
|
||||
'UPDATE users SET name = ?;',
|
||||
'UPDATE users SET name = ? WHERE name = ?;',
|
||||
'UPDATE categories SET "desc" = ?, priority = 0 WHERE id = ?;',
|
||||
'DELETE FROM categories WHERE 1;',
|
||||
'DELETE FROM todos WHERE id = ?;',
|
||||
'INSERT INTO "todos" ("content") VALUES (?)',
|
||||
'UPDATE "users" SET "name" = ?;',
|
||||
'UPDATE "users" SET "name" = ? WHERE "name" = ?;',
|
||||
'UPDATE "categories" SET "desc" = ?, "priority" = 0 WHERE "id" = ?;',
|
||||
'DELETE FROM "categories" WHERE 1;',
|
||||
'DELETE FROM "todos" WHERE "id" = ?;',
|
||||
'some custom statement',
|
||||
],
|
||||
[
|
||||
|
@ -90,8 +90,8 @@ void main() {
|
|||
|
||||
verify(executor.transactions.runBatched(BatchedStatements(
|
||||
[
|
||||
('INSERT INTO categories ("desc") VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET id = ?')
|
||||
('INSERT INTO "categories" ("desc") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "id" = ?')
|
||||
],
|
||||
[
|
||||
ArgumentsForBatchedStatement(0, ['description', 42])
|
||||
|
@ -111,8 +111,8 @@ void main() {
|
|||
|
||||
verify(executor.transactions.runBatched(BatchedStatements(
|
||||
[
|
||||
('INSERT INTO categories ("desc") VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET "desc" = ?')
|
||||
('INSERT INTO "categories" ("desc") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "desc" = ?')
|
||||
],
|
||||
[
|
||||
ArgumentsForBatchedStatement(0, ['first', 'first']),
|
||||
|
@ -145,9 +145,9 @@ void main() {
|
|||
|
||||
verify(executor.transactions.runBatched(BatchedStatements(
|
||||
[
|
||||
('INSERT INTO categories ("desc") VALUES (?) ON CONFLICT(id) '
|
||||
'DO UPDATE SET "desc" = categories."desc", '
|
||||
'priority = excluded.priority WHERE categories.id >= excluded.id')
|
||||
('INSERT INTO "categories" ("desc") VALUES (?) ON CONFLICT("id") '
|
||||
'DO UPDATE SET "desc" = "categories"."desc", '
|
||||
'"priority" = "excluded"."priority" WHERE "categories"."id" >= "excluded"."id"')
|
||||
],
|
||||
[
|
||||
ArgumentsForBatchedStatement(0, ['first']),
|
||||
|
@ -179,7 +179,7 @@ void main() {
|
|||
});
|
||||
|
||||
verify(executor.transactions.runBatched(BatchedStatements(
|
||||
['INSERT INTO categories ("desc") VALUES (?)'],
|
||||
['INSERT INTO "categories" ("desc") VALUES (?)'],
|
||||
[
|
||||
ArgumentsForBatchedStatement(0, ['first']),
|
||||
ArgumentsForBatchedStatement(0, ['second']),
|
||||
|
|
|
@ -13,7 +13,8 @@ void main() {
|
|||
|
||||
expect(
|
||||
existsExpression,
|
||||
generates('EXISTS (SELECT * FROM users WHERE users.is_awesome = ?)', [1]),
|
||||
generates(
|
||||
'EXISTS (SELECT * FROM "users" WHERE "users"."is_awesome" = ?)', [1]),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -23,7 +24,7 @@ void main() {
|
|||
|
||||
expect(
|
||||
notExistsExpression,
|
||||
generates('NOT EXISTS (SELECT * FROM users)'),
|
||||
generates('NOT EXISTS (SELECT * FROM "users")'),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,8 +27,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('generates parentheses for OR in AND', () {
|
||||
final c =
|
||||
GeneratedColumn<String>('c', 't', false, type: DriftSqlType.string);
|
||||
final c = CustomExpression<String>('c', precedence: Precedence.primary);
|
||||
final expr =
|
||||
(c.equals('A') | c.equals('B')) & (c.equals('C') | c.equals(''));
|
||||
expect(
|
||||
|
@ -54,7 +53,7 @@ void main() {
|
|||
expect(
|
||||
subqueryExpression<String>(
|
||||
db.selectOnly(db.users)..addColumns([db.users.name])),
|
||||
generates('(SELECT users.name AS "users.name" FROM users)'));
|
||||
generates('(SELECT "users"."name" AS "users.name" FROM "users")'));
|
||||
});
|
||||
|
||||
test('does not allow subqueries with more than one column', () {
|
||||
|
@ -77,8 +76,8 @@ void main() {
|
|||
innerJoin(db.categories, db.categories.id.equalsExp(db.users.id),
|
||||
useColumns: false)
|
||||
])),
|
||||
generates('(SELECT users.name AS "users.name" FROM users '
|
||||
'INNER JOIN categories ON categories.id = users.id)'),
|
||||
generates('(SELECT "users"."name" AS "users.name" FROM "users" '
|
||||
'INNER JOIN "categories" ON "categories"."id" = "users"."id")'),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -94,7 +93,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('generates a rowid expression', () {
|
||||
expect(TodoDb().categories.rowId, generates('_rowid_'));
|
||||
expect(TodoDb().categories.rowId, generates('"_rowid_"'));
|
||||
});
|
||||
|
||||
test('generates an aliased rowid expression when needed', () async {
|
||||
|
@ -108,7 +107,7 @@ void main() {
|
|||
await query.get();
|
||||
|
||||
verify(executor
|
||||
.runSelect(argThat(contains('ON categories._rowid_ = ?')), [3]));
|
||||
.runSelect(argThat(contains('ON "categories"."_rowid_" = ?')), [3]));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -28,8 +28,10 @@ void main() {
|
|||
final isInExpression = innerExpression
|
||||
.isInQuery(db.selectOnly(db.users)..addColumns([db.users.name]));
|
||||
|
||||
expect(isInExpression,
|
||||
generates('name IN (SELECT users.name AS "users.name" FROM users)'));
|
||||
expect(
|
||||
isInExpression,
|
||||
generates(
|
||||
'name IN (SELECT "users"."name" AS "users.name" FROM "users")'));
|
||||
|
||||
final ctx = stubContext();
|
||||
isInExpression.writeInto(ctx);
|
||||
|
@ -43,7 +45,7 @@ void main() {
|
|||
expect(
|
||||
isInExpression,
|
||||
generates(
|
||||
'name NOT IN (SELECT users.name AS "users.name" FROM users)'));
|
||||
'name NOT IN (SELECT "users"."name" AS "users.name" FROM "users")'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ void main() {
|
|||
test('without any constraints', () async {
|
||||
await db.delete(db.users).go();
|
||||
|
||||
verify(executor.runDelete('DELETE FROM users;', argThat(isEmpty)));
|
||||
verify(executor.runDelete('DELETE FROM "users";', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('for complex components', () async {
|
||||
|
@ -33,7 +33,8 @@ void main() {
|
|||
.go();
|
||||
|
||||
verify(executor.runDelete(
|
||||
'DELETE FROM users WHERE NOT is_awesome OR id < ?;', const [100]));
|
||||
'DELETE FROM "users" WHERE NOT "is_awesome" OR "id" < ?;',
|
||||
const [100]));
|
||||
});
|
||||
|
||||
test('to delete an entity via a dataclasss', () async {
|
||||
|
@ -42,7 +43,7 @@ void main() {
|
|||
.delete(const SharedTodo(todo: 3, user: 2));
|
||||
|
||||
verify(executor.runDelete(
|
||||
'DELETE FROM shared_todos WHERE todo = ? AND user = ?;',
|
||||
'DELETE FROM "shared_todos" WHERE "todo" = ? AND "user" = ?;',
|
||||
const [3, 2],
|
||||
));
|
||||
});
|
||||
|
@ -59,8 +60,8 @@ void main() {
|
|||
.delete(db.todosTable)
|
||||
.deleteReturning(const TodosTableCompanion(id: Value(10)));
|
||||
|
||||
verify(executor
|
||||
.runSelect('DELETE FROM todos WHERE id = ? RETURNING *;', [10]));
|
||||
verify(executor.runSelect(
|
||||
'DELETE FROM "todos" WHERE "id" = ? RETURNING *;', [10]));
|
||||
verify(streamQueries.handleTableUpdates(
|
||||
{TableUpdate.onTable(db.todosTable, kind: UpdateKind.delete)}));
|
||||
expect(returnedValue, const TodoEntry(id: 10, content: 'Content'));
|
||||
|
@ -70,7 +71,7 @@ void main() {
|
|||
final rows = await db.delete(db.users).goAndReturn();
|
||||
|
||||
expect(rows, isEmpty);
|
||||
verify(executor.runSelect('DELETE FROM users RETURNING *;', []));
|
||||
verify(executor.runSelect('DELETE FROM "users" RETURNING *;', []));
|
||||
verifyNever(streamQueries.handleTableUpdates(any));
|
||||
});
|
||||
});
|
||||
|
@ -107,19 +108,21 @@ void main() {
|
|||
test('delete()', () async {
|
||||
await db.users.delete().go();
|
||||
|
||||
verify(executor.runDelete('DELETE FROM users;', const []));
|
||||
verify(executor.runDelete('DELETE FROM "users";', const []));
|
||||
});
|
||||
|
||||
test('deleteOne()', () async {
|
||||
await db.users.deleteOne(const UsersCompanion(id: Value(3)));
|
||||
|
||||
verify(executor.runDelete('DELETE FROM users WHERE id = ?;', const [3]));
|
||||
verify(
|
||||
executor.runDelete('DELETE FROM "users" WHERE "id" = ?;', const [3]));
|
||||
});
|
||||
|
||||
test('deleteWhere', () async {
|
||||
await db.users.deleteWhere((tbl) => tbl.id.isSmallerThanValue(3));
|
||||
|
||||
verify(executor.runDelete('DELETE FROM users WHERE id < ?;', const [3]));
|
||||
verify(
|
||||
executor.runDelete('DELETE FROM "users" WHERE "id" < ?;', const [3]));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ void main() {
|
|||
title: Value.absent(),
|
||||
));
|
||||
|
||||
verify(executor.runInsert('INSERT INTO todos (content) VALUES (?)',
|
||||
verify(executor.runInsert('INSERT INTO "todos" ("content") VALUES (?)',
|
||||
['Implement insert statements']));
|
||||
});
|
||||
|
||||
|
@ -35,8 +35,8 @@ void main() {
|
|||
.toInsertable());
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO table_without_p_k '
|
||||
'(not_really_an_id, some_float, web_safe_int, custom) '
|
||||
'INSERT INTO "table_without_p_k" '
|
||||
'("not_really_an_id", "some_float", "web_safe_int", "custom") '
|
||||
'VALUES (?, ?, ?, ?)',
|
||||
[42, 3.1415, isNull, anything]));
|
||||
});
|
||||
|
@ -47,8 +47,8 @@ void main() {
|
|||
.toInsertable());
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO table_without_p_k '
|
||||
'(not_really_an_id, some_float, web_safe_int, custom) '
|
||||
'INSERT INTO "table_without_p_k" '
|
||||
'("not_really_an_id", "some_float", "web_safe_int", "custom") '
|
||||
'VALUES (?, ?, ?, ?)',
|
||||
[42, 0.0, BigInt.one, anything]));
|
||||
});
|
||||
|
@ -62,14 +62,15 @@ void main() {
|
|||
mode: InsertMode.insertOrReplace);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT OR REPLACE INTO todos (id, content) VALUES (?, ?)',
|
||||
'INSERT OR REPLACE INTO "todos" ("id", "content") VALUES (?, ?)',
|
||||
[113, 'Done']));
|
||||
});
|
||||
|
||||
test('generates DEFAULT VALUES statement when otherwise empty', () async {
|
||||
await db.into(db.pureDefaults).insert(const PureDefaultsCompanion());
|
||||
|
||||
verify(executor.runInsert('INSERT INTO pure_defaults DEFAULT VALUES', []));
|
||||
verify(
|
||||
executor.runInsert('INSERT INTO "pure_defaults" DEFAULT VALUES', []));
|
||||
});
|
||||
|
||||
test('notifies stream queries on inserts', () async {
|
||||
|
@ -156,7 +157,7 @@ void main() {
|
|||
TodosTableCompanion.insert(content: 'content', title: Value(null)));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (title, content) VALUES (?, ?)',
|
||||
'INSERT INTO "todos" ("title", "content") VALUES (?, ?)',
|
||||
[null, 'content']));
|
||||
});
|
||||
});
|
||||
|
@ -181,7 +182,7 @@ void main() {
|
|||
r'[0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12}');
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO table_without_p_k (not_really_an_id, some_float, custom) '
|
||||
'INSERT INTO "table_without_p_k" ("not_really_an_id", "some_float", "custom") '
|
||||
'VALUES (?, ?, ?)',
|
||||
[3, 3.14, matches(uuidRegex)],
|
||||
));
|
||||
|
@ -191,8 +192,8 @@ void main() {
|
|||
await db.into(db.pureDefaults).insert(
|
||||
PureDefaultsCompanion.insert(txt: Value(MyCustomObject('foo'))));
|
||||
|
||||
verify(executor
|
||||
.runInsert('INSERT INTO pure_defaults ("insert") VALUES (?)', ['foo']));
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO "pure_defaults" ("insert") VALUES (?)', ['foo']));
|
||||
});
|
||||
|
||||
test('can insert custom companions', () async {
|
||||
|
@ -204,7 +205,7 @@ void main() {
|
|||
|
||||
verify(
|
||||
executor.runInsert(
|
||||
'INSERT INTO users (name, is_awesome, profile_picture, creation_time) '
|
||||
'INSERT INTO "users" ("name", "is_awesome", "profile_picture", "creation_time") '
|
||||
'VALUES (?, 1, _custom_, '
|
||||
"CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER))",
|
||||
['User name'],
|
||||
|
@ -222,8 +223,8 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET content = ? || content',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "content" = ? || "content"',
|
||||
argThat(equals(['my content', 'important: '])),
|
||||
));
|
||||
});
|
||||
|
@ -238,9 +239,9 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET content = ? || content '
|
||||
'WHERE category = ?',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "content" = ? || "content" '
|
||||
'WHERE "category" = ?',
|
||||
argThat(equals(['my content', 'important: ', 1])),
|
||||
));
|
||||
});
|
||||
|
@ -268,9 +269,9 @@ void main() {
|
|||
]));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET content = ? || content '
|
||||
'ON CONFLICT(content) DO UPDATE SET content = ? || content',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "content" = ? || "content" '
|
||||
'ON CONFLICT("content") DO UPDATE SET "content" = ? || "content"',
|
||||
argThat(equals(['my content', 'important: ', 'second: '])),
|
||||
));
|
||||
},
|
||||
|
@ -296,11 +297,11 @@ void main() {
|
|||
]));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET content = ? || content '
|
||||
'WHERE category = ? '
|
||||
'ON CONFLICT(content) DO UPDATE SET content = ? || content '
|
||||
'WHERE category = ?',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "content" = ? || "content" '
|
||||
'WHERE "category" = ? '
|
||||
'ON CONFLICT("content") DO UPDATE SET "content" = ? || "content" '
|
||||
'WHERE "category" = ?',
|
||||
argThat(equals(['my content', 'important: ', 1, 'second: ', 1])),
|
||||
));
|
||||
},
|
||||
|
@ -316,8 +317,8 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(content) DO UPDATE SET content = ?',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("content") DO UPDATE SET "content" = ?',
|
||||
argThat(equals(['my content', 'changed'])),
|
||||
));
|
||||
});
|
||||
|
@ -332,9 +333,9 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(content) DO UPDATE SET content = ? '
|
||||
'WHERE content = title',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("content") DO UPDATE SET "content" = ? '
|
||||
'WHERE "content" = "title"',
|
||||
argThat(equals(['my content', 'changed'])),
|
||||
));
|
||||
});
|
||||
|
@ -346,8 +347,8 @@ void main() {
|
|||
TodosTableCompanion.insert(content: 'content', id: const Value(3)));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (id, content) VALUES (?, ?) '
|
||||
'ON CONFLICT(id) DO UPDATE SET id = ?, content = ?',
|
||||
'INSERT INTO "todos" ("id", "content") VALUES (?, ?) '
|
||||
'ON CONFLICT("id") DO UPDATE SET "id" = ?, "content" = ?',
|
||||
[3, 'content', 3, 'content'],
|
||||
));
|
||||
expect(id, 3);
|
||||
|
@ -364,9 +365,9 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE '
|
||||
'SET content = todos.content || excluded.content',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE '
|
||||
'SET "content" = "todos"."content" || "excluded"."content"',
|
||||
['content'],
|
||||
));
|
||||
});
|
||||
|
@ -382,10 +383,10 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO todos (content) VALUES (?) '
|
||||
'ON CONFLICT(id) DO UPDATE '
|
||||
'SET content = todos.content || excluded.content '
|
||||
'WHERE todos.title = excluded.title',
|
||||
'INSERT INTO "todos" ("content") VALUES (?) '
|
||||
'ON CONFLICT("id") DO UPDATE '
|
||||
'SET "content" = "todos"."content" || "excluded"."content" '
|
||||
'WHERE "todos"."title" = "excluded"."title"',
|
||||
['content'],
|
||||
));
|
||||
});
|
||||
|
@ -397,7 +398,7 @@ void main() {
|
|||
));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO categories ("desc", priority) VALUES (?, ?)',
|
||||
'INSERT INTO "categories" ("desc", "priority") VALUES (?, ?)',
|
||||
['description', 1],
|
||||
));
|
||||
});
|
||||
|
@ -420,7 +421,7 @@ void main() {
|
|||
));
|
||||
|
||||
verify(executor.runSelect(
|
||||
'INSERT INTO categories ("desc", priority) VALUES (?, ?) RETURNING *',
|
||||
'INSERT INTO "categories" ("desc", "priority") VALUES (?, ?) RETURNING *',
|
||||
['description', 1],
|
||||
));
|
||||
});
|
||||
|
@ -432,7 +433,7 @@ void main() {
|
|||
.insert(CategoriesCompanion.insert(description: 'description'));
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT INTO categories ("desc") VALUES (?)', ['description']));
|
||||
'INSERT INTO "categories" ("desc") VALUES (?)', ['description']));
|
||||
});
|
||||
|
||||
test('insertOne', () async {
|
||||
|
@ -441,7 +442,7 @@ void main() {
|
|||
mode: InsertMode.insertOrReplace);
|
||||
|
||||
verify(executor.runInsert(
|
||||
'INSERT OR REPLACE INTO categories ("desc") VALUES (?)',
|
||||
'INSERT OR REPLACE INTO "categories" ("desc") VALUES (?)',
|
||||
['description']));
|
||||
});
|
||||
|
||||
|
@ -470,7 +471,7 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runSelect(
|
||||
'INSERT INTO categories ("desc") VALUES (?) RETURNING *',
|
||||
'INSERT INTO "categories" ("desc") VALUES (?) RETURNING *',
|
||||
['description'],
|
||||
));
|
||||
});
|
||||
|
|
|
@ -23,12 +23,12 @@ void main() {
|
|||
]).get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT t.id AS "t.id", t.title AS "t.title", '
|
||||
't.content AS "t.content", t.target_date AS "t.target_date", '
|
||||
't.category AS "t.category", c.id AS "c.id", c."desc" AS "c.desc", '
|
||||
'c.priority AS "c.priority", '
|
||||
'c.description_in_upper_case AS "c.description_in_upper_case" '
|
||||
'FROM todos t LEFT OUTER JOIN categories c ON c.id = t.category;',
|
||||
'SELECT "t"."id" AS "t.id", "t"."title" AS "t.title", '
|
||||
'"t"."content" AS "t.content", "t"."target_date" AS "t.target_date", '
|
||||
'"t"."category" AS "t.category", "c"."id" AS "c.id", "c"."desc" AS "c.desc", '
|
||||
'"c"."priority" AS "c.priority", '
|
||||
'"c"."description_in_upper_case" AS "c.description_in_upper_case" '
|
||||
'FROM "todos" "t" LEFT OUTER JOIN "categories" "c" ON "c"."id" = "t"."category";',
|
||||
argThat(isEmpty)));
|
||||
});
|
||||
|
||||
|
@ -126,7 +126,7 @@ void main() {
|
|||
[innerJoin(categories, categories.id.equalsExp(todos.category))]).get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
argThat(contains('WHERE t.id < ? ORDER BY t.title ASC')), [3]));
|
||||
argThat(contains('WHERE "t"."id" < ? ORDER BY "t"."title" ASC')), [3]));
|
||||
});
|
||||
|
||||
test('limit clause is kept', () async {
|
||||
|
@ -189,8 +189,8 @@ void main() {
|
|||
|
||||
await query.get();
|
||||
|
||||
verify(executor
|
||||
.runSelect(argThat(contains('WHERE t.id < ? AND c.id >= ?')), [5, 10]));
|
||||
verify(executor.runSelect(
|
||||
argThat(contains('WHERE "t"."id" < ? AND "c"."id" >= ?')), [5, 10]));
|
||||
});
|
||||
|
||||
test('supports custom columns and results', () async {
|
||||
|
@ -214,10 +214,10 @@ void main() {
|
|||
final result = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT c.id AS "c.id", c."desc" AS "c.desc", '
|
||||
'c.priority AS "c.priority", c.description_in_upper_case AS '
|
||||
'"c.description_in_upper_case", LENGTH(c."desc") AS "c4" '
|
||||
'FROM categories c;',
|
||||
'SELECT "c"."id" AS "c.id", "c"."desc" AS "c.desc", '
|
||||
'"c"."priority" AS "c.priority", "c"."description_in_upper_case" AS '
|
||||
'"c.description_in_upper_case", LENGTH("c"."desc") AS "c4" '
|
||||
'FROM "categories" "c";',
|
||||
[],
|
||||
));
|
||||
|
||||
|
@ -263,11 +263,11 @@ void main() {
|
|||
final result = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT c.id AS "c.id", c."desc" AS "c.desc", c.priority AS "c.priority"'
|
||||
', c.description_in_upper_case AS "c.description_in_upper_case", '
|
||||
'LENGTH(c."desc") AS "c4" '
|
||||
'FROM categories c '
|
||||
'INNER JOIN todos t ON c.id = t.category;',
|
||||
'SELECT "c"."id" AS "c.id", "c"."desc" AS "c.desc", "c"."priority" AS "c.priority"'
|
||||
', "c"."description_in_upper_case" AS "c.description_in_upper_case", '
|
||||
'LENGTH("c"."desc") AS "c4" '
|
||||
'FROM "categories" "c" '
|
||||
'INNER JOIN "todos" "t" ON "c"."id" = "t"."category";',
|
||||
[],
|
||||
));
|
||||
|
||||
|
@ -319,12 +319,12 @@ void main() {
|
|||
final result = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT c.id AS "c.id", c."desc" AS "c.desc", '
|
||||
'c.priority AS "c.priority", '
|
||||
'c.description_in_upper_case AS "c.description_in_upper_case", '
|
||||
'COUNT(t.id) AS "c4" '
|
||||
'FROM categories c INNER JOIN todos t ON t.category = c.id '
|
||||
'GROUP BY c.id HAVING COUNT(t.id) >= ?;',
|
||||
'SELECT "c"."id" AS "c.id", "c"."desc" AS "c.desc", '
|
||||
'"c"."priority" AS "c.priority", '
|
||||
'"c"."description_in_upper_case" AS "c.description_in_upper_case", '
|
||||
'COUNT("t"."id") AS "c4" '
|
||||
'FROM "categories" "c" INNER JOIN "todos" "t" ON "t"."category" = "c"."id" '
|
||||
'GROUP BY "c"."id" HAVING COUNT("t"."id") >= ?;',
|
||||
[10]));
|
||||
|
||||
expect(result.readTableOrNull(todos), isNull);
|
||||
|
@ -356,8 +356,8 @@ void main() {
|
|||
final row = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT AVG(LENGTH(todos.content)) AS "c0", '
|
||||
'MAX(LENGTH(todos.content)) AS "c1" FROM todos;',
|
||||
'SELECT AVG(LENGTH("todos"."content")) AS "c0", '
|
||||
'MAX(LENGTH("todos"."content")) AS "c1" FROM "todos";',
|
||||
[]));
|
||||
|
||||
expect(row.read(avgLength), 3.0);
|
||||
|
@ -392,9 +392,9 @@ void main() {
|
|||
final result = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT categories.id AS "categories.id", COUNT(todos.id) AS "c1" '
|
||||
'FROM categories INNER JOIN todos ON todos.category = categories.id '
|
||||
'GROUP BY categories.id;',
|
||||
'SELECT "categories"."id" AS "categories.id", COUNT("todos"."id") AS "c1" '
|
||||
'FROM "categories" INNER JOIN "todos" ON "todos"."category" = "categories"."id" '
|
||||
'GROUP BY "categories"."id";',
|
||||
[]));
|
||||
|
||||
expect(result.read(categories.id), equals(2));
|
||||
|
@ -428,9 +428,9 @@ void main() {
|
|||
final result = await query.getSingle();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT categories.id AS "categories.id", COUNT(todos.id) AS "c1" '
|
||||
'FROM categories INNER JOIN todos ON todos.category = categories.id '
|
||||
'GROUP BY categories.id;',
|
||||
'SELECT "categories"."id" AS "categories.id", COUNT("todos"."id") AS "c1" '
|
||||
'FROM "categories" INNER JOIN "todos" ON "todos"."category" = "categories"."id" '
|
||||
'GROUP BY "categories"."id";',
|
||||
[]));
|
||||
|
||||
expect(result.read(categories.id), equals(2));
|
||||
|
|
|
@ -19,7 +19,7 @@ void main() {
|
|||
query.orderBy([(tbl) => OrderingTerm(expression: tbl.name)]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC;',
|
||||
'SELECT * FROM "users" ORDER BY "name" ASC;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ void main() {
|
|||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS LAST;',
|
||||
'SELECT * FROM "users" ORDER BY "name" ASC NULLS LAST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ void main() {
|
|||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS FIRST;',
|
||||
'SELECT * FROM "users" ORDER BY "name" ASC NULLS FIRST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ void main() {
|
|||
]);
|
||||
await query.get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY name ASC NULLS FIRST, creation_time ASC, profile_picture ASC NULLS LAST;',
|
||||
'SELECT * FROM "users" ORDER BY "name" ASC NULLS FIRST, "creation_time" ASC, "profile_picture" ASC NULLS LAST;',
|
||||
argThat(isEmpty),
|
||||
));
|
||||
});
|
||||
|
@ -79,10 +79,10 @@ void main() {
|
|||
test('works with helper factories', () {
|
||||
final table = db.users;
|
||||
|
||||
expect(OrderingTerm.asc(table.id), generates('id ASC'));
|
||||
expect(OrderingTerm.asc(table.id), generates('"id" ASC'));
|
||||
expect(OrderingTerm.asc(table.id, nulls: NullsOrder.last),
|
||||
generates('id ASC NULLS LAST'));
|
||||
generates('"id" ASC NULLS LAST'));
|
||||
expect(OrderingTerm.desc(table.id, nulls: NullsOrder.first),
|
||||
generates('id DESC NULLS FIRST'));
|
||||
generates('"id" DESC NULLS FIRST'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,40 +20,40 @@ void main() {
|
|||
|
||||
// should create todos, categories, users and shared_todos table
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS todos '
|
||||
'(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, title TEXT NULL, '
|
||||
'content TEXT NOT NULL, target_date INTEGER NULL UNIQUE, '
|
||||
'category INTEGER NULL REFERENCES categories (id), '
|
||||
'UNIQUE (title, category), UNIQUE (title, target_date));',
|
||||
'CREATE TABLE IF NOT EXISTS "todos" '
|
||||
'("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" TEXT NULL, '
|
||||
'"content" TEXT NOT NULL, "target_date" INTEGER NULL UNIQUE, '
|
||||
'"category" INTEGER NULL REFERENCES "categories" ("id"), '
|
||||
'UNIQUE ("title", "category"), UNIQUE ("title", "target_date"));',
|
||||
[]));
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS categories '
|
||||
'(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'CREATE TABLE IF NOT EXISTS "categories" '
|
||||
'("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'"desc" TEXT NOT NULL UNIQUE, '
|
||||
'priority INTEGER NOT NULL DEFAULT 0, '
|
||||
'description_in_upper_case TEXT NOT NULL GENERATED ALWAYS AS '
|
||||
'"priority" INTEGER NOT NULL DEFAULT 0, '
|
||||
'"description_in_upper_case" TEXT NOT NULL GENERATED ALWAYS AS '
|
||||
'(UPPER("desc")) VIRTUAL'
|
||||
');',
|
||||
[]));
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS users ('
|
||||
'id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'name TEXT NOT NULL UNIQUE, '
|
||||
'is_awesome INTEGER NOT NULL DEFAULT 1 CHECK (is_awesome IN (0, 1)), '
|
||||
'profile_picture BLOB NOT NULL, '
|
||||
'creation_time INTEGER NOT NULL '
|
||||
'CREATE TABLE IF NOT EXISTS "users" ('
|
||||
'"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'"name" TEXT NOT NULL UNIQUE, '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK ("is_awesome" IN (0, 1)), '
|
||||
'"profile_picture" BLOB NOT NULL, '
|
||||
'"creation_time" INTEGER NOT NULL '
|
||||
"DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)) "
|
||||
'CHECK(creation_time > -631152000)'
|
||||
'CHECK("creation_time" > -631152000)'
|
||||
');',
|
||||
[]));
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS shared_todos ('
|
||||
'todo INTEGER NOT NULL, '
|
||||
'user INTEGER NOT NULL, '
|
||||
'PRIMARY KEY (todo, user), '
|
||||
'CREATE TABLE IF NOT EXISTS "shared_todos" ('
|
||||
'"todo" INTEGER NOT NULL, '
|
||||
'"user" INTEGER NOT NULL, '
|
||||
'PRIMARY KEY ("todo", "user"), '
|
||||
'FOREIGN KEY (todo) REFERENCES todos(id), '
|
||||
'FOREIGN KEY (user) REFERENCES users(id)'
|
||||
');',
|
||||
|
@ -61,33 +61,33 @@ void main() {
|
|||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS '
|
||||
'table_without_p_k ('
|
||||
'not_really_an_id INTEGER NOT NULL, '
|
||||
'some_float REAL NOT NULL, '
|
||||
'web_safe_int INTEGER NULL, '
|
||||
'custom TEXT NOT NULL'
|
||||
'"table_without_p_k" ('
|
||||
'"not_really_an_id" INTEGER NOT NULL, '
|
||||
'"some_float" REAL NOT NULL, '
|
||||
'"web_safe_int" INTEGER NULL, '
|
||||
'"custom" TEXT NOT NULL'
|
||||
');',
|
||||
[]));
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE VIEW IF NOT EXISTS category_todo_count_view '
|
||||
'(description, item_count) AS SELECT '
|
||||
't1."desc" || \'!\' AS "description", '
|
||||
'COUNT(t0.id) AS "item_count" '
|
||||
'FROM categories t1 '
|
||||
'INNER JOIN todos t0 '
|
||||
'ON t0.category = t1.id '
|
||||
'GROUP BY t1.id',
|
||||
'CREATE VIEW IF NOT EXISTS "category_todo_count_view" '
|
||||
'("description", "item_count") AS SELECT '
|
||||
'"t1"."desc" || \'!\' AS "description", '
|
||||
'COUNT("t0"."id") AS "item_count" '
|
||||
'FROM "categories" "t1" '
|
||||
'INNER JOIN "todos" "t0" '
|
||||
'ON "t0"."category" = "t1"."id" '
|
||||
'GROUP BY "t1"."id"',
|
||||
[]));
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE VIEW IF NOT EXISTS todo_with_category_view '
|
||||
'(title, "desc") AS SELECT '
|
||||
't0.title AS "title", '
|
||||
't1."desc" AS "desc" '
|
||||
'FROM todos t0 '
|
||||
'INNER JOIN categories t1 '
|
||||
'ON t1.id = t0.category',
|
||||
'CREATE VIEW IF NOT EXISTS "todo_with_category_view" '
|
||||
'("title", "desc") AS SELECT '
|
||||
'"t0"."title" AS "title", '
|
||||
'"t1"."desc" AS "desc" '
|
||||
'FROM "todos" "t0" '
|
||||
'INNER JOIN "categories" "t1" '
|
||||
'ON "t1"."id" = "t0"."category"',
|
||||
[]));
|
||||
});
|
||||
|
||||
|
@ -95,14 +95,14 @@ void main() {
|
|||
await db.createMigrator().createTable(db.users);
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE TABLE IF NOT EXISTS users '
|
||||
'(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'name TEXT NOT NULL UNIQUE, '
|
||||
'is_awesome INTEGER NOT NULL DEFAULT 1 CHECK (is_awesome IN (0, 1)), '
|
||||
'profile_picture BLOB NOT NULL, '
|
||||
'creation_time INTEGER NOT NULL '
|
||||
'CREATE TABLE IF NOT EXISTS "users" '
|
||||
'("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, '
|
||||
'"name" TEXT NOT NULL UNIQUE, '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 CHECK ("is_awesome" IN (0, 1)), '
|
||||
'"profile_picture" BLOB NOT NULL, '
|
||||
'"creation_time" INTEGER NOT NULL '
|
||||
"DEFAULT (CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)) "
|
||||
'CHECK(creation_time > -631152000)'
|
||||
'CHECK("creation_time" > -631152000)'
|
||||
');',
|
||||
[]));
|
||||
});
|
||||
|
@ -111,21 +111,21 @@ void main() {
|
|||
await db.createMigrator().create(db.categoryTodoCountView);
|
||||
|
||||
verify(mockExecutor.runCustom(
|
||||
'CREATE VIEW IF NOT EXISTS category_todo_count_view '
|
||||
'(description, item_count) AS SELECT '
|
||||
't1."desc" || \'!\' AS "description", '
|
||||
'COUNT(t0.id) AS "item_count" '
|
||||
'FROM categories t1 '
|
||||
'INNER JOIN todos t0 '
|
||||
'ON t0.category = t1.id '
|
||||
'GROUP BY t1.id',
|
||||
'CREATE VIEW IF NOT EXISTS "category_todo_count_view" '
|
||||
'("description", "item_count") AS SELECT '
|
||||
'"t1"."desc" || \'!\' AS "description", '
|
||||
'COUNT("t0"."id") AS "item_count" '
|
||||
'FROM "categories" "t1" '
|
||||
'INNER JOIN "todos" "t0" '
|
||||
'ON "t0"."category" = "t1"."id" '
|
||||
'GROUP BY "t1"."id"',
|
||||
[]));
|
||||
});
|
||||
|
||||
test('drops tables', () async {
|
||||
await db.createMigrator().deleteTable('users');
|
||||
|
||||
verify(mockExecutor.runCustom('DROP TABLE IF EXISTS users;'));
|
||||
verify(mockExecutor.runCustom('DROP TABLE IF EXISTS "users";'));
|
||||
});
|
||||
|
||||
test('drops indices', () async {
|
||||
|
@ -137,15 +137,15 @@ void main() {
|
|||
test('drops triggers', () async {
|
||||
await db.createMigrator().drop(Trigger('foo', 'my_trigger'));
|
||||
|
||||
verify(mockExecutor.runCustom('DROP TRIGGER IF EXISTS my_trigger;'));
|
||||
verify(mockExecutor.runCustom('DROP TRIGGER IF EXISTS "my_trigger";'));
|
||||
});
|
||||
|
||||
test('adds columns', () async {
|
||||
await db.createMigrator().addColumn(db.users, db.users.isAwesome);
|
||||
|
||||
verify(mockExecutor.runCustom('ALTER TABLE users ADD COLUMN '
|
||||
'is_awesome INTEGER NOT NULL DEFAULT 1 '
|
||||
'CHECK (is_awesome IN (0, 1));'));
|
||||
verify(mockExecutor.runCustom('ALTER TABLE "users" ADD COLUMN '
|
||||
'"is_awesome" INTEGER NOT NULL DEFAULT 1 '
|
||||
'CHECK ("is_awesome" IN (0, 1));'));
|
||||
});
|
||||
|
||||
test('renames columns', () async {
|
||||
|
@ -154,7 +154,7 @@ void main() {
|
|||
.renameColumn(db.users, 'my name', db.users.name);
|
||||
|
||||
verify(mockExecutor
|
||||
.runCustom('ALTER TABLE users RENAME COLUMN "my name" TO name;'));
|
||||
.runCustom('ALTER TABLE "users" RENAME COLUMN "my name" TO "name";'));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -207,7 +207,7 @@ void main() {
|
|||
|
||||
// This should not attempt to generate a parameter (`?`)
|
||||
// https://github.com/simolus3/drift/discussions/1936
|
||||
verify(executor.runCustom(argThat(contains('CHECK(foo < 3)')), []));
|
||||
verify(executor.runCustom(argThat(contains('CHECK("foo" < 3)')), []));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -34,26 +34,26 @@ void main() {
|
|||
test('for simple statements', () async {
|
||||
await db.select(db.users, distinct: true).get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT DISTINCT * FROM users;', argThat(isEmpty)));
|
||||
'SELECT DISTINCT * FROM "users";', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('with limit statements', () async {
|
||||
await (db.select(db.users)..limit(10, offset: 0)).get();
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users LIMIT 10 OFFSET 0;', argThat(isEmpty)));
|
||||
'SELECT * FROM "users" LIMIT 10 OFFSET 0;', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('with simple limits', () async {
|
||||
await (db.select(db.users)..limit(10)).get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users LIMIT 10;', argThat(isEmpty)));
|
||||
'SELECT * FROM "users" LIMIT 10;', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('with like expressions', () async {
|
||||
await (db.select(db.users)..where((u) => u.name.like('Dash%'))).get();
|
||||
verify(executor
|
||||
.runSelect('SELECT * FROM users WHERE name LIKE ?;', ['Dash%']));
|
||||
.runSelect('SELECT * FROM "users" WHERE "name" LIKE ?;', ['Dash%']));
|
||||
});
|
||||
|
||||
test('with order-by clauses', () async {
|
||||
|
@ -65,8 +65,8 @@ void main() {
|
|||
.get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY '
|
||||
'is_awesome DESC, id ASC;',
|
||||
'SELECT * FROM "users" ORDER BY '
|
||||
'"is_awesome" DESC, "id" ASC;',
|
||||
argThat(isEmpty)));
|
||||
});
|
||||
|
||||
|
@ -75,7 +75,7 @@ void main() {
|
|||
.get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users ORDER BY random() ASC;', argThat(isEmpty)));
|
||||
'SELECT * FROM "users" ORDER BY random() ASC;', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('with complex predicates', () async {
|
||||
|
@ -85,7 +85,7 @@ void main() {
|
|||
.get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users WHERE NOT (name = ?) AND id > ?;',
|
||||
'SELECT * FROM "users" WHERE NOT ("name" = ?) AND "id" > ?;',
|
||||
['Dash', 12]));
|
||||
});
|
||||
|
||||
|
@ -93,7 +93,7 @@ void main() {
|
|||
await (db.select(db.users)..where((u) => u.isAwesome)).get();
|
||||
|
||||
verify(executor.runSelect(
|
||||
'SELECT * FROM users WHERE is_awesome;', argThat(isEmpty)));
|
||||
'SELECT * FROM "users" WHERE "is_awesome";', argThat(isEmpty)));
|
||||
});
|
||||
|
||||
test('with aliased tables', () async {
|
||||
|
@ -102,13 +102,14 @@ void main() {
|
|||
..where((u) => u.id.isSmallerThan(const Constant(5))))
|
||||
.get();
|
||||
|
||||
verify(executor.runSelect('SELECT * FROM users u WHERE id < 5;', []));
|
||||
verify(
|
||||
executor.runSelect('SELECT * FROM "users" "u" WHERE "id" < 5;', []));
|
||||
});
|
||||
});
|
||||
|
||||
group('SELECT results are parsed', () {
|
||||
test('when all fields are non-null', () {
|
||||
when(executor.runSelect('SELECT * FROM todos;', any))
|
||||
when(executor.runSelect('SELECT * FROM "todos";', any))
|
||||
.thenAnswer((_) => Future.value([_dataOfTodoEntry]));
|
||||
|
||||
expect(db.select(db.todosTable).get(), completion([_todoEntry]));
|
||||
|
@ -130,7 +131,7 @@ void main() {
|
|||
category: null,
|
||||
);
|
||||
|
||||
when(executor.runSelect('SELECT * FROM todos;', any))
|
||||
when(executor.runSelect('SELECT * FROM "todos";', any))
|
||||
.thenAnswer((_) => Future.value(data));
|
||||
|
||||
expect(db.select(db.todosTable).get(), completion([resolved]));
|
||||
|
@ -139,13 +140,13 @@ void main() {
|
|||
|
||||
group('queries for a single row', () {
|
||||
test('get once', () {
|
||||
when(executor.runSelect('SELECT * FROM todos;', any))
|
||||
when(executor.runSelect('SELECT * FROM "todos";', any))
|
||||
.thenAnswer((_) => Future.value([_dataOfTodoEntry]));
|
||||
expect(db.select(db.todosTable).getSingle(), completion(_todoEntry));
|
||||
});
|
||||
|
||||
test('get once without rows', () {
|
||||
when(executor.runSelect('SELECT * FROM todos;', any))
|
||||
when(executor.runSelect('SELECT * FROM "todos";', any))
|
||||
.thenAnswer((_) => Future.value([]));
|
||||
|
||||
expect(db.select(db.todosTable).getSingle(), throwsA(anything));
|
||||
|
@ -160,7 +161,7 @@ void main() {
|
|||
];
|
||||
var currentRow = 0;
|
||||
|
||||
when(executor.runSelect('SELECT * FROM todos;', any)).thenAnswer((_) {
|
||||
when(executor.runSelect('SELECT * FROM "todos";', any)).thenAnswer((_) {
|
||||
return Future.value(resultRows[currentRow++]);
|
||||
});
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ void main() {
|
|||
));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE todos SET title = ?, category = ?;', ['Updated title', 3]));
|
||||
'UPDATE "todos" SET "title" = ?, "category" = ?;',
|
||||
['Updated title', 3]));
|
||||
});
|
||||
|
||||
test('with a WHERE clause', () async {
|
||||
|
@ -37,7 +38,8 @@ void main() {
|
|||
.write(const TodosTableCompanion(title: Value('Changed title')));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE todos SET title = ? WHERE id < ?;', ['Changed title', 50]));
|
||||
'UPDATE "todos" SET "title" = ? WHERE "id" < ?;',
|
||||
['Changed title', 50]));
|
||||
});
|
||||
|
||||
test('with escaped column names', () async {
|
||||
|
@ -46,7 +48,7 @@ void main() {
|
|||
.write(PureDefaultsCompanion(txt: Value(MyCustomObject('foo'))));
|
||||
|
||||
verify(executor
|
||||
.runUpdate('UPDATE pure_defaults SET "insert" = ?;', ['foo']));
|
||||
.runUpdate('UPDATE "pure_defaults" SET "insert" = ?;', ['foo']));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -60,8 +62,8 @@ void main() {
|
|||
));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE todos SET title = ?, content = ?, '
|
||||
'target_date = ?, category = ? WHERE id = ?;',
|
||||
'UPDATE "todos" SET "title" = ?, "content" = ?, '
|
||||
'"target_date" = ?, "category" = ? WHERE "id" = ?;',
|
||||
['Title', 'Updated content', null, null, 3]));
|
||||
});
|
||||
|
||||
|
@ -75,9 +77,9 @@ void main() {
|
|||
);
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE users SET name = ?, profile_picture = ?, is_awesome = 1, '
|
||||
'creation_time = CAST(strftime(\'%s\', CURRENT_TIMESTAMP) AS INTEGER)'
|
||||
' WHERE id = ?;',
|
||||
'UPDATE "users" SET "name" = ?, "profile_picture" = ?, "is_awesome" = 1, '
|
||||
'"creation_time" = CAST(strftime(\'%s\', CURRENT_TIMESTAMP) AS INTEGER)'
|
||||
' WHERE "id" = ?;',
|
||||
['Hummingbird', Uint8List(0), 3]));
|
||||
});
|
||||
});
|
||||
|
@ -121,22 +123,22 @@ void main() {
|
|||
));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE todos SET content = content, target_date = target_date + ? '
|
||||
'WHERE id = ?;',
|
||||
'UPDATE "todos" SET "content" = "content", "target_date" = "target_date" + ? '
|
||||
'WHERE "id" = ?;',
|
||||
argThat(equals([86400, 4])),
|
||||
));
|
||||
});
|
||||
|
||||
group('custom updates', () {
|
||||
test('execute the correct sql', () async {
|
||||
await db.customUpdate('DELETE FROM users');
|
||||
await db.customUpdate('DELETE FROM "users"');
|
||||
|
||||
verify(executor.runUpdate('DELETE FROM users', []));
|
||||
verify(executor.runUpdate('DELETE FROM "users"', []));
|
||||
});
|
||||
|
||||
test('map the variables correctly', () async {
|
||||
await db.customUpdate(
|
||||
'DELETE FROM users WHERE name = ? AND birthdate < ?',
|
||||
'DELETE FROM "users" WHERE "name" = ? AND "birthdate" < ?',
|
||||
variables: [
|
||||
Variable.withString('Name'),
|
||||
Variable.withDateTime(
|
||||
|
@ -144,7 +146,7 @@ void main() {
|
|||
]);
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'DELETE FROM users WHERE name = ? AND birthdate < ?',
|
||||
'DELETE FROM "users" WHERE "name" = ? AND "birthdate" < ?',
|
||||
['Name', 1551297563]));
|
||||
});
|
||||
|
||||
|
@ -166,7 +168,7 @@ void main() {
|
|||
test('update()', () async {
|
||||
await db.users.update().write(const UsersCompanion(id: Value(3)));
|
||||
|
||||
verify(executor.runUpdate('UPDATE users SET id = ?;', [3]));
|
||||
verify(executor.runUpdate('UPDATE "users" SET "id" = ?;', [3]));
|
||||
});
|
||||
|
||||
test('replace', () async {
|
||||
|
@ -174,7 +176,7 @@ void main() {
|
|||
id: Value(3), description: Value('new name')));
|
||||
|
||||
verify(executor.runUpdate(
|
||||
'UPDATE categories SET "desc" = ?, priority = 0 WHERE id = ?;',
|
||||
'UPDATE "categories" SET "desc" = ?, "priority" = 0 WHERE "id" = ?;',
|
||||
['new name', 3]));
|
||||
});
|
||||
});
|
||||
|
@ -195,8 +197,8 @@ void main() {
|
|||
.update()
|
||||
.writeReturning(const CategoriesCompanion(description: Value('test')));
|
||||
|
||||
verify(executor
|
||||
.runSelect('UPDATE categories SET "desc" = ? RETURNING *;', ['test']));
|
||||
verify(executor.runSelect(
|
||||
'UPDATE "categories" SET "desc" = ? RETURNING *;', ['test']));
|
||||
verify(streamQueries.handleTableUpdates(
|
||||
{TableUpdate.onTable(db.categories, kind: UpdateKind.update)}));
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ void main() {
|
|||
nonNull.writeColumnDefinition(nonNullQuery);
|
||||
nullable.writeColumnDefinition(nullableQuery);
|
||||
|
||||
expect(nullableQuery.sql, equals('name INTEGER NULL'));
|
||||
expect(nonNullQuery.sql, equals('name INTEGER NOT NULL'));
|
||||
expect(nullableQuery.sql, equals('"name" INTEGER NULL'));
|
||||
expect(nonNullQuery.sql, equals('"name" INTEGER NOT NULL'));
|
||||
});
|
||||
|
||||
group('mapping datetime values', () {
|
||||
|
|
|
@ -16,8 +16,8 @@ void main() {
|
|||
final context = GenerationContext.fromDb(TodoDb());
|
||||
column.writeColumnDefinition(context);
|
||||
|
||||
expect(
|
||||
context.sql, equals('foo INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT'));
|
||||
expect(context.sql,
|
||||
equals('"foo" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT'));
|
||||
});
|
||||
|
||||
test('int column writes PRIMARY KEY constraint', () {
|
||||
|
@ -27,6 +27,6 @@ void main() {
|
|||
final context = GenerationContext.fromDb(TodoDb());
|
||||
column.writeColumnDefinition(context);
|
||||
|
||||
expect(context.sql, equals('foo INTEGER NOT NULL PRIMARY KEY'));
|
||||
expect(context.sql, equals('"foo" INTEGER NOT NULL PRIMARY KEY'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -495,7 +495,7 @@ class $TodosTableTable extends TodosTable
|
|||
'category', aliasedName, true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'REFERENCES categories (id)');
|
||||
defaultConstraints: 'REFERENCES "categories" ("id")');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[id, title, content, targetDate, category];
|
||||
|
@ -777,7 +777,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
|||
'is_awesome', aliasedName, false,
|
||||
type: DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'CHECK (is_awesome IN (0, 1))',
|
||||
defaultConstraints: 'CHECK ("is_awesome" IN (0, 1))',
|
||||
defaultValue: const Constant(true));
|
||||
final VerificationMeta _profilePictureMeta =
|
||||
const VerificationMeta('profilePicture');
|
||||
|
|
|
@ -7,32 +7,32 @@ import '../generated/custom_tables.dart';
|
|||
import '../test_utils/test_utils.dart';
|
||||
|
||||
const _createNoIds =
|
||||
'CREATE TABLE IF NOT EXISTS no_ids (payload BLOB NOT NULL PRIMARY KEY) '
|
||||
'CREATE TABLE IF NOT EXISTS "no_ids" ("payload" BLOB NOT NULL PRIMARY KEY) '
|
||||
'WITHOUT ROWID;';
|
||||
|
||||
const _createWithDefaults = 'CREATE TABLE IF NOT EXISTS with_defaults ('
|
||||
"a TEXT DEFAULT 'something', b INTEGER UNIQUE);";
|
||||
const _createWithDefaults = 'CREATE TABLE IF NOT EXISTS "with_defaults" ('
|
||||
"\"a\" TEXT DEFAULT 'something', \"b\" INTEGER UNIQUE);";
|
||||
|
||||
const _createWithConstraints = 'CREATE TABLE IF NOT EXISTS with_constraints ('
|
||||
'a TEXT, b INTEGER NOT NULL, c REAL, '
|
||||
const _createWithConstraints = 'CREATE TABLE IF NOT EXISTS "with_constraints" ('
|
||||
'"a" TEXT, "b" INTEGER NOT NULL, "c" REAL, '
|
||||
'FOREIGN KEY (a, b) REFERENCES with_defaults (a, b)'
|
||||
');';
|
||||
|
||||
const _createConfig = 'CREATE TABLE IF NOT EXISTS config ('
|
||||
'config_key TEXT not null primary key, '
|
||||
'config_value TEXT, '
|
||||
'sync_state INTEGER, '
|
||||
'sync_state_implicit INTEGER) STRICT;';
|
||||
const _createConfig = 'CREATE TABLE IF NOT EXISTS "config" ('
|
||||
'"config_key" TEXT not null primary key, '
|
||||
'"config_value" TEXT, '
|
||||
'"sync_state" INTEGER, '
|
||||
'"sync_state_implicit" INTEGER) STRICT;';
|
||||
|
||||
const _createMyTable = 'CREATE TABLE IF NOT EXISTS mytable ('
|
||||
'someid INTEGER NOT NULL, '
|
||||
'sometext TEXT, '
|
||||
'is_inserting INTEGER, '
|
||||
'somedate TEXT, '
|
||||
const _createMyTable = 'CREATE TABLE IF NOT EXISTS "mytable" ('
|
||||
'"someid" INTEGER NOT NULL, '
|
||||
'"sometext" TEXT, '
|
||||
'"is_inserting" INTEGER, '
|
||||
'"somedate" TEXT, '
|
||||
'PRIMARY KEY (someid DESC)'
|
||||
');';
|
||||
|
||||
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS email USING '
|
||||
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS "email" USING '
|
||||
'fts5(sender, title, body);';
|
||||
|
||||
const _createMyTrigger =
|
||||
|
@ -98,7 +98,7 @@ void main() {
|
|||
// regression test for #112: https://github.com/simolus3/drift/issues/112
|
||||
|
||||
await db.into(db.mytable).insert(const MytableCompanion());
|
||||
verify(mock.runInsert('INSERT INTO mytable DEFAULT VALUES', []));
|
||||
verify(mock.runInsert('INSERT INTO "mytable" DEFAULT VALUES', []));
|
||||
});
|
||||
|
||||
test('runs queries with arrays and Dart templates', () async {
|
||||
|
@ -108,7 +108,7 @@ void main() {
|
|||
|
||||
verify(mock.runSelect(
|
||||
'SELECT * FROM config WHERE config_key IN (?1, ?2) '
|
||||
'ORDER BY config_key ASC',
|
||||
'ORDER BY "config_key" ASC',
|
||||
['a', 'b'],
|
||||
));
|
||||
});
|
||||
|
@ -122,8 +122,8 @@ void main() {
|
|||
.readDynamic(predicate: (config) => config.configKey.equals('key'))
|
||||
.getSingle();
|
||||
|
||||
verify(
|
||||
mock.runSelect('SELECT * FROM config WHERE config_key = ?1', ['key']));
|
||||
verify(mock
|
||||
.runSelect('SELECT * FROM config WHERE "config_key" = ?1', ['key']));
|
||||
expect(parsed, const Config(configKey: 'key', configValue: 'value'));
|
||||
});
|
||||
|
||||
|
@ -136,7 +136,7 @@ void main() {
|
|||
test('columns use table names in queries with multiple tables', () async {
|
||||
await db.multiple(predicate: (d, c) => d.a.equals('foo')).get();
|
||||
|
||||
verify(mock.runSelect(argThat(contains('d.a = ?1')), any));
|
||||
verify(mock.runSelect(argThat(contains('"d"."a" = ?1')), any));
|
||||
});
|
||||
|
||||
test('order by-params are ignored by default', () async {
|
||||
|
@ -241,7 +241,7 @@ void main() {
|
|||
..where((tbl) => tbl.syncState.equalsValue(SyncType.synchronized)))
|
||||
.getSingleOrNull();
|
||||
|
||||
verify(mock.runSelect('SELECT * FROM config WHERE sync_state = ?;',
|
||||
verify(mock.runSelect('SELECT * FROM "config" WHERE "sync_state" = ?;',
|
||||
[ConfigTable.$converter0.toSql(SyncType.synchronized)]));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ void main() {
|
|||
.map((row) => row.read<String>('sql'))
|
||||
.getSingle();
|
||||
|
||||
expect(createStmt, contains('category INT'));
|
||||
expect(createStmt, contains('"category" INT'));
|
||||
|
||||
final item = await db.select(db.todosTable).getSingle();
|
||||
expect(item.category, 12);
|
||||
|
@ -102,7 +102,7 @@ void main() {
|
|||
|
||||
expect(
|
||||
createStmt,
|
||||
allOf(contains('category INT'), isNot(contains('category_old'))),
|
||||
allOf(contains('"category" INT'), isNot(contains('category_old'))),
|
||||
);
|
||||
|
||||
final item = await db.select(db.todosTable).getSingle();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:charcode/ascii.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:drift/drift.dart' show SqlDialect;
|
||||
import 'package:drift/sqlite_keywords.dart';
|
||||
import 'package:drift_dev/moor_generator.dart';
|
||||
import 'package:drift_dev/src/analyzer/options.dart';
|
||||
import 'package:drift_dev/src/utils/string_escaper.dart';
|
||||
|
@ -75,13 +74,6 @@ class SqlWriter extends NodeSqlBuilder {
|
|||
(f) => f.variable.resolvedIndex == target.resolvedIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
void identifier(String identifier,
|
||||
{bool spaceBefore = true, bool spaceAfter = true}) {
|
||||
final escaped = escapeIfNeeded(identifier, options.effectiveDialect);
|
||||
symbol(escaped, spaceBefore: spaceBefore, spaceAfter: spaceAfter);
|
||||
}
|
||||
|
||||
void _writeMoorVariable(FoundVariable variable) {
|
||||
if (variable.isArray) {
|
||||
_writeRawInSpaces('(\$${expandedName(variable)})');
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:drift/sqlite_keywords.dart';
|
||||
import 'package:sqlparser/sqlparser.dart';
|
||||
|
||||
import '../../model/model.dart';
|
||||
|
@ -32,8 +31,8 @@ String defaultConstraints(DriftColumn column) {
|
|||
|
||||
for (final feature in column.features) {
|
||||
if (feature is ResolvedDartForeignKeyReference) {
|
||||
final tableName = escapeIfNeeded(feature.otherTable.sqlName);
|
||||
final columnName = escapeIfNeeded(feature.otherColumn.name.name);
|
||||
final tableName = '"${feature.otherTable.sqlName}"';
|
||||
final columnName = '"${feature.otherColumn.name.name}"';
|
||||
|
||||
var constraint = 'REFERENCES $tableName ($columnName)';
|
||||
|
||||
|
@ -55,7 +54,7 @@ String defaultConstraints(DriftColumn column) {
|
|||
}
|
||||
|
||||
if (column.type == DriftSqlType.bool) {
|
||||
final name = escapeIfNeeded(column.name.name);
|
||||
final name = '"${column.name.name}"';
|
||||
defaultConstraints.add('CHECK ($name IN (0, 1))');
|
||||
}
|
||||
|
||||
|
|
|
@ -402,7 +402,7 @@ class $TodoEntriesTable extends TodoEntries
|
|||
'category', aliasedName, true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'REFERENCES categories (id)');
|
||||
defaultConstraints: 'REFERENCES "categories" ("id")');
|
||||
final VerificationMeta _dueDateMeta = const VerificationMeta('dueDate');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime> dueDate = GeneratedColumn<DateTime>(
|
||||
|
|
|
@ -200,7 +200,7 @@ class $UsersTable extends Users with TableInfo<$UsersTable, User> {
|
|||
'next_user', aliasedName, true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'REFERENCES users (id)');
|
||||
defaultConstraints: 'REFERENCES "users" ("id")');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name, birthday, nextUser];
|
||||
@override
|
||||
|
|
|
@ -474,7 +474,7 @@ class $FriendshipsTable extends Friendships
|
|||
'really_good_friends', aliasedName, false,
|
||||
type: DriftSqlType.bool,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: 'CHECK (really_good_friends IN (0, 1))',
|
||||
defaultConstraints: 'CHECK ("really_good_friends" IN (0, 1))',
|
||||
defaultValue: const Constant(false));
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
|
@ -562,7 +562,7 @@ abstract class _$Database extends GeneratedDatabase {
|
|||
|
||||
Selectable<FriendshipsOfResult> 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<int>(user)
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue