visitSelectStatement method
Implementation
@override
void visitSelectStatement(SelectStatement e, void arg) {
// a select statement can appear as a sub query which has its own scope, so
// we need to fork the scope here. There is one special case though:
// Select statements that appear as a query source can't depend on data
// defined in the outer scope. This is different from select statements
// that work as expressions.
// For instance, if you go to sqliteonline.com and issue the following
// query: "SELECT * FROM demo d1,
// (SELECT * FROM demo i WHERE i.id = d1.id) d2;"
// it won't work.
final isInFROM = e.parent is Queryable;
StatementScope scope;
if (isInFROM) {
final surroundingSelect = e.parents
.firstWhere((node) => node is HasFrom)
.scope as StatementScope;
scope = StatementScope(SourceScope(surroundingSelect));
} else {
scope = StatementScope.forStatement(context.rootScope, e);
}
e.scope = scope;
for (final windowDecl in e.windowDeclarations) {
scope.windowDeclarations[windowDecl.name] = windowDecl;
}
// only the last statement in a compound select statement may have an order
// by or a limit clause
if (e.parent is CompoundSelectPart || e.parent is CompoundSelectStatement) {
bool isLast;
if (e.parent is CompoundSelectPart) {
final part = e.parent as CompoundSelectPart;
final compoundSelect = part.parent as CompoundSelectStatement;
final index = compoundSelect.additional.indexOf(part);
isLast = index == compoundSelect.additional.length - 1;
} else {
// if the parent is the compound select statement, this select query is
// the [CompoundSelectStatement.base], so definitely not the last query.
isLast = false;
}
if (!isLast) {
if (e.limit != null) {
context.reportError(AnalysisError(
type: AnalysisErrorType.synctactic,
message: 'Limit clause must appear in the last compound statement',
relevantNode: e.limit,
));
}
if (e.orderBy != null) {
context.reportError(AnalysisError(
type: AnalysisErrorType.synctactic,
message: 'Order by clause must appear in the compound statement',
relevantNode: e.orderBy,
));
}
}
}
visitChildren(e, arg);
}