mirror of https://github.com/AMT-Cheif/drift.git
Parse "STRICT" table definitions
This commit is contained in:
parent
6dc471a4ce
commit
074b663b79
|
@ -28,8 +28,16 @@ abstract class TableInducingStatement extends Statement
|
|||
class CreateTableStatement extends TableInducingStatement {
|
||||
List<ColumnDefinition> columns;
|
||||
List<TableConstraint> tableConstraints;
|
||||
|
||||
/// Whether this table has been defined with an `WITHOUT ROWID` clause.
|
||||
final bool withoutRowId;
|
||||
|
||||
/// Whether this table has been defined as `STRICT`.
|
||||
///
|
||||
/// Strict tables are limited to a few column type names. Columns in strict
|
||||
/// tables may not store other types.
|
||||
final bool isStrict;
|
||||
|
||||
Token? openingBracket;
|
||||
Token? closingBracket;
|
||||
|
||||
|
@ -39,6 +47,7 @@ class CreateTableStatement extends TableInducingStatement {
|
|||
this.columns = const [],
|
||||
this.tableConstraints = const [],
|
||||
this.withoutRowId = false,
|
||||
this.isStrict = false,
|
||||
MoorTableName? moorTableName,
|
||||
}) : super._(ifNotExists, tableName, moorTableName);
|
||||
|
||||
|
|
|
@ -67,13 +67,16 @@ class SqliteVersion implements Comparable<SqliteVersion> {
|
|||
/// can't provide analysis warnings when using recent sqlite3 features.
|
||||
static const SqliteVersion minimum = SqliteVersion.v3(34);
|
||||
|
||||
/// Version `3.37.0` of `sqlite3`.
|
||||
static const SqliteVersion v3_37 = SqliteVersion.v3(37);
|
||||
|
||||
/// Version `3.35.0` of `sqlite3`.
|
||||
static const SqliteVersion v3_35 = SqliteVersion.v3(35);
|
||||
|
||||
/// The highest sqlite version supported by this `sqlparser` package.
|
||||
///
|
||||
/// Newer features in `sqlite3` may not be recognized by this library.
|
||||
static const SqliteVersion current = SqliteVersion.v3(36);
|
||||
static const SqliteVersion current = v3_37;
|
||||
|
||||
/// The major version of sqlite.
|
||||
///
|
||||
|
|
|
@ -1885,10 +1885,41 @@ class Parser {
|
|||
_consume(TokenType.rightParen, 'Expected closing parenthesis');
|
||||
|
||||
var withoutRowId = false;
|
||||
if (_matchOne(TokenType.without)) {
|
||||
_consume(
|
||||
TokenType.rowid, 'Expected ROWID to complete the WITHOUT ROWID part');
|
||||
withoutRowId = true;
|
||||
var isStrict = false;
|
||||
|
||||
// Parses a `WITHOUT ROWID` or a `STRICT` keyword. Returns if either such
|
||||
// option has been parsed.
|
||||
bool tableOptions() {
|
||||
if (_matchOne(TokenType.strict)) {
|
||||
isStrict = true;
|
||||
return true;
|
||||
} else if (_matchOne(TokenType.without)) {
|
||||
_consume(TokenType.rowid,
|
||||
'Expected ROWID to complete the WITHOUT ROWID part');
|
||||
withoutRowId = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Table options can be seperated by comma, but they're not required either.
|
||||
if (tableOptions()) {
|
||||
while (_matchOne(TokenType.comma)) {
|
||||
if (!tableOptions()) {
|
||||
_error('Expected WITHOUT ROWID or STRICT here!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (_check(TokenType.without) || _check(TokenType.strict)) {
|
||||
if (_matchOne(TokenType.without)) {
|
||||
} else {
|
||||
// Matched a strict keyword
|
||||
isStrict = true;
|
||||
_advance();
|
||||
assert(_previous.type == TokenType.strict);
|
||||
}
|
||||
}
|
||||
|
||||
final overriddenName = _moorTableName();
|
||||
|
@ -1899,6 +1930,7 @@ class Parser {
|
|||
withoutRowId: withoutRowId,
|
||||
columns: columns,
|
||||
tableConstraints: tableConstraints,
|
||||
isStrict: isStrict,
|
||||
moorTableName: overriddenName,
|
||||
)
|
||||
..setSpan(first, _previous)
|
||||
|
|
|
@ -167,6 +167,7 @@ enum TokenType {
|
|||
shiftRight,
|
||||
slash,
|
||||
star,
|
||||
strict,
|
||||
stringLiteral,
|
||||
table,
|
||||
temp,
|
||||
|
@ -329,6 +330,7 @@ const Map<String, TokenType> keywords = {
|
|||
'SAVEPOINT': TokenType.savepoint,
|
||||
'SELECT': TokenType.select,
|
||||
'SET': TokenType.set,
|
||||
'STRICT': TokenType.strict,
|
||||
'TABLE': TokenType.table,
|
||||
'TEMP': TokenType.temp,
|
||||
'TEMPORARY': TokenType.temporary,
|
||||
|
|
|
@ -206,7 +206,8 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
|
|||
_assert(
|
||||
current.ifNotExists == e.ifNotExists &&
|
||||
current.tableName == e.tableName &&
|
||||
current.withoutRowId == e.withoutRowId,
|
||||
current.withoutRowId == e.withoutRowId &&
|
||||
current.isStrict == e.isStrict,
|
||||
e);
|
||||
_checkChildren(e);
|
||||
}
|
||||
|
|
|
@ -393,6 +393,12 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
|
|||
_keyword(TokenType.without);
|
||||
_keyword(TokenType.rowid);
|
||||
}
|
||||
|
||||
if (e.isStrict) {
|
||||
if (e.withoutRowId) _symbol(',');
|
||||
|
||||
_keyword(TokenType.strict);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -251,4 +251,18 @@ void main() {
|
|||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('parses WITHOUT ROWID and STRICT', () {
|
||||
testStatement(
|
||||
'CREATE TABLE a (c INTEGER) STRICT, WITHOUT ROWID, STRICT',
|
||||
CreateTableStatement(
|
||||
tableName: 'a',
|
||||
columns: [
|
||||
ColumnDefinition(columnName: 'c', typeName: 'INTEGER'),
|
||||
],
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -94,8 +94,9 @@ CREATE VIEW my_view AS SELECT * FROM t1;
|
|||
''');
|
||||
});
|
||||
|
||||
test('table', () {
|
||||
testFormat('''
|
||||
group('table', () {
|
||||
test('complex', () {
|
||||
testFormat('''
|
||||
CREATE TABLE IF NOT EXISTS my_table(
|
||||
foo TEXT NOT NULL PRIMARY KEY DEFAULT (3 * 4),
|
||||
baz INT CONSTRAINT not_null NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
|
@ -114,16 +115,35 @@ CREATE TABLE IF NOT EXISTS my_table(
|
|||
FOREIGN KEY (bar) REFERENCES t2 (bax) ON DELETE SET DEFAULT NOT DEFERRABLE
|
||||
);
|
||||
''');
|
||||
});
|
||||
|
||||
testFormat('''
|
||||
test('WITHOUT ROWID', () {
|
||||
testFormat('''
|
||||
CREATE TABLE IF NOT EXISTS my_table(
|
||||
foo INTEGER NOT NULL PRIMARY KEY ASC
|
||||
) WITHOUT ROWID;
|
||||
''');
|
||||
});
|
||||
});
|
||||
|
||||
test('virtual table', () {
|
||||
testFormat('CREATE VIRTUAL TABLE foo USING bar(a, b, c);');
|
||||
test('STRICT', () {
|
||||
testFormat('''
|
||||
CREATE TABLE IF NOT EXISTS my_table(
|
||||
foo INTEGER NOT NULL PRIMARY KEY ASC
|
||||
) STRICT;
|
||||
''');
|
||||
});
|
||||
|
||||
test('STRICT and WITHOUT ROWID', () {
|
||||
testFormat('''
|
||||
CREATE TABLE IF NOT EXISTS my_table(
|
||||
foo INTEGER NOT NULL PRIMARY KEY ASC
|
||||
) WITHOUT ROWID, STRICT;
|
||||
''');
|
||||
});
|
||||
|
||||
test('virtual', () {
|
||||
testFormat('CREATE VIRTUAL TABLE foo USING bar(a, b, c);');
|
||||
});
|
||||
});
|
||||
|
||||
test('index', () {
|
||||
|
|
Loading…
Reference in New Issue