Write model classes to represent CREATE TABLE statements

This commit is contained in:
Simon Binder 2019-07-26 11:35:53 +02:00
parent 21956a6b48
commit 888e429467
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 188 additions and 0 deletions

View File

@ -19,6 +19,9 @@ part 'expressions/subquery.dart';
part 'expressions/tuple.dart';
part 'expressions/variables.dart';
part 'schema/column_definition.dart';
part 'statements/create_table.dart';
part 'statements/delete.dart';
part 'statements/select.dart';
part 'statements/statement.dart';
@ -127,6 +130,7 @@ abstract class AstVisitor<T> {
T visitResultColumn(ResultColumn e);
T visitDeleteStatement(DeleteStatement e);
T visitUpdateStatement(UpdateStatement e);
T visitCreateTableStatement(CreateTableStatement e);
T visitOrderBy(OrderBy e);
T visitOrderingTerm(OrderingTerm e);
@ -137,6 +141,9 @@ abstract class AstVisitor<T> {
T visitSetComponent(SetComponent e);
T visitColumnDefinition(ColumnDefinition e);
T visitColumnConstraint(ColumnConstraint e);
T visitBinaryExpression(BinaryExpression e);
T visitStringComparison(StringComparisonExpression e);
T visitUnaryExpression(UnaryExpression e);
@ -236,9 +243,18 @@ class RecursiveVisitor<T> extends AstVisitor<T> {
@override
T visitUpdateStatement(UpdateStatement e) => visitChildren(e);
@override
T visitCreateTableStatement(CreateTableStatement e) => visitChildren(e);
@override
T visitUnaryExpression(UnaryExpression e) => visitChildren(e);
@override
T visitColumnDefinition(ColumnDefinition e) => visitChildren(e);
@override
T visitColumnConstraint(ColumnConstraint e) => visitChildren(e);
@protected
T visitChildren(AstNode e) {
for (var child in e.childNodes) {

View File

@ -0,0 +1,132 @@
part of '../ast.dart';
/// https://www.sqlite.org/syntax/column-def.html
class ColumnDefinition extends AstNode {
final String columnName;
final String typeName;
final List<ColumnConstraint> constraints;
ColumnDefinition(
{@required this.columnName,
@required this.typeName,
this.constraints = const []});
@override
T accept<T>(AstVisitor<T> visitor) => visitor.visitColumnDefinition(this);
@override
Iterable<AstNode> get childNodes => constraints;
@override
bool contentEquals(ColumnDefinition other) {
return other.columnName == columnName && other.typeName == typeName;
}
}
/// https://www.sqlite.org/syntax/column-constraint.html
abstract class ColumnConstraint extends AstNode {
// todo foreign key clause
@override
T accept<T>(AstVisitor<T> visitor) => visitor.visitColumnConstraint(this);
T when<T>({
T Function(NotNull n) notNull,
T Function(PrimaryKey) primaryKey,
T Function(Unique) unique,
T Function(Check) check,
T Function(Default) isDefault,
T Function(CollateConstraint) collate,
}) {
if (this is NotNull) {
return notNull?.call(this as NotNull);
} else if (this is PrimaryKey) {
return primaryKey?.call(this as PrimaryKey);
} else if (this is Unique) {
return unique?.call(this as Unique);
} else if (this is Check) {
return check?.call(this as Check);
} else if (this is Default) {
return isDefault?.call(this as Default);
} else if (this is CollateConstraint) {
return collate?.call(this as CollateConstraint);
} else {
throw Exception('Did not expect $runtimeType as a ColumnConstraint');
}
}
}
enum ConflictClause { rollback, abort, fail, ignore, replace }
class NotNull extends ColumnConstraint {
@override
final Iterable<AstNode> childNodes = const [];
@override
bool contentEquals(NotNull other) => true;
}
class PrimaryKey extends ColumnConstraint {
final bool autoIncrement;
final OrderingMode mode;
PrimaryKey(this.autoIncrement, this.mode);
@override
Iterable<AstNode> get childNodes => null;
@override
bool contentEquals(PrimaryKey other) {
return other.autoIncrement == autoIncrement && other.mode == mode;
}
}
class Unique extends ColumnConstraint {
final ConflictClause onConflict;
Unique(this.onConflict);
@override
Iterable<AstNode> get childNodes => const [];
@override
bool contentEquals(Unique other) {
return other.onConflict == onConflict;
}
}
class Check extends ColumnConstraint {
final Expression expression;
Check(this.expression);
@override
Iterable<AstNode> get childNodes => [expression];
@override
bool contentEquals(Check other) => true;
}
class Default extends ColumnConstraint {
final Expression expression;
Default(this.expression);
@override
Iterable<AstNode> get childNodes => [expression];
@override
bool contentEquals(Default other) => true;
}
class CollateConstraint extends ColumnConstraint {
final String collation;
CollateConstraint(this.collation);
@override
final Iterable<AstNode> childNodes = const [];
@override
bool contentEquals(CollateConstraint other) => true;
}

View File

@ -0,0 +1,29 @@
part of '../ast.dart';
/// A "CREATE TABLE" statement, see https://www.sqlite.org/lang_createtable.html
/// for the individual components.
class CreateTableStatement extends Statement {
final bool ifNotExists;
final String tableName;
final List<ColumnDefinition> columns;
final bool withoutRowId;
CreateTableStatement(
{this.ifNotExists = false,
@required this.tableName,
this.columns,
this.withoutRowId = false});
@override
T accept<T>(AstVisitor<T> visitor) => visitor.visitCreateTableStatement(this);
@override
Iterable<AstNode> get childNodes => columns;
@override
bool contentEquals(CreateTableStatement other) {
return other.ifNotExists == ifNotExists &&
other.tableName == tableName &&
other.withoutRowId == withoutRowId;
}
}

View File

@ -95,6 +95,12 @@ enum TokenType {
ignore,
set,
create,
table,
$if,
without,
rowid,
semicolon,
eof,
}
@ -154,6 +160,11 @@ const Map<String, TokenType> keywords = {
'REPLACE': TokenType.replace,
'FAIL': TokenType.fail,
'IGNORE': TokenType.ignore,
'CREATE': TokenType.create,
'TABLE': TokenType.table,
'IF': TokenType.$if,
'WITHOUT': TokenType.without,
'ROWID': TokenType.rowid,
};
class Token {