brick icon indicating copy to clipboard operation
brick copied to clipboard

Upsert with Many-to-Many associations generates invalid empty `or: ()` query for Supabase

Open KiddoV opened this issue 3 months ago • 0 comments

Description:

When performing an upsert on a model that has many-to-many association can cause Brick to generate an invalid or: () condition, which fails in Supabase with: PostgrestException(message: "failed to parse logic tree (())" ...)

Steps to reproduce:

@ConnectOfflineFirstWithSupabase(
  supabaseConfig: SupabaseSerializable(tableName: "groups"),
)
@MappableClass()
class Group extends OfflineFirstWithSupabaseModel with GroupMappable {
  final String id;
  final String creatorId;
  @Supabase(ignore: true)
  final List<GroupMember> memberLinks;

  Group({
    required this.id,
    required this.creatorId,
    List<GroupMember>? memberLinks,
  }) : memberLinks = memberLinks ?? [];
}

@ConnectOfflineFirstWithSupabase(
  supabaseConfig: SupabaseSerializable(tableName: "group_members"),
)
@MappableClass()
class GroupMember extends OfflineFirstWithSupabaseModel with GroupMemberMappable {
  final String id;
  final Group group;
  final Person person;

  GroupMember({
    required this.id,
    required this.group,
    required this.person,
  });
}

@ConnectOfflineFirstWithSupabase(
  supabaseConfig: SupabaseSerializable(tableName: "persons"),
)
@MappableClass()
class Person extends OfflineFirstWithSupabaseModel with PersonMappable {
  final String id;
  Person({required this.id});
}
final group = Group(id: 'grp1', creatorId: 'user1');
final members = [Person(id: 'p1'), Person(id: 'p2')];
final links = members.map((p) => GroupMember(id: p.id, group: group, person: p)).toList();

// This upsert triggers Brick to generate an invalid `or: ()`
await Future.wait(links.map((link) => appDB.upsert<GroupMember>(link)));

Observed behavior:

>>> WherePhrase optional, returning OR clause: {or: ()}
OfflineFirstRepository: WARNING: #hydrate supabase failure: PostgrestException(message: "failed to parse logic tree (())" ...)

Expected behavior:

  • Brick should skip empty WherePhrase objects when generating upsert queries.
  • No invalid empty or: () should be sent to Supabase.

Related code:

https://github.com/GetDutchie/brick/blob/063b85324b1c7d28aa12bd9af1319917e677a912/packages/brick_supabase/lib/src/query_supabase_transformer.dart#L149

KiddoV avatar Oct 07 '25 16:10 KiddoV