Skip to content

PostgreSQL 'double precision' columns are read back as float32 (ddl2cpp generates 'float' instead of 'double') #586

Description

@Yaraslaut

Surfaced by the column-type coverage added in #579, where it is asserted as-is and labelled KNOWN DEFECT so it does not go unnoticed.

Symptom

A PostgreSQL DOUBLE PRECISION column is read back out of the catalog as Real { .precision = 24 }, so CxxModelPrinter::MakeType emits float instead of double. Every generated record silently narrows such a column from 8 bytes to 4.

The same declaration is handled correctly on SQLite and MS SQL Server — this is PostgreSQL-only.

Cause

The schema reader's float fixup matches dialect type names literally:

// src/Lightweight/SqlSchema.cpp:1439
if (column.dialectDependantTypeString == "float" || column.dialectDependantTypeString == "FLOAT"
    || column.dialectDependantTypeString == "real" || column.dialectDependantTypeString == "REAL")
{
    column.type = SqlColumnTypeDefinitions::Real { .precision = 53 };
}

PostgreSQL names its floating-point types float4 and float8, so float8 never enters the branch. The column then keeps whatever precision the driver-reported width produced, and CxxModelPrinter maps precision <= 24 to float:

// src/Lightweight/Tools/CxxModelPrinter.cpp:740
[](Real const& v) -> std::string { return v.precision <= 24 ? "float" : "double"; },

The write side already knows about this hazard — PostgreSqlFormatter::ColumnType carries the comment "or restore silently narrows it to float32" (src/Lightweight/QueryFormatter/PostgreSqlFormatter.hpp:165). The read side is still missing the equivalent handling.

Impact

  • ddl2cpp generates precision-losing record members for every double precision column in a PostgreSQL schema.
  • Any consumer of SqlSchema::Column (backup/restore, migration diffing) sees a 4-byte column where the database has an 8-byte one.

Suggested fix

Teach the fixup PostgreSQL's type names — map float8 to Real { .precision = 53 } and float4 to Real { .precision = 24 }. Given the surrounding code is a chain of literal string comparisons, a small descriptor table of dialect type name → canonical Real precision would fit the project's data-driven-design guideline better than another || clause.

Verification

src/tests/Ddl2CppColumnTypeTests.cpp (from #579) already asserts the current wrong behaviour through a dialectException entry. When fixing this, update that entry to expect double rather than adding a new exception — the comment above it says so explicitly.

Related: #191, #579

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions