@@ -26,7 +26,7 @@ def executemany(self, statement, parameters):
2626 def description (self ):
2727 raise NotImplementedError
2828
29- async def prepare (self , query , timeout ):
29+ async def prepare (self , context , clause = None ):
3030 raise NotImplementedError
3131
3232 async def async_execute (self , query , timeout , args , limit = 0 , many = False ):
@@ -67,18 +67,62 @@ async def rollback(self):
6767
6868
6969class PreparedStatement :
70- def __init__ (self ):
70+ def __init__ (self , clause = None ):
7171 self .context = None
72+ self .clause = clause
7273
7374 def iterate (self , * params , ** kwargs ):
7475 return _PreparedIterableCursor (self , params , kwargs )
7576
77+ async def _do_execute (self , multiparams , params , one = False ,
78+ return_model = True , status = False ):
79+ ctx = self .context .connection .execute (
80+ self .clause , * multiparams , ** params ).context
81+ if ctx .executemany :
82+ raise ValueError ('PreparedStatement does not support multiple '
83+ 'parameters.' )
84+ assert ctx .statement == self .context .statement , (
85+ 'Prepared statement generated different SQL with parameters' )
86+ params = []
87+ for val in ctx .parameters [0 ]:
88+ params .append (val )
89+ msg , rows = await self ._execute (params , one )
90+ if status :
91+ return msg
92+ item = self .context .process_rows (rows , return_model = return_model )
93+ if one :
94+ if item :
95+ item = item [0 ]
96+ else :
97+ item = None
98+ return item
99+
100+ async def all (self , * multiparams , ** params ):
101+ return await self ._do_execute (multiparams , params )
102+
103+ async def first (self , * multiparams , ** params ):
104+ return await self ._do_execute (multiparams , params , one = True )
105+
106+ async def scalar (self , * multiparams , ** params ):
107+ rv = await self ._do_execute (multiparams , params , one = True ,
108+ return_model = False )
109+ if rv :
110+ return rv [0 ]
111+ else :
112+ return None
113+
114+ async def status (self , * multiparams , ** params ):
115+ return await self ._do_execute (multiparams , params , status = True )
116+
76117 def _get_iterator (self , * params , ** kwargs ):
77118 raise NotImplementedError
78119
79120 async def _get_cursor (self , * params , ** kwargs ):
80121 raise NotImplementedError
81122
123+ async def _execute (self , params , one ):
124+ raise NotImplementedError
125+
82126
83127class _PreparedIterableCursor :
84128 def __init__ (self , prepared , params , kwargs ):
@@ -100,9 +144,7 @@ def __init__(self, context):
100144 self ._context = context
101145
102146 async def _iterate (self ):
103- prepared = await self ._context .cursor .prepare (self ._context .statement ,
104- self ._context .timeout )
105- prepared .context = self ._context
147+ prepared = await self ._context .cursor .prepare (self ._context )
106148 return prepared .iterate (* self ._context .parameters [0 ],
107149 timeout = self ._context .timeout )
108150
@@ -173,6 +215,9 @@ def iterate(self):
173215 raise ValueError ('too many multiparams' )
174216 return _IterableCursor (self ._context )
175217
218+ async def prepare (self , clause ):
219+ return await self ._context .cursor .prepare (self ._context , clause )
220+
176221 def _soft_close (self ):
177222 pass
178223
@@ -237,6 +282,88 @@ def process_rows(self, rows, return_model=True):
237282 def get_result_proxy (self ):
238283 return _ResultProxy (self )
239284
285+ @classmethod
286+ def _init_compiled_prepared (cls , dialect , connection , dbapi_connection ,
287+ compiled , parameters ):
288+ self = cls .__new__ (cls )
289+ self .root_connection = connection
290+ self ._dbapi_connection = dbapi_connection
291+ self .dialect = connection .dialect
292+
293+ self .compiled = compiled
294+
295+ # this should be caught in the engine before
296+ # we get here
297+ assert compiled .can_execute
298+
299+ self .execution_options = compiled .execution_options .union (
300+ connection ._execution_options )
301+
302+ self .result_column_struct = (
303+ compiled ._result_columns , compiled ._ordered_columns ,
304+ compiled ._textual_ordered_columns )
305+
306+ self .unicode_statement = util .text_type (compiled )
307+ if not dialect .supports_unicode_statements :
308+ self .statement = self .unicode_statement .encode (
309+ self .dialect .encoding )
310+ else :
311+ self .statement = self .unicode_statement
312+
313+ self .isinsert = compiled .isinsert
314+ self .isupdate = compiled .isupdate
315+ self .isdelete = compiled .isdelete
316+ self .is_text = compiled .isplaintext
317+
318+ self .executemany = False
319+
320+ self .cursor = self .create_cursor ()
321+
322+ if self .isinsert or self .isupdate or self .isdelete :
323+ self .is_crud = True
324+ self ._is_explicit_returning = bool (compiled .statement ._returning )
325+ self ._is_implicit_returning = bool (
326+ compiled .returning and not compiled .statement ._returning )
327+
328+ if self .dialect .positional :
329+ self .parameters = [dialect .execute_sequence_format ()]
330+ else :
331+ self .parameters = [{}]
332+ self .compiled_parameters = [{}]
333+
334+ return self
335+
336+ @classmethod
337+ def _init_statement_prepared (cls , dialect , connection , dbapi_connection ,
338+ statement , parameters ):
339+ """Initialize execution context for a string SQL statement."""
340+
341+ self = cls .__new__ (cls )
342+ self .root_connection = connection
343+ self ._dbapi_connection = dbapi_connection
344+ self .dialect = connection .dialect
345+ self .is_text = True
346+
347+ # plain text statement
348+ self .execution_options = connection ._execution_options
349+
350+ if self .dialect .positional :
351+ self .parameters = [dialect .execute_sequence_format ()]
352+ else :
353+ self .parameters = [{}]
354+
355+ self .executemany = False
356+
357+ if not dialect .supports_unicode_statements and \
358+ isinstance (statement , util .text_type ):
359+ self .unicode_statement = statement
360+ self .statement = dialect ._encoder (statement )[0 ]
361+ else :
362+ self .statement = self .unicode_statement = statement
363+
364+ self .cursor = self .create_cursor ()
365+ return self
366+
240367
241368class AsyncDialectMixin :
242369 cursor_cls = DBAPICursor
0 commit comments