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