summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/postgresql/asyncpg.py
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2022-12-02 11:58:40 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-12-05 09:59:01 -0500
commit06c234d037bdab48e716d6c5f5dc200095269474 (patch)
tree8ed48e0627f0e4816b7e26f9e6294330f1ba19d6 /lib/sqlalchemy/dialects/postgresql/asyncpg.py
parent9058593e0b28cee0211251de6604e4601ff69a00 (diff)
downloadsqlalchemy-06c234d037bdab48e716d6c5f5dc200095269474.tar.gz
Rewrite positional handling, test for "numeric"
Changed how the positional compilation is performed. It's rendered by the compiler the same as the pyformat compilation. The string is then processed to replace the placeholders with the correct ones, and to obtain the correct order of the parameters. This vastly simplifies the computation of the order of the parameters, that in case of nested CTE is very hard to compute correctly. Reworked how numeric paramstyle behavers: - added support for repeated parameter, without duplicating them like in normal positional dialects - implement insertmany support. This requires that the dialect supports out of order placehoders, since all parameters that are not part of the VALUES clauses are placed at the beginning of the parameter tuple - support for different identifiers for a numeric parameter. It's for example possible to use postgresql style placeholder $1, $2, etc Added two new dialect based on sqlite to test "numeric" fully using both :1 style and $1 style. Includes a workaround for SQLite's not-really-correct numeric implementation. Changed parmstyle of asyncpg dialect to use numeric, rendering with its native $ identifiers Fixes: #8926 Fixes: #8849 Change-Id: I7c640467d49adfe6d795cc84296fc7403dcad4d6
Diffstat (limited to 'lib/sqlalchemy/dialects/postgresql/asyncpg.py')
-rw-r--r--lib/sqlalchemy/dialects/postgresql/asyncpg.py17
1 files changed, 3 insertions, 14 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/asyncpg.py b/lib/sqlalchemy/dialects/postgresql/asyncpg.py
index 751dc3dcf..b8f614eba 100644
--- a/lib/sqlalchemy/dialects/postgresql/asyncpg.py
+++ b/lib/sqlalchemy/dialects/postgresql/asyncpg.py
@@ -438,9 +438,6 @@ class AsyncAdapt_asyncpg_cursor:
def _handle_exception(self, error):
self._adapt_connection._handle_exception(error)
- def _parameter_placeholders(self, params):
- return tuple(f"${idx:d}" for idx, _ in enumerate(params, 1))
-
async def _prepare_and_execute(self, operation, parameters):
adapt_connection = self._adapt_connection
@@ -449,11 +446,7 @@ class AsyncAdapt_asyncpg_cursor:
if not adapt_connection._started:
await adapt_connection._start_transaction()
- if parameters is not None:
- operation = operation % self._parameter_placeholders(
- parameters
- )
- else:
+ if parameters is None:
parameters = ()
try:
@@ -506,10 +499,6 @@ class AsyncAdapt_asyncpg_cursor:
if not adapt_connection._started:
await adapt_connection._start_transaction()
- operation = operation % self._parameter_placeholders(
- seq_of_parameters[0]
- )
-
try:
return await self._connection.executemany(
operation, seq_of_parameters
@@ -808,7 +797,7 @@ class AsyncAdaptFallback_asyncpg_connection(AsyncAdapt_asyncpg_connection):
class AsyncAdapt_asyncpg_dbapi:
def __init__(self, asyncpg):
self.asyncpg = asyncpg
- self.paramstyle = "format"
+ self.paramstyle = "numeric_dollar"
def connect(self, *arg, **kw):
async_fallback = kw.pop("async_fallback", False)
@@ -900,7 +889,7 @@ class PGDialect_asyncpg(PGDialect):
render_bind_cast = True
has_terminate = True
- default_paramstyle = "format"
+ default_paramstyle = "numeric_dollar"
supports_sane_multi_rowcount = False
execution_ctx_cls = PGExecutionContext_asyncpg
statement_compiler = PGCompiler_asyncpg