mirror of https://github.com/AMT-Cheif/drift.git
Fix false-positive trigger syntax error (#2360)
This commit is contained in:
parent
a6549425ef
commit
c38e9cc6c0
|
@ -1,3 +1,7 @@
|
||||||
|
## 0.29.0-dev
|
||||||
|
|
||||||
|
- Fix false-positive warnings about `AS` aliases in subqueries used in triggers.
|
||||||
|
|
||||||
## 0.28.0
|
## 0.28.0
|
||||||
|
|
||||||
- Support the `unhex` function added in sqlite 3.41.0
|
- Support the `unhex` function added in sqlite 3.41.0
|
||||||
|
|
|
@ -6,10 +6,24 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
final EngineOptions options;
|
final EngineOptions options;
|
||||||
final AnalysisContext context;
|
final AnalysisContext context;
|
||||||
|
|
||||||
bool _isTopLevelStatement = true;
|
bool _isInTopLevelTriggerStatement = false;
|
||||||
|
|
||||||
LintingVisitor(this.options, this.context);
|
LintingVisitor(this.options, this.context);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void visitBaseSelectStatement(BaseSelectStatement stmt, void arg) {
|
||||||
|
if (_isInTopLevelTriggerStatement) {
|
||||||
|
// If this select statement is used as a subqery, we're no longer in a
|
||||||
|
// top-level trigger statements.
|
||||||
|
final saved = _isInTopLevelTriggerStatement;
|
||||||
|
_isInTopLevelTriggerStatement = stmt.parent is Block;
|
||||||
|
super.visitBaseSelectStatement(stmt, arg);
|
||||||
|
_isInTopLevelTriggerStatement = saved;
|
||||||
|
} else {
|
||||||
|
super.visitBaseSelectStatement(stmt, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void visitBinaryExpression(BinaryExpression e, void arg) {
|
void visitBinaryExpression(BinaryExpression e, void arg) {
|
||||||
final operator = e.operator.type;
|
final operator = e.operator.type;
|
||||||
|
@ -141,10 +155,10 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void visitCreateTriggerStatement(CreateTriggerStatement e, void arg) {
|
void visitCreateTriggerStatement(CreateTriggerStatement e, void arg) {
|
||||||
final topLevelBefore = _isTopLevelStatement;
|
final topLevelBefore = _isInTopLevelTriggerStatement;
|
||||||
_isTopLevelStatement = false;
|
_isInTopLevelTriggerStatement = true;
|
||||||
visitChildren(e, arg);
|
visitChildren(e, arg);
|
||||||
_isTopLevelStatement = topLevelBefore;
|
_isInTopLevelTriggerStatement = topLevelBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -172,7 +186,7 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
@override
|
@override
|
||||||
void visitDefaultValues(DefaultValues e, void arg) {
|
void visitDefaultValues(DefaultValues e, void arg) {
|
||||||
// `DEFAULT VALUES` is not supported in a trigger, see https://www.sqlite.org/lang_insert.html
|
// `DEFAULT VALUES` is not supported in a trigger, see https://www.sqlite.org/lang_insert.html
|
||||||
if (!_isTopLevelStatement) {
|
if (_isInTopLevelTriggerStatement) {
|
||||||
context.reportError(
|
context.reportError(
|
||||||
AnalysisError(
|
AnalysisError(
|
||||||
type: AnalysisErrorType.synctactic,
|
type: AnalysisErrorType.synctactic,
|
||||||
|
@ -304,7 +318,7 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void visitRaiseExpression(RaiseExpression e, void arg) {
|
void visitRaiseExpression(RaiseExpression e, void arg) {
|
||||||
if (_isTopLevelStatement) {
|
if (!_isInTopLevelTriggerStatement) {
|
||||||
context.reportError(AnalysisError(
|
context.reportError(AnalysisError(
|
||||||
type: AnalysisErrorType.raiseMisuse,
|
type: AnalysisErrorType.raiseMisuse,
|
||||||
relevantNode: e,
|
relevantNode: e,
|
||||||
|
@ -328,7 +342,7 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
|
|
||||||
// https://www.sqlite.org/lang_returning.html#limitations_and_caveats
|
// https://www.sqlite.org/lang_returning.html#limitations_and_caveats
|
||||||
// Returning is not allowed in triggers
|
// Returning is not allowed in triggers
|
||||||
if (!_isTopLevelStatement) {
|
if (_isInTopLevelTriggerStatement) {
|
||||||
context.reportError(AnalysisError(
|
context.reportError(AnalysisError(
|
||||||
type: AnalysisErrorType.illegalUseOfReturning,
|
type: AnalysisErrorType.illegalUseOfReturning,
|
||||||
message: 'RETURNING is not allowed in triggers',
|
message: 'RETURNING is not allowed in triggers',
|
||||||
|
@ -421,7 +435,7 @@ class LintingVisitor extends RecursiveVisitor<void, void> {
|
||||||
if (parent is HasPrimarySource && parent.table == e) {
|
if (parent is HasPrimarySource && parent.table == e) {
|
||||||
// The source of a `INSERT`, `UPDATE` or `DELETE` statement must not have
|
// The source of a `INSERT`, `UPDATE` or `DELETE` statement must not have
|
||||||
// an alias in `CREATE TRIGGER` statements.
|
// an alias in `CREATE TRIGGER` statements.
|
||||||
if (!_isTopLevelStatement && e.as != null) {
|
if (_isInTopLevelTriggerStatement && e.as != null) {
|
||||||
context.reportError(AnalysisError(
|
context.reportError(AnalysisError(
|
||||||
type: AnalysisErrorType.synctactic,
|
type: AnalysisErrorType.synctactic,
|
||||||
message:
|
message:
|
||||||
|
|
|
@ -107,6 +107,14 @@ void main() {
|
||||||
'END;')
|
'END;')
|
||||||
.expectError('demo d', type: AnalysisErrorType.synctactic);
|
.expectError('demo d', type: AnalysisErrorType.synctactic);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('allowed in subquery', () {
|
||||||
|
engine.analyze('''
|
||||||
|
CREATE TRIGGER tgr AFTER DELETE ON demo BEGIN
|
||||||
|
INSERT INTO demo (content) SELECT content FROM demo AS ok;
|
||||||
|
END;
|
||||||
|
''').expectNoError();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue