mirror of https://github.com/AMT-Cheif/drift.git
Add integration test for existing types in drift
This commit is contained in:
parent
a463ee14cb
commit
a3fea1af04
|
@ -1853,6 +1853,33 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
|||
});
|
||||
}
|
||||
|
||||
Selectable<MyCustomResultClass> customResult() {
|
||||
return customSelect(
|
||||
'SELECT with_constraints.b, config.sync_state,"config"."config_key" AS "nested_0.config_key", "config"."config_value" AS "nested_0.config_value", "config"."sync_state" AS "nested_0.sync_state", "config"."sync_state_implicit" AS "nested_0.sync_state_implicit","no_ids"."payload" AS "nested_1.payload" FROM with_constraints INNER JOIN config ON config_key = with_constraints.a CROSS JOIN no_ids',
|
||||
variables: [],
|
||||
readsFrom: {
|
||||
withConstraints,
|
||||
config,
|
||||
noIds,
|
||||
}).asyncMap((QueryRow row) async => MyCustomResultClass(
|
||||
row.read<int>('b'),
|
||||
syncState: NullAwareTypeConverter.wrapFromSql(
|
||||
ConfigTable.$convertersyncState,
|
||||
row.readNullable<int>('sync_state')),
|
||||
config: await config.mapFromRow(row, tablePrefix: 'nested_0'),
|
||||
noIds: await noIds.mapFromRow(row, tablePrefix: 'nested_1'),
|
||||
nested: await customSelect('SELECT * FROM no_ids',
|
||||
variables: [],
|
||||
readsFrom: {
|
||||
noIds,
|
||||
})
|
||||
.map((QueryRow row) => Buffer(
|
||||
row.read<Uint8List>('payload'),
|
||||
))
|
||||
.get(),
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
|
|
|
@ -1,5 +1,41 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'converter.dart';
|
||||
import 'custom_tables.dart';
|
||||
|
||||
class NoIdRow {
|
||||
final List<int> payload;
|
||||
|
||||
NoIdRow(this.payload);
|
||||
}
|
||||
|
||||
class Buffer {
|
||||
Buffer(TypedData payload);
|
||||
}
|
||||
|
||||
/// The existing result class for the `customResult` query in `tables.drift`
|
||||
class MyCustomResultClass {
|
||||
// with_constraints.b
|
||||
final int b;
|
||||
|
||||
// config.sync_state
|
||||
final SyncType? syncState;
|
||||
|
||||
// config.** (drift-generated table row class)
|
||||
final Config config;
|
||||
|
||||
// no_ids.** (custom table row class)
|
||||
final NoIdRow noIds;
|
||||
|
||||
// LIST(SELECT * FROM no_ids). Note that we're replacing the custom table
|
||||
// row class with a custom structure class just for this query.
|
||||
final List<Buffer> nested;
|
||||
|
||||
MyCustomResultClass(
|
||||
this.b, {
|
||||
required this.syncState,
|
||||
required this.config,
|
||||
required this.noIds,
|
||||
required this.nested,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -98,3 +98,14 @@ addConfig: INSERT INTO config $value RETURNING *;
|
|||
nested: SELECT defaults.**, LIST(SELECT * FROM with_constraints c WHERE c.b = defaults.b)
|
||||
FROM with_defaults defaults
|
||||
WHERE a = ?;
|
||||
|
||||
customResult WITH MyCustomResultClass:
|
||||
SELECT
|
||||
with_constraints.b,
|
||||
config.sync_state,
|
||||
config.**,
|
||||
no_ids.**,
|
||||
LIST(SELECT * FROM no_ids) AS nested
|
||||
FROM with_constraints
|
||||
INNER JOIN config ON config_key = with_constraints.a
|
||||
CROSS JOIN no_ids;
|
||||
|
|
|
@ -172,4 +172,13 @@ void main() {
|
|||
);
|
||||
});
|
||||
}, skip: ifOlderThanSqlite335(sqlite3Version));
|
||||
|
||||
test('can run query with custom result set', () async {
|
||||
await db.withConstraints
|
||||
.insertOne(WithConstraintsCompanion.insert(b: 1, a: Value('key')));
|
||||
await db.noIds.insertOne(NoIdsCompanion.insert(payload: Uint8List(512)));
|
||||
|
||||
final result = await db.customResult().get();
|
||||
print('result');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -100,7 +100,8 @@ class FileAnalyzer {
|
|||
references: element.references,
|
||||
requiredVariables: options.variables);
|
||||
|
||||
result.resolvedQueries[element.id] = analyzer.analyze(element)
|
||||
result.resolvedQueries[element.id] = analyzer.analyze(element,
|
||||
sourceForCustomName: stmt.as)
|
||||
..declaredInDriftFile = true;
|
||||
|
||||
for (final error in analyzer.lints) {
|
||||
|
|
|
@ -25,6 +25,8 @@ class _QueryHandlerContext {
|
|||
final String? requestedResultClass;
|
||||
final DartType? requestedResultType;
|
||||
|
||||
final DriftTableName? sourceForFixedName;
|
||||
|
||||
_QueryHandlerContext({
|
||||
required List<FoundElement> foundElements,
|
||||
required this.root,
|
||||
|
@ -32,6 +34,7 @@ class _QueryHandlerContext {
|
|||
required this.nestedScope,
|
||||
this.requestedResultClass,
|
||||
this.requestedResultType,
|
||||
this.sourceForFixedName,
|
||||
}) : foundElements = List.unmodifiable(foundElements);
|
||||
}
|
||||
|
||||
|
@ -72,7 +75,18 @@ class QueryAnalyzer {
|
|||
return referencesByName[name.toLowerCase()] as E;
|
||||
}
|
||||
|
||||
SqlQuery analyze(DriftQueryDeclaration declaration) {
|
||||
/// Analyzes the query from its [declaration].
|
||||
///
|
||||
/// This runs drfit-specific query analysis and lints on the query. It will
|
||||
/// also detect read or written tables and a suitable result set for this
|
||||
/// query in Dart.
|
||||
///
|
||||
/// The [sourceForCustomName] can be set to the syntactic source responsible
|
||||
/// for a [DefinedSqlQuery.existingDartType] or[DefinedSqlQuery.resultClassName],
|
||||
/// respectively. It will improve the highlighted source span in error
|
||||
/// messages.
|
||||
SqlQuery analyze(DriftQueryDeclaration declaration,
|
||||
{DriftTableName? sourceForCustomName}) {
|
||||
final nestedAnalyzer = NestedQueryAnalyzer();
|
||||
NestedQueriesContainer? nestedScope;
|
||||
|
||||
|
@ -102,6 +116,7 @@ class QueryAnalyzer {
|
|||
requestedResultType: requestedResultType,
|
||||
root: context.root,
|
||||
nestedScope: nestedScope,
|
||||
sourceForFixedName: sourceForCustomName,
|
||||
));
|
||||
|
||||
final linter = DriftSqlLinter(
|
||||
|
@ -349,7 +364,7 @@ class QueryAnalyzer {
|
|||
lints.add(AnalysisError(
|
||||
type: AnalysisErrorType.other,
|
||||
message: message,
|
||||
relevantNode: queryContext.root,
|
||||
relevantNode: queryContext.sourceForFixedName ?? queryContext.root,
|
||||
));
|
||||
});
|
||||
|
||||
|
|
|
@ -424,7 +424,7 @@ bool checkType(
|
|||
if (typeConverter != null) {
|
||||
expectedDartType = typeConverter.dartType;
|
||||
if (typeConverter.canBeSkippedForNulls && columnIsNullable) {
|
||||
typeToCheck = typeSystem.promoteToNonNull(typeToCheck);
|
||||
expectedDartType = typeProvider.makeNullable(expectedDartType);
|
||||
}
|
||||
} else {
|
||||
expectedDartType = typeProvider.typeFor(columnType, knownTypes);
|
||||
|
@ -503,7 +503,7 @@ extension CreateRecordType on TypeProvider {
|
|||
if (type is InterfaceType) {
|
||||
return type.element.instantiate(
|
||||
typeArguments: type.typeArguments,
|
||||
nullabilitySuffix: NullabilitySuffix.none,
|
||||
nullabilitySuffix: NullabilitySuffix.question,
|
||||
);
|
||||
} else if (type is NeverType) {
|
||||
return nullType;
|
||||
|
|
Loading…
Reference in New Issue