mirror of https://github.com/AMT-Cheif/drift.git
Merge branch 'develop' into analyzer-plugin
This commit is contained in:
commit
4e75cee785
|
@ -19,6 +19,10 @@ abstract class Table {
|
|||
@visibleForOverriding
|
||||
String get tableName => null;
|
||||
|
||||
/// Whether to append a `WITHOUT ROWID` clause in the `CREATE TABLE`
|
||||
/// statement.
|
||||
bool get withoutRowId => false;
|
||||
|
||||
/// Override this to specify custom primary keys:
|
||||
/// ```dart
|
||||
/// class IngredientInRecipes extends Table {
|
||||
|
|
|
@ -6,8 +6,6 @@ import 'package:moor/src/runtime/expressions/expression.dart';
|
|||
/// The [CustomExpression.content] will be written into the query without any
|
||||
/// modification.
|
||||
///
|
||||
/// When this statement appears in a query
|
||||
///
|
||||
/// See also:
|
||||
/// - [currentDate] and [currentDateAndTime], which use a [CustomExpression]
|
||||
/// internally.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export 'bools.dart' show and, or, not;
|
||||
export 'custom.dart';
|
||||
export 'datetimes.dart';
|
||||
export 'in.dart';
|
||||
export 'null_check.dart';
|
||||
|
|
|
@ -109,13 +109,21 @@ class Migrator {
|
|||
context.buffer.write(')');
|
||||
}
|
||||
|
||||
final constraints = table.asDslTable.customConstraints ?? [];
|
||||
final dslTable = table.asDslTable;
|
||||
final constraints = dslTable.customConstraints ?? [];
|
||||
|
||||
for (var i = 0; i < constraints.length; i++) {
|
||||
context.buffer..write(', ')..write(constraints[i]);
|
||||
}
|
||||
|
||||
context.buffer.write(');');
|
||||
context.buffer.write(')');
|
||||
|
||||
// == true because of nullability
|
||||
if (dslTable.withoutRowId == true) {
|
||||
context.buffer.write(' WITHOUT ROWID');
|
||||
}
|
||||
|
||||
context.buffer.write(';');
|
||||
|
||||
return issueCustomQuery(context.sql, context.boundVariables);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import 'package:moor/moor.dart';
|
||||
|
||||
part 'custom_tables.g.dart';
|
||||
|
||||
@UseMoor(include: {'tables.moor'})
|
||||
class CustomTablesDb extends _$CustomTablesDb {
|
||||
CustomTablesDb(QueryExecutor e) : super(e);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
}
|
|
@ -0,0 +1,451 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'custom_tables.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// MoorGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps
|
||||
class NoId extends DataClass implements Insertable<NoId> {
|
||||
final Uint8List payload;
|
||||
NoId({@required this.payload});
|
||||
factory NoId.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final uint8ListType = db.typeSystem.forDartType<Uint8List>();
|
||||
return NoId(
|
||||
payload: uint8ListType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}payload']),
|
||||
);
|
||||
}
|
||||
factory NoId.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return NoId(
|
||||
payload: serializer.fromJson<Uint8List>(json['payload']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'payload': serializer.toJson<Uint8List>(payload),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<NoId>>(bool nullToAbsent) {
|
||||
return NoIdsCompanion(
|
||||
payload: payload == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(payload),
|
||||
) as T;
|
||||
}
|
||||
|
||||
NoId copyWith({Uint8List payload}) => NoId(
|
||||
payload: payload ?? this.payload,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('NoId(')..write('payload: $payload')..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf(payload.hashCode);
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) || (other is NoId && other.payload == payload);
|
||||
}
|
||||
|
||||
class NoIdsCompanion extends UpdateCompanion<NoId> {
|
||||
final Value<Uint8List> payload;
|
||||
const NoIdsCompanion({
|
||||
this.payload = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class NoIds extends Table with TableInfo<NoIds, NoId> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
NoIds(this._db, [this._alias]);
|
||||
final VerificationMeta _payloadMeta = const VerificationMeta('payload');
|
||||
GeneratedBlobColumn _payload;
|
||||
GeneratedBlobColumn get payload => _payload ??= _constructPayload();
|
||||
GeneratedBlobColumn _constructPayload() {
|
||||
return GeneratedBlobColumn('payload', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [payload];
|
||||
@override
|
||||
NoIds get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'no_ids';
|
||||
@override
|
||||
final String actualTableName = 'no_ids';
|
||||
@override
|
||||
VerificationContext validateIntegrity(NoIdsCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.payload.present) {
|
||||
context.handle(_payloadMeta,
|
||||
payload.isAcceptableValue(d.payload.value, _payloadMeta));
|
||||
} else if (payload.isRequired && isInserting) {
|
||||
context.missing(_payloadMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
||||
@override
|
||||
NoId map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return NoId.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(NoIdsCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.payload.present) {
|
||||
map['payload'] = Variable<Uint8List, BlobType>(d.payload.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
NoIds createAlias(String alias) {
|
||||
return NoIds(_db, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
final bool withoutRowId = true;
|
||||
}
|
||||
|
||||
class WithDefault extends DataClass implements Insertable<WithDefault> {
|
||||
final String a;
|
||||
final int b;
|
||||
WithDefault({this.a, this.b});
|
||||
factory WithDefault.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
return WithDefault(
|
||||
a: stringType.mapFromDatabaseResponse(data['${effectivePrefix}a']),
|
||||
b: intType.mapFromDatabaseResponse(data['${effectivePrefix}b']),
|
||||
);
|
||||
}
|
||||
factory WithDefault.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return WithDefault(
|
||||
a: serializer.fromJson<String>(json['a']),
|
||||
b: serializer.fromJson<int>(json['b']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'a': serializer.toJson<String>(a),
|
||||
'b': serializer.toJson<int>(b),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<WithDefault>>(bool nullToAbsent) {
|
||||
return WithDefaultsCompanion(
|
||||
a: a == null && nullToAbsent ? const Value.absent() : Value(a),
|
||||
b: b == null && nullToAbsent ? const Value.absent() : Value(b),
|
||||
) as T;
|
||||
}
|
||||
|
||||
WithDefault copyWith({String a, int b}) => WithDefault(
|
||||
a: a ?? this.a,
|
||||
b: b ?? this.b,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('WithDefault(')
|
||||
..write('a: $a, ')
|
||||
..write('b: $b')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(a.hashCode, b.hashCode));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is WithDefault && other.a == a && other.b == b);
|
||||
}
|
||||
|
||||
class WithDefaultsCompanion extends UpdateCompanion<WithDefault> {
|
||||
final Value<String> a;
|
||||
final Value<int> b;
|
||||
const WithDefaultsCompanion({
|
||||
this.a = const Value.absent(),
|
||||
this.b = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class WithDefaults extends Table with TableInfo<WithDefaults, WithDefault> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
WithDefaults(this._db, [this._alias]);
|
||||
final VerificationMeta _aMeta = const VerificationMeta('a');
|
||||
GeneratedTextColumn _a;
|
||||
GeneratedTextColumn get a => _a ??= _constructA();
|
||||
GeneratedTextColumn _constructA() {
|
||||
return GeneratedTextColumn('a', $tableName, true,
|
||||
$customConstraints: 'DEFAULT \'something\'',
|
||||
defaultValue:
|
||||
const CustomExpression<String, StringType>('\'something\''));
|
||||
}
|
||||
|
||||
final VerificationMeta _bMeta = const VerificationMeta('b');
|
||||
GeneratedIntColumn _b;
|
||||
GeneratedIntColumn get b => _b ??= _constructB();
|
||||
GeneratedIntColumn _constructB() {
|
||||
return GeneratedIntColumn('b', $tableName, true,
|
||||
$customConstraints: 'UNIQUE');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [a, b];
|
||||
@override
|
||||
WithDefaults get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'with_defaults';
|
||||
@override
|
||||
final String actualTableName = 'with_defaults';
|
||||
@override
|
||||
VerificationContext validateIntegrity(WithDefaultsCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.a.present) {
|
||||
context.handle(_aMeta, a.isAcceptableValue(d.a.value, _aMeta));
|
||||
} else if (a.isRequired && isInserting) {
|
||||
context.missing(_aMeta);
|
||||
}
|
||||
if (d.b.present) {
|
||||
context.handle(_bMeta, b.isAcceptableValue(d.b.value, _bMeta));
|
||||
} else if (b.isRequired && isInserting) {
|
||||
context.missing(_bMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
||||
@override
|
||||
WithDefault map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return WithDefault.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(WithDefaultsCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.a.present) {
|
||||
map['a'] = Variable<String, StringType>(d.a.value);
|
||||
}
|
||||
if (d.b.present) {
|
||||
map['b'] = Variable<int, IntType>(d.b.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
WithDefaults createAlias(String alias) {
|
||||
return WithDefaults(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class WithConstraint extends DataClass implements Insertable<WithConstraint> {
|
||||
final String a;
|
||||
final int b;
|
||||
final double c;
|
||||
WithConstraint({this.a, @required this.b, this.c});
|
||||
factory WithConstraint.fromData(
|
||||
Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final doubleType = db.typeSystem.forDartType<double>();
|
||||
return WithConstraint(
|
||||
a: stringType.mapFromDatabaseResponse(data['${effectivePrefix}a']),
|
||||
b: intType.mapFromDatabaseResponse(data['${effectivePrefix}b']),
|
||||
c: doubleType.mapFromDatabaseResponse(data['${effectivePrefix}c']),
|
||||
);
|
||||
}
|
||||
factory WithConstraint.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return WithConstraint(
|
||||
a: serializer.fromJson<String>(json['a']),
|
||||
b: serializer.fromJson<int>(json['b']),
|
||||
c: serializer.fromJson<double>(json['c']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'a': serializer.toJson<String>(a),
|
||||
'b': serializer.toJson<int>(b),
|
||||
'c': serializer.toJson<double>(c),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<WithConstraint>>(
|
||||
bool nullToAbsent) {
|
||||
return WithConstraintsCompanion(
|
||||
a: a == null && nullToAbsent ? const Value.absent() : Value(a),
|
||||
b: b == null && nullToAbsent ? const Value.absent() : Value(b),
|
||||
c: c == null && nullToAbsent ? const Value.absent() : Value(c),
|
||||
) as T;
|
||||
}
|
||||
|
||||
WithConstraint copyWith({String a, int b, double c}) => WithConstraint(
|
||||
a: a ?? this.a,
|
||||
b: b ?? this.b,
|
||||
c: c ?? this.c,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('WithConstraint(')
|
||||
..write('a: $a, ')
|
||||
..write('b: $b, ')
|
||||
..write('c: $c')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(a.hashCode, $mrjc(b.hashCode, c.hashCode)));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is WithConstraint && other.a == a && other.b == b && other.c == c);
|
||||
}
|
||||
|
||||
class WithConstraintsCompanion extends UpdateCompanion<WithConstraint> {
|
||||
final Value<String> a;
|
||||
final Value<int> b;
|
||||
final Value<double> c;
|
||||
const WithConstraintsCompanion({
|
||||
this.a = const Value.absent(),
|
||||
this.b = const Value.absent(),
|
||||
this.c = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class WithConstraints extends Table
|
||||
with TableInfo<WithConstraints, WithConstraint> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
WithConstraints(this._db, [this._alias]);
|
||||
final VerificationMeta _aMeta = const VerificationMeta('a');
|
||||
GeneratedTextColumn _a;
|
||||
GeneratedTextColumn get a => _a ??= _constructA();
|
||||
GeneratedTextColumn _constructA() {
|
||||
return GeneratedTextColumn('a', $tableName, true, $customConstraints: '');
|
||||
}
|
||||
|
||||
final VerificationMeta _bMeta = const VerificationMeta('b');
|
||||
GeneratedIntColumn _b;
|
||||
GeneratedIntColumn get b => _b ??= _constructB();
|
||||
GeneratedIntColumn _constructB() {
|
||||
return GeneratedIntColumn('b', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
final VerificationMeta _cMeta = const VerificationMeta('c');
|
||||
GeneratedRealColumn _c;
|
||||
GeneratedRealColumn get c => _c ??= _constructC();
|
||||
GeneratedRealColumn _constructC() {
|
||||
return GeneratedRealColumn('c', $tableName, true, $customConstraints: '');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [a, b, c];
|
||||
@override
|
||||
WithConstraints get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'with_constraints';
|
||||
@override
|
||||
final String actualTableName = 'with_constraints';
|
||||
@override
|
||||
VerificationContext validateIntegrity(WithConstraintsCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.a.present) {
|
||||
context.handle(_aMeta, a.isAcceptableValue(d.a.value, _aMeta));
|
||||
} else if (a.isRequired && isInserting) {
|
||||
context.missing(_aMeta);
|
||||
}
|
||||
if (d.b.present) {
|
||||
context.handle(_bMeta, b.isAcceptableValue(d.b.value, _bMeta));
|
||||
} else if (b.isRequired && isInserting) {
|
||||
context.missing(_bMeta);
|
||||
}
|
||||
if (d.c.present) {
|
||||
context.handle(_cMeta, c.isAcceptableValue(d.c.value, _cMeta));
|
||||
} else if (c.isRequired && isInserting) {
|
||||
context.missing(_cMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
||||
@override
|
||||
WithConstraint map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return WithConstraint.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(WithConstraintsCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.a.present) {
|
||||
map['a'] = Variable<String, StringType>(d.a.value);
|
||||
}
|
||||
if (d.b.present) {
|
||||
map['b'] = Variable<int, IntType>(d.b.value);
|
||||
}
|
||||
if (d.c.present) {
|
||||
map['c'] = Variable<double, RealType>(d.c.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
WithConstraints createAlias(String alias) {
|
||||
return WithConstraints(_db, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
final List<String> customConstraints = const [
|
||||
'FOREIGN KEY (a, b) REFERENCES with_defaults (a, b)'
|
||||
];
|
||||
}
|
||||
|
||||
abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||
_$CustomTablesDb(QueryExecutor e)
|
||||
: super(const SqlTypeSystem.withDefaults(), e);
|
||||
NoIds _noIds;
|
||||
NoIds get noIds => _noIds ??= NoIds(this);
|
||||
WithDefaults _withDefaults;
|
||||
WithDefaults get withDefaults => _withDefaults ??= WithDefaults(this);
|
||||
WithConstraints _withConstraints;
|
||||
WithConstraints get withConstraints =>
|
||||
_withConstraints ??= WithConstraints(this);
|
||||
@override
|
||||
List<TableInfo> get allTables => [noIds, withDefaults, withConstraints];
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
CREATE TABLE no_ids (
|
||||
payload BLOB NOT NULL
|
||||
) WITHOUT ROWID;
|
||||
|
||||
CREATE TABLE with_defaults (
|
||||
a TEXT DEFAULT 'something',
|
||||
b INT UNIQUE
|
||||
)
|
||||
|
||||
CREATE TABLE with_constraints (
|
||||
a TEXT,
|
||||
b INT NOT NULL,
|
||||
c FLOAT(10, 2),
|
||||
|
||||
FOREIGN KEY (a, b) REFERENCES with_defaults (a, b)
|
||||
)
|
|
@ -1,10 +0,0 @@
|
|||
CREATE TABLE states (
|
||||
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE experiments (
|
||||
id INT NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
description TEXT NOT NULL,
|
||||
state INT REFERENCES states(id) ON UPDATE CASCADE ON DELETE SET NULL
|
||||
)
|
|
@ -88,7 +88,6 @@ class CustomConverter extends TypeConverter<MyCustomObject, String> {
|
|||
PureDefaults,
|
||||
],
|
||||
daos: [SomeDao],
|
||||
include: {'test.moor'},
|
||||
queries: {
|
||||
'allTodosWithCategory': 'SELECT t.*, c.id as catId, c."desc" as catDesc '
|
||||
'FROM todos t INNER JOIN categories c ON c.id = t.category',
|
||||
|
|
|
@ -1187,325 +1187,6 @@ class $PureDefaultsTable extends PureDefaults
|
|||
}
|
||||
}
|
||||
|
||||
class State extends DataClass implements Insertable<State> {
|
||||
final int id;
|
||||
final String name;
|
||||
State({@required this.id, @required this.name});
|
||||
factory State.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return State(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
name: stringType.mapFromDatabaseResponse(data['${effectivePrefix}name']),
|
||||
);
|
||||
}
|
||||
factory State.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return State(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': serializer.toJson<int>(id),
|
||||
'name': serializer.toJson<String>(name),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<State>>(bool nullToAbsent) {
|
||||
return StatesCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
name: name == null && nullToAbsent ? const Value.absent() : Value(name),
|
||||
) as T;
|
||||
}
|
||||
|
||||
State copyWith({int id, String name}) => State(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('State(')
|
||||
..write('id: $id, ')
|
||||
..write('name: $name')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(id.hashCode, name.hashCode));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is State && other.id == id && other.name == name);
|
||||
}
|
||||
|
||||
class StatesCompanion extends UpdateCompanion<State> {
|
||||
final Value<int> id;
|
||||
final Value<String> name;
|
||||
const StatesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class States extends Table with TableInfo<States, State> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
States(this._db, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
GeneratedIntColumn _id;
|
||||
GeneratedIntColumn get id => _id ??= _constructId();
|
||||
GeneratedIntColumn _constructId() {
|
||||
return GeneratedIntColumn('id', $tableName, false,
|
||||
hasAutoIncrement: true,
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||
}
|
||||
|
||||
final VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||
GeneratedTextColumn _name;
|
||||
GeneratedTextColumn get name => _name ??= _constructName();
|
||||
GeneratedTextColumn _constructName() {
|
||||
return GeneratedTextColumn('name', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name];
|
||||
@override
|
||||
States get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'states';
|
||||
@override
|
||||
final String actualTableName = 'states';
|
||||
@override
|
||||
VerificationContext validateIntegrity(StatesCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.id.present) {
|
||||
context.handle(_idMeta, id.isAcceptableValue(d.id.value, _idMeta));
|
||||
} else if (id.isRequired && isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (d.name.present) {
|
||||
context.handle(
|
||||
_nameMeta, name.isAcceptableValue(d.name.value, _nameMeta));
|
||||
} else if (name.isRequired && isInserting) {
|
||||
context.missing(_nameMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
State map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return State.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(StatesCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.id.present) {
|
||||
map['id'] = Variable<int, IntType>(d.id.value);
|
||||
}
|
||||
if (d.name.present) {
|
||||
map['name'] = Variable<String, StringType>(d.name.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
States createAlias(String alias) {
|
||||
return States(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class Experiment extends DataClass implements Insertable<Experiment> {
|
||||
final int id;
|
||||
final String description;
|
||||
final int state;
|
||||
Experiment({@required this.id, @required this.description, this.state});
|
||||
factory Experiment.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
final intType = db.typeSystem.forDartType<int>();
|
||||
final stringType = db.typeSystem.forDartType<String>();
|
||||
return Experiment(
|
||||
id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']),
|
||||
description: stringType
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}description']),
|
||||
state: intType.mapFromDatabaseResponse(data['${effectivePrefix}state']),
|
||||
);
|
||||
}
|
||||
factory Experiment.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return Experiment(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
description: serializer.fromJson<String>(json['description']),
|
||||
state: serializer.fromJson<int>(json['state']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson(
|
||||
{ValueSerializer serializer = const ValueSerializer.defaults()}) {
|
||||
return {
|
||||
'id': serializer.toJson<int>(id),
|
||||
'description': serializer.toJson<String>(description),
|
||||
'state': serializer.toJson<int>(state),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
T createCompanion<T extends UpdateCompanion<Experiment>>(bool nullToAbsent) {
|
||||
return ExperimentsCompanion(
|
||||
id: id == null && nullToAbsent ? const Value.absent() : Value(id),
|
||||
description: description == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(description),
|
||||
state:
|
||||
state == null && nullToAbsent ? const Value.absent() : Value(state),
|
||||
) as T;
|
||||
}
|
||||
|
||||
Experiment copyWith({int id, String description, int state}) => Experiment(
|
||||
id: id ?? this.id,
|
||||
description: description ?? this.description,
|
||||
state: state ?? this.state,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('Experiment(')
|
||||
..write('id: $id, ')
|
||||
..write('description: $description, ')
|
||||
..write('state: $state')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
$mrjf($mrjc(id.hashCode, $mrjc(description.hashCode, state.hashCode)));
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) ||
|
||||
(other is Experiment &&
|
||||
other.id == id &&
|
||||
other.description == description &&
|
||||
other.state == state);
|
||||
}
|
||||
|
||||
class ExperimentsCompanion extends UpdateCompanion<Experiment> {
|
||||
final Value<int> id;
|
||||
final Value<String> description;
|
||||
final Value<int> state;
|
||||
const ExperimentsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.state = const Value.absent(),
|
||||
});
|
||||
}
|
||||
|
||||
class Experiments extends Table with TableInfo<Experiments, Experiment> {
|
||||
final GeneratedDatabase _db;
|
||||
final String _alias;
|
||||
Experiments(this._db, [this._alias]);
|
||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
GeneratedIntColumn _id;
|
||||
GeneratedIntColumn get id => _id ??= _constructId();
|
||||
GeneratedIntColumn _constructId() {
|
||||
return GeneratedIntColumn('id', $tableName, false,
|
||||
hasAutoIncrement: true,
|
||||
$customConstraints: 'NOT NULL PRIMARY KEY AUTOINCREMENT');
|
||||
}
|
||||
|
||||
final VerificationMeta _descriptionMeta =
|
||||
const VerificationMeta('description');
|
||||
GeneratedTextColumn _description;
|
||||
GeneratedTextColumn get description =>
|
||||
_description ??= _constructDescription();
|
||||
GeneratedTextColumn _constructDescription() {
|
||||
return GeneratedTextColumn('description', $tableName, false,
|
||||
$customConstraints: 'NOT NULL');
|
||||
}
|
||||
|
||||
final VerificationMeta _stateMeta = const VerificationMeta('state');
|
||||
GeneratedIntColumn _state;
|
||||
GeneratedIntColumn get state => _state ??= _constructState();
|
||||
GeneratedIntColumn _constructState() {
|
||||
return GeneratedIntColumn('state', $tableName, true,
|
||||
$customConstraints:
|
||||
'REFERENCES states(id) ON UPDATE CASCADE ON DELETE SET NULL');
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, description, state];
|
||||
@override
|
||||
Experiments get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'experiments';
|
||||
@override
|
||||
final String actualTableName = 'experiments';
|
||||
@override
|
||||
VerificationContext validateIntegrity(ExperimentsCompanion d,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
if (d.id.present) {
|
||||
context.handle(_idMeta, id.isAcceptableValue(d.id.value, _idMeta));
|
||||
} else if (id.isRequired && isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (d.description.present) {
|
||||
context.handle(_descriptionMeta,
|
||||
description.isAcceptableValue(d.description.value, _descriptionMeta));
|
||||
} else if (description.isRequired && isInserting) {
|
||||
context.missing(_descriptionMeta);
|
||||
}
|
||||
if (d.state.present) {
|
||||
context.handle(
|
||||
_stateMeta, state.isAcceptableValue(d.state.value, _stateMeta));
|
||||
} else if (state.isRequired && isInserting) {
|
||||
context.missing(_stateMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
Experiment map(Map<String, dynamic> data, {String tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null;
|
||||
return Experiment.fromData(data, _db, prefix: effectivePrefix);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Variable> entityToSql(ExperimentsCompanion d) {
|
||||
final map = <String, Variable>{};
|
||||
if (d.id.present) {
|
||||
map['id'] = Variable<int, IntType>(d.id.value);
|
||||
}
|
||||
if (d.description.present) {
|
||||
map['description'] = Variable<String, StringType>(d.description.value);
|
||||
}
|
||||
if (d.state.present) {
|
||||
map['state'] = Variable<int, IntType>(d.state.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
Experiments createAlias(String alias) {
|
||||
return Experiments(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class AllTodosWithCategoryResult {
|
||||
final int id;
|
||||
final String title;
|
||||
|
@ -1548,10 +1229,6 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
|||
$PureDefaultsTable _pureDefaults;
|
||||
$PureDefaultsTable get pureDefaults =>
|
||||
_pureDefaults ??= $PureDefaultsTable(this);
|
||||
States _states;
|
||||
States get states => _states ??= States(this);
|
||||
Experiments _experiments;
|
||||
Experiments get experiments => _experiments ??= Experiments(this);
|
||||
SomeDao _someDao;
|
||||
SomeDao get someDao => _someDao ??= SomeDao(this as TodoDb);
|
||||
AllTodosWithCategoryResult _rowToAllTodosWithCategoryResult(QueryRow row) {
|
||||
|
@ -1690,9 +1367,7 @@ abstract class _$TodoDb extends GeneratedDatabase {
|
|||
users,
|
||||
sharedTodos,
|
||||
tableWithoutPK,
|
||||
pureDefaults,
|
||||
states,
|
||||
experiments
|
||||
pureDefaults
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:built_value/built_value.dart';
|
||||
import 'package:moor_generator/src/model/used_type_converter.dart';
|
||||
|
||||
|
@ -61,6 +60,15 @@ const Map<ColumnType, String> createVariable = {
|
|||
ColumnType.real: 'Variable.withReal',
|
||||
};
|
||||
|
||||
const Map<ColumnType, String> sqlTypes = {
|
||||
ColumnType.boolean: 'BoolType',
|
||||
ColumnType.text: 'StringType',
|
||||
ColumnType.integer: 'IntType',
|
||||
ColumnType.datetime: 'DateTimeType',
|
||||
ColumnType.blob: 'BlobType',
|
||||
ColumnType.real: 'RealType',
|
||||
};
|
||||
|
||||
/// A column, as specified by a getter in a table.
|
||||
class SpecifiedColumn {
|
||||
/// The getter name of this column in the table class. It will also be used
|
||||
|
@ -95,10 +103,9 @@ class SpecifiedColumn {
|
|||
/// default ones.
|
||||
final String customConstraints;
|
||||
|
||||
/// If a default expression has been provided as the argument of
|
||||
/// ColumnBuilder.withDefault, contains the Dart code that references that
|
||||
/// expression.
|
||||
final Expression defaultArgument;
|
||||
/// Dart code that generates the default expression for this column, or null
|
||||
/// if there is no default expression.
|
||||
final String defaultArgument;
|
||||
|
||||
/// The [UsedTypeConverter], if one has been set on this column.
|
||||
final UsedTypeConverter typeConverter;
|
||||
|
@ -142,14 +149,7 @@ class SpecifiedColumn {
|
|||
|
||||
/// The class inside the moor library that represents the same sql type as
|
||||
/// this column.
|
||||
String get sqlTypeName => const {
|
||||
ColumnType.boolean: 'BoolType',
|
||||
ColumnType.text: 'StringType',
|
||||
ColumnType.integer: 'IntType',
|
||||
ColumnType.datetime: 'DateTimeType',
|
||||
ColumnType.blob: 'BlobType',
|
||||
ColumnType.real: 'RealType',
|
||||
}[type];
|
||||
String get sqlTypeName => sqlTypes[type];
|
||||
|
||||
const SpecifiedColumn({
|
||||
this.type,
|
||||
|
|
|
@ -48,13 +48,23 @@ class SpecifiedTable {
|
|||
/// not been defined that way.
|
||||
final Set<SpecifiedColumn> primaryKey;
|
||||
|
||||
/// When non-null, the generated table class will override the `withoutRowId`
|
||||
/// getter on the table class with this value.
|
||||
final bool overrideWithoutRowId;
|
||||
|
||||
/// When non-null, the generated table class will override the
|
||||
/// `customConstraints` getter in the table class with this value.
|
||||
final List<String> overrideTableConstraints;
|
||||
|
||||
const SpecifiedTable(
|
||||
{this.fromClass,
|
||||
this.columns,
|
||||
this.sqlName,
|
||||
this.dartTypeName,
|
||||
this.primaryKey,
|
||||
String overriddenName})
|
||||
String overriddenName,
|
||||
this.overrideWithoutRowId,
|
||||
this.overrideTableConstraints})
|
||||
: _overriddenName = overriddenName;
|
||||
|
||||
/// Finds all type converters used in this tables.
|
||||
|
|
|
@ -199,7 +199,7 @@ class ColumnParser extends ParserBase {
|
|||
customConstraints: foundCustomConstraint,
|
||||
nullable: nullable,
|
||||
features: foundFeatures,
|
||||
defaultArgument: foundDefaultExpression,
|
||||
defaultArgument: foundDefaultExpression?.toSource(),
|
||||
typeConverter: converter);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:moor_generator/src/model/specified_column.dart';
|
|||
import 'package:moor_generator/src/model/specified_table.dart';
|
||||
import 'package:moor_generator/src/parser/sql/type_mapping.dart';
|
||||
import 'package:moor_generator/src/utils/names.dart';
|
||||
import 'package:moor_generator/src/utils/string_escaper.dart';
|
||||
import 'package:recase/recase.dart';
|
||||
import 'package:sqlparser/sqlparser.dart';
|
||||
|
||||
|
@ -45,6 +46,8 @@ class CreateTable {
|
|||
final sqlName = column.name;
|
||||
final dartName = ReCase(sqlName).camelCase;
|
||||
final constraintWriter = StringBuffer();
|
||||
final moorType = mapper.resolvedToMoor(column.type);
|
||||
String defaultValue;
|
||||
|
||||
for (var constraint in column.constraints) {
|
||||
if (constraint is PrimaryKeyColumn) {
|
||||
|
@ -53,6 +56,13 @@ class CreateTable {
|
|||
features.add(AutoIncrement());
|
||||
}
|
||||
}
|
||||
if (constraint is Default) {
|
||||
final dartType = dartTypeNames[moorType];
|
||||
final sqlType = sqlTypes[moorType];
|
||||
final expressionName = 'const CustomExpression<$dartType, $sqlType>';
|
||||
final sqlDefault = constraint.expression.span.text;
|
||||
defaultValue = '$expressionName(${asDartLiteral(sqlDefault)})';
|
||||
}
|
||||
|
||||
if (constraintWriter.isNotEmpty) {
|
||||
constraintWriter.write(' ');
|
||||
|
@ -61,13 +71,14 @@ class CreateTable {
|
|||
}
|
||||
|
||||
final parsed = SpecifiedColumn(
|
||||
type: mapper.resolvedToMoor(column.type),
|
||||
type: moorType,
|
||||
nullable: column.type.nullable,
|
||||
dartGetterName: dartName,
|
||||
name: ColumnName.implicitly(sqlName),
|
||||
declaredAsPrimaryKey: isPrimaryKey,
|
||||
features: features,
|
||||
customConstraints: constraintWriter.toString(),
|
||||
defaultArgument: defaultValue,
|
||||
);
|
||||
|
||||
foundColumns[column.name] = parsed;
|
||||
|
@ -79,7 +90,8 @@ class CreateTable {
|
|||
final tableName = table.name;
|
||||
final dartTableName = ReCase(tableName).pascalCase;
|
||||
|
||||
// todo include WITHOUT ROWID clause and table constraints
|
||||
final constraints = table.tableConstraints.map((c) => c.span.text).toList();
|
||||
|
||||
return SpecifiedTable(
|
||||
fromClass: null,
|
||||
columns: foundColumns.values.toList(),
|
||||
|
@ -87,6 +99,8 @@ class CreateTable {
|
|||
dartTypeName: dataClassNameForClassName(dartTableName),
|
||||
overriddenName: ReCase(tableName).pascalCase,
|
||||
primaryKey: primaryKey,
|
||||
overrideWithoutRowId: table.withoutRowId ? true : null,
|
||||
overrideTableConstraints: constraints.isNotEmpty ? constraints : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ class UseDaoParser {
|
|||
Future<SpecifiedDao> parseDao(
|
||||
ClassElement element, ConstantReader annotation) async {
|
||||
final tableTypes =
|
||||
annotation.peek('tables').listValue.map((obj) => obj.toTypeValue());
|
||||
annotation.peek('tables')?.listValue?.map((obj) => obj.toTypeValue()) ??
|
||||
[];
|
||||
final queryStrings = annotation.peek('queries')?.mapValue ?? {};
|
||||
|
||||
final includes = annotation
|
||||
|
|
|
@ -15,7 +15,8 @@ class UseMoorParser {
|
|||
ClassElement element, ConstantReader annotation) async {
|
||||
// the types declared in UseMoor.tables
|
||||
final tableTypes =
|
||||
annotation.peek('tables').listValue.map((obj) => obj.toTypeValue());
|
||||
annotation.peek('tables')?.listValue?.map((obj) => obj.toTypeValue()) ??
|
||||
[];
|
||||
final queryStrings = annotation.peek('queries')?.mapValue ?? {};
|
||||
final includes = annotation
|
||||
.read('include')
|
||||
|
|
|
@ -63,6 +63,7 @@ class TableWriter {
|
|||
_writeAliasGenerator(buffer);
|
||||
|
||||
_writeConvertersAsStaticFields(buffer);
|
||||
_overrideFieldsIfNeeded(buffer);
|
||||
|
||||
// close class
|
||||
buffer.write('}');
|
||||
|
@ -148,7 +149,7 @@ class TableWriter {
|
|||
}
|
||||
|
||||
if (column.defaultArgument != null) {
|
||||
additionalParams['defaultValue'] = column.defaultArgument.toSource();
|
||||
additionalParams['defaultValue'] = column.defaultArgument;
|
||||
}
|
||||
|
||||
expressionBuffer
|
||||
|
@ -259,4 +260,20 @@ class TableWriter {
|
|||
..write('return $typeName(_db, alias);')
|
||||
..write('}');
|
||||
}
|
||||
|
||||
void _overrideFieldsIfNeeded(StringBuffer buffer) {
|
||||
if (table.overrideWithoutRowId != null) {
|
||||
final value = table.overrideWithoutRowId ? 'true' : 'false';
|
||||
buffer..write('@override\n')..write('final bool withoutRowId = $value;');
|
||||
}
|
||||
|
||||
if (table.overrideTableConstraints != null) {
|
||||
final value =
|
||||
table.overrideTableConstraints.map(asDartLiteral).join(', ');
|
||||
|
||||
buffer
|
||||
..write('@override\n')
|
||||
..write('final List<String> customConstraints = const [$value];');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
part of 'parser.dart';
|
||||
|
||||
const _tokensInTypename = [
|
||||
TokenType.identifier,
|
||||
TokenType.leftParen,
|
||||
TokenType.rightParen,
|
||||
TokenType.numberLiteral,
|
||||
];
|
||||
|
||||
mixin SchemaParser on ParserBase {
|
||||
CreateTableStatement _createTable() {
|
||||
if (!_matchOne(TokenType.create)) return null;
|
||||
|
@ -70,14 +63,7 @@ mixin SchemaParser on ParserBase {
|
|||
final name = _consume(TokenType.identifier, 'Expected a column name')
|
||||
as IdentifierToken;
|
||||
|
||||
final typeNameBuilder = StringBuffer();
|
||||
while (_match(_tokensInTypename)) {
|
||||
typeNameBuilder.write(_previous.lexeme);
|
||||
}
|
||||
|
||||
final typeName =
|
||||
typeNameBuilder.isEmpty ? null : typeNameBuilder.toString();
|
||||
|
||||
final typeName = _typeName();
|
||||
final constraints = <ColumnConstraint>[];
|
||||
ColumnConstraint constraint;
|
||||
while ((constraint = _columnConstraint(orNull: true)) != null) {
|
||||
|
@ -91,6 +77,33 @@ mixin SchemaParser on ParserBase {
|
|||
)..setSpan(name, _previous);
|
||||
}
|
||||
|
||||
String _typeName() {
|
||||
// sqlite doesn't really define what a type name is and has very loose rules
|
||||
// at turning them into a type affinity. We support this pattern:
|
||||
// typename = identifier [ "(" { identifier | comma | number_literal } ")" ]
|
||||
if (!_matchOne(TokenType.identifier)) return null;
|
||||
|
||||
final typeNameBuilder = StringBuffer(_previous.lexeme);
|
||||
|
||||
if (_matchOne(TokenType.leftParen)) {
|
||||
typeNameBuilder.write('(');
|
||||
|
||||
const inBrackets = [
|
||||
TokenType.identifier,
|
||||
TokenType.comma,
|
||||
TokenType.numberLiteral
|
||||
];
|
||||
while (_match(inBrackets)) {
|
||||
typeNameBuilder..write(' ')..write(_previous.lexeme);
|
||||
}
|
||||
|
||||
_consume(TokenType.rightParen,
|
||||
'Expected closing paranthesis to finish type name');
|
||||
}
|
||||
|
||||
return typeNameBuilder.toString();
|
||||
}
|
||||
|
||||
ColumnConstraint _columnConstraint({bool orNull = false}) {
|
||||
final first = _peek;
|
||||
|
||||
|
@ -127,7 +140,7 @@ mixin SchemaParser on ParserBase {
|
|||
// when not a literal, expect an expression in parentheses
|
||||
expr ??= _expressionInParentheses();
|
||||
|
||||
return Default(resolvedName, expr);
|
||||
return Default(resolvedName, expr)..setSpan(first, _previous);
|
||||
}
|
||||
if (_matchOne(TokenType.collate)) {
|
||||
final collation = _consumeIdentifier('Expected the collation name');
|
||||
|
|
|
@ -1,103 +1,118 @@
|
|||
import 'package:sqlparser/sqlparser.dart';
|
||||
import 'package:sqlparser/src/ast/ast.dart';
|
||||
import 'package:test_core/test_core.dart';
|
||||
|
||||
import '../common_data.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
testStatement(
|
||||
createTableStmt,
|
||||
CreateTableStatement(
|
||||
tableName: 'users',
|
||||
ifNotExists: true,
|
||||
withoutRowId: false,
|
||||
columns: [
|
||||
ColumnDefinition(
|
||||
columnName: 'id',
|
||||
typeName: 'INT',
|
||||
constraints: [
|
||||
NotNull(null),
|
||||
PrimaryKeyColumn(
|
||||
null,
|
||||
autoIncrement: true,
|
||||
onConflict: ConflictClause.rollback,
|
||||
mode: OrderingMode.descending,
|
||||
),
|
||||
],
|
||||
),
|
||||
ColumnDefinition(
|
||||
columnName: 'email',
|
||||
typeName: 'VARCHAR',
|
||||
constraints: [
|
||||
NotNull(null),
|
||||
UniqueColumn(null, ConflictClause.abort),
|
||||
],
|
||||
),
|
||||
ColumnDefinition(
|
||||
columnName: 'score',
|
||||
typeName: 'INT',
|
||||
constraints: [
|
||||
NotNull('score set'),
|
||||
Default(null, NumericLiteral(420, token(TokenType.numberLiteral))),
|
||||
CheckColumn(
|
||||
null,
|
||||
BinaryExpression(
|
||||
Reference(columnName: 'score'),
|
||||
token(TokenType.more),
|
||||
NumericLiteral(
|
||||
0,
|
||||
token(TokenType.numberLiteral),
|
||||
test('parsers simple create table statements', () {
|
||||
testStatement(
|
||||
'CREATE TABLE my_tbl (a INT, b TEXT)',
|
||||
CreateTableStatement(tableName: 'my_tbl', columns: [
|
||||
ColumnDefinition(columnName: 'a', typeName: 'INT'),
|
||||
ColumnDefinition(columnName: 'b', typeName: 'TEXT'),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('parses complex CREATE TABLE statements', () {
|
||||
testStatement(
|
||||
createTableStmt,
|
||||
CreateTableStatement(
|
||||
tableName: 'users',
|
||||
ifNotExists: true,
|
||||
withoutRowId: false,
|
||||
columns: [
|
||||
ColumnDefinition(
|
||||
columnName: 'id',
|
||||
typeName: 'INT',
|
||||
constraints: [
|
||||
NotNull(null),
|
||||
PrimaryKeyColumn(
|
||||
null,
|
||||
autoIncrement: true,
|
||||
onConflict: ConflictClause.rollback,
|
||||
mode: OrderingMode.descending,
|
||||
),
|
||||
],
|
||||
),
|
||||
ColumnDefinition(
|
||||
columnName: 'email',
|
||||
typeName: 'VARCHAR',
|
||||
constraints: [
|
||||
NotNull(null),
|
||||
UniqueColumn(null, ConflictClause.abort),
|
||||
],
|
||||
),
|
||||
ColumnDefinition(
|
||||
columnName: 'score',
|
||||
typeName: 'INT',
|
||||
constraints: [
|
||||
NotNull('score set'),
|
||||
Default(
|
||||
null, NumericLiteral(420, token(TokenType.numberLiteral))),
|
||||
CheckColumn(
|
||||
null,
|
||||
BinaryExpression(
|
||||
Reference(columnName: 'score'),
|
||||
token(TokenType.more),
|
||||
NumericLiteral(
|
||||
0,
|
||||
token(TokenType.numberLiteral),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
ColumnDefinition(
|
||||
columnName: 'display_name',
|
||||
typeName: 'VARCHAR',
|
||||
constraints: [
|
||||
CollateConstraint(
|
||||
null,
|
||||
'BINARY',
|
||||
),
|
||||
ForeignKeyColumnConstraint(
|
||||
null,
|
||||
ForeignKeyClause(
|
||||
foreignTable: TableReference('some', null),
|
||||
columnNames: [Reference(columnName: 'thing')],
|
||||
onUpdate: ReferenceAction.cascade,
|
||||
onDelete: ReferenceAction.setNull,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
tableConstraints: [
|
||||
KeyClause(
|
||||
null,
|
||||
isPrimaryKey: false,
|
||||
indexedColumns: [
|
||||
Reference(columnName: 'score'),
|
||||
Reference(columnName: 'display_name'),
|
||||
],
|
||||
onConflict: ConflictClause.abort,
|
||||
),
|
||||
ForeignKeyTableConstraint(
|
||||
null,
|
||||
columns: [
|
||||
Reference(columnName: 'id'),
|
||||
Reference(columnName: 'email'),
|
||||
],
|
||||
clause: ForeignKeyClause(
|
||||
foreignTable: TableReference('another', null),
|
||||
columnNames: [
|
||||
Reference(columnName: 'a'),
|
||||
Reference(columnName: 'b'),
|
||||
],
|
||||
onDelete: ReferenceAction.noAction,
|
||||
onUpdate: ReferenceAction.restrict,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
ColumnDefinition(
|
||||
columnName: 'display_name',
|
||||
typeName: 'VARCHAR',
|
||||
constraints: [
|
||||
CollateConstraint(
|
||||
null,
|
||||
'BINARY',
|
||||
),
|
||||
ForeignKeyColumnConstraint(
|
||||
null,
|
||||
ForeignKeyClause(
|
||||
foreignTable: TableReference('some', null),
|
||||
columnNames: [Reference(columnName: 'thing')],
|
||||
onUpdate: ReferenceAction.cascade,
|
||||
onDelete: ReferenceAction.setNull,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
tableConstraints: [
|
||||
KeyClause(
|
||||
null,
|
||||
isPrimaryKey: false,
|
||||
indexedColumns: [
|
||||
Reference(columnName: 'score'),
|
||||
Reference(columnName: 'display_name'),
|
||||
],
|
||||
onConflict: ConflictClause.abort,
|
||||
),
|
||||
ForeignKeyTableConstraint(
|
||||
null,
|
||||
columns: [
|
||||
Reference(columnName: 'id'),
|
||||
Reference(columnName: 'email'),
|
||||
],
|
||||
clause: ForeignKeyClause(
|
||||
foreignTable: TableReference('another', null),
|
||||
columnNames: [
|
||||
Reference(columnName: 'a'),
|
||||
Reference(columnName: 'b'),
|
||||
],
|
||||
onDelete: ReferenceAction.noAction,
|
||||
onUpdate: ReferenceAction.restrict,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue