Skip to content

feat(postgres/sqlite): update API to be fully async#148

Merged
vdice merged 1 commit intospinframework:mainfrom
vdice:feat/opinionated-db-modules
Apr 13, 2026
Merged

feat(postgres/sqlite): update API to be fully async#148
vdice merged 1 commit intospinframework:mainfrom
vdice:feat/opinionated-db-modules

Conversation

@vdice
Copy link
Copy Markdown
Contributor

@vdice vdice commented Apr 10, 2026

Updates the postgres and sqlite modules to provide a completely async, opinionated API. This breaks the previous (canary) versions of the v4 SDKs but as they hadn't yet been released, this seems a good time to do it.

TODO:

Closes #146

Copy link
Copy Markdown
Collaborator

@dicej dicej left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Copy Markdown
Contributor

@itowlson itowlson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this!

Comment thread examples/spin-sqlite/app.py Outdated
rows = result.rows

with await Connection.open_default() as db:
await db.execute("INSERT INTO todos (description, due) VALUES (?, ?)", [Value_Text("Try out Spin SQLite"), Value_Text("Friday")])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle this should presumably check the returned error future? (I am not quite sure when/where SQLite would produce the error in this case!)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, here's what I did to make the spin-sqlite example work on an empty database, but never got around to PR'ing:

from spin_sdk import http, sqlite
from spin_sdk.http import Request, Response
from spin_sdk.sqlite import Value_Integer, Value_Text
from spin_sdk.util import collect

class HttpHandler(http.Handler):
    async def handle_request(self, request: Request) -> Response:
        with await sqlite.open_default() as db:
            _, stream, result = await db.execute(
                "CREATE TABLE IF NOT EXISTS example (id INTEGER NOT NULL PRIMARY KEY, value TEXT NOT NULL)",
                []
            )
            await collect((stream, result))

            insert = "INSERT INTO example (id, value) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET value=excluded.value"
            
            _, stream, result = await db.execute(insert, [Value_Integer(1), Value_Text("foo")])
            await collect((stream, result))
            
            _, stream, result = await db.execute(insert, [Value_Integer(2), Value_Text("bar")])
            await collect((stream, result))
            
            columns, stream, result = await db.execute("SELECT * FROM example WHERE id > (?);", [Value_Integer(1)])
            rows = await collect((stream, result))

            assert columns == ["id", "value"]
            assert len(rows) == 1
            assert isinstance(rows[0].values[0], Value_Integer)
            assert rows[0].values[0].value == 2
            assert isinstance(rows[0].values[1], Value_Text)
            assert rows[0].values[1].value == "bar"
        
        return Response(
            200,
            {"content-type": "text/plain"},
            bytes(str(rows), "utf-8")
        )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dicej, I've updated the example.

Comment thread src/spin_sdk/postgres.py Outdated
"""
Open a connection with a Postgres database.

The connection_string is the Postgres URL connection string.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we support both the URL form and the connection string form.

Suggested change
The connection_string is the Postgres URL connection string.
The connection_string is the Postgres URL or connection string.

Signed-off-by: Vaughn Dice <vdice@akamai.com>
Co-authored-by: Joel Dice <joel.dice@akamai.com>
@vdice vdice force-pushed the feat/opinionated-db-modules branch from 5a0a3ae to 022f16b Compare April 13, 2026 17:00
@vdice vdice merged commit 7ef996c into spinframework:main Apr 13, 2026
2 checks passed
@vdice vdice deleted the feat/opinionated-db-modules branch April 13, 2026 17:05
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.

modules(db): only surface async methods

3 participants