diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-10-15 18:18:03 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-10-16 14:28:04 -0400 |
| commit | 87c24c498cb660e7a8d7d4dd5f630b967f79d3c8 (patch) | |
| tree | 06f1113c0db30fb1471ac74e69af5a67976b1246 /lib/sqlalchemy/engine/default.py | |
| parent | 41d3e16773e84692b6625ccb67da204b5362d9c3 (diff) | |
| download | sqlalchemy-87c24c498cb660e7a8d7d4dd5f630b967f79d3c8.tar.gz | |
Genericize setinputsizes and support pyodbc
Reworked the "setinputsizes()" set of dialect hooks to be correctly
extensible for any arbirary DBAPI, by allowing dialects individual hooks
that may invoke cursor.setinputsizes() in the appropriate style for that
DBAPI. In particular this is intended to support pyodbc's style of usage
which is fundamentally different from that of cx_Oracle. Added support
for pyodbc.
Fixes: #5649
Change-Id: I9f1794f8368bf3663a286932cfe3992dae244a10
Diffstat (limited to 'lib/sqlalchemy/engine/default.py')
| -rw-r--r-- | lib/sqlalchemy/engine/default.py | 132 |
1 files changed, 52 insertions, 80 deletions
diff --git a/lib/sqlalchemy/engine/default.py b/lib/sqlalchemy/engine/default.py index ff29c3b9d..d63cb4add 100644 --- a/lib/sqlalchemy/engine/default.py +++ b/lib/sqlalchemy/engine/default.py @@ -56,6 +56,7 @@ class DefaultDialect(interfaces.Dialect): supports_alter = True supports_comments = False inline_comments = False + use_setinputsizes = False # the first value we'd get for an autoincrement # column. @@ -782,6 +783,9 @@ class DefaultExecutionContext(interfaces.ExecutionContext): returned_default_rows = None execution_options = util.immutabledict() + include_set_input_sizes = None + exclude_set_input_sizes = None + cursor_fetch_strategy = _cursor._DEFAULT_FETCH cache_stats = None @@ -1477,9 +1481,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext): self.compiled.postfetch ) - def set_input_sizes( - self, translate=None, include_types=None, exclude_types=None - ): + def _set_input_sizes(self): """Given a cursor and ClauseParameters, call the appropriate style of ``setinputsizes()`` on the cursor, using DB-API types from the bind parameter's ``TypeEngine`` objects. @@ -1488,14 +1490,14 @@ class DefaultExecutionContext(interfaces.ExecutionContext): currently cx_oracle. """ - if self.isddl: - return None + if self.isddl or self.is_text: + return inputsizes = self.compiled._get_set_input_sizes_lookup( - translate=translate, - include_types=include_types, - exclude_types=exclude_types, + include_types=self.include_set_input_sizes, + exclude_types=self.exclude_set_input_sizes, ) + if inputsizes is None: return @@ -1506,82 +1508,52 @@ class DefaultExecutionContext(interfaces.ExecutionContext): ) if self.dialect.positional: - positional_inputsizes = [] - for key in self.compiled.positiontup: - bindparam = self.compiled.binds[key] - if bindparam in self.compiled.literal_execute_params: - continue - - if key in self._expanded_parameters: - if bindparam.type._is_tuple_type: - num = len(bindparam.type.types) - dbtypes = inputsizes[bindparam] - positional_inputsizes.extend( - [ - dbtypes[idx % num] - for idx, key in enumerate( - self._expanded_parameters[key] - ) - ] - ) - else: - dbtype = inputsizes.get(bindparam, None) - positional_inputsizes.extend( - dbtype for dbtype in self._expanded_parameters[key] - ) - else: - dbtype = inputsizes[bindparam] - positional_inputsizes.append(dbtype) - try: - self.cursor.setinputsizes(*positional_inputsizes) - except BaseException as e: - self.root_connection._handle_dbapi_exception( - e, None, None, None, self - ) + items = [ + (key, self.compiled.binds[key]) + for key in self.compiled.positiontup + ] else: - keyword_inputsizes = {} - for bindparam, key in self.compiled.bind_names.items(): - if bindparam in self.compiled.literal_execute_params: - continue - - if key in self._expanded_parameters: - if bindparam.type._is_tuple_type: - num = len(bindparam.type.types) - dbtypes = inputsizes[bindparam] - keyword_inputsizes.update( - [ - (key, dbtypes[idx % num]) - for idx, key in enumerate( - self._expanded_parameters[key] - ) - ] + items = [ + (key, bindparam) + for bindparam, key in self.compiled.bind_names.items() + ] + + generic_inputsizes = [] + for key, bindparam in items: + if bindparam in self.compiled.literal_execute_params: + continue + + if key in self._expanded_parameters: + if bindparam.type._is_tuple_type: + num = len(bindparam.type.types) + dbtypes = inputsizes[bindparam] + generic_inputsizes.extend( + ( + paramname, + dbtypes[idx % num], + bindparam.type.types[idx % num], ) - else: - dbtype = inputsizes.get(bindparam, None) - if dbtype is not None: - keyword_inputsizes.update( - (expand_key, dbtype) - for expand_key in self._expanded_parameters[ - key - ] - ) + for idx, paramname in enumerate( + self._expanded_parameters[key] + ) + ) else: dbtype = inputsizes.get(bindparam, None) - if dbtype is not None: - if translate: - # TODO: this part won't work w/ the - # expanded_parameters feature, e.g. for cx_oracle - # quoted bound names - key = translate.get(key, key) - if not self.dialect.supports_unicode_binds: - key = self.dialect._encoder(key)[0] - keyword_inputsizes[key] = dbtype - try: - self.cursor.setinputsizes(**keyword_inputsizes) - except BaseException as e: - self.root_connection._handle_dbapi_exception( - e, None, None, None, self - ) + generic_inputsizes.extend( + (paramname, dbtype, bindparam.type) + for paramname in self._expanded_parameters[key] + ) + else: + dbtype = inputsizes.get(bindparam, None) + generic_inputsizes.append((key, dbtype, bindparam.type)) + try: + self.dialect.do_set_input_sizes( + self.cursor, generic_inputsizes, self + ) + except BaseException as e: + self.root_connection._handle_dbapi_exception( + e, None, None, None, self + ) def _exec_default(self, column, default, type_): if default.is_sequence: |
