default.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. # engine/default.py
  2. # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """Default implementations of per-dialect sqlalchemy.engine classes.
  8. These are semi-private implementation classes which are only of importance
  9. to database dialect authors; dialects will usually use the classes here
  10. as the base class for their own corresponding classes.
  11. """
  12. import re
  13. import random
  14. from . import reflection, interfaces, result
  15. from ..sql import compiler, expression, schema
  16. from .. import types as sqltypes
  17. from .. import exc, util, pool, processors
  18. import codecs
  19. import weakref
  20. from .. import event
  21. AUTOCOMMIT_REGEXP = re.compile(
  22. r'\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)',
  23. re.I | re.UNICODE)
  24. # When we're handed literal SQL, ensure it's a SELECT query
  25. SERVER_SIDE_CURSOR_RE = re.compile(
  26. r'\s*SELECT',
  27. re.I | re.UNICODE)
  28. class DefaultDialect(interfaces.Dialect):
  29. """Default implementation of Dialect"""
  30. statement_compiler = compiler.SQLCompiler
  31. ddl_compiler = compiler.DDLCompiler
  32. type_compiler = compiler.GenericTypeCompiler
  33. preparer = compiler.IdentifierPreparer
  34. supports_alter = True
  35. # the first value we'd get for an autoincrement
  36. # column.
  37. default_sequence_base = 1
  38. # most DBAPIs happy with this for execute().
  39. # not cx_oracle.
  40. execute_sequence_format = tuple
  41. supports_views = True
  42. supports_sequences = False
  43. sequences_optional = False
  44. preexecute_autoincrement_sequences = False
  45. postfetch_lastrowid = True
  46. implicit_returning = False
  47. supports_right_nested_joins = True
  48. supports_native_enum = False
  49. supports_native_boolean = False
  50. supports_simple_order_by_label = True
  51. engine_config_types = util.immutabledict([
  52. ('convert_unicode', util.bool_or_str('force')),
  53. ('pool_timeout', util.asint),
  54. ('echo', util.bool_or_str('debug')),
  55. ('echo_pool', util.bool_or_str('debug')),
  56. ('pool_recycle', util.asint),
  57. ('pool_size', util.asint),
  58. ('max_overflow', util.asint),
  59. ('pool_threadlocal', util.asbool),
  60. ])
  61. # if the NUMERIC type
  62. # returns decimal.Decimal.
  63. # *not* the FLOAT type however.
  64. supports_native_decimal = False
  65. if util.py3k:
  66. supports_unicode_statements = True
  67. supports_unicode_binds = True
  68. returns_unicode_strings = True
  69. description_encoding = None
  70. else:
  71. supports_unicode_statements = False
  72. supports_unicode_binds = False
  73. returns_unicode_strings = False
  74. description_encoding = 'use_encoding'
  75. name = 'default'
  76. # length at which to truncate
  77. # any identifier.
  78. max_identifier_length = 9999
  79. # length at which to truncate
  80. # the name of an index.
  81. # Usually None to indicate
  82. # 'use max_identifier_length'.
  83. # thanks to MySQL, sigh
  84. max_index_name_length = None
  85. supports_sane_rowcount = True
  86. supports_sane_multi_rowcount = True
  87. dbapi_type_map = {}
  88. colspecs = {}
  89. default_paramstyle = 'named'
  90. supports_default_values = False
  91. supports_empty_insert = True
  92. supports_multivalues_insert = False
  93. supports_server_side_cursors = False
  94. server_version_info = None
  95. construct_arguments = None
  96. """Optional set of argument specifiers for various SQLAlchemy
  97. constructs, typically schema items.
  98. To implement, establish as a series of tuples, as in::
  99. construct_arguments = [
  100. (schema.Index, {
  101. "using": False,
  102. "where": None,
  103. "ops": None
  104. })
  105. ]
  106. If the above construct is established on the PostgreSQL dialect,
  107. the :class:`.Index` construct will now accept the keyword arguments
  108. ``postgresql_using``, ``postgresql_where``, nad ``postgresql_ops``.
  109. Any other argument specified to the constructor of :class:`.Index`
  110. which is prefixed with ``postgresql_`` will raise :class:`.ArgumentError`.
  111. A dialect which does not include a ``construct_arguments`` member will
  112. not participate in the argument validation system. For such a dialect,
  113. any argument name is accepted by all participating constructs, within
  114. the namespace of arguments prefixed with that dialect name. The rationale
  115. here is so that third-party dialects that haven't yet implemented this
  116. feature continue to function in the old way.
  117. .. versionadded:: 0.9.2
  118. .. seealso::
  119. :class:`.DialectKWArgs` - implementing base class which consumes
  120. :attr:`.DefaultDialect.construct_arguments`
  121. """
  122. # indicates symbol names are
  123. # UPPERCASEd if they are case insensitive
  124. # within the database.
  125. # if this is True, the methods normalize_name()
  126. # and denormalize_name() must be provided.
  127. requires_name_normalize = False
  128. reflection_options = ()
  129. dbapi_exception_translation_map = util.immutabledict()
  130. """mapping used in the extremely unusual case that a DBAPI's
  131. published exceptions don't actually have the __name__ that they
  132. are linked towards.
  133. .. versionadded:: 1.0.5
  134. """
  135. def __init__(self, convert_unicode=False,
  136. encoding='utf-8', paramstyle=None, dbapi=None,
  137. implicit_returning=None,
  138. supports_right_nested_joins=None,
  139. case_sensitive=True,
  140. supports_native_boolean=None,
  141. label_length=None, **kwargs):
  142. if not getattr(self, 'ported_sqla_06', True):
  143. util.warn(
  144. "The %s dialect is not yet ported to the 0.6 format" %
  145. self.name)
  146. self.convert_unicode = convert_unicode
  147. self.encoding = encoding
  148. self.positional = False
  149. self._ischema = None
  150. self.dbapi = dbapi
  151. if paramstyle is not None:
  152. self.paramstyle = paramstyle
  153. elif self.dbapi is not None:
  154. self.paramstyle = self.dbapi.paramstyle
  155. else:
  156. self.paramstyle = self.default_paramstyle
  157. if implicit_returning is not None:
  158. self.implicit_returning = implicit_returning
  159. self.positional = self.paramstyle in ('qmark', 'format', 'numeric')
  160. self.identifier_preparer = self.preparer(self)
  161. self.type_compiler = self.type_compiler(self)
  162. if supports_right_nested_joins is not None:
  163. self.supports_right_nested_joins = supports_right_nested_joins
  164. if supports_native_boolean is not None:
  165. self.supports_native_boolean = supports_native_boolean
  166. self.case_sensitive = case_sensitive
  167. if label_length and label_length > self.max_identifier_length:
  168. raise exc.ArgumentError(
  169. "Label length of %d is greater than this dialect's"
  170. " maximum identifier length of %d" %
  171. (label_length, self.max_identifier_length))
  172. self.label_length = label_length
  173. if self.description_encoding == 'use_encoding':
  174. self._description_decoder = \
  175. processors.to_unicode_processor_factory(
  176. encoding
  177. )
  178. elif self.description_encoding is not None:
  179. self._description_decoder = \
  180. processors.to_unicode_processor_factory(
  181. self.description_encoding
  182. )
  183. self._encoder = codecs.getencoder(self.encoding)
  184. self._decoder = processors.to_unicode_processor_factory(self.encoding)
  185. @util.memoized_property
  186. def _type_memos(self):
  187. return weakref.WeakKeyDictionary()
  188. @property
  189. def dialect_description(self):
  190. return self.name + "+" + self.driver
  191. @classmethod
  192. def get_pool_class(cls, url):
  193. return getattr(cls, 'poolclass', pool.QueuePool)
  194. def initialize(self, connection):
  195. try:
  196. self.server_version_info = \
  197. self._get_server_version_info(connection)
  198. except NotImplementedError:
  199. self.server_version_info = None
  200. try:
  201. self.default_schema_name = \
  202. self._get_default_schema_name(connection)
  203. except NotImplementedError:
  204. self.default_schema_name = None
  205. try:
  206. self.default_isolation_level = \
  207. self.get_isolation_level(connection.connection)
  208. except NotImplementedError:
  209. self.default_isolation_level = None
  210. self.returns_unicode_strings = self._check_unicode_returns(connection)
  211. if self.description_encoding is not None and \
  212. self._check_unicode_description(connection):
  213. self._description_decoder = self.description_encoding = None
  214. self.do_rollback(connection.connection)
  215. def on_connect(self):
  216. """return a callable which sets up a newly created DBAPI connection.
  217. This is used to set dialect-wide per-connection options such as
  218. isolation modes, unicode modes, etc.
  219. If a callable is returned, it will be assembled into a pool listener
  220. that receives the direct DBAPI connection, with all wrappers removed.
  221. If None is returned, no listener will be generated.
  222. """
  223. return None
  224. def _check_unicode_returns(self, connection, additional_tests=None):
  225. if util.py2k and not self.supports_unicode_statements:
  226. cast_to = util.binary_type
  227. else:
  228. cast_to = util.text_type
  229. if self.positional:
  230. parameters = self.execute_sequence_format()
  231. else:
  232. parameters = {}
  233. def check_unicode(test):
  234. statement = cast_to(
  235. expression.select([test]).compile(dialect=self))
  236. try:
  237. cursor = connection.connection.cursor()
  238. connection._cursor_execute(cursor, statement, parameters)
  239. row = cursor.fetchone()
  240. cursor.close()
  241. except exc.DBAPIError as de:
  242. # note that _cursor_execute() will have closed the cursor
  243. # if an exception is thrown.
  244. util.warn("Exception attempting to "
  245. "detect unicode returns: %r" % de)
  246. return False
  247. else:
  248. return isinstance(row[0], util.text_type)
  249. tests = [
  250. # detect plain VARCHAR
  251. expression.cast(
  252. expression.literal_column("'test plain returns'"),
  253. sqltypes.VARCHAR(60)
  254. ),
  255. # detect if there's an NVARCHAR type with different behavior
  256. # available
  257. expression.cast(
  258. expression.literal_column("'test unicode returns'"),
  259. sqltypes.Unicode(60)
  260. ),
  261. ]
  262. if additional_tests:
  263. tests += additional_tests
  264. results = set([check_unicode(test) for test in tests])
  265. if results.issuperset([True, False]):
  266. return "conditional"
  267. else:
  268. return results == set([True])
  269. def _check_unicode_description(self, connection):
  270. # all DBAPIs on Py2K return cursor.description as encoded,
  271. # until pypy2.1beta2 with sqlite, so let's just check it -
  272. # it's likely others will start doing this too in Py2k.
  273. if util.py2k and not self.supports_unicode_statements:
  274. cast_to = util.binary_type
  275. else:
  276. cast_to = util.text_type
  277. cursor = connection.connection.cursor()
  278. try:
  279. cursor.execute(
  280. cast_to(
  281. expression.select([
  282. expression.literal_column("'x'").label("some_label")
  283. ]).compile(dialect=self)
  284. )
  285. )
  286. return isinstance(cursor.description[0][0], util.text_type)
  287. finally:
  288. cursor.close()
  289. def type_descriptor(self, typeobj):
  290. """Provide a database-specific :class:`.TypeEngine` object, given
  291. the generic object which comes from the types module.
  292. This method looks for a dictionary called
  293. ``colspecs`` as a class or instance-level variable,
  294. and passes on to :func:`.types.adapt_type`.
  295. """
  296. return sqltypes.adapt_type(typeobj, self.colspecs)
  297. def reflecttable(
  298. self, connection, table, include_columns, exclude_columns, **opts):
  299. insp = reflection.Inspector.from_engine(connection)
  300. return insp.reflecttable(
  301. table, include_columns, exclude_columns, **opts)
  302. def get_pk_constraint(self, conn, table_name, schema=None, **kw):
  303. """Compatibility method, adapts the result of get_primary_keys()
  304. for those dialects which don't implement get_pk_constraint().
  305. """
  306. return {
  307. 'constrained_columns':
  308. self.get_primary_keys(conn, table_name,
  309. schema=schema, **kw)
  310. }
  311. def validate_identifier(self, ident):
  312. if len(ident) > self.max_identifier_length:
  313. raise exc.IdentifierError(
  314. "Identifier '%s' exceeds maximum length of %d characters" %
  315. (ident, self.max_identifier_length)
  316. )
  317. def connect(self, *cargs, **cparams):
  318. return self.dbapi.connect(*cargs, **cparams)
  319. def create_connect_args(self, url):
  320. opts = url.translate_connect_args()
  321. opts.update(url.query)
  322. return [[], opts]
  323. def set_engine_execution_options(self, engine, opts):
  324. if 'isolation_level' in opts:
  325. isolation_level = opts['isolation_level']
  326. @event.listens_for(engine, "engine_connect")
  327. def set_isolation(connection, branch):
  328. if not branch:
  329. self._set_connection_isolation(connection, isolation_level)
  330. if 'schema_translate_map' in opts:
  331. getter = schema._schema_getter(opts['schema_translate_map'])
  332. engine.schema_for_object = getter
  333. @event.listens_for(engine, "engine_connect")
  334. def set_schema_translate_map(connection, branch):
  335. connection.schema_for_object = getter
  336. def set_connection_execution_options(self, connection, opts):
  337. if 'isolation_level' in opts:
  338. self._set_connection_isolation(connection, opts['isolation_level'])
  339. if 'schema_translate_map' in opts:
  340. getter = schema._schema_getter(opts['schema_translate_map'])
  341. connection.schema_for_object = getter
  342. def _set_connection_isolation(self, connection, level):
  343. if connection.in_transaction():
  344. util.warn(
  345. "Connection is already established with a Transaction; "
  346. "setting isolation_level may implicitly rollback or commit "
  347. "the existing transaction, or have no effect until "
  348. "next transaction")
  349. self.set_isolation_level(connection.connection, level)
  350. connection.connection._connection_record.\
  351. finalize_callback.append(self.reset_isolation_level)
  352. def do_begin(self, dbapi_connection):
  353. pass
  354. def do_rollback(self, dbapi_connection):
  355. dbapi_connection.rollback()
  356. def do_commit(self, dbapi_connection):
  357. dbapi_connection.commit()
  358. def do_close(self, dbapi_connection):
  359. dbapi_connection.close()
  360. def create_xid(self):
  361. """Create a random two-phase transaction ID.
  362. This id will be passed to do_begin_twophase(), do_rollback_twophase(),
  363. do_commit_twophase(). Its format is unspecified.
  364. """
  365. return "_sa_%032x" % random.randint(0, 2 ** 128)
  366. def do_savepoint(self, connection, name):
  367. connection.execute(expression.SavepointClause(name))
  368. def do_rollback_to_savepoint(self, connection, name):
  369. connection.execute(expression.RollbackToSavepointClause(name))
  370. def do_release_savepoint(self, connection, name):
  371. connection.execute(expression.ReleaseSavepointClause(name))
  372. def do_executemany(self, cursor, statement, parameters, context=None):
  373. cursor.executemany(statement, parameters)
  374. def do_execute(self, cursor, statement, parameters, context=None):
  375. cursor.execute(statement, parameters)
  376. def do_execute_no_params(self, cursor, statement, context=None):
  377. cursor.execute(statement)
  378. def is_disconnect(self, e, connection, cursor):
  379. return False
  380. def reset_isolation_level(self, dbapi_conn):
  381. # default_isolation_level is read from the first connection
  382. # after the initial set of 'isolation_level', if any, so is
  383. # the configured default of this dialect.
  384. self.set_isolation_level(dbapi_conn, self.default_isolation_level)
  385. class StrCompileDialect(DefaultDialect):
  386. statement_compiler = compiler.StrSQLCompiler
  387. ddl_compiler = compiler.DDLCompiler
  388. type_compiler = compiler.StrSQLTypeCompiler
  389. preparer = compiler.IdentifierPreparer
  390. supports_sequences = True
  391. sequences_optional = True
  392. preexecute_autoincrement_sequences = False
  393. implicit_returning = False
  394. supports_native_boolean = True
  395. supports_simple_order_by_label = True
  396. class DefaultExecutionContext(interfaces.ExecutionContext):
  397. isinsert = False
  398. isupdate = False
  399. isdelete = False
  400. is_crud = False
  401. is_text = False
  402. isddl = False
  403. executemany = False
  404. compiled = None
  405. statement = None
  406. result_column_struct = None
  407. returned_defaults = None
  408. _is_implicit_returning = False
  409. _is_explicit_returning = False
  410. # a hook for SQLite's translation of
  411. # result column names
  412. _translate_colname = None
  413. @classmethod
  414. def _init_ddl(cls, dialect, connection, dbapi_connection, compiled_ddl):
  415. """Initialize execution context for a DDLElement construct."""
  416. self = cls.__new__(cls)
  417. self.root_connection = connection
  418. self._dbapi_connection = dbapi_connection
  419. self.dialect = connection.dialect
  420. self.compiled = compiled = compiled_ddl
  421. self.isddl = True
  422. self.execution_options = compiled.execution_options
  423. if connection._execution_options:
  424. self.execution_options = dict(self.execution_options)
  425. self.execution_options.update(connection._execution_options)
  426. if not dialect.supports_unicode_statements:
  427. self.unicode_statement = util.text_type(compiled)
  428. self.statement = dialect._encoder(self.unicode_statement)[0]
  429. else:
  430. self.statement = self.unicode_statement = util.text_type(compiled)
  431. self.cursor = self.create_cursor()
  432. self.compiled_parameters = []
  433. if dialect.positional:
  434. self.parameters = [dialect.execute_sequence_format()]
  435. else:
  436. self.parameters = [{}]
  437. return self
  438. @classmethod
  439. def _init_compiled(cls, dialect, connection, dbapi_connection,
  440. compiled, parameters):
  441. """Initialize execution context for a Compiled construct."""
  442. self = cls.__new__(cls)
  443. self.root_connection = connection
  444. self._dbapi_connection = dbapi_connection
  445. self.dialect = connection.dialect
  446. self.compiled = compiled
  447. # this should be caught in the engine before
  448. # we get here
  449. assert compiled.can_execute
  450. self.execution_options = compiled.execution_options.union(
  451. connection._execution_options)
  452. self.result_column_struct = (
  453. compiled._result_columns, compiled._ordered_columns,
  454. compiled._textual_ordered_columns)
  455. self.unicode_statement = util.text_type(compiled)
  456. if not dialect.supports_unicode_statements:
  457. self.statement = self.unicode_statement.encode(
  458. self.dialect.encoding)
  459. else:
  460. self.statement = self.unicode_statement
  461. self.isinsert = compiled.isinsert
  462. self.isupdate = compiled.isupdate
  463. self.isdelete = compiled.isdelete
  464. self.is_text = compiled.isplaintext
  465. if not parameters:
  466. self.compiled_parameters = [compiled.construct_params()]
  467. else:
  468. self.compiled_parameters = \
  469. [compiled.construct_params(m, _group_number=grp) for
  470. grp, m in enumerate(parameters)]
  471. self.executemany = len(parameters) > 1
  472. self.cursor = self.create_cursor()
  473. if self.isinsert or self.isupdate or self.isdelete:
  474. self.is_crud = True
  475. self._is_explicit_returning = bool(compiled.statement._returning)
  476. self._is_implicit_returning = bool(
  477. compiled.returning and not compiled.statement._returning)
  478. if self.compiled.insert_prefetch or self.compiled.update_prefetch:
  479. if self.executemany:
  480. self._process_executemany_defaults()
  481. else:
  482. self._process_executesingle_defaults()
  483. processors = compiled._bind_processors
  484. # Convert the dictionary of bind parameter values
  485. # into a dict or list to be sent to the DBAPI's
  486. # execute() or executemany() method.
  487. parameters = []
  488. if dialect.positional:
  489. for compiled_params in self.compiled_parameters:
  490. param = []
  491. for key in self.compiled.positiontup:
  492. if key in processors:
  493. param.append(processors[key](compiled_params[key]))
  494. else:
  495. param.append(compiled_params[key])
  496. parameters.append(dialect.execute_sequence_format(param))
  497. else:
  498. encode = not dialect.supports_unicode_statements
  499. for compiled_params in self.compiled_parameters:
  500. if encode:
  501. param = dict(
  502. (
  503. dialect._encoder(key)[0],
  504. processors[key](compiled_params[key])
  505. if key in processors
  506. else compiled_params[key]
  507. )
  508. for key in compiled_params
  509. )
  510. else:
  511. param = dict(
  512. (
  513. key,
  514. processors[key](compiled_params[key])
  515. if key in processors
  516. else compiled_params[key]
  517. )
  518. for key in compiled_params
  519. )
  520. parameters.append(param)
  521. self.parameters = dialect.execute_sequence_format(parameters)
  522. return self
  523. @classmethod
  524. def _init_statement(cls, dialect, connection, dbapi_connection,
  525. statement, parameters):
  526. """Initialize execution context for a string SQL statement."""
  527. self = cls.__new__(cls)
  528. self.root_connection = connection
  529. self._dbapi_connection = dbapi_connection
  530. self.dialect = connection.dialect
  531. self.is_text = True
  532. # plain text statement
  533. self.execution_options = connection._execution_options
  534. if not parameters:
  535. if self.dialect.positional:
  536. self.parameters = [dialect.execute_sequence_format()]
  537. else:
  538. self.parameters = [{}]
  539. elif isinstance(parameters[0], dialect.execute_sequence_format):
  540. self.parameters = parameters
  541. elif isinstance(parameters[0], dict):
  542. if dialect.supports_unicode_statements:
  543. self.parameters = parameters
  544. else:
  545. self.parameters = [
  546. dict((dialect._encoder(k)[0], d[k]) for k in d)
  547. for d in parameters
  548. ] or [{}]
  549. else:
  550. self.parameters = [dialect.execute_sequence_format(p)
  551. for p in parameters]
  552. self.executemany = len(parameters) > 1
  553. if not dialect.supports_unicode_statements and \
  554. isinstance(statement, util.text_type):
  555. self.unicode_statement = statement
  556. self.statement = dialect._encoder(statement)[0]
  557. else:
  558. self.statement = self.unicode_statement = statement
  559. self.cursor = self.create_cursor()
  560. return self
  561. @classmethod
  562. def _init_default(cls, dialect, connection, dbapi_connection):
  563. """Initialize execution context for a ColumnDefault construct."""
  564. self = cls.__new__(cls)
  565. self.root_connection = connection
  566. self._dbapi_connection = dbapi_connection
  567. self.dialect = connection.dialect
  568. self.execution_options = connection._execution_options
  569. self.cursor = self.create_cursor()
  570. return self
  571. @util.memoized_property
  572. def engine(self):
  573. return self.root_connection.engine
  574. @util.memoized_property
  575. def postfetch_cols(self):
  576. return self.compiled.postfetch
  577. @util.memoized_property
  578. def prefetch_cols(self):
  579. if self.isinsert:
  580. return self.compiled.insert_prefetch
  581. elif self.isupdate:
  582. return self.compiled.update_prefetch
  583. else:
  584. return ()
  585. @util.memoized_property
  586. def returning_cols(self):
  587. self.compiled.returning
  588. @util.memoized_property
  589. def no_parameters(self):
  590. return self.execution_options.get("no_parameters", False)
  591. @util.memoized_property
  592. def should_autocommit(self):
  593. autocommit = self.execution_options.get('autocommit',
  594. not self.compiled and
  595. self.statement and
  596. expression.PARSE_AUTOCOMMIT
  597. or False)
  598. if autocommit is expression.PARSE_AUTOCOMMIT:
  599. return self.should_autocommit_text(self.unicode_statement)
  600. else:
  601. return autocommit
  602. def _execute_scalar(self, stmt, type_):
  603. """Execute a string statement on the current cursor, returning a
  604. scalar result.
  605. Used to fire off sequences, default phrases, and "select lastrowid"
  606. types of statements individually or in the context of a parent INSERT
  607. or UPDATE statement.
  608. """
  609. conn = self.root_connection
  610. if isinstance(stmt, util.text_type) and \
  611. not self.dialect.supports_unicode_statements:
  612. stmt = self.dialect._encoder(stmt)[0]
  613. if self.dialect.positional:
  614. default_params = self.dialect.execute_sequence_format()
  615. else:
  616. default_params = {}
  617. conn._cursor_execute(self.cursor, stmt, default_params, context=self)
  618. r = self.cursor.fetchone()[0]
  619. if type_ is not None:
  620. # apply type post processors to the result
  621. proc = type_._cached_result_processor(
  622. self.dialect,
  623. self.cursor.description[0][1]
  624. )
  625. if proc:
  626. return proc(r)
  627. return r
  628. @property
  629. def connection(self):
  630. return self.root_connection._branch()
  631. def should_autocommit_text(self, statement):
  632. return AUTOCOMMIT_REGEXP.match(statement)
  633. def _use_server_side_cursor(self):
  634. if not self.dialect.supports_server_side_cursors:
  635. return False
  636. if self.dialect.server_side_cursors:
  637. use_server_side = \
  638. self.execution_options.get('stream_results', True) and (
  639. (self.compiled and isinstance(self.compiled.statement,
  640. expression.Selectable)
  641. or
  642. (
  643. (not self.compiled or
  644. isinstance(self.compiled.statement,
  645. expression.TextClause))
  646. and self.statement and SERVER_SIDE_CURSOR_RE.match(
  647. self.statement))
  648. )
  649. )
  650. else:
  651. use_server_side = \
  652. self.execution_options.get('stream_results', False)
  653. return use_server_side
  654. def create_cursor(self):
  655. if self._use_server_side_cursor():
  656. self._is_server_side = True
  657. return self.create_server_side_cursor()
  658. else:
  659. self._is_server_side = False
  660. return self._dbapi_connection.cursor()
  661. def create_server_side_cursor(self):
  662. raise NotImplementedError()
  663. def pre_exec(self):
  664. pass
  665. def post_exec(self):
  666. pass
  667. def get_result_processor(self, type_, colname, coltype):
  668. """Return a 'result processor' for a given type as present in
  669. cursor.description.
  670. This has a default implementation that dialects can override
  671. for context-sensitive result type handling.
  672. """
  673. return type_._cached_result_processor(self.dialect, coltype)
  674. def get_lastrowid(self):
  675. """return self.cursor.lastrowid, or equivalent, after an INSERT.
  676. This may involve calling special cursor functions,
  677. issuing a new SELECT on the cursor (or a new one),
  678. or returning a stored value that was
  679. calculated within post_exec().
  680. This function will only be called for dialects
  681. which support "implicit" primary key generation,
  682. keep preexecute_autoincrement_sequences set to False,
  683. and when no explicit id value was bound to the
  684. statement.
  685. The function is called once, directly after
  686. post_exec() and before the transaction is committed
  687. or ResultProxy is generated. If the post_exec()
  688. method assigns a value to `self._lastrowid`, the
  689. value is used in place of calling get_lastrowid().
  690. Note that this method is *not* equivalent to the
  691. ``lastrowid`` method on ``ResultProxy``, which is a
  692. direct proxy to the DBAPI ``lastrowid`` accessor
  693. in all cases.
  694. """
  695. return self.cursor.lastrowid
  696. def handle_dbapi_exception(self, e):
  697. pass
  698. def get_result_proxy(self):
  699. if self._is_server_side:
  700. return result.BufferedRowResultProxy(self)
  701. else:
  702. return result.ResultProxy(self)
  703. @property
  704. def rowcount(self):
  705. return self.cursor.rowcount
  706. def supports_sane_rowcount(self):
  707. return self.dialect.supports_sane_rowcount
  708. def supports_sane_multi_rowcount(self):
  709. return self.dialect.supports_sane_multi_rowcount
  710. def _setup_crud_result_proxy(self):
  711. if self.isinsert and \
  712. not self.executemany:
  713. if not self._is_implicit_returning and \
  714. not self.compiled.inline and \
  715. self.dialect.postfetch_lastrowid:
  716. self._setup_ins_pk_from_lastrowid()
  717. elif not self._is_implicit_returning:
  718. self._setup_ins_pk_from_empty()
  719. result = self.get_result_proxy()
  720. if self.isinsert:
  721. if self._is_implicit_returning:
  722. row = result.fetchone()
  723. self.returned_defaults = row
  724. self._setup_ins_pk_from_implicit_returning(row)
  725. result._soft_close()
  726. result._metadata = None
  727. elif not self._is_explicit_returning:
  728. result._soft_close()
  729. result._metadata = None
  730. elif self.isupdate and self._is_implicit_returning:
  731. row = result.fetchone()
  732. self.returned_defaults = row
  733. result._soft_close()
  734. result._metadata = None
  735. elif result._metadata is None:
  736. # no results, get rowcount
  737. # (which requires open cursor on some drivers
  738. # such as kintersbasdb, mxodbc)
  739. result.rowcount
  740. result._soft_close()
  741. return result
  742. def _setup_ins_pk_from_lastrowid(self):
  743. key_getter = self.compiled._key_getters_for_crud_column[2]
  744. table = self.compiled.statement.table
  745. compiled_params = self.compiled_parameters[0]
  746. lastrowid = self.get_lastrowid()
  747. if lastrowid is not None:
  748. autoinc_col = table._autoincrement_column
  749. if autoinc_col is not None:
  750. # apply type post processors to the lastrowid
  751. proc = autoinc_col.type._cached_result_processor(
  752. self.dialect, None)
  753. if proc is not None:
  754. lastrowid = proc(lastrowid)
  755. self.inserted_primary_key = [
  756. lastrowid if c is autoinc_col else
  757. compiled_params.get(key_getter(c), None)
  758. for c in table.primary_key
  759. ]
  760. else:
  761. # don't have a usable lastrowid, so
  762. # do the same as _setup_ins_pk_from_empty
  763. self.inserted_primary_key = [
  764. compiled_params.get(key_getter(c), None)
  765. for c in table.primary_key
  766. ]
  767. def _setup_ins_pk_from_empty(self):
  768. key_getter = self.compiled._key_getters_for_crud_column[2]
  769. table = self.compiled.statement.table
  770. compiled_params = self.compiled_parameters[0]
  771. self.inserted_primary_key = [
  772. compiled_params.get(key_getter(c), None)
  773. for c in table.primary_key
  774. ]
  775. def _setup_ins_pk_from_implicit_returning(self, row):
  776. if row is None:
  777. self.inserted_primary_key = None
  778. return
  779. key_getter = self.compiled._key_getters_for_crud_column[2]
  780. table = self.compiled.statement.table
  781. compiled_params = self.compiled_parameters[0]
  782. self.inserted_primary_key = [
  783. row[col] if value is None else value
  784. for col, value in [
  785. (col, compiled_params.get(key_getter(col), None))
  786. for col in table.primary_key
  787. ]
  788. ]
  789. def lastrow_has_defaults(self):
  790. return (self.isinsert or self.isupdate) and \
  791. bool(self.compiled.postfetch)
  792. def set_input_sizes(self, translate=None, exclude_types=None):
  793. """Given a cursor and ClauseParameters, call the appropriate
  794. style of ``setinputsizes()`` on the cursor, using DB-API types
  795. from the bind parameter's ``TypeEngine`` objects.
  796. This method only called by those dialects which require it,
  797. currently cx_oracle.
  798. """
  799. if not hasattr(self.compiled, 'bind_names'):
  800. return
  801. types = dict(
  802. (self.compiled.bind_names[bindparam], bindparam.type)
  803. for bindparam in self.compiled.bind_names)
  804. if self.dialect.positional:
  805. inputsizes = []
  806. for key in self.compiled.positiontup:
  807. typeengine = types[key]
  808. dbtype = typeengine.dialect_impl(self.dialect).\
  809. get_dbapi_type(self.dialect.dbapi)
  810. if dbtype is not None and \
  811. (not exclude_types or dbtype not in exclude_types):
  812. inputsizes.append(dbtype)
  813. try:
  814. self.cursor.setinputsizes(*inputsizes)
  815. except BaseException as e:
  816. self.root_connection._handle_dbapi_exception(
  817. e, None, None, None, self)
  818. else:
  819. inputsizes = {}
  820. for key in self.compiled.bind_names.values():
  821. typeengine = types[key]
  822. dbtype = typeengine.dialect_impl(self.dialect).\
  823. get_dbapi_type(self.dialect.dbapi)
  824. if dbtype is not None and \
  825. (not exclude_types or dbtype not in exclude_types):
  826. if translate:
  827. key = translate.get(key, key)
  828. if not self.dialect.supports_unicode_binds:
  829. key = self.dialect._encoder(key)[0]
  830. inputsizes[key] = dbtype
  831. try:
  832. self.cursor.setinputsizes(**inputsizes)
  833. except BaseException as e:
  834. self.root_connection._handle_dbapi_exception(
  835. e, None, None, None, self)
  836. def _exec_default(self, default, type_):
  837. if default.is_sequence:
  838. return self.fire_sequence(default, type_)
  839. elif default.is_callable:
  840. return default.arg(self)
  841. elif default.is_clause_element:
  842. # TODO: expensive branching here should be
  843. # pulled into _exec_scalar()
  844. conn = self.connection
  845. c = expression.select([default.arg]).compile(bind=conn)
  846. return conn._execute_compiled(c, (), {}).scalar()
  847. else:
  848. return default.arg
  849. def get_insert_default(self, column):
  850. if column.default is None:
  851. return None
  852. else:
  853. return self._exec_default(column.default, column.type)
  854. def get_update_default(self, column):
  855. if column.onupdate is None:
  856. return None
  857. else:
  858. return self._exec_default(column.onupdate, column.type)
  859. def _process_executemany_defaults(self):
  860. key_getter = self.compiled._key_getters_for_crud_column[2]
  861. scalar_defaults = {}
  862. insert_prefetch = self.compiled.insert_prefetch
  863. update_prefetch = self.compiled.update_prefetch
  864. # pre-determine scalar Python-side defaults
  865. # to avoid many calls of get_insert_default()/
  866. # get_update_default()
  867. for c in insert_prefetch:
  868. if c.default and c.default.is_scalar:
  869. scalar_defaults[c] = c.default.arg
  870. for c in update_prefetch:
  871. if c.onupdate and c.onupdate.is_scalar:
  872. scalar_defaults[c] = c.onupdate.arg
  873. for param in self.compiled_parameters:
  874. self.current_parameters = param
  875. for c in insert_prefetch:
  876. if c in scalar_defaults:
  877. val = scalar_defaults[c]
  878. else:
  879. val = self.get_insert_default(c)
  880. if val is not None:
  881. param[key_getter(c)] = val
  882. for c in update_prefetch:
  883. if c in scalar_defaults:
  884. val = scalar_defaults[c]
  885. else:
  886. val = self.get_update_default(c)
  887. if val is not None:
  888. param[key_getter(c)] = val
  889. del self.current_parameters
  890. def _process_executesingle_defaults(self):
  891. key_getter = self.compiled._key_getters_for_crud_column[2]
  892. self.current_parameters = compiled_parameters = \
  893. self.compiled_parameters[0]
  894. for c in self.compiled.insert_prefetch:
  895. if c.default and \
  896. not c.default.is_sequence and c.default.is_scalar:
  897. val = c.default.arg
  898. else:
  899. val = self.get_insert_default(c)
  900. if val is not None:
  901. compiled_parameters[key_getter(c)] = val
  902. for c in self.compiled.update_prefetch:
  903. val = self.get_update_default(c)
  904. if val is not None:
  905. compiled_parameters[key_getter(c)] = val
  906. del self.current_parameters
  907. DefaultDialect.execution_ctx_cls = DefaultExecutionContext