mirror of https://github.com/AMT-Cheif/drift.git
Support for STRICT tables in drift files
This commit is contained in:
parent
6b5acdf3c6
commit
44281bebaf
|
@ -12,7 +12,7 @@ jobs:
|
|||
name: "Compile sqlite3 for tests"
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
SQLITE_VERSION: "3350500"
|
||||
SQLITE_VERSION: "3370000"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
Thanks to [@westito](https://github.com/westito).
|
||||
- Allow the generator to emit correct SQL code when using arrays with the
|
||||
`new_sql_code_generation` option in specific scenarios.
|
||||
- Add support for [strict tables](https://sqlite.org/stricttables.html) in `.drift` files.
|
||||
- Add the `generatedAs` method to declare generated columns for Dart tables.
|
||||
- Add `OrderingTerm.random` to fetch rows in a random order.
|
||||
- Improved support for pausing query stream subscriptions. Instead of buffering events,
|
||||
|
|
|
@ -17,7 +17,7 @@ targets:
|
|||
sql:
|
||||
dialect: sqlite
|
||||
options:
|
||||
version: "3.35"
|
||||
version: "3.37"
|
||||
modules:
|
||||
- json1
|
||||
- fts5
|
||||
|
|
|
@ -34,6 +34,13 @@ abstract class Table extends HasResultSet {
|
|||
/// This is intended to be used by generated code only.
|
||||
bool get dontWriteConstraints => false;
|
||||
|
||||
/// Whether this table is `STRICT`.
|
||||
///
|
||||
/// Strict tables enforce stronger type constraints for inserts and updates.
|
||||
/// Support for strict tables was added in sqlite3 version 37.
|
||||
/// This field is intended to be used by generated code only.
|
||||
bool get isStrict => false;
|
||||
|
||||
/// Override this to specify custom primary keys:
|
||||
/// ```dart
|
||||
/// class IngredientInRecipes extends Table {
|
||||
|
|
|
@ -289,9 +289,12 @@ class Migrator {
|
|||
context.buffer.write(')');
|
||||
|
||||
// == true because of nullability
|
||||
if (dslTable.withoutRowId == true) {
|
||||
if (dslTable.withoutRowId) {
|
||||
context.buffer.write(' WITHOUT ROWID');
|
||||
}
|
||||
if (dslTable.isStrict) {
|
||||
context.buffer.write(' STRICT');
|
||||
}
|
||||
|
||||
context.buffer.write(';');
|
||||
}
|
||||
|
|
|
@ -284,6 +284,8 @@ class ConfigTable extends Table with TableInfo<ConfigTable, Config> {
|
|||
static TypeConverter<SyncType?, int> $converter1 =
|
||||
const EnumIndexConverter<SyncType>(SyncType.values);
|
||||
@override
|
||||
bool get isStrict => true;
|
||||
@override
|
||||
bool get dontWriteConstraints => true;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ create table config (
|
|||
config_value TEXT,
|
||||
sync_state INTEGER MAPPED BY `const SyncTypeConverter()`,
|
||||
sync_state_implicit ENUM(SyncType)
|
||||
) AS "Config";
|
||||
) STRICT AS "Config";
|
||||
|
||||
CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ 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);';
|
||||
'sync_state_implicit INTEGER) STRICT;';
|
||||
|
||||
const _createMyTable = 'CREATE TABLE IF NOT EXISTS mytable ('
|
||||
'someid INTEGER NOT NULL, '
|
||||
|
|
|
@ -228,6 +228,7 @@ class CreateTableReader {
|
|||
overrideDontWriteConstraints: true,
|
||||
declaration: MoorTableDeclaration(stmt, step.file),
|
||||
existingRowClass: existingRowClass,
|
||||
isStrict: table.isStrict,
|
||||
)..parserTable = table;
|
||||
|
||||
// Having a mapping from parser table to moor tables helps with IDE features
|
||||
|
|
|
@ -103,6 +103,10 @@ class MoorTable extends MoorEntityWithResultSet {
|
|||
/// getter on the table class with this value.
|
||||
final bool? overrideWithoutRowId;
|
||||
|
||||
/// Whether this table is defined as `STRICT`. Support for strict tables has
|
||||
/// been added in sqlite 3.37.
|
||||
final bool isStrict;
|
||||
|
||||
/// When non-null, the generated table class will override the
|
||||
/// `dontWriteConstraint` getter on the table class with this value.
|
||||
final bool? overrideDontWriteConstraints;
|
||||
|
@ -145,6 +149,7 @@ class MoorTable extends MoorEntityWithResultSet {
|
|||
this.overrideDontWriteConstraints,
|
||||
this.declaration,
|
||||
this.existingRowClass,
|
||||
this.isStrict = false,
|
||||
}) : _overriddenName = overriddenName {
|
||||
_attachToConverters();
|
||||
}
|
||||
|
|
|
@ -444,6 +444,12 @@ class TableWriter extends TableOrViewWriter {
|
|||
..write('bool get withoutRowId => $value;\n');
|
||||
}
|
||||
|
||||
if (table.isStrict) {
|
||||
buffer
|
||||
..write('@override\n')
|
||||
..write('bool get isStrict => true;\n');
|
||||
}
|
||||
|
||||
if (table.overrideTableConstraints != null) {
|
||||
final value =
|
||||
table.overrideTableConstraints!.map(asDartLiteral).join(', ');
|
||||
|
|
|
@ -74,6 +74,7 @@ class SchemaFromCreateTable {
|
|||
primaryKeyColumnsInStrictTable: stmt.isStrict ? primaryKey : null)
|
||||
],
|
||||
withoutRowId: stmt.withoutRowId,
|
||||
isStrict: stmt.isStrict,
|
||||
tableConstraints: stmt.tableConstraints,
|
||||
definition: stmt,
|
||||
);
|
||||
|
@ -167,11 +168,13 @@ class SchemaFromCreateTable {
|
|||
bool isValidTypeNameForStrictTable(String typeName) {
|
||||
// See https://www.sqlite.org/draft/stricttables.html
|
||||
const allowed = {'INT', 'INTEGER', 'REAL', 'TEXT', 'BLOB', 'ANY'};
|
||||
const alsoAllowedInMoor = {'ENUM', 'BOOL', 'DATE'};
|
||||
const alsoAllowedInMoor = {'BOOL', 'DATE'};
|
||||
|
||||
if (allowed.contains(typeName.toUpperCase()) ||
|
||||
final upper = typeName.toUpperCase();
|
||||
|
||||
if (allowed.contains(upper) ||
|
||||
(moorExtensions &&
|
||||
alsoAllowedInMoor.contains(typeName.toUpperCase()))) {
|
||||
(alsoAllowedInMoor.contains(upper) || upper.contains('ENUM')))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ class Table extends NamedResultSet with HasMetaMixin implements HumanReadable {
|
|||
/// Whether this table was created with an "WITHOUT ROWID" modifier
|
||||
final bool withoutRowId;
|
||||
|
||||
final bool isStrict;
|
||||
|
||||
/// Additional constraints set on this table.
|
||||
final List<TableConstraint> tableConstraints;
|
||||
|
||||
|
@ -44,6 +46,7 @@ class Table extends NamedResultSet with HasMetaMixin implements HumanReadable {
|
|||
required this.name,
|
||||
required this.resolvedColumns,
|
||||
this.withoutRowId = false,
|
||||
this.isStrict = false,
|
||||
this.tableConstraints = const [],
|
||||
this.definition,
|
||||
this.isVirtual = false,
|
||||
|
|
|
@ -190,4 +190,34 @@ void main() {
|
|||
expect(table.resolvedColumns.single.type.nullable, isFalse);
|
||||
});
|
||||
});
|
||||
|
||||
group('sets withoutRowid and isStrict', () {
|
||||
final engine = SqlEngine(EngineOptions(version: SqliteVersion.v3_37));
|
||||
|
||||
void testWith(String suffix, bool withoutRowid, bool strict) {
|
||||
final stmt =
|
||||
engine.parse('CREATE TABLE foo (bar TEXT) $suffix;').rootNode;
|
||||
|
||||
final table = engine.schemaReader.read(stmt as CreateTableStatement);
|
||||
expect(table.withoutRowId, withoutRowid);
|
||||
expect(table.isStrict, strict);
|
||||
}
|
||||
|
||||
test('when the table is neither', () {
|
||||
testWith('', false, false);
|
||||
});
|
||||
|
||||
test('when the table is without rowid', () {
|
||||
testWith('WITHOUT ROWID', true, false);
|
||||
});
|
||||
|
||||
test('when the table is strict', () {
|
||||
testWith('STRICT', false, true);
|
||||
});
|
||||
|
||||
test('when the table is both', () {
|
||||
testWith('WITHOUT ROWID, STRICT', true, true);
|
||||
testWith('STRICT, WITHOUT ROWID', true, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue