Feature support
Which sqlc features and query commands the plugin supports.
Macros
Every sqlc macro is
supported (sqlc.arg, sqlc.narg, sqlc.embed, sqlc.slice).
sqlc.slice is for the SQLite and MySQL drivers, where a list cannot be
passed to the IN operator: the generated function expands the placeholder
at call time, one placeholder per element, and an empty sequence matches no
rows. Because the SQL is built per call, it cannot be used with prepared
statements. On PostgreSQL the macro is not needed - use = ANY($1::type[]),
which accepts the sequence directly.Query commands
The supported query annotations depend on the driver:
| Command | aiosqlite | sqlite3 | asyncpg | psycopg_async | psycopg_sync | asyncmy | pymysql | turso_async | turso_sync |
|---|---|---|---|---|---|---|---|---|---|
:one | yes | yes | yes | yes | yes | yes | yes | yes | yes |
:many | yes | yes | yes | yes | yes | yes | yes | yes | yes |
:exec | yes | yes | yes | yes | yes | yes | yes | yes | yes |
:execresult | yes | yes | yes | yes | yes | yes | yes | yes | yes |
:execrows | yes | yes | yes | yes | yes | yes | yes | yes | yes |
:execlastid | yes | yes | no | no | no | yes | yes | yes | yes |
:copyfrom | no | no | yes | yes | yes | no | no | no | no |
See Writing queries for what each command generates.
:execlastidrelies on a last-inserted-row id, which PostgreSQL does not provide - use aRETURNINGclause with:oneinstead.- On the turso drivers
:execlastidreturnsNoneforUPDATE/DELETEstatements - turso’slastrowidonly reflects the cursor’s ownINSERT. :copyfrommaps to PostgreSQL’s bulkCOPYprotocol (copy_records_to_tableon asyncpg,cursor.copy()on psycopg), which the SQLite-engine and MySQL drivers have no equivalent for. MySQL’sLOAD DATA LOCAL INFILEexposes no row-streaming driver API to generate against; if you need it, run it as a plain:execstatement.
Prepared queries
Looking for sqlc’s
emit_prepared_queries?
There is none, on purpose: every stable driver already prepares statements
automatically. What differs is when a query is prepared and which knob
controls it:
asyncpg prepares every query it runs and keeps it in a per-connection LRU statement cache (100 entries by default). Tune it at connect time:
conn = await asyncpg.connect( dsn, statement_cache_size=200, # default 100; 0 disables the cache )psycopg (both flavors) prepares a query server-side once it has been executed more than
prepare_thresholdtimes on the connection - with the default of 5, the sixth execution is the first prepared one. Set it to0to prepare from the first execution, orNoneto never prepare:conn = await psycopg.AsyncConnection.connect(dsn, prepare_threshold=0) # psycopg_async conn = psycopg.connect(dsn, prepare_threshold=0) # psycopg_syncsqlite3 / aiosqlite expose no explicit prepare API, but the
sqlite3module compiles each statement once and reuses it through an internal per-connection cache (128 entries by default). Raise it with thecached_statementsargument ofconnect()if you have more distinct queries than that.asyncmy / pymysql use MySQL’s text protocol: parameters are interpolated client-side and nothing is prepared server-side, so there is no knob and nothing to disable behind a pooler.
turso_sync / turso_async (experimental) are the exception among the prepared-statement drivers: pyturso currently has no statement cache and no tuning knob, so every execution prepares the statement anew.
statement_cache_size=0 for asyncpg, prepare_threshold=None for psycopg.Not supported
:batch*commands (:batchexec,:batchmany,:batchone) are not supported and likely never will be.psycopg2is not supported; Psycopg 3 is, via thepsycopg_async(asyncio) andpsycopg_sync(synchronous) drivers. For MySQL, useasyncmyorpymysql-mysqlclientandmysql-connector-pythonare not codegen targets (PyMySQL-targeted code is source-compatible withmysqlclientexcept thatjsoncolumns arrive asbytesthere).