mirror of https://github.com/AMT-Cheif/drift.git
Parse NULL column constraints to fix parsing errors (#909)
This commit is contained in:
parent
def55a0d29
commit
1d7479226a
|
@ -56,6 +56,7 @@ abstract class ColumnConstraint extends AstNode {
|
|||
|
||||
T when<T>({
|
||||
T Function(NotNull) notNull,
|
||||
T Function(NullColumnConstraint) nullable,
|
||||
T Function(PrimaryKeyColumn) primaryKey,
|
||||
T Function(UniqueColumn) unique,
|
||||
T Function(CheckColumn) check,
|
||||
|
@ -66,6 +67,8 @@ abstract class ColumnConstraint extends AstNode {
|
|||
}) {
|
||||
if (this is NotNull) {
|
||||
return notNull?.call(this as NotNull);
|
||||
} else if (this is NullColumnConstraint) {
|
||||
return nullable?.call(this as NullColumnConstraint);
|
||||
} else if (this is PrimaryKeyColumn) {
|
||||
return primaryKey?.call(this as PrimaryKeyColumn);
|
||||
} else if (this is UniqueColumn) {
|
||||
|
@ -96,6 +99,22 @@ abstract class ColumnConstraint extends AstNode {
|
|||
|
||||
enum ConflictClause { rollback, abort, fail, ignore, replace }
|
||||
|
||||
class NullColumnConstraint extends ColumnConstraint {
|
||||
/// The `NULL` token forming this constraint.
|
||||
Token $null;
|
||||
|
||||
NullColumnConstraint(String name, {this.$null}) : super(name);
|
||||
|
||||
@override
|
||||
bool _equalToConstraint(NullColumnConstraint other) => true;
|
||||
|
||||
@override
|
||||
Iterable<AstNode> get childNodes => const Iterable.empty();
|
||||
|
||||
@override
|
||||
void transformChildren<A>(Transformer<A> transformer, A arg) {}
|
||||
}
|
||||
|
||||
class NotNull extends ColumnConstraint {
|
||||
final ConflictClause onConflict;
|
||||
|
||||
|
|
|
@ -436,6 +436,11 @@ mixin SchemaParser on ParserBase {
|
|||
autoIncrement: hasAutoInc, mode: mode, onConflict: conflict)
|
||||
..setSpan(first, _previous);
|
||||
}
|
||||
if (_matchOne(TokenType.$null)) {
|
||||
final nullToken = _previous;
|
||||
return NullColumnConstraint(resolvedName, $null: nullToken)
|
||||
..setSpan(nullToken, nullToken);
|
||||
}
|
||||
if (_matchOne(TokenType.not)) {
|
||||
_suggestHint(HintDescription.token(TokenType.$null));
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS users (
|
|||
id INT NOT NULL PRIMARY KEY DESC ON CONFLICT ROLLBACK AUTOINCREMENT,
|
||||
email VARCHAR NOT NULL UNIQUE ON CONFLICT ABORT,
|
||||
score INT CONSTRAINT "score set" NOT NULL DEFAULT 420 CHECK (score > 0),
|
||||
display_name VARCHAR COLLATE BINARY
|
||||
display_name VARCHAR NULL COLLATE BINARY
|
||||
REFERENCES some(thing) ON UPDATE CASCADE ON DELETE SET NULL
|
||||
DEFERRABLE INITIALLY DEFERRED,
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ void main() {
|
|||
columnName: 'display_name',
|
||||
typeName: 'VARCHAR',
|
||||
constraints: [
|
||||
NullColumnConstraint(null),
|
||||
CollateConstraint(
|
||||
null,
|
||||
'BINARY',
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:sqlparser/sqlparser.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
void main() {
|
||||
const stmts = [
|
||||
'CREATE TABLE plots (owner_id VARCHAR NOT NULL, deleted INTEGER NOT NULL, last_synced INTEGER NULL, last_modified INTEGER NOT NULL, id VARCHAR NOT NULL, name VARCHAR NOT NULL, crop VARCHAR NOT NULL, crop_variety VARCHAR NOT NULL, planting_date INTEGER NOT NULL, is_outdoor_trial INTEGER NOT NULL CHECK (is_outdoor_trial in (0, 1)), uses_crop_blanket INTEGER NOT NULL CHECK (uses_crop_blanket in (0, 1)), is_raised_bed INTEGER NOT NULL CHECK (is_raised_bed in (0, 1)), plant_spacing REAL NOT NULL, row_spacing REAL NOT NULL, irrigation_type VARCHAR NOT NULL, rows_per_bed REAL NULL, bed_spacing REAL NULL, coordinates VARCHAR NOT NULL, PRIMARY KEY (id))',
|
||||
'CREATE TABLE lab_reports (owner_id VARCHAR NOT NULL, deleted INTEGER NOT NULL, last_synced INTEGER NULL, last_modified INTEGER NOT NULL, id VARCHAR NOT NULL, sample_date INTEGER NOT NULL, source VARCHAR NOT NULL, PRIMARY KEY (id))',
|
||||
'CREATE TABLE dissipated_active_ingredients (id VARCHAR NOT NULL, lab_report_id VARCHAR NOT NULL, active_ingredient_id VARCHAR NULL, name VARCHAR NULL, residue REAL NOT NULL, PRIMARY KEY (id))',
|
||||
'CREATE TABLE sprays (owner_id VARCHAR NOT NULL, deleted INTEGER NOT NULL, last_synced INTEGER NULL, last_modified INTEGER NOT NULL, id VARCHAR NOT NULL, create_date INTEGER NOT NULL, application_method VARCHAR NOT NULL, growth_stage VARCHAR NOT NULL, PRIMARY KEY (id))',
|
||||
'CREATE TABLE products (id VARCHAR NOT NULL, trade_name VARCHAR NOT NULL, type VARCHAR NOT NULL, owner_id VARCHAR NULL, PRIMARY KEY (id))',
|
||||
'CREATE TABLE markets (owner_id VARCHAR NOT NULL, deleted INTEGER NOT NULL, last_synced INTEGER NULL, last_modified INTEGER NOT NULL, id VARCHAR NOT NULL, name VARCHAR NOT NULL, mrl REAL NOT NULL, arfd REAL NOT NULL, adi REAL NOT NULL, total_active_ingredients INTEGER NOT NULL, PRIMARY KEY (id))',
|
||||
];
|
||||
|
||||
test('parses statements', () {
|
||||
final engine = SqlEngine();
|
||||
|
||||
for (final stmt in stmts) {
|
||||
final result = engine.parse(stmt);
|
||||
expect(result.errors, isEmpty);
|
||||
expect(result.rootNode, isA<CreateTableStatement>());
|
||||
}
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue