Summary
QueryResult.metadata[*].type is incorrect for every non-null declared SQLite type because mapSQLiteTypeToColumnType() treats a non-zero strcmp() result as a match.
Verified on main at ad8b835 (v9.7.0).
Code evidence
types.hpp#L25-L40 currently contains conditions such as:
} else if (strcmp(type, "BOOLEAN")) {
return ColumnType::BOOLEAN;
}
strcmp() returns 0 when strings are equal. Consequently:
INTEGER, TEXT, BLOB, FLOAT, and any other non-BOOLEAN declaration take the first branch and report BOOLEAN.
BOOLEAN skips the first branch, then differs from FLOAT, so it reports NUMBER.
- The later intended mappings are effectively unreachable.
The result is exposed through the metadata construction in operations.cpp#L247-L258.
Smallest reproducer
const db = open({ name: 'metadata.sqlite' })
db.execute(`
CREATE TABLE values_table (
boolean_value BOOLEAN,
float_value FLOAT,
integer_value INTEGER,
text_value TEXT,
blob_value BLOB
)
`)
const result = db.execute('SELECT * FROM values_table')
console.log(result.metadata)
Expected declared types:
BOOLEAN, NUMBER, INT64, TEXT, ARRAY_BUFFER
Observed from the current mapping logic:
NUMBER, BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN
This is distinct from #194, which reports missing metadata entries. This issue concerns the declared type values assigned to entries that are present.
Impact
Consumers cannot rely on query metadata for schema introspection, adapters, serializers, or ORMs. In particular, integer, text, and blob columns can be interpreted as booleans.
Acceptance criteria
- Compare declared types for equality (
strcmp(...) == 0) or use a less error-prone mapping.
- Add focused coverage for
BOOLEAN, FLOAT, INTEGER, TEXT, BLOB, and a null declaration (sqlite3_column_decltype() == nullptr).
- Define and test behavior for common SQLite affinity declarations such as
REAL, DOUBLE, VARCHAR(...), and INT, or document that only the current exact declarations are supported.
- Verify both
execute() and executeAsync() expose the corrected metadata.
Regression-test target
A native or Harness test that creates one column per supported declared type and asserts result.metadata[column].type for both sync and async execution.
Summary
QueryResult.metadata[*].typeis incorrect for every non-null declared SQLite type becausemapSQLiteTypeToColumnType()treats a non-zerostrcmp()result as a match.Verified on
mainatad8b835(v9.7.0).Code evidence
types.hpp#L25-L40currently contains conditions such as:strcmp()returns0when strings are equal. Consequently:INTEGER,TEXT,BLOB,FLOAT, and any other non-BOOLEANdeclaration take the first branch and reportBOOLEAN.BOOLEANskips the first branch, then differs fromFLOAT, so it reportsNUMBER.The result is exposed through the metadata construction in
operations.cpp#L247-L258.Smallest reproducer
Expected declared types:
Observed from the current mapping logic:
This is distinct from #194, which reports missing metadata entries. This issue concerns the declared type values assigned to entries that are present.
Impact
Consumers cannot rely on query metadata for schema introspection, adapters, serializers, or ORMs. In particular, integer, text, and blob columns can be interpreted as booleans.
Acceptance criteria
strcmp(...) == 0) or use a less error-prone mapping.BOOLEAN,FLOAT,INTEGER,TEXT,BLOB, and a null declaration (sqlite3_column_decltype() == nullptr).REAL,DOUBLE,VARCHAR(...), andINT, or document that only the current exact declarations are supported.execute()andexecuteAsync()expose the corrected metadata.Regression-test target
A native or Harness test that creates one column per supported declared type and asserts
result.metadata[column].typefor both sync and async execution.