Skip to content

BuildingRepository.GetByBuildingCode cannot correctly populate a struct from any table shape #13

Description

@jravani

What's broken

BuildingRepository.GetByBuildingCode (internal/db/repository/building_repository.go) has two compounding bugs that mean it can never correctly populate a TabulaBuildingParameters struct, regardless of the target table's shape:

  1. Filter/table-shape mismatch. Its query uses an unquoted identifier:

    query := fmt.Sprintf(`SELECT * FROM %s WHERE code_buildingvariant = $1 LIMIT 1`, r.qualifyTable(tableName))

    Postgres folds unquoted identifiers to lowercase, so this only matches a table whose column is literally named code_buildingvariant. But TableConstructor (internal/db/table_constructor.go) creates tables with quoted, mixed-case columns (e.g. "Code_BuildingVariant") — the real shape of every table this app actually builds. Run against a real, production-shaped table, the WHERE clause never matches.

  2. Population mismatch, even when a row is found. populateStructFromMap looks up scanned values by the field's mixed-case JSON tag ("A_Roof_1"), but rowsToDataMap keys its map off rows.FieldDescriptions() — the column names Postgres actually returns. For a table with unquoted (hence lowercased) columns, that's "a_roof_1", which never matches the mixed-case tag lookup. So even a fixture built specifically to satisfy bug [Template Sync] Update legal copyright information #1 above returns no error but a struct with every field left at its zero value.

Combined, there is no table shape for which this function both finds a row and populates it correctly.

Why this hasn't surfaced

GetByBuildingCode is only reachable via IgnisService.GetBuildingByCode, constructed through NewIgnisServiceWithDB — and nothing in the codebase calls NewIgnisServiceWithDB or GetBuildingByCode. It's dead code today, so this has no production impact. All real building-lookup traffic goes through TabulaRepository (used by the API handlers), which uses quoted, case-correct queries and works correctly.

Found and documented (not fixed) while adding integration test coverage for internal/db/repository in #12 — see internal/db/repository/repository_integration_test.go's TestBuildingRepository_GetByBuildingCode_success and _mismatchAgainstProductionShape, which lock in and explain the current (broken) behavior.

Suggested fix

Either:

  • Quote "Code_BuildingVariant" in the WHERE clause (matching TabulaRepository's style) and fix populateStructFromMap's lookup to be case-insensitive or use consistent key casing, or
  • If BuildingRepository/GetByBuildingCode/NewIgnisServiceWithDB are genuinely unused, remove them instead of fixing dead code.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions