Skip to content

Commit

Permalink
verify SQL transformer behavior #429
Browse files Browse the repository at this point in the history
  • Loading branch information
tshedor committed Aug 30, 2024
1 parent e7f6859 commit 0edeabe
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 16 deletions.
34 changes: 34 additions & 0 deletions packages/brick_sqlite/test/query_sql_transformer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,40 @@ void main() {
expect(statement, sqliteQuery.statement);
sqliteStatementExpectation(statement);
});

// This behavior is not explicitly supported - field names should be used.
// This is considered functionality behavior and is not guaranteed in
// future Brick releases.
// https://github.com/GetDutchie/brick/issues/429
test('incorrectly cased columns are forwarded as is', () async {
final statement =
'SELECT DISTINCT `DemoModel`.* FROM `DemoModel` ORDER BY complex_field_name DESC';
final sqliteQuery = QuerySqlTransformer<DemoModel>(
modelDictionary: dictionary,
query: Query(providerArgs: {'orderBy': 'complex_field_name DESC'}),
);
await db.rawQuery(sqliteQuery.statement, sqliteQuery.values);

expect(statement, sqliteQuery.statement);
sqliteStatementExpectation(statement);
});

// This behavior is not explicitly supported because table names are autogenerated
// and not configurable. This is considered functionality behavior and is not
// guaranteed in future Brick releases.
// https://github.com/GetDutchie/brick/issues/429
test('ordering by association is forwarded as is', () async {
final statement =
'SELECT DISTINCT `DemoModel`.* FROM `DemoModel` ORDER BY other_table.complex_field_name DESC';
final sqliteQuery = QuerySqlTransformer<DemoModel>(
modelDictionary: dictionary,
query: Query(providerArgs: {'orderBy': 'other_table.complex_field_name DESC'}),
);
await db.rawQuery(sqliteQuery.statement, sqliteQuery.values);

expect(statement, sqliteQuery.statement);
sqliteStatementExpectation(statement);
});
});

group('#values', () {
Expand Down
46 changes: 30 additions & 16 deletions packages/brick_supabase/lib/src/supabase_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,47 +87,49 @@ class SupabaseProvider implements Provider<SupabaseModel> {
/// when `Room` is upserted, `Pillow` is upserted and then `Bed` is upserted.
@override
Future<TModel> upsert<TModel extends SupabaseModel>(instance, {query, repository}) async {
final adapter = modelDictionary.adapterFor[TModel]!;
final output = await adapter.toSupabase(instance, provider: this, repository: repository);

return await _recursiveAssociationUpsert(
instance,
output,
type: TModel,
query: query,
repository: repository,
) as TModel;
}

Future<SupabaseModel> _upsertByType(
SupabaseModel instance, {
Map<String, dynamic> serializedInstance, {
required Type type,
Query? query,
ModelRepository<SupabaseModel>? repository,
}) async {
assert(modelDictionary.adapterFor.containsKey(type));

final adapter = modelDictionary.adapterFor[type]!;
final output = await adapter.toSupabase(instance, provider: this, repository: repository);

final queryTransformer =
QuerySupabaseTransformer(adapter: adapter, modelDictionary: modelDictionary, query: query);

final builder = adapter.uniqueFields.fold(client.from(adapter.supabaseTableName).upsert(output),
(acc, uniqueFieldName) {
final builder = adapter.uniqueFields.fold(
client.from(adapter.supabaseTableName).upsert(serializedInstance), (acc, uniqueFieldName) {
final columnName = adapter.fieldsToSupabaseColumns[uniqueFieldName]!.columnName;
if (output.containsKey(columnName)) {
return acc.eq(columnName, output[columnName]);
if (serializedInstance.containsKey(columnName)) {
return acc.eq(columnName, serializedInstance[columnName]);
}
return acc;
});
final resp = await builder.select(queryTransformer.selectFields).limit(1).maybeSingle();

if (resp == null) {
throw StateError('Upsert of $instance failed');
throw StateError('Upsert of $type failed');
}

return adapter.fromSupabase(resp, repository: repository, provider: this);
}

Future<SupabaseModel> _recursiveAssociationUpsert(
SupabaseModel instance, {
Map<String, dynamic> serializedInstance, {
required Type type,
Query? query,
ModelRepository<SupabaseModel>? repository,
Expand All @@ -139,13 +141,25 @@ class SupabaseProvider implements Provider<SupabaseModel> {
.where((a) => a.association && a.associationType != null);

for (final association in associations) {
await _recursiveAssociationUpsert(
instance,
type: association.associationType!,
query: query,
repository: repository,
);
if (!serializedInstance.containsKey(association.columnName)) {
continue;
}

if (serializedInstance[association.columnName] is Map) {
await _recursiveAssociationUpsert(
Map<String, dynamic>.from(serializedInstance[association.columnName]),
type: association.associationType!,
query: query,
repository: repository,
);
}
}
return await _upsertByType(instance, type: type, query: query, repository: repository);

return await _upsertByType(
serializedInstance,
type: type,
query: query,
repository: repository,
);
}
}

0 comments on commit 0edeabe

Please sign in to comment.