summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2020-07-23 16:11:47 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2020-07-23 16:11:47 +0000
commit67e8359931b18d2d13231a0d4e665b03958d6d7f (patch)
tree8ff67bc21dc1c4a8fed3dd5122726712f555fd20 /lib/sqlalchemy/sql
parentc2b9162b5d7a5d63fde677ba55f6227a669ca7fa (diff)
parent83b3ce6b7c7991d2faf314dc44571de9e6e9c27b (diff)
downloadsqlalchemy-67e8359931b18d2d13231a0d4e665b03958d6d7f.tar.gz
Merge "Revise setinputsizes approach"
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/compiler.py63
-rw-r--r--lib/sqlalchemy/sql/type_api.py47
2 files changed, 94 insertions, 16 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 3a3ce5c45..61e26b003 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -957,6 +957,68 @@ class SQLCompiler(Compiled):
pd[name] = value_param.value
return pd
+ @util.memoized_instancemethod
+ def _get_set_input_sizes_lookup(
+ self, translate=None, include_types=None, exclude_types=None
+ ):
+ if not hasattr(self, "bind_names"):
+ return None
+
+ dialect = self.dialect
+ dbapi = self.dialect.dbapi
+
+ # _unwrapped_dialect_impl() is necessary so that we get the
+ # correct dialect type for a custom TypeDecorator, or a Variant,
+ # which is also a TypeDecorator. Special types like Interval,
+ # that use TypeDecorator but also might be mapped directly
+ # for a dialect impl, also subclass Emulated first which overrides
+ # this behavior in those cases to behave like the default.
+
+ if not include_types and not exclude_types:
+
+ def _lookup_type(typ):
+ dialect_impl = typ._unwrapped_dialect_impl(dialect)
+ return dialect_impl.get_dbapi_type(dbapi)
+
+ else:
+
+ def _lookup_type(typ):
+ dialect_impl = typ._unwrapped_dialect_impl(dialect)
+ dbtype = dialect_impl.get_dbapi_type(dbapi)
+
+ if (
+ dbtype is not None
+ and (
+ not exclude_types
+ or dbtype not in exclude_types
+ and type(dialect_impl) not in exclude_types
+ )
+ and (
+ not include_types
+ or dbtype in include_types
+ or type(dialect_impl) in include_types
+ )
+ ):
+ return dbtype
+ else:
+ return None
+
+ inputsizes = {}
+ literal_execute_params = self.literal_execute_params
+
+ for bindparam in self.bind_names:
+ if bindparam in literal_execute_params:
+ continue
+
+ if bindparam._expanding_in_types:
+ inputsizes[bindparam] = [
+ _lookup_type(typ) for typ in bindparam._expanding_in_types
+ ]
+ else:
+ inputsizes[bindparam] = _lookup_type(bindparam.type)
+
+ return inputsizes
+
@property
def params(self):
"""Return the bind param dictionary embedded into this
@@ -4546,6 +4608,7 @@ class IdentifierPreparer(object):
if name is None:
name = table.name
+
result = self.quote(name)
effective_schema = self.schema_for_object(table)
diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py
index 83c7960ac..2d23c56e1 100644
--- a/lib/sqlalchemy/sql/type_api.py
+++ b/lib/sqlalchemy/sql/type_api.py
@@ -745,20 +745,20 @@ class Emulated(object):
def adapt(self, impltype, **kw):
if hasattr(impltype, "adapt_emulated_to_native"):
-
if self.native:
# native support requested, dialect gave us a native
# implementor, pass control over to it
return impltype.adapt_emulated_to_native(self, **kw)
else:
- # impltype adapts to native, and we are not native,
- # so reject the impltype in favor of "us"
- impltype = self.__class__
-
- if issubclass(impltype, self.__class__):
- return self.adapt_to_emulated(impltype, **kw)
+ # non-native support, let the native implementor
+ # decide also, at the moment this is just to help debugging
+ # as only the default logic is implemented.
+ return impltype.adapt_native_to_emulated(self, **kw)
else:
- return super(Emulated, self).adapt(impltype, **kw)
+ if issubclass(impltype, self.__class__):
+ return self.adapt_to_emulated(impltype, **kw)
+ else:
+ return super(Emulated, self).adapt(impltype, **kw)
class NativeForEmulated(object):
@@ -769,6 +769,16 @@ class NativeForEmulated(object):
"""
@classmethod
+ def adapt_native_to_emulated(cls, impl, **kw):
+ """Given an impl, adapt this type's class to the impl assuming
+ "emulated".
+
+
+ """
+ impltype = impl.__class__
+ return impl.adapt(impltype, **kw)
+
+ @classmethod
def adapt_emulated_to_native(cls, impl, **kw):
"""Given an impl, adapt this type's class to the impl assuming "native".
@@ -974,7 +984,7 @@ class TypeDecorator(SchemaEventTarget, TypeEngine):
# otherwise adapt the impl type, link
# to a copy of this TypeDecorator and return
# that.
- typedesc = self._unwrapped_dialect_impl(dialect)
+ typedesc = self.load_dialect_impl(dialect).dialect_impl(dialect)
tt = self.copy()
if not isinstance(tt, self.__class__):
raise AssertionError(
@@ -1045,16 +1055,21 @@ class TypeDecorator(SchemaEventTarget, TypeEngine):
def _unwrapped_dialect_impl(self, dialect):
"""Return the 'unwrapped' dialect impl for this type.
- For a type that applies wrapping logic (e.g. TypeDecorator), give
- us the real, actual dialect-level type that is used.
-
- This is used by TypeDecorator itself as well at least one case where
- dialects need to check that a particular specific dialect-level
- type is in use, within the :meth:`.DefaultDialect.set_input_sizes`
+ This is used by the :meth:`.DefaultDialect.set_input_sizes`
method.
"""
- return self.load_dialect_impl(dialect).dialect_impl(dialect)
+
+ # some dialects have a lookup for a TypeDecorator subclass directly.
+ # postgresql.INTERVAL being the main example
+ typ = self.dialect_impl(dialect)
+
+ # if we are still a type decorator, load the per-dialect switch
+ # (such as what Variant uses), then get the dialect impl for that.
+ if isinstance(typ, self.__class__):
+ return typ.load_dialect_impl(dialect).dialect_impl(dialect)
+ else:
+ return typ
def __getattr__(self, key):
"""Proxy all other undefined accessors to the underlying