update sqlalchemy

This commit is contained in:
j 2016-02-22 16:43:36 +05:30
commit 3b436646a2
362 changed files with 37720 additions and 11021 deletions

View file

@ -1,5 +1,5 @@
# engine/default.py
# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@ -61,14 +61,13 @@ class DefaultDialect(interfaces.Dialect):
engine_config_types = util.immutabledict([
('convert_unicode', util.bool_or_str('force')),
('pool_timeout', int),
('pool_timeout', util.asint),
('echo', util.bool_or_str('debug')),
('echo_pool', util.bool_or_str('debug')),
('pool_recycle', int),
('pool_size', int),
('max_overflow', int),
('pool_threadlocal', bool),
('use_native_unicode', bool),
('pool_recycle', util.asint),
('pool_size', util.asint),
('max_overflow', util.asint),
('pool_threadlocal', util.asbool),
])
# if the NUMERIC type
@ -157,6 +156,15 @@ class DefaultDialect(interfaces.Dialect):
reflection_options = ()
dbapi_exception_translation_map = util.immutabledict()
"""mapping used in the extremely unusual case that a DBAPI's
published exceptions don't actually have the __name__ that they
are linked towards.
.. versionadded:: 1.0.5
"""
def __init__(self, convert_unicode=False,
encoding='utf-8', paramstyle=None, dbapi=None,
implicit_returning=None,
@ -395,6 +403,12 @@ class DefaultDialect(interfaces.Dialect):
self._set_connection_isolation(connection, opts['isolation_level'])
def _set_connection_isolation(self, connection, level):
if connection.in_transaction():
util.warn(
"Connection is already established with a Transaction; "
"setting isolation_level may implicitly rollback or commit "
"the existing transaction, or have no effect until "
"next transaction")
self.set_isolation_level(connection.connection, level)
connection.connection._connection_record.\
finalize_callback.append(self.reset_isolation_level)
@ -452,14 +466,13 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
isinsert = False
isupdate = False
isdelete = False
is_crud = False
is_text = False
isddl = False
executemany = False
result_map = None
compiled = None
statement = None
postfetch_cols = None
prefetch_cols = None
returning_cols = None
result_column_struct = None
_is_implicit_returning = False
_is_explicit_returning = False
@ -472,10 +485,9 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
"""Initialize execution context for a DDLElement construct."""
self = cls.__new__(cls)
self.dialect = dialect
self.root_connection = connection
self._dbapi_connection = dbapi_connection
self.engine = connection.engine
self.dialect = connection.dialect
self.compiled = compiled = compiled_ddl
self.isddl = True
@ -507,25 +519,20 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
"""Initialize execution context for a Compiled construct."""
self = cls.__new__(cls)
self.dialect = dialect
self.root_connection = connection
self._dbapi_connection = dbapi_connection
self.engine = connection.engine
self.dialect = connection.dialect
self.compiled = compiled
if not compiled.can_execute:
raise exc.ArgumentError("Not an executable clause")
self.execution_options = compiled.statement._execution_options
if connection._execution_options:
self.execution_options = dict(self.execution_options)
self.execution_options.update(connection._execution_options)
self.execution_options = compiled.statement._execution_options.union(
connection._execution_options)
# compiled clauseelement. process bind params, process table defaults,
# track collections used by ResultProxy to target and process results
self.result_map = compiled.result_map
self.result_column_struct = (
compiled._result_columns, compiled._ordered_columns)
self.unicode_statement = util.text_type(compiled)
if not dialect.supports_unicode_statements:
@ -537,11 +544,7 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
self.isinsert = compiled.isinsert
self.isupdate = compiled.isupdate
self.isdelete = compiled.isdelete
if self.isinsert or self.isupdate or self.isdelete:
self._is_explicit_returning = bool(compiled.statement._returning)
self._is_implicit_returning = bool(
compiled.returning and not compiled.statement._returning)
self.is_text = compiled.isplaintext
if not parameters:
self.compiled_parameters = [compiled.construct_params()]
@ -553,11 +556,19 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
self.executemany = len(parameters) > 1
self.cursor = self.create_cursor()
if self.isinsert or self.isupdate:
self.postfetch_cols = self.compiled.postfetch
self.prefetch_cols = self.compiled.prefetch
self.returning_cols = self.compiled.returning
self.__process_defaults()
if self.isinsert or self.isupdate or self.isdelete:
self.is_crud = True
self._is_explicit_returning = bool(compiled.statement._returning)
self._is_implicit_returning = bool(
compiled.returning and not compiled.statement._returning)
if not self.isdelete:
if self.compiled.prefetch:
if self.executemany:
self._process_executemany_defaults()
else:
self._process_executesingle_defaults()
processors = compiled._bind_processors
@ -577,21 +588,28 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
else:
encode = not dialect.supports_unicode_statements
for compiled_params in self.compiled_parameters:
param = {}
if encode:
for key in compiled_params:
if key in processors:
param[dialect._encoder(key)[0]] = \
processors[key](compiled_params[key])
else:
param[dialect._encoder(key)[0]] = \
compiled_params[key]
param = dict(
(
dialect._encoder(key)[0],
processors[key](compiled_params[key])
if key in processors
else compiled_params[key]
)
for key in compiled_params
)
else:
for key in compiled_params:
if key in processors:
param[key] = processors[key](compiled_params[key])
else:
param[key] = compiled_params[key]
param = dict(
(
key,
processors[key](compiled_params[key])
if key in processors
else compiled_params[key]
)
for key in compiled_params
)
parameters.append(param)
self.parameters = dialect.execute_sequence_format(parameters)
@ -603,10 +621,10 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
"""Initialize execution context for a string SQL statement."""
self = cls.__new__(cls)
self.dialect = dialect
self.root_connection = connection
self._dbapi_connection = dbapi_connection
self.engine = connection.engine
self.dialect = connection.dialect
self.is_text = True
# plain text statement
self.execution_options = connection._execution_options
@ -647,21 +665,32 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
"""Initialize execution context for a ColumnDefault construct."""
self = cls.__new__(cls)
self.dialect = dialect
self.root_connection = connection
self._dbapi_connection = dbapi_connection
self.engine = connection.engine
self.dialect = connection.dialect
self.execution_options = connection._execution_options
self.cursor = self.create_cursor()
return self
@util.memoized_property
def no_parameters(self):
return self.execution_options.get("no_parameters", False)
def engine(self):
return self.root_connection.engine
@util.memoized_property
def is_crud(self):
return self.isinsert or self.isupdate or self.isdelete
def postfetch_cols(self):
return self.compiled.postfetch
@util.memoized_property
def prefetch_cols(self):
return self.compiled.prefetch
@util.memoized_property
def returning_cols(self):
self.compiled.returning
@util.memoized_property
def no_parameters(self):
return self.execution_options.get("no_parameters", False)
@util.memoized_property
def should_autocommit(self):
@ -778,16 +807,51 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
def supports_sane_multi_rowcount(self):
return self.dialect.supports_sane_multi_rowcount
def post_insert(self):
if not self._is_implicit_returning and \
not self._is_explicit_returning and \
not self.compiled.inline and \
self.dialect.postfetch_lastrowid and \
(not self.inserted_primary_key or
None in self.inserted_primary_key):
def _setup_crud_result_proxy(self):
if self.isinsert and \
not self.executemany:
if not self._is_implicit_returning and \
not self.compiled.inline and \
self.dialect.postfetch_lastrowid:
table = self.compiled.statement.table
lastrowid = self.get_lastrowid()
self._setup_ins_pk_from_lastrowid()
elif not self._is_implicit_returning:
self._setup_ins_pk_from_empty()
result = self.get_result_proxy()
if self.isinsert:
if self._is_implicit_returning:
row = result.fetchone()
self.returned_defaults = row
self._setup_ins_pk_from_implicit_returning(row)
result._soft_close(_autoclose_connection=False)
result._metadata = None
elif not self._is_explicit_returning:
result._soft_close(_autoclose_connection=False)
result._metadata = None
elif self.isupdate and self._is_implicit_returning:
row = result.fetchone()
self.returned_defaults = row
result._soft_close(_autoclose_connection=False)
result._metadata = None
elif result._metadata is None:
# no results, get rowcount
# (which requires open cursor on some drivers
# such as kintersbasdb, mxodbc)
result.rowcount
result._soft_close(_autoclose_connection=False)
return result
def _setup_ins_pk_from_lastrowid(self):
key_getter = self.compiled._key_getters_for_crud_column[2]
table = self.compiled.statement.table
compiled_params = self.compiled_parameters[0]
lastrowid = self.get_lastrowid()
if lastrowid is not None:
autoinc_col = table._autoincrement_column
if autoinc_col is not None:
# apply type post processors to the lastrowid
@ -795,35 +859,44 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
self.dialect, None)
if proc is not None:
lastrowid = proc(lastrowid)
self.inserted_primary_key = [
lastrowid if c is autoinc_col else v
for c, v in zip(
table.primary_key,
self.inserted_primary_key)
lastrowid if c is autoinc_col else
compiled_params.get(key_getter(c), None)
for c in table.primary_key
]
else:
# don't have a usable lastrowid, so
# do the same as _setup_ins_pk_from_empty
self.inserted_primary_key = [
compiled_params.get(key_getter(c), None)
for c in table.primary_key
]
def _fetch_implicit_returning(self, resultproxy):
def _setup_ins_pk_from_empty(self):
key_getter = self.compiled._key_getters_for_crud_column[2]
table = self.compiled.statement.table
row = resultproxy.fetchone()
compiled_params = self.compiled_parameters[0]
self.inserted_primary_key = [
compiled_params.get(key_getter(c), None)
for c in table.primary_key
]
ipk = []
for c, v in zip(table.primary_key, self.inserted_primary_key):
if v is not None:
ipk.append(v)
else:
ipk.append(row[c])
def _setup_ins_pk_from_implicit_returning(self, row):
key_getter = self.compiled._key_getters_for_crud_column[2]
table = self.compiled.statement.table
compiled_params = self.compiled_parameters[0]
self.inserted_primary_key = ipk
self.returned_defaults = row
def _fetch_implicit_update_returning(self, resultproxy):
row = resultproxy.fetchone()
self.returned_defaults = row
self.inserted_primary_key = [
row[col] if value is None else value
for col, value in [
(col, compiled_params.get(key_getter(col), None))
for col in table.primary_key
]
]
def lastrow_has_defaults(self):
return (self.isinsert or self.isupdate) and \
bool(self.postfetch_cols)
bool(self.compiled.postfetch)
def set_input_sizes(self, translate=None, exclude_types=None):
"""Given a cursor and ClauseParameters, call the appropriate
@ -901,58 +974,53 @@ class DefaultExecutionContext(interfaces.ExecutionContext):
else:
return self._exec_default(column.onupdate, column.type)
def __process_defaults(self):
"""Generate default values for compiled insert/update statements,
and generate inserted_primary_key collection.
"""
def _process_executemany_defaults(self):
key_getter = self.compiled._key_getters_for_crud_column[2]
if self.executemany:
if len(self.compiled.prefetch):
scalar_defaults = {}
prefetch = self.compiled.prefetch
scalar_defaults = {}
# pre-determine scalar Python-side defaults
# to avoid many calls of get_insert_default()/
# get_update_default()
for c in self.prefetch_cols:
if self.isinsert and c.default and c.default.is_scalar:
scalar_defaults[c] = c.default.arg
elif self.isupdate and c.onupdate and c.onupdate.is_scalar:
scalar_defaults[c] = c.onupdate.arg
# pre-determine scalar Python-side defaults
# to avoid many calls of get_insert_default()/
# get_update_default()
for c in prefetch:
if self.isinsert and c.default and c.default.is_scalar:
scalar_defaults[c] = c.default.arg
elif self.isupdate and c.onupdate and c.onupdate.is_scalar:
scalar_defaults[c] = c.onupdate.arg
for param in self.compiled_parameters:
self.current_parameters = param
for c in self.prefetch_cols:
if c in scalar_defaults:
val = scalar_defaults[c]
elif self.isinsert:
val = self.get_insert_default(c)
else:
val = self.get_update_default(c)
if val is not None:
param[key_getter(c)] = val
del self.current_parameters
else:
self.current_parameters = compiled_parameters = \
self.compiled_parameters[0]
for c in self.compiled.prefetch:
if self.isinsert:
for param in self.compiled_parameters:
self.current_parameters = param
for c in prefetch:
if c in scalar_defaults:
val = scalar_defaults[c]
elif self.isinsert:
val = self.get_insert_default(c)
else:
val = self.get_update_default(c)
if val is not None:
compiled_parameters[key_getter(c)] = val
del self.current_parameters
param[key_getter(c)] = val
del self.current_parameters
def _process_executesingle_defaults(self):
key_getter = self.compiled._key_getters_for_crud_column[2]
prefetch = self.compiled.prefetch
self.current_parameters = compiled_parameters = \
self.compiled_parameters[0]
for c in prefetch:
if self.isinsert:
self.inserted_primary_key = [
self.compiled_parameters[0].get(key_getter(c), None)
for c in self.compiled.
statement.table.primary_key
]
if c.default and \
not c.default.is_sequence and c.default.is_scalar:
val = c.default.arg
else:
val = self.get_insert_default(c)
else:
val = self.get_update_default(c)
if val is not None:
compiled_parameters[key_getter(c)] = val
del self.current_parameters
DefaultDialect.execution_ctx_cls = DefaultExecutionContext