Why GridDB Python Client Returns Different Types for get() vs query().fetch()
Understanding the Type Mismatch in GridDB Python Client
When working with GridDB in Python, you might encounter a puzzling behavior: retrieving a row using container.get() returns the correct Python types (like int), but querying the same row using query().fetch() converts those same integer values into Python float types. This article explains why this happens and how to resolve it.
The Symptom
Consider a container defined with an INTEGER key and a FLOAT value. When you fetch the row directly, the types are preserved:
row = container.get(1)
print(type(row[0]), type(row[1]))
# Output: <class 'int'> <class 'float'>However, when executing a TQL query and fetching the results, the integer is unexpectedly promoted to a float:
query = container.query("SELECT *")
rs = query.fetch()
for row in rs:
print(type(row[0]), type(row[1]))
# Output: <class 'float'> <class 'float'>Why Does This Happen?
This inconsistency stems from how the griddb_python C-wrapper handles data deserialization across two different execution paths:
- The Direct Path (
container.get): This method uses the container's strict, predefined schema. The client knows exactly what type each column is supposed to be beforehand, mapping GridDB'sType.INTEGERdirectly to a Pythonint. - The Query Path (
query().fetch()): When you run a query, GridDB returns a dynamicRowSet. The Python client's underlying C/C++ binding layer materializes these rows dynamically. In certain versions of the Python SDK, the dynamic type mapper defaults generic numeric values returned by the query engine to double-precision floats to prevent precision loss, resulting in Pythonfloattypes. This is especially true whenfetch(False)is used, which retrieves raw query projections rather than mapping back to the container's strict row schema.
How to Fix and Work Around This Issue
1. Use query.fetch() without disabling row-mapping
If you pass False to fetch(), it tells GridDB not to bind the results to the container's row type. Try calling fetch() without arguments (or passing True, depending on your SDK version) to force the client to use the container's schema definition during deserialization:
rs = query.fetch(True) # Or simply query.fetch()2. Explicit Type Casting in Python
If you are executing complex queries or projections where schema binding isn't possible, the safest workaround is to explicitly cast the values to your expected types in Python:
for row in rs:
row_id = int(row[0])
reading = float(row[1])
# Process your data with correct types3. Upgrade the griddb_python Client
Type coercion issues in dynamic row sets are frequently addressed in newer releases of the GridDB Python client. Ensure you are using the latest version of the C client and Python binding:
pip install --upgrade griddb_pythonConclusion
The type discrepancy between get() and query().fetch() is a side-effect of dynamic row-set materialization in the GridDB Python C-bindings. By ensuring your queries bind back to the container schema or by performing explicit type casting, you can maintain type safety across your GridDB applications.