mirror of https://github.com/AMT-Cheif/drift.git
Respect tables in the body of a CREATE TRIGGER statement
This commit is contained in:
parent
4c68b31564
commit
3ee05bf647
|
@ -174,139 +174,6 @@ class ConfigTable extends Table with TableInfo<ConfigTable, Config> {
|
||||||
bool get dontWriteConstraints => true;
|
bool get dontWriteConstraints => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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}) {
|
|
||||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
|
||||||
return NoId(
|
|
||||||
payload: serializer.fromJson<Uint8List>(json['payload']),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
factory NoId.fromJsonString(String encodedJson,
|
|
||||||
{ValueSerializer serializer}) =>
|
|
||||||
NoId.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
|
||||||
serializer: serializer);
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
|
||||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
|
||||||
return <String, dynamic>{
|
|
||||||
'payload': serializer.toJson<Uint8List>(payload),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
NoIdsCompanion createCompanion(bool nullToAbsent) {
|
|
||||||
return NoIdsCompanion(
|
|
||||||
payload: payload == null && nullToAbsent
|
|
||||||
? const Value.absent()
|
|
||||||
: Value(payload),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ==(dynamic other) =>
|
|
||||||
identical(this, other) ||
|
|
||||||
(other is NoId && other.payload == this.payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
class NoIdsCompanion extends UpdateCompanion<NoId> {
|
|
||||||
final Value<Uint8List> payload;
|
|
||||||
const NoIdsCompanion({
|
|
||||||
this.payload = const Value.absent(),
|
|
||||||
});
|
|
||||||
NoIdsCompanion.insert({
|
|
||||||
@required Uint8List payload,
|
|
||||||
}) : payload = Value(payload);
|
|
||||||
NoIdsCompanion copyWith({Value<Uint8List> payload}) {
|
|
||||||
return NoIdsCompanion(
|
|
||||||
payload: payload ?? this.payload,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 PRIMARY KEY');
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 (isInserting) {
|
|
||||||
context.missing(_payloadMeta);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<GeneratedColumn> get $primaryKey => {payload};
|
|
||||||
@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
|
|
||||||
bool get withoutRowId => true;
|
|
||||||
@override
|
|
||||||
bool get dontWriteConstraints => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class WithDefault extends DataClass implements Insertable<WithDefault> {
|
class WithDefault extends DataClass implements Insertable<WithDefault> {
|
||||||
final String a;
|
final String a;
|
||||||
final int b;
|
final int b;
|
||||||
|
@ -463,6 +330,139 @@ class WithDefaults extends Table with TableInfo<WithDefaults, WithDefault> {
|
||||||
bool get dontWriteConstraints => true;
|
bool get dontWriteConstraints => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}) {
|
||||||
|
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||||
|
return NoId(
|
||||||
|
payload: serializer.fromJson<Uint8List>(json['payload']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
factory NoId.fromJsonString(String encodedJson,
|
||||||
|
{ValueSerializer serializer}) =>
|
||||||
|
NoId.fromJson(DataClass.parseJson(encodedJson) as Map<String, dynamic>,
|
||||||
|
serializer: serializer);
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({ValueSerializer serializer}) {
|
||||||
|
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'payload': serializer.toJson<Uint8List>(payload),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
NoIdsCompanion createCompanion(bool nullToAbsent) {
|
||||||
|
return NoIdsCompanion(
|
||||||
|
payload: payload == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(payload),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ==(dynamic other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is NoId && other.payload == this.payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoIdsCompanion extends UpdateCompanion<NoId> {
|
||||||
|
final Value<Uint8List> payload;
|
||||||
|
const NoIdsCompanion({
|
||||||
|
this.payload = const Value.absent(),
|
||||||
|
});
|
||||||
|
NoIdsCompanion.insert({
|
||||||
|
@required Uint8List payload,
|
||||||
|
}) : payload = Value(payload);
|
||||||
|
NoIdsCompanion copyWith({Value<Uint8List> payload}) {
|
||||||
|
return NoIdsCompanion(
|
||||||
|
payload: payload ?? this.payload,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 PRIMARY KEY');
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (isInserting) {
|
||||||
|
context.missing(_payloadMeta);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<GeneratedColumn> get $primaryKey => {payload};
|
||||||
|
@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
|
||||||
|
bool get withoutRowId => true;
|
||||||
|
@override
|
||||||
|
bool get dontWriteConstraints => true;
|
||||||
|
}
|
||||||
|
|
||||||
class WithConstraint extends DataClass implements Insertable<WithConstraint> {
|
class WithConstraint extends DataClass implements Insertable<WithConstraint> {
|
||||||
final String a;
|
final String a;
|
||||||
final int b;
|
final int b;
|
||||||
|
@ -1089,10 +1089,10 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
_$CustomTablesDb.connect(DatabaseConnection c) : super.connect(c);
|
_$CustomTablesDb.connect(DatabaseConnection c) : super.connect(c);
|
||||||
ConfigTable _config;
|
ConfigTable _config;
|
||||||
ConfigTable get config => _config ??= ConfigTable(this);
|
ConfigTable get config => _config ??= ConfigTable(this);
|
||||||
NoIds _noIds;
|
|
||||||
NoIds get noIds => _noIds ??= NoIds(this);
|
|
||||||
WithDefaults _withDefaults;
|
WithDefaults _withDefaults;
|
||||||
WithDefaults get withDefaults => _withDefaults ??= WithDefaults(this);
|
WithDefaults get withDefaults => _withDefaults ??= WithDefaults(this);
|
||||||
|
NoIds _noIds;
|
||||||
|
NoIds get noIds => _noIds ??= NoIds(this);
|
||||||
WithConstraints _withConstraints;
|
WithConstraints _withConstraints;
|
||||||
WithConstraints get withConstraints =>
|
WithConstraints get withConstraints =>
|
||||||
_withConstraints ??= WithConstraints(this);
|
_withConstraints ??= WithConstraints(this);
|
||||||
|
@ -1214,11 +1214,11 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities => [
|
List<DatabaseSchemaEntity> get allSchemaEntities => [
|
||||||
config,
|
config,
|
||||||
|
withDefaults,
|
||||||
Trigger(
|
Trigger(
|
||||||
'CREATE TRIGGER my_trigger AFTER INSERT ON config BEGIN\n INSERT INTO with_defaults VALUES (new.config_key, LENGTH(new.config_value));\nEND;',
|
'CREATE TRIGGER my_trigger AFTER INSERT ON config BEGIN\n INSERT INTO with_defaults VALUES (new.config_key, LENGTH(new.config_value));\nEND;',
|
||||||
'my_trigger'),
|
'my_trigger'),
|
||||||
noIds,
|
noIds,
|
||||||
withDefaults,
|
|
||||||
withConstraints,
|
withConstraints,
|
||||||
mytable,
|
mytable,
|
||||||
email
|
email
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
- Support explicit type arguments for queries in moor files. In
|
- Support explicit type arguments for queries in moor files. In
|
||||||
`foo(:bar AS TEXT, :baz AS INT): SELECT :bar, :baz;`, the column type can now be inferred.
|
`foo(:bar AS TEXT, :baz AS INT): SELECT :bar, :baz;`, the column type can now be inferred.
|
||||||
Previously, the query would fail because of an unknown type.
|
Previously, the query would fail because of an unknown type.
|
||||||
|
- Support `CREATE TRIGGER` statements in moor files
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:moor_generator/moor_generator.dart';
|
||||||
import 'package:moor_generator/src/analyzer/errors.dart';
|
import 'package:moor_generator/src/analyzer/errors.dart';
|
||||||
import 'package:moor_generator/src/analyzer/runner/results.dart';
|
import 'package:moor_generator/src/analyzer/runner/results.dart';
|
||||||
import 'package:moor_generator/src/analyzer/runner/steps.dart';
|
import 'package:moor_generator/src/analyzer/runner/steps.dart';
|
||||||
|
import 'package:moor_generator/src/analyzer/sql_queries/affected_tables_visitor.dart';
|
||||||
import 'package:moor_generator/src/analyzer/sql_queries/lints/linter.dart';
|
import 'package:moor_generator/src/analyzer/sql_queries/lints/linter.dart';
|
||||||
import 'package:moor_generator/src/analyzer/sql_queries/query_analyzer.dart';
|
import 'package:moor_generator/src/analyzer/sql_queries/query_analyzer.dart';
|
||||||
import 'package:sqlparser/sqlparser.dart';
|
import 'package:sqlparser/sqlparser.dart';
|
||||||
|
@ -33,6 +34,7 @@ class EntityHandler extends BaseAnalyzer {
|
||||||
|
|
||||||
for (final trigger in file.declaredEntities.whereType<MoorTrigger>()) {
|
for (final trigger in file.declaredEntities.whereType<MoorTrigger>()) {
|
||||||
trigger.on = null;
|
trigger.on = null;
|
||||||
|
trigger.bodyReferences.clear();
|
||||||
|
|
||||||
final declaration = trigger.declaration as MoorTriggerDeclaration;
|
final declaration = trigger.declaration as MoorTriggerDeclaration;
|
||||||
final node = declaration.node;
|
final node = declaration.node;
|
||||||
|
@ -46,6 +48,12 @@ class EntityHandler extends BaseAnalyzer {
|
||||||
final linter = Linter(context, mapper);
|
final linter = Linter(context, mapper);
|
||||||
linter.reportLints();
|
linter.reportLints();
|
||||||
reportLints(linter.lints, name: trigger.displayName);
|
reportLints(linter.lints, name: trigger.displayName);
|
||||||
|
|
||||||
|
// find additional tables that might be referenced in the body
|
||||||
|
final tablesFinder = ReferencedTablesVisitor();
|
||||||
|
node.action.acceptWithoutArg(tablesFinder);
|
||||||
|
final tablesFromBody = tablesFinder.foundTables.map(mapper.tableToMoor);
|
||||||
|
trigger.bodyReferences.addAll(tablesFromBody);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ class MoorTrigger implements MoorSchemaEntity {
|
||||||
///
|
///
|
||||||
/// This field can be null in case the table wasn't resolved.
|
/// This field can be null in case the table wasn't resolved.
|
||||||
MoorTable on;
|
MoorTable on;
|
||||||
|
List<MoorTable> bodyReferences = [];
|
||||||
|
|
||||||
String _create;
|
String _create;
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ class MoorTrigger implements MoorSchemaEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Iterable<MoorSchemaEntity> get references => [on];
|
Iterable<MoorSchemaEntity> get references => {on, ...bodyReferences};
|
||||||
|
|
||||||
/// The `CREATE TRIGGER` statement that can be used to create this trigger.
|
/// The `CREATE TRIGGER` statement that can be used to create this trigger.
|
||||||
String get create {
|
String get create {
|
||||||
|
|
|
@ -38,7 +38,7 @@ CREATE TABLE friendships (
|
||||||
table.references,
|
table.references,
|
||||||
[
|
[
|
||||||
const TypeMatcher<MoorTable>()
|
const TypeMatcher<MoorTable>()
|
||||||
.having((table) => table.displayName, 'displayName', 'users')
|
.having((table) => table.displayName, 'displayName', 'users'),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -48,8 +48,16 @@ CREATE TABLE friendships (
|
||||||
'foo|lib/a.moor': '''
|
'foo|lib/a.moor': '''
|
||||||
import 'b.moor';
|
import 'b.moor';
|
||||||
|
|
||||||
|
CREATE TABLE friendships (
|
||||||
|
user_a INTEGER REFERENCES users (id),
|
||||||
|
user_b INTEGER REFERENCES users (id),
|
||||||
|
|
||||||
|
PRIMARY KEY(user_a, user_b),
|
||||||
|
CHECK (user_a != user_b)
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TRIGGER my_trigger AFTER DELETE ON users BEGIN
|
CREATE TRIGGER my_trigger AFTER DELETE ON users BEGIN
|
||||||
SELECT * FROM users;
|
DELETE FROM friendships WHERE user_a = old.id OR user_b = old.id;
|
||||||
END;
|
END;
|
||||||
''',
|
''',
|
||||||
...definitions,
|
...definitions,
|
||||||
|
@ -58,13 +66,16 @@ END;
|
||||||
final file = await state.analyze('package:foo/a.moor');
|
final file = await state.analyze('package:foo/a.moor');
|
||||||
expect(file.errors.errors, isEmpty);
|
expect(file.errors.errors, isEmpty);
|
||||||
|
|
||||||
final trigger = file.currentResult.declaredEntities.single;
|
final trigger =
|
||||||
|
file.currentResult.declaredEntities.whereType<MoorTrigger>().single;
|
||||||
expect(
|
expect(
|
||||||
trigger.references,
|
trigger.references,
|
||||||
[
|
{
|
||||||
|
const TypeMatcher<MoorTable>().having(
|
||||||
|
(table) => table.displayName, 'displayName', 'friendships'),
|
||||||
const TypeMatcher<MoorTable>()
|
const TypeMatcher<MoorTable>()
|
||||||
.having((table) => table.displayName, 'displayName', 'users')
|
.having((table) => table.displayName, 'displayName', 'users'),
|
||||||
],
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue