Two more lints for RETURNING clauses

This commit is contained in:
Simon Binder 2021-03-30 10:30:24 +02:00
parent 24f77bafa1
commit 0842a47d31
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
3 changed files with 59 additions and 0 deletions

View File

@ -1,3 +1,7 @@
## 0.15.1-dev
- New analysis checks for `RETURNING`: Disallow `table.*` syntax and aggregate expressions
## 0.15.0
- __Breaking__: Change `InsertStatement.upsert` to a list of upsert clauses

View File

@ -128,6 +128,29 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
}
}
for (final column in e.columns) {
// Table wildcards are not currently allowed, see
// https://www.sqlite.org/src/info/132994c8b1063bfb
if (column is StarResultColumn && column.tableName != null) {
context.reportError(AnalysisError(
type: AnalysisErrorType.synctactic,
message: 'Columns in RETURNING may not use the TABLE.* syntax',
relevantNode: column,
));
} else if (column is ExpressionResultColumn) {
// While we're at it, window expressions aren't allowed either
if (column.expression is AggregateExpression) {
context.reportError(
AnalysisError(
type: AnalysisErrorType.illegalUseOfReturning,
message: 'Aggregate expressions are not allowed in RETURNING',
relevantNode: column.expression,
),
);
}
}
}
visitChildren(e, arg);
}

View File

@ -30,4 +30,36 @@ void main() {
expect(result.errors, hasLength(1));
expect(result.errors.single.type, AnalysisErrorType.illegalUseOfReturning);
});
test('does not allow star columns with an associated table', () {
final result = engine.analyze('''
UPDATE t SET id = t.id + 1
FROM (SELECT * FROM t) AS old
RETURNING old.*;
''');
expect(result.errors, hasLength(1));
expect(
result.errors.single,
isA<AnalysisError>()
.having((e) => e.source!.span!.text, 'source.span.text', 'old.*')
.having((e) => e.message, 'message',
contains('RETURNING may not use the TABLE.* syntax')),
);
});
test('does not allow aggregate expressions', () {
final result = engine.analyze('INSERT INTO t DEFAULT VALUES RETURNING '
'MAX(id) OVER (PARTITION BY c2)');
expect(result.errors, hasLength(1));
expect(
result.errors.single,
isA<AnalysisError>()
.having((e) => e.source!.span!.text, 'source.span.text',
'MAX(id) OVER (PARTITION BY c2)')
.having((e) => e.message, 'message',
'Aggregate expressions are not allowed in RETURNING'),
);
});
}