codekingpro/portable-devtools
115k
1# engine/reflection.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8"""Provides an abstraction for obtaining database schema information.
9
10Usage Notes:
11
12Here are some general conventions when accessing the low level inspector
13methods such as get_table_names, get_columns, etc.
14
151. Inspector methods return lists of dicts in most cases for the following
16 reasons:
17
18 * They're both standard types that can be serialized.
19 * Using a dict instead of a tuple allows easy expansion of attributes.
20 * Using a list for the outer structure maintains order and is easy to work
21 with (e.g. list comprehension [d['name'] for d in cols]).
22
232. Records that contain a name, such as the column name in a column record
24 use the key 'name'. So for most return values, each record will have a
25 'name' attribute..
26"""
27from __future__ import annotations
28
29import contextlib
30from dataclasses import dataclass
31from enum import auto
32from enum import Flag
33from enum import unique
34from typing import Any
35from typing import Callable
36from typing import Collection
37from typing import Dict
38from typing import Generator
39from typing import Iterable
40from typing import List
41from typing import Optional
42from typing import Sequence
43from typing import Set
44from typing import Tuple
45from typing import TYPE_CHECKING
46from typing import TypeVar
47from typing import Union
48
49from .base import Connection
50from .base import Engine
51from .. import exc
52from .. import inspection
53from .. import sql
54from .. import util
55from ..sql import operators
56from ..sql import schema as sa_schema
57from ..sql.cache_key import _ad_hoc_cache_key_from_args
58from ..sql.elements import TextClause
59from ..sql.type_api import TypeEngine
60from ..sql.visitors import InternalTraversal
61from ..util import topological
62from ..util.typing import final
63
64if TYPE_CHECKING:
65 from .interfaces import Dialect
66 from .interfaces import ReflectedCheckConstraint
67 from .interfaces import ReflectedColumn
68 from .interfaces import ReflectedForeignKeyConstraint
69 from .interfaces import ReflectedIndex
70 from .interfaces import ReflectedPrimaryKeyConstraint
71 from .interfaces import ReflectedTableComment
72 from .interfaces import ReflectedUniqueConstraint
73 from .interfaces import TableKey
74
75_R = TypeVar("_R")
76
77
78@util.decorator
79def cache(
80 fn: Callable[..., _R],
81 self: Dialect,
82 con: Connection,
83 *args: Any,
84 **kw: Any,
85) -> _R:
86 info_cache = kw.get("info_cache", None)
87 if info_cache is None:
88 return fn(self, con, *args, **kw)
89 exclude = {"info_cache", "unreflectable"}
90 key = (
91 fn.__name__,
92 tuple(a for a in args if isinstance(a, str)),
93 tuple((k, v) for k, v in kw.items() if k not in exclude),
94 )
95 ret: _R = info_cache.get(key)
96 if ret is None:
97 ret = fn(self, con, *args, **kw)
98 info_cache[key] = ret
99 return ret
100
101
102def flexi_cache(
103 *traverse_args: Tuple[str, InternalTraversal]
104) -> Callable[[Callable[..., _R]], Callable[..., _R]]:
105 @util.decorator
106 def go(
107 fn: Callable[..., _R],
108 self: Dialect,
109 con: Connection,
110 *args: Any,
111 **kw: Any,
112 ) -> _R:
113 info_cache = kw.get("info_cache", None)
114 if info_cache is None:
115 return fn(self, con, *args, **kw)
116 key = _ad_hoc_cache_key_from_args((fn.__name__,), traverse_args, args)
117 ret: _R = info_cache.get(key)
118 if ret is None:
119 ret = fn(self, con, *args, **kw)
120 info_cache[key] = ret
121 return ret
122
123 return go
124
125
126@unique
127class ObjectKind(Flag):
128 """Enumerator that indicates which kind of object to return when calling
129 the ``get_multi`` methods.
130
131 This is a Flag enum, so custom combinations can be passed. For example,
132 to reflect tables and plain views ``ObjectKind.TABLE | ObjectKind.VIEW``
133 may be used.
134
135 .. note::
136 Not all dialect may support all kind of object. If a dialect does
137 not support a particular object an empty dict is returned.
138 In case a dialect supports an object, but the requested method
139 is not applicable for the specified kind the default value
140 will be returned for each reflected object. For example reflecting
141 check constraints of view return a dict with all the views with
142 empty lists as values.
143 """
144
145 TABLE = auto()
146 "Reflect table objects"
147 VIEW = auto()
148 "Reflect plain view objects"
149 MATERIALIZED_VIEW = auto()
150 "Reflect materialized view object"
151
152 ANY_VIEW = VIEW | MATERIALIZED_VIEW
153 "Reflect any kind of view objects"
154 ANY = TABLE | VIEW | MATERIALIZED_VIEW
155 "Reflect all type of objects"
156
157
158@unique
159class ObjectScope(Flag):
160 """Enumerator that indicates which scope to use when calling
161 the ``get_multi`` methods.
162 """
163
164 DEFAULT = auto()
165 "Include default scope"
166 TEMPORARY = auto()
167 "Include only temp scope"
168 ANY = DEFAULT | TEMPORARY
169 "Include both default and temp scope"
170
171
172@inspection._self_inspects
173class Inspector(inspection.Inspectable["Inspector"]):
174 """Performs database schema inspection.
175
176 The Inspector acts as a proxy to the reflection methods of the
177 :class:`~sqlalchemy.engine.interfaces.Dialect`, providing a
178 consistent interface as well as caching support for previously
179 fetched metadata.
180
181 A :class:`_reflection.Inspector` object is usually created via the
182 :func:`_sa.inspect` function, which may be passed an
183 :class:`_engine.Engine`
184 or a :class:`_engine.Connection`::
185
186 from sqlalchemy import inspect, create_engine
187 engine = create_engine('...')
188 insp = inspect(engine)
189
190 Where above, the :class:`~sqlalchemy.engine.interfaces.Dialect` associated
191 with the engine may opt to return an :class:`_reflection.Inspector`
192 subclass that
193 provides additional methods specific to the dialect's target database.
194
195 """
196
197 bind: Union[Engine, Connection]
198 engine: Engine
199 _op_context_requires_connect: bool
200 dialect: Dialect
201 info_cache: Dict[Any, Any]
202
203 @util.deprecated(
204 "1.4",
205 "The __init__() method on :class:`_reflection.Inspector` "
206 "is deprecated and "
207 "will be removed in a future release. Please use the "
208 ":func:`.sqlalchemy.inspect` "
209 "function on an :class:`_engine.Engine` or "
210 ":class:`_engine.Connection` "
211 "in order to "
212 "acquire an :class:`_reflection.Inspector`.",
213 )
214 def __init__(self, bind: Union[Engine, Connection]):
215 """Initialize a new :class:`_reflection.Inspector`.
216
217 :param bind: a :class:`~sqlalchemy.engine.Connection`,
218 which is typically an instance of
219 :class:`~sqlalchemy.engine.Engine` or
220 :class:`~sqlalchemy.engine.Connection`.
221
222 For a dialect-specific instance of :class:`_reflection.Inspector`, see
223 :meth:`_reflection.Inspector.from_engine`
224
225 """
226 self._init_legacy(bind)
227
228 @classmethod
229 def _construct(
230 cls, init: Callable[..., Any], bind: Union[Engine, Connection]
231 ) -> Inspector:
232 if hasattr(bind.dialect, "inspector"):
233 cls = bind.dialect.inspector
234
235 self = cls.__new__(cls)
236 init(self, bind)
237 return self
238
239 def _init_legacy(self, bind: Union[Engine, Connection]) -> None:
240 if hasattr(bind, "exec_driver_sql"):
241 self._init_connection(bind) # type: ignore[arg-type]
242 else:
243 self._init_engine(bind)
244
245 def _init_engine(self, engine: Engine) -> None:
246 self.bind = self.engine = engine
247 engine.connect().close()
248 self._op_context_requires_connect = True
249 self.dialect = self.engine.dialect
250 self.info_cache = {}
251
252 def _init_connection(self, connection: Connection) -> None:
253 self.bind = connection
254 self.engine = connection.engine
255 self._op_context_requires_connect = False
256 self.dialect = self.engine.dialect
257 self.info_cache = {}
258
259 def clear_cache(self) -> None:
260 """reset the cache for this :class:`.Inspector`.
261
262 Inspection methods that have data cached will emit SQL queries
263 when next called to get new data.
264
265 .. versionadded:: 2.0
266
267 """
268 self.info_cache.clear()
269
270 @classmethod
271 @util.deprecated(
272 "1.4",
273 "The from_engine() method on :class:`_reflection.Inspector` "
274 "is deprecated and "
275 "will be removed in a future release. Please use the "
276 ":func:`.sqlalchemy.inspect` "
277 "function on an :class:`_engine.Engine` or "
278 ":class:`_engine.Connection` "
279 "in order to "
280 "acquire an :class:`_reflection.Inspector`.",
281 )
282 def from_engine(cls, bind: Engine) -> Inspector:
283 """Construct a new dialect-specific Inspector object from the given
284 engine or connection.
285
286 :param bind: a :class:`~sqlalchemy.engine.Connection`
287 or :class:`~sqlalchemy.engine.Engine`.
288
289 This method differs from direct a direct constructor call of
290 :class:`_reflection.Inspector` in that the
291 :class:`~sqlalchemy.engine.interfaces.Dialect` is given a chance to
292 provide a dialect-specific :class:`_reflection.Inspector` instance,
293 which may
294 provide additional methods.
295
296 See the example at :class:`_reflection.Inspector`.
297
298 """
299 return cls._construct(cls._init_legacy, bind)
300
301 @inspection._inspects(Engine)
302 def _engine_insp(bind: Engine) -> Inspector: # type: ignore[misc]
303 return Inspector._construct(Inspector._init_engine, bind)
304
305 @inspection._inspects(Connection)
306 def _connection_insp(bind: Connection) -> Inspector: # type: ignore[misc]
307 return Inspector._construct(Inspector._init_connection, bind)
308
309 @contextlib.contextmanager
310 def _operation_context(self) -> Generator[Connection, None, None]:
311 """Return a context that optimizes for multiple operations on a single
312 transaction.
313
314 This essentially allows connect()/close() to be called if we detected
315 that we're against an :class:`_engine.Engine` and not a
316 :class:`_engine.Connection`.
317
318 """
319 conn: Connection
320 if self._op_context_requires_connect:
321 conn = self.bind.connect() # type: ignore[union-attr]
322 else:
323 conn = self.bind # type: ignore[assignment]
324 try:
325 yield conn
326 finally:
327 if self._op_context_requires_connect:
328 conn.close()
329
330 @contextlib.contextmanager
331 def _inspection_context(self) -> Generator[Inspector, None, None]:
332 """Return an :class:`_reflection.Inspector`
333 from this one that will run all
334 operations on a single connection.
335
336 """
337
338 with self._operation_context() as conn:
339 sub_insp = self._construct(self.__class__._init_connection, conn)
340 sub_insp.info_cache = self.info_cache
341 yield sub_insp
342
343 @property
344 def default_schema_name(self) -> Optional[str]:
345 """Return the default schema name presented by the dialect
346 for the current engine's database user.
347
348 E.g. this is typically ``public`` for PostgreSQL and ``dbo``
349 for SQL Server.
350
351 """
352 return self.dialect.default_schema_name
353
354 def get_schema_names(self, **kw: Any) -> List[str]:
355 r"""Return all schema names.
356
357 :param \**kw: Additional keyword argument to pass to the dialect
358 specific implementation. See the documentation of the dialect
359 in use for more information.
360 """
361
362 with self._operation_context() as conn:
363 return self.dialect.get_schema_names(
364 conn, info_cache=self.info_cache, **kw
365 )
366
367 def get_table_names(
368 self, schema: Optional[str] = None, **kw: Any
369 ) -> List[str]:
370 r"""Return all table names within a particular schema.
371
372 The names are expected to be real tables only, not views.
373 Views are instead returned using the
374 :meth:`_reflection.Inspector.get_view_names` and/or
375 :meth:`_reflection.Inspector.get_materialized_view_names`
376 methods.
377
378 :param schema: Schema name. If ``schema`` is left at ``None``, the
379 database's default schema is
380 used, else the named schema is searched. If the database does not
381 support named schemas, behavior is undefined if ``schema`` is not
382 passed as ``None``. For special quoting, use :class:`.quoted_name`.
383 :param \**kw: Additional keyword argument to pass to the dialect
384 specific implementation. See the documentation of the dialect
385 in use for more information.
386
387 .. seealso::
388
389 :meth:`_reflection.Inspector.get_sorted_table_and_fkc_names`
390
391 :attr:`_schema.MetaData.sorted_tables`
392
393 """
394
395 with self._operation_context() as conn:
396 return self.dialect.get_table_names(
397 conn, schema, info_cache=self.info_cache, **kw
398 )
399
400 def has_table(
401 self, table_name: str, schema: Optional[str] = None, **kw: Any
402 ) -> bool:
403 r"""Return True if the backend has a table, view, or temporary
404 table of the given name.
405
406 :param table_name: name of the table to check
407 :param schema: schema name to query, if not the default schema.
408 :param \**kw: Additional keyword argument to pass to the dialect
409 specific implementation. See the documentation of the dialect
410 in use for more information.
411
412 .. versionadded:: 1.4 - the :meth:`.Inspector.has_table` method
413 replaces the :meth:`_engine.Engine.has_table` method.
414
415 .. versionchanged:: 2.0:: :meth:`.Inspector.has_table` now formally
416 supports checking for additional table-like objects:
417
418 * any type of views (plain or materialized)
419 * temporary tables of any kind
420
421 Previously, these two checks were not formally specified and
422 different dialects would vary in their behavior. The dialect
423 testing suite now includes tests for all of these object types
424 and should be supported by all SQLAlchemy-included dialects.
425 Support among third party dialects may be lagging, however.
426
427 """
428 with self._operation_context() as conn:
429 return self.dialect.has_table(
430 conn, table_name, schema, info_cache=self.info_cache, **kw
431 )
432
433 def has_sequence(
434 self, sequence_name: str, schema: Optional[str] = None, **kw: Any
435 ) -> bool:
436 r"""Return True if the backend has a sequence with the given name.
437
438 :param sequence_name: name of the sequence to check
439 :param schema: schema name to query, if not the default schema.
440 :param \**kw: Additional keyword argument to pass to the dialect
441 specific implementation. See the documentation of the dialect
442 in use for more information.
443
444 .. versionadded:: 1.4
445
446 """
447 with self._operation_context() as conn:
448 return self.dialect.has_sequence(
449 conn, sequence_name, schema, info_cache=self.info_cache, **kw
450 )
451
452 def has_index(
453 self,
454 table_name: str,
455 index_name: str,
456 schema: Optional[str] = None,
457 **kw: Any,
458 ) -> bool:
459 r"""Check the existence of a particular index name in the database.
460
461 :param table_name: the name of the table the index belongs to
462 :param index_name: the name of the index to check
463 :param schema: schema name to query, if not the default schema.
464 :param \**kw: Additional keyword argument to pass to the dialect
465 specific implementation. See the documentation of the dialect
466 in use for more information.
467
468 .. versionadded:: 2.0
469
470 """
471 with self._operation_context() as conn:
472 return self.dialect.has_index(
473 conn,
474 table_name,
475 index_name,
476 schema,
477 info_cache=self.info_cache,
478 **kw,
479 )
480
481 def has_schema(self, schema_name: str, **kw: Any) -> bool:
482 r"""Return True if the backend has a schema with the given name.
483
484 :param schema_name: name of the schema to check
485 :param \**kw: Additional keyword argument to pass to the dialect
486 specific implementation. See the documentation of the dialect
487 in use for more information.
488
489 .. versionadded:: 2.0
490
491 """
492 with self._operation_context() as conn:
493 return self.dialect.has_schema(
494 conn, schema_name, info_cache=self.info_cache, **kw
495 )
496
497 def get_sorted_table_and_fkc_names(
498 self,
499 schema: Optional[str] = None,
500 **kw: Any,
501 ) -> List[Tuple[Optional[str], List[Tuple[str, Optional[str]]]]]:
502 r"""Return dependency-sorted table and foreign key constraint names in
503 referred to within a particular schema.
504
505 This will yield 2-tuples of
506 ``(tablename, [(tname, fkname), (tname, fkname), ...])``
507 consisting of table names in CREATE order grouped with the foreign key
508 constraint names that are not detected as belonging to a cycle.
509 The final element
510 will be ``(None, [(tname, fkname), (tname, fkname), ..])``
511 which will consist of remaining
512 foreign key constraint names that would require a separate CREATE
513 step after-the-fact, based on dependencies between tables.
514
515 :param schema: schema name to query, if not the default schema.
516 :param \**kw: Additional keyword argument to pass to the dialect
517 specific implementation. See the documentation of the dialect
518 in use for more information.
519
520 .. seealso::
521
522 :meth:`_reflection.Inspector.get_table_names`
523
524 :func:`.sort_tables_and_constraints` - similar method which works
525 with an already-given :class:`_schema.MetaData`.
526
527 """
528
529 return [
530 (
531 table_key[1] if table_key else None,
532 [(tname, fks) for (_, tname), fks in fk_collection],
533 )
534 for (
535 table_key,
536 fk_collection,
537 ) in self.sort_tables_on_foreign_key_dependency(
538 consider_schemas=(schema,)
539 )
540 ]
541
542 def sort_tables_on_foreign_key_dependency(
543 self,
544 consider_schemas: Collection[Optional[str]] = (None,),
545 **kw: Any,
546 ) -> List[
547 Tuple[
548 Optional[Tuple[Optional[str], str]],
549 List[Tuple[Tuple[Optional[str], str], Optional[str]]],
550 ]
551 ]:
552 r"""Return dependency-sorted table and foreign key constraint names
553 referred to within multiple schemas.
554
555 This method may be compared to
556 :meth:`.Inspector.get_sorted_table_and_fkc_names`, which
557 works on one schema at a time; here, the method is a generalization
558 that will consider multiple schemas at once including that it will
559 resolve for cross-schema foreign keys.
560
561 .. versionadded:: 2.0
562
563 """
564 SchemaTab = Tuple[Optional[str], str]
565
566 tuples: Set[Tuple[SchemaTab, SchemaTab]] = set()
567 remaining_fkcs: Set[Tuple[SchemaTab, Optional[str]]] = set()
568 fknames_for_table: Dict[SchemaTab, Set[Optional[str]]] = {}
569 tnames: List[SchemaTab] = []
570
571 for schname in consider_schemas:
572 schema_fkeys = self.get_multi_foreign_keys(schname, **kw)
573 tnames.extend(schema_fkeys)
574 for (_, tname), fkeys in schema_fkeys.items():
575 fknames_for_table[(schname, tname)] = {
576 fk["name"] for fk in fkeys
577 }
578 for fkey in fkeys:
579 if (
580 tname != fkey["referred_table"]
581 or schname != fkey["referred_schema"]
582 ):
583 tuples.add(
584 (
585 (
586 fkey["referred_schema"],
587 fkey["referred_table"],
588 ),
589 (schname, tname),
590 )
591 )
592 try:
593 candidate_sort = list(topological.sort(tuples, tnames))
594 except exc.CircularDependencyError as err:
595 edge: Tuple[SchemaTab, SchemaTab]
596 for edge in err.edges:
597 tuples.remove(edge)
598 remaining_fkcs.update(
599 (edge[1], fkc) for fkc in fknames_for_table[edge[1]]
600 )
601
602 candidate_sort = list(topological.sort(tuples, tnames))
603 ret: List[
604 Tuple[Optional[SchemaTab], List[Tuple[SchemaTab, Optional[str]]]]
605 ]
606 ret = [
607 (
608 (schname, tname),
609 [
610 ((schname, tname), fk)
611 for fk in fknames_for_table[(schname, tname)].difference(
612 name for _, name in remaining_fkcs
613 )
614 ],
615 )
616 for (schname, tname) in candidate_sort
617 ]
618 return ret + [(None, list(remaining_fkcs))]
619
620 def get_temp_table_names(self, **kw: Any) -> List[str]:
621 r"""Return a list of temporary table names for the current bind.
622
623 This method is unsupported by most dialects; currently
624 only Oracle, PostgreSQL and SQLite implements it.
625
626 :param \**kw: Additional keyword argument to pass to the dialect
627 specific implementation. See the documentation of the dialect
628 in use for more information.
629
630 """
631
632 with self._operation_context() as conn:
633 return self.dialect.get_temp_table_names(
634 conn, info_cache=self.info_cache, **kw
635 )
636
637 def get_temp_view_names(self, **kw: Any) -> List[str]:
638 r"""Return a list of temporary view names for the current bind.
639
640 This method is unsupported by most dialects; currently
641 only PostgreSQL and SQLite implements it.
642
643 :param \**kw: Additional keyword argument to pass to the dialect
644 specific implementation. See the documentation of the dialect
645 in use for more information.
646
647 """
648 with self._operation_context() as conn:
649 return self.dialect.get_temp_view_names(
650 conn, info_cache=self.info_cache, **kw
651 )
652
653 def get_table_options(
654 self, table_name: str, schema: Optional[str] = None, **kw: Any
655 ) -> Dict[str, Any]:
656 r"""Return a dictionary of options specified when the table of the
657 given name was created.
658
659 This currently includes some options that apply to MySQL and Oracle
660 tables.
661
662 :param table_name: string name of the table. For special quoting,
663 use :class:`.quoted_name`.
664
665 :param schema: string schema name; if omitted, uses the default schema
666 of the database connection. For special quoting,
667 use :class:`.quoted_name`.
668
669 :param \**kw: Additional keyword argument to pass to the dialect
670 specific implementation. See the documentation of the dialect
671 in use for more information.
672
673 :return: a dict with the table options. The returned keys depend on the
674 dialect in use. Each one is prefixed with the dialect name.
675
676 .. seealso:: :meth:`Inspector.get_multi_table_options`
677
678 """
679 with self._operation_context() as conn:
680 return self.dialect.get_table_options(
681 conn, table_name, schema, info_cache=self.info_cache, **kw
682 )
683
684 def get_multi_table_options(
685 self,
686 schema: Optional[str] = None,
687 filter_names: Optional[Sequence[str]] = None,
688 kind: ObjectKind = ObjectKind.TABLE,
689 scope: ObjectScope = ObjectScope.DEFAULT,
690 **kw: Any,
691 ) -> Dict[TableKey, Dict[str, Any]]:
692 r"""Return a dictionary of options specified when the tables in the
693 given schema were created.
694
695 The tables can be filtered by passing the names to use to
696 ``filter_names``.
697
698 This currently includes some options that apply to MySQL and Oracle
699 tables.
700
701 :param schema: string schema name; if omitted, uses the default schema
702 of the database connection. For special quoting,
703 use :class:`.quoted_name`.
704
705 :param filter_names: optionally return information only for the
706 objects listed here.
707
708 :param kind: a :class:`.ObjectKind` that specifies the type of objects
709 to reflect. Defaults to ``ObjectKind.TABLE``.
710
711 :param scope: a :class:`.ObjectScope` that specifies if options of
712 default, temporary or any tables should be reflected.
713 Defaults to ``ObjectScope.DEFAULT``.
714
715 :param \**kw: Additional keyword argument to pass to the dialect
716 specific implementation. See the documentation of the dialect
717 in use for more information.
718
719 :return: a dictionary where the keys are two-tuple schema,table-name
720 and the values are dictionaries with the table options.
721 The returned keys in each dict depend on the
722 dialect in use. Each one is prefixed with the dialect name.
723 The schema is ``None`` if no schema is provided.
724
725 .. versionadded:: 2.0
726
727 .. seealso:: :meth:`Inspector.get_table_options`
728 """
729 with self._operation_context() as conn:
730 res = self.dialect.get_multi_table_options(
731 conn,
732 schema=schema,
733 filter_names=filter_names,
734 kind=kind,
735 scope=scope,
736 info_cache=self.info_cache,
737 **kw,
738 )
739 return dict(res)
740
741 def get_view_names(
742 self, schema: Optional[str] = None, **kw: Any
743 ) -> List[str]:
744 r"""Return all non-materialized view names in `schema`.
745
746 :param schema: Optional, retrieve names from a non-default schema.
747 For special quoting, use :class:`.quoted_name`.
748 :param \**kw: Additional keyword argument to pass to the dialect
749 specific implementation. See the documentation of the dialect
750 in use for more information.
751
752
753 .. versionchanged:: 2.0 For those dialects that previously included
754 the names of materialized views in this list (currently PostgreSQL),
755 this method no longer returns the names of materialized views.
756 the :meth:`.Inspector.get_materialized_view_names` method should
757 be used instead.
758
759 .. seealso::
760
761 :meth:`.Inspector.get_materialized_view_names`
762
763 """
764
765 with self._operation_context() as conn:
766 return self.dialect.get_view_names(
767 conn, schema, info_cache=self.info_cache, **kw
768 )
769
770 def get_materialized_view_names(
771 self, schema: Optional[str] = None, **kw: Any
772 ) -> List[str]:
773 r"""Return all materialized view names in `schema`.
774
775 :param schema: Optional, retrieve names from a non-default schema.
776 For special quoting, use :class:`.quoted_name`.
777 :param \**kw: Additional keyword argument to pass to the dialect
778 specific implementation. See the documentation of the dialect
779 in use for more information.
780
781 .. versionadded:: 2.0
782
783 .. seealso::
784
785 :meth:`.Inspector.get_view_names`
786
787 """
788
789 with self._operation_context() as conn:
790 return self.dialect.get_materialized_view_names(
791 conn, schema, info_cache=self.info_cache, **kw
792 )
793
794 def get_sequence_names(
795 self, schema: Optional[str] = None, **kw: Any
796 ) -> List[str]:
797 r"""Return all sequence names in `schema`.
798
799 :param schema: Optional, retrieve names from a non-default schema.
800 For special quoting, use :class:`.quoted_name`.
801 :param \**kw: Additional keyword argument to pass to the dialect
802 specific implementation. See the documentation of the dialect
803 in use for more information.
804
805 """
806
807 with self._operation_context() as conn:
808 return self.dialect.get_sequence_names(
809 conn, schema, info_cache=self.info_cache, **kw
810 )
811
812 def get_view_definition(
813 self, view_name: str, schema: Optional[str] = None, **kw: Any
814 ) -> str:
815 r"""Return definition for the plain or materialized view called
816 ``view_name``.
817
818 :param view_name: Name of the view.
819 :param schema: Optional, retrieve names from a non-default schema.
820 For special quoting, use :class:`.quoted_name`.
821 :param \**kw: Additional keyword argument to pass to the dialect
822 specific implementation. See the documentation of the dialect
823 in use for more information.
824
825 """
826
827 with self._operation_context() as conn:
828 return self.dialect.get_view_definition(
829 conn, view_name, schema, info_cache=self.info_cache, **kw
830 )
831
832 def get_columns(
833 self, table_name: str, schema: Optional[str] = None, **kw: Any
834 ) -> List[ReflectedColumn]:
835 r"""Return information about columns in ``table_name``.
836
837 Given a string ``table_name`` and an optional string ``schema``,
838 return column information as a list of :class:`.ReflectedColumn`.
839
840 :param table_name: string name of the table. For special quoting,
841 use :class:`.quoted_name`.
842
843 :param schema: string schema name; if omitted, uses the default schema
844 of the database connection. For special quoting,
845 use :class:`.quoted_name`.
846
847 :param \**kw: Additional keyword argument to pass to the dialect
848 specific implementation. See the documentation of the dialect
849 in use for more information.
850
851 :return: list of dictionaries, each representing the definition of
852 a database column.
853
854 .. seealso:: :meth:`Inspector.get_multi_columns`.
855
856 """
857
858 with self._operation_context() as conn:
859 col_defs = self.dialect.get_columns(
860 conn, table_name, schema, info_cache=self.info_cache, **kw
861 )
862 if col_defs:
863 self._instantiate_types([col_defs])
864 return col_defs
865
866 def _instantiate_types(
867 self, data: Iterable[List[ReflectedColumn]]
868 ) -> None:
869 # make this easy and only return instances for coltype
870 for col_defs in data:
871 for col_def in col_defs:
872 coltype = col_def["type"]
873 if not isinstance(coltype, TypeEngine):
874 col_def["type"] = coltype()
875
876 def get_multi_columns(
877 self,
878 schema: Optional[str] = None,
879 filter_names: Optional[Sequence[str]] = None,
880 kind: ObjectKind = ObjectKind.TABLE,
881 scope: ObjectScope = ObjectScope.DEFAULT,
882 **kw: Any,
883 ) -> Dict[TableKey, List[ReflectedColumn]]:
884 r"""Return information about columns in all objects in the given
885 schema.
886
887 The objects can be filtered by passing the names to use to
888 ``filter_names``.
889
890 For each table the value is a list of :class:`.ReflectedColumn`.
891
892 :param schema: string schema name; if omitted, uses the default schema
893 of the database connection. For special quoting,
894 use :class:`.quoted_name`.
895
896 :param filter_names: optionally return information only for the
897 objects listed here.
898
899 :param kind: a :class:`.ObjectKind` that specifies the type of objects
900 to reflect. Defaults to ``ObjectKind.TABLE``.
901
902 :param scope: a :class:`.ObjectScope` that specifies if columns of
903 default, temporary or any tables should be reflected.
904 Defaults to ``ObjectScope.DEFAULT``.
905
906 :param \**kw: Additional keyword argument to pass to the dialect
907 specific implementation. See the documentation of the dialect
908 in use for more information.
909
910 :return: a dictionary where the keys are two-tuple schema,table-name
911 and the values are list of dictionaries, each representing the
912 definition of a database column.
913 The schema is ``None`` if no schema is provided.
914
915 .. versionadded:: 2.0
916
917 .. seealso:: :meth:`Inspector.get_columns`
918 """
919
920 with self._operation_context() as conn:
921 table_col_defs = dict(
922 self.dialect.get_multi_columns(
923 conn,
924 schema=schema,
925 filter_names=filter_names,
926 kind=kind,
927 scope=scope,
928 info_cache=self.info_cache,
929 **kw,
930 )
931 )
932 self._instantiate_types(table_col_defs.values())
933 return table_col_defs
934
935 def get_pk_constraint(
936 self, table_name: str, schema: Optional[str] = None, **kw: Any
937 ) -> ReflectedPrimaryKeyConstraint:
938 r"""Return information about primary key constraint in ``table_name``.
939
940 Given a string ``table_name``, and an optional string `schema`, return
941 primary key information as a :class:`.ReflectedPrimaryKeyConstraint`.
942
943 :param table_name: string name of the table. For special quoting,
944 use :class:`.quoted_name`.
945
946 :param schema: string schema name; if omitted, uses the default schema
947 of the database connection. For special quoting,
948 use :class:`.quoted_name`.
949
950 :param \**kw: Additional keyword argument to pass to the dialect
951 specific implementation. See the documentation of the dialect
952 in use for more information.
953
954 :return: a dictionary representing the definition of
955 a primary key constraint.
956
957 .. seealso:: :meth:`Inspector.get_multi_pk_constraint`
958 """
959 with self._operation_context() as conn:
960 return self.dialect.get_pk_constraint(
961 conn, table_name, schema, info_cache=self.info_cache, **kw
962 )
963
964 def get_multi_pk_constraint(
965 self,
966 schema: Optional[str] = None,
967 filter_names: Optional[Sequence[str]] = None,
968 kind: ObjectKind = ObjectKind.TABLE,
969 scope: ObjectScope = ObjectScope.DEFAULT,
970 **kw: Any,
971 ) -> Dict[TableKey, ReflectedPrimaryKeyConstraint]:
972 r"""Return information about primary key constraints in
973 all tables in the given schema.
974
975 The tables can be filtered by passing the names to use to
976 ``filter_names``.
977
978 For each table the value is a :class:`.ReflectedPrimaryKeyConstraint`.
979
980 :param schema: string schema name; if omitted, uses the default schema
981 of the database connection. For special quoting,
982 use :class:`.quoted_name`.
983
984 :param filter_names: optionally return information only for the
985 objects listed here.
986
987 :param kind: a :class:`.ObjectKind` that specifies the type of objects
988 to reflect. Defaults to ``ObjectKind.TABLE``.
989
990 :param scope: a :class:`.ObjectScope` that specifies if primary keys of
991 default, temporary or any tables should be reflected.
992 Defaults to ``ObjectScope.DEFAULT``.
993
994 :param \**kw: Additional keyword argument to pass to the dialect
995 specific implementation. See the documentation of the dialect
996 in use for more information.
997
998 :return: a dictionary where the keys are two-tuple schema,table-name
999 and the values are dictionaries, each representing the
1000 definition of a primary key constraint.
1001 The schema is ``None`` if no schema is provided.
1002
1003 .. versionadded:: 2.0
1004
1005 .. seealso:: :meth:`Inspector.get_pk_constraint`
1006 """
1007 with self._operation_context() as conn:
1008 return dict(
1009 self.dialect.get_multi_pk_constraint(
1010 conn,
1011 schema=schema,
1012 filter_names=filter_names,
1013 kind=kind,
1014 scope=scope,
1015 info_cache=self.info_cache,
1016 **kw,
1017 )
1018 )
1019
1020 def get_foreign_keys(
1021 self, table_name: str, schema: Optional[str] = None, **kw: Any
1022 ) -> List[ReflectedForeignKeyConstraint]:
1023 r"""Return information about foreign_keys in ``table_name``.
1024
1025 Given a string ``table_name``, and an optional string `schema`, return
1026 foreign key information as a list of
1027 :class:`.ReflectedForeignKeyConstraint`.
1028
1029 :param table_name: string name of the table. For special quoting,
1030 use :class:`.quoted_name`.
1031
1032 :param schema: string schema name; if omitted, uses the default schema
1033 of the database connection. For special quoting,
1034 use :class:`.quoted_name`.
1035
1036 :param \**kw: Additional keyword argument to pass to the dialect
1037 specific implementation. See the documentation of the dialect
1038 in use for more information.
1039
1040 :return: a list of dictionaries, each representing the
1041 a foreign key definition.
1042
1043 .. seealso:: :meth:`Inspector.get_multi_foreign_keys`
1044 """
1045
1046 with self._operation_context() as conn:
1047 return self.dialect.get_foreign_keys(
1048 conn, table_name, schema, info_cache=self.info_cache, **kw
1049 )
1050
1051 def get_multi_foreign_keys(
1052 self,
1053 schema: Optional[str] = None,
1054 filter_names: Optional[Sequence[str]] = None,
1055 kind: ObjectKind = ObjectKind.TABLE,
1056 scope: ObjectScope = ObjectScope.DEFAULT,
1057 **kw: Any,
1058 ) -> Dict[TableKey, List[ReflectedForeignKeyConstraint]]:
1059 r"""Return information about foreign_keys in all tables
1060 in the given schema.
1061
1062 The tables can be filtered by passing the names to use to
1063 ``filter_names``.
1064
1065 For each table the value is a list of
1066 :class:`.ReflectedForeignKeyConstraint`.
1067
1068 :param schema: string schema name; if omitted, uses the default schema
1069 of the database connection. For special quoting,
1070 use :class:`.quoted_name`.
1071
1072 :param filter_names: optionally return information only for the
1073 objects listed here.
1074
1075 :param kind: a :class:`.ObjectKind` that specifies the type of objects
1076 to reflect. Defaults to ``ObjectKind.TABLE``.
1077
1078 :param scope: a :class:`.ObjectScope` that specifies if foreign keys of
1079 default, temporary or any tables should be reflected.
1080 Defaults to ``ObjectScope.DEFAULT``.
1081
1082 :param \**kw: Additional keyword argument to pass to the dialect
1083 specific implementation. See the documentation of the dialect
1084 in use for more information.
1085
1086 :return: a dictionary where the keys are two-tuple schema,table-name
1087 and the values are list of dictionaries, each representing
1088 a foreign key definition.
1089 The schema is ``None`` if no schema is provided.
1090
1091 .. versionadded:: 2.0
1092
1093 .. seealso:: :meth:`Inspector.get_foreign_keys`
1094 """
1095
1096 with self._operation_context() as conn:
1097 return dict(
1098 self.dialect.get_multi_foreign_keys(
1099 conn,
1100 schema=schema,
1101 filter_names=filter_names,
1102 kind=kind,
1103 scope=scope,
1104 info_cache=self.info_cache,
1105 **kw,
1106 )
1107 )
1108
1109 def get_indexes(
1110 self, table_name: str, schema: Optional[str] = None, **kw: Any
1111 ) -> List[ReflectedIndex]:
1112 r"""Return information about indexes in ``table_name``.
1113
1114 Given a string ``table_name`` and an optional string `schema`, return
1115 index information as a list of :class:`.ReflectedIndex`.
1116
1117 :param table_name: string name of the table. For special quoting,
1118 use :class:`.quoted_name`.
1119
1120 :param schema: string schema name; if omitted, uses the default schema
1121 of the database connection. For special quoting,
1122 use :class:`.quoted_name`.
1123
1124 :param \**kw: Additional keyword argument to pass to the dialect
1125 specific implementation. See the documentation of the dialect
1126 in use for more information.
1127
1128 :return: a list of dictionaries, each representing the
1129 definition of an index.
1130
1131 .. seealso:: :meth:`Inspector.get_multi_indexes`
1132 """
1133
1134 with self._operation_context() as conn:
1135 return self.dialect.get_indexes(
1136 conn, table_name, schema, info_cache=self.info_cache, **kw
1137 )
1138
1139 def get_multi_indexes(
1140 self,
1141 schema: Optional[str] = None,
1142 filter_names: Optional[Sequence[str]] = None,
1143 kind: ObjectKind = ObjectKind.TABLE,
1144 scope: ObjectScope = ObjectScope.DEFAULT,
1145 **kw: Any,
1146 ) -> Dict[TableKey, List[ReflectedIndex]]:
1147 r"""Return information about indexes in in all objects
1148 in the given schema.
1149
1150 The objects can be filtered by passing the names to use to
1151 ``filter_names``.
1152
1153 For each table the value is a list of :class:`.ReflectedIndex`.
1154
1155 :param schema: string schema name; if omitted, uses the default schema
1156 of the database connection. For special quoting,
1157 use :class:`.quoted_name`.
1158
1159 :param filter_names: optionally return information only for the
1160 objects listed here.
1161
1162 :param kind: a :class:`.ObjectKind` that specifies the type of objects
1163 to reflect. Defaults to ``ObjectKind.TABLE``.
1164
1165 :param scope: a :class:`.ObjectScope` that specifies if indexes of
1166 default, temporary or any tables should be reflected.
1167 Defaults to ``ObjectScope.DEFAULT``.
1168
1169 :param \**kw: Additional keyword argument to pass to the dialect
1170 specific implementation. See the documentation of the dialect
1171 in use for more information.
1172
1173 :return: a dictionary where the keys are two-tuple schema,table-name
1174 and the values are list of dictionaries, each representing the
1175 definition of an index.
1176 The schema is ``None`` if no schema is provided.
1177
1178 .. versionadded:: 2.0
1179
1180 .. seealso:: :meth:`Inspector.get_indexes`
1181 """
1182
1183 with self._operation_context() as conn:
1184 return dict(
1185 self.dialect.get_multi_indexes(
1186 conn,
1187 schema=schema,
1188 filter_names=filter_names,
1189 kind=kind,
1190 scope=scope,
1191 info_cache=self.info_cache,
1192 **kw,
1193 )
1194 )
1195
1196 def get_unique_constraints(
1197 self, table_name: str, schema: Optional[str] = None, **kw: Any
1198 ) -> List[ReflectedUniqueConstraint]:
1199 r"""Return information about unique constraints in ``table_name``.
1200
