From 5c6331e486371ba1078b6abf74ae8ace2ee8859d Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 15 Jun 2020 17:45:28 +0200 Subject: [PATCH] sqlparser: Make InsertSource an AstNode --- sqlparser/CHANGELOG.md | 2 +- sqlparser/lib/src/ast/statements/insert.dart | 62 +++++++++++++++----- sqlparser/lib/src/ast/visitor.dart | 23 ++++++++ sqlparser/lib/src/reader/parser/crud.dart | 11 +++- sqlparser/test/parser/insert_test.dart | 12 ++-- 5 files changed, 84 insertions(+), 26 deletions(-) diff --git a/sqlparser/CHANGELOG.md b/sqlparser/CHANGELOG.md index 4b9b652c..11b21827 100644 --- a/sqlparser/CHANGELOG.md +++ b/sqlparser/CHANGELOG.md @@ -2,7 +2,7 @@ - Breaking: Made `RecursiveVisitor.visit`, `visitList` and `visitExcept` an extension on `AstVisitor`. - Support the transformer pattern to modify ast nodes -- Breaking: `FrameBoundary`, `DeleteTarget`, `UpdateTarget` and `InsertTarget` are no longer constant +- Breaking: `FrameBoundary`, `DeleteTarget`, `UpdateTarget`, `DefaultValues` and `InsertTarget` are no longer constant - Support parsing and analyzing `CREATE VIEW` statements (see `SchemaFromCreateTable.readView`). Thanks to [@mqus](https://github.com/mqus) for their contribution! diff --git a/sqlparser/lib/src/ast/statements/insert.dart b/sqlparser/lib/src/ast/statements/insert.dart index d33237ce..4bf0d3d9 100644 --- a/sqlparser/lib/src/ast/statements/insert.dart +++ b/sqlparser/lib/src/ast/statements/insert.dart @@ -48,13 +48,13 @@ class InsertStatement extends CrudStatement { } @override - Iterable get childNodes sync* { - if (withClause != null) yield withClause; - yield table; - yield* targetColumns; - yield* source.childNodes; - if (upsert != null) yield upsert; - } + Iterable get childNodes => [ + if (withClause != null) withClause, + table, + ...targetColumns, + source, + if (upsert != null) upsert + ]; @override bool contentEquals(InsertStatement other) { @@ -62,12 +62,7 @@ class InsertStatement extends CrudStatement { } } -// todo: Should be an AstNode -abstract class InsertSource { - Iterable get childNodes; - - const InsertSource(); - +abstract class InsertSource extends AstNode { T when( {T Function(ValuesSource) isValues, T Function(SelectInsertSource) isSelect, @@ -92,22 +87,57 @@ class ValuesSource extends InsertSource { @override Iterable get childNodes => values; + + @override + R accept(AstVisitor visitor, A arg) { + return visitor.visitValuesSource(this, arg); + } + + @override + bool contentEquals(ValuesSource other) => true; + + @override + void transformChildren(Transformer transformer, A arg) { + transformer.transformChildren(values, this, arg); + } } /// Inserts the rows returned by [stmt]. class SelectInsertSource extends InsertSource { - final BaseSelectStatement stmt; + BaseSelectStatement stmt; SelectInsertSource(this.stmt); @override Iterable get childNodes => [stmt]; + + @override + R accept(AstVisitor visitor, A arg) { + return visitor.visitSelectInsertSource(this, arg); + } + + @override + bool contentEquals(SelectInsertSource other) => true; + + @override + void transformChildren(Transformer transformer, A arg) { + stmt = transformer.transformChild(stmt, this, arg); + } } /// Use `DEFAULT VALUES` for an insert statement. class DefaultValues extends InsertSource { - const DefaultValues(); - @override Iterable get childNodes => const []; + + @override + R accept(AstVisitor visitor, A arg) { + return visitor.visitDefaultValues(this, arg); + } + + @override + bool contentEquals(DefaultValues other) => true; + + @override + void transformChildren(Transformer transformer, A arg) {} } diff --git a/sqlparser/lib/src/ast/visitor.dart b/sqlparser/lib/src/ast/visitor.dart index 83fd4e8c..27bb4f97 100644 --- a/sqlparser/lib/src/ast/visitor.dart +++ b/sqlparser/lib/src/ast/visitor.dart @@ -34,6 +34,10 @@ abstract class AstVisitor { R visitSetComponent(SetComponent e, A arg); + R visitValuesSource(ValuesSource e, A arg); + R visitSelectInsertSource(SelectInsertSource e, A arg); + R visitDefaultValues(DefaultValues e, A arg); + R visitColumnDefinition(ColumnDefinition e, A arg); R visitColumnConstraint(ColumnConstraint e, A arg); R visitTableConstraint(TableConstraint e, A arg); @@ -257,6 +261,25 @@ class RecursiveVisitor implements AstVisitor { return defaultNode(e, arg); } + @override + R visitValuesSource(ValuesSource e, A arg) { + return defaultInsertSource(e, arg); + } + + @override + R visitSelectInsertSource(SelectInsertSource e, A arg) { + return defaultInsertSource(e, arg); + } + + @override + R visitDefaultValues(DefaultValues e, A arg) { + return defaultInsertSource(e, arg); + } + + R defaultInsertSource(InsertSource e, A arg) { + return defaultNode(e, arg); + } + @override R visitColumnDefinition(ColumnDefinition e, A arg) { return defaultNode(e, arg); diff --git a/sqlparser/lib/src/reader/parser/crud.dart b/sqlparser/lib/src/reader/parser/crud.dart index 9f1ae338..67ce483f 100644 --- a/sqlparser/lib/src/reader/parser/crud.dart +++ b/sqlparser/lib/src/reader/parser/crud.dart @@ -667,18 +667,23 @@ mixin CrudParser on ParserBase { InsertSource _insertSource() { if (_matchOne(TokenType.$values)) { + final first = _previous; final values = []; do { // it will be a tuple, we don't turn on "orSubQuery" values.add(_consumeTuple() as Tuple); } while (_matchOne(TokenType.comma)); - return ValuesSource(values); + + return ValuesSource(values)..setSpan(first, _previous); } else if (_matchOne(TokenType.$default)) { + final first = _previous; _consume(TokenType.$values, 'Expected DEFAULT VALUES'); - return const DefaultValues(); + return DefaultValues()..setSpan(first, _previous); } else { + final first = _previous; return SelectInsertSource( - _fullSelect() ?? _error('Expeced a select statement')); + _fullSelect() ?? _error('Expeced a select statement'), + )..setSpan(first, _previous); } } diff --git a/sqlparser/test/parser/insert_test.dart b/sqlparser/test/parser/insert_test.dart index 8b937e97..4500aa24 100644 --- a/sqlparser/test/parser/insert_test.dart +++ b/sqlparser/test/parser/insert_test.dart @@ -33,7 +33,7 @@ void main() { mode: InsertMode.insert, table: TableReference('tbl', null), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), ), ); }); @@ -63,7 +63,7 @@ void main() { InsertStatement( table: TableReference('tbl'), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), upsert: UpsertClause(action: DoNothing()), ), ); @@ -75,7 +75,7 @@ void main() { InsertStatement( table: TableReference('tbl'), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), upsert: UpsertClause( onColumns: [ IndexedColumn(Reference(columnName: 'foo')), @@ -96,7 +96,7 @@ void main() { InsertStatement( table: TableReference('tbl'), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), upsert: UpsertClause( onColumns: [ IndexedColumn(Reference(columnName: 'foo')), @@ -119,7 +119,7 @@ void main() { InsertStatement( table: TableReference('tbl'), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), upsert: UpsertClause( action: DoUpdate( [ @@ -140,7 +140,7 @@ void main() { InsertStatement( table: TableReference('tbl'), targetColumns: const [], - source: const DefaultValues(), + source: DefaultValues(), upsert: UpsertClause( action: DoUpdate( [