2727from sqlalchemy .engine import default , reflection
2828from sqlalchemy .exc import SQLAlchemyError
2929from sqlalchemy .sql import functions
30- from sqlalchemy .types import ARRAY
3130from sqlalchemy .util import asbool , to_list
3231
3332from .compiler import (
@@ -48,9 +47,10 @@ class UnresolvedType(sqltypes.UserDefinedType):
4847 A CrateDB type the dialect has no SQLAlchemy counterpart for.
4948
5049 Reflection yields it for a column it cannot resolve, carrying the CrateDB
51- type name as reported. Reading such a column is unaffected, and so is
52- printing its type, which shows the name. Compiling it as SQL is what has no
53- answer, and `CrateTypeCompiler` refuses there, naming the type.
50+ type name as reported. Such a column still reads. Compiling the type as SQL
51+ is what has no answer, and `CrateTypeCompiler` refuses there, naming the
52+ type. From SQLAlchemy 1.4 onwards, printing the type yields the name; older
53+ versions route printing through the same compiler and raise.
5454 """
5555
5656 __visit_name__ = "unresolved"
@@ -109,7 +109,7 @@ class Double(sqltypes.Float):
109109
110110 TYPES_MAP ["double" ] = DOUBLE
111111 TYPES_MAP ["double precision" ] = DOUBLE_PRECISION
112- except Exception : # noqa: S110
112+ except ImportError :
113113 pass
114114
115115
@@ -517,16 +517,31 @@ def _resolve_type(self, type_):
517517 Turn a type name, as `information_schema.columns` reports it, into the
518518 SQLAlchemy type a reflected column of that type carries.
519519
520- The map answers first, so that `object_array` keeps the entry it has.
521- Every other name ending in `_array` names an array of the type the rest
522- of the name names, and resolves to an `ARRAY` of that type. Two shapes
523- have no representation and are left unresolved: an array whose element
524- type is itself unresolved, and an array of arrays, which SQLAlchemy's
525- `ARRAY` cannot hold and `CrateTypeCompiler` refuses to render.
520+ A name with no type behind it yields an `UnresolvedType` under that same
521+ name, so an unresolved array reports the array's name rather than its
522+ element's, and the log carries the name the column actually has.
523+ """
524+ resolved = self ._lookup_type (type_ )
525+ if resolved is None :
526+ # Reflecting `pg_catalog` alone leaves twenty-odd columns unresolved,
527+ # so this records the name for tracing rather than to raise an alarm
528+ # about a schema nobody asked to reflect. What does deserve one is
529+ # asking such a column for SQL, and that raises.
530+ log .debug ("Unable to resolve CrateDB type: %s" , type_ )
531+ return UnresolvedType (type_ )
532+ return resolved
533+
534+ def _lookup_type (self , type_ ):
535+ """
536+ Find the SQLAlchemy type for a CrateDB type name, or `None` for a name
537+ the dialect has nothing to offer for.
526538
527- Whatever is left unresolved keeps the name of the type the column
528- actually has, so an unresolved array reports the array's name rather
529- than its element's.
539+ The map answers first, so that `object_array` resolves to its own entry.
540+ Every other name ending in `_array` names an array of the type the rest
541+ of the name names, and yields an `ARRAY` of that type. Two shapes have no
542+ representation: an array whose element type is itself unresolved, and an
543+ array of arrays, which SQLAlchemy's `ARRAY` cannot hold and
544+ `CrateTypeCompiler` refuses to render.
530545
531546 An `ARRAY` built here carries its element type into DDL and into the
532547 reflected column. It converts no values, because SQLAlchemy's `ARRAY`
@@ -536,17 +551,15 @@ def _resolve_type(self, type_):
536551 resolved = TYPES_MAP .get (type_ )
537552 if resolved is not None :
538553 return resolved
539- element_name = type_ [: - len (ARRAY_SUFFIX )] if type_ .endswith (ARRAY_SUFFIX ) else ""
540- if element_name and not element_name .endswith (ARRAY_SUFFIX ):
541- element_type = self ._resolve_type (element_name )
542- if not isinstance (element_type , UnresolvedType ):
543- return ARRAY (element_type )
544- # Reflecting `pg_catalog` alone leaves twenty-odd columns unresolved, so
545- # this records the name for tracing rather than to raise an alarm about
546- # a schema nobody asked to reflect. What does deserve one is asking such
547- # a column for SQL, and that raises.
548- log .debug ("Unable to resolve CrateDB type: %s" , type_ )
549- return UnresolvedType (type_ )
554+ if not type_ .endswith (ARRAY_SUFFIX ):
555+ return None
556+ element_name = type_ [: - len (ARRAY_SUFFIX )]
557+ if not element_name or element_name .endswith (ARRAY_SUFFIX ):
558+ return None
559+ element_type = self ._lookup_type (element_name )
560+ if element_type is None :
561+ return None
562+ return sqltypes .ARRAY (element_type )
550563
551564 def has_ilike_operator (self ):
552565 """
0 commit comments