More lints for trigger bodies (#1656)

This commit is contained in:
Simon Binder 2022-01-26 22:03:40 +01:00
parent 3f165c2df7
commit 45af68851d
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
2 changed files with 78 additions and 0 deletions

View File

@ -153,6 +153,22 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
visitChildren(e, arg);
}
@override
void visitDefaultValues(DefaultValues e, void arg) {
// `DEFAULT VALUES` is not supported in a trigger, see https://www.sqlite.org/lang_insert.html
if (!_isTopLevelStatement) {
context.reportError(
AnalysisError(
type: AnalysisErrorType.synctactic,
message: '`DEFAULT VALUES` cannot be used in a trigger.',
relevantNode: e,
),
);
}
visitChildren(e, arg);
}
@override
void visitInsertStatement(InsertStatement e, void arg) {
for (final target in e.targetColumns) {
@ -295,6 +311,25 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
visitChildren(e, arg);
}
@override
void visitTableReference(TableReference e, void arg) {
final parent = e.parent;
if (parent is HasPrimarySource && parent.table == e) {
// The source of a `INSERT`, `UPDATE` or `DELETE` statement must not have
// an alias in `CREATE TRIGGER` statements.
if (!_isTopLevelStatement && e.as != null) {
context.reportError(AnalysisError(
type: AnalysisErrorType.synctactic,
message:
'The source must not have an `AS` alias when used in a trigger.',
relevantNode: e,
));
}
}
visitChildren(e, arg);
}
@override
void visitTuple(Tuple e, void arg) {
if (!e.usedAsRowValue) return;

View File

@ -4,6 +4,7 @@ import 'package:sqlparser/sqlparser.dart';
import 'package:test/test.dart';
import '../data.dart';
import 'utils.dart';
void main() {
group('DO UPDATE clause without conflict target', () {
@ -66,4 +67,46 @@ void main() {
contains('Only column names can be used in a PRIMARY KEY clause'))
]);
});
group('illegal constructs in triggers', () {
final engine = SqlEngine()..registerTable(demoTable);
test('DEFAULT VALUES', () {
engine.analyze('INSERT INTO demo DEFAULT VALUES').expectNoError();
engine
.analyze('CREATE TRIGGER tgr AFTER DELETE ON demo BEGIN '
'INSERT INTO demo DEFAULT VALUES;'
'END;')
.expectError('DEFAULT VALUES', type: AnalysisErrorType.synctactic);
});
group('aliased source tables', () {
test('insert', () {
engine.analyze('INSERT INTO demo AS d VALUES (?, ?)').expectNoError();
engine
.analyze('CREATE TRIGGER tgr AFTER DELETE ON demo BEGIN '
'INSERT INTO demo AS d VALUES (?, ?);'
'END;')
.expectError('demo AS d', type: AnalysisErrorType.synctactic);
});
test('update', () {
engine.analyze('UPDATE demo AS d SET id = id + 1;').expectNoError();
engine
.analyze('CREATE TRIGGER tgr AFTER DELETE ON demo BEGIN '
'UPDATE demo AS d SET id = id + 1;'
'END;')
.expectError('demo AS d', type: AnalysisErrorType.synctactic);
});
test('delete', () {
engine.analyze('DELETE FROM demo d;').expectNoError();
engine
.analyze('CREATE TRIGGER tgr AFTER DELETE ON demo BEGIN '
'DELETE FROM demo d;'
'END;')
.expectError('demo d', type: AnalysisErrorType.synctactic);
});
});
});
}