Prepare parser for schema support

This commit is contained in:
Simon Binder 2021-07-22 21:32:53 +02:00
parent f23cf9f426
commit aa75cbaa19
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
18 changed files with 188 additions and 97 deletions

View File

@ -42,13 +42,14 @@ abstract class TableOrSubquery extends Queryable {
class TableReference extends TableOrSubquery class TableReference extends TableOrSubquery
with ReferenceOwner with ReferenceOwner
implements Renamable, ResolvesToResultSet { implements Renamable, ResolvesToResultSet {
final String? schemaName;
final String tableName; final String tableName;
Token? tableNameToken; Token? tableNameToken;
@override @override
final String? as; final String? as;
TableReference(this.tableName, [this.as]); TableReference(this.tableName, {this.as, this.schemaName});
@override @override
Iterable<AstNode> get childNodes => const []; Iterable<AstNode> get childNodes => const [];

View File

@ -8,6 +8,11 @@ part of '../ast.dart';
/// 2 * c AS d FROM table", the "c" after the "2 *" is a reference that refers /// 2 * c AS d FROM table", the "c" after the "2 *" is a reference that refers
/// to the expression "COUNT(*)". /// to the expression "COUNT(*)".
class Reference extends Expression with ReferenceOwner { class Reference extends Expression with ReferenceOwner {
/// An optional schema name.
///
/// When this is non-null, [entityName] will not be null either.
final String? schemaName;
/// Entity can be either a table or a view. /// Entity can be either a table or a view.
final String? entityName; final String? entityName;
final String columnName; final String columnName;
@ -17,7 +22,11 @@ class Reference extends Expression with ReferenceOwner {
Column? get resolvedColumn => resolved as Column?; Column? get resolvedColumn => resolved as Column?;
Reference({this.entityName, required this.columnName}); Reference({this.entityName, this.schemaName, required this.columnName})
: assert(
entityName != null || schemaName == null,
'When setting a schemaName, entityName must not be null either.',
);
@override @override
R accept<A, R>(AstVisitor<A, R> visitor, A arg) { R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
@ -32,10 +41,16 @@ class Reference extends Expression with ReferenceOwner {
@override @override
String toString() { String toString() {
if (entityName != null) { final result = StringBuffer();
return 'Reference to the column $entityName.$columnName';
} else { if (schemaName != null) {
return 'Reference to the column $columnName'; result..write(schemaName)..write('.');
} }
if (entityName != null) {
result..write(entityName)..write('.');
}
result.write(columnName);
return result.toString();
} }
} }

View File

@ -751,32 +751,7 @@ class Parser {
return CastExpression(operand, typeName)..setSpan(first, _previous); return CastExpression(operand, typeName)..setSpan(first, _previous);
} else if (_checkIdentifier()) { } else if (_checkIdentifier()) {
final first = _consumeIdentifier( return _referenceOrFunctionCall();
'This error message should never be displayed. Please report.');
// could be table.column, function(...) or just column
if (_matchOne(TokenType.dot)) {
final second =
_consumeIdentifier('Expected a column name here', lenient: true);
return Reference(
entityName: first.identifier, columnName: second.identifier)
..setSpan(first, second);
} else if (_matchOne(TokenType.leftParen)) {
// regular function invocation
final parameters = _functionParameters();
final rightParen = _consume(TokenType.rightParen,
'Expected closing bracket after argument list');
if (_peek.type == TokenType.filter || _peek.type == TokenType.over) {
return _aggregate(first, parameters);
}
return FunctionExpression(
name: first.identifier, parameters: parameters)
..setSpan(first, rightParen);
} else {
return Reference(columnName: first.identifier)..setSpan(first, first);
}
} }
if (_peek is KeywordToken) { if (_peek is KeywordToken) {
@ -787,6 +762,55 @@ class Parser {
} }
} }
Expression _referenceOrFunctionCall() {
final first = _consumeIdentifier(
'This error message should never be displayed. Please report.');
// An expression starting with an identifier could be three things:
// - a simple reference: "foo"
// - a reference with a table: "foo.bar"
// - a reference with a table and a schema: "foo.bar.baz"
// - a function call: "foo()"
if (_matchOne(TokenType.dot)) {
// Ok, we're down to two here. it's either a table or a schema ref
final second = _consumeIdentifier('Expected a column or table name here',
lenient: true);
if (_matchOne(TokenType.dot)) {
// Three identifiers, that's a schema reference
final third =
_consumeIdentifier('Expected a column name here', lenient: true);
return Reference(
schemaName: first.identifier,
entityName: second.identifier,
columnName: third.identifier,
)..setSpan(first, third);
} else {
// Two identifiers only, so we have a table-based reference
return Reference(
entityName: first.identifier,
columnName: second.identifier,
)..setSpan(first, second);
}
} else if (_matchOne(TokenType.leftParen)) {
// We have something like "foo(" -> that's a function!
final parameters = _functionParameters();
final rightParen = _consume(
TokenType.rightParen, 'Expected closing bracket after argument list');
if (_peek.type == TokenType.filter || _peek.type == TokenType.over) {
return _aggregate(first, parameters);
}
return FunctionExpression(name: first.identifier, parameters: parameters)
..setSpan(first, rightParen);
} else {
// Ok, just a regular reference then
return Reference(columnName: first.identifier)..setSpan(first, first);
}
}
Variable? _variableOrNull() { Variable? _variableOrNull() {
if (_matchOne(TokenType.questionMarkVariable)) { if (_matchOne(TokenType.questionMarkVariable)) {
return NumberedVariable(_previous as QuestionMarkVariableToken) return NumberedVariable(_previous as QuestionMarkVariableToken)
@ -1171,19 +1195,6 @@ class Parser {
return null; return null;
} }
TableReference _tableReference() {
_suggestHint(const TableNameDescription());
// ignore the schema name, it's not supported. Besides that, we're on the
// first branch in the diagram here https://www.sqlite.org/syntax/table-or-subquery.html
final firstToken = _consumeIdentifier('Expected a table reference');
final tableName = firstToken.identifier;
final alias = _as();
return TableReference(tableName, alias?.identifier)
..setSpan(firstToken, _previous)
..tableNameToken = firstToken;
}
JoinClause? _joinClause(TableOrSubquery start) { JoinClause? _joinClause(TableOrSubquery start) {
var operator = _parseJoinOperator(); var operator = _parseJoinOperator();
if (operator == null) { if (operator == null) {
@ -2424,15 +2435,37 @@ class Parser {
return null; return null;
} }
TableReference _tableReference({bool allowAlias = true}) {
_suggestHint(const TableNameDescription());
final first = _consumeIdentifier('Expected table or schema name here');
IdentifierToken? second;
IdentifierToken? as;
if (_matchOne(TokenType.dot)) {
second = _consumeIdentifier('Expected a table name here');
}
if (allowAlias) {
as = _as();
}
final tableNameToken = second ?? first;
return TableReference(
tableNameToken.identifier,
as: as?.identifier,
schemaName: second == null ? null : first.identifier,
)
..setSpan(first, _previous)
..tableNameToken = tableNameToken;
}
ForeignKeyClause _foreignKeyClause() { ForeignKeyClause _foreignKeyClause() {
// https://www.sqlite.org/syntax/foreign-key-clause.html // https://www.sqlite.org/syntax/foreign-key-clause.html
_consume(TokenType.references, 'Expected REFERENCES'); _consume(TokenType.references, 'Expected REFERENCES');
final firstToken = _previous; final firstToken = _previous;
final foreignTable = _consumeIdentifier('Expected a table name'); final foreignTable = _tableReference(allowAlias: false);
final foreignTableName = TableReference(foreignTable.identifier, null)
..setSpan(foreignTable, foreignTable);
final columnNames = _listColumnsInParentheses(allowEmpty: true); final columnNames = _listColumnsInParentheses(allowEmpty: true);
ReferenceAction? onDelete, onUpdate; ReferenceAction? onDelete, onUpdate;
@ -2472,7 +2505,7 @@ class Parser {
} }
return ForeignKeyClause( return ForeignKeyClause(
foreignTable: foreignTableName, foreignTable: foreignTable,
columnNames: columnNames, columnNames: columnNames,
onUpdate: onUpdate, onUpdate: onUpdate,
onDelete: onDelete, onDelete: onDelete,

View File

@ -547,7 +547,8 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
void visitReference(Reference e, void arg) { void visitReference(Reference e, void arg) {
final current = _currentAs<Reference>(e); final current = _currentAs<Reference>(e);
_assert( _assert(
current.entityName == e.entityName && current.schemaName == e.schemaName &&
current.entityName == e.entityName &&
current.columnName == e.columnName, current.columnName == e.columnName,
e); e);
_checkChildren(e); _checkChildren(e);
@ -628,7 +629,11 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
@override @override
void visitTableReference(TableReference e, void arg) { void visitTableReference(TableReference e, void arg) {
final current = _currentAs<TableReference>(e); final current = _currentAs<TableReference>(e);
_assert(current.tableName == e.tableName && current.as == e.as, e); _assert(
current.schemaName == e.schemaName &&
current.tableName == e.tableName &&
current.as == e.as,
e);
_checkChildren(e); _checkChildren(e);
} }

View File

@ -964,14 +964,22 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
@override @override
void visitReference(Reference e, void arg) { void visitReference(Reference e, void arg) {
var hasTable = false; var didWriteSpaceBefore = false;
if (e.entityName != null) {
hasTable = true; if (e.schemaName != null) {
_identifier(e.entityName!, spaceAfter: false); _identifier(e.schemaName!, spaceAfter: false);
_symbol('.'); _symbol('.');
didWriteSpaceBefore = true;
}
if (e.entityName != null) {
_identifier(e.entityName!,
spaceAfter: false, spaceBefore: !didWriteSpaceBefore);
_symbol('.');
didWriteSpaceBefore = true;
} }
_identifier(e.columnName, spaceAfter: true, spaceBefore: !hasTable); _identifier(e.columnName,
spaceAfter: true, spaceBefore: !didWriteSpaceBefore);
} }
@override @override
@ -1131,7 +1139,12 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
@override @override
void visitTableReference(TableReference e, void arg) { void visitTableReference(TableReference e, void arg) {
_identifier(e.tableName); if (e.schemaName != null) {
_identifier(e.schemaName!, spaceAfter: false);
_symbol('.');
}
_identifier(e.tableName, spaceBefore: e.schemaName == null);
if (e.as != null) { if (e.as != null) {
_keyword(TokenType.as); _keyword(TokenType.as);
_identifier(e.as!); _identifier(e.as!);

View File

@ -77,7 +77,7 @@ void main() {
ForeignKeyColumnConstraint( ForeignKeyColumnConstraint(
null, null,
ForeignKeyClause( ForeignKeyClause(
foreignTable: TableReference('some', null), foreignTable: TableReference('some'),
columnNames: [Reference(columnName: 'thing')], columnNames: [Reference(columnName: 'thing')],
onUpdate: ReferenceAction.cascade, onUpdate: ReferenceAction.cascade,
onDelete: ReferenceAction.setNull, onDelete: ReferenceAction.setNull,
@ -107,7 +107,7 @@ void main() {
Reference(columnName: 'email'), Reference(columnName: 'email'),
], ],
clause: ForeignKeyClause( clause: ForeignKeyClause(
foreignTable: TableReference('another', null), foreignTable: TableReference('another'),
columnNames: [ columnNames: [
Reference(columnName: 'a'), Reference(columnName: 'a'),
Reference(columnName: 'b'), Reference(columnName: 'b'),

View File

@ -9,7 +9,7 @@ void main() {
testStatement( testStatement(
'DELETE FROM tbl WHERE id = 5', 'DELETE FROM tbl WHERE id = 5',
DeleteStatement( DeleteStatement(
from: TableReference('tbl', null), from: TableReference('tbl'),
where: BinaryExpression( where: BinaryExpression(
Reference(columnName: 'id'), Reference(columnName: 'id'),
token(TokenType.equal), token(TokenType.equal),
@ -26,7 +26,7 @@ void main() {
testStatement( testStatement(
'DELETE FROM tbl RETURNING *;', 'DELETE FROM tbl RETURNING *;',
DeleteStatement( DeleteStatement(
from: TableReference('tbl', null), from: TableReference('tbl'),
returning: Returning([StarResultColumn()]), returning: Returning([StarResultColumn()]),
), ),
); );

View File

@ -106,7 +106,7 @@ final Map<String, Expression> _testCases = {
ExistsExpression( ExistsExpression(
select: SelectStatement( select: SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('demo', null), from: TableReference('demo'),
), ),
), ),
), ),
@ -141,7 +141,7 @@ final Map<String, Expression> _testCases = {
expression: Reference(columnName: 'col'), expression: Reference(columnName: 'col'),
) )
], ],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
), ),
@ -192,6 +192,13 @@ final Map<String, Expression> _testCases = {
'RAISE(IGNORE)': RaiseExpression(RaiseKind.ignore), 'RAISE(IGNORE)': RaiseExpression(RaiseKind.ignore),
"RAISE(ROLLBACK, 'Not allowed')": "RAISE(ROLLBACK, 'Not allowed')":
RaiseExpression(RaiseKind.rollback, 'Not allowed'), RaiseExpression(RaiseKind.rollback, 'Not allowed'),
'foo': Reference(columnName: 'foo'),
'foo.bar': Reference(entityName: 'foo', columnName: 'bar'),
'foo.bar.baz': Reference(
schemaName: 'foo',
entityName: 'bar',
columnName: 'baz',
),
}; };
void main() { void main() {

View File

@ -9,7 +9,7 @@ void main() {
r'SELECT * FROM tbl LIMIT $limit', r'SELECT * FROM tbl LIMIT $limit',
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
limit: DartLimitPlaceholder(name: 'limit'), limit: DartLimitPlaceholder(name: 'limit'),
), ),
moorMode: true, moorMode: true,
@ -21,7 +21,7 @@ void main() {
r'SELECT * FROM tbl LIMIT $amount OFFSET 3', r'SELECT * FROM tbl LIMIT $amount OFFSET 3',
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
limit: Limit( limit: Limit(
count: DartExpressionPlaceholder(name: 'amount'), count: DartExpressionPlaceholder(name: 'amount'),
offsetSeparator: token(TokenType.offset), offsetSeparator: token(TokenType.offset),
@ -37,7 +37,7 @@ void main() {
r'SELECT * FROM tbl ORDER BY $term, $expr DESC', r'SELECT * FROM tbl ORDER BY $term, $expr DESC',
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
orderBy: OrderBy( orderBy: OrderBy(
terms: [ terms: [
DartOrderingTermPlaceholder(name: 'term'), DartOrderingTermPlaceholder(name: 'term'),
@ -57,7 +57,7 @@ void main() {
r'SELECT * FROM tbl ORDER BY $order', r'SELECT * FROM tbl ORDER BY $order',
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
orderBy: DartOrderByPlaceholder(name: 'order'), orderBy: DartOrderByPlaceholder(name: 'order'),
), ),
moorMode: true, moorMode: true,

View File

@ -9,7 +9,7 @@ void main() {
'INSERT OR REPLACE INTO tbl (a, b, c) VALUES (d, e, f)', 'INSERT OR REPLACE INTO tbl (a, b, c) VALUES (d, e, f)',
InsertStatement( InsertStatement(
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
table: TableReference('tbl', null), table: TableReference('tbl'),
targetColumns: [ targetColumns: [
Reference(columnName: 'a'), Reference(columnName: 'a'),
Reference(columnName: 'b'), Reference(columnName: 'b'),
@ -31,7 +31,7 @@ void main() {
'INSERT INTO tbl DEFAULT VALUES', 'INSERT INTO tbl DEFAULT VALUES',
InsertStatement( InsertStatement(
mode: InsertMode.insert, mode: InsertMode.insert,
table: TableReference('tbl', null), table: TableReference('tbl'),
targetColumns: const [], targetColumns: const [],
source: DefaultValues(), source: DefaultValues(),
), ),
@ -43,12 +43,12 @@ void main() {
'REPLACE INTO tbl SELECT * FROM tbl', 'REPLACE INTO tbl SELECT * FROM tbl',
InsertStatement( InsertStatement(
mode: InsertMode.replace, mode: InsertMode.replace,
table: TableReference('tbl', null), table: TableReference('tbl'),
targetColumns: const [], targetColumns: const [],
source: SelectInsertSource( source: SelectInsertSource(
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
), ),

View File

@ -46,7 +46,7 @@ void main() {
ForeignKeyColumnConstraint( ForeignKeyColumnConstraint(
null, null,
ForeignKeyClause( ForeignKeyClause(
foreignTable: TableReference('other', null), foreignTable: TableReference('other'),
columnNames: [ columnNames: [
Reference(columnName: 'location'), Reference(columnName: 'location'),
], ],
@ -62,7 +62,7 @@ void main() {
SimpleName('all'), SimpleName('all'),
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
where: DartExpressionPlaceholder(name: 'predicate'), where: DartExpressionPlaceholder(name: 'predicate'),
), ),
), ),
@ -70,7 +70,7 @@ void main() {
SpecialStatementIdentifier('special'), SpecialStatementIdentifier('special'),
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
DeclaredStatement( DeclaredStatement(
@ -104,7 +104,7 @@ void main() {
SimpleName('nested'), SimpleName('nested'),
SelectStatement( SelectStatement(
columns: [NestedStarResultColumn('foo')], columns: [NestedStarResultColumn('foo')],
from: TableReference('tbl', 'foo'), from: TableReference('tbl', as: 'foo'),
), ),
as: 'MyResultSet', as: 'MyResultSet',
), ),

View File

@ -16,7 +16,7 @@ void main() {
DeclaredStatement( DeclaredStatement(
SimpleName('a'), SimpleName('a'),
UpdateStatement( UpdateStatement(
table: TableReference('tbl', null), table: TableReference('tbl'),
set: [ set: [
SetComponent( SetComponent(
column: Reference(columnName: 'a'), column: Reference(columnName: 'a'),
@ -29,7 +29,7 @@ void main() {
SimpleName('b'), SimpleName('b'),
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
]), ]),
@ -48,7 +48,7 @@ void main() {
SimpleName('b'), SimpleName('b'),
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
); );
@ -78,7 +78,7 @@ void main() {
SimpleName('query'), SimpleName('query'),
SelectStatement( SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
), ),
); );

View File

@ -47,7 +47,7 @@ void main() {
and n.folderId = :selectedFolderId; and n.folderId = :selectedFolderId;
''', ''',
SelectStatement( SelectStatement(
from: TableReference('notes', 'n'), from: TableReference('notes', as: 'n'),
columns: [StarResultColumn()], columns: [StarResultColumn()],
where: BinaryExpression( where: BinaryExpression(
caseExpr, caseExpr,
@ -69,7 +69,7 @@ void main() {
END; END;
''', ''',
SelectStatement( SelectStatement(
from: TableReference('notes', 'n'), from: TableReference('notes', as: 'n'),
columns: [StarResultColumn()], columns: [StarResultColumn()],
where: BinaryExpression( where: BinaryExpression(
folderExpr, folderExpr,

View File

@ -10,7 +10,7 @@ void main() {
CompoundSelectStatement( CompoundSelectStatement(
base: SelectStatement( base: SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
additional: [ additional: [
CompoundSelectPart( CompoundSelectPart(

View File

@ -16,7 +16,13 @@ void main() {
final stmt = final stmt =
SqlEngine().parse('SELECT * FROM tbl').rootNode as SelectStatement; SqlEngine().parse('SELECT * FROM tbl').rootNode as SelectStatement;
enforceEqual(stmt.from!, TableReference('tbl', null)); _enforceFrom(stmt, TableReference('tbl'));
});
test('schema name and alias', () {
final stmt = SqlEngine().parse('SELECT * FROM main.tbl foo').rootNode
as SelectStatement;
_enforceFrom(stmt, TableReference('tbl', schemaName: 'main', as: 'foo'));
}); });
test('from more than one table', () { test('from more than one table', () {
@ -27,11 +33,11 @@ void main() {
_enforceFrom( _enforceFrom(
stmt, stmt,
JoinClause( JoinClause(
primary: TableReference('tbl', 'test'), primary: TableReference('tbl', as: 'test'),
joins: [ joins: [
Join( Join(
operator: JoinOperator.comma, operator: JoinOperator.comma,
query: TableReference('table2', null), query: TableReference('table2'),
), ),
], ],
), ),
@ -46,11 +52,11 @@ void main() {
_enforceFrom( _enforceFrom(
stmt, stmt,
JoinClause( JoinClause(
primary: TableReference('tbl', 'test'), primary: TableReference('tbl', as: 'test'),
joins: [ joins: [
Join( Join(
operator: JoinOperator.comma, operator: JoinOperator.comma,
query: TableReference('table2', null), query: TableReference('table2'),
constraint: OnConstraint( constraint: OnConstraint(
expression: BooleanLiteral.withTrue(token(TokenType.$true)), expression: BooleanLiteral.withTrue(token(TokenType.$true)),
), ),
@ -69,14 +75,14 @@ void main() {
_enforceFrom( _enforceFrom(
stmt, stmt,
JoinClause( JoinClause(
primary: TableReference('table1', null), primary: TableReference('table1'),
joins: [ joins: [
Join( Join(
operator: JoinOperator.comma, operator: JoinOperator.comma,
query: SelectStatementAsSource( query: SelectStatementAsSource(
statement: SelectStatement( statement: SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('table2', null), from: TableReference('table2'),
where: Reference(columnName: 'a'), where: Reference(columnName: 'a'),
), ),
as: 'inner', as: 'inner',
@ -132,16 +138,16 @@ void main() {
_enforceFrom( _enforceFrom(
stmt, stmt,
JoinClause( JoinClause(
primary: TableReference('table1', null), primary: TableReference('table1'),
joins: [ joins: [
Join( Join(
operator: JoinOperator.inner, operator: JoinOperator.inner,
query: TableReference('table2', null), query: TableReference('table2'),
constraint: UsingConstraint(columnNames: ['test']), constraint: UsingConstraint(columnNames: ['test']),
), ),
Join( Join(
operator: JoinOperator.leftOuter, operator: JoinOperator.leftOuter,
query: TableReference('table3', null), query: TableReference('table3'),
constraint: OnConstraint( constraint: OnConstraint(
expression: BooleanLiteral.withTrue(token(TokenType.$true)), expression: BooleanLiteral.withTrue(token(TokenType.$true)),
), ),

View File

@ -32,16 +32,16 @@ final Map<String, AstNode> testCases = {
expression: SubQuery( expression: SubQuery(
select: SelectStatement( select: SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('table2', null), from: TableReference('table2'),
), ),
), ),
), ),
], ],
from: TableReference('tbl', null), from: TableReference('tbl'),
), ),
'SELECT * FROM tbl WHERE id IN ()': SelectStatement( 'SELECT * FROM tbl WHERE id IN ()': SelectStatement(
columns: [StarResultColumn(null)], columns: [StarResultColumn(null)],
from: TableReference('tbl', null), from: TableReference('tbl'),
where: InExpression( where: InExpression(
left: Reference(columnName: 'id'), left: Reference(columnName: 'id'),
inside: Tuple(expressions: []), inside: Tuple(expressions: []),

View File

@ -6,7 +6,7 @@ import 'utils.dart';
final Map<String, AstNode> testCases = { final Map<String, AstNode> testCases = {
'UPDATE OR ROLLBACK tbl SET a = NULL, b = c WHERE d': UpdateStatement( 'UPDATE OR ROLLBACK tbl SET a = NULL, b = c WHERE d': UpdateStatement(
or: FailureMode.rollback, or: FailureMode.rollback,
table: TableReference('tbl', null), table: TableReference('tbl'),
set: [ set: [
SetComponent( SetComponent(
column: Reference(columnName: 'a'), column: Reference(columnName: 'a'),

View File

@ -221,6 +221,11 @@ CREATE UNIQUE INDEX my_idx ON t1 (c1, c2, c3) WHERE c1 < c3;
'''); ''');
}); });
test('table references', () {
testFormat('SELECT * FROM foo');
testFormat('SELECT * FROM main.foo');
});
test('limit', () { test('limit', () {
testFormat('SELECT * FROM foo LIMIT 3, 4'); testFormat('SELECT * FROM foo LIMIT 3, 4');
testFormat('SELECT * FROM foo LIMIT 4 OFFSET 3'); testFormat('SELECT * FROM foo LIMIT 4 OFFSET 3');
@ -379,6 +384,12 @@ CREATE UNIQUE INDEX my_idx ON t1 (c1, c2, c3) WHERE c1 < c3;
test('unary expression', () { test('unary expression', () {
testFormat('SELECT -(+(~3));'); testFormat('SELECT -(+(~3));');
}); });
test('references', () {
testFormat('SELECT foo');
testFormat('SELECT foo.bar');
testFormat('SELECT foo.bar.baz');
});
}); });
group('moor', () { group('moor', () {