o znh@sdZddlmZddlmZddlmZddlmZddlmZddlmZdd lm Z dd l m Z dd lm Z dd lmZejd dZGdddeZdS)aProvides an abstraction for obtaining database schema information. Usage Notes: Here are some general conventions when accessing the low level inspector methods such as get_table_names, get_columns, etc. 1. Inspector methods return lists of dicts in most cases for the following reasons: * They're both standard types that can be serialized. * Using a dict instead of a tuple allows easy expansion of attributes. * Using a list for the outer structure maintains order and is easy to work with (e.g. list comprehension [d['name'] for d in cols]). 2. Records that contain a name, such as the column name in a column record use the key 'name'. So for most return values, each record will have a 'name' attribute.. ) Connectable)exc) inspection)sql)util) operators)schema) TypeEngine) deprecated) topologicalcOs|dd}|dur|||g|Ri|S|jtdd|Dtdd|Df}||}|durE|||g|Ri|}|||<|S)N info_cachecss |] }t|tjr|VqdSN) isinstancer string_types).0arG/usr/local/lib/python3.10/dist-packages/sqlalchemy/engine/reflection.py /szcache..css$|] \}}|dkr||fVqdS)r Nr)rkvrrrr0s")get__name__tupleitems)fnselfconargskwr keyretrrrcache(s  r#c@sfeZdZdZddZeddZee ddZ e dd Z d d Z ejd d dGddZdHddZddZddZdHddZdHddZdHddZdHddZedd dHd!d"ZdHd#d$ZdHd%d&ZdHd'd(ZdHd)d*ZdHd+d,ZdHd-d.Z / 0 dId1d2Z d3d4Z!d5d6Z"d7d8Z#d9d:Z$d;e%j&fde%j)fgZ*d?d@Z+dAdBZ,dCdDZ-dEdFZ.dS)J InspectoramPerforms database schema inspection. The Inspector acts as a proxy to the reflection methods of the :class:`~sqlalchemy.engine.interfaces.Dialect`, providing a consistent interface as well as caching support for previously fetched metadata. A :class:`.Inspector` object is usually created via the :func:`.inspect` function:: from sqlalchemy import inspect, create_engine engine = create_engine('...') insp = inspect(engine) The inspection method above is equivalent to using the :meth:`.Inspector.from_engine` method, i.e.:: engine = create_engine('...') insp = Inspector.from_engine(engine) Where above, the :class:`~sqlalchemy.engine.interfaces.Dialect` may opt to return an :class:`.Inspector` subclass that provides additional methods specific to the dialect's target database. cCsJ||_t|dr |j|_n||_|j|ur||jj|_i|_dS)ajInitialize a new :class:`.Inspector`. :param bind: a :class:`~sqlalchemy.engine.Connectable`, which is typically an instance of :class:`~sqlalchemy.engine.Engine` or :class:`~sqlalchemy.engine.Connection`. For a dialect-specific instance of :class:`.Inspector`, see :meth:`.Inspector.from_engine` engineN)bindhasattrr%connectclosedialectr )rr&rrr__init__Ts      zInspector.__init__cCs t|jdr |j|St|S)aConstruct a new dialect-specific Inspector object from the given engine or connection. :param bind: a :class:`~sqlalchemy.engine.Connectable`, which is typically an instance of :class:`~sqlalchemy.engine.Engine` or :class:`~sqlalchemy.engine.Connection`. This method differs from direct a direct constructor call of :class:`.Inspector` in that the :class:`~sqlalchemy.engine.interfaces.Dialect` is given a chance to provide a dialect-specific :class:`.Inspector` instance, which may provide additional methods. See the example at :class:`.Inspector`. inspector)r'r*r,r$)clsr&rrr from_engineps  zInspector.from_enginecCs t|Sr)r$r.)r&rrr_insps zInspector._inspcCs|jjS)zReturn the default schema name presented by the dialect for the current engine's database user. E.g. this is typically ``public`` for PostgreSQL and ``dbo`` for SQL Server. )r*default_schema_namerrrrr0s zInspector.default_schema_namecCs$t|jdr|jj|j|jdSgS)z!Return all schema names. get_schema_namesr )r'r*r2r&r r1rrrr2s zInspector.get_schema_names)z1.0zThe :paramref:`get_table_names.order_by` parameter is deprecated and will be removed in a future release. Please refer to :meth:`.Inspector.get_sorted_table_and_fkc_names` for a more comprehensive solution to resolving foreign key cycles between tables.)order_byNcCst|jdr|jj|j||jd}n|j|}|dkrCg}|D]}|||D]}||dkr9||d|fq(q t t ||}|S)aReturn all table names in referred to within a particular schema. The names are expected to be real tables only, not views. Views are instead returned using the :meth:`.Inspector.get_view_names` method. :param schema: Schema name. If ``schema`` is left at ``None``, the database's default schema is used, else the named schema is searched. If the database does not support named schemas, behavior is undefined if ``schema`` is not passed as ``None``. For special quoting, use :class:`.quoted_name`. :param order_by: Optional, may be the string "foreign_key" to sort the result on foreign key dependencies. Does not automatically resolve cycles, and will raise :class:`.CircularDependencyError` if cycles exist. .. seealso:: :meth:`.Inspector.get_sorted_table_and_fkc_names` :attr:`.MetaData.sorted_tables` get_table_namesr3 foreign_keyreferred_table) r'r*r5r&r r% table_namesget_foreign_keysappendlistr sort)rr r4tnamestuplestnamefkeyrrrr5s %   zInspector.get_table_namesc s8t|jdr|jj|j||jd}n|j|}t}ti|D]'}|||}tdd|D|<|D]}||dkrH| |d|fq7q"z t t ||}Wn6t jy}z)|jD]|fdddDq`t t ||}WYd }~nd }~wwfd d|Dd t fgS) axReturn dependency-sorted table and foreign key constraint names in referred to within a particular schema. This will yield 2-tuples of ``(tablename, [(tname, fkname), (tname, fkname), ...])`` consisting of table names in CREATE order grouped with the foreign key constraint names that are not detected as belonging to a cycle. The final element will be ``(None, [(tname, fkname), (tname, fkname), ..])`` which will consist of remaining foreign key constraint names that would require a separate CREATE step after-the-fact, based on dependencies between tables. .. versionadded:: 1.0.- .. seealso:: :meth:`.Inspector.get_table_names` :func:`.sort_tables_and_constraints` - similar method which works with an already-given :class:`.MetaData`. r5r3cSsg|]}|dqS)namer)rfkrrr sz.r7c3s|] }d|fVqdS)rNr)rfkc)edgerrrs  z;Inspector.get_sorted_table_and_fkc_names..rNcsg|] }||fqSr) difference)rr?)fknames_for_tableremaining_fkcsrrrCs)r'r*r5r&r r%r8setr9addr;r r<rCircularDependencyErroredgesremoveupdate) rr r=r>r?fkeysr@candidate_sorterrr)rErGrHrget_sorted_table_and_fkc_namess@           z(Inspector.get_sorted_table_and_fkc_namescC|jj|j|jdS)zreturn a list of temporary table names for the current bind. This method is unsupported by most dialects; currently only SQLite implements it. .. versionadded:: 1.0.0 r3)r*get_temp_table_namesr&r r1rrrrT  zInspector.get_temp_table_namescCrS)zreturn a list of temporary view names for the current bind. This method is unsupported by most dialects; currently only SQLite implements it. .. versionadded:: 1.0.0 r3)r*get_temp_view_namesr&r r1rrrrVrUzInspector.get_temp_view_namescKs0t|jdr|jj|j||fd|ji|SiS)aReturn a dictionary of options specified when the table of the given name was created. This currently includes some options that apply to MySQL tables. :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. get_table_optionsr )r'r*rWr&r r table_namer r rrrrW&s zInspector.get_table_optionscCs|jj|j||jdS)zReturn all view names in `schema`. :param schema: Optional, retrieve names from a non-default schema. For special quoting, use :class:`.quoted_name`. r3)r*get_view_namesr&r )rr rrrrZ:s zInspector.get_view_namescCs|jj|j|||jdS)zReturn definition for `view_name`. :param schema: Optional, retrieve names from a non-default schema. For special quoting, use :class:`.quoted_name`. r3)r*get_view_definitionr&r )r view_namer rrrr[Fs zInspector.get_view_definitioncKsJ|jj|j||fd|ji|}|D]}|d}t|ts"||d<q|S)aReturn information about columns in `table_name`. Given a string `table_name` and an optional string `schema`, return column information as a list of dicts with these keys: * ``name`` - the column's name * ``type`` - the type of this column; an instance of :class:`~sqlalchemy.types.TypeEngine` * ``nullable`` - boolean flag if the column is NULL or NOT NULL * ``default`` - the column's server default value - this is returned as a string SQL expression. * ``attrs`` - dict containing optional column attributes :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. :return: list of dictionaries, each representing the definition of a database column. r type)r* get_columnsr&r rr )rrYr r col_defscol_defcoltyperrrr^Rs  zInspector.get_columnsz0.7zThe :meth:`.Inspector.get_primary_keys` method is deprecated and will be removed in a future release. Please refer to the :meth:`.Inspector.get_pk_constraint` method.cKs$|jj|j||fd|ji|dS)zReturn information about primary keys in `table_name`. Given a string `table_name`, and an optional string `schema`, return primary key information as a list of column names. r constrained_columnsr*get_pk_constraintr&r rXrrrget_primary_keyszs zInspector.get_primary_keyscK |jj|j||fd|ji|S)aReturn information about primary key constraint on `table_name`. Given a string `table_name`, and an optional string `schema`, return primary key information as a dictionary with these keys: constrained_columns a list of column names that make up the primary key name optional name of the primary key constraint. :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. r rcrXrrrrdszInspector.get_pk_constraintcKrf)aReturn information about foreign_keys in `table_name`. Given a string `table_name`, and an optional string `schema`, return foreign key information as a list of dicts with these keys: constrained_columns a list of column names that make up the foreign key referred_schema the name of the referred schema referred_table the name of the referred table referred_columns a list of column names in the referred table that correspond to constrained_columns name optional name of the foreign key constraint. :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. r )r*r9r&r rXrrrr9szInspector.get_foreign_keyscKrf)aReturn information about indexes in `table_name`. Given a string `table_name` and an optional string `schema`, return index information as a list of dicts with these keys: name the index's name column_names list of column names in order unique boolean column_sorting optional dict mapping column names to tuple of sort keywords, which may include ``asc``, ``desc``, ``nullsfirst``, ``nullslast``. .. versionadded:: 1.3.5 dialect_options dict of dialect-specific index options. May not be present for all dialects. .. versionadded:: 1.0.0 :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. r )r* get_indexesr&r rXrrrrgs$zInspector.get_indexescKrf)aoReturn information about unique constraints in `table_name`. Given a string `table_name` and an optional string `schema`, return unique constraint information as a list of dicts with these keys: name the unique constraint's name column_names list of column names in order :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. r )r*get_unique_constraintsr&r rXrrrrhsz Inspector.get_unique_constraintscKrf)aReturn information about the table comment for ``table_name``. Given a string ``table_name`` and an optional string ``schema``, return table comment information as a dictionary with these keys: text text of the comment. Raises ``NotImplementedError`` for a dialect that does not support comments. .. versionadded:: 1.2 r )r*get_table_commentr&r rXrrrriszInspector.get_table_commentcKrf)aKReturn information about check constraints in `table_name`. Given a string `table_name` and an optional string `schema`, return check constraint information as a list of dicts with these keys: name the check constraint's name sqltext the check constraint's SQL expression dialect_options may or may not be present; a dictionary with additional dialect-specific options for this CHECK constraint .. versionadded:: 1.3.8 :param table_name: string name of the table. For special quoting, use :class:`.quoted_name`. :param schema: string schema name; if omitted, uses the default schema of the database connection. For special quoting, use :class:`.quoted_name`. .. versionadded:: 1.1.0 r )r*get_check_constraintsr&r rXrrrrjszInspector.get_check_constraintsrTc sp|dur|vr dS||jj}|j}j}tfdd|jD} |j||fij} | r: | t j rSt |t rH||j}t |t rS||j}d} i} |j||fijD] } d} || ||| qb| sxtj|||| ||||| |||| |||| ||| |||| ||| |||| ||| |||| dS)a Given a Table object, load its internal constructs based on introspection. This is the underlying method used by most dialects to produce table reflection. Direct usage is like:: from sqlalchemy import create_engine, MetaData, Table from sqlalchemy.engine.reflection import Inspector engine = create_engine('...') meta = MetaData() user_table = Table('user', meta) insp = Inspector.from_engine(engine) insp.reflecttable(user_table, None) :param table: a :class:`~sqlalchemy.schema.Table` instance. :param include_columns: a list of string column names to include in the reflection process. If ``None``, all columns are reflected. Nc3s*|]}|jvr|j|fVqdSr)dialect_kwargsrrrtablerrris z)Inspector.reflecttable..FT)rJr&r*schema_for_objectrAdictreflection_optionsrWrk_validate_dialect_kwargsrpy2krstrdecodeencodingr^_reflect_columnrNoSuchTableError _reflect_pk _reflect_fk_reflect_indexes_reflect_unique_constraints_reflect_check_constraints_reflect_table_comment)rrninclude_columnsexclude_columns resolve_fks _extend_onr*r rYrqtbl_opts found_tablecols_by_orig_namecol_drrmr reflecttable<s               zInspector.reflecttablec s,d}|j||d}|r||vs|r||vrdSd}tfdddD} dvr8| dg} ddurkd} t| tjjrTt j | dd } nt| t j sft j t ddd } | | d vru|| t j||g| Ri| ||<} | j|jvrd| _|| dS) NrAr]c3s$|] }|vr||fVqdSrrrlrrrrs  z,Inspector._reflect_column..)nullable autoincrementquoteinfor!commentdialect_optionsdefaultT) _reflectedsequence)dispatchcolumn_reflectrprNrrrelements TextClause sa_schema DefaultClause FetchedValuetextr:_reflect_col_sequenceColumnr! primary_key append_column) rrnrrrr orig_namerAracol_kwcolargsrcolrrrrwsH       zInspector._reflect_columncCsXd|vr*|d}t|ddd}d|vr|d|_d|vr#|d|_||dSdS)NrrArstart increment)rSequencerrr:)rrrseqrrrrrs  zInspector._reflect_col_sequencecsT|j||fi|j}|r(fdd|dD}|d|j_|j|dSdS)Ncs$g|]}|vr|vr|qSrr)rpkrrrrrC s z)Inspector._reflect_pk..rbrA)rdrkrrrA_reload)rrYr rnrrpk_conspk_colsrrrrys zInspector._reflect_pkc  s>|j||fi|j} | D]} | d} fdd| dD} |r(t| |r(q | d} | d}| d}g}| dur^|rMtj||jfd| |j|d ||D] }|d | ||gqOn#|rrtj||jfd|jtj |d ||D] }|d ||gqtd | vr| d }ni}| tj | || fd di|q dS)NrAcs"g|] }|vr |jn|qSr)r!)rcrrrrC,sz)Inspector._reflect_fk..rbreferred_schemar7referred_columnsT)autoloadr autoload_withr.)rrr roptions link_to_name) r9rkrI intersectionrTablemetadatar&r:join BLANK_SCHEMAappend_constraintForeignKeyConstraint)rrYr rnrrrrrqrOfkey_dconnamerbrr7rrefspeccolumnrrrrrzs      zInspector._reflect_fkascdesc nullsfirst nullslastc CsN|||}|D]} | d} | d} | di} | d} | dd}| di}| d}|rCt| |sCtd |d | fq|rFqg}| D]@}z||vrU||n|j|}Wntyntd |||fYqJw| |d }|j D] \}}||vr||}qx| |qJt j | g|Rd |it t|d| fgqdS)NrA column_namescolumn_sortinguniquer]indexrduplicates_constraintz5Omitting %s key for (%s), key covers omitted columns., z5%s key '%s' was not located in columns for table '%s'r_table)rgrrIissubsetrwarnrrKeyError_index_sort_exprsr:rIndexrpr;r)rrYr rnrrrrqindexesindex_drAcolumnsrrflavorr duplicatesidx_colsridx_col c_sortingroprrrr{isb         zInspector._reflect_indexesc Csz|||}Wn tyYdSw|D]_} | d} | d} | d} |r8t| |s8tdd| q| r;qg} | D])}z||vrJ||n|j|}Wnt ybtd||fYq?w| |q?| t j | d| iqdS)NrArduplicates_indexzDOmitting unique constraint key for (%s), key covers omitted columns.rzDunique constraint key '%s' was not located in columns for table '%s')rhNotImplementedErrorrrIrrrrrrr:rrUniqueConstraint)rrYr rnrrrrq constraintsconst_drrrconstrained_colsrconstrained_colrrrr|sJ     z%Inspector._reflect_unique_constraintsc CsJz|||}Wn tyYdSw|D] } |tjdi| qdS)Nr)rjrrrCheckConstraint) rrYr rnrrrrqrrrrrr}s  z$Inspector._reflect_check_constraintscCs8z|||}Wn tyYdSw|dd|_dS)Nr)rirrr)rrYr rnrq comment_dictrrrr~s  z Inspector._reflect_table_comment)NNr)rTN)/r __module__ __qualname____doc__r+ classmethodr.r _inspectsrr/propertyr0r2rdeprecated_paramsr5rRrTrVrWrZr[r^r rerdr9rgrhrirjrrwrryrzrasc_opdesc_op nullsfirst_op nullslast_oprr{r|r}r~rrrrr$9sd      *8  (   # (  % 9 I:3 r$N)rbaserrrrrrr r sql.type_apir r r decoratorr#objectr$rrrrs