Skip to content

Return Decimal values from Array(Numeric()) columns in SQLite - #1445

Merged
dantownsend merged 1 commit into
piccolo-orm:masterfrom
b84330808:fix-sqlite-numeric-array
Oct 28, 2026
Merged

dantownsend merged 1 commit into
piccolo-orm:masterfrom
b84330808:fix-sqlite-numeric-array

Conversation

@b84330808

Copy link
Copy Markdown
Contributor

Fixes #1444 (follow-up to #1342, related to #941).

#1342 registered an ARRAY_NUMERIC converter, but Array.column_type only uses the ARRAY_* column types for Date / Time / Timestamp / Timestamptz, so the column was still created as ARRAY and the converter never ran. Also, decimals are stored as JSON numbers, while convert_complex_array_out only converted strings.

This adds Numeric to the ARRAY_* column types, and converts numbers in convert_complex_array_out. Both are needed: with either one alone the values still come back as floats. The existing test passed because 50.0 == Decimal("50.0"), so I added a type check.

Existing SQLite tables keep their ARRAY column type, so they behave as before. Nested arrays, None elements and timestamp arrays work the same as before; on Postgres this only adds an isinstance check since asyncpg already returns Decimal.

I used Claude Code to write this change.

piccolo-orm#1342 registered an `ARRAY_NUMERIC` converter, but `Array.column_type`
only used the `ARRAY_*` types for date / time columns, so
`Array(Numeric())` was still created as `ARRAY` and the values came back
as floats. Decimals are stored as JSON numbers, so the array converter
also has to convert numbers, not just strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dantownsend

Copy link
Copy Markdown
Member

Thanks for this - what you've said does sound right.

@dantownsend

Copy link
Copy Markdown
Member

I tested it locally with this little script and it all seems to work great - thanks!

import asyncio
from decimal import Decimal

from piccolo.columns.column_types import Array, Numeric
from piccolo.engine.sqlite import SQLiteEngine
from piccolo.table import Table, create_db_tables

DB = SQLiteEngine()


class ArrayNumeric(Table, db=DB):
    array = Array(Numeric())


async def main():
    await create_db_tables(ArrayNumeric, if_not_exists=True)

    row = ArrayNumeric(
        {
            ArrayNumeric.array: [
                Decimal("1.0"),
                Decimal("5.32"),
            ]
        }
    )
    await row.save()

    rows = await ArrayNumeric.select().first()
    assert isinstance(rows["array"][0], Decimal)


if __name__ == "__main__":
    asyncio.run(main())

@dantownsend
dantownsend merged commit f90d179 into piccolo-orm:master Oct 28, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Array(Numeric()) returns floats instead of Decimal in SQLite

2 participants