mirror of https://github.com/AMT-Cheif/drift.git
Migrator support for indexes, tests
This commit is contained in:
parent
5b04a08786
commit
00c1d2a2e7
|
@ -74,6 +74,8 @@ class Migrator {
|
||||||
await createTable(entity);
|
await createTable(entity);
|
||||||
} else if (entity is Trigger) {
|
} else if (entity is Trigger) {
|
||||||
await createTrigger(entity);
|
await createTrigger(entity);
|
||||||
|
} else if (entity is Index) {
|
||||||
|
await createIndex(entity);
|
||||||
} else {
|
} else {
|
||||||
throw AssertionError('Unknown entity: $entity');
|
throw AssertionError('Unknown entity: $entity');
|
||||||
}
|
}
|
||||||
|
@ -167,6 +169,11 @@ class Migrator {
|
||||||
return issueCustomQuery(trigger.createTriggerStmt, const []);
|
return issueCustomQuery(trigger.createTriggerStmt, const []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes a `CREATE INDEX` statement to create the [index].
|
||||||
|
Future<void> createIndex(Index index) {
|
||||||
|
return issueCustomQuery(index.createIndexStmt, const []);
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes the table with the given name. Note that this function does not
|
/// Deletes the table with the given name. Note that this function does not
|
||||||
/// escape the [name] parameter.
|
/// escape the [name] parameter.
|
||||||
Future<void> deleteTable(String name) async {
|
Future<void> deleteTable(String name) async {
|
||||||
|
|
|
@ -1089,6 +1089,9 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
_$CustomTablesDb.connect(DatabaseConnection c) : super.connect(c);
|
_$CustomTablesDb.connect(DatabaseConnection c) : super.connect(c);
|
||||||
ConfigTable _config;
|
ConfigTable _config;
|
||||||
ConfigTable get config => _config ??= ConfigTable(this);
|
ConfigTable get config => _config ??= ConfigTable(this);
|
||||||
|
Index _valueIdx;
|
||||||
|
Index get valueIdx => _valueIdx ??= Index('value_idx',
|
||||||
|
'CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);');
|
||||||
WithDefaults _withDefaults;
|
WithDefaults _withDefaults;
|
||||||
WithDefaults get withDefaults => _withDefaults ??= WithDefaults(this);
|
WithDefaults get withDefaults => _withDefaults ??= WithDefaults(this);
|
||||||
Trigger _myTrigger;
|
Trigger _myTrigger;
|
||||||
|
@ -1216,8 +1219,16 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
List<DatabaseSchemaEntity> get allSchemaEntities => [
|
||||||
[config, withDefaults, myTrigger, noIds, withConstraints, mytable, email];
|
config,
|
||||||
|
valueIdx,
|
||||||
|
withDefaults,
|
||||||
|
myTrigger,
|
||||||
|
noIds,
|
||||||
|
withConstraints,
|
||||||
|
mytable,
|
||||||
|
email
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultipleResult {
|
class MultipleResult {
|
||||||
|
|
|
@ -20,6 +20,8 @@ create table config (
|
||||||
config_value TEXT
|
config_value TEXT
|
||||||
) AS "Config";
|
) AS "Config";
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);
|
||||||
|
|
||||||
CREATE TABLE mytable (
|
CREATE TABLE mytable (
|
||||||
someid INTEGER NOT NULL PRIMARY KEY,
|
someid INTEGER NOT NULL PRIMARY KEY,
|
||||||
sometext TEXT,
|
sometext TEXT,
|
||||||
|
|
|
@ -26,17 +26,20 @@ const _createMyTable = 'CREATE TABLE IF NOT EXISTS mytable ('
|
||||||
'somebool INTEGER, '
|
'somebool INTEGER, '
|
||||||
'somedate INTEGER);';
|
'somedate INTEGER);';
|
||||||
|
|
||||||
|
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS email USING '
|
||||||
|
'fts5(sender, title, body);';
|
||||||
|
|
||||||
const _createMyTrigger =
|
const _createMyTrigger =
|
||||||
'''CREATE TRIGGER my_trigger AFTER INSERT ON config BEGIN
|
'''CREATE TRIGGER my_trigger AFTER INSERT ON config BEGIN
|
||||||
INSERT INTO with_defaults VALUES (new.config_key, LENGTH(new.config_value));
|
INSERT INTO with_defaults VALUES (new.config_key, LENGTH(new.config_value));
|
||||||
END;''';
|
END;''';
|
||||||
|
|
||||||
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS email USING '
|
const _createValueIndex =
|
||||||
'fts5(sender, title, body);';
|
'CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// see ../data/tables/tables.moor
|
// see ../data/tables/tables.moor
|
||||||
test('creates tables as specified in .moor files', () async {
|
test('creates everything as specified in .moor files', () async {
|
||||||
final mockExecutor = MockExecutor();
|
final mockExecutor = MockExecutor();
|
||||||
final mockQueryExecutor = MockQueryExecutor();
|
final mockQueryExecutor = MockQueryExecutor();
|
||||||
final db = CustomTablesDb(mockExecutor);
|
final db = CustomTablesDb(mockExecutor);
|
||||||
|
@ -48,14 +51,8 @@ void main() {
|
||||||
verify(mockQueryExecutor.call(_createConfig, []));
|
verify(mockQueryExecutor.call(_createConfig, []));
|
||||||
verify(mockQueryExecutor.call(_createMyTable, []));
|
verify(mockQueryExecutor.call(_createMyTable, []));
|
||||||
verify(mockQueryExecutor.call(_createEmail, []));
|
verify(mockQueryExecutor.call(_createEmail, []));
|
||||||
});
|
|
||||||
|
|
||||||
test('creates triggers specified in .moor files', () async {
|
|
||||||
final mockQueryExecutor = MockQueryExecutor();
|
|
||||||
final db = CustomTablesDb(MockExecutor());
|
|
||||||
await Migrator(db, mockQueryExecutor).createAll();
|
|
||||||
|
|
||||||
verify(mockQueryExecutor.call(_createMyTrigger, []));
|
verify(mockQueryExecutor.call(_createMyTrigger, []));
|
||||||
|
verify(mockQueryExecutor.call(_createValueIndex, []));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('can create trigger manually', () async {
|
test('can create trigger manually', () async {
|
||||||
|
@ -66,6 +63,14 @@ void main() {
|
||||||
verify(mockQueryExecutor.call(_createMyTrigger, []));
|
verify(mockQueryExecutor.call(_createMyTrigger, []));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('can create index manually', () async {
|
||||||
|
final mockQueryExecutor = MockQueryExecutor();
|
||||||
|
final db = CustomTablesDb(MockExecutor());
|
||||||
|
|
||||||
|
await Migrator(db, mockQueryExecutor).createIndex(db.valueIdx);
|
||||||
|
verify(mockQueryExecutor.call(_createValueIndex, []));
|
||||||
|
});
|
||||||
|
|
||||||
test('infers primary keys correctly', () async {
|
test('infers primary keys correctly', () async {
|
||||||
final db = CustomTablesDb(null);
|
final db = CustomTablesDb(null);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class EntityHandler extends BaseAnalyzer {
|
||||||
entity.bodyReferences.clear();
|
entity.bodyReferences.clear();
|
||||||
|
|
||||||
final node =
|
final node =
|
||||||
_handleMoorDeclaration(entity, _tables) as CreateTriggerStatement;
|
_handleMoorDeclaration(entity, _triggers) as CreateTriggerStatement;
|
||||||
|
|
||||||
// triggers can have complex statements, so run the linter on them
|
// triggers can have complex statements, so run the linter on them
|
||||||
final context = engine.analyzeNode(node, file.parseResult.sql);
|
final context = engine.analyzeNode(node, file.parseResult.sql);
|
||||||
|
@ -55,7 +55,7 @@ class EntityHandler extends BaseAnalyzer {
|
||||||
} else if (entity is MoorIndex) {
|
} else if (entity is MoorIndex) {
|
||||||
entity.table = null;
|
entity.table = null;
|
||||||
|
|
||||||
_handleMoorDeclaration<MoorTableDeclaration>(entity, _indexes);
|
_handleMoorDeclaration<MoorIndexDeclaration>(entity, _indexes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,26 @@ END;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('in an index', () async {
|
||||||
|
final state = TestState.withContent(const {
|
||||||
|
'foo|lib/a.moor': '''
|
||||||
|
import 'b.moor';
|
||||||
|
|
||||||
|
CREATE INDEX idx ON users (name);
|
||||||
|
''',
|
||||||
|
...definitions,
|
||||||
|
});
|
||||||
|
|
||||||
|
final file = await state.analyze('package:foo/a.moor');
|
||||||
|
expect(file.errors.errors, isEmpty);
|
||||||
|
|
||||||
|
final trigger = file.currentResult.declaredEntities.single as MoorIndex;
|
||||||
|
expect(trigger.references, {
|
||||||
|
const TypeMatcher<MoorTable>()
|
||||||
|
.having((table) => table.displayName, 'displayName', 'users'),
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('issues error when referencing an unknown table', () {
|
group('issues error when referencing an unknown table', () {
|
||||||
|
|
Loading…
Reference in New Issue