Skip to content

NULL and empty string are indistinguishable, and empty values are skipped on hydrate #20

Description

@jkalias

Problem

On the fetch path, FetchRecordsQuery::HydrateCurrentRow (src/queries.cc:299) skips a column instead of assigning it in two cases, leaving the member at its default-constructed value:

  • NULL or BLOB: if (col_type == SQLITE_NULL || col_type == SQLITE_BLOB) { continue; } (src/queries.cc:316)
  • empty TEXT / DATETIME: if (byte_count == 0) { continue; } (src/queries.cc:342 and :353)

So a SQL NULL, an empty TEXT, and (for a numeric column read as NULL) all resolve to the member's default, and none is distinguishable from a genuinely stored zero/empty value.

Historical note: this issue originally described FetchRecordsQuery::GetColumnValue returning L"" for both SQLITE_NULL and empty TEXT, plus if (content.empty()) continue; in a text-based Hydrate. PR #31 removed that wstring round-trip in favor of direct typed hydration. The new code does explicitly detect SQLITE_NULL via sqlite3_column_type, but deliberately preserves the same skip-and-leave-default behavior, so the limitation below still stands.

Impact

  • A column that is SQL NULL and one holding an empty string (or numeric 0) are indistinguishable after hydration.
  • A NULL/empty value is silently dropped — the member keeps its default rather than reflecting what is actually stored.

This conflation also blocks a clean implementation of nullable fields (#2), which needs to distinguish "absent" from "empty/zero".

Suggested direction

Represent NULL distinctly from a present-but-empty/zero value, in coordination with the nullable-fields work in #2 (e.g. a nullable wrapper that hydration sets to "unset" on SQLITE_NULL). The raw SQLITE_NULL detection already exists in HydrateCurrentRow; what is missing is a typed representation to carry "absent" back to the caller.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions