buildSupabase method

String buildSupabase()

Builds the Supabase PostgREST-compatible select string.

This string defines which columns to fetch from the primary table and how to embed related data from other tables.

Format examples:

  • * (all columns from primary table)
  • id,name (specific columns)
  • *,author:authors!posts_author_id_fkey(*) (all from primary, embed author)
  • title,comments:comments!posts_id_fkey(text,user:users!comments_user_id_fkey(name)) (complex nesting)
  • title,author:authors!posts_author_id_fkey!inner(name) (using inner join)

Returns the generated select string.

Implementation

String buildSupabase() {
  final List<String> parts = [];

  // Determine columns for the primary table
  if (selectAllPrimary) {
    parts.add('*');
  } else if (selectedPrimaryColumns.isNotEmpty) {
    parts.addAll(selectedPrimaryColumns);
  } else {
    // PostgREST requires at least one column or '*' from the primary table
    // if embedding related resources. If no columns are selected and relations exist,
    // default to '*' for the primary table.
    // If no columns and no relations, PostgREST might default to PKs or all.
    // To be safe and explicit, if nothing is selected, default to '*' for the current table.
    parts.add('*');
    if (selectedPrimaryColumns.isEmpty && supabaseRelatedBuilders.isEmpty) {
      _logger.info(
        "Building Supabase select for '${currentTableInfo.originalName}': No specific columns or relations selected, defaulting to '*' for the primary table.",
      );
    } else if (selectedPrimaryColumns.isEmpty &&
        supabaseRelatedBuilders.isNotEmpty) {
      _logger.info(
        "Building Supabase select for '${currentTableInfo.originalName}': No specific primary columns selected but relations exist. Defaulting to '*' for the primary table to support embedding.",
      );
    }
  }

  // Add parts for related builders
  supabaseRelatedBuilders.forEach((jsonKey, relatedLink) {
    final targetTableName = relatedLink.builder.currentTableInfo.originalName;
    final fkConstraintName = relatedLink.fkConstraintName;
    final nestedSelect = relatedLink.builder.buildSupabase();
    final useInnerJoin = relatedLink.innerJoin;

    // Construct the relationship specifier: target_table!fk_constraint_name
    String relationshipSpecifier = '$targetTableName!$fkConstraintName';
    if (useInnerJoin) {
      relationshipSpecifier = '$relationshipSpecifier!inner';
    }

    // Format: jsonKey:relationship_specifier(nested_select)
    // If nestedSelect is empty (e.g., builder defaults to '*' or is misconfigured),
    // PostgREST might still work if it implies '*' for the nested part.
    // However, an empty nestedSelect string from buildSupabase() is unlikely if it defaults to '*' itself.
    if (nestedSelect.isNotEmpty) {
      parts.add('$jsonKey:$relationshipSpecifier($nestedSelect)');
    } else {
      // This case should ideally not be reached if nestedBuilder.buildSupabase()
      // always returns at least '*' or a valid column list.
      _logger.warning(
        "Nested select string for relation '$jsonKey' (targeting '$targetTableName' via FK '$fkConstraintName') is empty. PostgREST query might be malformed. Using format: '$jsonKey:$relationshipSpecifier'.",
      );
      parts.add('$jsonKey:$relationshipSpecifier');
    }
  });

  return parts.join(',');
}