Migrator support for indexes, tests

This commit is contained in:
Simon Binder 2020-01-03 20:08:10 +01:00
parent 5b04a08786
commit 00c1d2a2e7
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
6 changed files with 59 additions and 14 deletions

View File

@ -74,6 +74,8 @@ class Migrator {
await createTable(entity);
} else if (entity is Trigger) {
await createTrigger(entity);
} else if (entity is Index) {
await createIndex(entity);
} else {
throw AssertionError('Unknown entity: $entity');
}
@ -167,6 +169,11 @@ class Migrator {
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
/// escape the [name] parameter.
Future<void> deleteTable(String name) async {

View File

@ -1089,6 +1089,9 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
_$CustomTablesDb.connect(DatabaseConnection c) : super.connect(c);
ConfigTable _config;
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 get withDefaults => _withDefaults ??= WithDefaults(this);
Trigger _myTrigger;
@ -1216,8 +1219,16 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
@override
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
@override
List<DatabaseSchemaEntity> get allSchemaEntities =>
[config, withDefaults, myTrigger, noIds, withConstraints, mytable, email];
List<DatabaseSchemaEntity> get allSchemaEntities => [
config,
valueIdx,
withDefaults,
myTrigger,
noIds,
withConstraints,
mytable,
email
];
}
class MultipleResult {

View File

@ -20,6 +20,8 @@ create table config (
config_value TEXT
) AS "Config";
CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);
CREATE TABLE mytable (
someid INTEGER NOT NULL PRIMARY KEY,
sometext TEXT,

View File

@ -26,17 +26,20 @@ const _createMyTable = 'CREATE TABLE IF NOT EXISTS mytable ('
'somebool INTEGER, '
'somedate INTEGER);';
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS email USING '
'fts5(sender, title, body);';
const _createMyTrigger =
'''CREATE TRIGGER my_trigger AFTER INSERT ON config BEGIN
INSERT INTO with_defaults VALUES (new.config_key, LENGTH(new.config_value));
END;''';
const _createEmail = 'CREATE VIRTUAL TABLE IF NOT EXISTS email USING '
'fts5(sender, title, body);';
const _createValueIndex =
'CREATE INDEX IF NOT EXISTS value_idx ON config (config_value);';
void main() {
// 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 mockQueryExecutor = MockQueryExecutor();
final db = CustomTablesDb(mockExecutor);
@ -48,14 +51,8 @@ void main() {
verify(mockQueryExecutor.call(_createConfig, []));
verify(mockQueryExecutor.call(_createMyTable, []));
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(_createValueIndex, []));
});
test('can create trigger manually', () async {
@ -66,6 +63,14 @@ void main() {
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 {
final db = CustomTablesDb(null);

View File

@ -37,7 +37,7 @@ class EntityHandler extends BaseAnalyzer {
entity.bodyReferences.clear();
final node =
_handleMoorDeclaration(entity, _tables) as CreateTriggerStatement;
_handleMoorDeclaration(entity, _triggers) as CreateTriggerStatement;
// triggers can have complex statements, so run the linter on them
final context = engine.analyzeNode(node, file.parseResult.sql);
@ -55,7 +55,7 @@ class EntityHandler extends BaseAnalyzer {
} else if (entity is MoorIndex) {
entity.table = null;
_handleMoorDeclaration<MoorTableDeclaration>(entity, _indexes);
_handleMoorDeclaration<MoorIndexDeclaration>(entity, _indexes);
}
}
}

View File

@ -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', () {