mirror of https://github.com/AMT-Cheif/drift.git
Prepare parser for schema support
This commit is contained in:
parent
f23cf9f426
commit
aa75cbaa19
|
@ -42,13 +42,14 @@ abstract class TableOrSubquery extends Queryable {
|
|||
class TableReference extends TableOrSubquery
|
||||
with ReferenceOwner
|
||||
implements Renamable, ResolvesToResultSet {
|
||||
final String? schemaName;
|
||||
final String tableName;
|
||||
Token? tableNameToken;
|
||||
|
||||
@override
|
||||
final String? as;
|
||||
|
||||
TableReference(this.tableName, [this.as]);
|
||||
TableReference(this.tableName, {this.as, this.schemaName});
|
||||
|
||||
@override
|
||||
Iterable<AstNode> get childNodes => const [];
|
||||
|
|
|
@ -8,6 +8,11 @@ part of '../ast.dart';
|
|||
/// 2 * c AS d FROM table", the "c" after the "2 *" is a reference that refers
|
||||
/// to the expression "COUNT(*)".
|
||||
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.
|
||||
final String? entityName;
|
||||
final String columnName;
|
||||
|
@ -17,7 +22,11 @@ class Reference extends Expression with ReferenceOwner {
|
|||
|
||||
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
|
||||
R accept<A, R>(AstVisitor<A, R> visitor, A arg) {
|
||||
|
@ -32,10 +41,16 @@ class Reference extends Expression with ReferenceOwner {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
if (entityName != null) {
|
||||
return 'Reference to the column $entityName.$columnName';
|
||||
} else {
|
||||
return 'Reference to the column $columnName';
|
||||
final result = StringBuffer();
|
||||
|
||||
if (schemaName != null) {
|
||||
result..write(schemaName)..write('.');
|
||||
}
|
||||
if (entityName != null) {
|
||||
result..write(entityName)..write('.');
|
||||
}
|
||||
result.write(columnName);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -751,32 +751,7 @@ class Parser {
|
|||
|
||||
return CastExpression(operand, typeName)..setSpan(first, _previous);
|
||||
} else if (_checkIdentifier()) {
|
||||
final first = _consumeIdentifier(
|
||||
'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);
|
||||
}
|
||||
return _referenceOrFunctionCall();
|
||||
}
|
||||
|
||||
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() {
|
||||
if (_matchOne(TokenType.questionMarkVariable)) {
|
||||
return NumberedVariable(_previous as QuestionMarkVariableToken)
|
||||
|
@ -1171,19 +1195,6 @@ class Parser {
|
|||
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) {
|
||||
var operator = _parseJoinOperator();
|
||||
if (operator == null) {
|
||||
|
@ -2424,15 +2435,37 @@ class Parser {
|
|||
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() {
|
||||
// https://www.sqlite.org/syntax/foreign-key-clause.html
|
||||
_consume(TokenType.references, 'Expected REFERENCES');
|
||||
final firstToken = _previous;
|
||||
|
||||
final foreignTable = _consumeIdentifier('Expected a table name');
|
||||
final foreignTableName = TableReference(foreignTable.identifier, null)
|
||||
..setSpan(foreignTable, foreignTable);
|
||||
|
||||
final foreignTable = _tableReference(allowAlias: false);
|
||||
final columnNames = _listColumnsInParentheses(allowEmpty: true);
|
||||
|
||||
ReferenceAction? onDelete, onUpdate;
|
||||
|
@ -2472,7 +2505,7 @@ class Parser {
|
|||
}
|
||||
|
||||
return ForeignKeyClause(
|
||||
foreignTable: foreignTableName,
|
||||
foreignTable: foreignTable,
|
||||
columnNames: columnNames,
|
||||
onUpdate: onUpdate,
|
||||
onDelete: onDelete,
|
||||
|
|
|
@ -547,7 +547,8 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
|
|||
void visitReference(Reference e, void arg) {
|
||||
final current = _currentAs<Reference>(e);
|
||||
_assert(
|
||||
current.entityName == e.entityName &&
|
||||
current.schemaName == e.schemaName &&
|
||||
current.entityName == e.entityName &&
|
||||
current.columnName == e.columnName,
|
||||
e);
|
||||
_checkChildren(e);
|
||||
|
@ -628,7 +629,11 @@ class EqualityEnforcingVisitor implements AstVisitor<void, void> {
|
|||
@override
|
||||
void visitTableReference(TableReference e, void arg) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -964,14 +964,22 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
|
|||
|
||||
@override
|
||||
void visitReference(Reference e, void arg) {
|
||||
var hasTable = false;
|
||||
if (e.entityName != null) {
|
||||
hasTable = true;
|
||||
_identifier(e.entityName!, spaceAfter: false);
|
||||
var didWriteSpaceBefore = false;
|
||||
|
||||
if (e.schemaName != null) {
|
||||
_identifier(e.schemaName!, spaceAfter: false);
|
||||
_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
|
||||
|
@ -1131,7 +1139,12 @@ class NodeSqlBuilder extends AstVisitor<void, void> {
|
|||
|
||||
@override
|
||||
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) {
|
||||
_keyword(TokenType.as);
|
||||
_identifier(e.as!);
|
||||
|
|
|
@ -77,7 +77,7 @@ void main() {
|
|||
ForeignKeyColumnConstraint(
|
||||
null,
|
||||
ForeignKeyClause(
|
||||
foreignTable: TableReference('some', null),
|
||||
foreignTable: TableReference('some'),
|
||||
columnNames: [Reference(columnName: 'thing')],
|
||||
onUpdate: ReferenceAction.cascade,
|
||||
onDelete: ReferenceAction.setNull,
|
||||
|
@ -107,7 +107,7 @@ void main() {
|
|||
Reference(columnName: 'email'),
|
||||
],
|
||||
clause: ForeignKeyClause(
|
||||
foreignTable: TableReference('another', null),
|
||||
foreignTable: TableReference('another'),
|
||||
columnNames: [
|
||||
Reference(columnName: 'a'),
|
||||
Reference(columnName: 'b'),
|
||||
|
|
|
@ -9,7 +9,7 @@ void main() {
|
|||
testStatement(
|
||||
'DELETE FROM tbl WHERE id = 5',
|
||||
DeleteStatement(
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
where: BinaryExpression(
|
||||
Reference(columnName: 'id'),
|
||||
token(TokenType.equal),
|
||||
|
@ -26,7 +26,7 @@ void main() {
|
|||
testStatement(
|
||||
'DELETE FROM tbl RETURNING *;',
|
||||
DeleteStatement(
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
returning: Returning([StarResultColumn()]),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -106,7 +106,7 @@ final Map<String, Expression> _testCases = {
|
|||
ExistsExpression(
|
||||
select: SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('demo', null),
|
||||
from: TableReference('demo'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -141,7 +141,7 @@ final Map<String, Expression> _testCases = {
|
|||
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(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() {
|
||||
|
|
|
@ -9,7 +9,7 @@ void main() {
|
|||
r'SELECT * FROM tbl LIMIT $limit',
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
limit: DartLimitPlaceholder(name: 'limit'),
|
||||
),
|
||||
moorMode: true,
|
||||
|
@ -21,7 +21,7 @@ void main() {
|
|||
r'SELECT * FROM tbl LIMIT $amount OFFSET 3',
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
limit: Limit(
|
||||
count: DartExpressionPlaceholder(name: 'amount'),
|
||||
offsetSeparator: token(TokenType.offset),
|
||||
|
@ -37,7 +37,7 @@ void main() {
|
|||
r'SELECT * FROM tbl ORDER BY $term, $expr DESC',
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
orderBy: OrderBy(
|
||||
terms: [
|
||||
DartOrderingTermPlaceholder(name: 'term'),
|
||||
|
@ -57,7 +57,7 @@ void main() {
|
|||
r'SELECT * FROM tbl ORDER BY $order',
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
orderBy: DartOrderByPlaceholder(name: 'order'),
|
||||
),
|
||||
moorMode: true,
|
||||
|
|
|
@ -9,7 +9,7 @@ void main() {
|
|||
'INSERT OR REPLACE INTO tbl (a, b, c) VALUES (d, e, f)',
|
||||
InsertStatement(
|
||||
mode: InsertMode.insertOrReplace,
|
||||
table: TableReference('tbl', null),
|
||||
table: TableReference('tbl'),
|
||||
targetColumns: [
|
||||
Reference(columnName: 'a'),
|
||||
Reference(columnName: 'b'),
|
||||
|
@ -31,7 +31,7 @@ void main() {
|
|||
'INSERT INTO tbl DEFAULT VALUES',
|
||||
InsertStatement(
|
||||
mode: InsertMode.insert,
|
||||
table: TableReference('tbl', null),
|
||||
table: TableReference('tbl'),
|
||||
targetColumns: const [],
|
||||
source: DefaultValues(),
|
||||
),
|
||||
|
@ -43,12 +43,12 @@ void main() {
|
|||
'REPLACE INTO tbl SELECT * FROM tbl',
|
||||
InsertStatement(
|
||||
mode: InsertMode.replace,
|
||||
table: TableReference('tbl', null),
|
||||
table: TableReference('tbl'),
|
||||
targetColumns: const [],
|
||||
source: SelectInsertSource(
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -46,7 +46,7 @@ void main() {
|
|||
ForeignKeyColumnConstraint(
|
||||
null,
|
||||
ForeignKeyClause(
|
||||
foreignTable: TableReference('other', null),
|
||||
foreignTable: TableReference('other'),
|
||||
columnNames: [
|
||||
Reference(columnName: 'location'),
|
||||
],
|
||||
|
@ -62,7 +62,7 @@ void main() {
|
|||
SimpleName('all'),
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
where: DartExpressionPlaceholder(name: 'predicate'),
|
||||
),
|
||||
),
|
||||
|
@ -70,7 +70,7 @@ void main() {
|
|||
SpecialStatementIdentifier('special'),
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
),
|
||||
DeclaredStatement(
|
||||
|
@ -104,7 +104,7 @@ void main() {
|
|||
SimpleName('nested'),
|
||||
SelectStatement(
|
||||
columns: [NestedStarResultColumn('foo')],
|
||||
from: TableReference('tbl', 'foo'),
|
||||
from: TableReference('tbl', as: 'foo'),
|
||||
),
|
||||
as: 'MyResultSet',
|
||||
),
|
||||
|
|
|
@ -16,7 +16,7 @@ void main() {
|
|||
DeclaredStatement(
|
||||
SimpleName('a'),
|
||||
UpdateStatement(
|
||||
table: TableReference('tbl', null),
|
||||
table: TableReference('tbl'),
|
||||
set: [
|
||||
SetComponent(
|
||||
column: Reference(columnName: 'a'),
|
||||
|
@ -29,7 +29,7 @@ void main() {
|
|||
SimpleName('b'),
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
),
|
||||
]),
|
||||
|
@ -48,7 +48,7 @@ void main() {
|
|||
SimpleName('b'),
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -78,7 +78,7 @@ void main() {
|
|||
SimpleName('query'),
|
||||
SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -47,7 +47,7 @@ void main() {
|
|||
and n.folderId = :selectedFolderId;
|
||||
''',
|
||||
SelectStatement(
|
||||
from: TableReference('notes', 'n'),
|
||||
from: TableReference('notes', as: 'n'),
|
||||
columns: [StarResultColumn()],
|
||||
where: BinaryExpression(
|
||||
caseExpr,
|
||||
|
@ -69,7 +69,7 @@ void main() {
|
|||
END;
|
||||
''',
|
||||
SelectStatement(
|
||||
from: TableReference('notes', 'n'),
|
||||
from: TableReference('notes', as: 'n'),
|
||||
columns: [StarResultColumn()],
|
||||
where: BinaryExpression(
|
||||
folderExpr,
|
||||
|
|
|
@ -10,7 +10,7 @@ void main() {
|
|||
CompoundSelectStatement(
|
||||
base: SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
additional: [
|
||||
CompoundSelectPart(
|
||||
|
|
|
@ -16,7 +16,13 @@ void main() {
|
|||
final stmt =
|
||||
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', () {
|
||||
|
@ -27,11 +33,11 @@ void main() {
|
|||
_enforceFrom(
|
||||
stmt,
|
||||
JoinClause(
|
||||
primary: TableReference('tbl', 'test'),
|
||||
primary: TableReference('tbl', as: 'test'),
|
||||
joins: [
|
||||
Join(
|
||||
operator: JoinOperator.comma,
|
||||
query: TableReference('table2', null),
|
||||
query: TableReference('table2'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -46,11 +52,11 @@ void main() {
|
|||
_enforceFrom(
|
||||
stmt,
|
||||
JoinClause(
|
||||
primary: TableReference('tbl', 'test'),
|
||||
primary: TableReference('tbl', as: 'test'),
|
||||
joins: [
|
||||
Join(
|
||||
operator: JoinOperator.comma,
|
||||
query: TableReference('table2', null),
|
||||
query: TableReference('table2'),
|
||||
constraint: OnConstraint(
|
||||
expression: BooleanLiteral.withTrue(token(TokenType.$true)),
|
||||
),
|
||||
|
@ -69,14 +75,14 @@ void main() {
|
|||
_enforceFrom(
|
||||
stmt,
|
||||
JoinClause(
|
||||
primary: TableReference('table1', null),
|
||||
primary: TableReference('table1'),
|
||||
joins: [
|
||||
Join(
|
||||
operator: JoinOperator.comma,
|
||||
query: SelectStatementAsSource(
|
||||
statement: SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('table2', null),
|
||||
from: TableReference('table2'),
|
||||
where: Reference(columnName: 'a'),
|
||||
),
|
||||
as: 'inner',
|
||||
|
@ -132,16 +138,16 @@ void main() {
|
|||
_enforceFrom(
|
||||
stmt,
|
||||
JoinClause(
|
||||
primary: TableReference('table1', null),
|
||||
primary: TableReference('table1'),
|
||||
joins: [
|
||||
Join(
|
||||
operator: JoinOperator.inner,
|
||||
query: TableReference('table2', null),
|
||||
query: TableReference('table2'),
|
||||
constraint: UsingConstraint(columnNames: ['test']),
|
||||
),
|
||||
Join(
|
||||
operator: JoinOperator.leftOuter,
|
||||
query: TableReference('table3', null),
|
||||
query: TableReference('table3'),
|
||||
constraint: OnConstraint(
|
||||
expression: BooleanLiteral.withTrue(token(TokenType.$true)),
|
||||
),
|
||||
|
|
|
@ -32,16 +32,16 @@ final Map<String, AstNode> testCases = {
|
|||
expression: SubQuery(
|
||||
select: SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('table2', null),
|
||||
from: TableReference('table2'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
),
|
||||
'SELECT * FROM tbl WHERE id IN ()': SelectStatement(
|
||||
columns: [StarResultColumn(null)],
|
||||
from: TableReference('tbl', null),
|
||||
from: TableReference('tbl'),
|
||||
where: InExpression(
|
||||
left: Reference(columnName: 'id'),
|
||||
inside: Tuple(expressions: []),
|
||||
|
|
|
@ -6,7 +6,7 @@ import 'utils.dart';
|
|||
final Map<String, AstNode> testCases = {
|
||||
'UPDATE OR ROLLBACK tbl SET a = NULL, b = c WHERE d': UpdateStatement(
|
||||
or: FailureMode.rollback,
|
||||
table: TableReference('tbl', null),
|
||||
table: TableReference('tbl'),
|
||||
set: [
|
||||
SetComponent(
|
||||
column: Reference(columnName: 'a'),
|
||||
|
|
|
@ -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', () {
|
||||
testFormat('SELECT * FROM foo LIMIT 3, 4');
|
||||
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', () {
|
||||
testFormat('SELECT -(+(~3));');
|
||||
});
|
||||
|
||||
test('references', () {
|
||||
testFormat('SELECT foo');
|
||||
testFormat('SELECT foo.bar');
|
||||
testFormat('SELECT foo.bar.baz');
|
||||
});
|
||||
});
|
||||
|
||||
group('moor', () {
|
||||
|
|
Loading…
Reference in New Issue