Merge remote-tracking branch 'simolus3/develop' into views

This commit is contained in:
westito 2021-12-02 09:20:02 +01:00
commit d22bbcbadf
5 changed files with 58 additions and 12 deletions

View File

@ -16,15 +16,21 @@ class VerifierImplementation implements SchemaVerifier {
@override
Future<void> migrateAndValidate(GeneratedDatabase db, int expectedVersion,
{bool validateDropped = false}) async {
final virtualTables = <String>[
for (final table in db.allTables)
if (table is VirtualTableInfo) table.entityName,
];
// Open the database to collect its schema. Put a delegate in between
// claiming that the actual version is what we expect.
await db.executor.ensureOpen(_DelegatingUser(expectedVersion, db));
final actualSchema = await db.executor.collectSchemaInput();
final actualSchema = await db.executor.collectSchemaInput(virtualTables);
// Open another connection to instantiate and extract the reference schema.
final otherConnection = await startAt(expectedVersion);
await otherConnection.executor.ensureOpen(_DelegatingUser(expectedVersion));
final referenceSchema = await otherConnection.executor.collectSchemaInput();
final referenceSchema =
await otherConnection.executor.collectSchemaInput(virtualTables);
await otherConnection.executor.close();
final result =
@ -80,13 +86,16 @@ class VerifierImplementation implements SchemaVerifier {
}
extension on QueryExecutor {
Future<List<Input>> collectSchemaInput() async {
Future<List<Input>> collectSchemaInput(List<String> virtualTables) async {
final result = await runSelect('SELECT * FROM sqlite_master;', const []);
final inputs = <Input>[];
for (final row in result) {
final name = row['name'] as String;
// Skip sqlite-internal tables
if (name.startsWith('sqlite_autoindex')) continue;
if (virtualTables.any((v) => name.startsWith('${v}_'))) continue;
inputs.add(Input(name, row['sql'] as String));
}

View File

@ -19,5 +19,5 @@ Replace `_v2` with the current `schemaVersion`.
Run
```
dart run drift_dev schema generate moor_migrations/ test/generated/ --data-classes --companions
dart run drift_dev schema generate drift_migrations/ test/generated/ --data-classes --companions
```

View File

@ -716,9 +716,8 @@ class Parser {
final token = _peek;
Literal? _parseInner() {
if (_matchOne(TokenType.numberLiteral)) {
final number = token as NumericToken;
return NumericLiteral(number.parsedNumber, token);
if (_check(TokenType.numberLiteral)) {
return _numericLiteral();
}
if (_matchOne(TokenType.stringLiteral)) {
return StringLiteral(token as StringLiteralToken);
@ -752,6 +751,12 @@ class Parser {
return literal;
}
NumericLiteral _numericLiteral() {
final number = _consume(TokenType.numberLiteral, 'Expected a number here')
as NumericToken;
return NumericLiteral(number.parsedNumber, number)..setSpan(number, number);
}
Expression _primary() {
final literal = _literalOrNull();
if (literal != null) return literal;
@ -2442,10 +2447,17 @@ class Parser {
return CheckColumn(resolvedName, expr)..setSpan(first, _previous);
}
if (_matchOne(TokenType.$default)) {
Expression? expr = _literalOrNull();
Expression expr;
// when not a literal, expect an expression in parentheses
expr ??= _expressionInParentheses();
if (_match(const [TokenType.plus, TokenType.minus])) {
// Signed number
final operator = _previous;
expr = UnaryExpression(operator, _numericLiteral())
..setSpan(operator, _previous);
} else {
// Literal or an expression in parentheses
expr = _literalOrNull() ?? _expressionInParentheses();
}
return Default(resolvedName, expr)..setSpan(first, _previous);
}

View File

@ -300,4 +300,26 @@ void main() {
),
);
});
test('parses DEFAULT with a negative literal', () {
// regression test for https://github.com/simolus3/moor/discussions/1550
testStatement(
'CREATE TABLE a (b INTEGER NOT NULL DEFAULT -1);',
CreateTableStatement(
tableName: 'a',
columns: [
ColumnDefinition(columnName: 'b', typeName: 'INTEGER', constraints: [
NotNull(null),
Default(
null,
UnaryExpression(
Token(TokenType.minus, fakeSpan('-')),
NumericLiteral(1, NumericToken(fakeSpan('1'))),
),
)
])
],
),
);
});
}

View File

@ -38,8 +38,11 @@ void testMoorFile(String moorFile, MoorFile expected) {
}
void testStatement(String sql, AstNode expected, {bool moorMode = false}) {
final parsed =
SqlEngine(EngineOptions(useMoorExtensions: moorMode)).parse(sql).rootNode;
final result =
SqlEngine(EngineOptions(useMoorExtensions: moorMode)).parse(sql);
expect(result.errors, isEmpty);
final parsed = result.rootNode;
enforceHasSpan(parsed);
enforceEqual(parsed, expected);
}