Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!sӢӢddl.pynu[# sql/ddl.py # Copyright (C) 2009-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """ Provides the hierarchy of DDL-defining schema items as well as routines to invoke them for a create/drop call. """ from .base import _bind_or_error from .base import _generative from .base import Executable from .base import SchemaVisitor from .elements import ClauseElement from .. import event from .. import exc from .. import util from ..util import topological class _DDLCompiles(ClauseElement): def _compiler(self, dialect, **kw): """Return a compiler appropriate for this ClauseElement, given a Dialect.""" return dialect.ddl_compiler(dialect, self, **kw) class DDLElement(Executable, _DDLCompiles): """Base class for DDL expression constructs. This class is the base for the general purpose :class:`.DDL` class, as well as the various create/drop clause constructs such as :class:`.CreateTable`, :class:`.DropTable`, :class:`.AddConstraint`, etc. :class:`.DDLElement` integrates closely with SQLAlchemy events, introduced in :ref:`event_toplevel`. An instance of one is itself an event receiving callable:: event.listen( users, 'after_create', AddConstraint(constraint).execute_if(dialect='postgresql') ) .. seealso:: :class:`.DDL` :class:`.DDLEvents` :ref:`event_toplevel` :ref:`schema_ddl_sequences` """ _execution_options = Executable._execution_options.union( {"autocommit": True} ) target = None on = None dialect = None callable_ = None def _execute_on_connection(self, connection, multiparams, params): return connection._execute_ddl(self, multiparams, params) def execute(self, bind=None, target=None): """Execute this DDL immediately. Executes the DDL statement in isolation using the supplied :class:`.Connectable` or :class:`.Connectable` assigned to the ``.bind`` property, if not supplied. If the DDL has a conditional ``on`` criteria, it will be invoked with None as the event. :param bind: Optional, an ``Engine`` or ``Connection``. If not supplied, a valid :class:`.Connectable` must be present in the ``.bind`` property. :param target: Optional, defaults to None. The target :class:`_schema.SchemaItem` for the execute call. Will be passed to the ``on`` callable if any, and may also provide string expansion data for the statement. See ``execute_at`` for more information. """ if bind is None: bind = _bind_or_error(self) if self._should_execute(target, bind): return bind.execute(self.against(target)) else: bind.engine.logger.info("DDL execution skipped, criteria not met.") @util.deprecated( "0.7", "The :meth:`.DDLElement.execute_at` method is deprecated and will " "be removed in a future release. Please use the :class:`.DDLEvents` " "listener interface in conjunction with the " ":meth:`.DDLElement.execute_if` method.", ) def execute_at(self, event_name, target): """Link execution of this DDL to the DDL lifecycle of a SchemaItem. Links this ``DDLElement`` to a ``Table`` or ``MetaData`` instance, executing it when that schema item is created or dropped. The DDL statement will be executed using the same Connection and transactional context as the Table create/drop itself. The ``.bind`` property of this statement is ignored. :param event: One of the events defined in the schema item's ``.ddl_events``; e.g. 'before-create', 'after-create', 'before-drop' or 'after-drop' :param target: The Table or MetaData instance for which this DDLElement will be associated with. A DDLElement instance can be linked to any number of schema items. ``execute_at`` builds on the ``append_ddl_listener`` interface of :class:`_schema.MetaData` and :class:`_schema.Table` objects. Caveat: Creating or dropping a Table in isolation will also trigger any DDL set to ``execute_at`` that Table's MetaData. This may change in a future release. """ def call_event(target, connection, **kw): if self._should_execute_deprecated( event_name, target, connection, **kw ): return connection.execute(self.against(target)) event.listen(target, "" + event_name.replace("-", "_"), call_event) @_generative def against(self, target): """Return a copy of this DDL against a specific schema item.""" self.target = target @_generative def execute_if(self, dialect=None, callable_=None, state=None): r"""Return a callable that will execute this DDLElement conditionally. Used to provide a wrapper for event listening:: event.listen( metadata, 'before_create', DDL("my_ddl").execute_if(dialect='postgresql') ) :param dialect: May be a string, tuple or a callable predicate. If a string, it will be compared to the name of the executing database dialect:: DDL('something').execute_if(dialect='postgresql') If a tuple, specifies multiple dialect names:: DDL('something').execute_if(dialect=('postgresql', 'mysql')) :param callable\_: A callable, which will be invoked with four positional arguments as well as optional keyword arguments: :ddl: This DDL element. :target: The :class:`_schema.Table` or :class:`_schema.MetaData` object which is the target of this event. May be None if the DDL is executed explicitly. :bind: The :class:`_engine.Connection` being used for DDL execution :tables: Optional keyword argument - a list of Table objects which are to be created/ dropped within a MetaData.create_all() or drop_all() method call. :state: Optional keyword argument - will be the ``state`` argument passed to this function. :checkfirst: Keyword argument, will be True if the 'checkfirst' flag was set during the call to ``create()``, ``create_all()``, ``drop()``, ``drop_all()``. If the callable returns a True value, the DDL statement will be executed. :param state: any value which will be passed to the callable\_ as the ``state`` keyword argument. .. seealso:: :class:`.DDLEvents` :ref:`event_toplevel` """ self.dialect = dialect self.callable_ = callable_ self.state = state def _should_execute(self, target, bind, **kw): if self.on is not None and not self._should_execute_deprecated( None, target, bind, **kw ): return False if isinstance(self.dialect, util.string_types): if self.dialect != bind.engine.name: return False elif isinstance(self.dialect, (tuple, list, set)): if bind.engine.name not in self.dialect: return False if self.callable_ is not None and not self.callable_( self, target, bind, state=self.state, **kw ): return False return True def _should_execute_deprecated(self, event, target, bind, **kw): if self.on is None: return True elif isinstance(self.on, util.string_types): return self.on == bind.engine.name elif isinstance(self.on, (tuple, list, set)): return bind.engine.name in self.on else: return self.on(self, event, target, bind, **kw) def __call__(self, target, bind, **kw): """Execute the DDL as a ddl_listener.""" if self._should_execute(target, bind, **kw): return bind.execute(self.against(target)) def _check_ddl_on(self, on): if on is not None and ( not isinstance(on, util.string_types + (tuple, list, set)) and not util.callable(on) ): raise exc.ArgumentError( "Expected the name of a database dialect, a tuple " "of names, or a callable for " "'on' criteria, got type '%s'." % type(on).__name__ ) def bind(self): if self._bind: return self._bind def _set_bind(self, bind): self._bind = bind bind = property(bind, _set_bind) def _generate(self): s = self.__class__.__new__(self.__class__) s.__dict__ = self.__dict__.copy() return s class DDL(DDLElement): """A literal DDL statement. Specifies literal SQL DDL to be executed by the database. DDL objects function as DDL event listeners, and can be subscribed to those events listed in :class:`.DDLEvents`, using either :class:`_schema.Table` or :class:`_schema.MetaData` objects as targets. Basic templating support allows a single DDL instance to handle repetitive tasks for multiple tables. Examples:: from sqlalchemy import event, DDL tbl = Table('users', metadata, Column('uid', Integer)) event.listen(tbl, 'before_create', DDL('DROP TRIGGER users_trigger')) spow = DDL('ALTER TABLE %(table)s SET secretpowers TRUE') event.listen(tbl, 'after_create', spow.execute_if(dialect='somedb')) drop_spow = DDL('ALTER TABLE users SET secretpowers FALSE') connection.execute(drop_spow) When operating on Table events, the following ``statement`` string substitutions are available:: %(table)s - the Table name, with any required quoting applied %(schema)s - the schema name, with any required quoting applied %(fullname)s - the Table name including schema, quoted if needed The DDL's "context", if any, will be combined with the standard substitutions noted above. Keys present in the context will override the standard substitutions. """ __visit_name__ = "ddl" @util.deprecated_params( on=( "0.7", "The :paramref:`.DDL.on` parameter is deprecated and will be " "removed in a future release. Please refer to " ":meth:`.DDLElement.execute_if`.", ) ) def __init__(self, statement, on=None, context=None, bind=None): """Create a DDL statement. :param statement: A string or unicode string to be executed. Statements will be processed with Python's string formatting operator. See the ``context`` argument and the ``execute_at`` method. A literal '%' in a statement must be escaped as '%%'. SQL bind parameters are not available in DDL statements. :param on: Optional filtering criteria. May be a string, tuple or a callable predicate. If a string, it will be compared to the name of the executing database dialect:: DDL('something', on='postgresql') If a tuple, specifies multiple dialect names:: DDL('something', on=('postgresql', 'mysql')) If a callable, it will be invoked with four positional arguments as well as optional keyword arguments: :ddl: This DDL element. :event: The name of the event that has triggered this DDL, such as 'after-create' Will be None if the DDL is executed explicitly. :target: The ``Table`` or ``MetaData`` object which is the target of this event. May be None if the DDL is executed explicitly. :connection: The ``Connection`` being used for DDL execution :tables: Optional keyword argument - a list of Table objects which are to be created/ dropped within a MetaData.create_all() or drop_all() method call. If the callable returns a true value, the DDL statement will be executed. :param context: Optional dictionary, defaults to None. These values will be available for use in string substitutions on the DDL statement. :param bind: Optional. A :class:`.Connectable`, used by default when ``execute()`` is invoked without a bind argument. .. seealso:: :class:`.DDLEvents` :ref:`event_toplevel` """ if not isinstance(statement, util.string_types): raise exc.ArgumentError( "Expected a string or unicode SQL statement, got '%r'" % statement ) self.statement = statement self.context = context or {} self._check_ddl_on(on) self.on = on self._bind = bind def __repr__(self): return "<%s@%s; %s>" % ( type(self).__name__, id(self), ", ".join( [repr(self.statement)] + [ "%s=%r" % (key, getattr(self, key)) for key in ("on", "context") if getattr(self, key) ] ), ) class _CreateDropBase(DDLElement): """Base class for DDL constructs that represent CREATE and DROP or equivalents. The common theme of _CreateDropBase is a single ``element`` attribute which refers to the element to be created or dropped. """ def __init__(self, element, on=None, bind=None): self.element = element self._check_ddl_on(on) self.on = on self.bind = bind def _create_rule_disable(self, compiler): """Allow disable of _create_rule using a callable. Pass to _create_rule using util.portable_instancemethod(self._create_rule_disable) to retain serializability. """ return False class CreateSchema(_CreateDropBase): """Represent a CREATE SCHEMA statement. The argument here is the string name of the schema. """ __visit_name__ = "create_schema" def __init__(self, name, quote=None, **kw): """Create a new :class:`.CreateSchema` construct.""" self.quote = quote super(CreateSchema, self).__init__(name, **kw) class DropSchema(_CreateDropBase): """Represent a DROP SCHEMA statement. The argument here is the string name of the schema. """ __visit_name__ = "drop_schema" def __init__(self, name, quote=None, cascade=False, **kw): """Create a new :class:`.DropSchema` construct.""" self.quote = quote self.cascade = cascade super(DropSchema, self).__init__(name, **kw) class CreateTable(_CreateDropBase): """Represent a CREATE TABLE statement.""" __visit_name__ = "create_table" def __init__( self, element, on=None, bind=None, include_foreign_key_constraints=None ): """Create a :class:`.CreateTable` construct. :param element: a :class:`_schema.Table` that's the subject of the CREATE :param on: See the description for 'on' in :class:`.DDL`. :param bind: See the description for 'bind' in :class:`.DDL`. :param include_foreign_key_constraints: optional sequence of :class:`_schema.ForeignKeyConstraint` objects that will be included inline within the CREATE construct; if omitted, all foreign key constraints that do not specify use_alter=True are included. .. versionadded:: 1.0.0 """ super(CreateTable, self).__init__(element, on=on, bind=bind) self.columns = [CreateColumn(column) for column in element.columns] self.include_foreign_key_constraints = include_foreign_key_constraints class _DropView(_CreateDropBase): """Semi-public 'DROP VIEW' construct. Used by the test suite for dialect-agnostic drops of views. This object will eventually be part of a public "view" API. """ __visit_name__ = "drop_view" class CreateColumn(_DDLCompiles): """Represent a :class:`_schema.Column` as rendered in a CREATE TABLE statement, via the :class:`.CreateTable` construct. This is provided to support custom column DDL within the generation of CREATE TABLE statements, by using the compiler extension documented in :ref:`sqlalchemy.ext.compiler_toplevel` to extend :class:`.CreateColumn`. Typical integration is to examine the incoming :class:`_schema.Column` object, and to redirect compilation if a particular flag or condition is found:: from sqlalchemy import schema from sqlalchemy.ext.compiler import compiles @compiles(schema.CreateColumn) def compile(element, compiler, **kw): column = element.element if "special" not in column.info: return compiler.visit_create_column(element, **kw) text = "%s SPECIAL DIRECTIVE %s" % ( column.name, compiler.type_compiler.process(column.type) ) default = compiler.get_column_default_string(column) if default is not None: text += " DEFAULT " + default if not column.nullable: text += " NOT NULL" if column.constraints: text += " ".join( compiler.process(const) for const in column.constraints) return text The above construct can be applied to a :class:`_schema.Table` as follows:: from sqlalchemy import Table, Metadata, Column, Integer, String from sqlalchemy import schema metadata = MetaData() table = Table('mytable', MetaData(), Column('x', Integer, info={"special":True}, primary_key=True), Column('y', String(50)), Column('z', String(20), info={"special":True}) ) metadata.create_all(conn) Above, the directives we've added to the :attr:`_schema.Column.info` collection will be detected by our custom compilation scheme:: CREATE TABLE mytable ( x SPECIAL DIRECTIVE INTEGER NOT NULL, y VARCHAR(50), z SPECIAL DIRECTIVE VARCHAR(20), PRIMARY KEY (x) ) The :class:`.CreateColumn` construct can also be used to skip certain columns when producing a ``CREATE TABLE``. This is accomplished by creating a compilation rule that conditionally returns ``None``. This is essentially how to produce the same effect as using the ``system=True`` argument on :class:`_schema.Column`, which marks a column as an implicitly-present "system" column. For example, suppose we wish to produce a :class:`_schema.Table` which skips rendering of the PostgreSQL ``xmin`` column against the PostgreSQL backend, but on other backends does render it, in anticipation of a triggered rule. A conditional compilation rule could skip this name only on PostgreSQL:: from sqlalchemy.schema import CreateColumn @compiles(CreateColumn, "postgresql") def skip_xmin(element, compiler, **kw): if element.element.name == 'xmin': return None else: return compiler.visit_create_column(element, **kw) my_table = Table('mytable', metadata, Column('id', Integer, primary_key=True), Column('xmin', Integer) ) Above, a :class:`.CreateTable` construct will generate a ``CREATE TABLE`` which only includes the ``id`` column in the string; the ``xmin`` column will be omitted, but only against the PostgreSQL backend. """ __visit_name__ = "create_column" def __init__(self, element): self.element = element class DropTable(_CreateDropBase): """Represent a DROP TABLE statement.""" __visit_name__ = "drop_table" class CreateSequence(_CreateDropBase): """Represent a CREATE SEQUENCE statement.""" __visit_name__ = "create_sequence" class DropSequence(_CreateDropBase): """Represent a DROP SEQUENCE statement.""" __visit_name__ = "drop_sequence" class CreateIndex(_CreateDropBase): """Represent a CREATE INDEX statement.""" __visit_name__ = "create_index" class DropIndex(_CreateDropBase): """Represent a DROP INDEX statement.""" __visit_name__ = "drop_index" class AddConstraint(_CreateDropBase): """Represent an ALTER TABLE ADD CONSTRAINT statement.""" __visit_name__ = "add_constraint" def __init__(self, element, *args, **kw): super(AddConstraint, self).__init__(element, *args, **kw) element._create_rule = util.portable_instancemethod( self._create_rule_disable ) class DropConstraint(_CreateDropBase): """Represent an ALTER TABLE DROP CONSTRAINT statement.""" __visit_name__ = "drop_constraint" def __init__(self, element, cascade=False, **kw): self.cascade = cascade super(DropConstraint, self).__init__(element, **kw) element._create_rule = util.portable_instancemethod( self._create_rule_disable ) class SetTableComment(_CreateDropBase): """Represent a COMMENT ON TABLE IS statement.""" __visit_name__ = "set_table_comment" class DropTableComment(_CreateDropBase): """Represent a COMMENT ON TABLE '' statement. Note this varies a lot across database backends. """ __visit_name__ = "drop_table_comment" class SetColumnComment(_CreateDropBase): """Represent a COMMENT ON COLUMN IS statement.""" __visit_name__ = "set_column_comment" class DropColumnComment(_CreateDropBase): """Represent a COMMENT ON COLUMN IS NULL statement.""" __visit_name__ = "drop_column_comment" class DDLBase(SchemaVisitor): def __init__(self, connection): self.connection = connection class SchemaGenerator(DDLBase): def __init__( self, dialect, connection, checkfirst=False, tables=None, **kwargs ): super(SchemaGenerator, self).__init__(connection, **kwargs) self.checkfirst = checkfirst self.tables = tables self.preparer = dialect.identifier_preparer self.dialect = dialect self.memo = {} def _can_create_table(self, table): self.dialect.validate_identifier(table.name) effective_schema = self.connection.schema_for_object(table) if effective_schema: self.dialect.validate_identifier(effective_schema) return not self.checkfirst or not self.dialect.has_table( self.connection, table.name, schema=effective_schema ) def _can_create_sequence(self, sequence): effective_schema = self.connection.schema_for_object(sequence) return self.dialect.supports_sequences and ( (not self.dialect.sequences_optional or not sequence.optional) and ( not self.checkfirst or not self.dialect.has_sequence( self.connection, sequence.name, schema=effective_schema ) ) ) def visit_metadata(self, metadata): if self.tables is not None: tables = self.tables else: tables = list(metadata.tables.values()) collection = sort_tables_and_constraints( [t for t in tables if self._can_create_table(t)] ) seq_coll = [ s for s in metadata._sequences.values() if s.column is None and self._can_create_sequence(s) ] event_collection = [t for (t, fks) in collection if t is not None] metadata.dispatch.before_create( metadata, self.connection, tables=event_collection, checkfirst=self.checkfirst, _ddl_runner=self, ) for seq in seq_coll: self.traverse_single(seq, create_ok=True) for table, fkcs in collection: if table is not None: self.traverse_single( table, create_ok=True, include_foreign_key_constraints=fkcs, _is_metadata_operation=True, ) else: for fkc in fkcs: self.traverse_single(fkc) metadata.dispatch.after_create( metadata, self.connection, tables=event_collection, checkfirst=self.checkfirst, _ddl_runner=self, ) def visit_table( self, table, create_ok=False, include_foreign_key_constraints=None, _is_metadata_operation=False, ): if not create_ok and not self._can_create_table(table): return table.dispatch.before_create( table, self.connection, checkfirst=self.checkfirst, _ddl_runner=self, _is_metadata_operation=_is_metadata_operation, ) for column in table.columns: if column.default is not None: self.traverse_single(column.default) if not self.dialect.supports_alter: # e.g., don't omit any foreign key constraints include_foreign_key_constraints = None self.connection.execute( # fmt: off CreateTable( table, include_foreign_key_constraints= # noqa include_foreign_key_constraints, # noqa ) # fmt: on ) if hasattr(table, "indexes"): for index in table.indexes: self.traverse_single(index) if self.dialect.supports_comments and not self.dialect.inline_comments: if table.comment is not None: self.connection.execute(SetTableComment(table)) for column in table.columns: if column.comment is not None: self.connection.execute(SetColumnComment(column)) table.dispatch.after_create( table, self.connection, checkfirst=self.checkfirst, _ddl_runner=self, _is_metadata_operation=_is_metadata_operation, ) def visit_foreign_key_constraint(self, constraint): if not self.dialect.supports_alter: return self.connection.execute(AddConstraint(constraint)) def visit_sequence(self, sequence, create_ok=False): if not create_ok and not self._can_create_sequence(sequence): return self.connection.execute(CreateSequence(sequence)) def visit_index(self, index): self.connection.execute(CreateIndex(index)) class SchemaDropper(DDLBase): def __init__( self, dialect, connection, checkfirst=False, tables=None, **kwargs ): super(SchemaDropper, self).__init__(connection, **kwargs) self.checkfirst = checkfirst self.tables = tables self.preparer = dialect.identifier_preparer self.dialect = dialect self.memo = {} def visit_metadata(self, metadata): if self.tables is not None: tables = self.tables else: tables = list(metadata.tables.values()) try: unsorted_tables = [t for t in tables if self._can_drop_table(t)] collection = list( reversed( sort_tables_and_constraints( unsorted_tables, filter_fn=lambda constraint: False if not self.dialect.supports_alter or constraint.name is None else None, ) ) ) except exc.CircularDependencyError as err2: if not self.dialect.supports_alter: util.warn( "Can't sort tables for DROP; an " "unresolvable foreign key " "dependency exists between tables: %s; and backend does " "not support ALTER. To restore at least a partial sort, " "apply use_alter=True to ForeignKey and " "ForeignKeyConstraint " "objects involved in the cycle to mark these as known " "cycles that will be ignored." % (", ".join(sorted([t.fullname for t in err2.cycles]))) ) collection = [(t, ()) for t in unsorted_tables] else: util.raise_( exc.CircularDependencyError( err2.args[0], err2.cycles, err2.edges, msg="Can't sort tables for DROP; an " "unresolvable foreign key " "dependency exists between tables: %s. Please ensure " "that the ForeignKey and ForeignKeyConstraint objects " "involved in the cycle have " "names so that they can be dropped using " "DROP CONSTRAINT." % ( ", ".join( sorted([t.fullname for t in err2.cycles]) ) ), ), from_=err2, ) seq_coll = [ s for s in metadata._sequences.values() if self._can_drop_sequence(s) ] event_collection = [t for (t, fks) in collection if t is not None] metadata.dispatch.before_drop( metadata, self.connection, tables=event_collection, checkfirst=self.checkfirst, _ddl_runner=self, ) for table, fkcs in collection: if table is not None: self.traverse_single( table, drop_ok=True, _is_metadata_operation=True, _ignore_sequences=seq_coll, ) else: for fkc in fkcs: self.traverse_single(fkc) for seq in seq_coll: self.traverse_single(seq, drop_ok=seq.column is None) metadata.dispatch.after_drop( metadata, self.connection, tables=event_collection, checkfirst=self.checkfirst, _ddl_runner=self, ) def _can_drop_table(self, table): self.dialect.validate_identifier(table.name) effective_schema = self.connection.schema_for_object(table) if effective_schema: self.dialect.validate_identifier(effective_schema) return not self.checkfirst or self.dialect.has_table( self.connection, table.name, schema=effective_schema ) def _can_drop_sequence(self, sequence): effective_schema = self.connection.schema_for_object(sequence) return self.dialect.supports_sequences and ( (not self.dialect.sequences_optional or not sequence.optional) and ( not self.checkfirst or self.dialect.has_sequence( self.connection, sequence.name, schema=effective_schema ) ) ) def visit_index(self, index): self.connection.execute(DropIndex(index)) def visit_table( self, table, drop_ok=False, _is_metadata_operation=False, _ignore_sequences=[], ): if not drop_ok and not self._can_drop_table(table): return table.dispatch.before_drop( table, self.connection, checkfirst=self.checkfirst, _ddl_runner=self, _is_metadata_operation=_is_metadata_operation, ) self.connection.execute(DropTable(table)) # traverse client side defaults which may refer to server-side # sequences. noting that some of these client side defaults may also be # set up as server side defaults (see http://docs.sqlalchemy.org/en/ # latest/core/defaults.html#associating-a-sequence-as-the-server-side- # default), so have to be dropped after the table is dropped. for column in table.columns: if ( column.default is not None and column.default not in _ignore_sequences ): self.traverse_single(column.default) table.dispatch.after_drop( table, self.connection, checkfirst=self.checkfirst, _ddl_runner=self, _is_metadata_operation=_is_metadata_operation, ) def visit_foreign_key_constraint(self, constraint): if not self.dialect.supports_alter: return self.connection.execute(DropConstraint(constraint)) def visit_sequence(self, sequence, drop_ok=False): if not drop_ok and not self._can_drop_sequence(sequence): return self.connection.execute(DropSequence(sequence)) def sort_tables( tables, skip_fn=None, extra_dependencies=None, ): """Sort a collection of :class:`_schema.Table` objects based on dependency. This is a dependency-ordered sort which will emit :class:`_schema.Table` objects such that they will follow their dependent :class:`_schema.Table` objects. Tables are dependent on another based on the presence of :class:`_schema.ForeignKeyConstraint` objects as well as explicit dependencies added by :meth:`_schema.Table.add_is_dependent_on`. .. warning:: The :func:`._schema.sort_tables` function cannot by itself accommodate automatic resolution of dependency cycles between tables, which are usually caused by mutually dependent foreign key constraints. When these cycles are detected, the foreign keys of these tables are omitted from consideration in the sort. A warning is emitted when this condition occurs, which will be an exception raise in a future release. Tables which are not part of the cycle will still be returned in dependency order. To resolve these cycles, the :paramref:`_schema.ForeignKeyConstraint.use_alter` parameter may be applied to those constraints which create a cycle. Alternatively, the :func:`_schema.sort_tables_and_constraints` function will automatically return foreign key constraints in a separate collection when cycles are detected so that they may be applied to a schema separately. .. versionchanged:: 1.3.17 - a warning is emitted when :func:`_schema.sort_tables` cannot perform a proper sort due to cyclical dependencies. This will be an exception in a future release. Additionally, the sort will continue to return other tables not involved in the cycle in dependency order which was not the case previously. :param tables: a sequence of :class:`_schema.Table` objects. :param skip_fn: optional callable which will be passed a :class:`_schema.ForeignKey` object; if it returns True, this constraint will not be considered as a dependency. Note this is **different** from the same parameter in :func:`.sort_tables_and_constraints`, which is instead passed the owning :class:`_schema.ForeignKeyConstraint` object. :param extra_dependencies: a sequence of 2-tuples of tables which will also be considered as dependent on each other. .. seealso:: :func:`.sort_tables_and_constraints` :attr:`_schema.MetaData.sorted_tables` - uses this function to sort """ if skip_fn is not None: def _skip_fn(fkc): for fk in fkc.elements: if skip_fn(fk): return True else: return None else: _skip_fn = None return [ t for (t, fkcs) in sort_tables_and_constraints( tables, filter_fn=_skip_fn, extra_dependencies=extra_dependencies, _warn_for_cycles=True, ) if t is not None ] def sort_tables_and_constraints( tables, filter_fn=None, extra_dependencies=None, _warn_for_cycles=False ): """Sort a collection of :class:`_schema.Table` / :class:`_schema.ForeignKeyConstraint` objects. This is a dependency-ordered sort which will emit tuples of ``(Table, [ForeignKeyConstraint, ...])`` such that each :class:`_schema.Table` follows its dependent :class:`_schema.Table` objects. Remaining :class:`_schema.ForeignKeyConstraint` objects that are separate due to dependency rules not satisfied by the sort are emitted afterwards as ``(None, [ForeignKeyConstraint ...])``. Tables are dependent on another based on the presence of :class:`_schema.ForeignKeyConstraint` objects, explicit dependencies added by :meth:`_schema.Table.add_is_dependent_on`, as well as dependencies stated here using the :paramref:`~.sort_tables_and_constraints.skip_fn` and/or :paramref:`~.sort_tables_and_constraints.extra_dependencies` parameters. :param tables: a sequence of :class:`_schema.Table` objects. :param filter_fn: optional callable which will be passed a :class:`_schema.ForeignKeyConstraint` object, and returns a value based on whether this constraint should definitely be included or excluded as an inline constraint, or neither. If it returns False, the constraint will definitely be included as a dependency that cannot be subject to ALTER; if True, it will **only** be included as an ALTER result at the end. Returning None means the constraint is included in the table-based result unless it is detected as part of a dependency cycle. :param extra_dependencies: a sequence of 2-tuples of tables which will also be considered as dependent on each other. .. versionadded:: 1.0.0 .. seealso:: :func:`.sort_tables` """ fixed_dependencies = set() mutable_dependencies = set() if extra_dependencies is not None: fixed_dependencies.update(extra_dependencies) remaining_fkcs = set() for table in tables: for fkc in table.foreign_key_constraints: if fkc.use_alter is True: remaining_fkcs.add(fkc) continue if filter_fn: filtered = filter_fn(fkc) if filtered is True: remaining_fkcs.add(fkc) continue dependent_on = fkc.referred_table if dependent_on is not table: mutable_dependencies.add((dependent_on, table)) fixed_dependencies.update( (parent, table) for parent in table._extra_dependencies ) try: candidate_sort = list( topological.sort( fixed_dependencies.union(mutable_dependencies), tables, deterministic_order=True, ) ) except exc.CircularDependencyError as err: if _warn_for_cycles: util.warn( "Cannot correctly sort tables; there are unresolvable cycles " 'between tables "%s", which is usually caused by mutually ' "dependent foreign key constraints. Foreign key constraints " "involving these tables will not be considered; this warning " "may raise an error in a future release." % (", ".join(sorted(t.fullname for t in err.cycles)),) ) for edge in err.edges: if edge in mutable_dependencies: table = edge[1] if table not in err.cycles: continue can_remove = [ fkc for fkc in table.foreign_key_constraints if filter_fn is None or filter_fn(fkc) is not False ] remaining_fkcs.update(can_remove) for fkc in can_remove: dependent_on = fkc.referred_table if dependent_on is not table: mutable_dependencies.discard((dependent_on, table)) candidate_sort = list( topological.sort( fixed_dependencies.union(mutable_dependencies), tables, deterministic_order=True, ) ) return [ (table, table.foreign_key_constraints.difference(remaining_fkcs)) for table in candidate_sort ] + [(None, list(remaining_fkcs))] PK!B  compiler.pynu[# sql/compiler.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Base SQL and DDL compiler implementations. Classes provided include: :class:`.compiler.SQLCompiler` - renders SQL strings :class:`.compiler.DDLCompiler` - renders DDL (data definition language) strings :class:`.compiler.GenericTypeCompiler` - renders type specification strings. To generate user-defined SQL strings, see :doc:`/ext/compiler`. """ import contextlib import itertools import re from . import crud from . import elements from . import functions from . import operators from . import schema from . import selectable from . import sqltypes from . import visitors from .. import exc from .. import util RESERVED_WORDS = set( [ "all", "analyse", "analyze", "and", "any", "array", "as", "asc", "asymmetric", "authorization", "between", "binary", "both", "case", "cast", "check", "collate", "column", "constraint", "create", "cross", "current_date", "current_role", "current_time", "current_timestamp", "current_user", "default", "deferrable", "desc", "distinct", "do", "else", "end", "except", "false", "for", "foreign", "freeze", "from", "full", "grant", "group", "having", "ilike", "in", "initially", "inner", "intersect", "into", "is", "isnull", "join", "leading", "left", "like", "limit", "localtime", "localtimestamp", "natural", "new", "not", "notnull", "null", "off", "offset", "old", "on", "only", "or", "order", "outer", "overlaps", "placing", "primary", "references", "right", "select", "session_user", "set", "similar", "some", "symmetric", "table", "then", "to", "trailing", "true", "union", "unique", "user", "using", "verbose", "when", "where", ] ) LEGAL_CHARACTERS = re.compile(r"^[A-Z0-9_$]+$", re.I) LEGAL_CHARACTERS_PLUS_SPACE = re.compile(r"^[A-Z0-9_ $]+$", re.I) ILLEGAL_INITIAL_CHARACTERS = {str(x) for x in range(0, 10)}.union(["$"]) FK_ON_DELETE = re.compile( r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I ) FK_ON_UPDATE = re.compile( r"^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$", re.I ) FK_INITIALLY = re.compile(r"^(?:DEFERRED|IMMEDIATE)$", re.I) BIND_PARAMS = re.compile(r"(? ", operators.ge: " >= ", operators.eq: " = ", operators.is_distinct_from: " IS DISTINCT FROM ", operators.isnot_distinct_from: " IS NOT DISTINCT FROM ", operators.concat_op: " || ", operators.match_op: " MATCH ", operators.notmatch_op: " NOT MATCH ", operators.in_op: " IN ", operators.notin_op: " NOT IN ", operators.comma_op: ", ", operators.from_: " FROM ", operators.as_: " AS ", operators.is_: " IS ", operators.isnot: " IS NOT ", operators.collate: " COLLATE ", # unary operators.exists: "EXISTS ", operators.distinct_op: "DISTINCT ", operators.inv: "NOT ", operators.any_op: "ANY ", operators.all_op: "ALL ", # modifiers operators.desc_op: " DESC", operators.asc_op: " ASC", operators.nullsfirst_op: " NULLS FIRST", operators.nullslast_op: " NULLS LAST", } FUNCTIONS = { functions.coalesce: "coalesce", functions.current_date: "CURRENT_DATE", functions.current_time: "CURRENT_TIME", functions.current_timestamp: "CURRENT_TIMESTAMP", functions.current_user: "CURRENT_USER", functions.localtime: "LOCALTIME", functions.localtimestamp: "LOCALTIMESTAMP", functions.random: "random", functions.sysdate: "sysdate", functions.session_user: "SESSION_USER", functions.user: "USER", functions.cube: "CUBE", functions.rollup: "ROLLUP", functions.grouping_sets: "GROUPING SETS", } EXTRACT_MAP = { "month": "month", "day": "day", "year": "year", "second": "second", "hour": "hour", "doy": "doy", "minute": "minute", "quarter": "quarter", "dow": "dow", "week": "week", "epoch": "epoch", "milliseconds": "milliseconds", "microseconds": "microseconds", "timezone_hour": "timezone_hour", "timezone_minute": "timezone_minute", } COMPOUND_KEYWORDS = { selectable.CompoundSelect.UNION: "UNION", selectable.CompoundSelect.UNION_ALL: "UNION ALL", selectable.CompoundSelect.EXCEPT: "EXCEPT", selectable.CompoundSelect.EXCEPT_ALL: "EXCEPT ALL", selectable.CompoundSelect.INTERSECT: "INTERSECT", selectable.CompoundSelect.INTERSECT_ALL: "INTERSECT ALL", } class Compiled(object): """Represent a compiled SQL or DDL expression. The ``__str__`` method of the ``Compiled`` object should produce the actual text of the statement. ``Compiled`` objects are specific to their underlying database dialect, and also may or may not be specific to the columns referenced within a particular set of bind parameters. In no case should the ``Compiled`` object be dependent on the actual values of those bind parameters, even though it may reference those values as defaults. """ _cached_metadata = None schema_translate_map = None execution_options = util.immutabledict() """ Execution options propagated from the statement. In some cases, sub-elements of the statement can modify these. """ def __init__( self, dialect, statement, bind=None, schema_translate_map=None, compile_kwargs=util.immutabledict(), ): """Construct a new :class:`.Compiled` object. :param dialect: :class:`.Dialect` to compile against. :param statement: :class:`_expression.ClauseElement` to be compiled. :param bind: Optional Engine or Connection to compile this statement against. :param schema_translate_map: dictionary of schema names to be translated when forming the resultant SQL .. versionadded:: 1.1 .. seealso:: :ref:`schema_translating` :param compile_kwargs: additional kwargs that will be passed to the initial call to :meth:`.Compiled.process`. """ self.dialect = dialect self.bind = bind self.preparer = self.dialect.identifier_preparer self.schema_translate_map = schema_translate_map if schema_translate_map: self.preparer = self.preparer._with_schema_translate( schema_translate_map ) if statement is not None: self.statement = statement self.can_execute = statement.supports_execution if self.can_execute: self.execution_options = statement._execution_options self.string = self.process(self.statement, **compile_kwargs) @util.deprecated( "0.7", "The :meth:`.Compiled.compile` method is deprecated and will be " "removed in a future release. The :class:`.Compiled` object " "now runs its compilation within the constructor, and this method " "does nothing.", ) def compile(self): """Produce the internal string representation of this element.""" pass def _execute_on_connection(self, connection, multiparams, params): if self.can_execute: return connection._execute_compiled(self, multiparams, params) else: raise exc.ObjectNotExecutableError(self.statement) @property def sql_compiler(self): """Return a Compiled that is capable of processing SQL expressions. If this compiler is one, it would likely just return 'self'. """ raise NotImplementedError() def process(self, obj, **kwargs): return obj._compiler_dispatch(self, **kwargs) def __str__(self): """Return the string text of the generated SQL or DDL.""" return self.string or "" def construct_params(self, params=None): """Return the bind params for this compiled object. :param params: a dict of string/object pairs whose values will override bind values compiled in to the statement. """ raise NotImplementedError() @property def params(self): """Return the bind params for this compiled object.""" return self.construct_params() def execute(self, *multiparams, **params): """Execute this compiled object.""" e = self.bind if e is None: raise exc.UnboundExecutionError( "This Compiled object is not bound to any Engine " "or Connection.", code="2afi", ) return e._execute_compiled(self, multiparams, params) def scalar(self, *multiparams, **params): """Execute this compiled object and return the result's scalar value.""" return self.execute(*multiparams, **params).scalar() class TypeCompiler(util.with_metaclass(util.EnsureKWArgType, object)): """Produces DDL specification for TypeEngine objects.""" ensure_kwarg = r"visit_\w+" def __init__(self, dialect): self.dialect = dialect def process(self, type_, **kw): return type_._compiler_dispatch(self, **kw) class _CompileLabel(visitors.Visitable): """lightweight label object which acts as an expression.Label.""" __visit_name__ = "label" __slots__ = "element", "name" def __init__(self, col, name, alt_names=()): self.element = col self.name = name self._alt_names = (col,) + alt_names @property def proxy_set(self): return self.element.proxy_set @property def type(self): return self.element.type def self_group(self, **kw): return self class prefix_anon_map(dict): """A map that creates new keys for missing key access. Considers keys of the form " " to produce new symbols "_", where "index" is an incrementing integer corresponding to . Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which is otherwise usually used for this type of operation. """ def __missing__(self, key): (ident, derived) = key.split(" ", 1) anonymous_counter = self.get(derived, 1) self[derived] = anonymous_counter + 1 value = derived + "_" + str(anonymous_counter) self[key] = value return value class SQLCompiler(Compiled): """Default implementation of :class:`.Compiled`. Compiles :class:`_expression.ClauseElement` objects into SQL strings. """ extract_map = EXTRACT_MAP compound_keywords = COMPOUND_KEYWORDS isdelete = isinsert = isupdate = False """class-level defaults which can be set at the instance level to define if this Compiled instance represents INSERT/UPDATE/DELETE """ isplaintext = False returning = None """holds the "returning" collection of columns if the statement is CRUD and defines returning columns either implicitly or explicitly """ returning_precedes_values = False """set to True classwide to generate RETURNING clauses before the VALUES or WHERE clause (i.e. MSSQL) """ render_table_with_column_in_update_from = False """set to True classwide to indicate the SET clause in a multi-table UPDATE statement should qualify columns with the table name (i.e. MySQL only) """ contains_expanding_parameters = False """True if we've encountered bindparam(..., expanding=True). These need to be converted before execution time against the string statement. """ ansi_bind_rules = False """SQL 92 doesn't allow bind parameters to be used in the columns clause of a SELECT, nor does it allow ambiguous expressions like "? = ?". A compiler subclass can set this flag to False if the target driver/DB enforces this """ _textual_ordered_columns = False """tell the result object that the column names as rendered are important, but they are also "ordered" vs. what is in the compiled object here. """ _ordered_columns = True """ if False, means we can't be sure the list of entries in _result_columns is actually the rendered order. Usually True unless using an unordered TextAsFrom. """ _numeric_binds = False """ True if paramstyle is "numeric". This paramstyle is trickier than all the others. """ insert_single_values_expr = None """When an INSERT is compiled with a single set of parameters inside a VALUES expression, the string is assigned here, where it can be used for insert batching schemes to rewrite the VALUES expression. .. versionadded:: 1.3.8 """ insert_prefetch = update_prefetch = () def __init__( self, dialect, statement, column_keys=None, inline=False, **kwargs ): """Construct a new :class:`.SQLCompiler` object. :param dialect: :class:`.Dialect` to be used :param statement: :class:`_expression.ClauseElement` to be compiled :param column_keys: a list of column names to be compiled into an INSERT or UPDATE statement. :param inline: whether to generate INSERT statements as "inline", e.g. not formatted to return any generated defaults :param kwargs: additional keyword arguments to be consumed by the superclass. """ self.column_keys = column_keys # compile INSERT/UPDATE defaults/sequences inlined (no pre- # execute) self.inline = inline or getattr(statement, "inline", False) # a dictionary of bind parameter keys to BindParameter # instances. self.binds = {} # a dictionary of BindParameter instances to "compiled" names # that are actually present in the generated SQL self.bind_names = util.column_dict() # stack which keeps track of nested SELECT statements self.stack = [] # relates label names in the final SQL to a tuple of local # column/label name, ColumnElement object (if any) and # TypeEngine. ResultProxy uses this for type processing and # column targeting self._result_columns = [] # true if the paramstyle is positional self.positional = dialect.positional if self.positional: self.positiontup = [] self._numeric_binds = dialect.paramstyle == "numeric" self.bindtemplate = BIND_TEMPLATES[dialect.paramstyle] self.ctes = None self.label_length = ( dialect.label_length or dialect.max_identifier_length ) # a map which tracks "anonymous" identifiers that are created on # the fly here self.anon_map = prefix_anon_map() # a map which tracks "truncated" names based on # dialect.label_length or dialect.max_identifier_length self.truncated_names = {} Compiled.__init__(self, dialect, statement, **kwargs) if ( self.isinsert or self.isupdate or self.isdelete ) and statement._returning: self.returning = statement._returning if self.positional and self._numeric_binds: self._apply_numbered_params() @property def current_executable(self): """Return the current 'executable' that is being compiled. This is currently the :class:`_sql.Select`, :class:`_sql.Insert`, :class:`_sql.Update`, :class:`_sql.Delete`, :class:`_sql.CompoundSelect` object that is being compiled. Specifically it's assigned to the ``self.stack`` list of elements. When a statement like the above is being compiled, it normally is also assigned to the ``.statement`` attribute of the :class:`_sql.Compiler` object. However, all SQL constructs are ultimately nestable, and this attribute should never be consulted by a ``visit_`` method, as it is not guaranteed to be assigned nor guaranteed to correspond to the current statement being compiled. .. versionadded:: 1.3.21 For compatibility with previous versions, use the following recipe:: statement = getattr(self, "current_executable", False) if statement is False: statement = self.stack[-1]["selectable"] For versions 1.4 and above, ensure only .current_executable is used; the format of "self.stack" may change. """ try: return self.stack[-1]["selectable"] except IndexError as ie: util.raise_( IndexError("Compiler does not have a stack entry"), replace_context=ie, ) @property def prefetch(self): return list(self.insert_prefetch + self.update_prefetch) @util.memoized_instancemethod def _init_cte_state(self): """Initialize collections related to CTEs only if a CTE is located, to save on the overhead of these collections otherwise. """ # collect CTEs to tack on top of a SELECT self.ctes = util.OrderedDict() self.ctes_by_name = {} self.ctes_recursive = False if self.positional: self.cte_positional = {} @contextlib.contextmanager def _nested_result(self): """special API to support the use case of 'nested result sets'""" result_columns, ordered_columns = ( self._result_columns, self._ordered_columns, ) self._result_columns, self._ordered_columns = [], False try: if self.stack: entry = self.stack[-1] entry["need_result_map_for_nested"] = True else: entry = None yield self._result_columns, self._ordered_columns finally: if entry: entry.pop("need_result_map_for_nested") self._result_columns, self._ordered_columns = ( result_columns, ordered_columns, ) def _apply_numbered_params(self): poscount = itertools.count(1) self.string = re.sub( r"\[_POSITION\]", lambda m: str(util.next(poscount)), self.string ) @util.memoized_property def _bind_processors(self): return dict( (key, value) for key, value in ( ( self.bind_names[bindparam], bindparam.type._cached_bind_processor(self.dialect), ) for bindparam in self.bind_names ) if value is not None ) def is_subquery(self): return len(self.stack) > 1 @property def sql_compiler(self): return self def construct_params(self, params=None, _group_number=None, _check=True): """return a dictionary of bind parameter keys and values""" if params: pd = {} for bindparam in self.bind_names: name = self.bind_names[bindparam] if bindparam.key in params: pd[name] = params[bindparam.key] elif name in params: pd[name] = params[name] elif _check and bindparam.required: if _group_number: raise exc.InvalidRequestError( "A value is required for bind parameter %r, " "in parameter group %d" % (bindparam.key, _group_number), code="cd3x", ) else: raise exc.InvalidRequestError( "A value is required for bind parameter %r" % bindparam.key, code="cd3x", ) elif bindparam.callable: pd[name] = bindparam.effective_value else: pd[name] = bindparam.value return pd else: pd = {} for bindparam in self.bind_names: if _check and bindparam.required: if _group_number: raise exc.InvalidRequestError( "A value is required for bind parameter %r, " "in parameter group %d" % (bindparam.key, _group_number), code="cd3x", ) else: raise exc.InvalidRequestError( "A value is required for bind parameter %r" % bindparam.key, code="cd3x", ) if bindparam.callable: pd[self.bind_names[bindparam]] = bindparam.effective_value else: pd[self.bind_names[bindparam]] = bindparam.value return pd @property def params(self): """Return the bind param dictionary embedded into this compiled object, for those values that are present.""" return self.construct_params(_check=False) @util.dependencies("sqlalchemy.engine.result") def _create_result_map(self, result): """utility method used for unit tests only.""" return result.ResultMetaData._create_result_map(self._result_columns) def default_from(self): """Called when a SELECT statement has no froms, and no FROM clause is to be appended. Gives Oracle a chance to tack on a ``FROM DUAL`` to the string output. """ return "" def visit_grouping(self, grouping, asfrom=False, **kwargs): return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")" def visit_label_reference( self, element, within_columns_clause=False, **kwargs ): if self.stack and self.dialect.supports_simple_order_by_label: selectable = self.stack[-1]["selectable"] with_cols, only_froms, only_cols = selectable._label_resolve_dict if within_columns_clause: resolve_dict = only_froms else: resolve_dict = only_cols # this can be None in the case that a _label_reference() # were subject to a replacement operation, in which case # the replacement of the Label element may have changed # to something else like a ColumnClause expression. order_by_elem = element.element._order_by_label_element if ( order_by_elem is not None and order_by_elem.name in resolve_dict and order_by_elem.shares_lineage( resolve_dict[order_by_elem.name] ) ): kwargs[ "render_label_as_label" ] = element.element._order_by_label_element return self.process( element.element, within_columns_clause=within_columns_clause, **kwargs ) def visit_textual_label_reference( self, element, within_columns_clause=False, **kwargs ): if not self.stack: # compiling the element outside of the context of a SELECT return self.process(element._text_clause) selectable = self.stack[-1]["selectable"] with_cols, only_froms, only_cols = selectable._label_resolve_dict try: if within_columns_clause: col = only_froms[element.element] else: col = with_cols[element.element] except KeyError as ke: elements._no_text_coercion( element.element, exc.CompileError, "Can't resolve label reference for ORDER BY / " "GROUP BY / DISTINCT etc.", err=ke, ) else: kwargs["render_label_as_label"] = col return self.process( col, within_columns_clause=within_columns_clause, **kwargs ) def visit_label( self, label, add_to_result_map=None, within_label_clause=False, within_columns_clause=False, render_label_as_label=None, **kw ): # only render labels within the columns clause # or ORDER BY clause of a select. dialect-specific compilers # can modify this behavior. render_label_with_as = ( within_columns_clause and not within_label_clause ) render_label_only = render_label_as_label is label if render_label_only or render_label_with_as: if isinstance(label.name, elements._truncated_label): labelname = self._truncated_identifier("colident", label.name) else: labelname = label.name if render_label_with_as: if add_to_result_map is not None: add_to_result_map( labelname, label.name, (label, labelname) + label._alt_names, label.type, ) return ( label.element._compiler_dispatch( self, within_columns_clause=True, within_label_clause=True, **kw ) + OPERATORS[operators.as_] + self.preparer.format_label(label, labelname) ) elif render_label_only: return self.preparer.format_label(label, labelname) else: return label.element._compiler_dispatch( self, within_columns_clause=False, **kw ) def _fallback_column_name(self, column): raise exc.CompileError( "Cannot compile Column object until " "its 'name' is assigned." ) def visit_column( self, column, add_to_result_map=None, include_table=True, **kwargs ): name = orig_name = column.name if name is None: name = self._fallback_column_name(column) is_literal = column.is_literal if not is_literal and isinstance(name, elements._truncated_label): name = self._truncated_identifier("colident", name) if add_to_result_map is not None: add_to_result_map( name, orig_name, (column, name, column.key), column.type ) if is_literal: # note we are not currently accommodating for # literal_column(quoted_name('ident', True)) here name = self.escape_literal_column(name) else: name = self.preparer.quote(name) table = column.table if table is None or not include_table or not table.named_with_column: return name else: effective_schema = self.preparer.schema_for_object(table) if effective_schema: schema_prefix = ( self.preparer.quote_schema(effective_schema) + "." ) else: schema_prefix = "" tablename = table.name if isinstance(tablename, elements._truncated_label): tablename = self._truncated_identifier("alias", tablename) return schema_prefix + self.preparer.quote(tablename) + "." + name def visit_collation(self, element, **kw): return self.preparer.format_collation(element.collation) def visit_fromclause(self, fromclause, **kwargs): return fromclause.name def visit_index(self, index, **kwargs): return index.name def visit_typeclause(self, typeclause, **kw): kw["type_expression"] = typeclause return self.dialect.type_compiler.process(typeclause.type, **kw) def post_process_text(self, text): if self.preparer._double_percents: text = text.replace("%", "%%") return text def escape_literal_column(self, text): if self.preparer._double_percents: text = text.replace("%", "%%") return text def visit_textclause(self, textclause, **kw): def do_bindparam(m): name = m.group(1) if name in textclause._bindparams: return self.process(textclause._bindparams[name], **kw) else: return self.bindparam_string(name, **kw) if not self.stack: self.isplaintext = True # un-escape any \:params return BIND_PARAMS_ESC.sub( lambda m: m.group(1), BIND_PARAMS.sub( do_bindparam, self.post_process_text(textclause.text) ), ) def visit_text_as_from( self, taf, compound_index=None, asfrom=False, parens=True, **kw ): toplevel = not self.stack entry = self._default_stack_entry if toplevel else self.stack[-1] populate_result_map = ( toplevel or ( compound_index == 0 and entry.get("need_result_map_for_compound", False) ) or entry.get("need_result_map_for_nested", False) ) if populate_result_map: self._ordered_columns = ( self._textual_ordered_columns ) = taf.positional for c in taf.column_args: self.process( c, within_columns_clause=True, add_to_result_map=self._add_to_result_map, ) text = self.process(taf.element, **kw) if asfrom and parens: text = "(%s)" % text return text def visit_null(self, expr, **kw): return "NULL" def visit_true(self, expr, **kw): if self.dialect.supports_native_boolean: return "true" else: return "1" def visit_false(self, expr, **kw): if self.dialect.supports_native_boolean: return "false" else: return "0" def visit_clauselist(self, clauselist, **kw): sep = clauselist.operator if sep is None: sep = " " else: sep = OPERATORS[clauselist.operator] text = sep.join( s for s in ( c._compiler_dispatch(self, **kw) for c in clauselist.clauses ) if s ) if clauselist._tuple_values and self.dialect.tuple_in_values: text = "VALUES " + text return text def visit_case(self, clause, **kwargs): x = "CASE " if clause.value is not None: x += clause.value._compiler_dispatch(self, **kwargs) + " " for cond, result in clause.whens: x += ( "WHEN " + cond._compiler_dispatch(self, **kwargs) + " THEN " + result._compiler_dispatch(self, **kwargs) + " " ) if clause.else_ is not None: x += ( "ELSE " + clause.else_._compiler_dispatch(self, **kwargs) + " " ) x += "END" return x def visit_type_coerce(self, type_coerce, **kw): return type_coerce.typed_expression._compiler_dispatch(self, **kw) def visit_cast(self, cast, **kwargs): return "CAST(%s AS %s)" % ( cast.clause._compiler_dispatch(self, **kwargs), cast.typeclause._compiler_dispatch(self, **kwargs), ) def _format_frame_clause(self, range_, **kw): return "%s AND %s" % ( "UNBOUNDED PRECEDING" if range_[0] is elements.RANGE_UNBOUNDED else "CURRENT ROW" if range_[0] is elements.RANGE_CURRENT else "%s PRECEDING" % (self.process(elements.literal(abs(range_[0])), **kw),) if range_[0] < 0 else "%s FOLLOWING" % (self.process(elements.literal(range_[0]), **kw),), "UNBOUNDED FOLLOWING" if range_[1] is elements.RANGE_UNBOUNDED else "CURRENT ROW" if range_[1] is elements.RANGE_CURRENT else "%s PRECEDING" % (self.process(elements.literal(abs(range_[1])), **kw),) if range_[1] < 0 else "%s FOLLOWING" % (self.process(elements.literal(range_[1]), **kw),), ) def visit_over(self, over, **kwargs): if over.range_: range_ = "RANGE BETWEEN %s" % self._format_frame_clause( over.range_, **kwargs ) elif over.rows: range_ = "ROWS BETWEEN %s" % self._format_frame_clause( over.rows, **kwargs ) else: range_ = None return "%s OVER (%s)" % ( over.element._compiler_dispatch(self, **kwargs), " ".join( [ "%s BY %s" % (word, clause._compiler_dispatch(self, **kwargs)) for word, clause in ( ("PARTITION", over.partition_by), ("ORDER", over.order_by), ) if clause is not None and len(clause) ] + ([range_] if range_ else []) ), ) def visit_withingroup(self, withingroup, **kwargs): return "%s WITHIN GROUP (ORDER BY %s)" % ( withingroup.element._compiler_dispatch(self, **kwargs), withingroup.order_by._compiler_dispatch(self, **kwargs), ) def visit_funcfilter(self, funcfilter, **kwargs): return "%s FILTER (WHERE %s)" % ( funcfilter.func._compiler_dispatch(self, **kwargs), funcfilter.criterion._compiler_dispatch(self, **kwargs), ) def visit_extract(self, extract, **kwargs): field = self.extract_map.get(extract.field, extract.field) return "EXTRACT(%s FROM %s)" % ( field, extract.expr._compiler_dispatch(self, **kwargs), ) def visit_function(self, func, add_to_result_map=None, **kwargs): if add_to_result_map is not None: add_to_result_map(func.name, func.name, (), func.type) disp = getattr(self, "visit_%s_func" % func.name.lower(), None) if disp: return disp(func, **kwargs) else: name = FUNCTIONS.get(func.__class__, None) if name: if func._has_args: name += "%(expr)s" else: name = func.name name = ( self.preparer.quote(name) if self.preparer._requires_quotes_illegal_chars(name) or isinstance(name, elements.quoted_name) else name ) name = name + "%(expr)s" return ".".join( [ ( self.preparer.quote(tok) if self.preparer._requires_quotes_illegal_chars(tok) or isinstance(name, elements.quoted_name) else tok ) for tok in func.packagenames ] + [name] ) % {"expr": self.function_argspec(func, **kwargs)} def visit_next_value_func(self, next_value, **kw): return self.visit_sequence(next_value.sequence) def visit_sequence(self, sequence, **kw): raise NotImplementedError( "Dialect '%s' does not support sequence increments." % self.dialect.name ) def function_argspec(self, func, **kwargs): return func.clause_expr._compiler_dispatch(self, **kwargs) def visit_compound_select( self, cs, asfrom=False, parens=True, compound_index=0, **kwargs ): toplevel = not self.stack entry = self._default_stack_entry if toplevel else self.stack[-1] need_result_map = toplevel or ( compound_index == 0 and entry.get("need_result_map_for_compound", False) ) self.stack.append( { "correlate_froms": entry["correlate_froms"], "asfrom_froms": entry["asfrom_froms"], "selectable": cs, "need_result_map_for_compound": need_result_map, } ) keyword = self.compound_keywords.get(cs.keyword) text = (" " + keyword + " ").join( ( c._compiler_dispatch( self, asfrom=asfrom, parens=False, compound_index=i, **kwargs ) for i, c in enumerate(cs.selects) ) ) text += self.group_by_clause(cs, **dict(asfrom=asfrom, **kwargs)) text += self.order_by_clause(cs, **kwargs) text += ( (cs._limit_clause is not None or cs._offset_clause is not None) and self.limit_clause(cs, **kwargs) or "" ) if self.ctes and toplevel: text = self._render_cte_clause() + text self.stack.pop(-1) if asfrom and parens: return "(" + text + ")" else: return text def _get_operator_dispatch(self, operator_, qualifier1, qualifier2): attrname = "visit_%s_%s%s" % ( operator_.__name__, qualifier1, "_" + qualifier2 if qualifier2 else "", ) return getattr(self, attrname, None) def visit_unary(self, unary, **kw): if unary.operator: if unary.modifier: raise exc.CompileError( "Unary expression does not support operator " "and modifier simultaneously" ) disp = self._get_operator_dispatch( unary.operator, "unary", "operator" ) if disp: return disp(unary, unary.operator, **kw) else: return self._generate_generic_unary_operator( unary, OPERATORS[unary.operator], **kw ) elif unary.modifier: disp = self._get_operator_dispatch( unary.modifier, "unary", "modifier" ) if disp: return disp(unary, unary.modifier, **kw) else: return self._generate_generic_unary_modifier( unary, OPERATORS[unary.modifier], **kw ) else: raise exc.CompileError( "Unary expression has no operator or modifier" ) def visit_istrue_unary_operator(self, element, operator, **kw): if ( element._is_implicitly_boolean or self.dialect.supports_native_boolean ): return self.process(element.element, **kw) else: return "%s = 1" % self.process(element.element, **kw) def visit_isfalse_unary_operator(self, element, operator, **kw): if ( element._is_implicitly_boolean or self.dialect.supports_native_boolean ): return "NOT %s" % self.process(element.element, **kw) else: return "%s = 0" % self.process(element.element, **kw) def visit_notmatch_op_binary(self, binary, operator, **kw): return "NOT %s" % self.visit_binary( binary, override_operator=operators.match_op ) def _emit_empty_in_warning(self): util.warn( "The IN-predicate was invoked with an " "empty sequence. This results in a " "contradiction, which nonetheless can be " "expensive to evaluate. Consider alternative " "strategies for improved performance." ) def visit_empty_in_op_binary(self, binary, operator, **kw): if self.dialect._use_static_in: return "1 != 1" else: if self.dialect._warn_on_empty_in: self._emit_empty_in_warning() return self.process(binary.left != binary.left) def visit_empty_notin_op_binary(self, binary, operator, **kw): if self.dialect._use_static_in: return "1 = 1" else: if self.dialect._warn_on_empty_in: self._emit_empty_in_warning() return self.process(binary.left == binary.left) def visit_empty_set_expr(self, element_types): raise NotImplementedError( "Dialect '%s' does not support empty set expression." % self.dialect.name ) def visit_binary( self, binary, override_operator=None, eager_grouping=False, **kw ): # don't allow "? = ?" to render if ( self.ansi_bind_rules and isinstance(binary.left, elements.BindParameter) and isinstance(binary.right, elements.BindParameter) ): kw["literal_binds"] = True operator_ = override_operator or binary.operator disp = self._get_operator_dispatch(operator_, "binary", None) if disp: return disp(binary, operator_, **kw) else: try: opstring = OPERATORS[operator_] except KeyError as err: util.raise_( exc.UnsupportedCompilationError(self, operator_), replace_context=err, ) else: return self._generate_generic_binary(binary, opstring, **kw) def visit_function_as_comparison_op_binary(self, element, operator, **kw): return self.process(element.sql_function, **kw) def visit_mod_binary(self, binary, operator, **kw): if self.preparer._double_percents: return ( self.process(binary.left, **kw) + " %% " + self.process(binary.right, **kw) ) else: return ( self.process(binary.left, **kw) + " % " + self.process(binary.right, **kw) ) def visit_custom_op_binary(self, element, operator, **kw): kw["eager_grouping"] = operator.eager_grouping return self._generate_generic_binary( element, " " + operator.opstring + " ", **kw ) def visit_custom_op_unary_operator(self, element, operator, **kw): return self._generate_generic_unary_operator( element, operator.opstring + " ", **kw ) def visit_custom_op_unary_modifier(self, element, operator, **kw): return self._generate_generic_unary_modifier( element, " " + operator.opstring, **kw ) def _generate_generic_binary( self, binary, opstring, eager_grouping=False, **kw ): _in_binary = kw.get("_in_binary", False) kw["_in_binary"] = True text = ( binary.left._compiler_dispatch( self, eager_grouping=eager_grouping, **kw ) + opstring + binary.right._compiler_dispatch( self, eager_grouping=eager_grouping, **kw ) ) if _in_binary and eager_grouping: text = "(%s)" % text return text def _generate_generic_unary_operator(self, unary, opstring, **kw): return opstring + unary.element._compiler_dispatch(self, **kw) def _generate_generic_unary_modifier(self, unary, opstring, **kw): return unary.element._compiler_dispatch(self, **kw) + opstring @util.memoized_property def _like_percent_literal(self): return elements.literal_column("'%'", type_=sqltypes.STRINGTYPE) def visit_contains_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right).__add__(percent) return self.visit_like_op_binary(binary, operator, **kw) def visit_notcontains_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right).__add__(percent) return self.visit_notlike_op_binary(binary, operator, **kw) def visit_startswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__radd__(binary.right) return self.visit_like_op_binary(binary, operator, **kw) def visit_notstartswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__radd__(binary.right) return self.visit_notlike_op_binary(binary, operator, **kw) def visit_endswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right) return self.visit_like_op_binary(binary, operator, **kw) def visit_notendswith_op_binary(self, binary, operator, **kw): binary = binary._clone() percent = self._like_percent_literal binary.right = percent.__add__(binary.right) return self.visit_notlike_op_binary(binary, operator, **kw) def visit_like_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) # TODO: use ternary here, not "and"/ "or" return "%s LIKE %s" % ( binary.left._compiler_dispatch(self, **kw), binary.right._compiler_dispatch(self, **kw), ) + ( " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE) if escape else "" ) def visit_notlike_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "%s NOT LIKE %s" % ( binary.left._compiler_dispatch(self, **kw), binary.right._compiler_dispatch(self, **kw), ) + ( " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE) if escape else "" ) def visit_ilike_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "lower(%s) LIKE lower(%s)" % ( binary.left._compiler_dispatch(self, **kw), binary.right._compiler_dispatch(self, **kw), ) + ( " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE) if escape else "" ) def visit_notilike_op_binary(self, binary, operator, **kw): escape = binary.modifiers.get("escape", None) return "lower(%s) NOT LIKE lower(%s)" % ( binary.left._compiler_dispatch(self, **kw), binary.right._compiler_dispatch(self, **kw), ) + ( " ESCAPE " + self.render_literal_value(escape, sqltypes.STRINGTYPE) if escape else "" ) def visit_between_op_binary(self, binary, operator, **kw): symmetric = binary.modifiers.get("symmetric", False) return self._generate_generic_binary( binary, " BETWEEN SYMMETRIC " if symmetric else " BETWEEN ", **kw ) def visit_notbetween_op_binary(self, binary, operator, **kw): symmetric = binary.modifiers.get("symmetric", False) return self._generate_generic_binary( binary, " NOT BETWEEN SYMMETRIC " if symmetric else " NOT BETWEEN ", **kw ) def visit_bindparam( self, bindparam, within_columns_clause=False, literal_binds=False, skip_bind_expression=False, **kwargs ): if not skip_bind_expression: impl = bindparam.type.dialect_impl(self.dialect) if impl._has_bind_expression: bind_expression = impl.bind_expression(bindparam) return self.process( bind_expression, skip_bind_expression=True, within_columns_clause=within_columns_clause, literal_binds=literal_binds, **kwargs ) if literal_binds or (within_columns_clause and self.ansi_bind_rules): if bindparam.value is None and bindparam.callable is None: raise exc.CompileError( "Bind parameter '%s' without a " "renderable value not allowed here." % bindparam.key ) return self.render_literal_bindparam( bindparam, within_columns_clause=True, **kwargs ) name = self._truncate_bindparam(bindparam) if name in self.binds: existing = self.binds[name] if existing is not bindparam: if ( existing.unique or bindparam.unique ) and not existing.proxy_set.intersection(bindparam.proxy_set): raise exc.CompileError( "Bind parameter '%s' conflicts with " "unique bind parameter of the same name" % bindparam.key ) elif existing._is_crud or bindparam._is_crud: raise exc.CompileError( "bindparam() name '%s' is reserved " "for automatic usage in the VALUES or SET " "clause of this " "insert/update statement. Please use a " "name other than column name when using bindparam() " "with insert() or update() (for example, 'b_%s')." % (bindparam.key, bindparam.key) ) self.binds[bindparam.key] = self.binds[name] = bindparam return self.bindparam_string( name, expanding=bindparam.expanding, **kwargs ) def render_literal_bindparam(self, bindparam, **kw): value = bindparam.effective_value return self.render_literal_value(value, bindparam.type) def render_literal_value(self, value, type_): """Render the value of a bind parameter as a quoted literal. This is used for statement sections that do not accept bind parameters on the target driver/database. This should be implemented by subclasses using the quoting services of the DBAPI. """ processor = type_._cached_literal_processor(self.dialect) if processor: return processor(value) else: raise NotImplementedError( "Don't know how to literal-quote value %r" % value ) def _truncate_bindparam(self, bindparam): if bindparam in self.bind_names: return self.bind_names[bindparam] bind_name = bindparam.key if isinstance(bind_name, elements._truncated_label): bind_name = self._truncated_identifier("bindparam", bind_name) # add to bind_names for translation self.bind_names[bindparam] = bind_name return bind_name def _truncated_identifier(self, ident_class, name): if (ident_class, name) in self.truncated_names: return self.truncated_names[(ident_class, name)] anonname = name.apply_map(self.anon_map) if len(anonname) > self.label_length - 6: counter = self.truncated_names.get(ident_class, 1) truncname = ( anonname[0 : max(self.label_length - 6, 0)] + "_" + hex(counter)[2:] ) self.truncated_names[ident_class] = counter + 1 else: truncname = anonname self.truncated_names[(ident_class, name)] = truncname return truncname def _anonymize(self, name): return name % self.anon_map def bindparam_string( self, name, positional_names=None, expanding=False, **kw ): if self.positional: if positional_names is not None: positional_names.append(name) else: self.positiontup.append(name) if expanding: self.contains_expanding_parameters = True return "([EXPANDING_%s])" % name else: return self.bindtemplate % {"name": name} def visit_cte( self, cte, asfrom=False, ashint=False, fromhints=None, visiting_cte=None, **kwargs ): self._init_cte_state() kwargs["visiting_cte"] = cte if isinstance(cte.name, elements._truncated_label): cte_name = self._truncated_identifier("alias", cte.name) else: cte_name = cte.name is_new_cte = True embedded_in_current_named_cte = False if cte_name in self.ctes_by_name: existing_cte = self.ctes_by_name[cte_name] embedded_in_current_named_cte = visiting_cte is existing_cte # we've generated a same-named CTE that we are enclosed in, # or this is the same CTE. just return the name. if cte in existing_cte._restates or cte is existing_cte: is_new_cte = False elif existing_cte in cte._restates: # we've generated a same-named CTE that is # enclosed in us - we take precedence, so # discard the text for the "inner". del self.ctes[existing_cte] else: raise exc.CompileError( "Multiple, unrelated CTEs found with " "the same name: %r" % cte_name ) if asfrom or is_new_cte: if cte._cte_alias is not None: pre_alias_cte = cte._cte_alias cte_pre_alias_name = cte._cte_alias.name if isinstance(cte_pre_alias_name, elements._truncated_label): cte_pre_alias_name = self._truncated_identifier( "alias", cte_pre_alias_name ) else: pre_alias_cte = cte cte_pre_alias_name = None if is_new_cte: self.ctes_by_name[cte_name] = cte # look for embedded DML ctes and propagate autocommit if ( "autocommit" in cte.element._execution_options and "autocommit" not in self.execution_options ): self.execution_options = self.execution_options.union( { "autocommit": cte.element._execution_options[ "autocommit" ] } ) if pre_alias_cte not in self.ctes: self.visit_cte(pre_alias_cte, **kwargs) if not cte_pre_alias_name and cte not in self.ctes: if cte.recursive: self.ctes_recursive = True text = self.preparer.format_alias(cte, cte_name) if cte.recursive: if isinstance(cte.original, selectable.Select): col_source = cte.original elif isinstance(cte.original, selectable.CompoundSelect): col_source = cte.original.selects[0] else: assert False recur_cols = [ c for c in util.unique_list(col_source.inner_columns) if c is not None ] text += "(%s)" % ( ", ".join( self.preparer.format_column(ident) for ident in recur_cols ) ) if self.positional: kwargs["positional_names"] = self.cte_positional[cte] = [] text += " AS %s\n%s" % ( self._generate_prefixes(cte, cte._prefixes, **kwargs), cte.original._compiler_dispatch( self, asfrom=True, **kwargs ), ) if cte._suffixes: text += " " + self._generate_prefixes( cte, cte._suffixes, **kwargs ) self.ctes[cte] = text if asfrom: if not is_new_cte and embedded_in_current_named_cte: return self.preparer.format_alias(cte, cte_name) if cte_pre_alias_name: text = self.preparer.format_alias(cte, cte_pre_alias_name) if self.preparer._requires_quotes(cte_name): cte_name = self.preparer.quote(cte_name) text += self.get_render_as_alias_suffix(cte_name) return text else: return self.preparer.format_alias(cte, cte_name) def visit_alias( self, alias, asfrom=False, ashint=False, iscrud=False, fromhints=None, **kwargs ): if asfrom or ashint: if isinstance(alias.name, elements._truncated_label): alias_name = self._truncated_identifier("alias", alias.name) else: alias_name = alias.name if ashint: return self.preparer.format_alias(alias, alias_name) elif asfrom: ret = alias.original._compiler_dispatch( self, asfrom=True, **kwargs ) + self.get_render_as_alias_suffix( self.preparer.format_alias(alias, alias_name) ) if fromhints and alias in fromhints: ret = self.format_from_hint_text( ret, alias, fromhints[alias], iscrud ) return ret else: return alias.original._compiler_dispatch(self, **kwargs) def visit_lateral(self, lateral, **kw): kw["lateral"] = True return "LATERAL %s" % self.visit_alias(lateral, **kw) def visit_tablesample(self, tablesample, asfrom=False, **kw): text = "%s TABLESAMPLE %s" % ( self.visit_alias(tablesample, asfrom=True, **kw), tablesample._get_method()._compiler_dispatch(self, **kw), ) if tablesample.seed is not None: text += " REPEATABLE (%s)" % ( tablesample.seed._compiler_dispatch(self, **kw) ) return text def get_render_as_alias_suffix(self, alias_name_text): return " AS " + alias_name_text def _add_to_result_map(self, keyname, name, objects, type_): self._result_columns.append((keyname, name, objects, type_)) def _label_select_column( self, select, column, populate_result_map, asfrom, column_clause_args, name=None, within_columns_clause=True, need_column_expressions=False, ): """produce labeled columns present in a select().""" impl = column.type.dialect_impl(self.dialect) if impl._has_column_expression and ( need_column_expressions or populate_result_map ): col_expr = impl.column_expression(column) if populate_result_map: def add_to_result_map(keyname, name, objects, type_): self._add_to_result_map( keyname, name, (column,) + objects, type_ ) else: add_to_result_map = None else: col_expr = column if populate_result_map: add_to_result_map = self._add_to_result_map else: add_to_result_map = None if not within_columns_clause: result_expr = col_expr elif isinstance(column, elements.Label): if col_expr is not column: result_expr = _CompileLabel( col_expr, column.name, alt_names=(column.element,) ) else: result_expr = col_expr elif select is not None and name: result_expr = _CompileLabel( col_expr, name, alt_names=(column._key_label,) ) elif ( asfrom and isinstance(column, elements.ColumnClause) and not column.is_literal and column.table is not None and not isinstance(column.table, selectable.Select) ): result_expr = _CompileLabel( col_expr, elements._as_truncated(column.name), alt_names=(column.key,), ) elif ( not isinstance(column, elements.TextClause) and ( not isinstance(column, elements.UnaryExpression) or column.wraps_column_expression ) and ( not hasattr(column, "name") or isinstance(column, functions.Function) ) ): result_expr = _CompileLabel(col_expr, column.anon_label) elif col_expr is not column: # TODO: are we sure "column" has a .name and .key here ? # assert isinstance(column, elements.ColumnClause) result_expr = _CompileLabel( col_expr, elements._as_truncated(column.name), alt_names=(column.key,), ) else: result_expr = col_expr column_clause_args.update( within_columns_clause=within_columns_clause, add_to_result_map=add_to_result_map, ) return result_expr._compiler_dispatch(self, **column_clause_args) def format_from_hint_text(self, sqltext, table, hint, iscrud): hinttext = self.get_from_hint_text(table, hint) if hinttext: sqltext += " " + hinttext return sqltext def get_select_hint_text(self, byfroms): return None def get_from_hint_text(self, table, text): return None def get_crud_hint_text(self, table, text): return None def get_statement_hint_text(self, hint_texts): return " ".join(hint_texts) def _transform_select_for_nested_joins(self, select): """Rewrite any "a JOIN (b JOIN c)" expression as "a JOIN (select * from b JOIN c) AS anon", to support databases that can't parse a parenthesized join correctly (i.e. sqlite < 3.7.16). """ cloned = {} column_translate = [{}] def visit(element, **kw): if element in column_translate[-1]: return column_translate[-1][element] elif element in cloned: return cloned[element] newelem = cloned[element] = element._clone() if ( newelem.is_selectable and newelem._is_join and isinstance(newelem.right, selectable.FromGrouping) ): newelem._reset_exported() newelem.left = visit(newelem.left, **kw) right = visit(newelem.right, **kw) selectable_ = selectable.Select( [right.element], use_labels=True ).alias() for c in selectable_.c: c._key_label = c.key c._label = c.name translate_dict = dict( zip(newelem.right.element.c, selectable_.c) ) # translating from both the old and the new # because different select() structures will lead us # to traverse differently translate_dict[right.element.left] = selectable_ translate_dict[right.element.right] = selectable_ translate_dict[newelem.right.element.left] = selectable_ translate_dict[newelem.right.element.right] = selectable_ # propagate translations that we've gained # from nested visit(newelem.right) outwards # to the enclosing select here. this happens # only when we have more than one level of right # join nesting, i.e. "a JOIN (b JOIN (c JOIN d))" for k, v in list(column_translate[-1].items()): if v in translate_dict: # remarkably, no current ORM tests (May 2013) # hit this condition, only test_join_rewriting # does. column_translate[-1][k] = translate_dict[v] column_translate[-1].update(translate_dict) newelem.right = selectable_ newelem.onclause = visit(newelem.onclause, **kw) elif newelem._is_from_container: # if we hit an Alias, CompoundSelect or ScalarSelect, put a # marker in the stack. kw["transform_clue"] = "select_container" newelem._copy_internals(clone=visit, **kw) elif newelem.is_selectable and newelem._is_select: barrier_select = ( kw.get("transform_clue", None) == "select_container" ) # if we're still descended from an # Alias/CompoundSelect/ScalarSelect, we're # in a FROM clause, so start with a new translate collection if barrier_select: column_translate.append({}) kw["transform_clue"] = "inside_select" newelem._copy_internals(clone=visit, **kw) if barrier_select: del column_translate[-1] else: newelem._copy_internals(clone=visit, **kw) return newelem return visit(select) def _transform_result_map_for_nested_joins( self, select, transformed_select ): inner_col = dict( (c._key_label, c) for c in transformed_select.inner_columns ) d = dict((inner_col[c._key_label], c) for c in select.inner_columns) self._result_columns = [ (key, name, tuple([d.get(col, col) for col in objs]), typ) for key, name, objs, typ in self._result_columns ] _default_stack_entry = util.immutabledict( [("correlate_froms", frozenset()), ("asfrom_froms", frozenset())] ) def _display_froms_for_select(self, select, asfrom, lateral=False): # utility method to help external dialects # get the correct from list for a select. # specifically the oracle dialect needs this feature # right now. toplevel = not self.stack entry = self._default_stack_entry if toplevel else self.stack[-1] correlate_froms = entry["correlate_froms"] asfrom_froms = entry["asfrom_froms"] if asfrom and not lateral: froms = select._get_display_froms( explicit_correlate_froms=correlate_froms.difference( asfrom_froms ), implicit_correlate_froms=(), ) else: froms = select._get_display_froms( explicit_correlate_froms=correlate_froms, implicit_correlate_froms=asfrom_froms, ) return froms def visit_select( self, select, asfrom=False, parens=True, fromhints=None, compound_index=0, nested_join_translation=False, select_wraps_for=None, lateral=False, **kwargs ): needs_nested_translation = ( select.use_labels and not nested_join_translation and not self.stack and not self.dialect.supports_right_nested_joins ) if needs_nested_translation: transformed_select = self._transform_select_for_nested_joins( select ) text = self.visit_select( transformed_select, asfrom=asfrom, parens=parens, fromhints=fromhints, compound_index=compound_index, nested_join_translation=True, **kwargs ) toplevel = not self.stack entry = self._default_stack_entry if toplevel else self.stack[-1] populate_result_map = need_column_expressions = ( toplevel or entry.get("need_result_map_for_compound", False) or entry.get("need_result_map_for_nested", False) ) if compound_index > 0: populate_result_map = False # this was first proposed as part of #3372; however, it is not # reached in current tests and could possibly be an assertion # instead. if not populate_result_map and "add_to_result_map" in kwargs: del kwargs["add_to_result_map"] if needs_nested_translation: if populate_result_map: self._transform_result_map_for_nested_joins( select, transformed_select ) return text froms = self._setup_select_stack(select, entry, asfrom, lateral) column_clause_args = kwargs.copy() column_clause_args.update( {"within_label_clause": False, "within_columns_clause": False} ) text = "SELECT " # we're off to a good start ! if select._hints: hint_text, byfrom = self._setup_select_hints(select) if hint_text: text += hint_text + " " else: byfrom = None if select._prefixes: text += self._generate_prefixes(select, select._prefixes, **kwargs) text += self.get_select_precolumns(select, **kwargs) # the actual list of columns to print in the SELECT column list. inner_columns = [ c for c in [ self._label_select_column( select, column, populate_result_map, asfrom, column_clause_args, name=name, need_column_expressions=need_column_expressions, ) for name, column in select._columns_plus_names ] if c is not None ] if populate_result_map and select_wraps_for is not None: # if this select is a compiler-generated wrapper, # rewrite the targeted columns in the result map translate = dict( zip( [name for (key, name) in select._columns_plus_names], [ name for (key, name) in select_wraps_for._columns_plus_names ], ) ) self._result_columns = [ (key, name, tuple(translate.get(o, o) for o in obj), type_) for key, name, obj, type_ in self._result_columns ] text = self._compose_select_body( text, select, inner_columns, froms, byfrom, kwargs ) if select._statement_hints: per_dialect = [ ht for (dialect_name, ht) in select._statement_hints if dialect_name in ("*", self.dialect.name) ] if per_dialect: text += " " + self.get_statement_hint_text(per_dialect) if self.ctes and toplevel: text = self._render_cte_clause() + text if select._suffixes: text += " " + self._generate_prefixes( select, select._suffixes, **kwargs ) self.stack.pop(-1) if (asfrom or lateral) and parens: return "(" + text + ")" else: return text def _setup_select_hints(self, select): byfrom = dict( [ ( from_, hinttext % {"name": from_._compiler_dispatch(self, ashint=True)}, ) for (from_, dialect), hinttext in select._hints.items() if dialect in ("*", self.dialect.name) ] ) hint_text = self.get_select_hint_text(byfrom) return hint_text, byfrom def _setup_select_stack(self, select, entry, asfrom, lateral): correlate_froms = entry["correlate_froms"] asfrom_froms = entry["asfrom_froms"] if asfrom and not lateral: froms = select._get_display_froms( explicit_correlate_froms=correlate_froms.difference( asfrom_froms ), implicit_correlate_froms=(), ) else: froms = select._get_display_froms( explicit_correlate_froms=correlate_froms, implicit_correlate_froms=asfrom_froms, ) new_correlate_froms = set(selectable._from_objects(*froms)) all_correlate_froms = new_correlate_froms.union(correlate_froms) new_entry = { "asfrom_froms": new_correlate_froms, "correlate_froms": all_correlate_froms, "selectable": select, } self.stack.append(new_entry) return froms def _compose_select_body( self, text, select, inner_columns, froms, byfrom, kwargs ): text += ", ".join(inner_columns) if froms: text += " \nFROM " if select._hints: text += ", ".join( [ f._compiler_dispatch( self, asfrom=True, fromhints=byfrom, **kwargs ) for f in froms ] ) else: text += ", ".join( [ f._compiler_dispatch(self, asfrom=True, **kwargs) for f in froms ] ) else: text += self.default_from() if select._whereclause is not None: t = select._whereclause._compiler_dispatch(self, **kwargs) if t: text += " \nWHERE " + t if select._group_by_clause.clauses: text += self.group_by_clause(select, **kwargs) if select._having is not None: t = select._having._compiler_dispatch(self, **kwargs) if t: text += " \nHAVING " + t if select._order_by_clause.clauses: text += self.order_by_clause(select, **kwargs) if ( select._limit_clause is not None or select._offset_clause is not None ): text += self.limit_clause(select, **kwargs) if select._for_update_arg is not None: text += self.for_update_clause(select, **kwargs) return text def _generate_prefixes(self, stmt, prefixes, **kw): clause = " ".join( prefix._compiler_dispatch(self, **kw) for prefix, dialect_name in prefixes if dialect_name is None or dialect_name == self.dialect.name ) if clause: clause += " " return clause def _render_cte_clause(self): if self.positional: self.positiontup = ( sum([self.cte_positional[cte] for cte in self.ctes], []) + self.positiontup ) cte_text = self.get_cte_preamble(self.ctes_recursive) + " " cte_text += ", \n".join([txt for txt in self.ctes.values()]) cte_text += "\n " return cte_text def get_cte_preamble(self, recursive): if recursive: return "WITH RECURSIVE" else: return "WITH" def get_select_precolumns(self, select, **kw): """Called when building a ``SELECT`` statement, position is just before column list. """ return select._distinct and "DISTINCT " or "" def group_by_clause(self, select, **kw): """allow dialects to customize how GROUP BY is rendered.""" group_by = select._group_by_clause._compiler_dispatch(self, **kw) if group_by: return " GROUP BY " + group_by else: return "" def order_by_clause(self, select, **kw): """allow dialects to customize how ORDER BY is rendered.""" order_by = select._order_by_clause._compiler_dispatch(self, **kw) if order_by: return " ORDER BY " + order_by else: return "" def for_update_clause(self, select, **kw): return " FOR UPDATE" def returning_clause(self, stmt, returning_cols): raise exc.CompileError( "RETURNING is not supported by this " "dialect's statement compiler." ) def limit_clause(self, select, **kw): text = "" if select._limit_clause is not None: text += "\n LIMIT " + self.process(select._limit_clause, **kw) if select._offset_clause is not None: if select._limit_clause is None: text += "\n LIMIT -1" text += " OFFSET " + self.process(select._offset_clause, **kw) return text def visit_table( self, table, asfrom=False, iscrud=False, ashint=False, fromhints=None, use_schema=True, **kwargs ): if asfrom or ashint: effective_schema = self.preparer.schema_for_object(table) if use_schema and effective_schema: ret = ( self.preparer.quote_schema(effective_schema) + "." + self.preparer.quote(table.name) ) else: ret = self.preparer.quote(table.name) if fromhints and table in fromhints: ret = self.format_from_hint_text( ret, table, fromhints[table], iscrud ) return ret else: return "" def visit_join(self, join, asfrom=False, **kwargs): if join.full: join_type = " FULL OUTER JOIN " elif join.isouter: join_type = " LEFT OUTER JOIN " else: join_type = " JOIN " return ( join.left._compiler_dispatch(self, asfrom=True, **kwargs) + join_type + join.right._compiler_dispatch(self, asfrom=True, **kwargs) + " ON " + join.onclause._compiler_dispatch(self, **kwargs) ) def _setup_crud_hints(self, stmt, table_text): dialect_hints = dict( [ (table, hint_text) for (table, dialect), hint_text in stmt._hints.items() if dialect in ("*", self.dialect.name) ] ) if stmt.table in dialect_hints: table_text = self.format_from_hint_text( table_text, stmt.table, dialect_hints[stmt.table], True ) return dialect_hints, table_text def visit_insert(self, insert_stmt, asfrom=False, **kw): toplevel = not self.stack self.stack.append( { "correlate_froms": set(), "asfrom_froms": set(), "selectable": insert_stmt, } ) crud_params = crud._setup_crud_params( self, insert_stmt, crud.ISINSERT, **kw ) if ( not crud_params and not self.dialect.supports_default_values and not self.dialect.supports_empty_insert ): raise exc.CompileError( "The '%s' dialect with current database " "version settings does not support empty " "inserts." % self.dialect.name ) if insert_stmt._has_multi_parameters: if not self.dialect.supports_multivalues_insert: raise exc.CompileError( "The '%s' dialect with current database " "version settings does not support " "in-place multirow inserts." % self.dialect.name ) crud_params_single = crud_params[0] else: crud_params_single = crud_params preparer = self.preparer supports_default_values = self.dialect.supports_default_values text = "INSERT " if insert_stmt._prefixes: text += self._generate_prefixes( insert_stmt, insert_stmt._prefixes, **kw ) text += "INTO " table_text = preparer.format_table(insert_stmt.table) if insert_stmt._hints: _, table_text = self._setup_crud_hints(insert_stmt, table_text) text += table_text if crud_params_single or not supports_default_values: text += " (%s)" % ", ".join( [preparer.format_column(c[0]) for c in crud_params_single] ) if self.returning or insert_stmt._returning: returning_clause = self.returning_clause( insert_stmt, self.returning or insert_stmt._returning ) if self.returning_precedes_values: text += " " + returning_clause else: returning_clause = None if insert_stmt.select is not None: select_text = self.process(self._insert_from_select, **kw) if self.ctes and toplevel and self.dialect.cte_follows_insert: text += " %s%s" % (self._render_cte_clause(), select_text) else: text += " %s" % select_text elif not crud_params and supports_default_values: text += " DEFAULT VALUES" elif insert_stmt._has_multi_parameters: text += " VALUES %s" % ( ", ".join( "(%s)" % (", ".join(c[1] for c in crud_param_set)) for crud_param_set in crud_params ) ) else: insert_single_values_expr = ", ".join([c[1] for c in crud_params]) text += " VALUES (%s)" % insert_single_values_expr if toplevel: self.insert_single_values_expr = insert_single_values_expr if insert_stmt._post_values_clause is not None: post_values_clause = self.process( insert_stmt._post_values_clause, **kw ) if post_values_clause: text += " " + post_values_clause if returning_clause and not self.returning_precedes_values: text += " " + returning_clause if self.ctes and toplevel and not self.dialect.cte_follows_insert: text = self._render_cte_clause() + text self.stack.pop(-1) if asfrom: return "(" + text + ")" else: return text def update_limit_clause(self, update_stmt): """Provide a hook for MySQL to add LIMIT to the UPDATE""" return None def update_tables_clause(self, update_stmt, from_table, extra_froms, **kw): """Provide a hook to override the initial table clause in an UPDATE statement. MySQL overrides this. """ kw["asfrom"] = True return from_table._compiler_dispatch(self, iscrud=True, **kw) def update_from_clause( self, update_stmt, from_table, extra_froms, from_hints, **kw ): """Provide a hook to override the generation of an UPDATE..FROM clause. MySQL and MSSQL override this. """ raise NotImplementedError( "This backend does not support multiple-table " "criteria within UPDATE" ) def visit_update(self, update_stmt, asfrom=False, **kw): toplevel = not self.stack extra_froms = update_stmt._extra_froms is_multitable = bool(extra_froms) if is_multitable: # main table might be a JOIN main_froms = set(selectable._from_objects(update_stmt.table)) render_extra_froms = [ f for f in extra_froms if f not in main_froms ] correlate_froms = main_froms.union(extra_froms) else: render_extra_froms = [] correlate_froms = {update_stmt.table} self.stack.append( { "correlate_froms": correlate_froms, "asfrom_froms": correlate_froms, "selectable": update_stmt, } ) text = "UPDATE " if update_stmt._prefixes: text += self._generate_prefixes( update_stmt, update_stmt._prefixes, **kw ) table_text = self.update_tables_clause( update_stmt, update_stmt.table, render_extra_froms, **kw ) crud_params = crud._setup_crud_params( self, update_stmt, crud.ISUPDATE, **kw ) if update_stmt._hints: dialect_hints, table_text = self._setup_crud_hints( update_stmt, table_text ) else: dialect_hints = None text += table_text text += " SET " include_table = ( is_multitable and self.render_table_with_column_in_update_from ) text += ", ".join( c[0]._compiler_dispatch(self, include_table=include_table) + "=" + c[1] for c in crud_params ) if self.returning or update_stmt._returning: if self.returning_precedes_values: text += " " + self.returning_clause( update_stmt, self.returning or update_stmt._returning ) if extra_froms: extra_from_text = self.update_from_clause( update_stmt, update_stmt.table, render_extra_froms, dialect_hints, **kw ) if extra_from_text: text += " " + extra_from_text if update_stmt._whereclause is not None: t = self.process(update_stmt._whereclause, **kw) if t: text += " WHERE " + t limit_clause = self.update_limit_clause(update_stmt) if limit_clause: text += " " + limit_clause if ( self.returning or update_stmt._returning ) and not self.returning_precedes_values: text += " " + self.returning_clause( update_stmt, self.returning or update_stmt._returning ) if self.ctes and toplevel: text = self._render_cte_clause() + text self.stack.pop(-1) if asfrom: return "(" + text + ")" else: return text @util.memoized_property def _key_getters_for_crud_column(self): return crud._key_getters_for_crud_column(self, self.statement) def delete_extra_from_clause( self, update_stmt, from_table, extra_froms, from_hints, **kw ): """Provide a hook to override the generation of an DELETE..FROM clause. This can be used to implement DELETE..USING for example. MySQL and MSSQL override this. """ raise NotImplementedError( "This backend does not support multiple-table " "criteria within DELETE" ) def delete_table_clause(self, delete_stmt, from_table, extra_froms): return from_table._compiler_dispatch(self, asfrom=True, iscrud=True) def visit_delete(self, delete_stmt, asfrom=False, **kw): toplevel = not self.stack crud._setup_crud_params(self, delete_stmt, crud.ISDELETE, **kw) extra_froms = delete_stmt._extra_froms correlate_froms = {delete_stmt.table}.union(extra_froms) self.stack.append( { "correlate_froms": correlate_froms, "asfrom_froms": correlate_froms, "selectable": delete_stmt, } ) text = "DELETE " if delete_stmt._prefixes: text += self._generate_prefixes( delete_stmt, delete_stmt._prefixes, **kw ) text += "FROM " table_text = self.delete_table_clause( delete_stmt, delete_stmt.table, extra_froms ) if delete_stmt._hints: dialect_hints, table_text = self._setup_crud_hints( delete_stmt, table_text ) else: dialect_hints = None text += table_text if delete_stmt._returning: if self.returning_precedes_values: text += " " + self.returning_clause( delete_stmt, delete_stmt._returning ) if extra_froms: extra_from_text = self.delete_extra_from_clause( delete_stmt, delete_stmt.table, extra_froms, dialect_hints, **kw ) if extra_from_text: text += " " + extra_from_text if delete_stmt._whereclause is not None: t = delete_stmt._whereclause._compiler_dispatch(self, **kw) if t: text += " WHERE " + t if delete_stmt._returning and not self.returning_precedes_values: text += " " + self.returning_clause( delete_stmt, delete_stmt._returning ) if self.ctes and toplevel: text = self._render_cte_clause() + text self.stack.pop(-1) if asfrom: return "(" + text + ")" else: return text def visit_savepoint(self, savepoint_stmt): return "SAVEPOINT %s" % self.preparer.format_savepoint(savepoint_stmt) def visit_rollback_to_savepoint(self, savepoint_stmt): return "ROLLBACK TO SAVEPOINT %s" % self.preparer.format_savepoint( savepoint_stmt ) def visit_release_savepoint(self, savepoint_stmt): return "RELEASE SAVEPOINT %s" % self.preparer.format_savepoint( savepoint_stmt ) class StrSQLCompiler(SQLCompiler): """A :class:`.SQLCompiler` subclass which allows a small selection of non-standard SQL features to render into a string value. The :class:`.StrSQLCompiler` is invoked whenever a Core expression element is directly stringified without calling upon the :meth:`_expression.ClauseElement.compile` method. It can render a limited set of non-standard SQL constructs to assist in basic stringification, however for more substantial custom or dialect-specific SQL constructs, it will be necessary to make use of :meth:`_expression.ClauseElement.compile` directly. .. seealso:: :ref:`faq_sql_expression_string` """ def _fallback_column_name(self, column): return "" def visit_getitem_binary(self, binary, operator, **kw): return "%s[%s]" % ( self.process(binary.left, **kw), self.process(binary.right, **kw), ) def visit_json_getitem_op_binary(self, binary, operator, **kw): return self.visit_getitem_binary(binary, operator, **kw) def visit_json_path_getitem_op_binary(self, binary, operator, **kw): return self.visit_getitem_binary(binary, operator, **kw) def visit_sequence(self, seq, **kw): return "" % self.preparer.format_sequence(seq) def returning_clause(self, stmt, returning_cols): columns = [ self._label_select_column(None, c, True, False, {}) for c in elements._select_iterables(returning_cols) ] return "RETURNING " + ", ".join(columns) def update_from_clause( self, update_stmt, from_table, extra_froms, from_hints, **kw ): return "FROM " + ", ".join( t._compiler_dispatch(self, asfrom=True, fromhints=from_hints, **kw) for t in extra_froms ) def delete_extra_from_clause( self, update_stmt, from_table, extra_froms, from_hints, **kw ): return ", " + ", ".join( t._compiler_dispatch(self, asfrom=True, fromhints=from_hints, **kw) for t in extra_froms ) def get_from_hint_text(self, table, text): return "[%s]" % text class DDLCompiler(Compiled): @util.memoized_property def sql_compiler(self): return self.dialect.statement_compiler( self.dialect, None, schema_translate_map=self.schema_translate_map ) @util.memoized_property def type_compiler(self): return self.dialect.type_compiler def construct_params(self, params=None): return None def visit_ddl(self, ddl, **kwargs): # table events can substitute table and schema name context = ddl.context if isinstance(ddl.target, schema.Table): context = context.copy() preparer = self.preparer path = preparer.format_table_seq(ddl.target) if len(path) == 1: table, sch = path[0], "" else: table, sch = path[-1], path[0] context.setdefault("table", table) context.setdefault("schema", sch) context.setdefault("fullname", preparer.format_table(ddl.target)) return self.sql_compiler.post_process_text(ddl.statement % context) def visit_create_schema(self, create): schema = self.preparer.format_schema(create.element) return "CREATE SCHEMA " + schema def visit_drop_schema(self, drop): schema = self.preparer.format_schema(drop.element) text = "DROP SCHEMA " + schema if drop.cascade: text += " CASCADE" return text def visit_create_table(self, create): table = create.element preparer = self.preparer text = "\nCREATE " if table._prefixes: text += " ".join(table._prefixes) + " " text += "TABLE " + preparer.format_table(table) + " " create_table_suffix = self.create_table_suffix(table) if create_table_suffix: text += create_table_suffix + " " text += "(" separator = "\n" # if only one primary key, specify it along with the column first_pk = False for create_column in create.columns: column = create_column.element try: processed = self.process( create_column, first_pk=column.primary_key and not first_pk ) if processed is not None: text += separator separator = ", \n" text += "\t" + processed if column.primary_key: first_pk = True except exc.CompileError as ce: util.raise_( exc.CompileError( util.u("(in table '%s', column '%s'): %s") % (table.description, column.name, ce.args[0]) ), from_=ce, ) const = self.create_table_constraints( table, _include_foreign_key_constraints=create.include_foreign_key_constraints, # noqa ) if const: text += separator + "\t" + const text += "\n)%s\n\n" % self.post_create_table(table) return text def visit_create_column(self, create, first_pk=False): column = create.element if column.system: return None text = self.get_column_specification(column, first_pk=first_pk) const = " ".join( self.process(constraint) for constraint in column.constraints ) if const: text += " " + const return text def create_table_constraints( self, table, _include_foreign_key_constraints=None ): # On some DB order is significant: visit PK first, then the # other constraints (engine.ReflectionTest.testbasic failed on FB2) constraints = [] if table.primary_key: constraints.append(table.primary_key) all_fkcs = table.foreign_key_constraints if _include_foreign_key_constraints is not None: omit_fkcs = all_fkcs.difference(_include_foreign_key_constraints) else: omit_fkcs = set() constraints.extend( [ c for c in table._sorted_constraints if c is not table.primary_key and c not in omit_fkcs ] ) return ", \n\t".join( p for p in ( self.process(constraint) for constraint in constraints if ( constraint._create_rule is None or constraint._create_rule(self) ) and ( not self.dialect.supports_alter or not getattr(constraint, "use_alter", False) ) ) if p is not None ) def visit_drop_table(self, drop): return "\nDROP TABLE " + self.preparer.format_table(drop.element) def visit_drop_view(self, drop): return "\nDROP VIEW " + self.preparer.format_table(drop.element) def _verify_index_table(self, index): if index.table is None: raise exc.CompileError( "Index '%s' is not associated " "with any table." % index.name ) def visit_create_index( self, create, include_schema=False, include_table_schema=True ): index = create.element self._verify_index_table(index) preparer = self.preparer text = "CREATE " if index.unique: text += "UNIQUE " if index.name is None: raise exc.CompileError( "CREATE INDEX requires that the index have a name" ) text += "INDEX %s ON %s (%s)" % ( self._prepared_index_name(index, include_schema=include_schema), preparer.format_table( index.table, use_schema=include_table_schema ), ", ".join( self.sql_compiler.process( expr, include_table=False, literal_binds=True ) for expr in index.expressions ), ) return text def visit_drop_index(self, drop): index = drop.element if index.name is None: raise exc.CompileError( "DROP INDEX requires that the index have a name" ) return "\nDROP INDEX " + self._prepared_index_name( index, include_schema=True ) def _prepared_index_name(self, index, include_schema=False): if index.table is not None: effective_schema = self.preparer.schema_for_object(index.table) else: effective_schema = None if include_schema and effective_schema: schema_name = self.preparer.quote_schema(effective_schema) else: schema_name = None index_name = self.preparer.format_index(index) if schema_name: index_name = schema_name + "." + index_name return index_name def visit_add_constraint(self, create): return "ALTER TABLE %s ADD %s" % ( self.preparer.format_table(create.element.table), self.process(create.element), ) def visit_set_table_comment(self, create): return "COMMENT ON TABLE %s IS %s" % ( self.preparer.format_table(create.element), self.sql_compiler.render_literal_value( create.element.comment, sqltypes.String() ), ) def visit_drop_table_comment(self, drop): return "COMMENT ON TABLE %s IS NULL" % self.preparer.format_table( drop.element ) def visit_set_column_comment(self, create): return "COMMENT ON COLUMN %s IS %s" % ( self.preparer.format_column( create.element, use_table=True, use_schema=True ), self.sql_compiler.render_literal_value( create.element.comment, sqltypes.String() ), ) def visit_drop_column_comment(self, drop): return "COMMENT ON COLUMN %s IS NULL" % self.preparer.format_column( drop.element, use_table=True ) def visit_create_sequence(self, create): text = "CREATE SEQUENCE %s" % self.preparer.format_sequence( create.element ) if create.element.increment is not None: text += " INCREMENT BY %d" % create.element.increment if create.element.start is not None: text += " START WITH %d" % create.element.start if create.element.minvalue is not None: text += " MINVALUE %d" % create.element.minvalue if create.element.maxvalue is not None: text += " MAXVALUE %d" % create.element.maxvalue if create.element.nominvalue is not None: text += " NO MINVALUE" if create.element.nomaxvalue is not None: text += " NO MAXVALUE" if create.element.cache is not None: text += " CACHE %d" % create.element.cache if create.element.order is True: text += " ORDER" if create.element.cycle is not None: text += " CYCLE" return text def visit_drop_sequence(self, drop): return "DROP SEQUENCE %s" % self.preparer.format_sequence(drop.element) def visit_drop_constraint(self, drop): constraint = drop.element if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) else: formatted_name = None if formatted_name is None: raise exc.CompileError( "Can't emit DROP CONSTRAINT for constraint %r; " "it has no name" % drop.element ) return "ALTER TABLE %s DROP CONSTRAINT %s%s" % ( self.preparer.format_table(drop.element.table), formatted_name, drop.cascade and " CASCADE" or "", ) def get_column_specification(self, column, **kwargs): colspec = ( self.preparer.format_column(column) + " " + self.dialect.type_compiler.process( column.type, type_expression=column ) ) default = self.get_column_default_string(column) if default is not None: colspec += " DEFAULT " + default if column.computed is not None: colspec += " " + self.process(column.computed) if not column.nullable: colspec += " NOT NULL" return colspec def create_table_suffix(self, table): return "" def post_create_table(self, table): return "" def get_column_default_string(self, column): if isinstance(column.server_default, schema.DefaultClause): if isinstance(column.server_default.arg, util.string_types): return self.sql_compiler.render_literal_value( column.server_default.arg, sqltypes.STRINGTYPE ) else: return self.sql_compiler.process( column.server_default.arg, literal_binds=True ) else: return None def visit_check_constraint(self, constraint): text = "" if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) if formatted_name is not None: text += "CONSTRAINT %s " % formatted_name text += "CHECK (%s)" % self.sql_compiler.process( constraint.sqltext, include_table=False, literal_binds=True ) text += self.define_constraint_deferrability(constraint) return text def visit_column_check_constraint(self, constraint): text = "" if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) if formatted_name is not None: text += "CONSTRAINT %s " % formatted_name text += "CHECK (%s)" % self.sql_compiler.process( constraint.sqltext, include_table=False, literal_binds=True ) text += self.define_constraint_deferrability(constraint) return text def visit_primary_key_constraint(self, constraint): if len(constraint) == 0: return "" text = "" if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) if formatted_name is not None: text += "CONSTRAINT %s " % formatted_name text += "PRIMARY KEY " text += "(%s)" % ", ".join( self.preparer.quote(c.name) for c in ( constraint.columns_autoinc_first if constraint._implicit_generated else constraint.columns ) ) text += self.define_constraint_deferrability(constraint) return text def visit_foreign_key_constraint(self, constraint): preparer = self.preparer text = "" if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) if formatted_name is not None: text += "CONSTRAINT %s " % formatted_name remote_table = list(constraint.elements)[0].column.table text += "FOREIGN KEY(%s) REFERENCES %s (%s)" % ( ", ".join( preparer.quote(f.parent.name) for f in constraint.elements ), self.define_constraint_remote_table( constraint, remote_table, preparer ), ", ".join( preparer.quote(f.column.name) for f in constraint.elements ), ) text += self.define_constraint_match(constraint) text += self.define_constraint_cascades(constraint) text += self.define_constraint_deferrability(constraint) return text def define_constraint_remote_table(self, constraint, table, preparer): """Format the remote table clause of a CREATE CONSTRAINT clause.""" return preparer.format_table(table) def visit_unique_constraint(self, constraint): if len(constraint) == 0: return "" text = "" if constraint.name is not None: formatted_name = self.preparer.format_constraint(constraint) if formatted_name is not None: text += "CONSTRAINT %s " % formatted_name text += "UNIQUE (%s)" % ( ", ".join(self.preparer.quote(c.name) for c in constraint) ) text += self.define_constraint_deferrability(constraint) return text def define_constraint_cascades(self, constraint): text = "" if constraint.ondelete is not None: text += " ON DELETE %s" % self.preparer.validate_sql_phrase( constraint.ondelete, FK_ON_DELETE ) if constraint.onupdate is not None: text += " ON UPDATE %s" % self.preparer.validate_sql_phrase( constraint.onupdate, FK_ON_UPDATE ) return text def define_constraint_deferrability(self, constraint): text = "" if constraint.deferrable is not None: if constraint.deferrable: text += " DEFERRABLE" else: text += " NOT DEFERRABLE" if constraint.initially is not None: text += " INITIALLY %s" % self.preparer.validate_sql_phrase( constraint.initially, FK_INITIALLY ) return text def define_constraint_match(self, constraint): text = "" if constraint.match is not None: text += " MATCH %s" % constraint.match return text def visit_computed_column(self, generated): text = "GENERATED ALWAYS AS (%s)" % self.sql_compiler.process( generated.sqltext, include_table=False, literal_binds=True ) if generated.persisted is True: text += " STORED" elif generated.persisted is False: text += " VIRTUAL" return text class GenericTypeCompiler(TypeCompiler): def visit_FLOAT(self, type_, **kw): return "FLOAT" def visit_REAL(self, type_, **kw): return "REAL" def visit_NUMERIC(self, type_, **kw): if type_.precision is None: return "NUMERIC" elif type_.scale is None: return "NUMERIC(%(precision)s)" % {"precision": type_.precision} else: return "NUMERIC(%(precision)s, %(scale)s)" % { "precision": type_.precision, "scale": type_.scale, } def visit_DECIMAL(self, type_, **kw): if type_.precision is None: return "DECIMAL" elif type_.scale is None: return "DECIMAL(%(precision)s)" % {"precision": type_.precision} else: return "DECIMAL(%(precision)s, %(scale)s)" % { "precision": type_.precision, "scale": type_.scale, } def visit_INTEGER(self, type_, **kw): return "INTEGER" def visit_SMALLINT(self, type_, **kw): return "SMALLINT" def visit_BIGINT(self, type_, **kw): return "BIGINT" def visit_TIMESTAMP(self, type_, **kw): return "TIMESTAMP" def visit_DATETIME(self, type_, **kw): return "DATETIME" def visit_DATE(self, type_, **kw): return "DATE" def visit_TIME(self, type_, **kw): return "TIME" def visit_CLOB(self, type_, **kw): return "CLOB" def visit_NCLOB(self, type_, **kw): return "NCLOB" def _render_string_type(self, type_, name): text = name if type_.length: text += "(%d)" % type_.length if type_.collation: text += ' COLLATE "%s"' % type_.collation return text def visit_CHAR(self, type_, **kw): return self._render_string_type(type_, "CHAR") def visit_NCHAR(self, type_, **kw): return self._render_string_type(type_, "NCHAR") def visit_VARCHAR(self, type_, **kw): return self._render_string_type(type_, "VARCHAR") def visit_NVARCHAR(self, type_, **kw): return self._render_string_type(type_, "NVARCHAR") def visit_TEXT(self, type_, **kw): return self._render_string_type(type_, "TEXT") def visit_BLOB(self, type_, **kw): return "BLOB" def visit_BINARY(self, type_, **kw): return "BINARY" + (type_.length and "(%d)" % type_.length or "") def visit_VARBINARY(self, type_, **kw): return "VARBINARY" + (type_.length and "(%d)" % type_.length or "") def visit_BOOLEAN(self, type_, **kw): return "BOOLEAN" def visit_large_binary(self, type_, **kw): return self.visit_BLOB(type_, **kw) def visit_boolean(self, type_, **kw): return self.visit_BOOLEAN(type_, **kw) def visit_time(self, type_, **kw): return self.visit_TIME(type_, **kw) def visit_datetime(self, type_, **kw): return self.visit_DATETIME(type_, **kw) def visit_date(self, type_, **kw): return self.visit_DATE(type_, **kw) def visit_big_integer(self, type_, **kw): return self.visit_BIGINT(type_, **kw) def visit_small_integer(self, type_, **kw): return self.visit_SMALLINT(type_, **kw) def visit_integer(self, type_, **kw): return self.visit_INTEGER(type_, **kw) def visit_real(self, type_, **kw): return self.visit_REAL(type_, **kw) def visit_float(self, type_, **kw): return self.visit_FLOAT(type_, **kw) def visit_numeric(self, type_, **kw): return self.visit_NUMERIC(type_, **kw) def visit_string(self, type_, **kw): return self.visit_VARCHAR(type_, **kw) def visit_unicode(self, type_, **kw): return self.visit_VARCHAR(type_, **kw) def visit_text(self, type_, **kw): return self.visit_TEXT(type_, **kw) def visit_unicode_text(self, type_, **kw): return self.visit_TEXT(type_, **kw) def visit_enum(self, type_, **kw): return self.visit_VARCHAR(type_, **kw) def visit_null(self, type_, **kw): raise exc.CompileError( "Can't generate DDL for %r; " "did you forget to specify a " "type on this Column?" % type_ ) def visit_type_decorator(self, type_, **kw): return self.process(type_.type_engine(self.dialect), **kw) def visit_user_defined(self, type_, **kw): return type_.get_col_spec(**kw) class StrSQLTypeCompiler(GenericTypeCompiler): def __getattr__(self, key): if key.startswith("visit_"): return self._visit_unknown else: raise AttributeError(key) def _visit_unknown(self, type_, **kw): return "%s" % type_.__class__.__name__ class IdentifierPreparer(object): """Handle quoting and case-folding of identifiers based on options.""" reserved_words = RESERVED_WORDS legal_characters = LEGAL_CHARACTERS illegal_initial_characters = ILLEGAL_INITIAL_CHARACTERS schema_for_object = schema._schema_getter(None) def __init__( self, dialect, initial_quote='"', final_quote=None, escape_quote='"', quote_case_sensitive_collations=True, omit_schema=False, ): """Construct a new ``IdentifierPreparer`` object. initial_quote Character that begins a delimited identifier. final_quote Character that ends a delimited identifier. Defaults to `initial_quote`. omit_schema Prevent prepending schema name. Useful for databases that do not support schemae. """ self.dialect = dialect self.initial_quote = initial_quote self.final_quote = final_quote or self.initial_quote self.escape_quote = escape_quote self.escape_to_quote = self.escape_quote * 2 self.omit_schema = omit_schema self.quote_case_sensitive_collations = quote_case_sensitive_collations self._strings = {} self._double_percents = self.dialect.paramstyle in ( "format", "pyformat", ) def _with_schema_translate(self, schema_translate_map): prep = self.__class__.__new__(self.__class__) prep.__dict__.update(self.__dict__) prep.schema_for_object = schema._schema_getter(schema_translate_map) return prep def _escape_identifier(self, value): """Escape an identifier. Subclasses should override this to provide database-dependent escaping behavior. """ value = value.replace(self.escape_quote, self.escape_to_quote) if self._double_percents: value = value.replace("%", "%%") return value def _unescape_identifier(self, value): """Canonicalize an escaped identifier. Subclasses should override this to provide database-dependent unescaping behavior that reverses _escape_identifier. """ return value.replace(self.escape_to_quote, self.escape_quote) def validate_sql_phrase(self, element, reg): """keyword sequence filter. a filter for elements that are intended to represent keyword sequences, such as "INITIALLY", "INITIALLY DEFERRED", etc. no special characters should be present. .. versionadded:: 1.3 """ if element is not None and not reg.match(element): raise exc.CompileError( "Unexpected SQL phrase: %r (matching against %r)" % (element, reg.pattern) ) return element def quote_identifier(self, value): """Quote an identifier. Subclasses should override this to provide database-dependent quoting behavior. """ return ( self.initial_quote + self._escape_identifier(value) + self.final_quote ) def _requires_quotes(self, value): """Return True if the given identifier requires quoting.""" lc_value = value.lower() return ( lc_value in self.reserved_words or value[0] in self.illegal_initial_characters or not self.legal_characters.match(util.text_type(value)) or (lc_value != value) ) def _requires_quotes_illegal_chars(self, value): """Return True if the given identifier requires quoting, but not taking case convention into account.""" return not self.legal_characters.match(util.text_type(value)) def quote_schema(self, schema, force=None): """Conditionally quote a schema name. The name is quoted if it is a reserved word, contains quote-necessary characters, or is an instance of :class:`.quoted_name` which includes ``quote`` set to ``True``. Subclasses can override this to provide database-dependent quoting behavior for schema names. :param schema: string schema name :param force: unused .. deprecated:: 0.9 The :paramref:`.IdentifierPreparer.quote_schema.force` parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the :meth:`.IdentifierPreparer.quote` method; please refer to :class:`.quoted_name`. """ if force is not None: # not using the util.deprecated_params() decorator in this # case because of the additional function call overhead on this # very performance-critical spot. util.warn_deprecated( "The IdentifierPreparer.quote_schema.force parameter is " "deprecated and will be removed in a future release. This " "flag has no effect on the behavior of the " "IdentifierPreparer.quote method; please refer to " "quoted_name()." ) return self.quote(schema) def quote(self, ident, force=None): """Conditionally quote an identfier. The identifier is quoted if it is a reserved word, contains quote-necessary characters, or is an instance of :class:`.quoted_name` which includes ``quote`` set to ``True``. Subclasses can override this to provide database-dependent quoting behavior for identifier names. :param ident: string identifier :param force: unused .. deprecated:: 0.9 The :paramref:`.IdentifierPreparer.quote.force` parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the :meth:`.IdentifierPreparer.quote` method; please refer to :class:`.quoted_name`. """ if force is not None: # not using the util.deprecated_params() decorator in this # case because of the additional function call overhead on this # very performance-critical spot. util.warn_deprecated( "The IdentifierPreparer.quote.force parameter is " "deprecated and will be removed in a future release. This " "flag has no effect on the behavior of the " "IdentifierPreparer.quote method; please refer to " "quoted_name()." ) force = getattr(ident, "quote", None) if force is None: if ident in self._strings: return self._strings[ident] else: if self._requires_quotes(ident): self._strings[ident] = self.quote_identifier(ident) else: self._strings[ident] = ident return self._strings[ident] elif force: return self.quote_identifier(ident) else: return ident def format_collation(self, collation_name): if self.quote_case_sensitive_collations: return self.quote(collation_name) else: return collation_name def format_sequence(self, sequence, use_schema=True): name = self.quote(sequence.name) effective_schema = self.schema_for_object(sequence) if ( not self.omit_schema and use_schema and effective_schema is not None ): name = self.quote_schema(effective_schema) + "." + name return name def format_label(self, label, name=None): return self.quote(name or label.name) def format_alias(self, alias, name=None): return self.quote(name or alias.name) def format_savepoint(self, savepoint, name=None): # Running the savepoint name through quoting is unnecessary # for all known dialects. This is here to support potential # third party use cases ident = name or savepoint.ident if self._requires_quotes(ident): ident = self.quote_identifier(ident) return ident @util.dependencies("sqlalchemy.sql.naming") def format_constraint(self, naming, constraint): if constraint.name is elements._NONE_NAME: name = naming._constraint_name_for_table( constraint, constraint.table ) if name is None: return None else: name = constraint.name if isinstance(name, elements._truncated_label): # calculate these at format time so that ad-hoc changes # to dialect.max_identifier_length etc. can be reflected # as IdentifierPreparer is long lived if constraint.__visit_name__ == "index": max_ = ( self.dialect.max_index_name_length or self.dialect.max_identifier_length ) else: max_ = ( self.dialect.max_constraint_name_length or self.dialect.max_identifier_length ) if len(name) > max_: name = name[0 : max_ - 8] + "_" + util.md5_hex(name)[-4:] else: self.dialect.validate_identifier(name) return self.quote(name) def format_index(self, index): return self.format_constraint(index) def format_table(self, table, use_schema=True, name=None): """Prepare a quoted table and schema name.""" if name is None: name = table.name result = self.quote(name) effective_schema = self.schema_for_object(table) if not self.omit_schema and use_schema and effective_schema: result = self.quote_schema(effective_schema) + "." + result return result def format_schema(self, name): """Prepare a quoted schema name.""" return self.quote(name) def format_column( self, column, use_table=False, name=None, table_name=None, use_schema=False, ): """Prepare a quoted column name.""" if name is None: name = column.name if not getattr(column, "is_literal", False): if use_table: return ( self.format_table( column.table, use_schema=use_schema, name=table_name ) + "." + self.quote(name) ) else: return self.quote(name) else: # literal textual elements get stuck into ColumnClause a lot, # which shouldn't get quoted if use_table: return ( self.format_table( column.table, use_schema=use_schema, name=table_name ) + "." + name ) else: return name def format_table_seq(self, table, use_schema=True): """Format table name and schema as a tuple.""" # Dialects with more levels in their fully qualified references # ('database', 'owner', etc.) could override this and return # a longer sequence. effective_schema = self.schema_for_object(table) if not self.omit_schema and use_schema and effective_schema: return ( self.quote_schema(effective_schema), self.format_table(table, use_schema=False), ) else: return (self.format_table(table, use_schema=False),) @util.memoized_property def _r_identifiers(self): initial, final, escaped_final = [ re.escape(s) for s in ( self.initial_quote, self.final_quote, self._escape_identifier(self.final_quote), ) ] r = re.compile( r"(?:" r"(?:%(initial)s((?:%(escaped)s|[^%(final)s])+)%(final)s" r"|([^\.]+))(?=\.|$))+" % {"initial": initial, "final": final, "escaped": escaped_final} ) return r def unformat_identifiers(self, identifiers): """Unpack 'schema.table.column'-like strings into components.""" r = self._r_identifiers return [ self._unescape_identifier(i) for i in [a or b for a, b in r.findall(identifiers)] ] PK!%## expression.pynu[# sql/expression.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Defines the public namespace for SQL expression constructs. Prior to version 0.9, this module contained all of "elements", "dml", "default_comparator" and "selectable". The module was broken up and most "factory" functions were moved to be grouped with their associated class. """ __all__ = [ "Alias", "any_", "all_", "ClauseElement", "ColumnCollection", "ColumnElement", "CompoundSelect", "Delete", "FromClause", "Insert", "Join", "Lateral", "Select", "Selectable", "TableClause", "Update", "alias", "and_", "asc", "between", "bindparam", "case", "cast", "column", "cte", "delete", "desc", "distinct", "except_", "except_all", "exists", "extract", "func", "modifier", "collate", "insert", "intersect", "intersect_all", "join", "label", "lateral", "literal", "literal_column", "not_", "null", "nullsfirst", "nullslast", "or_", "outparam", "outerjoin", "over", "select", "subquery", "table", "text", "tuple_", "type_coerce", "quoted_name", "union", "union_all", "update", "within_group", "TableSample", "tablesample", ] from .base import _from_objects # noqa from .base import ColumnCollection # noqa from .base import Executable # noqa from .base import Generative # noqa from .base import PARSE_AUTOCOMMIT # noqa from .dml import Delete # noqa from .dml import Insert # noqa from .dml import Update # noqa from .dml import UpdateBase # noqa from .dml import ValuesBase # noqa from .elements import _clause_element_as_expr # noqa from .elements import _clone # noqa from .elements import _cloned_difference # noqa from .elements import _cloned_intersection # noqa from .elements import _column_as_key # noqa from .elements import _corresponding_column_or_error # noqa from .elements import _expression_literal_as_text # noqa from .elements import _is_column # noqa from .elements import _labeled # noqa from .elements import _literal_as_binds # noqa from .elements import _literal_as_column # noqa from .elements import _literal_as_label_reference # noqa from .elements import _literal_as_text # noqa from .elements import _only_column_elements # noqa from .elements import _select_iterables # noqa from .elements import _string_or_unprintable # noqa from .elements import _truncated_label # noqa from .elements import between # noqa from .elements import BinaryExpression # noqa from .elements import BindParameter # noqa from .elements import BooleanClauseList # noqa from .elements import Case # noqa from .elements import Cast # noqa from .elements import ClauseElement # noqa from .elements import ClauseList # noqa from .elements import collate # noqa from .elements import CollectionAggregate # noqa from .elements import ColumnClause # noqa from .elements import ColumnElement # noqa from .elements import Extract # noqa from .elements import False_ # noqa from .elements import FunctionFilter # noqa from .elements import Grouping # noqa from .elements import Label # noqa from .elements import literal # noqa from .elements import literal_column # noqa from .elements import not_ # noqa from .elements import Null # noqa from .elements import outparam # noqa from .elements import Over # noqa from .elements import quoted_name # noqa from .elements import ReleaseSavepointClause # noqa from .elements import RollbackToSavepointClause # noqa from .elements import SavepointClause # noqa from .elements import TextClause # noqa from .elements import True_ # noqa from .elements import Tuple # noqa from .elements import TypeClause # noqa from .elements import TypeCoerce # noqa from .elements import UnaryExpression # noqa from .elements import WithinGroup # noqa from .functions import func # noqa from .functions import Function # noqa from .functions import FunctionElement # noqa from .functions import modifier # noqa from .selectable import _interpret_as_from # noqa from .selectable import Alias # noqa from .selectable import CompoundSelect # noqa from .selectable import CTE # noqa from .selectable import Exists # noqa from .selectable import FromClause # noqa from .selectable import FromGrouping # noqa from .selectable import GenerativeSelect # noqa from .selectable import HasCTE # noqa from .selectable import HasPrefixes # noqa from .selectable import HasSuffixes # noqa from .selectable import Join # noqa from .selectable import Lateral # noqa from .selectable import ScalarSelect # noqa from .selectable import Select # noqa from .selectable import Selectable # noqa from .selectable import SelectBase # noqa from .selectable import subquery # noqa from .selectable import TableClause # noqa from .selectable import TableSample # noqa from .selectable import TextAsFrom # noqa from .visitors import Visitable # noqa from ..util.langhelpers import public_factory # noqa # factory functions - these pull class-bound constructors and classmethods # from SQL elements and selectables into public functions. This allows # the functions to be available in the sqlalchemy.sql.* namespace and # to be auto-cross-documenting from the function to the class itself. all_ = public_factory(CollectionAggregate._create_all, ".sql.expression.all_") any_ = public_factory(CollectionAggregate._create_any, ".sql.expression.any_") and_ = public_factory(BooleanClauseList.and_, ".sql.expression.and_") alias = public_factory(Alias._factory, ".sql.expression.alias") tablesample = public_factory( TableSample._factory, ".sql.expression.tablesample" ) lateral = public_factory(Lateral._factory, ".sql.expression.lateral") or_ = public_factory(BooleanClauseList.or_, ".sql.expression.or_") bindparam = public_factory(BindParameter, ".sql.expression.bindparam") select = public_factory(Select, ".sql.expression.select") text = public_factory(TextClause._create_text, ".sql.expression.text") table = public_factory(TableClause, ".sql.expression.table") column = public_factory(ColumnClause, ".sql.expression.column") over = public_factory(Over, ".sql.expression.over") within_group = public_factory(WithinGroup, ".sql.expression.within_group") label = public_factory(Label, ".sql.expression.label") case = public_factory(Case, ".sql.expression.case") cast = public_factory(Cast, ".sql.expression.cast") cte = public_factory(CTE._factory, ".sql.expression.cte") extract = public_factory(Extract, ".sql.expression.extract") tuple_ = public_factory(Tuple, ".sql.expression.tuple_") except_ = public_factory( CompoundSelect._create_except, ".sql.expression.except_" ) except_all = public_factory( CompoundSelect._create_except_all, ".sql.expression.except_all" ) intersect = public_factory( CompoundSelect._create_intersect, ".sql.expression.intersect" ) intersect_all = public_factory( CompoundSelect._create_intersect_all, ".sql.expression.intersect_all" ) union = public_factory(CompoundSelect._create_union, ".sql.expression.union") union_all = public_factory( CompoundSelect._create_union_all, ".sql.expression.union_all" ) exists = public_factory(Exists, ".sql.expression.exists") nullsfirst = public_factory( UnaryExpression._create_nullsfirst, ".sql.expression.nullsfirst" ) nullslast = public_factory( UnaryExpression._create_nullslast, ".sql.expression.nullslast" ) asc = public_factory(UnaryExpression._create_asc, ".sql.expression.asc") desc = public_factory(UnaryExpression._create_desc, ".sql.expression.desc") distinct = public_factory( UnaryExpression._create_distinct, ".sql.expression.distinct" ) type_coerce = public_factory(TypeCoerce, ".sql.expression.type_coerce") true = public_factory(True_._instance, ".sql.expression.true") false = public_factory(False_._instance, ".sql.expression.false") null = public_factory(Null._instance, ".sql.expression.null") join = public_factory(Join._create_join, ".sql.expression.join") outerjoin = public_factory(Join._create_outerjoin, ".sql.expression.outerjoin") insert = public_factory(Insert, ".sql.expression.insert") update = public_factory(Update, ".sql.expression.update") delete = public_factory(Delete, ".sql.expression.delete") funcfilter = public_factory(FunctionFilter, ".sql.expression.funcfilter") # internal functions still being called from tests and the ORM, # these might be better off in some other namespace # old names for compatibility _Executable = Executable _BindParamClause = BindParameter _Label = Label _SelectBase = SelectBase _BinaryExpression = BinaryExpression _Cast = Cast _Null = Null _False = False_ _True = True_ _TextClause = TextClause _UnaryExpression = UnaryExpression _Case = Case _Tuple = Tuple _Over = Over _Generative = Generative _TypeClause = TypeClause _Extract = Extract _Exists = Exists _Grouping = Grouping _FromGrouping = FromGrouping _ScalarSelect = ScalarSelect PK!D+TT schema.pynu[# sql/schema.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """The schema module provides the building blocks for database metadata. Each element within this module describes a database entity which can be created and dropped, or is otherwise part of such an entity. Examples include tables, columns, sequences, and indexes. All entities are subclasses of :class:`~sqlalchemy.schema.SchemaItem`, and as defined in this module they are intended to be agnostic of any vendor-specific constructs. A collection of entities are grouped into a unit called :class:`~sqlalchemy.schema.MetaData`. MetaData serves as a logical grouping of schema elements, and can also be associated with an actual database connection such that operations involving the contained elements can contact the database as needed. Two of the elements here also build upon their "syntactic" counterparts, which are defined in :class:`~sqlalchemy.sql.expression.`, specifically :class:`~sqlalchemy.schema.Table` and :class:`~sqlalchemy.schema.Column`. Since these objects are part of the SQL expression language, they are usable as components in SQL expressions. """ from __future__ import absolute_import import collections import operator import sqlalchemy from . import ddl from . import type_api from . import visitors from .base import _bind_or_error from .base import ColumnCollection from .base import DialectKWArgs from .base import SchemaEventTarget from .elements import _as_truncated from .elements import _document_text_coercion from .elements import _literal_as_text from .elements import ClauseElement from .elements import ColumnClause from .elements import ColumnElement from .elements import quoted_name from .elements import TextClause from .selectable import TableClause from .. import event from .. import exc from .. import inspection from .. import util RETAIN_SCHEMA = util.symbol("retain_schema") BLANK_SCHEMA = util.symbol( "blank_schema", """Symbol indicating that a :class:`_schema.Table` or :class:`.Sequence` should have 'None' for its schema, even if the parent :class:`_schema.MetaData` has specified a schema. .. versionadded:: 1.0.14 """, ) def _get_table_key(name, schema): if schema is None: return name else: return schema + "." + name # this should really be in sql/util.py but we'd have to # break an import cycle def _copy_expression(expression, source_table, target_table): if source_table is None or target_table is None: return expression def replace(col): if ( isinstance(col, Column) and col.table is source_table and col.key in source_table.c ): return target_table.c[col.key] else: return None return visitors.replacement_traverse(expression, {}, replace) @inspection._self_inspects class SchemaItem(SchemaEventTarget, visitors.Visitable): """Base class for items that define a database schema.""" __visit_name__ = "schema_item" def _init_items(self, *args): """Initialize the list of child items for this SchemaItem.""" for item in args: if item is not None: try: spwd = item._set_parent_with_dispatch except AttributeError as err: util.raise_( exc.ArgumentError( "'SchemaItem' object, such as a 'Column' or a " "'Constraint' expected, got %r" % item ), replace_context=err, ) else: spwd(self) def get_children(self, **kwargs): """used to allow SchemaVisitor access""" return [] def __repr__(self): return util.generic_repr(self, omit_kwarg=["info"]) @property @util.deprecated( "0.9", "The :attr:`.SchemaItem.quote` attribute is deprecated and will be " "removed in a future release. Use the :attr:`.quoted_name.quote` " "attribute on the ``name`` field of the target schema item to retrieve" "quoted status.", ) def quote(self): """Return the value of the ``quote`` flag passed to this schema object, for those schema items which have a ``name`` field. """ return self.name.quote @util.memoized_property def info(self): """Info dictionary associated with the object, allowing user-defined data to be associated with this :class:`.SchemaItem`. The dictionary is automatically generated when first accessed. It can also be specified in the constructor of some objects, such as :class:`_schema.Table` and :class:`_schema.Column`. """ return {} def _schema_item_copy(self, schema_item): if "info" in self.__dict__: schema_item.info = self.info.copy() schema_item.dispatch._update(self.dispatch) return schema_item def _translate_schema(self, effective_schema, map_): return map_.get(effective_schema, effective_schema) class Table(DialectKWArgs, SchemaItem, TableClause): r"""Represent a table in a database. e.g.:: mytable = Table("mytable", metadata, Column('mytable_id', Integer, primary_key=True), Column('value', String(50)) ) The :class:`_schema.Table` object constructs a unique instance of itself based on its name and optional schema name within the given :class:`_schema.MetaData` object. Calling the :class:`_schema.Table` constructor with the same name and same :class:`_schema.MetaData` argument a second time will return the *same* :class:`_schema.Table` object - in this way the :class:`_schema.Table` constructor acts as a registry function. .. seealso:: :ref:`metadata_describing` - Introduction to database metadata Constructor arguments are as follows: :param name: The name of this table as represented in the database. The table name, along with the value of the ``schema`` parameter, forms a key which uniquely identifies this :class:`_schema.Table` within the owning :class:`_schema.MetaData` collection. Additional calls to :class:`_schema.Table` with the same name, metadata, and schema name will return the same :class:`_schema.Table` object. Names which contain no upper case characters will be treated as case insensitive names, and will not be quoted unless they are a reserved word or contain special characters. A name with any number of upper case characters is considered to be case sensitive, and will be sent as quoted. To enable unconditional quoting for the table name, specify the flag ``quote=True`` to the constructor, or use the :class:`.quoted_name` construct to specify the name. :param metadata: a :class:`_schema.MetaData` object which will contain this table. The metadata is used as a point of association of this table with other tables which are referenced via foreign key. It also may be used to associate this table with a particular :class:`.Connectable`. :param \*args: Additional positional arguments are used primarily to add the list of :class:`_schema.Column` objects contained within this table. Similar to the style of a CREATE TABLE statement, other :class:`.SchemaItem` constructs may be added here, including :class:`.PrimaryKeyConstraint`, and :class:`_schema.ForeignKeyConstraint`. :param autoload: Defaults to False, unless :paramref:`_schema.Table.autoload_with` is set in which case it defaults to True; :class:`_schema.Column` objects for this table should be reflected from the database, possibly augmenting or replacing existing :class:`_schema.Column` objects that were explicitly specified. .. versionchanged:: 1.0.0 setting the :paramref:`_schema.Table.autoload_with` parameter implies that :paramref:`_schema.Table.autoload` will default to True. .. seealso:: :ref:`metadata_reflection_toplevel` :param autoload_replace: Defaults to ``True``; when using :paramref:`_schema.Table.autoload` in conjunction with :paramref:`_schema.Table.extend_existing`, indicates that :class:`_schema.Column` objects present in the already-existing :class:`_schema.Table` object should be replaced with columns of the same name retrieved from the autoload process. When ``False``, columns already present under existing names will be omitted from the reflection process. Note that this setting does not impact :class:`_schema.Column` objects specified programmatically within the call to :class:`_schema.Table` that also is autoloading; those :class:`_schema.Column` objects will always replace existing columns of the same name when :paramref:`_schema.Table.extend_existing` is ``True``. .. seealso:: :paramref:`_schema.Table.autoload` :paramref:`_schema.Table.extend_existing` :param autoload_with: An :class:`_engine.Engine` or :class:`_engine.Connection` object with which this :class:`_schema.Table` object will be reflected; when set to a non-None value, it implies that :paramref:`_schema.Table.autoload` is ``True``. If left unset, but :paramref:`_schema.Table.autoload` is explicitly set to ``True``, an autoload operation will attempt to proceed by locating an :class:`_engine.Engine` or :class:`_engine.Connection` bound to the underlying :class:`_schema.MetaData` object. .. seealso:: :paramref:`_schema.Table.autoload` :param extend_existing: When ``True``, indicates that if this :class:`_schema.Table` is already present in the given :class:`_schema.MetaData`, apply further arguments within the constructor to the existing :class:`_schema.Table`. If :paramref:`_schema.Table.extend_existing` or :paramref:`_schema.Table.keep_existing` are not set, and the given name of the new :class:`_schema.Table` refers to a :class:`_schema.Table` that is already present in the target :class:`_schema.MetaData` collection, and this :class:`_schema.Table` specifies additional columns or other constructs or flags that modify the table's state, an error is raised. The purpose of these two mutually-exclusive flags is to specify what action should be taken when a :class:`_schema.Table` is specified that matches an existing :class:`_schema.Table`, yet specifies additional constructs. :paramref:`_schema.Table.extend_existing` will also work in conjunction with :paramref:`_schema.Table.autoload` to run a new reflection operation against the database, even if a :class:`_schema.Table` of the same name is already present in the target :class:`_schema.MetaData`; newly reflected :class:`_schema.Column` objects and other options will be added into the state of the :class:`_schema.Table`, potentially overwriting existing columns and options of the same name. As is always the case with :paramref:`_schema.Table.autoload`, :class:`_schema.Column` objects can be specified in the same :class:`_schema.Table` constructor, which will take precedence. Below, the existing table ``mytable`` will be augmented with :class:`_schema.Column` objects both reflected from the database, as well as the given :class:`_schema.Column` named "y":: Table("mytable", metadata, Column('y', Integer), extend_existing=True, autoload=True, autoload_with=engine ) .. seealso:: :paramref:`_schema.Table.autoload` :paramref:`_schema.Table.autoload_replace` :paramref:`_schema.Table.keep_existing` :param implicit_returning: True by default - indicates that RETURNING can be used by default to fetch newly inserted primary key values, for backends which support this. Note that :func:`_sa.create_engine` also provides an ``implicit_returning`` flag. :param include_columns: A list of strings indicating a subset of columns to be loaded via the ``autoload`` operation; table columns who aren't present in this list will not be represented on the resulting ``Table`` object. Defaults to ``None`` which indicates all columns should be reflected. :param resolve_fks: Whether or not to reflect :class:`_schema.Table` objects related to this one via :class:`_schema.ForeignKey` objects, when :paramref:`_schema.Table.autoload` or :paramref:`_schema.Table.autoload_with` is specified. Defaults to True. Set to False to disable reflection of related tables as :class:`_schema.ForeignKey` objects are encountered; may be used either to save on SQL calls or to avoid issues with related tables that can't be accessed. Note that if a related table is already present in the :class:`_schema.MetaData` collection, or becomes present later, a :class:`_schema.ForeignKey` object associated with this :class:`_schema.Table` will resolve to that table normally. .. versionadded:: 1.3 .. seealso:: :paramref:`.MetaData.reflect.resolve_fks` :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. :param keep_existing: When ``True``, indicates that if this Table is already present in the given :class:`_schema.MetaData`, ignore further arguments within the constructor to the existing :class:`_schema.Table`, and return the :class:`_schema.Table` object as originally created. This is to allow a function that wishes to define a new :class:`_schema.Table` on first call, but on subsequent calls will return the same :class:`_schema.Table`, without any of the declarations (particularly constraints) being applied a second time. If :paramref:`_schema.Table.extend_existing` or :paramref:`_schema.Table.keep_existing` are not set, and the given name of the new :class:`_schema.Table` refers to a :class:`_schema.Table` that is already present in the target :class:`_schema.MetaData` collection, and this :class:`_schema.Table` specifies additional columns or other constructs or flags that modify the table's state, an error is raised. The purpose of these two mutually-exclusive flags is to specify what action should be taken when a :class:`_schema.Table` is specified that matches an existing :class:`_schema.Table`, yet specifies additional constructs. .. seealso:: :paramref:`_schema.Table.extend_existing` :param listeners: A list of tuples of the form ``(, )`` which will be passed to :func:`.event.listen` upon construction. This alternate hook to :func:`.event.listen` allows the establishment of a listener function specific to this :class:`_schema.Table` before the "autoload" process begins. Particularly useful for the :meth:`.DDLEvents.column_reflect` event:: def listen_for_reflect(table, column_info): "handle the column reflection event" # ... t = Table( 'sometable', autoload=True, listeners=[ ('column_reflect', listen_for_reflect) ]) :param mustexist: When ``True``, indicates that this Table must already be present in the given :class:`_schema.MetaData` collection, else an exception is raised. :param prefixes: A list of strings to insert after CREATE in the CREATE TABLE statement. They will be separated by spaces. :param quote: Force quoting of this table's name on or off, corresponding to ``True`` or ``False``. When left at its default of ``None``, the column identifier will be quoted according to whether the name is case sensitive (identifiers with at least one upper case character are treated as case sensitive), or if it's a reserved word. This flag is only needed to force quoting of a reserved word which is not known by the SQLAlchemy dialect. :param quote_schema: same as 'quote' but applies to the schema identifier. :param schema: The schema name for this table, which is required if the table resides in a schema other than the default selected schema for the engine's database connection. Defaults to ``None``. If the owning :class:`_schema.MetaData` of this :class:`_schema.Table` specifies its own :paramref:`_schema.MetaData.schema` parameter, then that schema name will be applied to this :class:`_schema.Table` if the schema parameter here is set to ``None``. To set a blank schema name on a :class:`_schema.Table` that would otherwise use the schema set on the owning :class:`_schema.MetaData`, specify the special symbol :attr:`.BLANK_SCHEMA`. .. versionadded:: 1.0.14 Added the :attr:`.BLANK_SCHEMA` symbol to allow a :class:`_schema.Table` to have a blank schema name even when the parent :class:`_schema.MetaData` specifies :paramref:`_schema.MetaData.schema`. The quoting rules for the schema name are the same as those for the ``name`` parameter, in that quoting is applied for reserved words or case-sensitive names; to enable unconditional quoting for the schema name, specify the flag ``quote_schema=True`` to the constructor, or use the :class:`.quoted_name` construct to specify the name. :param useexisting: the same as :paramref:`_schema.Table.extend_existing`. :param comment: Optional string that will render an SQL comment on table creation. .. versionadded:: 1.2 Added the :paramref:`_schema.Table.comment` parameter to :class:`_schema.Table`. :param \**kw: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. """ __visit_name__ = "table" @util.deprecated_params( useexisting=( "0.7", "The :paramref:`_schema.Table.useexisting` " "parameter is deprecated and " "will be removed in a future release. Please use " ":paramref:`_schema.Table.extend_existing`.", ) ) def __new__(cls, *args, **kw): if not args: # python3k pickle seems to call this return object.__new__(cls) try: name, metadata, args = args[0], args[1], args[2:] except IndexError: raise TypeError("Table() takes at least two arguments") schema = kw.get("schema", None) if schema is None: schema = metadata.schema elif schema is BLANK_SCHEMA: schema = None keep_existing = kw.pop("keep_existing", False) extend_existing = kw.pop("extend_existing", False) if "useexisting" in kw: if extend_existing: msg = "useexisting is synonymous with extend_existing." raise exc.ArgumentError(msg) extend_existing = kw.pop("useexisting", False) if keep_existing and extend_existing: msg = "keep_existing and extend_existing are mutually exclusive." raise exc.ArgumentError(msg) mustexist = kw.pop("mustexist", False) key = _get_table_key(name, schema) if key in metadata.tables: if not keep_existing and not extend_existing and bool(args): raise exc.InvalidRequestError( "Table '%s' is already defined for this MetaData " "instance. Specify 'extend_existing=True' " "to redefine " "options and columns on an " "existing Table object." % key ) table = metadata.tables[key] if extend_existing: table._init_existing(*args, **kw) return table else: if mustexist: raise exc.InvalidRequestError("Table '%s' not defined" % (key)) table = object.__new__(cls) table.dispatch.before_parent_attach(table, metadata) metadata._add_table(name, schema, table) try: table._init(name, metadata, *args, **kw) table.dispatch.after_parent_attach(table, metadata) return table except: with util.safe_reraise(): metadata._remove_table(name, schema) @property @util.deprecated( "0.9", "The :meth:`.SchemaItem.quote` method is deprecated and will be " "removed in a future release. Use the :attr:`.quoted_name.quote` " "attribute on the ``schema`` field of the target schema item to " "retrieve quoted status.", ) def quote_schema(self): """Return the value of the ``quote_schema`` flag passed to this :class:`_schema.Table`. """ return self.schema.quote def __init__(self, *args, **kw): """Constructor for :class:`_schema.Table`. This method is a no-op. See the top-level documentation for :class:`_schema.Table` for constructor arguments. """ # __init__ is overridden to prevent __new__ from # calling the superclass constructor. def _init(self, name, metadata, *args, **kwargs): super(Table, self).__init__( quoted_name(name, kwargs.pop("quote", None)) ) self.metadata = metadata self.schema = kwargs.pop("schema", None) if self.schema is None: self.schema = metadata.schema elif self.schema is BLANK_SCHEMA: self.schema = None else: quote_schema = kwargs.pop("quote_schema", None) self.schema = quoted_name(self.schema, quote_schema) self.indexes = set() self.constraints = set() self._columns = ColumnCollection() PrimaryKeyConstraint( _implicit_generated=True )._set_parent_with_dispatch(self) self.foreign_keys = set() self._extra_dependencies = set() if self.schema is not None: self.fullname = "%s.%s" % (self.schema, self.name) else: self.fullname = self.name autoload_with = kwargs.pop("autoload_with", None) autoload = kwargs.pop("autoload", autoload_with is not None) # this argument is only used with _init_existing() kwargs.pop("autoload_replace", True) _extend_on = kwargs.pop("_extend_on", None) resolve_fks = kwargs.pop("resolve_fks", True) include_columns = kwargs.pop("include_columns", None) self.implicit_returning = kwargs.pop("implicit_returning", True) self.comment = kwargs.pop("comment", None) if "info" in kwargs: self.info = kwargs.pop("info") if "listeners" in kwargs: listeners = kwargs.pop("listeners") for evt, fn in listeners: event.listen(self, evt, fn) self._prefixes = kwargs.pop("prefixes", []) self._extra_kwargs(**kwargs) # load column definitions from the database if 'autoload' is defined # we do it after the table is in the singleton dictionary to support # circular foreign keys if autoload: self._autoload( metadata, autoload_with, include_columns, _extend_on=_extend_on, resolve_fks=resolve_fks, ) # initialize all the column, etc. objects. done after reflection to # allow user-overrides self._init_items(*args) def _autoload( self, metadata, autoload_with, include_columns, exclude_columns=(), resolve_fks=True, _extend_on=None, ): if autoload_with: autoload_with.run_callable( autoload_with.dialect.reflecttable, self, include_columns, exclude_columns, resolve_fks, _extend_on=_extend_on, ) else: bind = _bind_or_error( metadata, msg="No engine is bound to this Table's MetaData. " "Pass an engine to the Table via " "autoload_with=, " "or associate the MetaData with an engine via " "metadata.bind=", ) bind.run_callable( bind.dialect.reflecttable, self, include_columns, exclude_columns, resolve_fks, _extend_on=_extend_on, ) @property def _sorted_constraints(self): """Return the set of constraints as a list, sorted by creation order. """ return sorted(self.constraints, key=lambda c: c._creation_order) @property def foreign_key_constraints(self): """:class:`_schema.ForeignKeyConstraint` objects referred to by this :class:`_schema.Table`. This list is produced from the collection of :class:`_schema.ForeignKey` objects currently associated. .. versionadded:: 1.0.0 """ return set(fkc.constraint for fkc in self.foreign_keys) def _init_existing(self, *args, **kwargs): autoload_with = kwargs.pop("autoload_with", None) autoload = kwargs.pop("autoload", autoload_with is not None) autoload_replace = kwargs.pop("autoload_replace", True) schema = kwargs.pop("schema", None) _extend_on = kwargs.pop("_extend_on", None) if schema and schema != self.schema: raise exc.ArgumentError( "Can't change schema of existing table from '%s' to '%s'", (self.schema, schema), ) include_columns = kwargs.pop("include_columns", None) resolve_fks = kwargs.pop("resolve_fks", True) if include_columns is not None: for c in self.c: if c.name not in include_columns: self._columns.remove(c) for key in ("quote", "quote_schema"): if key in kwargs: raise exc.ArgumentError( "Can't redefine 'quote' or 'quote_schema' arguments" ) if "comment" in kwargs: self.comment = kwargs.pop("comment", None) if "info" in kwargs: self.info = kwargs.pop("info") if autoload: if not autoload_replace: # don't replace columns already present. # we'd like to do this for constraints also however we don't # have simple de-duping for unnamed constraints. exclude_columns = [c.name for c in self.c] else: exclude_columns = () self._autoload( self.metadata, autoload_with, include_columns, exclude_columns, resolve_fks, _extend_on=_extend_on, ) self._extra_kwargs(**kwargs) self._init_items(*args) def _extra_kwargs(self, **kwargs): self._validate_dialect_kwargs(kwargs) def _init_collections(self): pass def _reset_exported(self): pass @property def _autoincrement_column(self): return self.primary_key._autoincrement_column @property def key(self): """Return the 'key' for this :class:`_schema.Table`. This value is used as the dictionary key within the :attr:`_schema.MetaData.tables` collection. It is typically the same as that of :attr:`_schema.Table.name` for a table with no :attr:`_schema.Table.schema` set; otherwise it is typically of the form ``schemaname.tablename``. """ return _get_table_key(self.name, self.schema) def __repr__(self): return "Table(%s)" % ", ".join( [repr(self.name)] + [repr(self.metadata)] + [repr(x) for x in self.columns] + ["%s=%s" % (k, repr(getattr(self, k))) for k in ["schema"]] ) def __str__(self): return _get_table_key(self.description, self.schema) @property def bind(self): """Return the connectable associated with this Table.""" return self.metadata and self.metadata.bind or None def add_is_dependent_on(self, table): """Add a 'dependency' for this Table. This is another Table object which must be created first before this one can, or dropped after this one. Usually, dependencies between tables are determined via ForeignKey objects. However, for other situations that create dependencies outside of foreign keys (rules, inheriting), this method can manually establish such a link. """ self._extra_dependencies.add(table) def append_column(self, column): """Append a :class:`_schema.Column` to this :class:`_schema.Table`. The "key" of the newly added :class:`_schema.Column`, i.e. the value of its ``.key`` attribute, will then be available in the ``.c`` collection of this :class:`_schema.Table`, and the column definition will be included in any CREATE TABLE, SELECT, UPDATE, etc. statements generated from this :class:`_schema.Table` construct. Note that this does **not** change the definition of the table as it exists within any underlying database, assuming that table has already been created in the database. Relational databases support the addition of columns to existing tables using the SQL ALTER command, which would need to be emitted for an already-existing table that doesn't contain the newly added column. """ column._set_parent_with_dispatch(self) def append_constraint(self, constraint): """Append a :class:`_schema.Constraint` to this :class:`_schema.Table`. This has the effect of the constraint being included in any future CREATE TABLE statement, assuming specific DDL creation events have not been associated with the given :class:`_schema.Constraint` object. Note that this does **not** produce the constraint within the relational database automatically, for a table that already exists in the database. To add a constraint to an existing relational database table, the SQL ALTER command must be used. SQLAlchemy also provides the :class:`.AddConstraint` construct which can produce this SQL when invoked as an executable clause. """ constraint._set_parent_with_dispatch(self) @util.deprecated( "0.7", "the :meth:`_schema.Table.append_ddl_listener` " "method is deprecated and " "will be removed in a future release. Please refer to " ":class:`.DDLEvents`.", ) def append_ddl_listener(self, event_name, listener): """Append a DDL event listener to this ``Table``.""" def adapt_listener(target, connection, **kw): listener(event_name, target, connection) event.listen(self, "" + event_name.replace("-", "_"), adapt_listener) def _set_parent(self, metadata): metadata._add_table(self.name, self.schema, self) self.metadata = metadata def get_children( self, column_collections=True, schema_visitor=False, **kw ): if not schema_visitor: return TableClause.get_children( self, column_collections=column_collections, **kw ) else: if column_collections: return list(self.columns) else: return [] def exists(self, bind=None): """Return True if this table exists.""" if bind is None: bind = _bind_or_error(self) return bind.run_callable( bind.dialect.has_table, self.name, schema=self.schema ) def create(self, bind=None, checkfirst=False): """Issue a ``CREATE`` statement for this :class:`_schema.Table`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.create_all`. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=False): """Issue a ``DROP`` statement for this :class:`_schema.Table`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.drop_all`. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) def tometadata( self, metadata, schema=RETAIN_SCHEMA, referred_schema_fn=None, name=None, ): """Return a copy of this :class:`_schema.Table` associated with a different :class:`_schema.MetaData`. E.g.:: m1 = MetaData() user = Table('user', m1, Column('id', Integer, primary_key=True)) m2 = MetaData() user_copy = user.tometadata(m2) :param metadata: Target :class:`_schema.MetaData` object, into which the new :class:`_schema.Table` object will be created. :param schema: optional string name indicating the target schema. Defaults to the special symbol :attr:`.RETAIN_SCHEMA` which indicates that no change to the schema name should be made in the new :class:`_schema.Table`. If set to a string name, the new :class:`_schema.Table` will have this new name as the ``.schema``. If set to ``None``, the schema will be set to that of the schema set on the target :class:`_schema.MetaData`, which is typically ``None`` as well, unless set explicitly:: m2 = MetaData(schema='newschema') # user_copy_one will have "newschema" as the schema name user_copy_one = user.tometadata(m2, schema=None) m3 = MetaData() # schema defaults to None # user_copy_two will have None as the schema name user_copy_two = user.tometadata(m3, schema=None) :param referred_schema_fn: optional callable which can be supplied in order to provide for the schema name that should be assigned to the referenced table of a :class:`_schema.ForeignKeyConstraint`. The callable accepts this parent :class:`_schema.Table`, the target schema that we are changing to, the :class:`_schema.ForeignKeyConstraint` object, and the existing "target schema" of that constraint. The function should return the string schema name that should be applied. E.g.:: def referred_schema_fn(table, to_schema, constraint, referred_schema): if referred_schema == 'base_tables': return referred_schema else: return to_schema new_table = table.tometadata(m2, schema="alt_schema", referred_schema_fn=referred_schema_fn) .. versionadded:: 0.9.2 :param name: optional string name indicating the target table name. If not specified or None, the table name is retained. This allows a :class:`_schema.Table` to be copied to the same :class:`_schema.MetaData` target with a new name. .. versionadded:: 1.0.0 """ if name is None: name = self.name if schema is RETAIN_SCHEMA: schema = self.schema elif schema is None: schema = metadata.schema key = _get_table_key(name, schema) if key in metadata.tables: util.warn( "Table '%s' already exists within the given " "MetaData - not copying." % self.description ) return metadata.tables[key] args = [] for c in self.columns: args.append(c.copy(schema=schema)) table = Table( name, metadata, schema=schema, comment=self.comment, *args, **self.kwargs ) for c in self.constraints: if isinstance(c, ForeignKeyConstraint): referred_schema = c._referred_schema if referred_schema_fn: fk_constraint_schema = referred_schema_fn( self, schema, c, referred_schema ) else: fk_constraint_schema = ( schema if referred_schema == self.schema else None ) table.append_constraint( c.copy(schema=fk_constraint_schema, target_table=table) ) elif not c._type_bound: # skip unique constraints that would be generated # by the 'unique' flag on Column if c._column_flag: continue table.append_constraint( c.copy(schema=schema, target_table=table) ) for index in self.indexes: # skip indexes that would be generated # by the 'index' flag on Column if index._column_flag: continue Index( index.name, unique=index.unique, *[ _copy_expression(expr, self, table) for expr in index.expressions ], _table=table, **index.kwargs ) return self._schema_item_copy(table) class Column(DialectKWArgs, SchemaItem, ColumnClause): """Represents a column in a database table.""" __visit_name__ = "column" def __init__(self, *args, **kwargs): r""" Construct a new ``Column`` object. :param name: The name of this column as represented in the database. This argument may be the first positional argument, or specified via keyword. Names which contain no upper case characters will be treated as case insensitive names, and will not be quoted unless they are a reserved word. Names with any number of upper case characters will be quoted and sent exactly. Note that this behavior applies even for databases which standardize upper case names as case insensitive such as Oracle. The name field may be omitted at construction time and applied later, at any time before the Column is associated with a :class:`_schema.Table`. This is to support convenient usage within the :mod:`~sqlalchemy.ext.declarative` extension. :param type\_: The column's type, indicated using an instance which subclasses :class:`~sqlalchemy.types.TypeEngine`. If no arguments are required for the type, the class of the type can be sent as well, e.g.:: # use a type with arguments Column('data', String(50)) # use no arguments Column('level', Integer) The ``type`` argument may be the second positional argument or specified by keyword. If the ``type`` is ``None`` or is omitted, it will first default to the special type :class:`.NullType`. If and when this :class:`_schema.Column` is made to refer to another column using :class:`_schema.ForeignKey` and/or :class:`_schema.ForeignKeyConstraint`, the type of the remote-referenced column will be copied to this column as well, at the moment that the foreign key is resolved against that remote :class:`_schema.Column` object. .. versionchanged:: 0.9.0 Support for propagation of type to a :class:`_schema.Column` from its :class:`_schema.ForeignKey` object has been improved and should be more reliable and timely. :param \*args: Additional positional arguments include various :class:`.SchemaItem` derived constructs which will be applied as options to the column. These include instances of :class:`.Constraint`, :class:`_schema.ForeignKey`, :class:`.ColumnDefault`, :class:`.Sequence`, :class:`.Computed`. In some cases an equivalent keyword argument is available such as ``server_default``, ``default`` and ``unique``. :param autoincrement: Set up "auto increment" semantics for an integer primary key column. The default value is the string ``"auto"`` which indicates that a single-column primary key that is of an INTEGER type with no stated client-side or python-side defaults should receive auto increment semantics automatically; all other varieties of primary key columns will not. This includes that :term:`DDL` such as PostgreSQL SERIAL or MySQL AUTO_INCREMENT will be emitted for this column during a table create, as well as that the column is assumed to generate new integer primary key values when an INSERT statement invokes which will be retrieved by the dialect. The flag may be set to ``True`` to indicate that a column which is part of a composite (e.g. multi-column) primary key should have autoincrement semantics, though note that only one column within a primary key may have this setting. It can also be set to ``True`` to indicate autoincrement semantics on a column that has a client-side or server-side default configured, however note that not all dialects can accommodate all styles of default as an "autoincrement". It can also be set to ``False`` on a single-column primary key that has a datatype of INTEGER in order to disable auto increment semantics for that column. .. versionchanged:: 1.1 The autoincrement flag now defaults to ``"auto"`` which indicates autoincrement semantics by default for single-column integer primary keys only; for composite (multi-column) primary keys, autoincrement is never implicitly enabled; as always, ``autoincrement=True`` will allow for at most one of those columns to be an "autoincrement" column. ``autoincrement=True`` may also be set on a :class:`_schema.Column` that has an explicit client-side or server-side default, subject to limitations of the backend database and dialect. The setting *only* has an effect for columns which are: * Integer derived (i.e. INT, SMALLINT, BIGINT). * Part of the primary key * Not referring to another column via :class:`_schema.ForeignKey`, unless the value is specified as ``'ignore_fk'``:: # turn on autoincrement for this column despite # the ForeignKey() Column('id', ForeignKey('other.id'), primary_key=True, autoincrement='ignore_fk') It is typically not desirable to have "autoincrement" enabled on a column that refers to another via foreign key, as such a column is required to refer to a value that originates from elsewhere. The setting has these two effects on columns that meet the above criteria: * DDL issued for the column will include database-specific keywords intended to signify this column as an "autoincrement" column, such as AUTO INCREMENT on MySQL, SERIAL on PostgreSQL, and IDENTITY on MS-SQL. It does *not* issue AUTOINCREMENT for SQLite since this is a special SQLite flag that is not required for autoincrementing behavior. .. seealso:: :ref:`sqlite_autoincrement` * The column will be considered to be available using an "autoincrement" method specific to the backend database, such as calling upon ``cursor.lastrowid``, using RETURNING in an INSERT statement to get at a sequence-generated value, or using special functions such as "SELECT scope_identity()". These methods are highly specific to the DBAPIs and databases in use and vary greatly, so care should be taken when associating ``autoincrement=True`` with a custom default generation function. :param default: A scalar, Python callable, or :class:`_expression.ColumnElement` expression representing the *default value* for this column, which will be invoked upon insert if this column is otherwise not specified in the VALUES clause of the insert. This is a shortcut to using :class:`.ColumnDefault` as a positional argument; see that class for full detail on the structure of the argument. Contrast this argument to :paramref:`_schema.Column.server_default` which creates a default generator on the database side. .. seealso:: :ref:`metadata_defaults_toplevel` :param doc: optional String that can be used by the ORM or similar to document attributes on the Python side. This attribute does **not** render SQL comments; use the :paramref:`_schema.Column.comment` parameter for this purpose. :param key: An optional string identifier which will identify this ``Column`` object on the :class:`_schema.Table`. When a key is provided, this is the only identifier referencing the ``Column`` within the application, including ORM attribute mapping; the ``name`` field is used only when rendering SQL. :param index: When ``True``, indicates that a :class:`_schema.Index` construct will be automatically generated for this :class:`_schema.Column`, which will result in a "CREATE INDEX" statement being emitted for the :class:`_schema.Table` when the DDL create operation is invoked. Using this flag is equivalent to making use of the :class:`_schema.Index` construct explicitly at the level of the :class:`_schema.Table` construct itself:: Table( "some_table", metadata, Column("x", Integer), Index("ix_some_table_x", "x") ) To add the :paramref:`_schema.Index.unique` flag to the :class:`_schema.Index`, set both the :paramref:`_schema.Column.unique` and :paramref:`_schema.Column.index` flags to True simultaneously, which will have the effect of rendering the "CREATE UNIQUE INDEX" DDL instruction instead of "CREATE INDEX". The name of the index is generated using the :ref:`default naming convention ` which for the :class:`_schema.Index` construct is of the form ``ix__``. As this flag is intended only as a convenience for the common case of adding a single-column, default configured index to a table definition, explicit use of the :class:`_schema.Index` construct should be preferred for most use cases, including composite indexes that encompass more than one column, indexes with SQL expressions or ordering, backend-specific index configuration options, and indexes that use a specific name. .. note:: the :attr:`_schema.Column.index` attribute on :class:`_schema.Column` **does not indicate** if this column is indexed or not, only if this flag was explicitly set here. To view indexes on a column, view the :attr:`_schema.Table.indexes` collection or use :meth:`_reflection.Inspector.get_indexes`. .. seealso:: :ref:`schema_indexes` :ref:`constraint_naming_conventions` :paramref:`_schema.Column.unique` :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. :param nullable: When set to ``False``, will cause the "NOT NULL" phrase to be added when generating DDL for the column. When ``True``, will normally generate nothing (in SQL this defaults to "NULL"), except in some very specific backend-specific edge cases where "NULL" may render explicitly. Defaults to ``True`` unless :paramref:`_schema.Column.primary_key` is also ``True``, in which case it defaults to ``False``. This parameter is only used when issuing CREATE TABLE statements. :param onupdate: A scalar, Python callable, or :class:`~sqlalchemy.sql.expression.ClauseElement` representing a default value to be applied to the column within UPDATE statements, which will be invoked upon update if this column is not present in the SET clause of the update. This is a shortcut to using :class:`.ColumnDefault` as a positional argument with ``for_update=True``. .. seealso:: :ref:`metadata_defaults` - complete discussion of onupdate :param primary_key: If ``True``, marks this column as a primary key column. Multiple columns can have this flag set to specify composite primary keys. As an alternative, the primary key of a :class:`_schema.Table` can be specified via an explicit :class:`.PrimaryKeyConstraint` object. :param server_default: A :class:`.FetchedValue` instance, str, Unicode or :func:`~sqlalchemy.sql.expression.text` construct representing the DDL DEFAULT value for the column. String types will be emitted as-is, surrounded by single quotes:: Column('x', Text, server_default="val") x TEXT DEFAULT 'val' A :func:`~sqlalchemy.sql.expression.text` expression will be rendered as-is, without quotes:: Column('y', DateTime, server_default=text('NOW()')) y DATETIME DEFAULT NOW() Strings and text() will be converted into a :class:`.DefaultClause` object upon initialization. Use :class:`.FetchedValue` to indicate that an already-existing column will generate a default value on the database side which will be available to SQLAlchemy for post-fetch after inserts. This construct does not specify any DDL and the implementation is left to the database, such as via a trigger. .. seealso:: :ref:`server_defaults` - complete discussion of server side defaults :param server_onupdate: A :class:`.FetchedValue` instance representing a database-side default generation function, such as a trigger. This indicates to SQLAlchemy that a newly generated value will be available after updates. This construct does not actually implement any kind of generation function within the database, which instead must be specified separately. .. warning:: This directive **does not** currently produce MySQL's "ON UPDATE CURRENT_TIMESTAMP()" clause. See :ref:`mysql_timestamp_onupdate` for background on how to produce this clause. .. seealso:: :ref:`triggered_columns` :param quote: Force quoting of this column's name on or off, corresponding to ``True`` or ``False``. When left at its default of ``None``, the column identifier will be quoted according to whether the name is case sensitive (identifiers with at least one upper case character are treated as case sensitive), or if it's a reserved word. This flag is only needed to force quoting of a reserved word which is not known by the SQLAlchemy dialect. :param unique: When ``True``, and the :paramref:`_schema.Column.index` parameter is left at its default value of ``False``, indicates that a :class:`_schema.UniqueConstraint` construct will be automatically generated for this :class:`_schema.Column`, which will result in a "UNIQUE CONSTRAINT" clause referring to this column being included in the ``CREATE TABLE`` statement emitted, when the DDL create operation for the :class:`_schema.Table` object is invoked. When this flag is ``True`` while the :paramref:`_schema.Column.index` parameter is simultaneously set to ``True``, the effect instead is that a :class:`_schema.Index` construct which includes the :paramref:`_schema.Index.unique` parameter set to ``True`` is generated. See the documentation for :paramref:`_schema.Column.index` for additional detail. Using this flag is equivalent to making use of the :class:`_schema.UniqueConstraint` construct explicitly at the level of the :class:`_schema.Table` construct itself:: Table( "some_table", metadata, Column("x", Integer), UniqueConstraint("x") ) The :paramref:`_schema.UniqueConstraint.name` parameter of the unique constraint object is left at its default value of ``None``; in the absence of a :ref:`naming convention ` for the enclosing :class:`_schema.MetaData`, the UNIQUE CONSTRAINT construct will be emitted as unnamed, which typically invokes a database-specific naming convention to take place. As this flag is intended only as a convenience for the common case of adding a single-column, default configured unique constraint to a table definition, explicit use of the :class:`_schema.UniqueConstraint` construct should be preferred for most use cases, including composite constraints that encompass more than one column, backend-specific index configuration options, and constraints that use a specific name. .. note:: the :attr:`_schema.Column.unique` attribute on :class:`_schema.Column` **does not indicate** if this column has a unique constraint or not, only if this flag was explicitly set here. To view indexes and unique constraints that may involve this column, view the :attr:`_schema.Table.indexes` and/or :attr:`_schema.Table.constraints` collections or use :meth:`_reflection.Inspector.get_indexes` and/or :meth:`_reflection.Inspector.get_unique_constraints` .. seealso:: :ref:`schema_unique_constraint` :ref:`constraint_naming_conventions` :paramref:`_schema.Column.index` :param system: When ``True``, indicates this is a "system" column, that is a column which is automatically made available by the database, and should not be included in the columns list for a ``CREATE TABLE`` statement. For more elaborate scenarios where columns should be conditionally rendered differently on different backends, consider custom compilation rules for :class:`.CreateColumn`. :param comment: Optional string that will render an SQL comment on table creation. .. versionadded:: 1.2 Added the :paramref:`_schema.Column.comment` parameter to :class:`_schema.Column`. """ # noqa E501 name = kwargs.pop("name", None) type_ = kwargs.pop("type_", None) args = list(args) if args: if isinstance(args[0], util.string_types): if name is not None: raise exc.ArgumentError( "May not pass name positionally and as a keyword." ) name = args.pop(0) if args: coltype = args[0] if hasattr(coltype, "_sqla_type"): if type_ is not None: raise exc.ArgumentError( "May not pass type_ positionally and as a keyword." ) type_ = args.pop(0) if name is not None: name = quoted_name(name, kwargs.pop("quote", None)) elif "quote" in kwargs: raise exc.ArgumentError( "Explicit 'name' is required when " "sending 'quote' argument" ) super(Column, self).__init__(name, type_) self.key = kwargs.pop("key", name) self.primary_key = kwargs.pop("primary_key", False) self.nullable = kwargs.pop("nullable", not self.primary_key) self.default = kwargs.pop("default", None) self.server_default = kwargs.pop("server_default", None) self.server_onupdate = kwargs.pop("server_onupdate", None) # these default to None because .index and .unique is *not* # an informational flag about Column - there can still be an # Index or UniqueConstraint referring to this Column. self.index = kwargs.pop("index", None) self.unique = kwargs.pop("unique", None) self.system = kwargs.pop("system", False) self.doc = kwargs.pop("doc", None) self.onupdate = kwargs.pop("onupdate", None) self.autoincrement = kwargs.pop("autoincrement", "auto") self.constraints = set() self.foreign_keys = set() self.comment = kwargs.pop("comment", None) self.computed = None # check if this Column is proxying another column if "_proxies" in kwargs: self._proxies = kwargs.pop("_proxies") # otherwise, add DDL-related events elif isinstance(self.type, SchemaEventTarget): self.type._set_parent_with_dispatch(self) if self.default is not None: if isinstance(self.default, (ColumnDefault, Sequence)): args.append(self.default) else: if getattr(self.type, "_warn_on_bytestring", False): if isinstance(self.default, util.binary_type): util.warn( "Unicode column '%s' has non-unicode " "default value %r specified." % (self.key, self.default) ) args.append(ColumnDefault(self.default)) if self.server_default is not None: if isinstance(self.server_default, FetchedValue): args.append(self.server_default._as_for_update(False)) else: args.append(DefaultClause(self.server_default)) if self.onupdate is not None: if isinstance(self.onupdate, (ColumnDefault, Sequence)): args.append(self.onupdate) else: args.append(ColumnDefault(self.onupdate, for_update=True)) if self.server_onupdate is not None: if isinstance(self.server_onupdate, FetchedValue): args.append(self.server_onupdate._as_for_update(True)) else: args.append( DefaultClause(self.server_onupdate, for_update=True) ) self._init_items(*args) util.set_creation_order(self) if "info" in kwargs: self.info = kwargs.pop("info") self._extra_kwargs(**kwargs) def _extra_kwargs(self, **kwargs): self._validate_dialect_kwargs(kwargs) # @property # def quote(self): # return getattr(self.name, "quote", None) def __str__(self): if self.name is None: return "(no name)" elif self.table is not None: if self.table.named_with_column: return self.table.description + "." + self.description else: return self.description else: return self.description def references(self, column): """Return True if this Column references the given column via foreign key.""" for fk in self.foreign_keys: if fk.column.proxy_set.intersection(column.proxy_set): return True else: return False def append_foreign_key(self, fk): fk._set_parent_with_dispatch(self) def __repr__(self): kwarg = [] if self.key != self.name: kwarg.append("key") if self.primary_key: kwarg.append("primary_key") if not self.nullable: kwarg.append("nullable") if self.onupdate: kwarg.append("onupdate") if self.default: kwarg.append("default") if self.server_default: kwarg.append("server_default") if self.comment: kwarg.append("comment") return "Column(%s)" % ", ".join( [repr(self.name)] + [repr(self.type)] + [repr(x) for x in self.foreign_keys if x is not None] + [repr(x) for x in self.constraints] + [ ( self.table is not None and "table=<%s>" % self.table.description or "table=None" ) ] + ["%s=%s" % (k, repr(getattr(self, k))) for k in kwarg] ) def _set_parent(self, table): if not self.name: raise exc.ArgumentError( "Column must be constructed with a non-blank name or " "assign a non-blank .name before adding to a Table." ) if self.key is None: self.key = self.name existing = getattr(self, "table", None) if existing is not None and existing is not table: raise exc.ArgumentError( "Column object '%s' already assigned to Table '%s'" % (self.key, existing.description) ) if self.key in table._columns: col = table._columns.get(self.key) if col is not self: for fk in col.foreign_keys: table.foreign_keys.remove(fk) if fk.constraint in table.constraints: # this might have been removed # already, if it's a composite constraint # and more than one col being replaced table.constraints.remove(fk.constraint) table._columns.replace(self) self.table = table if self.primary_key: table.primary_key._replace(self) elif self.key in table.primary_key: raise exc.ArgumentError( "Trying to redefine primary-key column '%s' as a " "non-primary-key column on table '%s'" % (self.key, table.fullname) ) if self.index: if isinstance(self.index, util.string_types): raise exc.ArgumentError( "The 'index' keyword argument on Column is boolean only. " "To create indexes with a specific name, create an " "explicit Index object external to the Table." ) table.append_constraint( Index( None, self.key, unique=bool(self.unique), _column_flag=True ) ) elif self.unique: if isinstance(self.unique, util.string_types): raise exc.ArgumentError( "The 'unique' keyword argument on Column is boolean " "only. To create unique constraints or indexes with a " "specific name, append an explicit UniqueConstraint to " "the Table's list of elements, or create an explicit " "Index object external to the Table." ) table.append_constraint( UniqueConstraint(self.key, _column_flag=True) ) self._setup_on_memoized_fks(lambda fk: fk._set_remote_table(table)) def _setup_on_memoized_fks(self, fn): fk_keys = [ ((self.table.key, self.key), False), ((self.table.key, self.name), True), ] for fk_key, link_to_name in fk_keys: if fk_key in self.table.metadata._fk_memos: for fk in self.table.metadata._fk_memos[fk_key]: if fk.link_to_name is link_to_name: fn(fk) def _on_table_attach(self, fn): if self.table is not None: fn(self, self.table) else: event.listen(self, "after_parent_attach", fn) def copy(self, **kw): """Create a copy of this ``Column``, uninitialized. This is used in :meth:`_schema.Table.tometadata`. """ # Constraint objects plus non-constraint-bound ForeignKey objects args = [ c.copy(**kw) for c in self.constraints if not c._type_bound ] + [c.copy(**kw) for c in self.foreign_keys if not c.constraint] # ticket #5276 column_kwargs = {} for dialect_name in self.dialect_options: dialect_options = self.dialect_options[dialect_name]._non_defaults for ( dialect_option_key, dialect_option_value, ) in dialect_options.items(): column_kwargs[ dialect_name + "_" + dialect_option_key ] = dialect_option_value server_default = self.server_default server_onupdate = self.server_onupdate if isinstance(server_default, Computed): server_default = server_onupdate = None args.append(self.server_default.copy(**kw)) type_ = self.type if isinstance(type_, SchemaEventTarget): type_ = type_.copy(**kw) c = self._constructor( name=self.name, type_=type_, key=self.key, primary_key=self.primary_key, nullable=self.nullable, unique=self.unique, system=self.system, # quote=self.quote, # disabled 2013-08-27 (commit 031ef080) index=self.index, autoincrement=self.autoincrement, default=self.default, server_default=server_default, onupdate=self.onupdate, server_onupdate=server_onupdate, doc=self.doc, comment=self.comment, *args, **column_kwargs ) return self._schema_item_copy(c) def _make_proxy( self, selectable, name=None, key=None, name_is_truncatable=False, **kw ): """Create a *proxy* for this column. This is a copy of this ``Column`` referenced by a different parent (such as an alias or select statement). The column should be used only in select scenarios, as its full DDL/default information is not transferred. """ fk = [ ForeignKey(f.column, _constraint=f.constraint) for f in self.foreign_keys ] if name is None and self.name is None: raise exc.InvalidRequestError( "Cannot initialize a sub-selectable" " with this Column object until its 'name' has " "been assigned." ) try: c = self._constructor( _as_truncated(name or self.name) if name_is_truncatable else (name or self.name), self.type, key=key if key else name if name else self.key, primary_key=self.primary_key, nullable=self.nullable, _proxies=[self], *fk ) except TypeError as err: util.raise_( TypeError( "Could not create a copy of this %r object. " "Ensure the class includes a _constructor() " "attribute or method which accepts the " "standard Column constructor arguments, or " "references the Column class itself." % self.__class__ ), from_=err, ) c.table = selectable selectable._columns.add(c) if selectable._is_clone_of is not None: c._is_clone_of = selectable._is_clone_of.columns.get(c.key) if self.primary_key: selectable.primary_key.add(c) c.dispatch.after_parent_attach(c, selectable) return c def get_children(self, schema_visitor=False, **kwargs): if schema_visitor: return ( [x for x in (self.default, self.onupdate) if x is not None] + list(self.foreign_keys) + list(self.constraints) ) else: return ColumnClause.get_children(self, **kwargs) class ForeignKey(DialectKWArgs, SchemaItem): """Defines a dependency between two columns. ``ForeignKey`` is specified as an argument to a :class:`_schema.Column` object, e.g.:: t = Table("remote_table", metadata, Column("remote_id", ForeignKey("main_table.id")) ) Note that ``ForeignKey`` is only a marker object that defines a dependency between two columns. The actual constraint is in all cases represented by the :class:`_schema.ForeignKeyConstraint` object. This object will be generated automatically when a ``ForeignKey`` is associated with a :class:`_schema.Column` which in turn is associated with a :class:`_schema.Table`. Conversely, when :class:`_schema.ForeignKeyConstraint` is applied to a :class:`_schema.Table`, ``ForeignKey`` markers are automatically generated to be present on each associated :class:`_schema.Column`, which are also associated with the constraint object. Note that you cannot define a "composite" foreign key constraint, that is a constraint between a grouping of multiple parent/child columns, using ``ForeignKey`` objects. To define this grouping, the :class:`_schema.ForeignKeyConstraint` object must be used, and applied to the :class:`_schema.Table`. The associated ``ForeignKey`` objects are created automatically. The ``ForeignKey`` objects associated with an individual :class:`_schema.Column` object are available in the `foreign_keys` collection of that column. Further examples of foreign key configuration are in :ref:`metadata_foreignkeys`. """ __visit_name__ = "foreign_key" def __init__( self, column, _constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None, link_to_name=False, match=None, info=None, **dialect_kw ): r""" Construct a column-level FOREIGN KEY. The :class:`_schema.ForeignKey` object when constructed generates a :class:`_schema.ForeignKeyConstraint` which is associated with the parent :class:`_schema.Table` object's collection of constraints. :param column: A single target column for the key relationship. A :class:`_schema.Column` object or a column name as a string: ``tablename.columnkey`` or ``schema.tablename.columnkey``. ``columnkey`` is the ``key`` which has been assigned to the column (defaults to the column name itself), unless ``link_to_name`` is ``True`` in which case the rendered name of the column is used. :param name: Optional string. An in-database name for the key if `constraint` is not provided. :param onupdate: Optional string. If set, emit ON UPDATE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param ondelete: Optional string. If set, emit ON DELETE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param link_to_name: if True, the string name given in ``column`` is the rendered name of the referenced column, not its locally assigned ``key``. :param use_alter: passed to the underlying :class:`_schema.ForeignKeyConstraint` to indicate the constraint should be generated/dropped externally from the CREATE TABLE/ DROP TABLE statement. See :paramref:`_schema.ForeignKeyConstraint.use_alter` for further description. .. seealso:: :paramref:`_schema.ForeignKeyConstraint.use_alter` :ref:`use_alter` :param match: Optional string. If set, emit MATCH when issuing DDL for this constraint. Typical values include SIMPLE, PARTIAL and FULL. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. The arguments are ultimately handled by a corresponding :class:`_schema.ForeignKeyConstraint`. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 """ self._colspec = column if isinstance(self._colspec, util.string_types): self._table_column = None else: if hasattr(self._colspec, "__clause_element__"): self._table_column = self._colspec.__clause_element__() else: self._table_column = self._colspec if not isinstance(self._table_column, ColumnClause): raise exc.ArgumentError( "String, Column, or Column-bound argument " "expected, got %r" % self._table_column ) elif not isinstance( self._table_column.table, (util.NoneType, TableClause) ): raise exc.ArgumentError( "ForeignKey received Column not bound " "to a Table, got: %r" % self._table_column.table ) # the linked ForeignKeyConstraint. # ForeignKey will create this when parent Column # is attached to a Table, *or* ForeignKeyConstraint # object passes itself in when creating ForeignKey # markers. self.constraint = _constraint self.parent = None self.use_alter = use_alter self.name = name self.onupdate = onupdate self.ondelete = ondelete self.deferrable = deferrable self.initially = initially self.link_to_name = link_to_name self.match = match if info: self.info = info self._unvalidated_dialect_kw = dialect_kw def __repr__(self): return "ForeignKey(%r)" % self._get_colspec() def copy(self, schema=None): """Produce a copy of this :class:`_schema.ForeignKey` object. The new :class:`_schema.ForeignKey` will not be bound to any :class:`_schema.Column`. This method is usually used by the internal copy procedures of :class:`_schema.Column`, :class:`_schema.Table`, and :class:`_schema.MetaData`. :param schema: The returned :class:`_schema.ForeignKey` will reference the original table and column name, qualified by the given string schema name. """ fk = ForeignKey( self._get_colspec(schema=schema), use_alter=self.use_alter, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, deferrable=self.deferrable, initially=self.initially, link_to_name=self.link_to_name, match=self.match, **self._unvalidated_dialect_kw ) return self._schema_item_copy(fk) def _get_colspec(self, schema=None, table_name=None): """Return a string based 'column specification' for this :class:`_schema.ForeignKey`. This is usually the equivalent of the string-based "tablename.colname" argument first passed to the object's constructor. """ if schema: _schema, tname, colname = self._column_tokens if table_name is not None: tname = table_name return "%s.%s.%s" % (schema, tname, colname) elif table_name: schema, tname, colname = self._column_tokens if schema: return "%s.%s.%s" % (schema, table_name, colname) else: return "%s.%s" % (table_name, colname) elif self._table_column is not None: return "%s.%s" % ( self._table_column.table.fullname, self._table_column.key, ) else: return self._colspec @property def _referred_schema(self): return self._column_tokens[0] def _table_key(self): if self._table_column is not None: if self._table_column.table is None: return None else: return self._table_column.table.key else: schema, tname, colname = self._column_tokens return _get_table_key(tname, schema) target_fullname = property(_get_colspec) def references(self, table): """Return True if the given :class:`_schema.Table` is referenced by this :class:`_schema.ForeignKey`.""" return table.corresponding_column(self.column) is not None def get_referent(self, table): """Return the :class:`_schema.Column` in the given :class:`_schema.Table` referenced by this :class:`_schema.ForeignKey`. Returns None if this :class:`_schema.ForeignKey` does not reference the given :class:`_schema.Table`. """ return table.corresponding_column(self.column) @util.memoized_property def _column_tokens(self): """parse a string-based _colspec into its component parts.""" m = self._get_colspec().split(".") if m is None: raise exc.ArgumentError( "Invalid foreign key column specification: %s" % self._colspec ) if len(m) == 1: tname = m.pop() colname = None else: colname = m.pop() tname = m.pop() # A FK between column 'bar' and table 'foo' can be # specified as 'foo', 'foo.bar', 'dbo.foo.bar', # 'otherdb.dbo.foo.bar'. Once we have the column name and # the table name, treat everything else as the schema # name. Some databases (e.g. Sybase) support # inter-database foreign keys. See tickets#1341 and -- # indirectly related -- Ticket #594. This assumes that '.' # will never appear *within* any component of the FK. if len(m) > 0: schema = ".".join(m) else: schema = None return schema, tname, colname def _resolve_col_tokens(self): if self.parent is None: raise exc.InvalidRequestError( "this ForeignKey object does not yet have a " "parent Column associated with it." ) elif self.parent.table is None: raise exc.InvalidRequestError( "this ForeignKey's parent column is not yet associated " "with a Table." ) parenttable = self.parent.table # assertion # basically Column._make_proxy() sends the actual # target Column to the ForeignKey object, so the # string resolution here is never called. for c in self.parent.base_columns: if isinstance(c, Column): assert c.table is parenttable break else: assert False ###################### schema, tname, colname = self._column_tokens if schema is None and parenttable.metadata.schema is not None: schema = parenttable.metadata.schema tablekey = _get_table_key(tname, schema) return parenttable, tablekey, colname def _link_to_col_by_colstring(self, parenttable, table, colname): if not hasattr(self.constraint, "_referred_table"): self.constraint._referred_table = table else: assert self.constraint._referred_table is table _column = None if colname is None: # colname is None in the case that ForeignKey argument # was specified as table name only, in which case we # match the column name to the same column on the # parent. key = self.parent _column = table.c.get(self.parent.key, None) elif self.link_to_name: key = colname for c in table.c: if c.name == colname: _column = c else: key = colname _column = table.c.get(colname, None) if _column is None: raise exc.NoReferencedColumnError( "Could not initialize target column " "for ForeignKey '%s' on table '%s': " "table '%s' has no column named '%s'" % (self._colspec, parenttable.name, table.name, key), table.name, key, ) self._set_target_column(_column) def _set_target_column(self, column): # propagate TypeEngine to parent if it didn't have one if self.parent.type._isnull: self.parent.type = column.type # super-edgy case, if other FKs point to our column, # they'd get the type propagated out also. if isinstance(self.parent.table, Table): def set_type(fk): if fk.parent.type._isnull: fk.parent.type = column.type self.parent._setup_on_memoized_fks(set_type) self.column = column @util.memoized_property def column(self): """Return the target :class:`_schema.Column` referenced by this :class:`_schema.ForeignKey`. If no target column has been established, an exception is raised. .. versionchanged:: 0.9.0 Foreign key target column resolution now occurs as soon as both the ForeignKey object and the remote Column to which it refers are both associated with the same MetaData object. """ if isinstance(self._colspec, util.string_types): parenttable, tablekey, colname = self._resolve_col_tokens() if tablekey not in parenttable.metadata: raise exc.NoReferencedTableError( "Foreign key associated with column '%s' could not find " "table '%s' with which to generate a " "foreign key to target column '%s'" % (self.parent, tablekey, colname), tablekey, ) elif parenttable.key not in parenttable.metadata: raise exc.InvalidRequestError( "Table %s is no longer associated with its " "parent MetaData" % parenttable ) else: raise exc.NoReferencedColumnError( "Could not initialize target column for " "ForeignKey '%s' on table '%s': " "table '%s' has no column named '%s'" % (self._colspec, parenttable.name, tablekey, colname), tablekey, colname, ) elif hasattr(self._colspec, "__clause_element__"): _column = self._colspec.__clause_element__() return _column else: _column = self._colspec return _column def _set_parent(self, column): if self.parent is not None and self.parent is not column: raise exc.InvalidRequestError( "This ForeignKey already has a parent !" ) self.parent = column self.parent.foreign_keys.add(self) self.parent._on_table_attach(self._set_table) def _set_remote_table(self, table): parenttable, tablekey, colname = self._resolve_col_tokens() self._link_to_col_by_colstring(parenttable, table, colname) self.constraint._validate_dest_table(table) def _remove_from_metadata(self, metadata): parenttable, table_key, colname = self._resolve_col_tokens() fk_key = (table_key, colname) if self in metadata._fk_memos[fk_key]: # TODO: no test coverage for self not in memos metadata._fk_memos[fk_key].remove(self) def _set_table(self, column, table): # standalone ForeignKey - create ForeignKeyConstraint # on the hosting Table when attached to the Table. if self.constraint is None and isinstance(table, Table): self.constraint = ForeignKeyConstraint( [], [], use_alter=self.use_alter, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, deferrable=self.deferrable, initially=self.initially, match=self.match, **self._unvalidated_dialect_kw ) self.constraint._append_element(column, self) self.constraint._set_parent_with_dispatch(table) table.foreign_keys.add(self) # set up remote ".column" attribute, or a note to pick it # up when the other Table/Column shows up if isinstance(self._colspec, util.string_types): parenttable, table_key, colname = self._resolve_col_tokens() fk_key = (table_key, colname) if table_key in parenttable.metadata.tables: table = parenttable.metadata.tables[table_key] try: self._link_to_col_by_colstring(parenttable, table, colname) except exc.NoReferencedColumnError: # this is OK, we'll try later pass parenttable.metadata._fk_memos[fk_key].append(self) elif hasattr(self._colspec, "__clause_element__"): _column = self._colspec.__clause_element__() self._set_target_column(_column) else: _column = self._colspec self._set_target_column(_column) class _NotAColumnExpr(object): def _not_a_column_expr(self): raise exc.InvalidRequestError( "This %s cannot be used directly " "as a column expression." % self.__class__.__name__ ) __clause_element__ = self_group = lambda self: self._not_a_column_expr() _from_objects = property(lambda self: self._not_a_column_expr()) class DefaultGenerator(_NotAColumnExpr, SchemaItem): """Base class for column *default* values.""" __visit_name__ = "default_generator" is_sequence = False is_server_default = False column = None def __init__(self, for_update=False): self.for_update = for_update def _set_parent(self, column): self.column = column if self.for_update: self.column.onupdate = self else: self.column.default = self def execute(self, bind=None, **kwargs): if bind is None: bind = _bind_or_error(self) return bind.execute(self, **kwargs) def _execute_on_connection(self, connection, multiparams, params): return connection._execute_default(self, multiparams, params) @property def bind(self): """Return the connectable associated with this default.""" if getattr(self, "column", None) is not None: return self.column.table.bind else: return None class ColumnDefault(DefaultGenerator): """A plain default value on a column. This could correspond to a constant, a callable function, or a SQL clause. :class:`.ColumnDefault` is generated automatically whenever the ``default``, ``onupdate`` arguments of :class:`_schema.Column` are used. A :class:`.ColumnDefault` can be passed positionally as well. For example, the following:: Column('foo', Integer, default=50) Is equivalent to:: Column('foo', Integer, ColumnDefault(50)) """ def __init__(self, arg, **kwargs): """Construct a new :class:`.ColumnDefault`. :param arg: argument representing the default value. May be one of the following: * a plain non-callable Python value, such as a string, integer, boolean, or other simple type. The default value will be used as is each time. * a SQL expression, that is one which derives from :class:`_expression.ColumnElement`. The SQL expression will be rendered into the INSERT or UPDATE statement, or in the case of a primary key column when RETURNING is not used may be pre-executed before an INSERT within a SELECT. * A Python callable. The function will be invoked for each new row subject to an INSERT or UPDATE. The callable must accept exactly zero or one positional arguments. The one-argument form will receive an instance of the :class:`.ExecutionContext`, which provides contextual information as to the current :class:`_engine.Connection` in use as well as the current statement and parameters. """ super(ColumnDefault, self).__init__(**kwargs) if isinstance(arg, FetchedValue): raise exc.ArgumentError( "ColumnDefault may not be a server-side default type." ) if util.callable(arg): arg = self._maybe_wrap_callable(arg) self.arg = arg @util.memoized_property def is_callable(self): return util.callable(self.arg) @util.memoized_property def is_clause_element(self): return isinstance(self.arg, ClauseElement) @util.memoized_property def is_scalar(self): return ( not self.is_callable and not self.is_clause_element and not self.is_sequence ) @util.memoized_property @util.dependencies("sqlalchemy.sql.sqltypes") def _arg_is_typed(self, sqltypes): if self.is_clause_element: return not isinstance(self.arg.type, sqltypes.NullType) else: return False def _maybe_wrap_callable(self, fn): """Wrap callables that don't accept a context. This is to allow easy compatibility with default callables that aren't specific to accepting of a context. """ try: argspec = util.get_callable_argspec(fn, no_self=True) except TypeError: return util.wrap_callable(lambda ctx: fn(), fn) defaulted = argspec[3] is not None and len(argspec[3]) or 0 positionals = len(argspec[0]) - defaulted if positionals == 0: return util.wrap_callable(lambda ctx: fn(), fn) elif positionals == 1: return fn else: raise exc.ArgumentError( "ColumnDefault Python function takes zero or one " "positional arguments" ) def _visit_name(self): if self.for_update: return "column_onupdate" else: return "column_default" __visit_name__ = property(_visit_name) def __repr__(self): return "ColumnDefault(%r)" % (self.arg,) class IdentityOptions(object): """Defines options for a named database sequence or an identity column. .. versionadded:: 1.3.18 .. seealso:: :class:`.Sequence` """ def __init__( self, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, cache=None, order=None, ): """Construct a :class:`.IdentityOptions` object. See the :class:`.Sequence` documentation for a complete description of the parameters :param start: the starting index of the sequence. :param increment: the increment value of the sequence. :param minvalue: the minimum value of the sequence. :param maxvalue: the maximum value of the sequence. :param nominvalue: no minimum value of the sequence. :param nomaxvalue: no maximum value of the sequence. :param cycle: allows the sequence to wrap around when the maxvalue or minvalue has been reached. :param cache: optional integer value; number of future values in the sequence which are calculated in advance. :param order: optional boolean value; if ``True``, renders the ORDER keyword. name. """ self.start = start self.increment = increment self.minvalue = minvalue self.maxvalue = maxvalue self.nominvalue = nominvalue self.nomaxvalue = nomaxvalue self.cycle = cycle self.cache = cache self.order = order class Sequence(IdentityOptions, DefaultGenerator): """Represents a named database sequence. The :class:`.Sequence` object represents the name and configurational parameters of a database sequence. It also represents a construct that can be "executed" by a SQLAlchemy :class:`_engine.Engine` or :class:`_engine.Connection`, rendering the appropriate "next value" function for the target database and returning a result. The :class:`.Sequence` is typically associated with a primary key column:: some_table = Table( 'some_table', metadata, Column('id', Integer, Sequence('some_table_seq'), primary_key=True) ) When CREATE TABLE is emitted for the above :class:`_schema.Table`, if the target platform supports sequences, a CREATE SEQUENCE statement will be emitted as well. For platforms that don't support sequences, the :class:`.Sequence` construct is ignored. .. seealso:: :class:`.CreateSequence` :class:`.DropSequence` """ __visit_name__ = "sequence" is_sequence = True def __init__( self, name, start=None, increment=None, minvalue=None, maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, schema=None, cache=None, order=None, optional=False, quote=None, metadata=None, quote_schema=None, for_update=False, ): """Construct a :class:`.Sequence` object. :param name: the name of the sequence. :param start: the starting index of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "START WITH" clause. If ``None``, the clause is omitted, which on most platforms indicates a starting value of 1. :param increment: the increment value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "INCREMENT BY" clause. If ``None``, the clause is omitted, which on most platforms indicates an increment of 1. :param minvalue: the minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "MINVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param maxvalue: the maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "MAXVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param nominvalue: no minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "NO MINVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param nomaxvalue: no maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "NO MAXVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param cycle: allows the sequence to wrap around when the maxvalue or minvalue has been reached by an ascending or descending sequence respectively. This value is used when the CREATE SEQUENCE command is emitted to the database as the "CYCLE" clause. If the limit is reached, the next number generated will be the minvalue or maxvalue, respectively. If cycle=False (the default) any calls to nextval after the sequence has reached its maximum value will return an error. .. versionadded:: 1.0.7 :param schema: optional schema name for the sequence, if located in a schema other than the default. The rules for selecting the schema name when a :class:`_schema.MetaData` is also present are the same as that of :paramref:`_schema.Table.schema`. :param cache: optional integer value; number of future values in the sequence which are calculated in advance. Renders the CACHE keyword understood by Oracle and PostgreSQL. .. versionadded:: 1.1.12 :param order: optional boolean value; if ``True``, renders the ORDER keyword, understood by Oracle, indicating the sequence is definitively ordered. May be necessary to provide deterministic ordering using Oracle RAC. .. versionadded:: 1.1.12 :param optional: boolean value, when ``True``, indicates that this :class:`.Sequence` object only needs to be explicitly generated on backends that don't provide another way to generate primary key identifiers. Currently, it essentially means, "don't create this sequence on the PostgreSQL backend, where the SERIAL keyword creates a sequence for us automatically". :param quote: boolean value, when ``True`` or ``False``, explicitly forces quoting of the :paramref:`_schema.Sequence.name` on or off. When left at its default of ``None``, normal quoting rules based on casing and reserved words take place. :param quote_schema: Set the quoting preferences for the ``schema`` name. :param metadata: optional :class:`_schema.MetaData` object which this :class:`.Sequence` will be associated with. A :class:`.Sequence` that is associated with a :class:`_schema.MetaData` gains the following capabilities: * The :class:`.Sequence` will inherit the :paramref:`_schema.MetaData.schema` parameter specified to the target :class:`_schema.MetaData`, which affects the production of CREATE / DROP DDL, if any. * The :meth:`.Sequence.create` and :meth:`.Sequence.drop` methods automatically use the engine bound to the :class:`_schema.MetaData` object, if any. * The :meth:`_schema.MetaData.create_all` and :meth:`_schema.MetaData.drop_all` methods will emit CREATE / DROP for this :class:`.Sequence`, even if the :class:`.Sequence` is not associated with any :class:`_schema.Table` / :class:`_schema.Column` that's a member of this :class:`_schema.MetaData`. The above behaviors can only occur if the :class:`.Sequence` is explicitly associated with the :class:`_schema.MetaData` via this parameter. .. seealso:: :ref:`sequence_metadata` - full discussion of the :paramref:`.Sequence.metadata` parameter. :param for_update: Indicates this :class:`.Sequence`, when associated with a :class:`_schema.Column`, should be invoked for UPDATE statements on that column's table, rather than for INSERT statements, when no value is otherwise present for that column in the statement. """ DefaultGenerator.__init__(self, for_update=for_update) IdentityOptions.__init__( self, start=start, increment=increment, minvalue=minvalue, maxvalue=maxvalue, nominvalue=nominvalue, nomaxvalue=nomaxvalue, cycle=cycle, cache=cache, order=order, ) self.name = quoted_name(name, quote) self.optional = optional if schema is BLANK_SCHEMA: self.schema = schema = None elif metadata is not None and schema is None and metadata.schema: self.schema = schema = metadata.schema else: self.schema = quoted_name(schema, quote_schema) self.metadata = metadata self._key = _get_table_key(name, schema) if metadata: self._set_metadata(metadata) @util.memoized_property def is_callable(self): return False @util.memoized_property def is_clause_element(self): return False @util.dependencies("sqlalchemy.sql.functions.func") def next_value(self, func): """Return a :class:`.next_value` function element which will render the appropriate increment function for this :class:`.Sequence` within any SQL expression. """ return func.next_value(self, bind=self.bind) def _set_parent(self, column): super(Sequence, self)._set_parent(column) column._on_table_attach(self._set_table) def _set_table(self, column, table): self._set_metadata(table.metadata) def _set_metadata(self, metadata): self.metadata = metadata self.metadata._sequences[self._key] = self @property def bind(self): if self.metadata: return self.metadata.bind else: return None def create(self, bind=None, checkfirst=True): """Creates this sequence in the database.""" if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=True): """Drops this sequence from the database.""" if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) def _not_a_column_expr(self): raise exc.InvalidRequestError( "This %s cannot be used directly " "as a column expression. Use func.next_value(sequence) " "to produce a 'next value' function that's usable " "as a column element." % self.__class__.__name__ ) @inspection._self_inspects class FetchedValue(_NotAColumnExpr, SchemaEventTarget): """A marker for a transparent database-side default. Use :class:`.FetchedValue` when the database is configured to provide some automatic default for a column. E.g.:: Column('foo', Integer, FetchedValue()) Would indicate that some trigger or default generator will create a new value for the ``foo`` column during an INSERT. .. seealso:: :ref:`triggered_columns` """ is_server_default = True reflected = False has_argument = False def __init__(self, for_update=False): self.for_update = for_update def _as_for_update(self, for_update): if for_update == self.for_update: return self else: return self._clone(for_update) def _clone(self, for_update): n = self.__class__.__new__(self.__class__) n.__dict__.update(self.__dict__) n.__dict__.pop("column", None) n.for_update = for_update return n def _set_parent(self, column): self.column = column if self.for_update: self.column.server_onupdate = self else: self.column.server_default = self def __repr__(self): return util.generic_repr(self) class DefaultClause(FetchedValue): """A DDL-specified DEFAULT column value. :class:`.DefaultClause` is a :class:`.FetchedValue` that also generates a "DEFAULT" clause when "CREATE TABLE" is emitted. :class:`.DefaultClause` is generated automatically whenever the ``server_default``, ``server_onupdate`` arguments of :class:`_schema.Column` are used. A :class:`.DefaultClause` can be passed positionally as well. For example, the following:: Column('foo', Integer, server_default="50") Is equivalent to:: Column('foo', Integer, DefaultClause("50")) """ has_argument = True def __init__(self, arg, for_update=False, _reflected=False): util.assert_arg_type( arg, (util.string_types[0], ClauseElement, TextClause), "arg" ) super(DefaultClause, self).__init__(for_update) self.arg = arg self.reflected = _reflected def __repr__(self): return "DefaultClause(%r, for_update=%r)" % (self.arg, self.for_update) @util.deprecated_cls( "0.6", ":class:`.PassiveDefault` is deprecated and will be removed in a " "future release. Please refer to :class:`.DefaultClause`.", ) class PassiveDefault(DefaultClause): """A DDL-specified DEFAULT column value.""" def __init__(self, *arg, **kw): DefaultClause.__init__(self, *arg, **kw) class Constraint(DialectKWArgs, SchemaItem): """A table-level SQL constraint.""" __visit_name__ = "constraint" def __init__( self, name=None, deferrable=None, initially=None, _create_rule=None, info=None, _type_bound=False, **dialect_kw ): r"""Create a SQL constraint. :param name: Optional, the in-database name of this ``Constraint``. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param _create_rule: a callable which is passed the DDLCompiler object during compilation. Returns True or False to signal inline generation of this Constraint. The AddConstraint and DropConstraint DDL constructs provide DDLElement's more comprehensive "conditional DDL" approach that is passed a database connection when DDL is being issued. _create_rule is instead called during any CREATE TABLE compilation, where there may not be any transaction/connection in progress. However, it allows conditional compilation of the constraint even for backends which do not support addition of constraints through ALTER TABLE, which currently includes SQLite. _create_rule is used by some types to create constraints. Currently, its call signature is subject to change at any time. :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. """ self.name = name self.deferrable = deferrable self.initially = initially if info: self.info = info self._create_rule = _create_rule self._type_bound = _type_bound util.set_creation_order(self) self._validate_dialect_kwargs(dialect_kw) @property def table(self): try: if isinstance(self.parent, Table): return self.parent except AttributeError: pass raise exc.InvalidRequestError( "This constraint is not bound to a table. Did you " "mean to call table.append_constraint(constraint) ?" ) def _set_parent(self, parent): self.parent = parent parent.constraints.add(self) def copy(self, **kw): raise NotImplementedError() def _to_schema_column(element): if hasattr(element, "__clause_element__"): element = element.__clause_element__() if not isinstance(element, Column): raise exc.ArgumentError("schema.Column object expected") return element def _to_schema_column_or_string(element): if element is None: return element elif hasattr(element, "__clause_element__"): element = element.__clause_element__() if not isinstance(element, util.string_types + (ColumnElement,)): msg = "Element %r is not a string name or column element" raise exc.ArgumentError(msg % element) return element class ColumnCollectionMixin(object): columns = None """A :class:`_expression.ColumnCollection` of :class:`_schema.Column` objects. This collection represents the columns which are referred to by this object. """ _allow_multiple_tables = False def __init__(self, *columns, **kw): _autoattach = kw.pop("_autoattach", True) self._column_flag = kw.pop("_column_flag", False) self.columns = ColumnCollection() self._pending_colargs = [ _to_schema_column_or_string(c) for c in columns ] if _autoattach and self._pending_colargs: self._check_attach() @classmethod def _extract_col_expression_collection(cls, expressions): for expr in expressions: strname = None column = None if hasattr(expr, "__clause_element__"): expr = expr.__clause_element__() if not isinstance(expr, (ColumnElement, TextClause)): # this assumes a string strname = expr else: cols = [] visitors.traverse(expr, {}, {"column": cols.append}) if cols: column = cols[0] add_element = column if column is not None else strname yield expr, column, strname, add_element def _check_attach(self, evt=False): col_objs = [c for c in self._pending_colargs if isinstance(c, Column)] cols_w_table = [c for c in col_objs if isinstance(c.table, Table)] cols_wo_table = set(col_objs).difference(cols_w_table) if cols_wo_table: # feature #3341 - place event listeners for Column objects # such that when all those cols are attached, we autoattach. assert not evt, "Should not reach here on event call" # issue #3411 - don't do the per-column auto-attach if some of the # columns are specified as strings. has_string_cols = set( c for c in self._pending_colargs if c is not None ).difference(col_objs) if not has_string_cols: def _col_attached(column, table): # this isinstance() corresponds with the # isinstance() above; only want to count Table-bound # columns if isinstance(table, Table): cols_wo_table.discard(column) if not cols_wo_table: self._check_attach(evt=True) self._cols_wo_table = cols_wo_table for col in cols_wo_table: col._on_table_attach(_col_attached) return columns = cols_w_table tables = {c.table for c in columns} if len(tables) == 1: self._set_parent_with_dispatch(tables.pop()) elif len(tables) > 1 and not self._allow_multiple_tables: table = columns[0].table others = [c for c in columns[1:] if c.table is not table] if others: raise exc.ArgumentError( "Column(s) %s are not part of table '%s'." % ( ", ".join("'%s'" % c for c in others), table.description, ) ) def _col_expressions(self, table): return [ table.c[col] if isinstance(col, util.string_types) else col for col in self._pending_colargs ] def _set_parent(self, table): for col in self._col_expressions(table): if col is not None: self.columns.add(col) class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): """A constraint that proxies a ColumnCollection.""" def __init__(self, *columns, **kw): r""" :param \*columns: A sequence of column names or Column objects. :param name: Optional, the in-database name of this constraint. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param \**kw: other keyword arguments including dialect-specific arguments are propagated to the :class:`.Constraint` superclass. """ _autoattach = kw.pop("_autoattach", True) _column_flag = kw.pop("_column_flag", False) Constraint.__init__(self, **kw) ColumnCollectionMixin.__init__( self, *columns, _autoattach=_autoattach, _column_flag=_column_flag ) columns = None """A :class:`_expression.ColumnCollection` representing the set of columns for this constraint. """ def _set_parent(self, table): Constraint._set_parent(self, table) ColumnCollectionMixin._set_parent(self, table) def __contains__(self, x): return x in self.columns def copy(self, target_table=None, **kw): # ticket #5276 constraint_kwargs = {} for dialect_name in self.dialect_options: dialect_options = self.dialect_options[dialect_name]._non_defaults for ( dialect_option_key, dialect_option_value, ) in dialect_options.items(): constraint_kwargs[ dialect_name + "_" + dialect_option_key ] = dialect_option_value c = self.__class__( name=self.name, deferrable=self.deferrable, initially=self.initially, *[ _copy_expression(expr, self.parent, target_table) for expr in self.columns ], **constraint_kwargs ) return self._schema_item_copy(c) def contains_column(self, col): """Return True if this constraint contains the given column. Note that this object also contains an attribute ``.columns`` which is a :class:`_expression.ColumnCollection` of :class:`_schema.Column` objects. """ return self.columns.contains_column(col) def __iter__(self): # inlining of # return iter(self.columns) # ColumnCollection->OrderedProperties->OrderedDict ordered_dict = self.columns._data return (ordered_dict[key] for key in ordered_dict._list) def __len__(self): return len(self.columns._data) class CheckConstraint(ColumnCollectionConstraint): """A table- or column-level CHECK constraint. Can be included in the definition of a Table or Column. """ _allow_multiple_tables = True @_document_text_coercion( "sqltext", ":class:`.CheckConstraint`", ":paramref:`.CheckConstraint.sqltext`", ) def __init__( self, sqltext, name=None, deferrable=None, initially=None, table=None, info=None, _create_rule=None, _autoattach=True, _type_bound=False, **kw ): r"""Construct a CHECK constraint. :param sqltext: A string containing the constraint definition, which will be used verbatim, or a SQL expression construct. If given as a string, the object is converted to a :func:`_expression.text` object. If the textual string includes a colon character, escape this using a backslash:: CheckConstraint(r"foo ~ E'a(?\:b|c)d") :param name: Optional, the in-database name of the constraint. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 """ self.sqltext = _literal_as_text(sqltext, allow_coercion_to_text=True) columns = [] visitors.traverse(self.sqltext, {}, {"column": columns.append}) super(CheckConstraint, self).__init__( name=name, deferrable=deferrable, initially=initially, _create_rule=_create_rule, info=info, _type_bound=_type_bound, _autoattach=_autoattach, *columns, **kw ) if table is not None: self._set_parent_with_dispatch(table) def __visit_name__(self): if isinstance(self.parent, Table): return "check_constraint" else: return "column_check_constraint" __visit_name__ = property(__visit_name__) def copy(self, target_table=None, **kw): if target_table is not None: # note that target_table is None for the copy process of # a column-bound CheckConstraint, so this path is not reached # in that case. sqltext = _copy_expression(self.sqltext, self.table, target_table) else: sqltext = self.sqltext c = CheckConstraint( sqltext, name=self.name, initially=self.initially, deferrable=self.deferrable, _create_rule=self._create_rule, table=target_table, _autoattach=False, _type_bound=self._type_bound, ) return self._schema_item_copy(c) class ForeignKeyConstraint(ColumnCollectionConstraint): """A table-level FOREIGN KEY constraint. Defines a single column or composite FOREIGN KEY ... REFERENCES constraint. For a no-frills, single column foreign key, adding a :class:`_schema.ForeignKey` to the definition of a :class:`_schema.Column` is a shorthand equivalent for an unnamed, single column :class:`_schema.ForeignKeyConstraint`. Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. """ __visit_name__ = "foreign_key_constraint" def __init__( self, columns, refcolumns, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None, use_alter=False, link_to_name=False, match=None, table=None, info=None, **dialect_kw ): r"""Construct a composite-capable FOREIGN KEY. :param columns: A sequence of local column names. The named columns must be defined and present in the parent Table. The names should match the ``key`` given to each column (defaults to the name) unless ``link_to_name`` is True. :param refcolumns: A sequence of foreign column names or Column objects. The columns must all be located within the same Table. :param name: Optional, the in-database name of the key. :param onupdate: Optional string. If set, emit ON UPDATE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param ondelete: Optional string. If set, emit ON DELETE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param link_to_name: if True, the string name given in ``column`` is the rendered name of the referenced column, not its locally assigned ``key``. :param use_alter: If True, do not emit the DDL for this constraint as part of the CREATE TABLE definition. Instead, generate it via an ALTER TABLE statement issued after the full collection of tables have been created, and drop it via an ALTER TABLE statement before the full collection of tables are dropped. The use of :paramref:`_schema.ForeignKeyConstraint.use_alter` is particularly geared towards the case where two or more tables are established within a mutually-dependent foreign key constraint relationship; however, the :meth:`_schema.MetaData.create_all` and :meth:`_schema.MetaData.drop_all` methods will perform this resolution automatically, so the flag is normally not needed. .. versionchanged:: 1.0.0 Automatic resolution of foreign key cycles has been added, removing the need to use the :paramref:`_schema.ForeignKeyConstraint.use_alter` in typical use cases. .. seealso:: :ref:`use_alter` :param match: Optional string. If set, emit MATCH when issuing DDL for this constraint. Typical values include SIMPLE, PARTIAL and FULL. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 """ Constraint.__init__( self, name=name, deferrable=deferrable, initially=initially, info=info, **dialect_kw ) self.onupdate = onupdate self.ondelete = ondelete self.link_to_name = link_to_name self.use_alter = use_alter self.match = match if len(set(columns)) != len(refcolumns): if len(set(columns)) != len(columns): # e.g. FOREIGN KEY (a, a) REFERENCES r (b, c) raise exc.ArgumentError( "ForeignKeyConstraint with duplicate source column " "references are not supported." ) else: # e.g. FOREIGN KEY (a) REFERENCES r (b, c) # paraphrasing https://www.postgresql.org/docs/9.2/static/\ # ddl-constraints.html raise exc.ArgumentError( "ForeignKeyConstraint number " "of constrained columns must match the number of " "referenced columns." ) # standalone ForeignKeyConstraint - create # associated ForeignKey objects which will be applied to hosted # Column objects (in col.foreign_keys), either now or when attached # to the Table for string-specified names self.elements = [ ForeignKey( refcol, _constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter, link_to_name=self.link_to_name, match=self.match, deferrable=self.deferrable, initially=self.initially, **self.dialect_kwargs ) for refcol in refcolumns ] ColumnCollectionMixin.__init__(self, *columns) if table is not None: if hasattr(self, "parent"): assert table is self.parent self._set_parent_with_dispatch(table) def _append_element(self, column, fk): self.columns.add(column) self.elements.append(fk) columns = None """A :class:`_expression.ColumnCollection` representing the set of columns for this constraint. """ elements = None """A sequence of :class:`_schema.ForeignKey` objects. Each :class:`_schema.ForeignKey` represents a single referring column/referred column pair. This collection is intended to be read-only. """ @property def _elements(self): # legacy - provide a dictionary view of (column_key, fk) return util.OrderedDict(zip(self.column_keys, self.elements)) @property def _referred_schema(self): for elem in self.elements: return elem._referred_schema else: return None @property def referred_table(self): """The :class:`_schema.Table` object to which this :class:`_schema.ForeignKeyConstraint` references. This is a dynamically calculated attribute which may not be available if the constraint and/or parent table is not yet associated with a metadata collection that contains the referred table. .. versionadded:: 1.0.0 """ return self.elements[0].column.table def _validate_dest_table(self, table): table_keys = set([elem._table_key() for elem in self.elements]) if None not in table_keys and len(table_keys) > 1: elem0, elem1 = sorted(table_keys)[0:2] raise exc.ArgumentError( "ForeignKeyConstraint on %s(%s) refers to " "multiple remote tables: %s and %s" % (table.fullname, self._col_description, elem0, elem1) ) @property def column_keys(self): """Return a list of string keys representing the local columns in this :class:`_schema.ForeignKeyConstraint`. This list is either the original string arguments sent to the constructor of the :class:`_schema.ForeignKeyConstraint`, or if the constraint has been initialized with :class:`_schema.Column` objects, is the string ``.key`` of each element. .. versionadded:: 1.0.0 """ if hasattr(self, "parent"): return self.columns.keys() else: return [ col.key if isinstance(col, ColumnElement) else str(col) for col in self._pending_colargs ] @property def _col_description(self): return ", ".join(self.column_keys) def _set_parent(self, table): Constraint._set_parent(self, table) try: ColumnCollectionConstraint._set_parent(self, table) except KeyError as ke: util.raise_( exc.ArgumentError( "Can't create ForeignKeyConstraint " "on table '%s': no column " "named '%s' is present." % (table.description, ke.args[0]) ), from_=ke, ) for col, fk in zip(self.columns, self.elements): if not hasattr(fk, "parent") or fk.parent is not col: fk._set_parent_with_dispatch(col) self._validate_dest_table(table) def copy(self, schema=None, target_table=None, **kw): fkc = ForeignKeyConstraint( [x.parent.key for x in self.elements], [ x._get_colspec( schema=schema, table_name=target_table.name if target_table is not None and x._table_key() == x.parent.table.key else None, ) for x in self.elements ], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter, deferrable=self.deferrable, initially=self.initially, link_to_name=self.link_to_name, match=self.match, ) for self_fk, other_fk in zip(self.elements, fkc.elements): self_fk._schema_item_copy(other_fk) return self._schema_item_copy(fkc) class PrimaryKeyConstraint(ColumnCollectionConstraint): """A table-level PRIMARY KEY constraint. The :class:`.PrimaryKeyConstraint` object is present automatically on any :class:`_schema.Table` object; it is assigned a set of :class:`_schema.Column` objects corresponding to those marked with the :paramref:`_schema.Column.primary_key` flag:: >>> my_table = Table('mytable', metadata, ... Column('id', Integer, primary_key=True), ... Column('version_id', Integer, primary_key=True), ... Column('data', String(50)) ... ) >>> my_table.primary_key PrimaryKeyConstraint( Column('id', Integer(), table=, primary_key=True, nullable=False), Column('version_id', Integer(), table=, primary_key=True, nullable=False) ) The primary key of a :class:`_schema.Table` can also be specified by using a :class:`.PrimaryKeyConstraint` object explicitly; in this mode of usage, the "name" of the constraint can also be specified, as well as other options which may be recognized by dialects:: my_table = Table('mytable', metadata, Column('id', Integer), Column('version_id', Integer), Column('data', String(50)), PrimaryKeyConstraint('id', 'version_id', name='mytable_pk') ) The two styles of column-specification should generally not be mixed. An warning is emitted if the columns present in the :class:`.PrimaryKeyConstraint` don't match the columns that were marked as ``primary_key=True``, if both are present; in this case, the columns are taken strictly from the :class:`.PrimaryKeyConstraint` declaration, and those columns otherwise marked as ``primary_key=True`` are ignored. This behavior is intended to be backwards compatible with previous behavior. .. versionchanged:: 0.9.2 Using a mixture of columns within a :class:`.PrimaryKeyConstraint` in addition to columns marked as ``primary_key=True`` now emits a warning if the lists don't match. The ultimate behavior of ignoring those columns marked with the flag only is currently maintained for backwards compatibility; this warning may raise an exception in a future release. For the use case where specific options are to be specified on the :class:`.PrimaryKeyConstraint`, but the usual style of using ``primary_key=True`` flags is still desirable, an empty :class:`.PrimaryKeyConstraint` may be specified, which will take on the primary key column collection from the :class:`_schema.Table` based on the flags:: my_table = Table('mytable', metadata, Column('id', Integer, primary_key=True), Column('version_id', Integer, primary_key=True), Column('data', String(50)), PrimaryKeyConstraint(name='mytable_pk', mssql_clustered=True) ) .. versionadded:: 0.9.2 an empty :class:`.PrimaryKeyConstraint` may now be specified for the purposes of establishing keyword arguments with the constraint, independently of the specification of "primary key" columns within the :class:`_schema.Table` itself; columns marked as ``primary_key=True`` will be gathered into the empty constraint's column collection. """ __visit_name__ = "primary_key_constraint" def __init__(self, *columns, **kw): self._implicit_generated = kw.pop("_implicit_generated", False) super(PrimaryKeyConstraint, self).__init__(*columns, **kw) def _set_parent(self, table): super(PrimaryKeyConstraint, self)._set_parent(table) if table.primary_key is not self: table.constraints.discard(table.primary_key) table.primary_key = self table.constraints.add(self) table_pks = [c for c in table.c if c.primary_key] if ( self.columns and table_pks and set(table_pks) != set(self.columns.values()) ): util.warn( "Table '%s' specifies columns %s as primary_key=True, " "not matching locally specified columns %s; setting the " "current primary key columns to %s. This warning " "may become an exception in a future release" % ( table.name, ", ".join("'%s'" % c.name for c in table_pks), ", ".join("'%s'" % c.name for c in self.columns), ", ".join("'%s'" % c.name for c in self.columns), ) ) table_pks[:] = [] for c in self.columns: c.primary_key = True c.nullable = False self.columns.extend(table_pks) def _reload(self, columns): """repopulate this :class:`.PrimaryKeyConstraint` given a set of columns. Existing columns in the table that are marked as primary_key=True are maintained. Also fires a new event. This is basically like putting a whole new :class:`.PrimaryKeyConstraint` object on the parent :class:`_schema.Table` object without actually replacing the object. The ordering of the given list of columns is also maintained; these columns will be appended to the list of columns after any which are already present. """ # set the primary key flag on new columns. # note any existing PK cols on the table also have their # flag still set. for col in columns: col.primary_key = True self.columns.extend(columns) PrimaryKeyConstraint._autoincrement_column._reset(self) self._set_parent_with_dispatch(self.table) def _replace(self, col): PrimaryKeyConstraint._autoincrement_column._reset(self) self.columns.replace(col) self.dispatch._sa_event_column_added_to_pk_constraint(self, col) @property def columns_autoinc_first(self): autoinc = self._autoincrement_column if autoinc is not None: return [autoinc] + [c for c in self.columns if c is not autoinc] else: return list(self.columns) @util.memoized_property def _autoincrement_column(self): def _validate_autoinc(col, autoinc_true): if col.type._type_affinity is None or not issubclass( col.type._type_affinity, type_api.INTEGERTYPE._type_affinity ): if autoinc_true: raise exc.ArgumentError( "Column type %s on column '%s' is not " "compatible with autoincrement=True" % (col.type, col) ) else: return False elif ( not isinstance(col.default, (type(None), Sequence)) and not autoinc_true ): return False elif col.server_default is not None and not autoinc_true: return False elif col.foreign_keys and col.autoincrement not in ( True, "ignore_fk", ): return False return True if len(self.columns) == 1: col = list(self.columns)[0] if col.autoincrement is True: _validate_autoinc(col, True) return col elif ( col.autoincrement in ( "auto", "ignore_fk", ) and _validate_autoinc(col, False) ): return col else: autoinc = None for col in self.columns: if col.autoincrement is True: _validate_autoinc(col, True) if autoinc is not None: raise exc.ArgumentError( "Only one Column may be marked " "autoincrement=True, found both %s and %s." % (col.name, autoinc.name) ) else: autoinc = col return autoinc class UniqueConstraint(ColumnCollectionConstraint): """A table-level UNIQUE constraint. Defines a single column or composite UNIQUE constraint. For a no-frills, single column constraint, adding ``unique=True`` to the ``Column`` definition is a shorthand equivalent for an unnamed, single column UniqueConstraint. """ __visit_name__ = "unique_constraint" class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): """A table-level INDEX. Defines a composite (one or more column) INDEX. E.g.:: sometable = Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)) ) Index("some_index", sometable.c.name) For a no-frills, single column index, adding :class:`_schema.Column` also supports ``index=True``:: sometable = Table("sometable", metadata, Column("name", String(50), index=True) ) For a composite index, multiple columns can be specified:: Index("some_index", sometable.c.name, sometable.c.address) Functional indexes are supported as well, typically by using the :data:`.func` construct in conjunction with table-bound :class:`_schema.Column` objects:: Index("some_index", func.lower(sometable.c.name)) An :class:`.Index` can also be manually associated with a :class:`_schema.Table`, either through inline declaration or using :meth:`_schema.Table.append_constraint`. When this approach is used, the names of the indexed columns can be specified as strings:: Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)), Index("some_index", "name", "address") ) To support functional or expression-based indexes in this form, the :func:`_expression.text` construct may be used:: from sqlalchemy import text Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)), Index("some_index", text("lower(name)")) ) .. versionadded:: 0.9.5 the :func:`_expression.text` construct may be used to specify :class:`.Index` expressions, provided the :class:`.Index` is explicitly associated with the :class:`_schema.Table`. .. seealso:: :ref:`schema_indexes` - General information on :class:`.Index`. :ref:`postgresql_indexes` - PostgreSQL-specific options available for the :class:`.Index` construct. :ref:`mysql_indexes` - MySQL-specific options available for the :class:`.Index` construct. :ref:`mssql_indexes` - MSSQL-specific options available for the :class:`.Index` construct. """ __visit_name__ = "index" def __init__(self, name, *expressions, **kw): r"""Construct an index object. :param name: The name of the index :param \*expressions: Column expressions to include in the index. The expressions are normally instances of :class:`_schema.Column`, but may also be arbitrary SQL expressions which ultimately refer to a :class:`_schema.Column`. :param unique=False: Keyword only argument; if True, create a unique index. :param quote=None: Keyword only argument; whether to apply quoting to the name of the index. Works in the same manner as that of :paramref:`_schema.Column.quote`. :param info=None: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**kw: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. """ self.table = table = None columns = [] processed_expressions = [] for ( expr, column, strname, add_element, ) in self._extract_col_expression_collection(expressions): columns.append(add_element) processed_expressions.append(expr) self.expressions = processed_expressions self.name = quoted_name(name, kw.pop("quote", None)) self.unique = kw.pop("unique", False) _column_flag = kw.pop("_column_flag", False) if "info" in kw: self.info = kw.pop("info") # TODO: consider "table" argument being public, but for # the purpose of the fix here, it starts as private. if "_table" in kw: table = kw.pop("_table") self._validate_dialect_kwargs(kw) # will call _set_parent() if table-bound column # objects are present ColumnCollectionMixin.__init__( self, *columns, _column_flag=_column_flag ) if table is not None: self._set_parent(table) def _set_parent(self, table): ColumnCollectionMixin._set_parent(self, table) if self.table is not None and table is not self.table: raise exc.ArgumentError( "Index '%s' is against table '%s', and " "cannot be associated with table '%s'." % (self.name, self.table.description, table.description) ) self.table = table table.indexes.add(self) expressions = self.expressions col_expressions = self._col_expressions(table) assert len(expressions) == len(col_expressions) self.expressions = [ expr if isinstance(expr, ClauseElement) else colexpr for expr, colexpr in zip(expressions, col_expressions) ] @property def bind(self): """Return the connectable associated with this Index.""" return self.table.bind def create(self, bind=None): """Issue a ``CREATE`` statement for this :class:`.Index`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.create_all`. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaGenerator, self) return self def drop(self, bind=None): """Issue a ``DROP`` statement for this :class:`.Index`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.drop_all`. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor(ddl.SchemaDropper, self) def __repr__(self): return "Index(%s)" % ( ", ".join( [repr(self.name)] + [repr(e) for e in self.expressions] + (self.unique and ["unique=True"] or []) ) ) DEFAULT_NAMING_CONVENTION = util.immutabledict({"ix": "ix_%(column_0_label)s"}) class MetaData(SchemaItem): """A collection of :class:`_schema.Table` objects and their associated schema constructs. Holds a collection of :class:`_schema.Table` objects as well as an optional binding to an :class:`_engine.Engine` or :class:`_engine.Connection`. If bound, the :class:`_schema.Table` objects in the collection and their columns may participate in implicit SQL execution. The :class:`_schema.Table` objects themselves are stored in the :attr:`_schema.MetaData.tables` dictionary. :class:`_schema.MetaData` is a thread-safe object for read operations. Construction of new tables within a single :class:`_schema.MetaData` object, either explicitly or via reflection, may not be completely thread-safe. .. seealso:: :ref:`metadata_describing` - Introduction to database metadata """ __visit_name__ = "metadata" @util.deprecated_params( reflect=( "0.8", "The :paramref:`_schema.MetaData.reflect` " "flag is deprecated and will " "be removed in a future release. Please use the " ":meth:`_schema.MetaData.reflect` method.", ) ) def __init__( self, bind=None, reflect=False, schema=None, quote_schema=None, naming_convention=None, info=None, ): """Create a new MetaData object. :param bind: An Engine or Connection to bind to. May also be a string or URL instance, these are passed to :func:`_sa.create_engine` and this :class:`_schema.MetaData` will be bound to the resulting engine. :param reflect: Optional, automatically load all tables from the bound database. Defaults to False. :paramref:`_schema.MetaData.bind` is required when this option is set. :param schema: The default schema to use for the :class:`_schema.Table`, :class:`.Sequence`, and potentially other objects associated with this :class:`_schema.MetaData`. Defaults to ``None``. When this value is set, any :class:`_schema.Table` or :class:`.Sequence` which specifies ``None`` for the schema parameter will instead have this schema name defined. To build a :class:`_schema.Table` or :class:`.Sequence` that still has ``None`` for the schema even when this parameter is present, use the :attr:`.BLANK_SCHEMA` symbol. .. note:: As referred above, the :paramref:`_schema.MetaData.schema` parameter only refers to the **default value** that will be applied to the :paramref:`_schema.Table.schema` parameter of an incoming :class:`_schema.Table` object. It does not refer to how the :class:`_schema.Table` is catalogued within the :class:`_schema.MetaData`, which remains consistent vs. a :class:`_schema.MetaData` collection that does not define this parameter. The :class:`_schema.Table` within the :class:`_schema.MetaData` will still be keyed based on its schema-qualified name, e.g. ``my_metadata.tables["some_schema.my_table"]``. The current behavior of the :class:`_schema.ForeignKey` object is to circumvent this restriction, where it can locate a table given the table name alone, where the schema will be assumed to be present from this value as specified on the owning :class:`_schema.MetaData` collection. However, this implies that a table qualified with BLANK_SCHEMA cannot currently be referred to by string name from :class:`_schema.ForeignKey`. Other parts of SQLAlchemy such as Declarative may not have similar behaviors built in, however may do so in a future release, along with a consistent method of referring to a table in BLANK_SCHEMA. .. seealso:: :paramref:`_schema.Table.schema` :paramref:`.Sequence.schema` :param quote_schema: Sets the ``quote_schema`` flag for those :class:`_schema.Table`, :class:`.Sequence`, and other objects which make usage of the local ``schema`` name. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param naming_convention: a dictionary referring to values which will establish default naming conventions for :class:`.Constraint` and :class:`.Index` objects, for those objects which are not given a name explicitly. The keys of this dictionary may be: * a constraint or Index class, e.g. the :class:`.UniqueConstraint`, :class:`_schema.ForeignKeyConstraint` class, the :class:`.Index` class * a string mnemonic for one of the known constraint classes; ``"fk"``, ``"pk"``, ``"ix"``, ``"ck"``, ``"uq"`` for foreign key, primary key, index, check, and unique constraint, respectively. * the string name of a user-defined "token" that can be used to define new naming tokens. The values associated with each "constraint class" or "constraint mnemonic" key are string naming templates, such as ``"uq_%(table_name)s_%(column_0_name)s"``, which describe how the name should be composed. The values associated with user-defined "token" keys should be callables of the form ``fn(constraint, table)``, which accepts the constraint/index object and :class:`_schema.Table` as arguments, returning a string result. The built-in names are as follows, some of which may only be available for certain types of constraint: * ``%(table_name)s`` - the name of the :class:`_schema.Table` object associated with the constraint. * ``%(referred_table_name)s`` - the name of the :class:`_schema.Table` object associated with the referencing target of a :class:`_schema.ForeignKeyConstraint`. * ``%(column_0_name)s`` - the name of the :class:`_schema.Column` at index position "0" within the constraint. * ``%(column_0N_name)s`` - the name of all :class:`_schema.Column` objects in order within the constraint, joined without a separator. * ``%(column_0_N_name)s`` - the name of all :class:`_schema.Column` objects in order within the constraint, joined with an underscore as a separator. * ``%(column_0_label)s``, ``%(column_0N_label)s``, ``%(column_0_N_label)s`` - the label of either the zeroth :class:`_schema.Column` or all :class:`.Columns`, separated with or without an underscore * ``%(column_0_key)s``, ``%(column_0N_key)s``, ``%(column_0_N_key)s`` - the key of either the zeroth :class:`_schema.Column` or all :class:`.Columns`, separated with or without an underscore * ``%(referred_column_0_name)s``, ``%(referred_column_0N_name)s`` ``%(referred_column_0_N_name)s``, ``%(referred_column_0_key)s``, ``%(referred_column_0N_key)s``, ... column tokens which render the names/keys/labels of columns that are referenced by a :class:`_schema.ForeignKeyConstraint`. * ``%(constraint_name)s`` - a special key that refers to the existing name given to the constraint. When this key is present, the :class:`.Constraint` object's existing name will be replaced with one that is composed from template string that uses this token. When this token is present, it is required that the :class:`.Constraint` is given an explicit name ahead of time. * user-defined: any additional token may be implemented by passing it along with a ``fn(constraint, table)`` callable to the naming_convention dictionary. .. versionadded:: 1.3.0 - added new ``%(column_0N_name)s``, ``%(column_0_N_name)s``, and related tokens that produce concatenations of names, keys, or labels for all columns referred to by a given constraint. .. seealso:: :ref:`constraint_naming_conventions` - for detailed usage examples. """ self.tables = util.immutabledict() self.schema = quoted_name(schema, quote_schema) self.naming_convention = ( naming_convention if naming_convention else DEFAULT_NAMING_CONVENTION ) if info: self.info = info self._schemas = set() self._sequences = {} self._fk_memos = collections.defaultdict(list) self.bind = bind if reflect: if not bind: raise exc.ArgumentError( "A bind must be supplied in conjunction " "with reflect=True" ) self.reflect() tables = None """A dictionary of :class:`_schema.Table` objects keyed to their name or "table key". The exact key is that determined by the :attr:`_schema.Table.key` attribute; for a table with no :attr:`_schema.Table.schema` attribute, this is the same as :attr:`_schema.Table.name`. For a table with a schema, it is typically of the form ``schemaname.tablename``. .. seealso:: :attr:`_schema.MetaData.sorted_tables` """ def __repr__(self): return "MetaData(bind=%r)" % self.bind def __contains__(self, table_or_key): if not isinstance(table_or_key, util.string_types): table_or_key = table_or_key.key return table_or_key in self.tables def _add_table(self, name, schema, table): key = _get_table_key(name, schema) dict.__setitem__(self.tables, key, table) if schema: self._schemas.add(schema) def _remove_table(self, name, schema): key = _get_table_key(name, schema) removed = dict.pop(self.tables, key, None) if removed is not None: for fk in removed.foreign_keys: fk._remove_from_metadata(self) if self._schemas: self._schemas = set( [ t.schema for t in self.tables.values() if t.schema is not None ] ) def __getstate__(self): return { "tables": self.tables, "schema": self.schema, "schemas": self._schemas, "sequences": self._sequences, "fk_memos": self._fk_memos, "naming_convention": self.naming_convention, } def __setstate__(self, state): self.tables = state["tables"] self.schema = state["schema"] self.naming_convention = state["naming_convention"] self._bind = None self._sequences = state["sequences"] self._schemas = state["schemas"] self._fk_memos = state["fk_memos"] def is_bound(self): """True if this MetaData is bound to an Engine or Connection.""" return self._bind is not None def bind(self): """An :class:`_engine.Engine` or :class:`_engine.Connection` to which this :class:`_schema.MetaData` is bound. Typically, a :class:`_engine.Engine` is assigned to this attribute so that "implicit execution" may be used, or alternatively as a means of providing engine binding information to an ORM :class:`.Session` object:: engine = create_engine("someurl://") metadata.bind = engine .. seealso:: :ref:`dbengine_implicit` - background on "bound metadata" """ return self._bind @util.dependencies("sqlalchemy.engine.url") def _bind_to(self, url, bind): """Bind this MetaData to an Engine, Connection, string or URL.""" if isinstance(bind, util.string_types + (url.URL,)): self._bind = sqlalchemy.create_engine(bind) else: self._bind = bind bind = property(bind, _bind_to) def clear(self): """Clear all Table objects from this MetaData.""" dict.clear(self.tables) self._schemas.clear() self._fk_memos.clear() def remove(self, table): """Remove the given Table object from this MetaData.""" self._remove_table(table.name, table.schema) @property def sorted_tables(self): """Returns a list of :class:`_schema.Table` objects sorted in order of foreign key dependency. The sorting will place :class:`_schema.Table` objects that have dependencies first, before the dependencies themselves, representing the order in which they can be created. To get the order in which the tables would be dropped, use the ``reversed()`` Python built-in. .. warning:: The :attr:`.MetaData.sorted_tables` attribute cannot by itself accommodate automatic resolution of dependency cycles between tables, which are usually caused by mutually dependent foreign key constraints. When these cycles are detected, the foreign keys of these tables are omitted from consideration in the sort. A warning is emitted when this condition occurs, which will be an exception raise in a future release. Tables which are not part of the cycle will still be returned in dependency order. To resolve these cycles, the :paramref:`_schema.ForeignKeyConstraint.use_alter` parameter may be applied to those constraints which create a cycle. Alternatively, the :func:`_schema.sort_tables_and_constraints` function will automatically return foreign key constraints in a separate collection when cycles are detected so that they may be applied to a schema separately. .. versionchanged:: 1.3.17 - a warning is emitted when :attr:`.MetaData.sorted_tables` cannot perform a proper sort due to cyclical dependencies. This will be an exception in a future release. Additionally, the sort will continue to return other tables not involved in the cycle in dependency order which was not the case previously. .. seealso:: :func:`_schema.sort_tables` :func:`_schema.sort_tables_and_constraints` :attr:`_schema.MetaData.tables` :meth:`_reflection.Inspector.get_table_names` :meth:`_reflection.Inspector.get_sorted_table_and_fkc_names` """ return ddl.sort_tables( sorted(self.tables.values(), key=lambda t: t.key) ) def reflect( self, bind=None, schema=None, views=False, only=None, extend_existing=False, autoload_replace=True, resolve_fks=True, **dialect_kwargs ): r"""Load all available table definitions from the database. Automatically creates ``Table`` entries in this ``MetaData`` for any table available in the database but not yet present in the ``MetaData``. May be called multiple times to pick up tables recently added to the database, however no special action is taken if a table in this ``MetaData`` no longer exists in the database. :param bind: A :class:`.Connectable` used to access the database; if None, uses the existing bind on this ``MetaData``, if any. :param schema: Optional, query and reflect tables from an alternate schema. If None, the schema associated with this :class:`_schema.MetaData` is used, if any. :param views: If True, also reflect views. :param only: Optional. Load only a sub-set of available named tables. May be specified as a sequence of names or a callable. If a sequence of names is provided, only those tables will be reflected. An error is raised if a table is requested but not available. Named tables already present in this ``MetaData`` are ignored. If a callable is provided, it will be used as a boolean predicate to filter the list of potential table names. The callable is called with a table name and this ``MetaData`` instance as positional arguments and should return a true value for any table to reflect. :param extend_existing: Passed along to each :class:`_schema.Table` as :paramref:`_schema.Table.extend_existing`. .. versionadded:: 0.9.1 :param autoload_replace: Passed along to each :class:`_schema.Table` as :paramref:`_schema.Table.autoload_replace`. .. versionadded:: 0.9.1 :param resolve_fks: if True, reflect :class:`_schema.Table` objects linked to :class:`_schema.ForeignKey` objects located in each :class:`_schema.Table`. For :meth:`_schema.MetaData.reflect`, this has the effect of reflecting related tables that might otherwise not be in the list of tables being reflected, for example if the referenced table is in a different schema or is omitted via the :paramref:`.MetaData.reflect.only` parameter. When False, :class:`_schema.ForeignKey` objects are not followed to the :class:`_schema.Table` in which they link, however if the related table is also part of the list of tables that would be reflected in any case, the :class:`_schema.ForeignKey` object will still resolve to its related :class:`_schema.Table` after the :meth:`_schema.MetaData.reflect` operation is complete. Defaults to True. .. versionadded:: 1.3.0 .. seealso:: :paramref:`_schema.Table.resolve_fks` :param \**dialect_kwargs: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 - Added :paramref:`.MetaData.reflect.**dialect_kwargs` to support dialect-level reflection options for all :class:`_schema.Table` objects reflected. """ if bind is None: bind = _bind_or_error(self) with bind.connect() as conn: reflect_opts = { "autoload": True, "autoload_with": conn, "extend_existing": extend_existing, "autoload_replace": autoload_replace, "resolve_fks": resolve_fks, "_extend_on": set(), } reflect_opts.update(dialect_kwargs) if schema is None: schema = self.schema if schema is not None: reflect_opts["schema"] = schema available = util.OrderedSet( bind.engine.table_names(schema, connection=conn) ) if views: available.update(bind.dialect.get_view_names(conn, schema)) if schema is not None: available_w_schema = util.OrderedSet( ["%s.%s" % (schema, name) for name in available] ) else: available_w_schema = available current = set(self.tables) if only is None: load = [ name for name, schname in zip(available, available_w_schema) if extend_existing or schname not in current ] elif util.callable(only): load = [ name for name, schname in zip(available, available_w_schema) if (extend_existing or schname not in current) and only(name, self) ] else: missing = [name for name in only if name not in available] if missing: s = schema and (" schema '%s'" % schema) or "" raise exc.InvalidRequestError( "Could not reflect: requested table(s) not available " "in %r%s: (%s)" % (bind.engine, s, ", ".join(missing)) ) load = [ name for name in only if extend_existing or name not in current ] for name in load: try: Table(name, self, **reflect_opts) except exc.UnreflectableTableError as uerr: util.warn("Skipping table %s: %s" % (name, uerr)) @util.deprecated( "0.7", "the :meth:`_schema.MetaData.append_ddl_listener` " "method is deprecated and " "will be removed in a future release. Please refer to " ":class:`.DDLEvents`.", ) def append_ddl_listener(self, event_name, listener): """Append a DDL event listener to this ``MetaData``.""" def adapt_listener(target, connection, **kw): tables = kw["tables"] listener(event, target, connection, tables=tables) event.listen(self, "" + event_name.replace("-", "_"), adapt_listener) def create_all(self, bind=None, tables=None, checkfirst=True): """Create all tables stored in this metadata. Conditional by default, will not attempt to recreate tables already present in the target database. :param bind: A :class:`.Connectable` used to access the database; if None, uses the existing bind on this ``MetaData``, if any. :param tables: Optional list of ``Table`` objects, which is a subset of the total tables in the ``MetaData`` (others are ignored). :param checkfirst: Defaults to True, don't issue CREATEs for tables already present in the target database. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor( ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables ) def drop_all(self, bind=None, tables=None, checkfirst=True): """Drop all tables stored in this metadata. Conditional by default, will not attempt to drop tables not present in the target database. :param bind: A :class:`.Connectable` used to access the database; if None, uses the existing bind on this ``MetaData``, if any. :param tables: Optional list of ``Table`` objects, which is a subset of the total tables in the ``MetaData`` (others are ignored). :param checkfirst: Defaults to True, only issue DROPs for tables confirmed to be present in the target database. """ if bind is None: bind = _bind_or_error(self) bind._run_visitor( ddl.SchemaDropper, self, checkfirst=checkfirst, tables=tables ) class ThreadLocalMetaData(MetaData): """A MetaData variant that presents a different ``bind`` in every thread. Makes the ``bind`` property of the MetaData a thread-local value, allowing this collection of tables to be bound to different ``Engine`` implementations or connections in each thread. The ThreadLocalMetaData starts off bound to None in each thread. Binds must be made explicitly by assigning to the ``bind`` property or using ``connect()``. You can also re-bind dynamically multiple times per thread, just like a regular ``MetaData``. """ __visit_name__ = "metadata" def __init__(self): """Construct a ThreadLocalMetaData.""" self.context = util.threading.local() self.__engines = {} super(ThreadLocalMetaData, self).__init__() def bind(self): """The bound Engine or Connection for this thread. This property may be assigned an Engine or Connection, or assigned a string or URL to automatically create a basic Engine for this bind with ``create_engine()``.""" return getattr(self.context, "_engine", None) @util.dependencies("sqlalchemy.engine.url") def _bind_to(self, url, bind): """Bind to a Connectable in the caller's thread.""" if isinstance(bind, util.string_types + (url.URL,)): try: self.context._engine = self.__engines[bind] except KeyError: e = sqlalchemy.create_engine(bind) self.__engines[bind] = e self.context._engine = e else: # TODO: this is squirrely. we shouldn't have to hold onto engines # in a case like this if bind not in self.__engines: self.__engines[bind] = bind self.context._engine = bind bind = property(bind, _bind_to) def is_bound(self): """True if there is a bind for this thread.""" return ( hasattr(self.context, "_engine") and self.context._engine is not None ) def dispose(self): """Dispose all bound engines, in all thread contexts.""" for e in self.__engines.values(): if hasattr(e, "dispose"): e.dispose() class _SchemaTranslateMap(object): """Provide translation of schema names based on a mapping. Also provides helpers for producing cache keys and optimized access when no mapping is present. Used by the :paramref:`.Connection.execution_options.schema_translate_map` feature. .. versionadded:: 1.1 """ __slots__ = "map_", "__call__", "hash_key", "is_default" _default_schema_getter = operator.attrgetter("schema") def __init__(self, map_): self.map_ = map_ if map_ is not None: def schema_for_object(obj): effective_schema = self._default_schema_getter(obj) effective_schema = obj._translate_schema( effective_schema, map_ ) return effective_schema self.__call__ = schema_for_object self.hash_key = ";".join( "%s=%s" % (k, map_[k]) for k in sorted(map_, key=str) ) self.is_default = False else: self.hash_key = 0 self.__call__ = self._default_schema_getter self.is_default = True @classmethod def _schema_getter(cls, map_): if map_ is None: return _default_schema_map elif isinstance(map_, _SchemaTranslateMap): return map_ else: return _SchemaTranslateMap(map_) _default_schema_map = _SchemaTranslateMap(None) _schema_getter = _SchemaTranslateMap._schema_getter class Computed(FetchedValue, SchemaItem): """Defines a generated column, i.e. "GENERATED ALWAYS AS" syntax. The :class:`.Computed` construct is an inline construct added to the argument list of a :class:`_schema.Column` object:: from sqlalchemy import Computed Table('square', meta, Column('side', Float, nullable=False), Column('area', Float, Computed('side * side')) ) See the linked documentation below for complete details. .. versionadded:: 1.3.11 .. seealso:: :ref:`computed_ddl` """ __visit_name__ = "computed_column" @_document_text_coercion( "sqltext", ":class:`.Computed`", ":paramref:`.Computed.sqltext`" ) def __init__(self, sqltext, persisted=None): """Construct a GENERATED ALWAYS AS DDL construct to accompany a :class:`_schema.Column`. :param sqltext: A string containing the column generation expression, which will be used verbatim, or a SQL expression construct, such as a :func:`_expression.text` object. If given as a string, the object is converted to a :func:`_expression.text` object. :param persisted: Optional, controls how this column should be persisted by the database. Possible values are: * ``None``, the default, it will use the default persistence defined by the database. * ``True``, will render ``GENERATED ALWAYS AS ... STORED``, or the equivalent for the target database if supported. * ``False``, will render ``GENERATED ALWAYS AS ... VIRTUAL``, or the equivalent for the target database if supported. Specifying ``True`` or ``False`` may raise an error when the DDL is emitted to the target database if the database does not support that persistence option. Leaving this parameter at its default of ``None`` is guaranteed to succeed for all databases that support ``GENERATED ALWAYS AS``. """ self.sqltext = _literal_as_text(sqltext, allow_coercion_to_text=True) self.persisted = persisted self.column = None def _set_parent(self, parent): if not isinstance( parent.server_default, (type(None), Computed) ) or not isinstance(parent.server_onupdate, (type(None), Computed)): raise exc.ArgumentError( "A generated column cannot specify a server_default or a " "server_onupdate argument" ) self.column = parent parent.computed = self self.column.server_onupdate = self self.column.server_default = self def _as_for_update(self, for_update): return self def copy(self, target_table=None, **kw): sqltext = _copy_expression( self.sqltext, self.column.table if self.column is not None else None, target_table, ) g = Computed(sqltext, persisted=self.persisted) return self._schema_item_copy(g) PK!UU sqltypes.pynu[# sql/sqltypes.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """SQL specific types. """ import codecs import datetime as dt import decimal import json from . import elements from . import operators from . import type_api from .base import _bind_or_error from .base import NO_ARG from .base import SchemaEventTarget from .elements import _literal_as_binds from .elements import _NONE_NAME from .elements import quoted_name from .elements import Slice from .elements import TypeCoerce as type_coerce # noqa from .type_api import Emulated from .type_api import NativeForEmulated # noqa from .type_api import to_instance from .type_api import TypeDecorator from .type_api import TypeEngine from .type_api import Variant from .. import event from .. import exc from .. import inspection from .. import processors from .. import util from ..util import compat from ..util import langhelpers from ..util import pickle if util.jython: import array class _LookupExpressionAdapter(object): """Mixin expression adaptations based on lookup tables. These rules are currently used by the numeric, integer and date types which have detailed cross-expression coercion rules. """ @property def _expression_adaptations(self): raise NotImplementedError() class Comparator(TypeEngine.Comparator): _blank_dict = util.immutabledict() def _adapt_expression(self, op, other_comparator): othertype = other_comparator.type._type_affinity lookup = self.type._expression_adaptations.get( op, self._blank_dict ).get(othertype, self.type) if lookup is othertype: return (op, other_comparator.type) elif lookup is self.type._type_affinity: return (op, self.type) else: return (op, to_instance(lookup)) comparator_factory = Comparator class Concatenable(object): """A mixin that marks a type as supporting 'concatenation', typically strings.""" class Comparator(TypeEngine.Comparator): def _adapt_expression(self, op, other_comparator): if op is operators.add and isinstance( other_comparator, (Concatenable.Comparator, NullType.Comparator), ): return operators.concat_op, self.expr.type else: return super(Concatenable.Comparator, self)._adapt_expression( op, other_comparator ) comparator_factory = Comparator class Indexable(object): """A mixin that marks a type as supporting indexing operations, such as array or JSON structures. .. versionadded:: 1.1.0 """ class Comparator(TypeEngine.Comparator): def _setup_getitem(self, index): raise NotImplementedError() def __getitem__(self, index): ( adjusted_op, adjusted_right_expr, result_type, ) = self._setup_getitem(index) return self.operate( adjusted_op, adjusted_right_expr, result_type=result_type ) comparator_factory = Comparator class String(Concatenable, TypeEngine): """The base for all string and character types. In SQL, corresponds to VARCHAR. Can also take Python unicode objects and encode to the database's encoding in bind params (and the reverse for result sets.) The `length` field is usually required when the `String` type is used within a CREATE TABLE statement, as VARCHAR requires a length on most databases. """ __visit_name__ = "string" @util.deprecated_params( convert_unicode=( "1.3", "The :paramref:`.String.convert_unicode` parameter is deprecated " "and will be removed in a future release. All modern DBAPIs " "now support Python Unicode directly and this parameter is " "unnecessary.", ), unicode_error=( "1.3", "The :paramref:`.String.unicode_errors` parameter is deprecated " "and will be removed in a future release. This parameter is " "unnecessary for modern Python DBAPIs and degrades performance " "significantly.", ), ) def __init__( self, length=None, collation=None, convert_unicode=False, unicode_error=None, _warn_on_bytestring=False, _expect_unicode=False, ): """ Create a string-holding type. :param length: optional, a length for the column for use in DDL and CAST expressions. May be safely omitted if no ``CREATE TABLE`` will be issued. Certain databases may require a ``length`` for use in DDL, and will raise an exception when the ``CREATE TABLE`` DDL is issued if a ``VARCHAR`` with no length is included. Whether the value is interpreted as bytes or characters is database specific. :param collation: Optional, a column-level collation for use in DDL and CAST expressions. Renders using the COLLATE keyword supported by SQLite, MySQL, and PostgreSQL. E.g.:: >>> from sqlalchemy import cast, select, String >>> print(select([cast('some string', String(collation='utf8'))])) SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1 :param convert_unicode: When set to ``True``, the :class:`.String` type will assume that input is to be passed as Python Unicode objects under Python 2, and results returned as Python Unicode objects. In the rare circumstance that the DBAPI does not support Python unicode under Python 2, SQLAlchemy will use its own encoder/decoder functionality on strings, referring to the value of the :paramref:`_sa.create_engine.encoding` parameter parameter passed to :func:`_sa.create_engine` as the encoding. For the extremely rare case that Python Unicode is to be encoded/decoded by SQLAlchemy on a backend that *does* natively support Python Unicode, the string value ``"force"`` can be passed here which will cause SQLAlchemy's encode/decode services to be used unconditionally. .. note:: SQLAlchemy's unicode-conversion flags and features only apply to Python 2; in Python 3, all string objects are Unicode objects. For this reason, as well as the fact that virtually all modern DBAPIs now support Unicode natively even under Python 2, the :paramref:`.String.convert_unicode` flag is inherently a legacy feature. .. note:: In the vast majority of cases, the :class:`.Unicode` or :class:`.UnicodeText` datatypes should be used for a :class:`_schema.Column` that expects to store non-ascii data. These datatypes will ensure that the correct types are used on the database side as well as set up the correct Unicode behaviors under Python 2. .. seealso:: :paramref:`_sa.create_engine.convert_unicode` - :class:`_engine.Engine`-wide parameter :param unicode_error: Optional, a method to use to handle Unicode conversion errors. Behaves like the ``errors`` keyword argument to the standard library's ``string.decode()`` functions, requires that :paramref:`.String.convert_unicode` is set to ``"force"`` """ if unicode_error is not None and convert_unicode != "force": raise exc.ArgumentError( "convert_unicode must be 'force' " "when unicode_error is set." ) self.length = length self.collation = collation self._expect_unicode = convert_unicode or _expect_unicode self._expect_unicode_error = unicode_error self._warn_on_bytestring = _warn_on_bytestring def literal_processor(self, dialect): def process(value): value = value.replace("'", "''") if dialect.identifier_preparer._double_percents: value = value.replace("%", "%%") return "'%s'" % value return process def bind_processor(self, dialect): if self._expect_unicode or dialect.convert_unicode: if ( dialect.supports_unicode_binds and self._expect_unicode != "force" ): if self._warn_on_bytestring: def process(value): if isinstance(value, util.binary_type): util.warn_limited( "Unicode type received non-unicode " "bind param value %r.", (util.ellipses_string(value),), ) return value return process else: return None else: encoder = codecs.getencoder(dialect.encoding) warn_on_bytestring = self._warn_on_bytestring def process(value): if isinstance(value, util.text_type): return encoder(value, self._expect_unicode_error)[0] elif warn_on_bytestring and value is not None: util.warn_limited( "Unicode type received non-unicode bind " "param value %r.", (util.ellipses_string(value),), ) return value return process else: return None def result_processor(self, dialect, coltype): wants_unicode = self._expect_unicode or dialect.convert_unicode needs_convert = wants_unicode and ( dialect.returns_unicode_strings is not True or self._expect_unicode in ("force", "force_nocheck") ) needs_isinstance = ( needs_convert and dialect.returns_unicode_strings and self._expect_unicode != "force_nocheck" ) if needs_convert: if needs_isinstance: return processors.to_conditional_unicode_processor_factory( dialect.encoding, self._expect_unicode_error ) else: return processors.to_unicode_processor_factory( dialect.encoding, self._expect_unicode_error ) else: return None @property def python_type(self): if self._expect_unicode: return util.text_type else: return str def get_dbapi_type(self, dbapi): return dbapi.STRING @classmethod def _warn_deprecated_unicode(cls): util.warn_deprecated( "The convert_unicode on Engine and String as well as the " "unicode_error flag on String are deprecated. All modern " "DBAPIs now support Python Unicode natively under Python 2, and " "under Python 3 all strings are inherently Unicode. These flags " "will be removed in a future release." ) class Text(String): """A variably sized string type. In SQL, usually corresponds to CLOB or TEXT. Can also take Python unicode objects and encode to the database's encoding in bind params (and the reverse for result sets.) In general, TEXT objects do not have a length; while some databases will accept a length argument here, it will be rejected by others. """ __visit_name__ = "text" class Unicode(String): """A variable length Unicode string type. The :class:`.Unicode` type is a :class:`.String` subclass that assumes input and output as Python ``unicode`` data, and in that regard is equivalent to the usage of the ``convert_unicode`` flag with the :class:`.String` type. However, unlike plain :class:`.String`, it also implies an underlying column type that is explicitly supporting of non-ASCII data, such as ``NVARCHAR`` on Oracle and SQL Server. This can impact the output of ``CREATE TABLE`` statements and ``CAST`` functions at the dialect level, and can also affect the handling of bound parameters in some specific DBAPI scenarios. The encoding used by the :class:`.Unicode` type is usually determined by the DBAPI itself; most modern DBAPIs feature support for Python ``unicode`` objects as bound values and result set values, and the encoding should be configured as detailed in the notes for the target DBAPI in the :ref:`dialect_toplevel` section. For those DBAPIs which do not support, or are not configured to accommodate Python ``unicode`` objects directly, SQLAlchemy does the encoding and decoding outside of the DBAPI. The encoding in this scenario is determined by the ``encoding`` flag passed to :func:`_sa.create_engine`. When using the :class:`.Unicode` type, it is only appropriate to pass Python ``unicode`` objects, and not plain ``str``. If a plain ``str`` is passed under Python 2, a warning is emitted. If you notice your application emitting these warnings but you're not sure of the source of them, the Python ``warnings`` filter, documented at http://docs.python.org/library/warnings.html, can be used to turn these warnings into exceptions which will illustrate a stack trace:: import warnings warnings.simplefilter('error') For an application that wishes to pass plain bytestrings and Python ``unicode`` objects to the ``Unicode`` type equally, the bytestrings must first be decoded into unicode. The recipe at :ref:`coerce_to_unicode` illustrates how this is done. .. seealso:: :class:`.UnicodeText` - unlengthed textual counterpart to :class:`.Unicode`. """ __visit_name__ = "unicode" def __init__(self, length=None, **kwargs): """ Create a :class:`.Unicode` object. Parameters are the same as that of :class:`.String`, with the exception that ``convert_unicode`` defaults to ``True``. """ kwargs.setdefault("_expect_unicode", True) kwargs.setdefault("_warn_on_bytestring", True) super(Unicode, self).__init__(length=length, **kwargs) class UnicodeText(Text): """An unbounded-length Unicode string type. See :class:`.Unicode` for details on the unicode behavior of this object. Like :class:`.Unicode`, usage the :class:`.UnicodeText` type implies a unicode-capable type being used on the backend, such as ``NCLOB``, ``NTEXT``. """ __visit_name__ = "unicode_text" def __init__(self, length=None, **kwargs): """ Create a Unicode-converting Text type. Parameters are the same as that of :class:`_expression.TextClause`, with the exception that ``convert_unicode`` defaults to ``True``. """ kwargs.setdefault("_expect_unicode", True) kwargs.setdefault("_warn_on_bytestring", True) super(UnicodeText, self).__init__(length=length, **kwargs) def _warn_deprecated_unicode(self): pass class Integer(_LookupExpressionAdapter, TypeEngine): """A type for ``int`` integers.""" __visit_name__ = "integer" def get_dbapi_type(self, dbapi): return dbapi.NUMBER @property def python_type(self): return int def literal_processor(self, dialect): def process(value): return str(value) return process @util.memoized_property def _expression_adaptations(self): # TODO: need a dictionary object that will # handle operators generically here, this is incomplete return { operators.add: { Date: Date, Integer: self.__class__, Numeric: Numeric, }, operators.mul: { Interval: Interval, Integer: self.__class__, Numeric: Numeric, }, operators.div: {Integer: self.__class__, Numeric: Numeric}, operators.truediv: {Integer: self.__class__, Numeric: Numeric}, operators.sub: {Integer: self.__class__, Numeric: Numeric}, } class SmallInteger(Integer): """A type for smaller ``int`` integers. Typically generates a ``SMALLINT`` in DDL, and otherwise acts like a normal :class:`.Integer` on the Python side. """ __visit_name__ = "small_integer" class BigInteger(Integer): """A type for bigger ``int`` integers. Typically generates a ``BIGINT`` in DDL, and otherwise acts like a normal :class:`.Integer` on the Python side. """ __visit_name__ = "big_integer" class Numeric(_LookupExpressionAdapter, TypeEngine): """A type for fixed precision numbers, such as ``NUMERIC`` or ``DECIMAL``. This type returns Python ``decimal.Decimal`` objects by default, unless the :paramref:`.Numeric.asdecimal` flag is set to False, in which case they are coerced to Python ``float`` objects. .. note:: The :class:`.Numeric` type is designed to receive data from a database type that is explicitly known to be a decimal type (e.g. ``DECIMAL``, ``NUMERIC``, others) and not a floating point type (e.g. ``FLOAT``, ``REAL``, others). If the database column on the server is in fact a floating-point type, such as ``FLOAT`` or ``REAL``, use the :class:`.Float` type or a subclass, otherwise numeric coercion between ``float``/``Decimal`` may or may not function as expected. .. note:: The Python ``decimal.Decimal`` class is generally slow performing; cPython 3.3 has now switched to use the `cdecimal `_ library natively. For older Python versions, the ``cdecimal`` library can be patched into any application where it will replace the ``decimal`` library fully, however this needs to be applied globally and before any other modules have been imported, as follows:: import sys import cdecimal sys.modules["decimal"] = cdecimal Note that the ``cdecimal`` and ``decimal`` libraries are **not compatible with each other**, so patching ``cdecimal`` at the global level is the only way it can be used effectively with various DBAPIs that hardcode to import the ``decimal`` library. """ __visit_name__ = "numeric" _default_decimal_return_scale = 10 def __init__( self, precision=None, scale=None, decimal_return_scale=None, asdecimal=True, ): """ Construct a Numeric. :param precision: the numeric precision for use in DDL ``CREATE TABLE``. :param scale: the numeric scale for use in DDL ``CREATE TABLE``. :param asdecimal: default True. Return whether or not values should be sent as Python Decimal objects, or as floats. Different DBAPIs send one or the other based on datatypes - the Numeric type will ensure that return values are one or the other across DBAPIs consistently. :param decimal_return_scale: Default scale to use when converting from floats to Python decimals. Floating point values will typically be much longer due to decimal inaccuracy, and most floating point database types don't have a notion of "scale", so by default the float type looks for the first ten decimal places when converting. Specifying this value will override that length. Types which do include an explicit ".scale" value, such as the base :class:`.Numeric` as well as the MySQL float types, will use the value of ".scale" as the default for decimal_return_scale, if not otherwise specified. .. versionadded:: 0.9.0 When using the ``Numeric`` type, care should be taken to ensure that the asdecimal setting is appropriate for the DBAPI in use - when Numeric applies a conversion from Decimal->float or float-> Decimal, this conversion incurs an additional performance overhead for all result columns received. DBAPIs that return Decimal natively (e.g. psycopg2) will have better accuracy and higher performance with a setting of ``True``, as the native translation to Decimal reduces the amount of floating- point issues at play, and the Numeric type itself doesn't need to apply any further conversions. However, another DBAPI which returns floats natively *will* incur an additional conversion overhead, and is still subject to floating point data loss - in which case ``asdecimal=False`` will at least remove the extra conversion overhead. """ self.precision = precision self.scale = scale self.decimal_return_scale = decimal_return_scale self.asdecimal = asdecimal @property def _effective_decimal_return_scale(self): if self.decimal_return_scale is not None: return self.decimal_return_scale elif getattr(self, "scale", None) is not None: return self.scale else: return self._default_decimal_return_scale def get_dbapi_type(self, dbapi): return dbapi.NUMBER def literal_processor(self, dialect): def process(value): return str(value) return process @property def python_type(self): if self.asdecimal: return decimal.Decimal else: return float def bind_processor(self, dialect): if dialect.supports_native_decimal: return None else: return processors.to_float def result_processor(self, dialect, coltype): if self.asdecimal: if dialect.supports_native_decimal: # we're a "numeric", DBAPI will give us Decimal directly return None else: util.warn( "Dialect %s+%s does *not* support Decimal " "objects natively, and SQLAlchemy must " "convert from floating point - rounding " "errors and other issues may occur. Please " "consider storing Decimal numbers as strings " "or integers on this platform for lossless " "storage." % (dialect.name, dialect.driver) ) # we're a "numeric", DBAPI returns floats, convert. return processors.to_decimal_processor_factory( decimal.Decimal, self.scale if self.scale is not None else self._default_decimal_return_scale, ) else: if dialect.supports_native_decimal: return processors.to_float else: return None @util.memoized_property def _expression_adaptations(self): return { operators.mul: { Interval: Interval, Numeric: self.__class__, Integer: self.__class__, }, operators.div: {Numeric: self.__class__, Integer: self.__class__}, operators.truediv: { Numeric: self.__class__, Integer: self.__class__, }, operators.add: {Numeric: self.__class__, Integer: self.__class__}, operators.sub: {Numeric: self.__class__, Integer: self.__class__}, } class Float(Numeric): """Type representing floating point types, such as ``FLOAT`` or ``REAL``. This type returns Python ``float`` objects by default, unless the :paramref:`.Float.asdecimal` flag is set to True, in which case they are coerced to ``decimal.Decimal`` objects. .. note:: The :class:`.Float` type is designed to receive data from a database type that is explicitly known to be a floating point type (e.g. ``FLOAT``, ``REAL``, others) and not a decimal type (e.g. ``DECIMAL``, ``NUMERIC``, others). If the database column on the server is in fact a Numeric type, such as ``DECIMAL`` or ``NUMERIC``, use the :class:`.Numeric` type or a subclass, otherwise numeric coercion between ``float``/``Decimal`` may or may not function as expected. """ __visit_name__ = "float" scale = None def __init__( self, precision=None, asdecimal=False, decimal_return_scale=None ): r""" Construct a Float. :param precision: the numeric precision for use in DDL ``CREATE TABLE``. :param asdecimal: the same flag as that of :class:`.Numeric`, but defaults to ``False``. Note that setting this flag to ``True`` results in floating point conversion. :param decimal_return_scale: Default scale to use when converting from floats to Python decimals. Floating point values will typically be much longer due to decimal inaccuracy, and most floating point database types don't have a notion of "scale", so by default the float type looks for the first ten decimal places when converting. Specifying this value will override that length. Note that the MySQL float types, which do include "scale", will use "scale" as the default for decimal_return_scale, if not otherwise specified. .. versionadded:: 0.9.0 """ self.precision = precision self.asdecimal = asdecimal self.decimal_return_scale = decimal_return_scale def result_processor(self, dialect, coltype): if self.asdecimal: return processors.to_decimal_processor_factory( decimal.Decimal, self._effective_decimal_return_scale ) elif dialect.supports_native_decimal: return processors.to_float else: return None class DateTime(_LookupExpressionAdapter, TypeEngine): """A type for ``datetime.datetime()`` objects. Date and time types return objects from the Python ``datetime`` module. Most DBAPIs have built in support for the datetime module, with the noted exception of SQLite. In the case of SQLite, date and time types are stored as strings which are then converted back to datetime objects when rows are returned. For the time representation within the datetime type, some backends include additional options, such as timezone support and fractional seconds support. For fractional seconds, use the dialect-specific datatype, such as :class:`.mysql.TIME`. For timezone support, use at least the :class:`_types.TIMESTAMP` datatype, if not the dialect-specific datatype object. """ __visit_name__ = "datetime" def __init__(self, timezone=False): """Construct a new :class:`.DateTime`. :param timezone: boolean. Indicates that the datetime type should enable timezone support, if available on the **base date/time-holding type only**. It is recommended to make use of the :class:`_types.TIMESTAMP` datatype directly when using this flag, as some databases include separate generic date/time-holding types distinct from the timezone-capable TIMESTAMP datatype, such as Oracle. """ self.timezone = timezone def get_dbapi_type(self, dbapi): return dbapi.DATETIME @property def python_type(self): return dt.datetime @util.memoized_property def _expression_adaptations(self): # Based on http://www.postgresql.org/docs/current/\ # static/functions-datetime.html. return { operators.add: {Interval: self.__class__}, operators.sub: {Interval: self.__class__, DateTime: Interval}, } class Date(_LookupExpressionAdapter, TypeEngine): """A type for ``datetime.date()`` objects.""" __visit_name__ = "date" def get_dbapi_type(self, dbapi): return dbapi.DATETIME @property def python_type(self): return dt.date @util.memoized_property def _expression_adaptations(self): # Based on http://www.postgresql.org/docs/current/\ # static/functions-datetime.html. return { operators.add: { Integer: self.__class__, Interval: DateTime, Time: DateTime, }, operators.sub: { # date - integer = date Integer: self.__class__, # date - date = integer. Date: Integer, Interval: DateTime, # date - datetime = interval, # this one is not in the PG docs # but works DateTime: Interval, }, } class Time(_LookupExpressionAdapter, TypeEngine): """A type for ``datetime.time()`` objects.""" __visit_name__ = "time" def __init__(self, timezone=False): self.timezone = timezone def get_dbapi_type(self, dbapi): return dbapi.DATETIME @property def python_type(self): return dt.time @util.memoized_property def _expression_adaptations(self): # Based on http://www.postgresql.org/docs/current/\ # static/functions-datetime.html. return { operators.add: {Date: DateTime, Interval: self.__class__}, operators.sub: {Time: Interval, Interval: self.__class__}, } class _Binary(TypeEngine): """Define base behavior for binary types.""" def __init__(self, length=None): self.length = length def literal_processor(self, dialect): def process(value): value = value.decode(dialect.encoding).replace("'", "''") return "'%s'" % value return process @property def python_type(self): return util.binary_type # Python 3 - sqlite3 doesn't need the `Binary` conversion # here, though pg8000 does to indicate "bytea" def bind_processor(self, dialect): if dialect.dbapi is None: return None DBAPIBinary = dialect.dbapi.Binary def process(value): if value is not None: return DBAPIBinary(value) else: return None return process # Python 3 has native bytes() type # both sqlite3 and pg8000 seem to return it, # psycopg2 as of 2.5 returns 'memoryview' if util.py2k: def result_processor(self, dialect, coltype): if util.jython: def process(value): if value is not None: if isinstance(value, array.array): return value.tostring() return str(value) else: return None else: process = processors.to_str return process else: def result_processor(self, dialect, coltype): def process(value): if value is not None: value = bytes(value) return value return process def coerce_compared_value(self, op, value): """See :meth:`.TypeEngine.coerce_compared_value` for a description.""" if isinstance(value, util.string_types): return self else: return super(_Binary, self).coerce_compared_value(op, value) def get_dbapi_type(self, dbapi): return dbapi.BINARY class LargeBinary(_Binary): """A type for large binary byte data. The :class:`.LargeBinary` type corresponds to a large and/or unlengthed binary type for the target platform, such as BLOB on MySQL and BYTEA for PostgreSQL. It also handles the necessary conversions for the DBAPI. """ __visit_name__ = "large_binary" def __init__(self, length=None): """ Construct a LargeBinary type. :param length: optional, a length for the column for use in DDL statements, for those binary types that accept a length, such as the MySQL BLOB type. """ _Binary.__init__(self, length=length) @util.deprecated_cls( "0.6", "The :class:`.Binary` class is deprecated and will be removed " "in a future relase. Please use :class:`.LargeBinary`.", ) class Binary(LargeBinary): def __init__(self, *arg, **kw): LargeBinary.__init__(self, *arg, **kw) class SchemaType(SchemaEventTarget): """Mark a type as possibly requiring schema-level DDL for usage. Supports types that must be explicitly created/dropped (i.e. PG ENUM type) as well as types that are complimented by table or schema level constraints, triggers, and other rules. :class:`.SchemaType` classes can also be targets for the :meth:`.DDLEvents.before_parent_attach` and :meth:`.DDLEvents.after_parent_attach` events, where the events fire off surrounding the association of the type object with a parent :class:`_schema.Column`. .. seealso:: :class:`.Enum` :class:`.Boolean` """ def __init__( self, name=None, schema=None, metadata=None, inherit_schema=False, quote=None, _create_events=True, ): if name is not None: self.name = quoted_name(name, quote) else: self.name = None self.schema = schema self.metadata = metadata self.inherit_schema = inherit_schema self._create_events = _create_events if _create_events and self.metadata: event.listen( self.metadata, "before_create", util.portable_instancemethod(self._on_metadata_create), ) event.listen( self.metadata, "after_drop", util.portable_instancemethod(self._on_metadata_drop), ) def _translate_schema(self, effective_schema, map_): return map_.get(effective_schema, effective_schema) def _set_parent(self, column, **kw): column._on_table_attach(util.portable_instancemethod(self._set_table)) def _variant_mapping_for_set_table(self, column): if isinstance(column.type, Variant): variant_mapping = column.type.mapping.copy() variant_mapping["_default"] = column.type.impl else: variant_mapping = None return variant_mapping def _set_table(self, column, table): if self.inherit_schema: self.schema = table.schema if not self._create_events: return variant_mapping = self._variant_mapping_for_set_table(column) event.listen( table, "before_create", util.portable_instancemethod( self._on_table_create, {"variant_mapping": variant_mapping} ), ) event.listen( table, "after_drop", util.portable_instancemethod( self._on_table_drop, {"variant_mapping": variant_mapping} ), ) if self.metadata is None: # TODO: what's the difference between self.metadata # and table.metadata here ? event.listen( table.metadata, "before_create", util.portable_instancemethod( self._on_metadata_create, {"variant_mapping": variant_mapping}, ), ) event.listen( table.metadata, "after_drop", util.portable_instancemethod( self._on_metadata_drop, {"variant_mapping": variant_mapping}, ), ) def copy(self, **kw): return self.adapt(self.__class__, _create_events=True) def adapt(self, impltype, **kw): schema = kw.pop("schema", self.schema) metadata = kw.pop("metadata", self.metadata) _create_events = kw.pop("_create_events", False) return impltype( name=self.name, schema=schema, inherit_schema=self.inherit_schema, metadata=metadata, _create_events=_create_events, **kw ) @property def bind(self): return self.metadata and self.metadata.bind or None def create(self, bind=None, checkfirst=False): """Issue CREATE DDL for this type, if applicable.""" if bind is None: bind = _bind_or_error(self) t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t.create(bind=bind, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=False): """Issue DROP DDL for this type, if applicable.""" if bind is None: bind = _bind_or_error(self) t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t.drop(bind=bind, checkfirst=checkfirst) def _on_table_create(self, target, bind, **kw): if not self._is_impl_for_variant(bind.dialect, kw): return t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t._on_table_create(target, bind, **kw) def _on_table_drop(self, target, bind, **kw): if not self._is_impl_for_variant(bind.dialect, kw): return t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t._on_table_drop(target, bind, **kw) def _on_metadata_create(self, target, bind, **kw): if not self._is_impl_for_variant(bind.dialect, kw): return t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t._on_metadata_create(target, bind, **kw) def _on_metadata_drop(self, target, bind, **kw): if not self._is_impl_for_variant(bind.dialect, kw): return t = self.dialect_impl(bind.dialect) if t.__class__ is not self.__class__ and isinstance(t, SchemaType): t._on_metadata_drop(target, bind, **kw) def _is_impl_for_variant(self, dialect, kw): variant_mapping = kw.pop("variant_mapping", None) if variant_mapping is None: return True if ( dialect.name in variant_mapping and variant_mapping[dialect.name] is self ): return True elif dialect.name not in variant_mapping: return variant_mapping["_default"] is self class Enum(Emulated, String, SchemaType): """Generic Enum Type. The :class:`.Enum` type provides a set of possible string values which the column is constrained towards. The :class:`.Enum` type will make use of the backend's native "ENUM" type if one is available; otherwise, it uses a VARCHAR datatype and produces a CHECK constraint. Use of the backend-native enum type can be disabled using the :paramref:`.Enum.native_enum` flag, and the production of the CHECK constraint is configurable using the :paramref:`.Enum.create_constraint` flag. The :class:`.Enum` type also provides in-Python validation of string values during both read and write operations. When reading a value from the database in a result set, the string value is always checked against the list of possible values and a ``LookupError`` is raised if no match is found. When passing a value to the database as a plain string within a SQL statement, if the :paramref:`.Enum.validate_strings` parameter is set to True, a ``LookupError`` is raised for any string value that's not located in the given list of possible values; note that this impacts usage of LIKE expressions with enumerated values (an unusual use case). .. versionchanged:: 1.1 the :class:`.Enum` type now provides in-Python validation of input values as well as on data being returned by the database. The source of enumerated values may be a list of string values, or alternatively a PEP-435-compliant enumerated class. For the purposes of the :class:`.Enum` datatype, this class need only provide a ``__members__`` method. When using an enumerated class, the enumerated objects are used both for input and output, rather than strings as is the case with a plain-string enumerated type:: import enum class MyEnum(enum.Enum): one = 1 two = 2 three = 3 t = Table( 'data', MetaData(), Column('value', Enum(MyEnum)) ) connection.execute(t.insert(), {"value": MyEnum.two}) assert connection.scalar(t.select()) is MyEnum.two Above, the string names of each element, e.g. "one", "two", "three", are persisted to the database; the values of the Python Enum, here indicated as integers, are **not** used; the value of each enum can therefore be any kind of Python object whether or not it is persistable. In order to persist the values and not the names, the :paramref:`.Enum.values_callable` parameter may be used. The value of this parameter is a user-supplied callable, which is intended to be used with a PEP-435-compliant enumerated class and returns a list of string values to be persisted. For a simple enumeration that uses string values, a callable such as ``lambda x: [e.value for e in x]`` is sufficient. .. versionadded:: 1.1 - support for PEP-435-style enumerated classes. .. seealso:: :class:`_postgresql.ENUM` - PostgreSQL-specific type, which has additional functionality. :class:`.mysql.ENUM` - MySQL-specific type """ __visit_name__ = "enum" @util.deprecated_params( convert_unicode=( "1.3", "The :paramref:`.Enum.convert_unicode` parameter is deprecated " "and will be removed in a future release. All modern DBAPIs " "now support Python Unicode directly and this parameter is " "unnecessary.", ) ) def __init__(self, *enums, **kw): r"""Construct an enum. Keyword arguments which don't apply to a specific backend are ignored by that backend. :param \*enums: either exactly one PEP-435 compliant enumerated type or one or more string or unicode enumeration labels. If unicode labels are present, the `convert_unicode` flag is auto-enabled. .. versionadded:: 1.1 a PEP-435 style enumerated class may be passed. :param convert_unicode: Enable unicode-aware bind parameter and result-set processing for this Enum's data. This is set automatically based on the presence of unicode label strings. :param create_constraint: defaults to True. When creating a non-native enumerated type, also build a CHECK constraint on the database against the valid values. .. versionadded:: 1.1 - added :paramref:`.Enum.create_constraint` which provides the option to disable the production of the CHECK constraint for a non-native enumerated type. :param metadata: Associate this type directly with a ``MetaData`` object. For types that exist on the target database as an independent schema construct (PostgreSQL), this type will be created and dropped within ``create_all()`` and ``drop_all()`` operations. If the type is not associated with any ``MetaData`` object, it will associate itself with each ``Table`` in which it is used, and will be created when any of those individual tables are created, after a check is performed for its existence. The type is only dropped when ``drop_all()`` is called for that ``Table`` object's metadata, however. :param name: The name of this type. This is required for PostgreSQL and any future supported database which requires an explicitly named type, or an explicitly named constraint in order to generate the type and/or a table that uses it. If a PEP-435 enumerated class was used, its name (converted to lower case) is used by default. :param native_enum: Use the database's native ENUM type when available. Defaults to True. When False, uses VARCHAR + check constraint for all backends. The VARCHAR length can be controlled with :paramref:`.Enum.length` :param length: Allows specifying a custom length for the VARCHAR when :paramref:`.Enum.native_enum` is False. By default it uses the length of the longest value. .. versionadded:: 1.3.16 :param schema: Schema name of this type. For types that exist on the target database as an independent schema construct (PostgreSQL), this parameter specifies the named schema in which the type is present. .. note:: The ``schema`` of the :class:`.Enum` type does not by default make use of the ``schema`` established on the owning :class:`_schema.Table`. If this behavior is desired, set the ``inherit_schema`` flag to ``True``. :param quote: Set explicit quoting preferences for the type's name. :param inherit_schema: When ``True``, the "schema" from the owning :class:`_schema.Table` will be copied to the "schema" attribute of this :class:`.Enum`, replacing whatever value was passed for the ``schema`` attribute. This also takes effect when using the :meth:`_schema.Table.tometadata` operation. :param validate_strings: when True, string values that are being passed to the database in a SQL statement will be checked for validity against the list of enumerated values. Unrecognized values will result in a ``LookupError`` being raised. .. versionadded:: 1.1.0b2 :param values_callable: A callable which will be passed the PEP-435 compliant enumerated type, which should then return a list of string values to be persisted. This allows for alternate usages such as using the string value of an enum to be persisted to the database instead of its name. .. versionadded:: 1.2.3 :param sort_key_function: a Python callable which may be used as the "key" argument in the Python ``sorted()`` built-in. The SQLAlchemy ORM requires that primary key columns which are mapped must be sortable in some way. When using an unsortable enumeration object such as a Python 3 ``Enum`` object, this parameter may be used to set a default sort key function for the objects. By default, the database value of the enumeration is used as the sorting function. .. versionadded:: 1.3.8 """ self._enum_init(enums, kw) @property def _enums_argument(self): if self.enum_class is not None: return [self.enum_class] else: return self.enums def _enum_init(self, enums, kw): """internal init for :class:`.Enum` and subclasses. friendly init helper used by subclasses to remove all the Enum-specific keyword arguments from kw. Allows all other arguments in kw to pass through. """ self.native_enum = kw.pop("native_enum", True) self.create_constraint = kw.pop("create_constraint", True) self.values_callable = kw.pop("values_callable", None) self._sort_key_function = kw.pop("sort_key_function", NO_ARG) length_arg = kw.pop("length", NO_ARG) values, objects = self._parse_into_values(enums, kw) self._setup_for_values(values, objects, kw) convert_unicode = kw.pop("convert_unicode", None) self.validate_strings = kw.pop("validate_strings", False) if convert_unicode is None: for e in self.enums: # this is all py2k logic that can go away for py3k only, # "expect unicode" will always be implicitly true if isinstance(e, util.text_type): _expect_unicode = True break else: _expect_unicode = False else: _expect_unicode = convert_unicode if self.enums: length = max(len(x) for x in self.enums) else: length = 0 if not self.native_enum and length_arg is not NO_ARG: if length_arg < length: raise ValueError( "When provided, length must be larger or equal" " than the length of the longest enum value. %s < %s" % (length_arg, length) ) length = length_arg self._valid_lookup[None] = self._object_lookup[None] = None super(Enum, self).__init__( length=length, _expect_unicode=_expect_unicode ) if self.enum_class: kw.setdefault("name", self.enum_class.__name__.lower()) SchemaType.__init__( self, name=kw.pop("name", None), schema=kw.pop("schema", None), metadata=kw.pop("metadata", None), inherit_schema=kw.pop("inherit_schema", False), quote=kw.pop("quote", None), _create_events=kw.pop("_create_events", True), ) def _parse_into_values(self, enums, kw): if not enums and "_enums" in kw: enums = kw.pop("_enums") if len(enums) == 1 and hasattr(enums[0], "__members__"): self.enum_class = enums[0] members = self.enum_class.__members__ if self.values_callable: values = self.values_callable(self.enum_class) else: values = list(members) objects = [members[k] for k in members] return values, objects else: self.enum_class = None return enums, enums def _setup_for_values(self, values, objects, kw): self.enums = list(values) self._valid_lookup = dict(zip(reversed(objects), reversed(values))) self._object_lookup = dict(zip(values, objects)) self._valid_lookup.update( [ (value, self._valid_lookup[self._object_lookup[value]]) for value in values ] ) @property def sort_key_function(self): if self._sort_key_function is NO_ARG: return self._db_value_for_elem else: return self._sort_key_function @property def native(self): return self.native_enum def _db_value_for_elem(self, elem): try: return self._valid_lookup[elem] except KeyError as err: # for unknown string values, we return as is. While we can # validate these if we wanted, that does not allow for lesser-used # end-user use cases, such as using a LIKE comparison with an enum, # or for an application that wishes to apply string tests to an # ENUM (see [ticket:3725]). While we can decide to differentiate # here between an INSERT statement and a criteria used in a SELECT, # for now we're staying conservative w/ behavioral changes (perhaps # someone has a trigger that handles strings on INSERT) if not self.validate_strings and isinstance( elem, compat.string_types ): return elem else: util.raise_( LookupError( "'%s' is not among the defined enum values. " "Enum name: %s. Possible values: %s" % ( elem, self.name, langhelpers.repr_tuple_names(self.enums), ) ), replace_context=err, ) class Comparator(String.Comparator): def _adapt_expression(self, op, other_comparator): op, typ = super(Enum.Comparator, self)._adapt_expression( op, other_comparator ) if op is operators.concat_op: typ = String( self.type.length, _expect_unicode=self.type._expect_unicode ) return op, typ comparator_factory = Comparator def _object_value_for_elem(self, elem): try: return self._object_lookup[elem] except KeyError as err: util.raise_( LookupError( "'%s' is not among the defined enum values. " "Enum name: %s. Possible values: %s" % ( elem, self.name, langhelpers.repr_tuple_names(self.enums), ) ), replace_context=err, ) def __repr__(self): return util.generic_repr( self, additional_kw=[("native_enum", True)], to_inspect=[Enum, SchemaType], ) def adapt_to_emulated(self, impltype, **kw): kw.setdefault("_expect_unicode", self._expect_unicode) kw.setdefault("validate_strings", self.validate_strings) kw.setdefault("name", self.name) kw.setdefault("schema", self.schema) kw.setdefault("inherit_schema", self.inherit_schema) kw.setdefault("metadata", self.metadata) kw.setdefault("_create_events", False) kw.setdefault("native_enum", self.native_enum) kw.setdefault("values_callable", self.values_callable) kw.setdefault("create_constraint", self.create_constraint) kw.setdefault("length", self.length) assert "_enums" in kw return impltype(**kw) def adapt(self, impltype, **kw): kw["_enums"] = self._enums_argument return super(Enum, self).adapt(impltype, **kw) def _should_create_constraint(self, compiler, **kw): if not self._is_impl_for_variant(compiler.dialect, kw): return False return ( not self.native_enum or not compiler.dialect.supports_native_enum ) @util.dependencies("sqlalchemy.sql.schema") def _set_table(self, schema, column, table): SchemaType._set_table(self, column, table) if not self.create_constraint: return variant_mapping = self._variant_mapping_for_set_table(column) e = schema.CheckConstraint( type_coerce(column, self).in_(self.enums), name=_NONE_NAME if self.name is None else self.name, _create_rule=util.portable_instancemethod( self._should_create_constraint, {"variant_mapping": variant_mapping}, ), _type_bound=True, ) assert e.table is table def literal_processor(self, dialect): parent_processor = super(Enum, self).literal_processor(dialect) def process(value): value = self._db_value_for_elem(value) if parent_processor: value = parent_processor(value) return value return process def bind_processor(self, dialect): def process(value): value = self._db_value_for_elem(value) if parent_processor: value = parent_processor(value) return value parent_processor = super(Enum, self).bind_processor(dialect) return process def result_processor(self, dialect, coltype): parent_processor = super(Enum, self).result_processor(dialect, coltype) def process(value): if parent_processor: value = parent_processor(value) value = self._object_value_for_elem(value) return value return process def copy(self, **kw): return SchemaType.copy(self, **kw) @property def python_type(self): if self.enum_class: return self.enum_class else: return super(Enum, self).python_type class PickleType(TypeDecorator): """Holds Python objects, which are serialized using pickle. PickleType builds upon the Binary type to apply Python's ``pickle.dumps()`` to incoming objects, and ``pickle.loads()`` on the way out, allowing any pickleable Python object to be stored as a serialized binary field. To allow ORM change events to propagate for elements associated with :class:`.PickleType`, see :ref:`mutable_toplevel`. """ impl = LargeBinary def __init__( self, protocol=pickle.HIGHEST_PROTOCOL, pickler=None, comparator=None ): """ Construct a PickleType. :param protocol: defaults to ``pickle.HIGHEST_PROTOCOL``. :param pickler: defaults to cPickle.pickle or pickle.pickle if cPickle is not available. May be any object with pickle-compatible ``dumps`` and ``loads`` methods. :param comparator: a 2-arg callable predicate used to compare values of this type. If left as ``None``, the Python "equals" operator is used to compare values. """ self.protocol = protocol self.pickler = pickler or pickle self.comparator = comparator super(PickleType, self).__init__() def __reduce__(self): return PickleType, (self.protocol, None, self.comparator) def bind_processor(self, dialect): impl_processor = self.impl.bind_processor(dialect) dumps = self.pickler.dumps protocol = self.protocol if impl_processor: def process(value): if value is not None: value = dumps(value, protocol) return impl_processor(value) else: def process(value): if value is not None: value = dumps(value, protocol) return value return process def result_processor(self, dialect, coltype): impl_processor = self.impl.result_processor(dialect, coltype) loads = self.pickler.loads if impl_processor: def process(value): value = impl_processor(value) if value is None: return None return loads(value) else: def process(value): if value is None: return None return loads(value) return process def compare_values(self, x, y): if self.comparator: return self.comparator(x, y) else: return x == y class Boolean(Emulated, TypeEngine, SchemaType): """A bool datatype. :class:`.Boolean` typically uses BOOLEAN or SMALLINT on the DDL side, and on the Python side deals in ``True`` or ``False``. The :class:`.Boolean` datatype currently has two levels of assertion that the values persisted are simple true/false values. For all backends, only the Python values ``None``, ``True``, ``False``, ``1`` or ``0`` are accepted as parameter values. For those backends that don't support a "native boolean" datatype, a CHECK constraint is also created on the target column. Production of the CHECK constraint can be disabled by passing the :paramref:`.Boolean.create_constraint` flag set to ``False``. .. versionchanged:: 1.2 the :class:`.Boolean` datatype now asserts that incoming Python values are already in pure boolean form. """ __visit_name__ = "boolean" native = True def __init__(self, create_constraint=True, name=None, _create_events=True): """Construct a Boolean. :param create_constraint: defaults to True. If the boolean is generated as an int/smallint, also create a CHECK constraint on the table that ensures 1 or 0 as a value. :param name: if a CHECK constraint is generated, specify the name of the constraint. """ self.create_constraint = create_constraint self.name = name self._create_events = _create_events def _should_create_constraint(self, compiler, **kw): if not self._is_impl_for_variant(compiler.dialect, kw): return False return ( not compiler.dialect.supports_native_boolean and compiler.dialect.non_native_boolean_check_constraint ) @util.dependencies("sqlalchemy.sql.schema") def _set_table(self, schema, column, table): if not self.create_constraint: return variant_mapping = self._variant_mapping_for_set_table(column) e = schema.CheckConstraint( type_coerce(column, self).in_([0, 1]), name=_NONE_NAME if self.name is None else self.name, _create_rule=util.portable_instancemethod( self._should_create_constraint, {"variant_mapping": variant_mapping}, ), _type_bound=True, ) assert e.table is table @property def python_type(self): return bool _strict_bools = frozenset([None, True, False]) def _strict_as_bool(self, value): if value not in self._strict_bools: if not isinstance(value, int): raise TypeError("Not a boolean value: %r" % value) else: raise ValueError( "Value %r is not None, True, or False" % value ) return value def literal_processor(self, dialect): compiler = dialect.statement_compiler(dialect, None) true = compiler.visit_true(None) false = compiler.visit_false(None) def process(value): return true if self._strict_as_bool(value) else false return process def bind_processor(self, dialect): _strict_as_bool = self._strict_as_bool if dialect.supports_native_boolean: _coerce = bool else: _coerce = int def process(value): value = _strict_as_bool(value) if value is not None: value = _coerce(value) return value return process def result_processor(self, dialect, coltype): if dialect.supports_native_boolean: return None else: return processors.int_to_boolean class _AbstractInterval(_LookupExpressionAdapter, TypeEngine): @util.memoized_property def _expression_adaptations(self): # Based on http://www.postgresql.org/docs/current/\ # static/functions-datetime.html. return { operators.add: { Date: DateTime, Interval: self.__class__, DateTime: DateTime, Time: Time, }, operators.sub: {Interval: self.__class__}, operators.mul: {Numeric: self.__class__}, operators.truediv: {Numeric: self.__class__}, operators.div: {Numeric: self.__class__}, } @property def _type_affinity(self): return Interval def coerce_compared_value(self, op, value): """See :meth:`.TypeEngine.coerce_compared_value` for a description.""" return self.impl.coerce_compared_value(op, value) class Interval(Emulated, _AbstractInterval, TypeDecorator): """A type for ``datetime.timedelta()`` objects. The Interval type deals with ``datetime.timedelta`` objects. In PostgreSQL, the native ``INTERVAL`` type is used; for others, the value is stored as a date which is relative to the "epoch" (Jan. 1, 1970). Note that the ``Interval`` type does not currently provide date arithmetic operations on platforms which do not support interval types natively. Such operations usually require transformation of both sides of the expression (such as, conversion of both sides into integer epoch values first) which currently is a manual procedure (such as via :attr:`~sqlalchemy.sql.expression.func`). """ impl = DateTime epoch = dt.datetime.utcfromtimestamp(0) def __init__(self, native=True, second_precision=None, day_precision=None): """Construct an Interval object. :param native: when True, use the actual INTERVAL type provided by the database, if supported (currently PostgreSQL, Oracle). Otherwise, represent the interval data as an epoch value regardless. :param second_precision: For native interval types which support a "fractional seconds precision" parameter, i.e. Oracle and PostgreSQL :param day_precision: for native interval types which support a "day precision" parameter, i.e. Oracle. """ super(Interval, self).__init__() self.native = native self.second_precision = second_precision self.day_precision = day_precision @property def python_type(self): return dt.timedelta def adapt_to_emulated(self, impltype, **kw): return _AbstractInterval.adapt(self, impltype, **kw) def bind_processor(self, dialect): impl_processor = self.impl.bind_processor(dialect) epoch = self.epoch if impl_processor: def process(value): if value is not None: value = epoch + value return impl_processor(value) else: def process(value): if value is not None: value = epoch + value return value return process def result_processor(self, dialect, coltype): impl_processor = self.impl.result_processor(dialect, coltype) epoch = self.epoch if impl_processor: def process(value): value = impl_processor(value) if value is None: return None return value - epoch else: def process(value): if value is None: return None return value - epoch return process class JSON(Indexable, TypeEngine): """Represent a SQL JSON type. .. note:: :class:`_types.JSON` is provided as a facade for vendor-specific JSON types. Since it supports JSON SQL operations, it only works on backends that have an actual JSON type, currently: * PostgreSQL * MySQL as of version 5.7 (MariaDB as of the 10.2 series does not) * SQLite as of version 3.9 :class:`_types.JSON` is part of the Core in support of the growing popularity of native JSON datatypes. The :class:`_types.JSON` type stores arbitrary JSON format data, e.g.:: data_table = Table('data_table', metadata, Column('id', Integer, primary_key=True), Column('data', JSON) ) with engine.connect() as conn: conn.execute( data_table.insert(), data = {"key1": "value1", "key2": "value2"} ) **JSON-Specific Expression Operators** The :class:`_types.JSON` datatype provides these additional SQL operations: * Keyed index operations:: data_table.c.data['some key'] * Integer index operations:: data_table.c.data[3] * Path index operations:: data_table.c.data[('key_1', 'key_2', 5, ..., 'key_n')] * Data casters for specific JSON element types, subsequent to an index or path operation being invoked:: data_table.c.data["some key"].as_integer() .. versionadded:: 1.3.11 Additional operations may be available from the dialect-specific versions of :class:`_types.JSON`, such as :class:`_postgresql.JSON` and :class:`_postgresql.JSONB` which both offer additional PostgreSQL-specific operations. **Casting JSON Elements to Other Types** Index operations, i.e. those invoked by calling upon the expression using the Python bracket operator as in ``some_column['some key']``, return an expression object whose type defaults to :class:`_types.JSON` by default, so that further JSON-oriented instructions may be called upon the result type. However, it is likely more common that an index operation is expected to return a specific scalar element, such as a string or integer. In order to provide access to these elements in a backend-agnostic way, a series of data casters are provided: * :meth:`.JSON.Comparator.as_string` - return the element as a string * :meth:`.JSON.Comparator.as_boolean` - return the element as a boolean * :meth:`.JSON.Comparator.as_float` - return the element as a float * :meth:`.JSON.Comparator.as_integer` - return the element as an integer These data casters are implemented by supporting dialects in order to assure that comparisons to the above types will work as expected, such as:: # integer comparison data_table.c.data["some_integer_key"].as_integer() == 5 # boolean comparison data_table.c.data["some_boolean"].as_boolean() == True .. versionadded:: 1.3.11 Added type-specific casters for the basic JSON data element types. .. note:: The data caster functions are new in version 1.3.11, and supersede the previous documented approaches of using CAST; for reference, this looked like:: from sqlalchemy import cast, type_coerce from sqlalchemy import String, JSON cast( data_table.c.data['some_key'], String ) == type_coerce(55, JSON) The above case now works directly as:: data_table.c.data['some_key'].as_integer() == 5 For details on the previous comparison approach within the 1.3.x series, see the documentation for SQLAlchemy 1.2 or the included HTML files in the doc/ directory of the version's distribution. **Detecting Changes in JSON columns when using the ORM** The :class:`_types.JSON` type, when used with the SQLAlchemy ORM, does not detect in-place mutations to the structure. In order to detect these, the :mod:`sqlalchemy.ext.mutable` extension must be used. This extension will allow "in-place" changes to the datastructure to produce events which will be detected by the unit of work. See the example at :class:`.HSTORE` for a simple example involving a dictionary. **Support for JSON null vs. SQL NULL** When working with NULL values, the :class:`_types.JSON` type recommends the use of two specific constants in order to differentiate between a column that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string of ``"null"``. To insert or select against a value that is SQL NULL, use the constant :func:`.null`:: from sqlalchemy import null conn.execute(table.insert(), json_value=null()) To insert or select against a value that is JSON ``"null"``, use the constant :attr:`_types.JSON.NULL`:: conn.execute(table.insert(), json_value=JSON.NULL) The :class:`_types.JSON` type supports a flag :paramref:`_types.JSON.none_as_null` which when set to True will result in the Python constant ``None`` evaluating to the value of SQL NULL, and when set to False results in the Python constant ``None`` evaluating to the value of JSON ``"null"``. The Python value ``None`` may be used in conjunction with either :attr:`_types.JSON.NULL` and :func:`.null` in order to indicate NULL values, but care must be taken as to the value of the :paramref:`_types.JSON.none_as_null` in these cases. **Customizing the JSON Serializer** The JSON serializer and deserializer used by :class:`_types.JSON` defaults to Python's ``json.dumps`` and ``json.loads`` functions; in the case of the psycopg2 dialect, psycopg2 may be using its own custom loader function. In order to affect the serializer / deserializer, they are currently configurable at the :func:`_sa.create_engine` level via the :paramref:`_sa.create_engine.json_serializer` and :paramref:`_sa.create_engine.json_deserializer` parameters. For example, to turn off ``ensure_ascii``:: engine = create_engine( "sqlite://", json_serializer=lambda obj: json.dumps(obj, ensure_ascii=False)) .. versionchanged:: 1.3.7 SQLite dialect's ``json_serializer`` and ``json_deserializer`` parameters renamed from ``_json_serializer`` and ``_json_deserializer``. .. seealso:: :class:`_postgresql.JSON` :class:`_postgresql.JSONB` :class:`.mysql.JSON` :class:`_sqlite.JSON` .. versionadded:: 1.1 """ __visit_name__ = "JSON" hashable = False NULL = util.symbol("JSON_NULL") """Describe the json value of NULL. This value is used to force the JSON value of ``"null"`` to be used as the value. A value of Python ``None`` will be recognized either as SQL NULL or JSON ``"null"``, based on the setting of the :paramref:`_types.JSON.none_as_null` flag; the :attr:`_types.JSON.NULL` constant can be used to always resolve to JSON ``"null"`` regardless of this setting. This is in contrast to the :func:`_expression.null` construct, which always resolves to SQL NULL. E.g.:: from sqlalchemy import null from sqlalchemy.dialects.postgresql import JSON # will *always* insert SQL NULL obj1 = MyObject(json_value=null()) # will *always* insert JSON string "null" obj2 = MyObject(json_value=JSON.NULL) session.add_all([obj1, obj2]) session.commit() In order to set JSON NULL as a default value for a column, the most transparent method is to use :func:`_expression.text`:: Table( 'my_table', metadata, Column('json_data', JSON, default=text("'null'")) ) While it is possible to use :attr:`_types.JSON.NULL` in this context, the :attr:`_types.JSON.NULL` value will be returned as the value of the column, which in the context of the ORM or other repurposing of the default value, may not be desirable. Using a SQL expression means the value will be re-fetched from the database within the context of retrieving generated defaults. """ def __init__(self, none_as_null=False): """Construct a :class:`_types.JSON` type. :param none_as_null=False: if True, persist the value ``None`` as a SQL NULL value, not the JSON encoding of ``null``. Note that when this flag is False, the :func:`.null` construct can still be used to persist a NULL value:: from sqlalchemy import null conn.execute(table.insert(), data=null()) .. note:: :paramref:`_types.JSON.none_as_null` does **not** apply to the values passed to :paramref:`_schema.Column.default` and :paramref:`_schema.Column.server_default`; a value of ``None`` passed for these parameters means "no default present". .. seealso:: :attr:`.types.JSON.NULL` """ self.none_as_null = none_as_null class JSONElementType(TypeEngine): """Common function for index / path elements in a JSON expression.""" _integer = Integer() _string = String() def string_bind_processor(self, dialect): return self._string._cached_bind_processor(dialect) def string_literal_processor(self, dialect): return self._string._cached_literal_processor(dialect) def bind_processor(self, dialect): int_processor = self._integer._cached_bind_processor(dialect) string_processor = self.string_bind_processor(dialect) def process(value): if int_processor and isinstance(value, int): value = int_processor(value) elif string_processor and isinstance(value, util.string_types): value = string_processor(value) return value return process def literal_processor(self, dialect): int_processor = self._integer._cached_literal_processor(dialect) string_processor = self.string_literal_processor(dialect) def process(value): if int_processor and isinstance(value, int): value = int_processor(value) elif string_processor and isinstance(value, util.string_types): value = string_processor(value) return value return process class JSONIndexType(JSONElementType): """Placeholder for the datatype of a JSON index value. This allows execution-time processing of JSON index values for special syntaxes. """ class JSONPathType(JSONElementType): """Placeholder type for JSON path operations. This allows execution-time processing of a path-based index value into a specific SQL syntax. """ class Comparator(Indexable.Comparator, Concatenable.Comparator): """Define comparison operations for :class:`_types.JSON`.""" @util.dependencies("sqlalchemy.sql.default_comparator") def _setup_getitem(self, default_comparator, index): if not isinstance(index, util.string_types) and isinstance( index, compat.collections_abc.Sequence ): index = default_comparator._check_literal( self.expr, operators.json_path_getitem_op, index, bindparam_type=JSON.JSONPathType, ) operator = operators.json_path_getitem_op else: index = default_comparator._check_literal( self.expr, operators.json_getitem_op, index, bindparam_type=JSON.JSONIndexType, ) operator = operators.json_getitem_op return operator, index, self.type def as_boolean(self): """Cast an indexed value as boolean. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_boolean() ]).where( mytable.c.json_column['some_data'].as_boolean() == True ) .. versionadded:: 1.3.11 """ return self._binary_w_type(Boolean(), "as_boolean") def as_string(self): """Cast an indexed value as string. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_string() ]).where( mytable.c.json_column['some_data'].as_string() == 'some string' ) .. versionadded:: 1.3.11 """ return self._binary_w_type(String(), "as_string") def as_integer(self): """Cast an indexed value as integer. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_integer() ]).where( mytable.c.json_column['some_data'].as_integer() == 5 ) .. versionadded:: 1.3.11 """ return self._binary_w_type(Integer(), "as_integer") def as_float(self): """Cast an indexed value as float. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_float() ]).where( mytable.c.json_column['some_data'].as_float() == 29.75 ) .. versionadded:: 1.3.11 """ # note there's no Numeric or Decimal support here yet return self._binary_w_type(Float(), "as_float") def as_json(self): """Cast an indexed value as JSON. This is the default behavior of indexed elements in any case. Note that comparison of full JSON structures may not be supported by all backends. .. versionadded:: 1.3.11 """ return self.expr def _binary_w_type(self, typ, method_name): if not isinstance( self.expr, elements.BinaryExpression ) or self.expr.operator not in ( operators.json_getitem_op, operators.json_path_getitem_op, ): raise exc.InvalidRequestError( "The JSON cast operator JSON.%s() only works with a JSON " "index expression e.g. col['q'].%s()" % (method_name, method_name) ) expr = self.expr._clone() expr.type = typ return expr comparator_factory = Comparator @property def python_type(self): return dict @property def should_evaluate_none(self): """Alias of :attr:`_types.JSON.none_as_null`""" return not self.none_as_null @should_evaluate_none.setter def should_evaluate_none(self, value): self.none_as_null = not value @util.memoized_property def _str_impl(self): return String(_expect_unicode=True) def bind_processor(self, dialect): string_process = self._str_impl.bind_processor(dialect) json_serializer = dialect._json_serializer or json.dumps def process(value): if value is self.NULL: value = None elif isinstance(value, elements.Null) or ( value is None and self.none_as_null ): return None serialized = json_serializer(value) if string_process: serialized = string_process(serialized) return serialized return process def result_processor(self, dialect, coltype): string_process = self._str_impl.result_processor(dialect, coltype) json_deserializer = dialect._json_deserializer or json.loads def process(value): if value is None: return None if string_process: value = string_process(value) return json_deserializer(value) return process class ARRAY(SchemaEventTarget, Indexable, Concatenable, TypeEngine): """Represent a SQL Array type. .. note:: This type serves as the basis for all ARRAY operations. However, currently **only the PostgreSQL backend has support for SQL arrays in SQLAlchemy**. It is recommended to use the :class:`_postgresql.ARRAY` type directly when using ARRAY types with PostgreSQL, as it provides additional operators specific to that backend. :class:`_types.ARRAY` is part of the Core in support of various SQL standard functions such as :class:`_functions.array_agg` which explicitly involve arrays; however, with the exception of the PostgreSQL backend and possibly some third-party dialects, no other SQLAlchemy built-in dialect has support for this type. An :class:`_types.ARRAY` type is constructed given the "type" of element:: mytable = Table("mytable", metadata, Column("data", ARRAY(Integer)) ) The above type represents an N-dimensional array, meaning a supporting backend such as PostgreSQL will interpret values with any number of dimensions automatically. To produce an INSERT construct that passes in a 1-dimensional array of integers:: connection.execute( mytable.insert(), data=[1,2,3] ) The :class:`_types.ARRAY` type can be constructed given a fixed number of dimensions:: mytable = Table("mytable", metadata, Column("data", ARRAY(Integer, dimensions=2)) ) Sending a number of dimensions is optional, but recommended if the datatype is to represent arrays of more than one dimension. This number is used: * When emitting the type declaration itself to the database, e.g. ``INTEGER[][]`` * When translating Python values to database values, and vice versa, e.g. an ARRAY of :class:`.Unicode` objects uses this number to efficiently access the string values inside of array structures without resorting to per-row type inspection * When used with the Python ``getitem`` accessor, the number of dimensions serves to define the kind of type that the ``[]`` operator should return, e.g. for an ARRAY of INTEGER with two dimensions:: >>> expr = table.c.column[5] # returns ARRAY(Integer, dimensions=1) >>> expr = expr[6] # returns Integer For 1-dimensional arrays, an :class:`_types.ARRAY` instance with no dimension parameter will generally assume single-dimensional behaviors. SQL expressions of type :class:`_types.ARRAY` have support for "index" and "slice" behavior. The Python ``[]`` operator works normally here, given integer indexes or slices. Arrays default to 1-based indexing. The operator produces binary expression constructs which will produce the appropriate SQL, both for SELECT statements:: select([mytable.c.data[5], mytable.c.data[2:7]]) as well as UPDATE statements when the :meth:`_expression.Update.values` method is used:: mytable.update().values({ mytable.c.data[5]: 7, mytable.c.data[2:7]: [1, 2, 3] }) The :class:`_types.ARRAY` type also provides for the operators :meth:`.types.ARRAY.Comparator.any` and :meth:`.types.ARRAY.Comparator.all`. The PostgreSQL-specific version of :class:`_types.ARRAY` also provides additional operators. .. versionadded:: 1.1.0 .. seealso:: :class:`_postgresql.ARRAY` """ __visit_name__ = "ARRAY" _is_array = True zero_indexes = False """If True, Python zero-based indexes should be interpreted as one-based on the SQL expression side.""" class Comparator(Indexable.Comparator, Concatenable.Comparator): """Define comparison operations for :class:`_types.ARRAY`. More operators are available on the dialect-specific form of this type. See :class:`.postgresql.ARRAY.Comparator`. """ def _setup_getitem(self, index): if isinstance(index, slice): return_type = self.type if self.type.zero_indexes: index = slice(index.start + 1, index.stop + 1, index.step) index = Slice( _literal_as_binds( index.start, name=self.expr.key, type_=type_api.INTEGERTYPE, ), _literal_as_binds( index.stop, name=self.expr.key, type_=type_api.INTEGERTYPE, ), _literal_as_binds( index.step, name=self.expr.key, type_=type_api.INTEGERTYPE, ), ) else: if self.type.zero_indexes: index += 1 if self.type.dimensions is None or self.type.dimensions == 1: return_type = self.type.item_type else: adapt_kw = {"dimensions": self.type.dimensions - 1} return_type = self.type.adapt( self.type.__class__, **adapt_kw ) return operators.getitem, index, return_type def contains(self, *arg, **kw): raise NotImplementedError( "ARRAY.contains() not implemented for the base " "ARRAY type; please use the dialect-specific ARRAY type" ) @util.dependencies("sqlalchemy.sql.elements") def any(self, elements, other, operator=None): """Return ``other operator ANY (array)`` clause. Argument places are switched, because ANY requires array expression to be on the right hand-side. E.g.:: from sqlalchemy.sql import operators conn.execute( select([table.c.data]).where( table.c.data.any(7, operator=operators.lt) ) ) :param other: expression to be compared :param operator: an operator object from the :mod:`sqlalchemy.sql.operators` package, defaults to :func:`.operators.eq`. .. seealso:: :func:`_expression.any_` :meth:`.types.ARRAY.Comparator.all` """ operator = operator if operator else operators.eq # send plain BinaryExpression so that negate remains at None, # leading to NOT expr for negation. return elements.BinaryExpression( elements._literal_as_binds(other), elements.CollectionAggregate._create_any(self.expr), operator, ) @util.dependencies("sqlalchemy.sql.elements") def all(self, elements, other, operator=None): """Return ``other operator ALL (array)`` clause. Argument places are switched, because ALL requires array expression to be on the right hand-side. E.g.:: from sqlalchemy.sql import operators conn.execute( select([table.c.data]).where( table.c.data.all(7, operator=operators.lt) ) ) :param other: expression to be compared :param operator: an operator object from the :mod:`sqlalchemy.sql.operators` package, defaults to :func:`.operators.eq`. .. seealso:: :func:`_expression.all_` :meth:`.types.ARRAY.Comparator.any` """ operator = operator if operator else operators.eq # send plain BinaryExpression so that negate remains at None, # leading to NOT expr for negation. return elements.BinaryExpression( elements._literal_as_binds(other), elements.CollectionAggregate._create_all(self.expr), operator, ) comparator_factory = Comparator def __init__( self, item_type, as_tuple=False, dimensions=None, zero_indexes=False ): """Construct an :class:`_types.ARRAY`. E.g.:: Column('myarray', ARRAY(Integer)) Arguments are: :param item_type: The data type of items of this array. Note that dimensionality is irrelevant here, so multi-dimensional arrays like ``INTEGER[][]``, are constructed as ``ARRAY(Integer)``, not as ``ARRAY(ARRAY(Integer))`` or such. :param as_tuple=False: Specify whether return results should be converted to tuples from lists. This parameter is not generally needed as a Python list corresponds well to a SQL array. :param dimensions: if non-None, the ARRAY will assume a fixed number of dimensions. This impacts how the array is declared on the database, how it goes about interpreting Python and result values, as well as how expression behavior in conjunction with the "getitem" operator works. See the description at :class:`_types.ARRAY` for additional detail. :param zero_indexes=False: when True, index values will be converted between Python zero-based and SQL one-based indexes, e.g. a value of one will be added to all index values before passing to the database. """ if isinstance(item_type, ARRAY): raise ValueError( "Do not nest ARRAY types; ARRAY(basetype) " "handles multi-dimensional arrays of basetype" ) if isinstance(item_type, type): item_type = item_type() self.item_type = item_type self.as_tuple = as_tuple self.dimensions = dimensions self.zero_indexes = zero_indexes @property def hashable(self): return self.as_tuple @property def python_type(self): return list def compare_values(self, x, y): return x == y def _set_parent(self, column, **kw): """Support SchemaEventTarget""" if isinstance(self.item_type, SchemaEventTarget): self.item_type._set_parent(column, **kw) def _set_parent_with_dispatch(self, parent, **kw): """Support SchemaEventTarget""" super(ARRAY, self)._set_parent_with_dispatch(parent) if isinstance(self.item_type, SchemaEventTarget): self.item_type._set_parent_with_dispatch(parent) class REAL(Float): """The SQL REAL type.""" __visit_name__ = "REAL" class FLOAT(Float): """The SQL FLOAT type.""" __visit_name__ = "FLOAT" class NUMERIC(Numeric): """The SQL NUMERIC type.""" __visit_name__ = "NUMERIC" class DECIMAL(Numeric): """The SQL DECIMAL type.""" __visit_name__ = "DECIMAL" class INTEGER(Integer): """The SQL INT or INTEGER type.""" __visit_name__ = "INTEGER" INT = INTEGER class SMALLINT(SmallInteger): """The SQL SMALLINT type.""" __visit_name__ = "SMALLINT" class BIGINT(BigInteger): """The SQL BIGINT type.""" __visit_name__ = "BIGINT" class TIMESTAMP(DateTime): """The SQL TIMESTAMP type. :class:`_types.TIMESTAMP` datatypes have support for timezone storage on some backends, such as PostgreSQL and Oracle. Use the :paramref:`~types.TIMESTAMP.timezone` argument in order to enable "TIMESTAMP WITH TIMEZONE" for these backends. """ __visit_name__ = "TIMESTAMP" def __init__(self, timezone=False): """Construct a new :class:`_types.TIMESTAMP`. :param timezone: boolean. Indicates that the TIMESTAMP type should enable timezone support, if available on the target database. On a per-dialect basis is similar to "TIMESTAMP WITH TIMEZONE". If the target database does not support timezones, this flag is ignored. """ super(TIMESTAMP, self).__init__(timezone=timezone) def get_dbapi_type(self, dbapi): return dbapi.TIMESTAMP class DATETIME(DateTime): """The SQL DATETIME type.""" __visit_name__ = "DATETIME" class DATE(Date): """The SQL DATE type.""" __visit_name__ = "DATE" class TIME(Time): """The SQL TIME type.""" __visit_name__ = "TIME" class TEXT(Text): """The SQL TEXT type.""" __visit_name__ = "TEXT" class CLOB(Text): """The CLOB type. This type is found in Oracle and Informix. """ __visit_name__ = "CLOB" class VARCHAR(String): """The SQL VARCHAR type.""" __visit_name__ = "VARCHAR" class NVARCHAR(Unicode): """The SQL NVARCHAR type.""" __visit_name__ = "NVARCHAR" class CHAR(String): """The SQL CHAR type.""" __visit_name__ = "CHAR" class NCHAR(Unicode): """The SQL NCHAR type.""" __visit_name__ = "NCHAR" class BLOB(LargeBinary): """The SQL BLOB type.""" __visit_name__ = "BLOB" class BINARY(_Binary): """The SQL BINARY type.""" __visit_name__ = "BINARY" class VARBINARY(_Binary): """The SQL VARBINARY type.""" __visit_name__ = "VARBINARY" class BOOLEAN(Boolean): """The SQL BOOLEAN type.""" __visit_name__ = "BOOLEAN" class NullType(TypeEngine): """An unknown type. :class:`.NullType` is used as a default type for those cases where a type cannot be determined, including: * During table reflection, when the type of a column is not recognized by the :class:`.Dialect` * When constructing SQL expressions using plain Python objects of unknown types (e.g. ``somecolumn == my_special_object``) * When a new :class:`_schema.Column` is created, and the given type is passed as ``None`` or is not passed at all. The :class:`.NullType` can be used within SQL expression invocation without issue, it just has no behavior either at the expression construction level or at the bind-parameter/result processing level. :class:`.NullType` will result in a :exc:`.CompileError` if the compiler is asked to render the type itself, such as if it is used in a :func:`.cast` operation or within a schema creation operation such as that invoked by :meth:`_schema.MetaData.create_all` or the :class:`.CreateTable` construct. """ __visit_name__ = "null" _isnull = True hashable = False def literal_processor(self, dialect): def process(value): return "NULL" return process class Comparator(TypeEngine.Comparator): def _adapt_expression(self, op, other_comparator): if isinstance( other_comparator, NullType.Comparator ) or not operators.is_commutative(op): return op, self.expr.type else: return other_comparator._adapt_expression(op, self) comparator_factory = Comparator class MatchType(Boolean): """Refers to the return type of the MATCH operator. As the :meth:`.ColumnOperators.match` is probably the most open-ended operator in generic SQLAlchemy Core, we can't assume the return type at SQL evaluation time, as MySQL returns a floating point, not a boolean, and other backends might do something different. So this type acts as a placeholder, currently subclassing :class:`.Boolean`. The type allows dialects to inject result-processing functionality if needed, and on MySQL will return floating-point values. .. versionadded:: 1.0.0 """ NULLTYPE = NullType() BOOLEANTYPE = Boolean() STRINGTYPE = String() INTEGERTYPE = Integer() MATCHTYPE = MatchType() _type_map = { int: Integer(), float: Float(), bool: BOOLEANTYPE, decimal.Decimal: Numeric(), dt.date: Date(), dt.datetime: DateTime(), dt.time: Time(), dt.timedelta: Interval(), util.NoneType: NULLTYPE, } if util.py3k: _type_map[bytes] = LargeBinary() # noqa _type_map[str] = Unicode() else: _type_map[unicode] = Unicode() # noqa _type_map[str] = String() _type_map_get = _type_map.get def _resolve_value_to_type(value): _result_type = _type_map_get(type(value), False) if _result_type is False: # use inspect() to detect SQLAlchemy built-in # objects. insp = inspection.inspect(value, False) if ( insp is not None and # foil mock.Mock() and other impostors by ensuring # the inspection target itself self-inspects insp.__class__ in inspection._registrars ): raise exc.ArgumentError( "Object %r is not legal as a SQL literal value" % value ) return NULLTYPE else: return _result_type # back-assign to type_api type_api.BOOLEANTYPE = BOOLEANTYPE type_api.STRINGTYPE = STRINGTYPE type_api.INTEGERTYPE = INTEGERTYPE type_api.NULLTYPE = NULLTYPE type_api.MATCHTYPE = MATCHTYPE type_api.INDEXABLE = Indexable type_api._resolve_value_to_type = _resolve_value_to_type TypeEngine.Comparator.BOOLEANTYPE = BOOLEANTYPE PK!4gEE annotation.pynu[# sql/annotation.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """The :class:`.Annotated` class and related routines; creates hash-equivalent copies of SQL constructs which contain context-specific markers and associations. """ from . import operators from .. import util class Annotated(object): """clones a ClauseElement and applies an 'annotations' dictionary. Unlike regular clones, this clone also mimics __hash__() and __cmp__() of the original element so that it takes its place in hashed collections. A reference to the original element is maintained, for the important reason of keeping its hash value current. When GC'ed, the hash value may be reused, causing conflicts. .. note:: The rationale for Annotated producing a brand new class, rather than placing the functionality directly within ClauseElement, is **performance**. The __hash__() method is absent on plain ClauseElement which leads to significantly reduced function call overhead, as the use of sets and dictionaries against ClauseElement objects is prevalent, but most are not "annotated". """ def __new__(cls, *args): if not args: # clone constructor return object.__new__(cls) else: element, values = args # pull appropriate subclass from registry of annotated # classes try: cls = annotated_classes[element.__class__] except KeyError: cls = _new_annotation_type(element.__class__, cls) return object.__new__(cls) def __init__(self, element, values): self.__dict__ = element.__dict__.copy() self.__element = element self._annotations = values self._hash = hash(element) def _annotate(self, values): _values = self._annotations.copy() _values.update(values) return self._with_annotations(_values) def _with_annotations(self, values): clone = self.__class__.__new__(self.__class__) clone.__dict__ = self.__dict__.copy() clone._annotations = values return clone def _deannotate(self, values=None, clone=True): if values is None: return self.__element else: _values = self._annotations.copy() for v in values: _values.pop(v, None) return self._with_annotations(_values) def _compiler_dispatch(self, visitor, **kw): return self.__element.__class__._compiler_dispatch(self, visitor, **kw) @property def _constructor(self): return self.__element._constructor def _clone(self): clone = self.__element._clone() if clone is self.__element: # detect immutable, don't change anything return self else: # update the clone with any changes that have occurred # to this object's __dict__. clone.__dict__.update(self.__dict__) return self.__class__(clone, self._annotations) def __reduce__(self): return self.__class__, (self.__element, self._annotations) def __hash__(self): return self._hash def __eq__(self, other): if isinstance(self.__element, operators.ColumnOperators): return self.__element.__class__.__eq__(self, other) else: return hash(other) == hash(self) # hard-generate Annotated subclasses. this technique # is used instead of on-the-fly types (i.e. type.__new__()) # so that the resulting objects are pickleable. annotated_classes = {} def _deep_annotate(element, annotations, exclude=None): """Deep copy the given ClauseElement, annotating each element with the given annotations dictionary. Elements within the exclude collection will be cloned but not annotated. """ def clone(elem): if ( exclude and hasattr(elem, "proxy_set") and elem.proxy_set.intersection(exclude) ): newelem = elem._clone() elif annotations != elem._annotations: newelem = elem._annotate(annotations) else: newelem = elem newelem._copy_internals(clone=clone) return newelem if element is not None: element = clone(element) clone = None # remove gc cycles return element def _deep_deannotate(element, values=None): """Deep copy the given element, removing annotations.""" cloned = util.column_dict() def clone(elem): # if a values dict is given, # the elem must be cloned each time it appears, # as there may be different annotations in source # elements that are remaining. if totally # removing all annotations, can assume the same # slate... if values or elem not in cloned: newelem = elem._deannotate(values=values, clone=True) newelem._copy_internals(clone=clone) if not values: cloned[elem] = newelem return newelem else: return cloned[elem] if element is not None: element = clone(element) clone = None # remove gc cycles return element def _shallow_annotate(element, annotations): """Annotate the given ClauseElement and copy its internals so that internal objects refer to the new annotated object. Basically used to apply a "dont traverse" annotation to a selectable, without digging throughout the whole structure wasting time. """ element = element._annotate(annotations) element._copy_internals() return element def _new_annotation_type(cls, base_cls): if issubclass(cls, Annotated): return cls elif cls in annotated_classes: return annotated_classes[cls] for super_ in cls.__mro__: # check if an Annotated subclass more specific than # the given base_cls is already registered, such # as AnnotatedColumnElement. if super_ in annotated_classes: base_cls = annotated_classes[super_] break annotated_classes[cls] = anno_cls = type( "Annotated%s" % cls.__name__, (base_cls, cls), {} ) globals()["Annotated%s" % cls.__name__] = anno_cls return anno_cls def _prepare_annotations(target_hierarchy, base_cls): stack = [target_hierarchy] while stack: cls = stack.pop() stack.extend(cls.__subclasses__()) _new_annotation_type(cls, base_cls) PK!t22&__pycache__/selectable.cpython-311.pycnu[ |oi!ldZddlZddlZddlZddlmZddlmZddlmZddlm Z ddl m Z dd l m Z dd l mZdd l mZdd l mZdd l mZddl mZddl mZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$dd lm%Z%dd!lm&Z&dd"lm'Z'dd#lm(Z(dd$lm)Z)d%d&lm*Z*d%d'lm+Z+d%d(lm,Z,d)Z-d*Z.Gd+d,e#Z/dZd-Z0d.Z1d/Z2Gd0d1e$Z3Gd2d3e4Z5Gd4d5e4Z6Gd6d7e3Z7Gd8d9e7Z8Gd:d;e7Z9Gd<d=e9Z:Gd>d?e9Z;Gd@dAee5e6e9Z<GdBdCe4Z=GdDdEe7Z>GdFdGee7Z?GdHdIe$Z@GdJdKe=ee7ZAGdLdMeAZBGdNdOeBZCGdPdQe5e6eBZDGdRdSee&ZEGdTdUe)ZFGdVdWeAZGGdXdYe ZHdS)[ztThe :class:`_expression.FromClause` class of SQL expression elements, representing SQL tables and derived rowsets. N) attrgetter) Visitable) operators)type_api) Annotated) _from_objects) _generative)ColumnCollection) ColumnSet) Executable) Generative) Immutable)_anonymous_label)_clause_element_as_expr)_clone)_cloned_difference_cloned_intersection)_document_text_coercion)_expand_cloned_interpret_as_column_or_from)&_literal_and_labels_as_label_reference_literal_as_label_reference_literal_as_text)_no_text_coercion)_select_iterables)and_) BindParameter) ClauseElement) ClauseList)Grouping)literal_column)True_)UnaryExpression)exc) inspection)utilctj|d}|)t|tjrt | |jS#t$r3}tjtj d|Yd}~dSd}~wwxYw)NF)raiseerrzFROM expression expectedreplace_context) r+inspect isinstancer, string_typesr selectableAttributeErrorraise_r* ArgumentError)elementinsperrs P/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/selectable.py_interpret_as_fromr<8s  g 6 6 6D | gt0 1 1 ' g & & &       8 9 93           sA B(BBct|}t|tr|j}t|ts|}|SN)r<r2Aliasoriginal SelectBaseselectr8s r;_interpret_as_selectrDEsO ))G'5!!#" gz * *#.."" Nc$eZdZedZdS)_OffsetLimitParamc|jSr>)effective_valueselfs r;_limit_offset_valuez%_OffsetLimitParam._limit_offset_valueOs ##rEN)__name__ __module__ __qualname__propertyrLrEr;rGrGNs- $$X$$$rErGc|dSt|dr|St|tr|St j|}t |||dS)zConvert the given value to an "offset or limit" clause. This handles incoming integers and converts to an expression; if an expression is already given, it is passed through. N__clause_element__T)type_unique)hasattrrSr2rr,asintrG)r8namerTvalues r;_offset_or_limit_clauserZTsrt . / /H))+++ GY ' 'H 7## uE$GGGGrEc|dS |j}tj|S#t$r6}tjt jd|z|Yd}~dSd}~wwxYw)zConvert the "offset or limit" clause of a select construct to an integer. This is only possible if the value is stored as a simple bound parameter. Otherwise, a compilation error is raised. Nz@This SELECT structure does not use a simple integer value for %sr/)rLr,rWr5r6r* CompileError)clauseattrnamerYr:s r;_offset_or_limit_clause_asintr_fs~t !*z%         ')12              s! A!+AA!c@t|i||S)zReturn an :class:`_expression.Alias` object derived from a :class:`_expression.Select`. :param alias: the alias name :param \*args, \**kwargs: all other arguments are delivered to the :func:`_expression.select` function. )Selectalias)rbargskwargss r;subqueryre~s% 4 "6 " " ( ( / //rEc0eZdZdZdZdZedZdS) Selectablez!Mark a class as being selectable.r4Tc|Sr>rQrJs r;r4zSelectable.selectables rEN)rMrNrO__doc____visit_name__ is_selectablerPr4rQrEr;rgrgs=++!NM XrErgcVeZdZdZeeddddZddZdS) HasPrefixesrQexprz+:meth:`_expression.HasPrefixes.prefix_with`z*:paramref:`.HasPrefixes.prefix_with.*expr`c|dd}|r*tjdd|z|||dS)aAdd one or more expressions following the statement keyword, i.e. SELECT, INSERT, UPDATE, or DELETE. Generative. This is used to support backend-specific prefix keywords such as those provided by MySQL. E.g.:: stmt = table.insert().prefix_with("LOW_PRIORITY", dialect="mysql") # MySQL 5.7 optimizer hints stmt = select([table]).prefix_with( "/*+ BKA(t1) */", dialect="mysql") Multiple prefixes can be specified by multiple calls to :meth:`_expression.HasPrefixes.prefix_with`. :param \*expr: textual or :class:`_expression.ClauseElement` construct which will be rendered following the INSERT, UPDATE, or DELETE keyword. :param \**kw: A single keyword 'dialect' is accepted. This is an optional string dialect name which will limit rendering of this prefix to only that dialect. dialectNUnsupported argument(s): %s,)popr*r7join_setup_prefixesrKrnkwrps r; prefix_withzHasPrefixes.prefix_withseB&&D))  #- <  T7+++++rENcX|jtfd|Dz|_dS)Nc6g|]}t|dfST)allow_coercion_to_textr.0prps r; z/HasPrefixes._setup_prefixes..;   "!DAAA7K   rE) _prefixestuple)rKprefixesrps `r;ruzHasPrefixes._setup_prefixesG%    !   + +  rEr>)rMrNrOrr rrxrurQrEr;rmrmsjI54 , , [ ,D      rErmcVeZdZdZeeddddZddZdS) HasSuffixesrQrnz+:meth:`_expression.HasSuffixes.suffix_with`z*:paramref:`.HasSuffixes.suffix_with.*expr`c|dd}|r*tjdd|z|||dS)aAdd one or more expressions following the statement as a whole. This is used to support backend-specific suffix keywords on certain constructs. E.g.:: stmt = select([col1, col2]).cte().suffix_with( "cycle empno set y_cycle to 1 default 0", dialect="oracle") Multiple suffixes can be specified by multiple calls to :meth:`_expression.HasSuffixes.suffix_with`. :param \*expr: textual or :class:`_expression.ClauseElement` construct which will be rendered following the target clause. :param \**kw: A single keyword 'dialect' is accepted. This is an optional string dialect name which will limit rendering of this suffix to only that dialect. rpNrqrr)rsr*r7rt_setup_suffixesrvs r; suffix_withzHasSuffixes.suffix_withsd8&&D))  #- <  T7+++++rENcX|jtfd|Dz|_dS)Nc6g|]}t|dfSr{rr}s r;rz/HasSuffixes._setup_suffixes..rrE) _suffixesr)rKsuffixesrps `r;rzHasSuffixes._setup_suffixesrrEr>)rMrNrOrr rrrrQrEr;rrsiI54 ,, [ ,:      rErceZdZdZdZdZgZdZdZdZ dZ dZ dZ dZ ejdgZejdd ejd d$d Zd$d Zd%d Zd&dZd&dZd$dZd'dZdZdZejddZdZd(dZedZ dZ!edZ"edZ#edZ$ee%ddZ&ee%dZ'd Z(ed!Z)d"Z*d#Z+dS)) FromClauseaERepresent an element that can be used within the ``FROM`` clause of a ``SELECT`` statement. The most common forms of :class:`_expression.FromClause` are the :class:`_schema.Table` and the :func:`_expression.select` constructs. Key features common to all :class:`_expression.FromClause` objects include: * a :attr:`.c` collection, which provides per-name access to a collection of :class:`_expression.ColumnElement` objects. * a :attr:`.primary_key` attribute, which is a collection of all those :class:`_expression.ColumnElement` objects that indicate the ``primary_key`` flag. * Methods to generate various derivations of a "from" clause, including :meth:`_expression.FromClause.alias`, :meth:`_expression.FromClause.join`, :meth:`_expression.FromClause.select`. fromclauseFNc|Sr>rQ)rKeffective_schemamap_s r;_translate_schemazFromClause._translate_schema'srE_columnsz1.1zThe :meth:`.FromClause.count` method is deprecated, and will be removed in a future release. Please use the :class:`_functions.count` function available from the :attr:`.func` namespace.messagesqlalchemy.sql.functionsc |jrt|jd}nt|jd}t|j|dg|fd|gi|S)zReturn a SELECT COUNT generated against this :class:`_expression.FromClause`. .. seealso:: :class:`_functions.count` r tbl_row_countfrom_obj) primary_keylistcolumnsrafunccountlabel)rK functions whereclauseparamscols r;rzFromClause.count,s$   (t'((+CCt|$$Q'C ^ ! !# & & , ,_ = = >   V     rEc t|g|fi|S)zReturn a SELECT of this :class:`_expression.FromClause`. .. seealso:: :func:`_expression.select` - general purpose method which allows for arbitrary column lists. rarKrrs r;rBzFromClause.selectIstfk44V444rEc(t|||||S)aReturn a :class:`_expression.Join` from this :class:`_expression.FromClause` to another :class:`_expression.FromClause`. E.g.:: from sqlalchemy import join j = user_table.join(address_table, user_table.c.id == address_table.c.user_id) stmt = select([user_table]).select_from(j) would emit SQL along the lines of:: SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN. :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER JOIN. Implies :paramref:`.FromClause.join.isouter`. .. versionadded:: 1.1 .. seealso:: :func:`_expression.join` - standalone function :class:`_expression.Join` - the type of object produced Join)rKrightonclauseisouterfulls r;rtzFromClause.joinUsXD%7D999rEc(t|||d|S)a Return a :class:`_expression.Join` from this :class:`_expression.FromClause` to another :class:`FromClause`, with the "isouter" flag set to True. E.g.:: from sqlalchemy import outerjoin j = user_table.outerjoin(address_table, user_table.c.id == address_table.c.user_id) The above is equivalent to:: j = user_table.join( address_table, user_table.c.id == address_table.c.user_id, isouter=True) :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER JOIN. .. versionadded:: 1.1 .. seealso:: :meth:`_expression.FromClause.join` :class:`_expression.Join` Tr)rKrrrs r; outerjoinzFromClause.outerjoinsXD%4666rEc8t||S)asReturn an alias of this :class:`_expression.FromClause`. E.g.:: a2 = some_table.alias('a2') The above code creates an :class:`_expression.Alias` object which can be used as a FROM clause in any SELECT statement. .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` )r? _constructrKrXflats r;rbzFromClause.aliass&d+++rEc8t||S)aMReturn a LATERAL alias of this :class:`_expression.FromClause`. The return value is the :class:`_expression.Lateral` construct also provided by the top-level :func:`_expression.lateral` function. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. )LateralrrKrXs r;lateralzFromClause.laterals!!$---rEc<t||||S)avReturn a TABLESAMPLE alias of this :class:`_expression.FromClause`. The return value is the :class:`_expression.TableSample` construct also provided by the top-level :func:`_expression.tablesample` function. .. versionadded:: 1.1 .. seealso:: :func:`_expression.tablesample` - usage guidelines and parameters ) TableSampler)rKsamplingrXseeds r; tablesamplezFromClause.tablesamples%%dHdDAAArEc||jvS)zReturn ``True`` if this :class:`_expression.FromClause` is 'derived' from the given ``FromClause``. An example would be an Alias of a Table is derived from that Table. ) _cloned_setrKrs r;is_derived_fromzFromClause.is_derived_fromsT---rEc@|j|jS)zReturn ``True`` if this :class:`_expression.FromClause` and the other represent the same lexical identity. This tests if either one is a copy of the other, or if they are the same via annotation identity. )r intersectionrKothers r;_is_lexical_equivalentz!FromClause._is_lexical_equivalents,,U->???rEsqlalchemy.sql.utilcR|||S)zReplace all occurrences of FromClause 'old' with the given Alias object, returning a copy of this :class:`_expression.FromClause`. ) ClauseAdaptertraverse)rKsqlutiloldrbs r;replace_selectablezFromClause.replace_selectables&$$U++44T:::rEc||d}|,||vr(||D]}||d}|r|cS |S)zzReturn corresponding_column for the given column, or if None search for a match in the given dictionary. T)require_embedded)corresponding_column)rKcolumn equivalentsrequivncs r;correspond_on_equivalentsz$FromClause.correspond_on_equivalentssr '''FF ;3+--$S)  ..ut.LLIII rEcxd}|jrSd\}}j}|jj}|D]}t t |j} || } | r|r || |r||| }}Ot| t|kr|| }}t| |krtj tj fd| D} tj tj fd| D} | | kr|| }}|S)aXGiven a :class:`_expression.ColumnElement`, return the exported :class:`_expression.ColumnElement` object from this :class:`expression.Selectable` which corresponds to that original :class:`~sqlalchemy.schema.Column` via a common ancestor column. :param column: the target :class:`_expression.ColumnElement` to be matched :param require_embedded: only return corresponding columns for the given :class:`_expression.ColumnElement`, if the given :class:`_expression.ColumnElement` is actually present within a sub-element of this :class:`_expression.FromClause`. Normally the column will match if it merely shares a common ancestor with one of the exported columns of this :class:`_expression.FromClause`. c||D]5}tt|g|sdS6dS)NFT) differencesetrr)expanded_proxy_set target_setts r;embeddedz1FromClause.corresponding_column..embedded'sb**+=>> ! !>1#..//<<&!!55!4rENNNcpg|]2}||jdd3Sweightrshares_lineage _annotationsgetr~scrs r;rz3FromClause.corresponding_column..WO "!0088O//!<<rEcpg|]2}||jdd3Srrrs r;rz3FromClause.corresponding_column.._rrE) ccontains_column proxy_set _all_columnsrrrlenr,reduceoperatoradd_uncached_proxy_set) rKrrrr intersectrcolsrri col_distance c_distances ` r;rzFromClause.corresponding_columns,    6 ! !& ) ) M#Y% v"1 .1 .A!$^AK%@%@!A!A ''(:;;A. .$. .8. ;;. .;&'CCVVc)nn,,&'CC)^^$(; &)&=&=&?&?$$L"& &'&;&;&=&=""J"L00)*AY rEc>t|d|jjdzS)z|A brief description of this :class:`_expression.FromClause`. Used primarily for error message formatting. rXz object)getattr __class__rMrJs r; descriptionzFromClause.descriptionis tVT^%NFFNFrF),rMrNrOrirjnamed_with_column _hide_froms_is_join _is_select_is_from_container _is_lateral_textualschemarr,!group_expirable_memoized_propertyr deprecated dependenciesrrBrtrrbrrrrrrrrPrrrrr rr_select_iterablerr rrrQrEr;rrs("NKHJKHF   @? MMT_ #T122   32 * 5 5 5 5,:,:,:,:\,7,7,7,7\,,,,* . . . .BBBB . . .@@@T,--;;.-;   VVVVpJJXJ666 ,,,$   !!!  9 :   A x 9 5 566"""++X+   rErceZdZdZdZdZddZeddZe ddZ e d Z d Z dd Z ejd d ZdZefdZdZdZeejd d dZeddZeejd dZedZddZe dZejd ddZe dZe dZdS)!raRepresent a ``JOIN`` construct between two :class:`_expression.FromClause` elements. The public constructor function for :class:`_expression.Join` is the module-level :func:`_expression.join()` function, as well as the :meth:`_expression.FromClause.join` method of any :class:`_expression.FromClause` (e.g. such as :class:`_schema.Table`). .. seealso:: :func:`_expression.join` :meth:`_expression.FromClause.join` rtTNFct||_t||_|&||j|j|_n||_||_||_dS)zConstruct a new :class:`_expression.Join`. The usual entrypoint here is the :func:`_expression.join` function or the :meth:`_expression.FromClause.join` method of any :class:`_expression.FromClause` object. N)r<left self_groupr_match_primariesrrr)rKr$rrrrs r;__init__z Join.__init__sj't,, '..99;;   11$)TZHHDMM$DM  rEc"||||d|S)aReturn an ``OUTER JOIN`` clause element. The returned object is an instance of :class:`_expression.Join`. Similar functionality is also available via the :meth:`_expression.FromClause.outerjoin` method on any :class:`_expression.FromClause`. :param left: The left side of the join. :param right: The right side of the join. :param onclause: Optional criterion for the ``ON`` clause, is derived from foreign key relationships established between left and right otherwise. To chain joins together, use the :meth:`_expression.FromClause.join` or :meth:`_expression.FromClause.outerjoin` methods on the resulting :class:`_expression.Join` object. TrrrQ)clsr$rrrs r;_create_outerjoinzJoin._create_outerjoins0s4$TBBBBrEc ||||||S)a8Produce a :class:`_expression.Join` object, given two :class:`_expression.FromClause` expressions. E.g.:: j = join(user_table, address_table, user_table.c.id == address_table.c.user_id) stmt = select([user_table]).select_from(j) would emit SQL along the lines of:: SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id Similar functionality is available given any :class:`_expression.FromClause` object (e.g. such as a :class:`_schema.Table`) using the :meth:`_expression.FromClause.join` method. :param left: The left side of the join. :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN. :param full: if True, render a FULL OUTER JOIN, instead of JOIN. .. versionadded:: 1.1 .. seealso:: :meth:`_expression.FromClause.join` - method form, based on a given left side. :class:`_expression.Join` - the type of object produced. rQ)r*r$rrrrs r; _create_joinzJoin._create_joinshs4'4888rEcd|jjt|j|jjt|jfzS)Nz Join object on %s(%d) and %s(%d))r$ridrrJs r;rzJoin.descriptionTs:1 I ! tyMM J " tzNN 5   rEcr||up3|j|p|j|Sr>)r$rrrs r;rzJoin.is_derived_from]s? $  6y((44 6z))*55 rEc t|Sr> FromGroupingrKagainsts r;r%zJoin.self_groupdD!!!rErcd|jjDd|jjDz}|j|d|D|j|jd|D|j tj d|DdS)Ncg|]}|SrQrQr~rs r;rz4Join._populate_column_collection..is0001000rEcg|]}|SrQrQr9s r;rz4Join._populate_column_collection..is%4 4 4 A4 4 4 rEc3(K|] }|j |VdSr>)rr9s r; z3Join._populate_column_collection..os)55qq}5555555rEc3(K|] }|j|fVdSr>)_labelr~rs r;r<z3Join._populate_column_collection..rs)BB3cj#.BBBBBBrEcg|] }|j SrQ)r r?s r;rz4Join._populate_column_collection..tsBBB3c.BBBrE) r$rrrextendreduce_columnsrrupdater  itertoolschain)rKrrs r;rz Join._populate_column_collectiongs00di/0004 4 z)4 4 4     " "55G555t}     BB'BBBBBB   OBB'BBB C     rEc&|j|}||j|}|X|jrQ||j|j<|j|j|jr|j ||SdSr>) r$rrr rr>r rCrrrKrrs r;rzJoin._refresh_for_new_columnwsi//77 ;*44V<)rr$rrrKclonerws r;_copy_internalszJoin._copy_internalssi E$)**r** U4:,,,, dm22r22 rEc *|j|j|jfSr>)r$rrrKrds r; get_childrenzJoin.get_childrensy$*dm33rEcpt|tr|j}nd}||||S)N)a_subset)r2rr_join_condition)rKr$r left_rights r;r&zJoin._match_primariess= dD ! ! JJJ##D%*#EEErE)0.9zThe :paramref:`.join_condition.ignore_nonexistent_tables` parameter is deprecated and will be removed in a future release. Tables outside of the two tables being handled are no longer considered.)ignore_nonexistent_tablesc|||||}t|dkr|||||t|dkrAt|trd}nd}t jd|jd|jd|dt| dD}t|dkr|dSt|S) aCreate a join condition between two tables or selectables. e.g.:: join_condition(tablea, tableb) would produce an expression along the lines of:: tablea.c.id==tableb.c.tablea_id The join is determined based on the foreign key relationships between the two selectables. If there are multiple ways to join, or no way to join, an error is raised. :param ignore_nonexistent_tables: unused - tables outside of the two tables being handled are not considered. :param a_subset: An optional expression that is a sub-component of ``a``. An attempt will be made to join to just this sub-component first before looking at the full ``a`` construct, and if found will be successful even if there are other ways to join to ``a``. This allows the "right side" of a join to be passed thereby providing a "natural join". rrzI Perhaps you meant to convert the right side to a subquery using alias()?z2Can't find any foreign key relationships between '' and 'z'.c g|] \}}||k SrQrQ)r~xys r;rz(Join._join_condition..s CCCTQaCCCrE) _joincond_scan_left_rightr_joincond_trim_constraintsr2r3r*NoForeignKeysErrorrrvaluesr!) r*abrTrPconsider_as_foreign_keys constraintshintcrits r;rQzJoin._join_conditionsV33 x4   {  a    * *1k#;    {  q !\** . ((===!---7  DCT+*<*<*>*>%?%?%BCCC t99>>7N; rEct|tr|j}nd}|||||}t |S)N)r_r`rPra)r2rrr[bool)r*r$rrarRrbs r; _can_joinzJoin._can_joinsX dD ! ! JJJ33%= 4  K   rEc tjt}||fD]d}|t|jdD]}| |j|vr ||} nE#tj$r3} d| |D} | j | vrYd} ~ bd} ~ wwxYw| '||j  | |jf||urt|jdD]}| |j|vr ||} nE#tj$r3} d| |D} | j | vrYd} ~ bd} ~ wwxYw| '||j  | |jf|rnf|S)Nc|jjSr>parent_creation_orderfks r;z0Join._joincond_scan_left_right..s ry/HrErch|] }|j SrQrXr~rs r; z1Join._joincond_scan_left_right..s"N"N"Na16"N"N"NrEc|jjSr>rjrms r;roz0Join._joincond_scan_left_right.. s bi6OrEch|] }|j SrQrrrss r;rtz1Join._joincond_scan_left_right..s&O&O&O!qv&O&O&OrE) collections defaultdictrsortedr rk get_referentr*NoReferenceError find_tables table_name constraintappend) r*sql_utilr_rPr`rarbr$rnrnrte table_namess r;r[zJoin._joincond_scan_left_rights "-d33 qM+ + D|$H$H H H-8 )AAA!//$//CC+!!!"N"N83G3G3M3M"N"N"NK+55  !? .55sBI6FGGG1}} %+O+OLLB1<I-EEE % ooa00/%%%&O&Ox7K7KA7N7N&O&O&O ?k99!$HHHH %#BM2993 :JKKK  s0 A  B"/)BB"9DE)E  Ec|rDt|D]4}td|jDt|kr||=5t|dkr]td|D}t|dkrt|d}|||i}t|dkr%t jd|jd|jddS)Nc3$K|] }|jV dSr>)rkr~fs r;r<z2Join._joincond_trim_constraints..*s$88Aqx888888rErc34K|]}t|VdSr>)r)r~rds r;r<z2Join._joincond_trim_constraints..2s(FFtFFFFFFrErzCan't determine join between 'rWz'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly.)rrelementsrr^r*AmbiguousForeignKeysErrorr)r*r_r`rbraconstdedupers r;r\zJoin._joincond_trim_constraints!s $ +k** + +8888888C,==$E* {  a  FF1C1C1E1EFFFFFF6{{a;''*"K$45 {  q // '(mmmQ]]] D  ! rEc @|j|jg}t||fd|gi|S)aSCreate a :class:`_expression.Select` from this :class:`_expression.Join`. The equivalent long-hand form, given a :class:`_expression.Join` object ``j``, is:: from sqlalchemy import select j = select([j.left, j.right], **kw).\ where(whereclause).\ select_from(j) :param whereclause: the WHERE criterion that will be sent to the :func:`select()` function :param \**kwargs: all other kwargs are sent to the underlying :func:`select()` function. r)r$rra)rKrrdcollists r;rBz Join.select@s1(9dj)g{FFdVFvFFFrEc2|jjp |jjSr>)r$bindrrJs r;rz Join.bindXsy~00rEc|r| Jd|jd|jd}}||||}||||j|j|j S| dd|S)aReturn an alias of this :class:`_expression.Join`. The default behavior here is to first produce a SELECT construct from this :class:`_expression.Join`, then to produce an :class:`_expression.Alias` from that. So given a join of the form:: j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) The JOIN by itself would look like:: table_a JOIN table_b ON table_a.id = table_b.a_id Whereas the alias of the above, ``j.alias()``, would in a SELECT context look like:: (SELECT table_a.id AS table_a_id, table_b.id AS table_b_id, table_b.a_id AS table_b_a_id FROM table_a JOIN table_b ON table_a.id = table_b.a_id) AS anon_1 The equivalent long-hand form, given a :class:`_expression.Join` object ``j``, is:: from sqlalchemy import select, alias j = alias( select([j.left, j.right]).\ select_from(j).\ with_labels(True).\ correlate(False), name=name ) The selectable produced by :meth:`_expression.Join.alias` features the same columns as that of the two individual selectables presented under a single name - the individual columns are "auto-labeled", meaning the ``.c.`` collection of the resulting :class:`_expression.Alias` represents the names of the individual columns using a ``_`` scheme:: j.c.table_a_id j.c.table_b_a_id :meth:`_expression.Join.alias` also features an alternate option for aliasing joins which produces no enclosing SELECT and does not normally apply labels to the column names. The ``flat=True`` option will call :meth:`_expression.FromClause.alias` against the left and right sides individually. Using this option, no new ``SELECT`` is produced; we instead, from a construct as below:: j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) j = j.alias(flat=True) we get a result like this:: table_a AS table_a_1 JOIN table_b AS table_b_1 ON table_a_1.id = table_b_1.a_id The ``flat=True`` argument is also propagated to the contained selectables, so that a composite join such as:: j = table_a.join( table_b.join(table_c, table_b.c.id == table_c.c.b_id), table_b.c.a_id == table_a.c.id ).alias(flat=True) Will produce an expression like:: table_a AS table_a_1 JOIN ( table_b AS table_b_1 JOIN table_c AS table_c_1 ON table_b_1.id = table_c_1.b_id ) ON table_a_1.id = table_b_1.a_id The standalone :func:`_expression.alias` function as well as the base :meth:`_expression.FromClause.alias` method also support the ``flat=True`` argument as a no-op, so that the argument can be passed to the ``alias()`` method of any selectable. .. versionadded:: 0.9.0 Added the ``flat=True`` option to create "aliases" of joins without enclosing inside of a SELECT subquery. :param name: name given to the alias. :param flat: if True, produce an alias of the left and right sides of this :class:`_expression.Join` and return the join of those two selectables. This produces join expression that does not include an enclosing SELECT. .. versionadded:: 0.9.0 .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` Nz"Can't send name argument with flatT)rr)F) use_labels correlate) r$rbrrrErtrrrrrB)rKrrXrleft_aright_aadapters r;rbz Join.alias\sR  M<.s& G G GmAFAG,, G G GrE)rDrErrJs r;rzJoin._hide_fromss% G Gd6F G G G  rEcV|g|jjz|jjz|jjzSr>)rr r$rrJs r;r zJoin._from_objectss7Fm) *i% &j& ' rErrr>)FNN) rMrNrOrirjrr' classmethodr+r-rPrrr%r,r rrrrKrNr&deprecated_paramsrQrgr[r\rBrrbrr rQrEr;rrs$NH&CCC[C2=B393939[39j  X    """"T,--   .-     %+3333 444FFFT# #(!% <<<[<| ! ! ![ !T,--11.-[1f[<GGGG011X1T,--yMyMyM.-yMv  X   X   rErceZdZdZdZdZdZdZedZ eddZ dd Z dfd Z e d Zd Zd ZdZdZefdZddZe dZe dZxZS)r?aRepresents an table or selectable alias (AS). Represents an alias, as typically applied to any table or sub-select within a SQL statement using the ``AS`` keyword (or without the keyword on certain databases such as Oracle). This object is constructed from the :func:`_expression.alias` module level function as well as the :meth:`_expression.FromClause.alias` method available on all :class:`_expression.FromClause` subclasses. rbTc td|jjd|jjd|jjd)NzThe zC class is not intended to be constructed directly. Please use the z() standalone function or the z8() method available from appropriate selectable objects.)NotImplementedErrorrrMlower)rKargrws r;r'zAlias.__init__s`!! ''''--////'--////    rEcJ||}|j|i||Sr>)__new___init)r*rrwobjs r;rzAlias._constructs/kk# 3" rENFcJt|||S)a Return an :class:`_expression.Alias` object. An :class:`_expression.Alias` represents any :class:`_expression.FromClause` with an alternate name assigned within SQL, typically using the ``AS`` clause when generated, e.g. ``SELECT * FROM table AS aliasname``. Similar functionality is available via the :meth:`_expression.FromClause.alias` method available on all :class:`_expression.FromClause` subclasses. In terms of a SELECT object as generated from the :func:`_expression.select` function, the :meth:`_expression.SelectBase.alias` method returns an :class:`_expression.Alias` or similar object which represents a named, parenthesized subquery. When an :class:`_expression.Alias` is created from a :class:`_schema.Table` object, this has the effect of the table being rendered as ``tablename AS aliasname`` in a SELECT statement. For :func:`_expression.select` objects, the effect is that of creating a named subquery, i.e. ``(select ...) AS aliasname``. The ``name`` parameter is optional, and provides the name to use in the rendered SQL. If blank, an "anonymous" name will be deterministically generated at compile time. Deterministic means the name is guaranteed to be unique against other constructs used in the same statement, and will also be the same name for each successive compilation of the same statement object. :param selectable: any :class:`_expression.FromClause` subclass, such as a table, select statement, etc. :param name: string name to be assigned as the alias. If ``None``, a name will be deterministically generated at compile time. :param flat: Will be passed through to if the given selectable is an instance of :class:`_expression.Join` - see :meth:`_expression.Join.alias` for details. .. versionadded:: 0.9.0 )rXr)r<rb)r*r4rXrs r;_factoryzAlias._factorys&b"*--33D3IIIrEcb|}t|tr|j}t|t||_|j|_|jr |j|_||_|E|jjrt|jdd}tdt||pdfz}||_ dS)NrXz %%(%d %s)sanon) r2r?r8r@supports_execution_execution_optionsrrrr/rX)rKr4rXbaseselectables r;rz Alias._initAs#// 4+3N// 4& "0"C  " H&4&GD #! <}. <t}fd;;#LBtHHdnf3M$MNND rEct|trBt|jtr(|jrt |St t||S)Nr5) r2CompoundSelectr@ra_needs_parens_for_groupingr3superr?r%)rKr5rs r;r%zAlias.self_groupPsr w / / &4=&11 & 88:: &  %% %UD!!,,W,===rEc^tjr|jS|jddSNasciibackslashreplacer,py3krXencoderJs r;rzAlias.descriptionZ. 9 A9 9##G-?@@ @rEc |jS#t$r6}tjtd|jz|Yd}~dSd}~wwxYw)Nz)Element %s does not support 'as_scalar()'r/)r8 as_scalarr5r,r6)rKr:s r;rzAlias.as_scalaras <))++ +    K$&*l3!$            s A+AAcL||jvrdS|j|S)NT)rr8rrs r;rzAlias.is_derived_fromms+ ) ) )4|++J777rEcX|jjjD]}||dSr>)r8rr _make_proxy)rKrs r;rz!Alias._populate_column_collectionrs8<'4 " "C OOD ! ! ! ! " "rEcz|j|}||jsdS||SdSr>)r8rr rrGs r;rzAlias._refresh_for_new_columnvsCl226:: ?' -tt,,,4rEc t|jtrdS|||jfi||_|j}t|tr|j}t|t||_dSr>)r2r8 TableClauserr?r@)rKrJrwrs r;rKzAlias._copy_internalss dlK 0 0  F uT\00R00 // 4+3N// 4& rEc+<K|r|jD]}|V|jVdSr>)rr8)rKcolumn_collectionsrwrs r;rNzAlias.get_childrens>  V  lrEc|gSr>rQrJs r;r zAlias._from_objects v rEc|jjSr>)r8rrJs r;rz Alias.binds |  rErr>T)rMrNrOrirjrrr'rrrrr%rPrrrrrrrKrNr r __classcell__rs@r;r?r?sz  N    [ 0J0J0J[0Jd    >>>>>>AAXA   888 """%+ ' ' ' ' X!!X!!!!!rEr?c2eZdZdZdZdZeddZdS)raRepresent a LATERAL subquery. This object is constructed from the :func:`_expression.lateral` module level function as well as the :meth:`_expression.FromClause.lateral` method available on all :class:`_expression.FromClause` subclasses. While LATERAL is part of the SQL standard, currently only more recent PostgreSQL versions provide support for this keyword. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. rTNcHt||S)aReturn a :class:`_expression.Lateral` object. :class:`_expression.Lateral` is an :class:`_expression.Alias` subclass that represents a subquery with the LATERAL keyword applied to it. The special behavior of a LATERAL subquery is that it appears in the FROM clause of an enclosing SELECT, but may correlate to other FROM clauses of that SELECT. It is a special case of subquery only supported by a small number of backends, currently more recent PostgreSQL versions. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. rr)r<r)r*r4rXs r;rzLateral._factorys#*"*--5545@@@rEr>)rMrNrOrirjrrrrQrEr;rrsN$NKAAA[AAArErcreZdZdZdZeddZdfd Zej ddZ xZ S) radRepresent a TABLESAMPLE clause. This object is constructed from the :func:`_expression.tablesample` module level function as well as the :meth:`_expression.FromClause.tablesample` method available on all :class:`_expression.FromClause` subclasses. .. versionadded:: 1.1 .. seealso:: :func:`_expression.tablesample` rNcLt||||S)aReturn a :class:`_expression.TableSample` object. :class:`_expression.TableSample` is an :class:`_expression.Alias` subclass that represents a table with the TABLESAMPLE clause applied to it. :func:`_expression.tablesample` is also available from the :class:`_expression.FromClause` class via the :meth:`_expression.FromClause.tablesample` method. The TABLESAMPLE clause allows selecting a randomly selected approximate percentage of rows from a table. It supports multiple sampling methods, most commonly BERNOULLI and SYSTEM. e.g.:: from sqlalchemy import func selectable = people.tablesample( func.bernoulli(1), name='alias', seed=func.random()) stmt = select([selectable.c.people_id]) Assuming ``people`` with a column ``people_id``, the above statement would render as:: SELECT alias.people_id FROM people AS alias TABLESAMPLE bernoulli(:bernoulli_1) REPEATABLE (random()) .. versionadded:: 1.1 :param sampling: a ``float`` percentage between 0 and 100 or :class:`_functions.Function`. :param name: optional alias name :param seed: any real-valued SQL expression. When specified, the REPEATABLE sub-clause is also rendered. )rXr)r<r)r*r4rrXrs r;rzTableSample._factorys1X"*--99 4d:   rEcx||_||_tt|||dSNrr)rrrrr)rKr4rrXrrs r;rzTableSample._init s:    k4  &&z&=====rErct|j|jr|jS|j|jSr>)r2rFunctionrsystem)rKrs r; _get_methodzTableSample._get_methods9 dmY%7 8 8 8= >((77 7rEr) rMrNrOrirjrrrr,r rrrs@r;rrs  #N- - - [- ^>>>>>> T122883288888rErceZdZdZdZed dZdddeddffd Ze ffd Z e j dd Z d d Zd Zd ZxZS)CTEzRepresent a Common Table Expression. The :class:`_expression.CTE` object is obtained using the :meth:`_expression.SelectBase.cte` method from any selectable. See that method for complete examples. cteNFcJt|||S)zReturn a new :class:`_expression.CTE`, or Common Table Expression instance. Please see :meth:`_expression.HasCTE.cte` for detail on CTE usage. rX recursive)r<r)r*r4rXrs r;rz CTE._factory$s."*--112   rEc||_||_||_|r||_|r||_t t |||dSr)r _cte_alias _restatesrrrrr) rKr4rXrrrrrrs r;rz CTE._init0sa#$"  '&DN  '&DN c4z55555rEc tt|jfi|j|jfi|_t fd|jD|_dS)Nc"g|] }|fi SrQrQ)r~elemrJrws r;rz'CTE._copy_internals..Hs+ : : :4UU4  2   : : :rE)rrrKr frozensetr)rKrJrwrs ``r;rKzCTE._copy_internalsCs~(c4(55"555 ? &#eDO::r::DO" : : : : :4> : : :  rEsqlalchemy.sql.dmlct|j|jr&|jjD]}||dS|jjjD]}||dSr>)r2r8 UpdateBase _returningrrr)rKdmlrs r;rzCTE._populate_column_collectionKs dlCN 3 3 &|. & &%%%% & &|+8 & &%%%% & &rEcjt|j||j||j|jS)a1Return an :class:`_expression.Alias` of this :class:`_expression.CTE`. This method is a CTE-specific specialization of the :meth:`_expression.FromClause.alias` method. .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` )rXrrrr)rrr@rrrrs r;rbz CTE.aliasTs9~~ Mnnn    rEct|j||j|j|j|g|j|jSN)rXrrrr) rrr@unionrXrrrrrs r;rz CTE.unionksY~~ M   & &nn**D622nn    rEct|j||j|j|j|g|j|j Sr) rrr@ union_allrXrrrrrrs r;rz CTE.union_allusY~~ M # #E * *nn**D622nn    rEr)rMrNrOrirjrrrrrrKr,r rrbrrrrs@r;rrsN    [  )++666666&%+      T+,,&&-,&    .          rErceZdZdZddZdS)HasCTEzTMixin that declares a class to include CTE support. .. versionadded:: 1.1 NFc<t|||S)aReturn a new :class:`_expression.CTE`, or Common Table Expression instance. Common table expressions are a SQL standard whereby SELECT statements can draw upon secondary statements specified along with the primary statement, using a clause called "WITH". Special semantics regarding UNION can also be employed to allow "recursive" queries, where a SELECT statement can draw upon the set of rows that have previously been selected. CTEs can also be applied to DML constructs UPDATE, INSERT and DELETE on some databases, both as a source of CTE rows when combined with RETURNING, as well as a consumer of CTE rows. .. versionchanged:: 1.1 Added support for UPDATE/INSERT/DELETE as CTE, CTEs added to UPDATE/INSERT/DELETE. SQLAlchemy detects :class:`_expression.CTE` objects, which are treated similarly to :class:`_expression.Alias` objects, as special elements to be delivered to the FROM clause of the statement as well as to a WITH clause at the top of the statement. For special prefixes such as PostgreSQL "MATERIALIZED" and "NOT MATERIALIZED", the :meth:`_expression.CTE.prefix_with` method may be used to establish these. .. versionchanged:: 1.3.13 Added support for prefixes. In particular - MATERIALIZED and NOT MATERIALIZED. :param name: name given to the common table expression. Like :meth:`_expression.FromClause.alias`, the name can be left as ``None`` in which case an anonymous symbol will be used at query compile time. :param recursive: if ``True``, will render ``WITH RECURSIVE``. A recursive common table expression is intended to be used in conjunction with UNION ALL in order to derive rows from those already selected. The following examples include two from PostgreSQL's documentation at http://www.postgresql.org/docs/current/static/queries-with.html, as well as additional examples. Example 1, non recursive:: from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() orders = Table('orders', metadata, Column('region', String), Column('amount', Integer), Column('product', String), Column('quantity', Integer) ) regional_sales = select([ orders.c.region, func.sum(orders.c.amount).label('total_sales') ]).group_by(orders.c.region).cte("regional_sales") top_regions = select([regional_sales.c.region]).\ where( regional_sales.c.total_sales > select([ func.sum(regional_sales.c.total_sales)/10 ]) ).cte("top_regions") statement = select([ orders.c.region, orders.c.product, func.sum(orders.c.quantity).label("product_units"), func.sum(orders.c.amount).label("product_sales") ]).where(orders.c.region.in_( select([top_regions.c.region]) )).group_by(orders.c.region, orders.c.product) result = conn.execute(statement).fetchall() Example 2, WITH RECURSIVE:: from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() parts = Table('parts', metadata, Column('part', String), Column('sub_part', String), Column('quantity', Integer), ) included_parts = select([ parts.c.sub_part, parts.c.part, parts.c.quantity]).\ where(parts.c.part=='our part').\ cte(recursive=True) incl_alias = included_parts.alias() parts_alias = parts.alias() included_parts = included_parts.union_all( select([ parts_alias.c.sub_part, parts_alias.c.part, parts_alias.c.quantity ]). where(parts_alias.c.part==incl_alias.c.sub_part) ) statement = select([ included_parts.c.sub_part, func.sum(included_parts.c.quantity). label('total_quantity') ]).\ group_by(included_parts.c.sub_part) result = conn.execute(statement).fetchall() Example 3, an upsert using UPDATE and INSERT with CTEs:: from datetime import date from sqlalchemy import (MetaData, Table, Column, Integer, Date, select, literal, and_, exists) metadata = MetaData() visitors = Table('visitors', metadata, Column('product_id', Integer, primary_key=True), Column('date', Date, primary_key=True), Column('count', Integer), ) # add 5 visitors for the product_id == 1 product_id = 1 day = date.today() count = 5 update_cte = ( visitors.update() .where(and_(visitors.c.product_id == product_id, visitors.c.date == day)) .values(count=visitors.c.count + count) .returning(literal(1)) .cte('update_cte') ) upsert = visitors.insert().from_select( [visitors.c.product_id, visitors.c.date, visitors.c.count], select([literal(product_id), literal(day), literal(count)]) .where(~exists(update_cte.select())) ) connection.execute(upsert) .. seealso:: :meth:`.orm.query.Query.cte` - ORM version of :meth:`_expression.HasCTE.cte`. r)rr)rKrXrs r;rz HasCTE.ctesN~~d~CCCrEr)rMrNrOrirrQrEr;rrs> gDgDgDgDgDgDrErceZdZdZdZdZdZedZedZ edZ dZ d Z ed Z d Zefd Zed ZdZdZdZdS)r3z%Represent a grouping of a FROM clausegroupingc||_dSr>rCrKr8s r;r'zFromGrouping.__init__6s  rEcdSr>rQrJs r;rzFromGrouping._init_collections9 rEc|jjSr>)r8rrJs r;rzFromGrouping.columns<s |##rEc|jjSr>)r8rrJs r;rzFromGrouping.primary_key@ |''rEc|jjSr>)r8r rJs r;r zFromGrouping.foreign_keysDs |((rEc6|j|Sr>)r8rrs r;rzFromGrouping.is_derived_fromHs|++G444rEc @t|jjdi|S)NrQ)r3r8rb)rKrws r;rbzFromGrouping.aliasKs&.DL.4444555rEc|jjSr>)r8rrJs r;rzFromGrouping._hide_fromsNrrEc |jfSr>rCrMs r;rNzFromGrouping.get_childrenRs  rEc ,||jfi||_dSr>rCrIs r;rKzFromGrouping._copy_internalsUs!uT\00R00 rEc|jjSr>)r8r rJs r;r zFromGrouping._from_objectsXs |))rEc,t|j|Sr>)rr8)rKattrs r; __getattr__zFromGrouping.__getattr__\st|T***rEcd|jiSNr8rCrJs r; __getstate__zFromGrouping.__getstate___s4<((rEc |d|_dSrrC)rKstates r; __setstate__zFromGrouping.__setstate__bsY' rEN)rMrNrOrirjr'rrPrrr rrbrrNrrKr rrrrQrEr;r3r31s7//N   $$X$((X())X)555666((X(%+1111**X*+++)))(((((rEr3ceZdZdZdZdZdZ dZ fdZdZ e j dZ d Z dd Ze jd dd Ze jd  dd Ze jd ddZedZxZS)ra-Represents a minimal "table" construct. This is a lightweight table object that has only a name, a collection of columns, which are typically produced by the :func:`_expression.column` function, and a schema:: from sqlalchemy import table, column user = table("user", column("id"), column("name"), column("description"), ) The :class:`_expression.TableClause` construct serves as the base for the more commonly used :class:`_schema.Table` object, providing the usual set of :class:`_expression.FromClause` services including the ``.c.`` collection and statement generation methods. It does **not** provide all the additional schema-level services of :class:`_schema.Table`, including constraints, references to other tables, or support for :class:`_schema.MetaData`-level services. It's useful on its own as an ad-hoc construct used to generate quick SQL statements when a more fully fledged :class:`_schema.Table` is not on hand. tableTFNctt||x|_|_t |_t|_t|_ |D]}| || dd}|||_ |r$tjdt!|zdS)aProduce a new :class:`_expression.TableClause`. The object returned is an instance of :class:`_expression.TableClause`, which represents the "syntactical" portion of the schema-level :class:`_schema.Table` object. It may be used to construct lightweight table constructs. .. versionchanged:: 1.0.0 :func:`_expression.table` can now be imported from the plain ``sqlalchemy`` namespace like any other SQL element. :param name: Name of the table. :param columns: A collection of :func:`_expression.column` constructs. :param schema: The schema name for this table. .. versionadded:: 1.3.18 :func:`_expression.table` can now accept a ``schema`` argument. rNrq)rrr'rXfullnamer rr rrr  append_columnrsrr*r7r)rKrXrrwrrrs r;r'zTableClause.__init__s0 k4  ))+++$(( DM(** $;;EE " "A   q ! ! ! !$''   DK  N#$ADHH$LMM M N NrEcdSr>rQrJs r;rzTableClause._init_collectionsrrEc^tjr|jS|jddSrrrJs r;rzTableClause.descriptionrrEc |j}|2||ur.tjd|jdt |d|||j|j<||_dS)Nzcolumn object 'z' already assigned to table r)rr*r7rrr)rKrexistings r;r zTableClause.append_columnsl7  HD$8$8##555'(M8DDDF  ! aerEc ,|rd|jDSgS)Ncg|]}|SrQrQr9s r;rz,TableClause.get_children..s&&&!A&&&rE)rrKrrds r;rNzTableClause.get_childrens%  &&tv&&& &IrErc $|j|f||d|S)zGenerate an :func:`_expression.insert` construct against this :class:`_expression.TableClause`. E.g.:: table.insert().values(name='foo') See :func:`_expression.insert` for argument and usage information. )r^inline)Insert)rKrr^rrds r;insertzTableClause.inserts%sz$GvfGGGGGrEc &|j|f|||d|S)aGenerate an :func:`_expression.update` construct against this :class:`_expression.TableClause`. E.g.:: table.update().where(table.c.id==7).values(name='foo') See :func:`_expression.update` for argument and usage information. )rr^r)Update)rKrrr^rrds r;rCzTableClause.updates:sz  #       rEc |j||fi|S)zGenerate a :func:`_expression.delete` construct against this :class:`_expression.TableClause`. E.g.:: table.delete().where(table.c.id==7) See :func:`_expression.delete` for argument and usage information. )Delete)rKrrrds r;deletezTableClause.deletes sz$ 66v666rEc|gSr>rQrJs r;r zTableClause._from_objectsrrErr)NNFr>)rMrNrOrirjrimplicit_returning_autoincrement_columnr'rr,memoized_propertyrr rNr rrCrrPr rrs@r;rrfsn:N=!>$N$N$N$N$NL    AAA    T+,, H H H-, HT+,,9>   -, ,T+,, 7 7 7-, 7XrErcbeZdZedZedZdZdZe fdZ d dZ dS) ForUpdateArgc|dvrdSdx}}|dkrd}n/|dkrd}n&|dkrdx}}n|durtjd|zt|| S) aParse the for_update argument of :func:`_expression.select`. :param mode: Defines the lockmode to use. ``None`` - translates to no lockmode ``'update'`` - translates to ``FOR UPDATE`` (standard SQL, supported by most dialects) ``'nowait'`` - translates to ``FOR UPDATE NOWAIT`` (supported by Oracle, PostgreSQL 8.1 upwards) ``'read'`` - translates to ``LOCK IN SHARE MODE`` (for MySQL), and ``FOR SHARE`` (for PostgreSQL) ``'read_nowait'`` - translates to ``FOR SHARE NOWAIT`` (supported by PostgreSQL). ``FOR SHARE`` and ``FOR SHARE NOWAIT`` (PostgreSQL). rNFnowaitTread read_nowaitzUnknown for_update argument: %rr$r#)r*r7r!)rKrr#r$s r;parse_legacy_selectz ForUpdateArg.parse_legacy_select s, -  4 (??FF F]]DD M ! ! D66 __#$E$KLL Lf5555rEcX|jr |jsdS|jr |jrdS|jrdSdS)Nr$r%r#Tr&rJs r;legacy_for_update_valuez$ForUpdateArg.legacy_for_update_value1sF 9 T[ 6 Y 4;  = [ 84rEct|toM|j|jko=|j|jko-|j|jko|j|jko |j|juSr>)r2r!r#r$ skip_locked key_shareofrs r;__eq__zForUpdateArg.__eq__<sq ul + + $  + $ di' $!T%55 $4>1  $ DG#  rEc t|Sr>)r/rJs r;__hash__zForUpdateArg.__hash__Fs $xxrEc N|jfd|jD|_dSdS)Nc"g|] }|fi SrQrQ)r~rrJrws r;rz0ForUpdateArg._copy_internals..Ks+;;;CuuS''B'';;;rE)r-rIs ``r;rKzForUpdateArg._copy_internalsIs8 7 ;;;;;47;;;DGGG  rEFNc||_||_||_||_|%dt j|D|_dSd|_dS)z{Represents arguments specified to :meth:`_expression.Select.for_update`. .. versionadded:: 0.9.0 Nc,g|]}t|SrQr)r~rs r;rz)ForUpdateArg.__init__..as.7;,T22rE)r#r$r+r,r,to_listr-rKr#r$r-r+r,s r;r'zForUpdateArg.__init__Msa  &" >?C|B?O?ODGGGDGGGrEFFNFF) rMrNrOrr'rPr)r.r0rrKr'rQrEr;r!r! s"6"6["6HX   %+<<<<    rEr!ceZdZdZdZdZeejdddZ dZ e d Z d S) rAzBase class for SELECT statements. This includes :class:`_expression.Select`, :class:`_selectable.CompoundSelect` and :class:`.TextAsFrom`. c t|S)aLReturn a 'scalar' representation of this selectable, which can be used as a column expression. Typically, a select statement which has only one column in its columns clause is eligible to be used as a scalar expression. The returned object is an instance of :class:`ScalarSelect`. ) ScalarSelectrJs r;rzSelectBase.as_scalarssD!!!rEcP||S)zReturn a 'scalar' representation of this selectable, embedded as a subquery with a label. .. seealso:: :meth:`_expression.SelectBase.as_scalar`. )rrrs r;rzSelectBase.labels"~~%%d+++rE0.6zThe :meth:`.SelectBase.autocommit` method is deprecated, and will be removed in a future release. Please use the the :paramref:`.Connection.execution_options.autocommit` parameter in conjunction with the :meth:`.Executable.execution_options` method.rcH|jddi|_dS)zQReturn a new selectable with the 'autocommit' flag set to True. autocommitTN)rrrJs r;r>zSelectBase.autocommits-#'"9"?"? 4 # # rEc|j|j}|j|_||S)zWOverride the default _generate() method to also clear out exported collections.)rrrcopyr)rKss r; _generatezSelectBase._generatesG N " "4> 2 2]''))  rEc|gSr>rQrJs r;r zSelectBase._from_objectsrrEN) rMrNrOrirrr r,rr>rBrPr rQrEr;rArAhs " " " , , ,T_ 8  [ XrErAceZdZdZeZeZdZdZdZ ddZ e dZ e j dZ e ddZedZe d Ze d Ze d Ze d Zed ZedZedZedZdZdZe dZefdZdS)GenerativeSelectaZBase class for SELECT statements where additional elements can be added. This serves as the base for :class:`_expression.Select` and :class:`_selectable.CompoundSelect` where elements such as ORDER BY, GROUP BY can be added and column rendering can be controlled. Compare to :class:`.TextAsFrom`, which, while it subclasses :class:`_expression.SelectBase` and is also a SELECT construct, represents a fixed textual string which cannot be altered at this level, only wrapped as a subquery. .. versionadded:: 0.9.0 :class:`_expression.GenerativeSelect` was added to provide functionality specific to :class:`_expression.Select` and :class:`_selectable.CompoundSelect` while allowing :class:`_expression.SelectBase` to be used for other SELECT-like objects, e.g. :class:`.TextAsFrom`. NFc ||_|durt||_|5t jd|jd|i|_|t||_ |t||_ ||_ |(tt j |dti|_|*tt j |dt i|_dSdS)NFzThe select.autocommit parameter is deprecated and will be removed in a future release. Please refer to the Select.execution_options.autocommit` parameter.r>r)rr!r'_for_update_argr,warn_deprecatedrrrZ _limit_clause_offset_clause_bindr$r5r_order_by_clauser_group_by_clause) rKr for_updatelimitoffsetorder_bygroup_byrr>s r;r'zGenerativeSelect.__init__s% U " "#/#C#CJ#O#OD  !  B    '+&=&C&Cz*''D #  !8!?!?D   "9&"A"AD   $.h''%!G%%D !  $.h''%!<%%D ! ! ! rEc,|j |jjSdS)z@Provide legacy dialect support for the ``for_update`` attribute.N)rGr)rJs r;rNzGenerativeSelect.for_updates   +'? ?4rEcDt||_dSr>)r!r'rG)rKrYs r;rNzGenerativeSelect.for_updates+??FFrEc8t||||||_dS)aSpecify a ``FOR UPDATE`` clause for this :class:`_expression.GenerativeSelect`. E.g.:: stmt = select([table]).with_for_update(nowait=True) On a database like PostgreSQL or Oracle, the above would render a statement like:: SELECT table.a, table.b FROM table FOR UPDATE NOWAIT on other backends, the ``nowait`` option is ignored and instead would produce:: SELECT table.a, table.b FROM table FOR UPDATE When called with no arguments, the statement will render with the suffix ``FOR UPDATE``. Additional arguments can then be provided which allow for common database-specific variants. :param nowait: boolean; will render ``FOR UPDATE NOWAIT`` on Oracle and PostgreSQL dialects. :param read: boolean; will render ``LOCK IN SHARE MODE`` on MySQL, ``FOR SHARE`` on PostgreSQL. On PostgreSQL, when combined with ``nowait``, will render ``FOR SHARE NOWAIT``. :param of: SQL expression or list of SQL expression elements (typically :class:`_schema.Column` objects or a compatible expression) which will render into a ``FOR UPDATE OF`` clause; supported by PostgreSQL and Oracle. May render as a table or as a column depending on backend. :param skip_locked: boolean, will render ``FOR UPDATE SKIP LOCKED`` on Oracle and PostgreSQL dialects or ``FOR SHARE SKIP LOCKED`` if ``read=True`` is also specified. .. versionadded:: 1.1.0 :param key_share: boolean, will render ``FOR NO KEY UPDATE``, or if combined with ``read=True`` will render ``FOR KEY SHARE``, on the PostgreSQL dialect. .. versionadded:: 1.1.0 )r#r$r-r+r,N)r!rGr6s r;with_for_updatez GenerativeSelect.with_for_updates1t ,#    rEcd|_dS)aReturn a new selectable with the 'use_labels' flag set to True. This will result in column expressions being generated using labels against their table name, such as "SELECT somecolumn AS tablename_somecolumn". This allows selectables which contain multiple FROM clauses to produce a unique set of column names regardless of name conflicts among the individual FROM clauses. TN)rrJs r; apply_labelszGenerativeSelect.apply_labels? srEc,t|jdS)zGet an integer value for the limit. This should only be used by code that cannot support a limit as a BindParameter or other custom clause as it will throw an exception if the limit isn't currently set to an integer. rO)r_rIrJs r;_limitzGenerativeSelect._limitL s-T-?IIIrEc6t|jtS)zqTrue if the LIMIT clause is a simple integer, False if it is not present or is a SQL expression. )r2rIrGrJs r;_simple_int_limitz"GenerativeSelect._simple_int_limitV s $,.?@@@rEc6t|jtS)zrTrue if the OFFSET clause is a simple integer, False if it is not present or is a SQL expression. )r2rJrGrJs r;_simple_int_offsetz#GenerativeSelect._simple_int_offset] s $-/@AAArEc,t|jdS)zGet an integer value for the offset. This should only be used by code that cannot support an offset as a BindParameter or other custom clause as it will throw an exception if the offset isn't currently set to an integer. rP)r_rJrJs r;_offsetzGenerativeSelect._offsetd s-T-@(KKKrEc.t||_dS)a1Return a new selectable with the given LIMIT criterion applied. This is a numerical value which usually renders as a ``LIMIT`` expression in the resulting select. Backends that don't support ``LIMIT`` will attempt to provide similar functionality. .. versionchanged:: 1.0.0 - :meth:`_expression.Select.limit` can now accept arbitrary SQL expressions as well as integer values. :param limit: an integer LIMIT parameter, or a SQL expression that provides an integer result. N)rZrI)rKrOs r;rOzGenerativeSelect.limitn s$5U;;rEc.t||_dS)a8Return a new selectable with the given OFFSET criterion applied. This is a numeric value which usually renders as an ``OFFSET`` expression in the resulting select. Backends that don't support ``OFFSET`` will attempt to provide similar functionality. .. versionchanged:: 1.0.0 - :meth:`_expression.Select.offset` can now accept arbitrary SQL expressions as well as integer values. :param offset: an integer OFFSET parameter, or a SQL expression that provides an integer result. N)rZrJ)rKrPs r;rPzGenerativeSelect.offset s(6f==rEc|j|dS)aReturn a new selectable with the given list of ORDER BY criterion applied. e.g.:: stmt = select([table]).order_by(table.c.id, table.c.name) :param \*clauses: a series of :class:`_expression.ColumnElement` constructs which will be used to generate an ORDER BY clause. .. seealso:: :ref:`core_tutorial_ordering` N)append_order_byrKclausess r;rQzGenerativeSelect.order_by s& g&&&&rEc|j|dS)aReturn a new selectable with the given list of GROUP BY criterion applied. e.g.:: stmt = select([table.c.name, func.max(table.c.stat)]).\ group_by(table.c.name) :param \*clauses: a series of :class:`_expression.ColumnElement` constructs which will be used to generate an GROUP BY clause. .. seealso:: :ref:`core_tutorial_ordering` N)append_group_byres r;rRzGenerativeSelect.group_by s( g&&&&rEct|dkr|dt|_dSt|dd$t |jt |z}t|dt i|_dS)aAppend the given ORDER BY criterion applied to this selectable. The criterion will be appended to any pre-existing ORDER BY criterion. This is an **in-place** mutation method; the :meth:`_expression.GenerativeSelect.order_by` method is preferred, as it provides standard :term:`method chaining`. .. seealso:: :meth:`_expression.GenerativeSelect.order_by` rrNrLr)rr$rLrrrres r;rdz GenerativeSelect.append_order_by s w<<1  !3$.LLD ! ! !t/66Bt455W E$.%!G%%D ! ! !rEct|dkr|dt|_dSt|dd$t |jt |z}t|dt i|_dS)aAppend the given GROUP BY criterion applied to this selectable. The criterion will be appended to any pre-existing GROUP BY criterion. This is an **in-place** mutation method; the :meth:`_expression.GenerativeSelect.group_by` method is preferred, as it provides standard :term:`method chaining`. .. seealso:: :meth:`_expression.GenerativeSelect.group_by` rrNrMr)rr$rMrrrres r;rhz GenerativeSelect.append_group_by s w<<1  !3$.LLD ! ! !t/66Bt455W E$.%+F%%D ! ! !rEctr>)rrJs r;_label_resolve_dictz$GenerativeSelect._label_resolve_dict s!###rEc r|j||jfi||_|j||jfi||_dSdSr>)rIrJrIs r;rKz GenerativeSelect._copy_internals s\   )!&t'9!@!@R!@!@D    *"'%(;"B"Br"B"BD    + *rE)FFNNNNNNr7)rMrNrOrir$rLrMrIrJrGr'rPrNsetterr rVrXrZr\r^r`rOrPrQrRrdrhrlrrKrQrEr;rErEs<("z||!z||MNO ((((TXGGG   ? ? ? [? B  [ JJXJAAXA BBXB LLXL<<[<&>>[>*''['(''['*2.$$X$%+CCCCCCrErEceZdZdZdZejdZejdZejdZ ejdZ ejdZ ejdZ d Z d Zed Zed Zed ZedZedZedZedZdZddZdZdZdZeffd ZddZdZ dZ!ee e!Z xZ"S)raXForms the basis of ``UNION``, ``UNION ALL``, and other SELECT-based set operations. .. seealso:: :func:`_expression.union` :func:`_expression.union_all` :func:`_expression.intersect` :func:`_expression.intersect_all` :func:`_expression.except` :func:`_expression.except_all` compound_selectUNIONz UNION ALLEXCEPTz EXCEPT ALL INTERSECTz INTERSECT ALLTc D|dd|_||_g|_d}t |D]\}}t |}|st |jj}ntt |jj|krWtj ddt |jdjj|dzt |jjfz|j | |tj|fi|dS)NrFz}All selectables passed to CompoundSelect must have identical numbers of columns; select #%d has %d columns, select #%d has %drrr)rs_auto_correlatekeywordselects enumeraterrrrr*r7rr%rEr')rKrvrwrdnumcolsnrAs r;r'zCompoundSelect.__init__ s(%zz+u==  g&& < rpr9s r;r<z5CompoundSelect._label_resolve_dict..? s(,,!%,,,,,,rE)dictr)rKds r;rlz"CompoundSelect._label_resolve_dict= s+ ,,TV,,, , ,!QwrEc6ttjg|Ri|S)aReturn a ``UNION`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. A similar :func:`union()` method is available on all :class:`_expression.FromClause` subclasses. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )rrqr*rwrds r; _create_unionzCompoundSelect._create_unionB s%$n2GWGGGGGGrEc6ttjg|Ri|S)aReturn a ``UNION ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. A similar :func:`union_all()` method is available on all :class:`_expression.FromClause` subclasses. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )r UNION_ALLrs r;_create_union_allz CompoundSelect._create_union_allV s%$n6KKKKFKKKrEc6ttjg|Ri|S)a]Return an ``EXCEPT`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )rrrrs r;_create_exceptzCompoundSelect._create_exceptj s%n3HgHHHHHHrEc6ttjg|Ri|S)aaReturn an ``EXCEPT ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )r EXCEPT_ALLrs r;_create_except_allz!CompoundSelect._create_except_all{ s%n7L'LLLVLLLrEc6ttjg|Ri|S)a`Return an ``INTERSECT`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )rrsrs r;_create_intersectz CompoundSelect._create_intersect s%n6KKKKFKKKrEc6ttjg|Ri|S)adReturn an ``INTERSECT ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. )r INTERSECT_ALLrs r;_create_intersect_allz$CompoundSelect._create_intersect_all s%n:OWOOOOOOrEc@|jdSNr)rw _scalar_typerJs r;rzCompoundSelect._scalar_type s|A++---rENc t|Sr>r2r4s r;r%zCompoundSelect.self_group r6rEcJ|jD]}||rdSdSNTF)rwr)rKrrAs r;rzCompoundSelect.is_derived_from s:  A  ,, tt urEctd|jDD]f}|d||jr |djnd|jr |djnd}dt |D|_gdS)Nc&g|]}|jjSrQ)rr)r~rAs r;rz>CompoundSelect._populate_column_collection.. sAAAq!#*AAArEr)rXrcHg|]\}}|d|dzi Sr) _annotate)r~rrs r;rz>CompoundSelect._populate_column_collection.. s>39Aq Xq1u-..rE)ziprwrrr> _key_labelrx_proxies)rKrproxys r;rz*CompoundSelect._populate_column_collection sAADLAAAB  DG'''+@T!W^^D*./CDG&&t(E=Ft__ENN/  rEcp|jD]}|||jsdStd)NzUCompoundSelect constructs don't support addition of columns to underlying selectables)rwrr r)rKrrAs r;rz&CompoundSelect._refresh_for_new_column sQ . .A % %f - - - -# 4!    rEc Btt|jfi|fd|jD|_t |dr|`dD]8}t||&t||t||fi9dS)Nc"g|] }|fi SrQrQ)r~rArJrws r;rz2CompoundSelect._copy_internals.. s'===1a2===rE_col_map)rLrMrG) rrrKrrwrVrrsetattr)rKrJrwrrs `` r;rKzCompoundSelect._copy_internals s3nd##3E@@R@@@ ===== === 4 $ $    F FD tT"".dEE'$*=*=$D$D$D$DEEE  F FrEc z|rt|jpg|j|jgzt|jzSr>)rrrLrMrwrs r;rNzCompoundSelect.get_children sA  0DLL 6B$d&;< =4<   ! rEcP|jr|jS|jD]}|j}|r|cSdSr>)rKrwr)rKrAes r;rzCompoundSelect.bind sI : :   AA  4rEc||_dSr>rKrKrs r; _set_bindzCompoundSelect._set_bind  rEr>r)#rMrNrOrirjr,symbolrqrrrrrsrrr'rPrlrrrrrrrrr%rrrrrKrNrrrrs@r;rr s,('N DK E K((I T[ " "F\**J K((IDK00M222>XHH[H&LL[L&II[I MM[M LL[L PP[P ..."""" 8    %+ F F F F F F     8D) $ $DDDDDrErc eZdZdZdZdZdZejZ dZ dZ dZ dZ dZejZdZejdd  d6d Zed Z d7d Zd ZedZd8dZed8dZedZejdZedZedZ dZ!e"ffd Z#d9dZ$edZ%ej&dd9dZ'edZ(edZ)edZ*edZ+ed Z,ed!Z-ed"Z.d#Z/d$Z0d%Z1d&Z2d'Z3d(Z4ed)Z5d*Z6d+Z7d,Z8d:d-Z9d.Z:d/Z;d0Zd3Z?d4Z@d5ZAee@eAZ@xZBS);raz"Represents a ``SELECT`` statement.rBrQFNT)r<aGThe :paramref:`_expression.select.autocommit` parameter is deprecated and will be removed in a future release. Please refer to the :paramref:`.Connection.execution_options.autocommit` parameter in conjunction with the the :meth:`.Executable.execution_options` method in order to affect the autocommit behavior for a statement.)rSzThe :paramref:`_expression.select.for_update` parameter is deprecated and will be removed in a future release. Please refer to the :meth:`_expression.Select.with_for_update` to specify the structure of the ``FOR UPDATE`` clause.)r>rNc  ||_|dur/|durd|_n#dtj|D|_|6tjdtj|D|_ntj|_ t |} n?#t$r2} tjtj d| Yd} ~ nd} ~ wwxYw| rkg|_ |D]`} t| } t| tr | t j} |j | ang|_ |3t'|t j|_nd|_|3t'|t j|_nd|_|r|||r||t3j|fi| dS) aConstruct a new :class:`_expression.Select`. Similar functionality is also available via the :meth:`_expression.FromClause.select` method on any :class:`_expression.FromClause`. All arguments which accept :class:`_expression.ClauseElement` arguments also accept string arguments, which will be converted as appropriate into either :func:`_expression.text` or :func:`_expression.literal_column` constructs. .. seealso:: :ref:`coretutorial_selecting` - Core Tutorial description of :func:`_expression.select`. :param columns: A list of :class:`_expression.ColumnElement` or :class:`_expression.FromClause` objects which will form the columns clause of the resulting statement. For those objects that are instances of :class:`_expression.FromClause` (typically :class:`_schema.Table` or :class:`_expression.Alias` objects), the :attr:`_expression.FromClause.c` collection is extracted to form a collection of :class:`_expression.ColumnElement` objects. This parameter will also accept :class:`_expression.TextClause` constructs as given, as well as ORM-mapped classes. .. note:: The :paramref:`_expression.select.columns` parameter is not available in the method form of :func:`_expression.select`, e.g. :meth:`_expression.FromClause.select`. .. seealso:: :meth:`_expression.Select.column` :meth:`_expression.Select.with_only_columns` :param whereclause: A :class:`_expression.ClauseElement` expression which will be used to form the ``WHERE`` clause. It is typically preferable to add WHERE criterion to an existing :class:`_expression.Select` using method chaining with :meth:`_expression.Select.where`. .. seealso:: :meth:`_expression.Select.where` :param from_obj: A list of :class:`_expression.ClauseElement` objects which will be added to the ``FROM`` clause of the resulting statement. This is equivalent to calling :meth:`_expression.Select.select_from` using method chaining on an existing :class:`_expression.Select` object. .. seealso:: :meth:`_expression.Select.select_from` - full description of explicit FROM clause specification. :param autocommit: legacy autocommit parameter. :param bind=None: an :class:`_engine.Engine` or :class:`_engine.Connection` instance to which the resulting :class:`_expression.Select` object will be bound. The :class:`_expression.Select` object will otherwise automatically bind to whatever :class:`~.base.Connectable` instances can be located within its contained :class:`_expression.ClauseElement` members. :param correlate=True: indicates that this :class:`_expression.Select` object should have its contained :class:`_expression.FromClause` elements "correlated" to an enclosing :class:`_expression.Select` object. It is typically preferable to specify correlations on an existing :class:`_expression.Select` construct using :meth:`_expression.Select.correlate`. .. seealso:: :meth:`_expression.Select.correlate` - full description of correlation. :param distinct=False: when ``True``, applies a ``DISTINCT`` qualifier to the columns clause of the resulting statement. The boolean argument may also be a column expression or list of column expressions - this is a special calling form which is understood by the PostgreSQL dialect to render the ``DISTINCT ON ()`` syntax. ``distinct`` is also available on an existing :class:`_expression.Select` object via the :meth:`_expression.Select.distinct` method. .. seealso:: :meth:`_expression.Select.distinct` :param for_update=False: when ``True``, applies ``FOR UPDATE`` to the end of the resulting statement. ``for_update`` accepts various string values interpreted by specific backends, including: * ``"read"`` - on MySQL, translates to ``LOCK IN SHARE MODE``; on PostgreSQL, translates to ``FOR SHARE``. * ``"nowait"`` - on PostgreSQL and Oracle, translates to ``FOR UPDATE NOWAIT``. * ``"read_nowait"`` - on PostgreSQL, translates to ``FOR SHARE NOWAIT``. .. seealso:: :meth:`_expression.Select.with_for_update` - improved API for specifying the ``FOR UPDATE`` clause. :param group_by: a list of :class:`_expression.ClauseElement` objects which will comprise the ``GROUP BY`` clause of the resulting select. This parameter is typically specified more naturally using the :meth:`_expression.Select.group_by` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.group_by` :param having: a :class:`_expression.ClauseElement` that will comprise the ``HAVING`` clause of the resulting select when ``GROUP BY`` is used. This parameter is typically specified more naturally using the :meth:`_expression.Select.having` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.having` :param limit=None: a numerical value which usually renders as a ``LIMIT`` expression in the resulting select. Backends that don't support ``LIMIT`` will attempt to provide similar functionality. This parameter is typically specified more naturally using the :meth:`_expression.Select.limit` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.limit` :param offset=None: a numeric value which usually renders as an ``OFFSET`` expression in the resulting select. Backends that don't support ``OFFSET`` will attempt to provide similar functionality. This parameter is typically specified more naturally using the :meth:`_expression.Select.offset` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.offset` :param order_by: a scalar or list of :class:`_expression.ClauseElement` objects which will comprise the ``ORDER BY`` clause of the resulting select. This parameter is typically specified more naturally using the :meth:`_expression.Select.order_by` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.order_by` :param use_labels=False: when ``True``, the statement will be generated using labels for each column in the columns clause, which qualify each column with its parent table's (or aliases) name so that name conflicts between columns in different tables don't occur. The format of the label is ``_``. The "c" collection of the resulting :class:`_expression.Select` object will use these names as well for targeting column members. This parameter can also be specified on an existing :class:`_expression.Select` object using the :meth:`_expression.Select.apply_labels` method. .. seealso:: :meth:`_expression.Select.apply_labels` FTc,g|]}t|SrQrr~rs r;rz#Select.__init__.. s0"""022"""rENc34K|]}t|VdSr>r<rs r;r<z"Select.__init__.. s<--*+"1%%------rEzDcolumns argument to select() must be a Python list or other iterabler/r)ru _distinctr,r5 OrderedSet _from_objrf TypeErrorr6r*r7 _raw_columnsrr2r:r%rcomma_oprr_asbool _whereclause_havingrurrEr') rKrrrdistincthavingrrrrd cols_presentr:rs r;r'zSelect.__init__ sxn ) 5 4!%""!\(33"""  !_--/3|H/E/E---DNN"_..DN ==LL    K!9!$             # "D  , ,033a..A Y-? @@A!((++++  , !#D   " 0 = = H H!)!I!!D  !%D   +F33>>!)?DLL DL  +   * * *  +   * * *!$11&11111s B C&(CCcg}t}|j}tjt |j|jt |jnd|jD]q}||urtj d|r ||vr||}| |j s| || |j r|S)NrQz-select() construct refers to itself as a FROM)r _from_clonedrDrEr rrrr*InvalidRequestErrorrrrrC)rKfromsseen translateitems r;_fromsz Select._fromsK s uu% O 4, - , $+ , , , N    * *Dt||-C 'TY.. $$T%566 # T""" KK( ) ) ) ) rEcjttjdDrNjr9fdjDfdDjrjrfdDjfdDj rJrHtdkr5fdDtstj d zS) aReturn the full list of 'from' clauses to be displayed. Takes into account a set of existing froms which may be rendered in the FROM clause of enclosing selects; this Select may want to leave those absent if it is automatically correlating. c6g|]}t|jSrQ)rrrs r;rz-Select._get_display_froms..v s"KKKnQ];;KKKrEc3rK|]1}j||"j|V2dSr>)rr)r~rrKs r;r<z,Select._get_display_froms..} s[  (+BB1EE %a(      rEcg|]}|v| SrQrQ)r~rtoremoves r;rz-Select._get_display_froms.. s#;;;1():):Q):):):rEc Xg|]&}|ttpdv$|'SrQr)r~rexplicit_correlate_fromsr to_correlates r;rz-Select._get_display_froms.. s`   /,!#;#Ar% rENc bg|]+}|ttpdjv)|,Sr)rr_correlate_except)r~rrrrKs r;rz-Select._get_display_froms.. sc   )(7=2* rErc8g|]}|tv|SrQr)r~rrimplicit_correlate_fromss r;rz-Select._get_display_froms.. sI+E3KLLMMMMMrEzSelect statement '%s' returned no FROM clauses due to auto-correlation; specify correlate() to control correlation manually.) rrrDrErrCr _correlaterrurr*r)rKrrrrrs```@@@r;_get_display_fromszSelect._get_display_fromsh s  OKKUKKK L    <      %2243DEE   <;;;;;;E ? ?L       "     ! -         E   ( E QEu:: - #' ' rEc^|jd}t|j}|djSr)rrr!type)rKrrs r;rzSelect._scalar_type s+ #D)**Aw|rEc*|S)z1Return the displayed list of FromClause elements.)rrJs r;rz Select.froms s&&(((rE*c0|d||S)aAdd a statement hint to this :class:`_expression.Select`. This method is similar to :meth:`_expression.Select.with_hint` except that it does not require an individual table, and instead applies to the statement as a whole. Hints here are specific to the backend database and may include directives such as isolation levels, file directives, fetch directives, etc. .. versionadded:: 1.0.0 .. seealso:: :meth:`_expression.Select.with_hint` :meth:`.Select.prefix_with` - generic SELECT prefixing which also can suit some database-specific HINT syntaxes such as MySQL optimizer hints N) with_hint)rKtext dialect_names r;with_statement_hintzSelect.with_statement_hint s.~~dD,777rEcz||xj||ffz c_dS|j||f|i|_dS)aAdd an indexing or other executional context hint for the given selectable to this :class:`_expression.Select`. The text of the hint is rendered in the appropriate location for the database backend in use, relative to the given :class:`_schema.Table` or :class:`_expression.Alias` passed as the ``selectable`` argument. The dialect implementation typically uses Python string substitution syntax with the token ``%(name)s`` to render the name of the table or alias. E.g. when using Oracle, the following:: select([mytable]).\ with_hint(mytable, "index(%(name)s ix_mytable)") Would render SQL as:: select /*+ index(mytable ix_mytable) */ ... from mytable The ``dialect_name`` option will limit the rendering of a particular hint to a particular backend. Such as, to add hints for both Oracle and Sybase simultaneously:: select([mytable]).\ with_hint(mytable, "index(%(name)s ix_mytable)", 'oracle').\ with_hint(mytable, "WITH INDEX ix_mytable", 'sybase') .. seealso:: :meth:`_expression.Select.with_statement_hint` N)_statement_hints_hintsr)rKr4rrs r;rzSelect.with_hint sRF    ! !|T&:%< < ! ! ! !+++j,-G,NOODKKKrEc*tjd)NzvSelect objects don't have a type. Call as_scalar() on this Select object to return a 'scalar' version of this Select.r*rrJs r;rz Select.type s%    rEcB|j}|tt|zS)aReturn a Set of all :class:`_expression.FromClause` elements referenced by this Select. This set is a superset of that returned by the ``froms`` property, which is specifically for those FromClause elements that would actually be rendered. )rrr )rKrs r;locate_all_fromszSelect.locate_all_froms s# tM512222rEc*t|jS)zAn iterator of all :class:`_expression.ColumnElement` expressions which would be rendered into the columns clause of the resulting SELECT statement. )r rrJs r; inner_columnszSelect.inner_columns s!!2333rEc@tdt|jD}tdt|jD}|}|D]\}}||||||fS)Nc3RK|]"}|j |jp |jp|j|fV#dSr>)_allow_label_resolve_resolve_labelr>rr9s r;r<z-Select._label_resolve_dict..) sU  %   2 2QUA 6      rEc36K|]}|j |j|fVdSr>)rrr9s r;r<z-Select._label_resolve_dict... sE  % UAJ      rE)r}r rrr@items setdefault)rK with_cols only_froms only_colsrrYs r;rlzSelect._label_resolve_dict' s  &t'899       &tz22     NN$$ $**,, - -JC  e , , , ,*i//rEcz||jvrdS|D]}||rdSdSr)rrr)rKrrs r;rzSelect.is_derived_from9 sW :) ) )4&&((  A  ,, tt urEc tt|jfitfd|j|jDx|_tj fd|jD|_tfd|j D|j |_ |j r>tfd|j D|j |_ fd|j D|_ dD]8}t||&t||t||fi9|dS)Nc3.K|]}||fifVdSr>rQr~rrJrws r;r<z)Select._copy_internals..P sG/ / $%Qa2 / / / / / / rEc3(K|] }|V dSr>rQ)r~r from_cloneds r;r<z)Select._copy_internals..U s8) )  KN) ) ) ) ) ) rEc3*K|] }|fiVdSr>rQrs r;r<z)Select._copy_internals.._ s1FFeeAnnnnFFFFFFrEc3*K|] }|fiVdSr>rQrs r;r<z)Select._copy_internals..f sB))#$a2))))))rEc"g|] }|fi SrQrQ)r~rrJrws r;rz*Select._copy_internals..o s'GGGUU1^^^^GGGrE)rrrLrMrG)rrarKr}rrrrr,rrrrrrrr)rKrJrwrrrs `` @r;rKzSelect._copy_internalsB s+fd+E88R888+// / / / / )-)=)=dk)J)J/ / / + +  K ) ) ) ) $(N) ) )   FFFFFdoFFFFFLL O    ! ,%()))))(,(>)))&&eD*++  "HGGGGT5FGGG  F FDtT"".dEE'$*=*=$D$D$D$DEEE rEc |rt|jpg|jzt|jzd|j|j|j|jfDzS)z=Return child elements as per the ClauseElement specification.cg|]}||Sr>rQrs r;rz'Select.get_children.. s)    =!==rE)rrrrrrrLrMrs r;rNzSelect.get_children~ sy 6D$6$6 <" 4;   %L))      rEc0||dS)aReturn a new :func:`_expression.select` construct with the given column expression added to its columns clause. E.g.:: my_select = my_select.column(table.c.new_column) See the documentation for :meth:`_expression.Select.with_only_columns` for guidelines on adding /replacing the columns of a :class:`_expression.Select` object. N)r rs r;rz Select.column s 6"""""rErc ||j|jg|jft |jzRd|iS)aReturn a new :func:`_expression.select` construct with redundantly named, equivalently-valued columns removed from the columns clause. "Redundant" here means two columns where one refers to the other either based on foreign key, or via a simple equality comparison in the WHERE clause of the statement. The primary purpose of this method is to automatically construct a select statement with all uniquely-named columns, without the need to use table-qualified labels as :meth:`_expression.Select.apply_labels` does. When columns are omitted based on foreign key, the referred-to column is the one that's kept. When columns are omitted based on WHERE equivalence, the first column in the columns clause is the one that's kept. :param only_synonyms: when True, limit the removal of columns to those which have the same name as the equivalent. Otherwise, all columns that are equivalent to another are removed. only_synonyms)with_only_columnsrBrrrr)rKrrs r;rBzSelect.reduce_columns se.%% "G "" #%dn(=(==   +     rEc|g}|D][}t|}t|tr |t j}||\||_dS)av Return a new :func:`_expression.select` construct with its columns clause replaced with the given columns. This method is exactly equivalent to as if the original :func:`_expression.select` had been called with the given columns clause. I.e. a statement:: s = select([table1.c.a, table1.c.b]) s = s.with_only_columns([table1.c.b]) should be exactly equivalent to:: s = select([table1.c.b]) This means that FROM clauses which are only derived from the column list will be discarded if the new column list no longer contains that FROM:: >>> table1 = table('t1', column('a'), column('b')) >>> table2 = table('t2', column('a'), column('b')) >>> s1 = select([table1.c.a, table2.c.b]) >>> print(s1) SELECT t1.a, t2.b FROM t1, t2 >>> s2 = s1.with_only_columns([table2.c.b]) >>> print(s2) SELECT t2.b FROM t1 The preferred way to maintain a specific FROM clause in the construct, assuming it won't be represented anywhere else (i.e. not in the WHERE clause, etc.) is to set it using :meth:`_expression.Select.select_from`:: >>> s1 = select([table1.c.a, table2.c.b]).\ ... select_from(table1.join(table2, ... table1.c.a==table2.c.a)) >>> s2 = s1.with_only_columns([table2.c.b]) >>> print(s2) SELECT t2.b FROM t1 JOIN t2 ON t1.a=t2.a Care should also be taken to use the correct set of column objects passed to :meth:`_expression.Select.with_only_columns`. Since the method is essentially equivalent to calling the :func:`_expression.select` construct in the first place with the given columns, the columns passed to :meth:`_expression.Select.with_only_columns` should usually be a subset of those which were passed to the :func:`_expression.select` construct, not those which are available from the ``.c`` collection of that :func:`_expression.select`. That is:: s = select([table1.c.a, table1.c.b]).select_from(table1) s = s.with_only_columns([table1.c.b]) and **not**:: # usually incorrect s = s.with_only_columns([s.c.b]) The latter would produce the SQL:: SELECT b FROM (SELECT t1.a AS a, t1.b AS b FROM t1), t1 Since the :func:`_expression.select` construct is essentially being asked to select both from ``table1`` as well as itself. rN) rrr2r:r%rrrr)rKrrcrs r;rzSelect.with_only_columns sL    A,Q//A!\** =LL);L<< IIaLLLLrEc0||dS)zReturn a new :func:`_expression.select` construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. N)append_whereclauserKrs r;wherez Select.wheres  ,,,,,rEc0||dS)zReturn a new :func:`_expression.select` construct with the given expression added to its HAVING clause, joined to the existing clause via AND, if any. N) append_havingrKrs r;rz Select.havings 6"""""rEc|r@d|D}t|jtr|j|z|_dS||_dSd|_dS)aReturn a new :func:`_expression.select` construct which will apply DISTINCT to its columns clause. :param \*expr: optional column expressions. When present, the PostgreSQL dialect will render a ``DISTINCT ON (>)`` construct. c,g|]}t|SrQrrs r;rz#Select.distinct...s!AAAq/22AAArETN)r2rr)rKrns r;rzSelect.distinct#s[  "AADAAAD$.$// &!%$!6!%!DNNNrEc0||dS)a Return a new :func:`_expression.select` construct with the given FROM expression(s) merged into its list of FROM objects. E.g.:: table1 = table('t1', column('a')) table2 = table('t2', column('b')) s = select([table1.c.a]).\ select_from( table1.join(table2, table1.c.a==table2.c.b) ) The "from" list is a unique set on the identity of each element, so adding an already present :class:`_schema.Table` or other selectable will have no effect. Passing a :class:`_expression.Join` that refers to an already present :class:`_schema.Table` or other selectable will have the effect of concealing the presence of that selectable as an individual element in the rendered FROM list, instead rendering it into a JOIN clause. While the typical purpose of :meth:`_expression.Select.select_from` is to replace the default, derived FROM clause with a join, it can also be called with individual table elements, multiple times if desired, in the case that the FROM clause cannot be fully derived from the columns clause:: select([func.count('*')]).select_from(table1) N) append_fromrs r; select_fromzSelect.select_from6sF $$$$$rEcd|_|r|d d|_dSt|jd|D|_dS)aUReturn a new :class:`_expression.Select` which will correlate the given FROM clauses to that of an enclosing :class:`_expression.Select`. Calling this method turns off the :class:`_expression.Select` object's default behavior of "auto-correlation". Normally, FROM elements which appear in a :class:`_expression.Select` that encloses this one via its :term:`WHERE clause`, ORDER BY, HAVING or :term:`columns clause` will be omitted from this :class:`_expression.Select` object's :term:`FROM clause`. Setting an explicit correlation collection using the :meth:`_expression.Select.correlate` method provides a fixed list of FROM objects that can potentially take place in this process. When :meth:`_expression.Select.correlate` is used to apply specific FROM clauses for correlation, the FROM elements become candidates for correlation regardless of how deeply nested this :class:`_expression.Select` object is, relative to an enclosing :class:`_expression.Select` which refers to the same FROM object. This is in contrast to the behavior of "auto-correlation" which only correlates to an immediate enclosing :class:`_expression.Select`. Multi-level correlation ensures that the link between enclosed and enclosing :class:`_expression.Select` is always via at least one WHERE/ORDER BY/HAVING/columns clause in order for correlation to take place. If ``None`` is passed, the :class:`_expression.Select` object will correlate none of its FROM entries, and all will render unconditionally in the local FROM clause. :param \*fromclauses: a list of one or more :class:`_expression.FromClause` constructs, or other compatible constructs (i.e. ORM-mapped classes) to become part of the correlate collection. .. seealso:: :meth:`_expression.Select.correlate_except` :ref:`correlated_subqueries` FrNrQc34K|]}t|VdSr>rrs r;r<z#Select.correlate..s<99*+"1%%999999rE)rurrrrK fromclausess r;rzSelect.correlate[sjj %  ;q>1 DOOO!$/228899/:999DOOOrEcd|_|r|d d|_dSt|jpdd|D|_dS)aReturn a new :class:`_expression.Select` which will omit the given FROM clauses from the auto-correlation process. Calling :meth:`_expression.Select.correlate_except` turns off the :class:`_expression.Select` object's default behavior of "auto-correlation" for the given FROM elements. An element specified here will unconditionally appear in the FROM list, while all other FROM elements remain subject to normal auto-correlation behaviors. If ``None`` is passed, the :class:`_expression.Select` object will correlate all of its FROM entries. :param \*fromclauses: a list of one or more :class:`_expression.FromClause` constructs, or other compatible constructs (i.e. ORM-mapped classes) to become part of the correlate-exception collection. .. seealso:: :meth:`_expression.Select.correlate` :ref:`correlated_subqueries` FrNrQc34K|]}t|VdSr>rrs r;r<z*Select.correlate_except..sDMM*+"1%%MMMMMMrE)rurrrrs r;correlate_exceptzSelect.correlate_exceptsz< %  ;q>1%'D " " "%()?)E2%F%F%L%LMM/:MMM&&D " " "rEcd|_t|jd|D|_dS)aAppend the given correlation expression to this :func:`_expression.select` construct. This is an **in-place** mutation method; the :meth:`_expression.Select.correlate` method is preferred, as it provides standard :term:`method chaining`. Fc34K|]}t|VdSr>rrs r;r<z,Select.append_correlation..s<5 5 &' q ! !5 5 5 5 5 5 rEN)rurrrrs r;append_correlationzSelect.append_correlationsM %do..445 5 +55 5 5   rEc|t|}t|tr |t j}|j|gz|_dS)a-Append the given column expression to the columns clause of this :func:`_expression.select` construct. E.g.:: my_select.append_column(some_table.c.new_column) This is an **in-place** mutation method; the :meth:`_expression.Select.column` method is preferred, as it provides standard :term:`method chaining`. See the documentation for :meth:`_expression.Select.with_only_columns` for guidelines on adding /replacing the columns of a :class:`_expression.Select` object. rN)rrr2r:r%rrrrs r;r zSelect.append_columnsg" -f55 fl + + C&&y/A&BBF -8rEcDt|}|j|fz|_dS)a$Append the given columns clause prefix expression to this :func:`_expression.select` construct. This is an **in-place** mutation method; the :meth:`_expression.Select.prefix_with` method is preferred, as it provides standard :term:`method chaining`. N)rr)rKr]s r; append_prefixzSelect.append_prefixs%"&))6)3rEc|ttj|j||_dS)afAppend the given expression to this :func:`_expression.select` construct's WHERE criterion. The expression will be joined to existing WHERE criterion via AND. This is an **in-place** mutation method; the :meth:`_expression.Select.where` method is preferred, as it provides standard :term:`method chaining`. N)rr!r'_ifnonerrs r;rzSelect.append_whereclauses;  t/@!A!A;OOrEc|ttj|j||_dS)aiAppend the given expression to this :func:`_expression.select` construct's HAVING criterion. The expression will be joined to existing HAVING criterion via AND. This is an **in-place** mutation method; the :meth:`_expression.Select.having` method is preferred, as it provides standard :term:`method chaining`. N)rr!r'rrrs r;rzSelect.append_havings7 EM$,77@@ rEc|t|}|j|g|_dS)a'Append the given FromClause expression to this :func:`_expression.select` construct's FROM clause. This is an **in-place** mutation method; the :meth:`_expression.Select.select_from` method is preferred, as it provides standard :term:`method chaining`. N)rr<rrrs r;r zSelect.append_froms@ ' 33 --zl;;rEc|jrEtfdfdtjt |jDSdtjt |jDS)Nc|j|jsd|fS|j}|vr|j}n|||fSr>)r>_render_label_in_columns_clause anon_labelr)rrXnamess r; name_for_colz0Select._columns_plus_names..name_for_col!sN8#1+L# !9$x5==.,s1 QrEcg|]}d|fSr>rQr9s r;rz.Select._columns_plus_names..1s,q rE)rrr, unique_listr r)rKr#r"s @@r;_columns_plus_nameszSelect._columns_plus_namess ? EEE     )*;D)rKrrr our_labels r;rzSelect._refresh_for_new_columnDs+  J44V<)rIrJrfrLrfrJs r;rz!Select._needs_parens_for_groupingTs8  d * 3"$. 3D)122 rEcvt|tr|s|St|S)a@Return a 'grouping' construct as per the :class:`_expression.ClauseElement` specification. This produces an element that can be embedded in an expression. Note that this method is called automatically as needed when constructing expressions and should not require explicit use. )r2rrr3r4s r;r%zSelect.self_group[s? w / / 3355 KD!!!rEc (tj||fi|S)zaReturn a SQL ``UNION`` of this select() construct against the given selectable. )rrrKrrds r;rz Select.unionks +D%BB6BBBrEc (tj||fi|S)zeReturn a SQL ``UNION ALL`` of this select() construct against the given selectable. )rrr/s r;rzSelect.union_allr /eFFvFFFrEc (tj||fi|S)zbReturn a SQL ``EXCEPT`` of this select() construct against the given selectable. )rrr/s r;except_zSelect.except_ys ,T5CCFCCCrEc (tj||fi|S)zfReturn a SQL ``EXCEPT ALL`` of this select() construct against the given selectable. )rrr/s r; except_allzSelect.except_alls 0uGGGGGrEc (tj||fi|S)zeReturn a SQL ``INTERSECT`` of this select() construct against the given selectable. )rrr/s r;rzSelect.intersectr1rEc (tj||fi|S)ziReturn a SQL ``INTERSECT ALL`` of this select() construct against the given selectable. )rrr/s r; intersect_allzSelect.intersect_alls 3D%JJ6JJJrEc|jr|jS|j}|s|jD]}|j}|r ||_|cSn%t |dj}|r ||_|SdSr)rKrrrr)rKrrrs r;rz Select.binds : :   &  F!"DJHHH  U A#A  trEc||_dSr>rrs r;rzSelect._set_bindrrE)NNNFNTNNr)rrr>)CrMrNrOrirjrrr, immutabledictrrrrrrrArrrr'rPrrrrrr rrmethodrrrlrrrKrNrr rBrrrrr rrrr rrrr r'rrrr%rrr3r5rr8rrrrs@r;rara s,,NII T  ! !FILJ#6JT   ,]2]2]2)(]2~X:GKRRRRh ))X) 88882%P%P%P[%PN  X  3 3 344X4000"%+::::::x    &##[# T,--   .- <LL[L\--[-##[#""["$"%"%["%H::[:x##[#J    9992 4 4 4 P P P A A A < < <2 N N N    """" CCCGGGDDDHHHGGGKKK$ 8D) $ $DDDDDrEracVeZdZgZdZdZdZedZeZ e dZ dZ dS)r:TFcF||_||_dSr>)r8rrrs r;r'zScalarSelect.__init__s  ((** rEc*tjd)NzcScalar Select expression has no columns; use this object directly within a column-level expression.rrJs r;rzScalarSelect.columnss% 0   rEcD|j||_dS)zuApply a WHERE clause to the SELECT statement referred to by this :class:`_expression.ScalarSelect`. N)r8r)rKrds r;rzScalarSelect.wheres |))$// rEc |Sr>rQrMs r;r%zScalarSelect.self_groups rEN) rMrNrOr r_is_implicitly_booleanr'rPrrr rr%rQrEr;r:r:s~M"+++  X  A00[0rEr:cJeZdZdZejZgZdZd dZdZ dZ dZ dZ dS) ExistszRepresent an ``EXISTS`` clause.c@|r+t|dttfr |d}nC|stdgf}t |i|}tj||tj tj ddS)a\Construct a new :class:`_expression.Exists` against an existing :class:`_expression.Select` object. Calling styles are of the following forms:: # use on an existing select() s = select([table.c.col1]).where(table.c.col2==5) s_e = exists(s) # an exists is usually used in a where of another select # to produce a WHERE EXISTS (SELECT ... ) select([table.c.col1]).where(s_e) # but can also be used in a select to produce a # SELECT EXISTS (SELECT ... ) query select([s_e]) # construct a select() at once exists(['*'], **select_arguments).where(criterion) # columns argument is optional, generates "EXISTS (SELECT *)" # by default. exists().where(table.c.col2==5) rrT)rrTwraps_column_expressionN) r2rAr:r&rarr%r(r'rexistsr BOOLEANTYPE)rKrcrdrAs r;r'zExists.__init__s4  AJtAw\(BCC AQAA 0',,-/'''1133>>@@A  %&$(       rENc t|g|fi|Sr>rrs r;rBz Exists.selectstfk44V444rEcz|}|jj||_|Sr>)rr8rr%rKrrs r;rzExists.correlates3 KKMM*DL*J7BBDD rEcz|}|jj||_|Sr>)rr8rr%rKs r;rzExists.correlate_excepts3 KKMM1DL1:>IIKK rEc|}|j||_|S)zReturn a new :class:`_expression.Exists` construct, applying the given expression to the :meth:`_expression.Select.select_from` method of the select statement contained. )rr8r r%rKr]rs r;r zExists.select_froms9 KKMML,,V44??AA rEc|}|j||_|S)zReturn a new :func:`_expression.exists` construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. )rr8rr%rNs r;rz Exists.wheres9 KKMML&&v..99;; rEr>) rMrNrOrir(rjr r'rBrrr rrQrEr;rDrDs))$3NM' ' ' R5555    rErDcdeZdZdZdZdZd dZedZe dZ dZ e fd Z d Zd S) TextAsFromadWrap a :class:`_expression.TextClause` construct within a :class:`_expression.SelectBase` interface. This allows the :class:`_expression.TextClause` object to gain a ``.c`` collection and other FROM-like capabilities such as :meth:`_expression.FromClause.alias`, :meth:`_expression.SelectBase.cte`, etc. The :class:`.TextAsFrom` construct is produced via the :meth:`_expression.TextClause.columns` method - see that method for details. .. versionadded:: 0.9.0 .. seealso:: :func:`_expression.text` :meth:`_expression.TextClause.columns` text_as_fromTFc0||_||_||_dSr>)r8 column_args positional)rKrrrUs r;r'zTextAsFrom.__init__<s "$rEc|jjSr>)r8rKrJs r;rKzTextAsFrom._bindAs |!!rEc4|jj|i||_dSr>)r8 bindparams)rKbindsbind_as_valuess r;rXzTextAsFrom.bindparamsEs!.t|.HHH rEcD|jD]}||dSr>)rTr)rKrs r;rz&TextAsFrom._populate_column_collectionIs3!  A MM$      rEc T|||jfi||_dSr>)rr8rIs r;rKzTextAsFrom._copy_internalsMs3 uT\00R00 rEc&|jdjSr)rTrrJs r;rzTextAsFrom._scalar_typeQs"''rENr)rMrNrOrirjrr'rPrKr rXrrrKrrQrEr;rQrQs0$NH%%%% ""X"II[I   %+1111(((((rErQceZdZdZdS)AnnotatedFromClausec@|jtj|||dSr>)rrr')rKr8r^s r;r'zAnnotatedFromClause.__init__Vs&  4&11111rEN)rMrNrOr'rQrEr;r_r_Us#22222rEr_r)IrirwrDrrsqlalchemy.sql.visitorsrrVrr annotationrbaser r r r r rrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r*r+r,r<rDrGrZr_rergobjectrmrrrr?rrrrr3rr!rArErrar:rDrQr_rQrEr;resZ ------!!!!!!""""""&&&&&&------((((((******------$$$$$$222222<<<<<<111111&&&&&&''''''''''''############ $$$$$$%%%%%%    $$$$$ $$$ HHHH$!!!0 0 0 0        1 1 1 1 1 &1 1 1 h, , , , , &, , , ^]]]]]]]]@K K K K K :K K K \q!q!q!q!q!Jq!q!q!h+A+A+A+A+Ae+A+A+A\L8L8L8L8L8%L8L8L8^d d d d d *k;d d d NnDnDnDnDnDVnDnDnDb2(2(2(2(2(:2(2(2(jbbbbb)ZbbbJZZZZZ=ZZZzAAAAAZAAAHOCOCOCOCOCzOCOCOCd G%G%G%G%G%%G%G%G%Tb%b%b%b%b%[+'7b%b%b%J%:x>PPPPP_PPPf3(3(3(3(3(3(3(3(l22222)22222rEPK!55.__pycache__/default_comparator.cpython-311.pycnu[ |oi/XdZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd lm Z dd lm Z dd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZdd ej e!fdfd!Z"dSd"Z#dSd#Z$d$Z%d%Z&d&Z'd'Z(d(Z)d)Z*d*Z+d+Z,d,Z-d-Z.d.Z/id/e%fd0e%fd1e*fd2e$fd3e$fd4e$fd5e$fd6e$fd7e$fd8e#fd9e$fd:e$fd;e$fde"ej2fd?e"ej3fid@e"ej4fdAe"ej5fdBe"ej6fdCe"ej7fdDe"ej8fdEe"ej9fdFe"ej:fdGe"ej;fdHe"ej<fdIe"ej=fdJe"ej>fdKe"ej?fdLe"ej@fdMe&ejAfdNe&ejBfdOe&ejCfdPe&ejDfe'ejEfe'ejFfe"ejGfe"ejHfe/fe,fe,fe-fe.fe.fe+fe(fe)fe)fe)fdQZIdTdRZJdS)Uz5Default implementation of SQL comparison operations. ) operators)type_api)_clause_element_as_expr) _const_expr) _is_literal)_literal_as_text)and_)BinaryExpression) BindParameter) ClauseElement) ClauseListcollate)CollectionAggregate) ColumnElement)False_)Null)or_) TextClause)True_)Tuple)UnaryExpression) Visitable)Alias) ScalarSelect) Selectable) SelectBase)exc)utilNFc || tj}t||ttt fzrL|t jt jfvrDt|ttt fr"t|t|||||S|t j t j fvr"t|t|||||S|t jt jfvr5t|t|t jt j|S|t jt jfvr5t|t|t jt j|St#jdt'|||}|rt||||||St||||||S)N)type_negate modifiers)r#r"z|Only '=', '!=', 'is_()', 'isnot()', 'is_distinct_from()', 'isnot_distinct_from()' operators can be used with None/True/False)r BOOLEANTYPE isinstancerrrreqneboolr ris_distinct_fromisnot_distinct_fromis_risnotr ArgumentError_check_literal)expropobjr#reverse_python_is_types result_typekwargss X/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/default_comparator.py_boolean_comparer8)s* #'4*??@@2, ), - - -* $v&3 3 -$ %%!  I. 0MN N N# %%!  ilIM222'$$M$?%  io666'$$O$=% 'A T2s++  rVv     #rVv    c n|"|jr|j}n|jr tj}t |||f||d|S)N)r3r5) return_type is_comparisonrr%_binary_operate)r0r1r2r3r5kws r7_custom_op_operater?us^ > /.KK   /".K  b# &K  CE  r9c t|||}|r||}}n||}}|#|j||j\}}t|||||S)N)r"r$)r/ comparator_adapt_expressionr )r0r1r2r3r5r>leftrights r7r=r=ss r3 ' 'C 4eCe/;;    K D%;" M M MMr9c |tjurt||S|tjurt||StN)rr rNotImplementedErrorr0r1otherr>s r7_conjunction_operaterJsH Y^D%   y}  4!###r9c ||SrF)r0r1fnr>s r7_scalarrNs 2d88Or9c t|}t|trt||||St|tr#t|||fd|i|St|t tfrt|||fd|i|St|trzt|trN|j rGt|tr| d|D}t||||Stjd|zg}|D]}t|s2t|t jstjd|zn'|t%}n|||}||t+|dkrA|t jurt jt jfnt jt jf\}}t||t3|dt|ti||S)N)r#r#cg|] }|j SrL)type).0elems r7 z_in_impl..s0004TY000r9z_in_() accepts either a list of expressions, a selectable, or an "expanding" bound parameter: %r _tuple_values)against)rr&rr8r as_scalarrrr r expandingr_with_expanding_in_typesrInvalidRequestErrorrrColumnOperatorsr _bind_paramappendlenin_op empty_in_opempty_notin_opr self_group)r0r1seq_or_selectable negate_opr>argsos r7_in_implrhs/0ABB#\22$b*;INNNN %z 2 2" "'1133  s r7rkrks >L  r9c Xt|dr|jS|S)z%See :meth:`.ColumnOperators.__inv__`.negation_clause)hasattrrq_negater0r1r>s r7 _inv_implrus,t&''##||~~r9c Dt|tj|jS)z%See :meth:`.ColumnOperators.__neg__`.operatorr")rrnegrQrts r7 _neg_implrzs 4)-ty I I IIr9c t|tjt|tj|ftj|tjur tjn tjd|S)z#See :meth:`.ColumnOperators.match`.)r5r#)r8rmatch_opr/r MATCHTYPE notmatch_oprHs r7 _match_implrsl  tY/77 & # # #$$        r9c Dt|tj|jS)z&See :meth:`.ColumnOperators.distinct`.rw)rr distinct_oprQrts r7_distinct_implrs%  y,DI   r9c t|tt|tj|t|tj|tjdd||tjur tjn tj|S)z%See :meth:`.ColumnOperators.between`.F)rxgroupgroup_contents)r#r$)r r r/rr between_op notbetween_op)r0r1cleftcrightr>s r7 _between_implrs   4 7 7 4 8 8^     % % %&&  !   r9c "t||SrFrrHs r7 _collate_implr,s 4  r9r rinvaddmulsubdivmodtruediv custom_opjson_path_getitem_opjson_getitem_op concat_opany_opall_opltler(gtger'r*r+like_opilike_op notlike_op notilike_op contains_op startswith_op endswith_opdesc_opasc_op nullsfirst_op nullslast_op)r`notin_opr,r-rr|r~rrrrygetitemlshiftrshiftcontainsct|ttfrCt|tr,|jjr |}|j|_|St|dr|}n&t|tj j r|j }t|ttfr|St|t s||||S|S)N__clause_element__)r")r&rrr rQ_isnull_clonerrrr TypeEngine Comparatorr0rrrXrr])r0rxrIbindparam_types r7r/r/gs%-455 e] + + # 0B #LLNNEEJ , - -((** E8.9 : : %*e,--   y ) )%~FFF r9)FNrF)K__doc__rrelementsrrrrr r r r r rrrrrrrrrrr selectablerrrrrr NoneTyper)r8r?r=rJrNrhrlrkrurzrrrr _create_any _create_allrrr'rrr(r+r*rrrrnotcontains_opnotstartswith_opnotendswith_op _create_desc _create_asc_create_nullsfirst_create_nullslastrr`r,r-operator_lookupr/rLr9r7rs0------!!!!!!!!!!!!&&&&&&&&&&&&############ ))))))###### %%%%%%$$$$$$""""""""""""  mT*I I I I X     N N N N $$$GGGT111 JJJ   &   2 ! #2 "2 I<2 O  2  O  2  O  2 O 2 O 2!2$&2_.2)2/#2 w+782 w+782  Y\ *!2" Y\ *#22$ Y\ *%2& Y\ *'2( Y\ *)2* Y\ *+2,)9+HI-2.,i.HI/20 )"67122!9#89324#Y%67526$i&89728$i&>?92:& (BC;2<$i&>?=2>56?2@ w34A2BgABC2DWo?@E22F * +9?+ im ,  0>"$ "#% < " ""$c222jr9PK!dz1##"__pycache__/naming.cpython-311.pycnu[ |oi dZddlZddlmZddlmZddlmZddlmZddlmZdd lm Z dd lm Z dd lm Z dd lm Z dd lm Z ddlmZddlmZddlmZGddeZe de dede de diZdZdZeje ddZejedeje ddZdS)z5Establish constraint and index naming conventions. N) _NONE_NAME)conv)CheckConstraint)Column) Constraint)ForeignKeyConstraint)Index)PrimaryKeyConstraint)Table)UniqueConstraint)event)events)exccJeZdZdZdZdZdZdZdZdZ dZ d Z d Z d S) ConventionDictc|||_t|t|_||_||_|j|_dSN)const isinstancer _is_fktable conventionname _const_name)selfrrrs L/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/naming.py__init__zConventionDict.__init__s9  (<==  $ :c|jjSr)rrrs r_key_table_namezConventionDict._key_table_name&s zr c|jr9 |jj|}t|j|S#t $rYdSwxYwt |jj} ||}t||S#t $rYdSwxYw)N)rrelementsgetattrparent IndexErrorlistcolumns)ridxattrnamefkcolscols r _column_XzConventionDict._column_X)s ; . 4Z(-ry(333   rr   *++D .3isH---   rr s0 >>A33 BBc|jdtfvrtjdt |jt s d|j_|jS)NzcNaming convention including %(constraint_name)s token requires that constraint is explicitly named.)rrrInvalidRequestErrorrrrrr"s r_key_constraint_namez#ConventionDict._key_constraint_name:sX  j1 1 1)2  $*D11 #"DJOr c.||dS)Nkeyr1rr,s r_key_column_X_keyz ConventionDict._key_column_X_keyEs~~c5)))r c.||dS)Nrr7r8s r_key_column_X_namez!ConventionDict._key_column_X_nameKs~~c6***r c.||dS)N _ddl_labelr7r8s r_key_column_X_labelz"ConventionDict._key_column_X_labelNs~~c<000r c|jjd}|jd}t |dkr|\}}}n|\}}|S)Nr.)rr&target_fullnamesplitlen)rr.refs refschemareftablerefcols r_key_referred_table_namez'ConventionDict._key_referred_table_nameQsS Z  #!'',, t99>>*. 'Ix# Hfr c>|jj|}|jjSr)rr&columnr)rr,r.s r_key_referred_column_X_namez*ConventionDict._key_referred_column_X_nameZs Z  %y~r c||jvr!|j||j|jSt|d|zrt |d|zSt jd|}|rU|d}|d}|r|jr |jj }nt|jj }g}t|D]k\}}d| d|zdz} |t |||O#t$rt!|wxYw|drdnd } | |Sd| |dz}t'|}t||rt |||St!|) Nz_key_%sz.*_?column_(\d+)(_?N)?_.+rr_key_0X_r%)rrrhasattrr'rematchgrouprr&r*r+ enumeratereplaceappendAttributeErrorKeyError startswithjoinint) rr6 col_templater, multipleselemstokenselemattrseps r __getitem__zConventionDict.__getitem__as $/ ! !'4?3' DJ?? ? T9s? + + 8174S1133 38$@#FFL 8"((++(..q11 8{9 $ 3 $TZ%7 8 8F%.u%5%500 T&S9_c)J)JJ0"MM*='$*=*=c*B*BCCCC-000"*3--/0!*!5!5c!:!:B##C88F+++"S[[c%:%::Dc((CtT**82wtT223777smms =,D**EN) __name__ __module__ __qualname__rr#r1r4r9r;r>rIrLrer rrrs&&&..."    *** +++111r rixpkckuqr.c|jD]=}|tvr$t||vr|t|cS||vr ||cS>dSr)__mro__ _prefix_dict)dict_r6super_s r_get_conventionrssh+ \ ! !l6&:e&C&Cf-. . . . u__= tr cf|j}t|jt|}t |jt r|jS|Yt |jt s?|jd|vs|jtur&t |t|||jzS|turdSdS)Nconstraint_name) metadatarsnaming_conventiontyperrrrr)rrrvrs r_constraint_name_for_tablerys~H !;T%[[IIJ%*d##z5:t,,  J  J..zZ'' UE8+EFF G    z ! !t " !r '_sa_event_column_added_to_pk_constraintcj|jr)|j}d|_t||}|r ||_dSdSdSr)_implicit_generatedrrry) pk_constraintr0rnewnames r_column_added_to_pk_constraintrsZ( ) #! ,]EBB  )!(M    ) ) ) )r after_parent_attachc t|trtj|dfddSt|trEtjt sjturdSt|}|r |_dSdSdS)Nrc$t|Sr)_constraint_name)r0rrs rz"_constraint_name..s/u==r ) rrrlistenr rrrry)rrr~s` rrrs%  !   ! = = = =     E5 ! !! ej$ ' ' 5:+C+C F,UE::  ! EJJJ !!  ! !r )__doc__rSr&rrschemarrrr r r r r r%rrrobjectrrprsry listens_forrrrir rrs  ######(((((((((((($$$$$$aaaaaVaaaJ 4$Td$  .C ) ) ):4555/00!!1065!!!r PK!>W__pycache__/ddl.cpython-311.pycnu[ |oiӢdZddlmZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd l m Z Gd d eZ Gddee ZGddeZGddeZGddeZGddeZGddeZGddeZGdde ZGddeZGd d!eZGd"d#eZGd$d%eZGd&d'eZGd(d)eZGd*d+eZGd,d-eZGd.d/eZGd0d1eZGd2d3eZ Gd4d5eZ!Gd6d7e!Z"Gd8d9e!Z# d>d;Z$ d?d=Z%d:S)@zq Provides the hierarchy of DDL-defining schema items as well as routines to invoke them for a create/drop call. )_bind_or_error) _generative) Executable) SchemaVisitor) ClauseElement)event)exc)util) topologicalceZdZdZdS) _DDLCompilesc |j||fi|S)zNReturn a compiler appropriate for this ClauseElement, given a Dialect.) ddl_compiler)selfdialectkws I/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/ddl.py _compilerz_DDLCompiles._compilers!$w#GT88R888N)__name__ __module__ __qualname__rrrrrs#99999rrc eZdZdZejddiZdZdZdZ dZ dZ ddZ e jddd Zed Zedd Zd Zd ZdZdZdZdZeeeZdZdS) DDLElementaBase class for DDL expression constructs. This class is the base for the general purpose :class:`.DDL` class, as well as the various create/drop clause constructs such as :class:`.CreateTable`, :class:`.DropTable`, :class:`.AddConstraint`, etc. :class:`.DDLElement` integrates closely with SQLAlchemy events, introduced in :ref:`event_toplevel`. An instance of one is itself an event receiving callable:: event.listen( users, 'after_create', AddConstraint(constraint).execute_if(dialect='postgresql') ) .. seealso:: :class:`.DDL` :class:`.DDLEvents` :ref:`event_toplevel` :ref:`schema_ddl_sequences` autocommitTNc0||||SN) _execute_ddl)r connection multiparamsparamss r_execute_on_connectionz!DDLElement._execute_on_connectionGs&&t[&AAArc|t|}|||r(|||S|jjddS)a1Execute this DDL immediately. Executes the DDL statement in isolation using the supplied :class:`.Connectable` or :class:`.Connectable` assigned to the ``.bind`` property, if not supplied. If the DDL has a conditional ``on`` criteria, it will be invoked with None as the event. :param bind: Optional, an ``Engine`` or ``Connection``. If not supplied, a valid :class:`.Connectable` must be present in the ``.bind`` property. :param target: Optional, defaults to None. The target :class:`_schema.SchemaItem` for the execute call. Will be passed to the ``on`` callable if any, and may also provide string expansion data for the statement. See ``execute_at`` for more information. Nz(DDL execution skipped, criteria not met.)r_should_executeexecuteagainstengineloggerinfo)rbindtargets rr'zDDLElement.executeJsm, <!$''D    - - P<< V 4 455 5 K  # #$N O O O O Or0.7zThe :meth:`.DDLElement.execute_at` method is deprecated and will be removed in a future release. Please use the :class:`.DDLEvents` listener interface in conjunction with the :meth:`.DDLElement.execute_if` method.cpfd}tj|dddz|dS)a_Link execution of this DDL to the DDL lifecycle of a SchemaItem. Links this ``DDLElement`` to a ``Table`` or ``MetaData`` instance, executing it when that schema item is created or dropped. The DDL statement will be executed using the same Connection and transactional context as the Table create/drop itself. The ``.bind`` property of this statement is ignored. :param event: One of the events defined in the schema item's ``.ddl_events``; e.g. 'before-create', 'after-create', 'before-drop' or 'after-drop' :param target: The Table or MetaData instance for which this DDLElement will be associated with. A DDLElement instance can be linked to any number of schema items. ``execute_at`` builds on the ``append_ddl_listener`` interface of :class:`_schema.MetaData` and :class:`_schema.Table` objects. Caveat: Creating or dropping a Table in isolation will also trigger any DDL set to ``execute_at`` that Table's MetaData. This may change in a future release. cxj||fi|r(||SdSr)_should_execute_deprecatedr'r()r-r!r event_namers r call_eventz)DDLElement.execute_at..call_events].t.FJ24 @"))$,,v*>*>??? @ @r-_N)r listenreplace)rr2r-r3s`` r execute_atzDDLElement.execute_athsZF @ @ @ @ @ @  VR*"4"4S#">">> KKKKKrc||_dS)z9Return a copy of this DDL against a specific schema item.N)r-)rr-s rr(zDDLElement.againsts rc0||_||_||_dS)aReturn a callable that will execute this DDLElement conditionally. Used to provide a wrapper for event listening:: event.listen( metadata, 'before_create', DDL("my_ddl").execute_if(dialect='postgresql') ) :param dialect: May be a string, tuple or a callable predicate. If a string, it will be compared to the name of the executing database dialect:: DDL('something').execute_if(dialect='postgresql') If a tuple, specifies multiple dialect names:: DDL('something').execute_if(dialect=('postgresql', 'mysql')) :param callable\_: A callable, which will be invoked with four positional arguments as well as optional keyword arguments: :ddl: This DDL element. :target: The :class:`_schema.Table` or :class:`_schema.MetaData` object which is the target of this event. May be None if the DDL is executed explicitly. :bind: The :class:`_engine.Connection` being used for DDL execution :tables: Optional keyword argument - a list of Table objects which are to be created/ dropped within a MetaData.create_all() or drop_all() method call. :state: Optional keyword argument - will be the ``state`` argument passed to this function. :checkfirst: Keyword argument, will be True if the 'checkfirst' flag was set during the call to ``create()``, ``create_all()``, ``drop()``, ``drop_all()``. If the callable returns a True value, the DDL statement will be executed. :param state: any value which will be passed to the callable\_ as the ``state`` keyword argument. .. seealso:: :class:`.DDLEvents` :ref:`event_toplevel` N)r callable_state)rrr<r=s r execute_ifzDDLElement.execute_ifsD " rc ^|j|jd||fi|sdSt|jtjr|j|jjkrdSn %ndn &$/ / &*j/ 46/ / %5trc |jdSt|jtjr|j|jjkSt|jt ttfr|jj|jvS|j||||fi|SNT) r@rAr rBr)rCrDrErF)rr r-r,rs rr1z%DDLElement._should_execute_deprecateds 7?4 !2 3 3 <7dk.. . %s!3 4 4 <;#tw. .474;;;; ;rc t|j||fi|r(|||SdS)z"Execute the DDL as a ddl_listener.N)r&r'r(rGs r__call__zDDLElement.__call__sK 4  3 3 3 3 6<< V 4 455 5 6 6rc|lt|tjttt fzs?tj|s-tjdt|j zdSdSdS)NzjExpected the name of a database dialect, a tuple of names, or a callable for 'on' criteria, got type '%s'.) rAr rBrDrErFcallabler ArgumentErrortyper)rr@s r _check_ddl_onzDDLElement._check_ddl_onsw >2t0E43EEFF M"%% #026r((2CD  >>>>>rc"|jr|jSdSr_bindrs rr,zDDLElement.bind s : :   rc||_dSrrR)rr,s r _set_bindzDDLElement._set_binds  rc|j|j}|j|_|Sr) __class____new____dict__copy)rss r _generatezDDLElement._generates3 N " "4> 2 2]'')) rNNNNN)rrr__doc__r_execution_optionsunionr-r@rr<r$r'r deprecatedr9rr(r>r&r1rKrPr,rVpropertyr]rrrrr su:$6<< tF BGIBBBPPPP<T_  1"L"L"LH[ CCC[CJ&<<<666    8D) $ $DrrcReZdZdZdZejdddZdZdS) DDLaAA literal DDL statement. Specifies literal SQL DDL to be executed by the database. DDL objects function as DDL event listeners, and can be subscribed to those events listed in :class:`.DDLEvents`, using either :class:`_schema.Table` or :class:`_schema.MetaData` objects as targets. Basic templating support allows a single DDL instance to handle repetitive tasks for multiple tables. Examples:: from sqlalchemy import event, DDL tbl = Table('users', metadata, Column('uid', Integer)) event.listen(tbl, 'before_create', DDL('DROP TRIGGER users_trigger')) spow = DDL('ALTER TABLE %(table)s SET secretpowers TRUE') event.listen(tbl, 'after_create', spow.execute_if(dialect='somedb')) drop_spow = DDL('ALTER TABLE users SET secretpowers FALSE') connection.execute(drop_spow) When operating on Table events, the following ``statement`` string substitutions are available:: %(table)s - the Table name, with any required quoting applied %(schema)s - the schema name, with any required quoting applied %(fullname)s - the Table name including schema, quoted if needed The DDL's "context", if any, will be combined with the standard substitutions noted above. Keys present in the context will override the standard substitutions. ddl)r.zThe :paramref:`.DDL.on` parameter is deprecated and will be removed in a future release. Please refer to :meth:`.DDLElement.execute_if`.)r@Nct|tjstjd|z||_|pi|_||||_||_ dS)a)Create a DDL statement. :param statement: A string or unicode string to be executed. Statements will be processed with Python's string formatting operator. See the ``context`` argument and the ``execute_at`` method. A literal '%' in a statement must be escaped as '%%'. SQL bind parameters are not available in DDL statements. :param on: Optional filtering criteria. May be a string, tuple or a callable predicate. If a string, it will be compared to the name of the executing database dialect:: DDL('something', on='postgresql') If a tuple, specifies multiple dialect names:: DDL('something', on=('postgresql', 'mysql')) If a callable, it will be invoked with four positional arguments as well as optional keyword arguments: :ddl: This DDL element. :event: The name of the event that has triggered this DDL, such as 'after-create' Will be None if the DDL is executed explicitly. :target: The ``Table`` or ``MetaData`` object which is the target of this event. May be None if the DDL is executed explicitly. :connection: The ``Connection`` being used for DDL execution :tables: Optional keyword argument - a list of Table objects which are to be created/ dropped within a MetaData.create_all() or drop_all() method call. If the callable returns a true value, the DDL statement will be executed. :param context: Optional dictionary, defaults to None. These values will be available for use in string substitutions on the DDL statement. :param bind: Optional. A :class:`.Connectable`, used by default when ``execute()`` is invoked without a bind argument. .. seealso:: :class:`.DDLEvents` :ref:`event_toplevel` z4Expected a string or unicode SQL statement, got '%r'N) rAr rBr rN statementcontextrPr@rS)rrir@rjr,s r__init__z DDL.__init__BstV)T%677 #F  #}"  2 rc dtjdtddt jgfddDzdS)N<@z; , cZg|]'}t||dt|(S)=)getattr).0keyrs r z DDL.__repr__..sOtS))"ssGD#$6$6$67r)r@rj>)rOridjoinreprrirTs`r__repr__z DDL.__repr__s JJ    tHHHH IIdn%%&0      rr_) rrrr`__visit_name__r deprecated_paramsrkrzrrrrfrfst!!FNT NNNN`      rrfc eZdZdZddZdZdS)_CreateDropBasezBase class for DDL constructs that represent CREATE and DROP or equivalents. The common theme of _CreateDropBase is a single ``element`` attribute which refers to the element to be created or dropped. NcZ||_||||_||_dSr)elementrPr@r,)rrr@r,s rrkz_CreateDropBase.__init__s/  2 rcdS)zAllow disable of _create_rule using a callable. Pass to _create_rule using util.portable_instancemethod(self._create_rule_disable) to retain serializability. Fr)rcompilers r_create_rule_disablez$_CreateDropBase._create_rule_disables urr^)rrrr`rkrrrrr~r~sA rr~c(eZdZdZdZdfd ZxZS) CreateSchemazcRepresent a CREATE SCHEMA statement. The argument here is the string name of the schema. create_schemaNc X||_tt|j|fi|dS)z.Create a new :class:`.CreateSchema` construct.N)quotesuperrrk)rrCrrrXs rrkzCreateSchema.__init__s7 *lD!!*466266666rrrrrr`r{rk __classcell__rXs@rrrsN %N7777777777rrc(eZdZdZdZdfd ZxZS) DropSchemazaRepresent a DROP SCHEMA statement. The argument here is the string name of the schema. drop_schemaNFc f||_||_tt|j|fi|dS)z,Create a new :class:`.DropSchema` construct.N)rcascaderrrk)rrCrrrrXs rrkzDropSchema.__init__s>  (j$(4444444rNFrrs@rrrsN #N5555555555rrc*eZdZdZdZ dfd ZxZS) CreateTablez#Represent a CREATE TABLE statement. create_tableNctt||||d|jD|_||_dS)aZCreate a :class:`.CreateTable` construct. :param element: a :class:`_schema.Table` that's the subject of the CREATE :param on: See the description for 'on' in :class:`.DDL`. :param bind: See the description for 'bind' in :class:`.DDL`. :param include_foreign_key_constraints: optional sequence of :class:`_schema.ForeignKeyConstraint` objects that will be included inline within the CREATE construct; if omitted, all foreign key constraints that do not specify use_alter=True are included. .. versionadded:: 1.0.0 )r@r,c,g|]}t|Sr) CreateColumn)rscolumns rruz(CreateTable.__init__..s KKK V,,KKKrN)rrrkcolumnsinclude_foreign_key_constraints)rrr@r,rrXs rrkzCreateTable.__init__sO" k4  ))'bt)DDDKK7?KKK /N,,,rr_rrs@rrrsY--#NLPOOOOOOOOOOrrceZdZdZdZdS) _DropViewzSemi-public 'DROP VIEW' construct. Used by the test suite for dialect-agnostic drops of views. This object will eventually be part of a public "view" API. drop_viewNrrrr`r{rrrrrs!NNNrrceZdZdZdZdZdS)raRepresent a :class:`_schema.Column` as rendered in a CREATE TABLE statement, via the :class:`.CreateTable` construct. This is provided to support custom column DDL within the generation of CREATE TABLE statements, by using the compiler extension documented in :ref:`sqlalchemy.ext.compiler_toplevel` to extend :class:`.CreateColumn`. Typical integration is to examine the incoming :class:`_schema.Column` object, and to redirect compilation if a particular flag or condition is found:: from sqlalchemy import schema from sqlalchemy.ext.compiler import compiles @compiles(schema.CreateColumn) def compile(element, compiler, **kw): column = element.element if "special" not in column.info: return compiler.visit_create_column(element, **kw) text = "%s SPECIAL DIRECTIVE %s" % ( column.name, compiler.type_compiler.process(column.type) ) default = compiler.get_column_default_string(column) if default is not None: text += " DEFAULT " + default if not column.nullable: text += " NOT NULL" if column.constraints: text += " ".join( compiler.process(const) for const in column.constraints) return text The above construct can be applied to a :class:`_schema.Table` as follows:: from sqlalchemy import Table, Metadata, Column, Integer, String from sqlalchemy import schema metadata = MetaData() table = Table('mytable', MetaData(), Column('x', Integer, info={"special":True}, primary_key=True), Column('y', String(50)), Column('z', String(20), info={"special":True}) ) metadata.create_all(conn) Above, the directives we've added to the :attr:`_schema.Column.info` collection will be detected by our custom compilation scheme:: CREATE TABLE mytable ( x SPECIAL DIRECTIVE INTEGER NOT NULL, y VARCHAR(50), z SPECIAL DIRECTIVE VARCHAR(20), PRIMARY KEY (x) ) The :class:`.CreateColumn` construct can also be used to skip certain columns when producing a ``CREATE TABLE``. This is accomplished by creating a compilation rule that conditionally returns ``None``. This is essentially how to produce the same effect as using the ``system=True`` argument on :class:`_schema.Column`, which marks a column as an implicitly-present "system" column. For example, suppose we wish to produce a :class:`_schema.Table` which skips rendering of the PostgreSQL ``xmin`` column against the PostgreSQL backend, but on other backends does render it, in anticipation of a triggered rule. A conditional compilation rule could skip this name only on PostgreSQL:: from sqlalchemy.schema import CreateColumn @compiles(CreateColumn, "postgresql") def skip_xmin(element, compiler, **kw): if element.element.name == 'xmin': return None else: return compiler.visit_create_column(element, **kw) my_table = Table('mytable', metadata, Column('id', Integer, primary_key=True), Column('xmin', Integer) ) Above, a :class:`.CreateTable` construct will generate a ``CREATE TABLE`` which only includes the ``id`` column in the string; the ``xmin`` column will be omitted, but only against the PostgreSQL backend. create_columnc||_dSr)r)rrs rrkzCreateColumn.__init__ts  rN)rrrr`r{rkrrrrr s7ddL%NrrceZdZdZdZdS) DropTablez!Represent a DROP TABLE statement. drop_tableNrrrrrrx++!NNNrrceZdZdZdZdS)CreateSequencez&Represent a CREATE SEQUENCE statement.create_sequenceNrrrrrr~s00&NNNrrceZdZdZdZdS) DropSequencez$Represent a DROP SEQUENCE statement. drop_sequenceNrrrrrrs..$NNNrrceZdZdZdZdS) CreateIndexz#Represent a CREATE INDEX statement. create_indexNrrrrrrs--#NNNrrceZdZdZdZdS) DropIndexz!Represent a DROP INDEX statement. drop_indexNrrrrrrrrrc&eZdZdZdZfdZxZS) AddConstraintz2Represent an ALTER TABLE ADD CONSTRAINT statement.add_constraintctt|j|g|Ri|tj|j|_dSr)rrrkr portable_instancemethodr _create_rule)rrargsrrXs rrkzAddConstraint.__init__sQ+mT""+GAdAAAbAAA#;  %  rrrs@rrrsC<<%N         rrc(eZdZdZdZdfd ZxZS)DropConstraintz3Represent an ALTER TABLE DROP CONSTRAINT statement.drop_constraintFc ||_tt|j|fi|t j|j|_dSr)rrrrkr rrr)rrrrrXs rrkzDropConstraint.__init__sP ,nd##,W;;;;;#;  %  rFrrs@rrrsH==&N          rrceZdZdZdZdS)SetTableCommentz*Represent a COMMENT ON TABLE IS statement.set_table_commentNrrrrrrs44(NNNrrceZdZdZdZdS)DropTableCommentzfRepresent a COMMENT ON TABLE '' statement. Note this varies a lot across database backends. drop_table_commentNrrrrrrs *NNNrrceZdZdZdZdS)SetColumnCommentz+Represent a COMMENT ON COLUMN IS statement.set_column_commentNrrrrrrs55)NNNrrceZdZdZdZdS)DropColumnCommentz0Represent a COMMENT ON COLUMN IS NULL statement.drop_column_commentNrrrrrrs::*NNNrrceZdZdZdS)DDLBasec||_dSr)r!)rr!s rrkzDDLBase.__init__s $rN)rrrrkrrrrrs#%%%%%rrcVeZdZ d fd ZdZdZdZ d dZdZd d Z d Z xZ S)SchemaGeneratorFNc tt|j|fi|||_||_|j|_||_i|_dSr) rrrk checkfirsttablesidentifier_preparerpreparerrmemorrr!rrkwargsrXs rrkzSchemaGenerator.__init__sT .ot$$-jCCFCCC$ 3   rc |j|j|j|}|r|j||j p'|j|j|j| SN)schemarvalidate_identifierrCr!schema_for_objectr has_tablertableeffective_schemas r_can_create_tablez!SchemaGenerator._can_create_tables ((444?< > >?" $,*@*@ OUZ0@+A+ + '  rc|j|}|jjoD|jj s|j o/|j p'|j|j|j| Sr r!rrsupports_sequencessequences_optionaloptionalr has_sequencerCrsequencers r_can_create_sequencez$SchemaGenerator._can_create_sequences}?<g|]}||Sr)rrstrs rruz2SchemaGenerator.visit_metadata..s, < < <1$"8"8";"; .s>   xD$=$=a$@$@ rcg|] \}}|| Srrrsrfkss rruz2SchemaGenerator.visit_metadata..JJJ(1cAMAMMMrrr _ddl_runnerT) create_ok)rr_is_metadata_operation) rrEvaluessort_tables_and_constraints _sequencesdispatch before_creater!rtraverse_single after_create) rmetadatar collectionseq_collevent_collectionseqrfkcsfkcs ` rvisit_metadatazSchemaGenerator.visit_metadatas ; "[FF(/002233F0 < < < < < < <      (//11    KJjJJJ''  O# (    6 6C   5 5 5 5% . .KE4 $$"48+/ % ..C((----. &&  O# '     rc|s||sdS|j||j|j|||jD]#}|j||j$|jj sd}|j t||t|dr|j D]}|||jjrr|jjsf|j'|j t#||jD]0}|j'|j t%|1|j||j|j||dS)Nrrr)rindexes)rrrr!rrdefaultrrsupports_alterr'rhasattrr supports_commentsinline_commentscommentrrr)rrrrrrindexs r visit_tablezSchemaGenerator.visit_table!s !7!7!>!>  F $$  O#9 %   m 5 5F~)$$V^444|* 3.2 +  3       5) $ $ , , ,$$U++++ < ) F$,2N F}(''(>(>???- F F>-O++,g|]}||Sr)_can_drop_tablers rruz0SchemaDropper.visit_metadata..ys,LLLQD4H4H4K4KLqLLLrc2jjr|jdndSr)rr rC)rrs rz.SchemaDropper.visit_metadata..~s)#|:6"%?26;U"r) filter_fna4Can't sort tables for DROP; an unresolvable foreign key dependency exists between tables: %s; and backend does not support ALTER. To restore at least a partial sort, apply use_alter=True to ForeignKey and ForeignKeyConstraint objects involved in the cycle to mark these as known cycles that will be ignored.rocg|] }|j Srfullnamersrs rruz0SchemaDropper.visit_metadata..s(I(I(I(I(I(Ircg|]}|dfS)rrr*s rruz0SchemaDropper.visit_metadata..s???!q"g???rzCan't sort tables for DROP; an unresolvable foreign key dependency exists between tables: %s. Please ensure that the ForeignKey and ForeignKeyConstraint objects involved in the cycle have names so that they can be dropped using DROP CONSTRAINT.cg|] }|j Srr(r*s rruz0SchemaDropper.visit_metadata..s'H'H'Hq 'H'H'Hr)msg)from_c>g|]}||Sr)_can_drop_sequencers rruz0SchemaDropper.visit_metadata..s=   &&q))    rcg|] \}}|| Srrrs rruz0SchemaDropper.visit_metadata..rrrT)drop_okr_ignore_sequences)r3)rrErreversedrr CircularDependencyErrorrr r warnrxsortedcyclesraise_redgesrr before_dropr!rrr after_drop) rrrunsorted_tablesrerr2rrrrrrs ` rrzSchemaDropper.visit_metadatars ; "[FF(/002233F/ LLLL&LLLO/'#"#"#"#"  JJ*" " " <.!  3yy(I(IT[(I(I(I!J!JKKM   @????  / !   +!II &'H'HDK'H'H'H I I  "%" H    (//11    KJjJJJ%%  O# &   & . .KE4 $$ +/&. % ..C((----. B BC  cjD.@ A A A A$$  O# %     s > >?" dl&<&< OUZ0@'=' '  rc|j|}|jjoC|jj s|j o.|j p&|j|j|j|Srrrs rr1z SchemaDropper._can_drop_sequencesx?<._skip_fn]s7l  72;; 44 trcg|] \}}|| Srr)rsrrs rruzsort_tables..gs-    Q =  ==rT)r&extra_dependencies_warn_for_cycles)r)rrJrMrKs ` r sort_tablesrOsm~        4 1!        rFc  t}t}|||t |D]jD]j}|jdur |!r%|}|dur |H|j}|ur||fk|fdjD ttj | ||d} n #tj $r} |rGtjddt!d| jDd| jD]g} | |vra| d | jvrfd jD} | | D]$}|j}|ur||f%httj | ||d} Yd} ~ nd} ~ wwxYw fd | Ddt fgzS) aSort a collection of :class:`_schema.Table` / :class:`_schema.ForeignKeyConstraint` objects. This is a dependency-ordered sort which will emit tuples of ``(Table, [ForeignKeyConstraint, ...])`` such that each :class:`_schema.Table` follows its dependent :class:`_schema.Table` objects. Remaining :class:`_schema.ForeignKeyConstraint` objects that are separate due to dependency rules not satisfied by the sort are emitted afterwards as ``(None, [ForeignKeyConstraint ...])``. Tables are dependent on another based on the presence of :class:`_schema.ForeignKeyConstraint` objects, explicit dependencies added by :meth:`_schema.Table.add_is_dependent_on`, as well as dependencies stated here using the :paramref:`~.sort_tables_and_constraints.skip_fn` and/or :paramref:`~.sort_tables_and_constraints.extra_dependencies` parameters. :param tables: a sequence of :class:`_schema.Table` objects. :param filter_fn: optional callable which will be passed a :class:`_schema.ForeignKeyConstraint` object, and returns a value based on whether this constraint should definitely be included or excluded as an inline constraint, or neither. If it returns False, the constraint will definitely be included as a dependency that cannot be subject to ALTER; if True, it will **only** be included as an ALTER result at the end. Returning None means the constraint is included in the table-based result unless it is detected as part of a dependency cycle. :param extra_dependencies: a sequence of 2-tuples of tables which will also be considered as dependent on each other. .. versionadded:: 1.0.0 .. seealso:: :func:`.sort_tables` NTc3 K|]}|fV dSrr)rsparentrs r z.sort_tables_and_constraints..s8" " &VUO" " " " " " r)deterministic_orderzLCannot correctly sort tables; there are unresolvable cycles between tables "roc3$K|] }|jV dSrr(r*s rrSz.sort_tables_and_constraints..s$#C#C1AJ#C#C#C#C#C#Crz", which is usually caused by mutually dependent foreign key constraints. Foreign key constraints involving these tables will not be considered; this warning may raise an error in a future release.rc2g|]} |du|Srr)rsrr&s rruz/sort_tables_and_constraints..s; (IIcNN%,G,G,G,G,GrcHg|]}||jfSr)foreign_key_constraints difference)rsrremaining_fkcss rruz/sort_tables_and_constraints..s?     -88HHI   r)rFupdaterX use_alteraddreferred_table_extra_dependenciesrEr sortrbr r6r r7rxr8r9r;discard)rr&rMrNfixed_dependenciesmutable_dependenciesrfiltered dependent_oncandidate_sorterredge can_removerZrs ` @@rrrss2`55%!!"4555UUN  0 @ @C}$$""3''' $9S>>t##"&&s+++-L5(($((,)>???!!" " " " */*C" " "     '   "(()=>>$(       &     II 99V#C#C #C#C#CCCDDDD G   I L LD+++Q **$< %%j111%LLC#L#500,44lE5JKKK  "(()=>>$(     3 B    #    ^$$ %& ''s#7DH$+C/HH$r^)NNF)&r`baserrrrrHrr4r r r r rrrfr~rrrrrrrrrrrrrrrrrrrrOrrrrrks ! ######99999=999yyyyy\yyyxJ J J J J *J J J Zj6 7 7 7 7 7? 7 7 7 55555555"OOOOO/OOO6!!!!!!!!jjjjj<jjjZ"""""""" '''''_''' %%%%%?%%% $$$$$/$$$ """"""""      O          _    )))))o))) **************** ++++++++ %%%%%m%%% T4T4T4T4T4gT4T4T4nr8r8r8r8r8Gr8r8r8n TTTTpGLx'x'x'x'x'x'rPK!Ȧ̇ __pycache__/base.cpython-311.pycnu[ |oiT(dZddlZddlZddlmZddlmZddlmZejdZ ejd Z Gd d e Z d Z ejd ZGddejjZGddejjZGdde ZGdde ZGddeZGdde ZGddeZGddejZGddejeZGd d!ejZd#d"ZdS)$z4Foundational utilities common to many sql modules. N) ClauseVisitor)exc)utilPARSE_AUTOCOMMITNO_ARGc$eZdZdZdZdZdZdS) Immutablez@mark a ClauseElement as 'immutable' when expressions are cloned.c tdNz(Immutable objects do not support copyingNotImplementedErrorself optionaldictkwargss J/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/base.py unique_paramszImmutable.unique_params!"LMMMc tdr rrs rparamszImmutable.paramsrrc|SNrs r_clonezImmutable._clone"s rN)__name__ __module__ __qualname____doc__rrrrrrr r sMJJNNNNNNrr c2tjd|DS)Ncg|] }|j Sr) _from_objects).0elements r z!_from_objects..'sKKKwW2KKKr) itertoolschain)elementss rr%r%&s ?KK(KKK LLrcb|d}||g|ddRi||S)zMark a method as generative.rrN) _generate)fnargskwrs r _generativer1*sF 7    DBtd122h" Krc<eZdZdZdZdZdZdZdZdZ dZ d S) _DialectArgViewzaA dictionary view of dialect-level arguments in the form _. c||_dSr)obj)rr5s r__init__z_DialectArgView.__init__9s rc |dd\}}||fS#t$r.}tjt ||Yd}~dSd}~wwxYw)N_rreplace_context)split ValueErrorrraise_KeyError)rkeydialect value_keyerrs r_keyz_DialectArgView._key<sz &!$3!2!2 GYI% % < < < K s ; ; ; ; ; ; ; ; ; ; )rr?r@rAoptrBs r __getitem__z_DialectArgView.__getitem__Ds!YYs^^ "(*73Cy> !$ < < < K s ; ; ; ; ; ; ; ; ; ; _r9)rCr5rEr>rr=r ArgumentError)rr?valuer@rArBs r __setitem__z_DialectArgView.__setitem__Ns A!%3 GYK|]}t|jVdSr)len _non_defaults)r&r/s r z*_DialectArgView.__len__..`sA   " # #      r)sumr5rEvaluesrs r__len__z_DialectArgView.__len___sA  07799      rc4fdjjDS)Nc3~K|]7}jj|jD]}tj|d|V8dS)r8N)r5rErRr safe_kwarg)r& dialect_name value_namers rrSz+_DialectArgView.__iter__..fss  "h6    O|||ZZ@ A A       r)r5rErs`r__iter__z_DialectArgView.__iter__es3    $ 8    rN) rr r!r"r6rCrHrLrNrVr\rrrr3r33s &&&""" A A A999        rr3c6eZdZdZdZdZdZdZdZdZ dS) _DialectArgDictzA dictionary view of dialect-level arguments for a specific dialect. Maintains a separate collection of user-specified arguments and dialect-specified default arguments. c"i|_i|_dSrrR _defaultsrs rr6z_DialectArgDict.__init__xsrcttt|j|jSr)rQsetrRunionrars rrVz_DialectArgDict.__len__|s+3t)**00@@AAArcttt|j|jSr)iterrcrRrdrars rr\z_DialectArgDict.__iter__s+C*++11$.AABBBrcH||jvr |j|S|j|Srr`rr?s rrHz_DialectArgDict.__getitem__s+ $$ $ $%c* *>#& &rc||j|<dSrrR)rr?rKs rrLz_DialectArgDict.__setitem__s"'3rc|j|=dSrrjrhs rrNz_DialectArgDict.__delitem__s  s # # #rN) rr r!r"r6rVr\rHrLrNrrrr^r^os~BBBCCC''' ((($$$$$rr^ceZdZdZedZejdZe dZ ej ddZ ej e ZdZejdZd Zd S) DialectKWArgsa9Establish the ability for a class to have dialect-specific arguments with defaults and constructor validation. The :class:`.DialectKWArgs` interacts with the :attr:`.DefaultDialect.construct_arguments` present on a dialect. .. seealso:: :attr:`.DefaultDialect.construct_arguments` ctj|}|tjd|z||vri||<||||<dS)aAdd a new kind of dialect-specific keyword argument for this class. E.g.:: Index.argument_for("mydialect", "length", None) some_index = Index('a', 'b', mydialect_length=5) The :meth:`.DialectKWArgs.argument_for` method is a per-argument way adding extra arguments to the :attr:`.DefaultDialect.construct_arguments` dictionary. This dictionary provides a list of argument names accepted by various schema-level constructs on behalf of a dialect. New dialects should typically specify this dictionary all at once as a data member of the dialect class. The use case for ad-hoc addition of argument names is typically for end-user code that is also using a custom compilation scheme which consumes the additional arguments. :param dialect_name: name of a dialect. The dialect must be locatable, else a :class:`.NoSuchModuleError` is raised. The dialect must also include an existing :attr:`.DefaultDialect.construct_arguments` collection, indicating that it participates in the keyword-argument validation and default system, else :class:`.ArgumentError` is raised. If the dialect does not include this collection, then any keyword argument can be specified on behalf of this dialect already. All dialects packaged within SQLAlchemy include this collection, however for third party dialects, support may vary. :param argument_name: name of the parameter. :param default: default value of the parameter. .. versionadded:: 0.9.4 NzRDialect '%s' does have keyword-argument validation and defaults enabled configured)rm _kw_registryrrJ)clsrZ argument_namedefaultconstruct_arg_dictionarys r argument_forzDialectKWArgs.argument_forskP$1#=l#K # +#=?KL  . . .,. $S )7> %m444rc t|S)a9A collection of keyword arguments specified as dialect-specific options to this construct. The arguments are present here in their original ``_`` format. Only arguments that were actually passed are included; unlike the :attr:`.DialectKWArgs.dialect_options` collection, which contains all options known by this dialect including defaults. The collection is also writable; keys are accepted of the form ``_`` where the value will be assembled into the list of options. .. versionadded:: 0.9.2 .. versionchanged:: 0.9.4 The :attr:`.DialectKWArgs.dialect_kwargs` collection is now writable. .. seealso:: :attr:`.DialectKWArgs.dialect_options` - nested dictionary form )r3rs rdialect_kwargszDialectKWArgs.dialect_kwargss0t$$$rc|jS)z4A synonym for :attr:`.DialectKWArgs.dialect_kwargs`.)rvrs rrzDialectKWArgs.kwargss ""rzsqlalchemy.dialectscp|j|}|jdSt|jSr)registryloadconstruct_argumentsdict)dialectsrZ dialect_clss r_kw_reg_for_dialectz!DialectKWArgs._kw_reg_for_dialects7',,\::  * 24K3444rctj|}t}||jddin@t |jjD]&}||vr |j||'|S)N*)rmror^raupdatereversed __class____mro__)rrZrsdrps r_kw_reg_for_dialect_clsz%DialectKWArgs._kw_reg_for_dialect_clss#0#=l#K    # + K  T{ + + + + 677 F F222K&&'?'DEEErcXtjtj|jS)aA collection of keyword arguments specified as dialect-specific options to this construct. This is a two-level nested registry, keyed to ```` and ````. For example, the ``postgresql_where`` argument would be locatable as:: arg = my_object.dialect_options['postgresql']['where'] .. versionadded:: 0.9.2 .. seealso:: :attr:`.DialectKWArgs.dialect_kwargs` - flat dictionary form )r PopulateDictportable_instancemethodrrs rrEzDialectKWArgs.dialect_optionss*&  ()E F F   rc |sdS|D]}tjd|}|std|z|dd\}} |j|}d|vr&||vr"t jd|d|d|j||||<#t j$ratj d |d |tx|j|<}|j ddi|||j|<YwxYwdS) Nz ^(.+?)_(.+)$zGAdditional arguments should be named _, got '%s'rrrz Argument z is not accepted by dialect z on behalf of zCan't validate argument z,; can't locate any SQLAlchemy dialect named )rematch TypeErrorgrouprErrJrrFrwarnr^rarrR)rrkmrZarg_namersrs r_validate_dialect_kwargsz&DialectKWArgs._validate_dialect_kwargss  F C CA++A ?ABC&'WWQ]] "L( C+/+? +M(777 (@@@++11lllDNN< :@,X66)( 6 6 6 qq,,( :I9J9JJ$\2Q ""C;///,21I))) 6 C Cs BA-C?>C?N)rr r!r" classmethodrtrmemoized_propertyrvpropertyr dependenciesrrrorrErrrrrmrms  /?/?[/?b %%%2##X#T,--55.-5 %4$%899L       ,%C%C%C%C%CrrmceZdZdZdZdS) GenerativezRAllow a ClauseElement to generate itself via the @_generative decorator. c|j|j}|j|_|Sr)r__new____dict__copy)rss rr-zGenerative._generateGs3 N " "4> 2 2]'')) rN)rr r!r"r-rrrrrAs- rrcveZdZdZdZejZdZe dZ dZ dZ dZ edZdS) ExecutablezMark a :class:`_expression.ClauseElement` as supporting execution. :class:`.Executable` is a superclass for all "statement" types of objects, including :func:`select`, :func:`delete`, :func:`update`, :func:`insert`, :func:`text`. TNc d|vrtjdd|vrtjd|j||_dS)aSet non-SQL options for the statement which take effect during execution. Execution options can be set on a per-statement or per :class:`_engine.Connection` basis. Additionally, the :class:`_engine.Engine` and ORM :class:`~.orm.query.Query` objects provide access to execution options which they in turn configure upon connections. The :meth:`execution_options` method is generative. A new instance of this statement is returned that contains the options:: statement = select([table.c.x, table.c.y]) statement = statement.execution_options(autocommit=True) Note that only a subset of possible execution options can be applied to a statement - these include "autocommit" and "stream_results", but not "isolation_level" or "compiled_cache". See :meth:`_engine.Connection.execution_options` for a full list of possible options. .. seealso:: :meth:`_engine.Connection.execution_options` :meth:`_query.Query.execution_options` :meth:`.Executable.get_execution_options` isolation_levelz'isolation_level' execution option may only be specified on Connection.execution_options(), or per-engine using the isolation_level argument to create_engine().compiled_cachezm'compiled_cache' execution option may only be specified on Connection.execution_options(), not per statement.N)rrJ_execution_optionsrd)rr0s rexecution_optionszExecutable.execution_optionsZssB  " "#/  r ! !#H #'"9"?"?"C"Crc|jS)zGet the non-SQL options which will take effect during execution. .. versionadded:: 1.3 .. seealso:: :meth:`.Executable.execution_options` )rrs rget_execution_optionsz Executable.get_execution_optionss &&rc|j}|4t|d|jj}d|z}t j|||||S)z.Compile and execute this :class:`.Executable`.N descriptionzThis %s is not directly bound to a Connection or Engine. Use the .execute() method of a Connection or Engine to execute this construct.)bindgetattrrrrUnboundExecutionError_execute_clauseelement)r multiparamsrelabelmsgs rexecutezExecutable.executesa I 9D-1HIIE-/45  +C00 0''k6BBBrc@|j|i|S)znCompile and execute this :class:`.Executable`, returning the result's scalar representation. )rscalar)rrrs rrzExecutable.scalars' t|[3F33::<<.s***SVV***r)reprrs r__str__zColumnCollection.__str__s**T***+++rcndj|vr<jjkr,|j}|j|jkr||j|j=j|jvr|jj|jj< fd|jD|jdd<dS|jdS)aAdd the given column to this collection, removing unaliased versions of this column as well as existing columns with the same key. E.g.:: t = Table('sometable', metadata, Column('col1', Integer)) t.columns.replace(Column('col1', Integer, key='columnone')) will remove the original 'col1' from the collection, and add the new column under the name 'columnname'. Used by schema.Column to override columns during table reflection. Nc g|] }|urn| Srr)r&rcolumn remove_cols rr(z,ColumnCollection.replace..s2$$$56!z//q$$$r)namer?_datarappend)rrotherrs ` @rreplacezColumnCollection.replaces  ;$  6:#<#<%EzUY&&" Juy) : # #FJ/J!' 6:  !$$$$$:>:K$$$D aaa    $ $V , , , , ,rcP|jstjd|||j<dS)zAdd a column to this collection. The key attribute of the column will be used as the hash key for this dictionary. z-Can't add unnamed column to column collectionN)r?rrJrrs rrzColumnCollection.add s:z #? "VZrctrrrhs rrNzColumnCollection.__delitem__!###rctrr)rr?r5s rrzColumnCollection.__setattr__rrc 6||vrp||}||urdS||s-tjd|dt|ddd|dtj|d|j|||j|<dS)NzColumn z on table tablez being replaced by zG, which has the same key. Consider use_labels for select() statements. proxy_set) shares_lineagerrrrresetrrr)rr?rKexistings rrLzColumnCollection.__setitem__ s $;; CyH5  **511  ssGHgt<<<.As%   AVOOAOOOr)rr?rrs `rremovezColumnCollection.remove?sL Jvz "    (   !!!rct|}t|j|jfd|D|jd|DdS)Nc3*K|] \}}|v |VdSrr)r&rr all_col_sets rrSz*ColumnCollection.update..Hs:! ! %a{&:&:A&:&:&:&:! ! rc3$K|] \}}||fV dSrr)r&rrs rrSz*ColumnCollection.update..Ks*::5!*::::::rlistrcrextendrrriter_colsrs @rrzColumnCollection.updateEsE{{$+,,    ! ! ! ! "! ! !     ::T::::::::rct|}t|j|jfd|D|jd|DdS)Nc3$K|] }|v|V dSrr)r&rrs rrSz*ColumnCollection.extend..Ps- I IqA[4H4H4H4H4H4H I Irc3(K|] }|j|fVdSr)r?rs rrSz*ColumnCollection.extend..Qs(3315!*333333rrrs @rrzColumnCollection.extendMsuE{{$+,,    I I I ID I I IIII 33d33333333rNsqlalchemy.sql.elementscg}t|d|D]:}|jD]0}||r|||k1;|j|Sr)rrrrand_rr+rlrlocals r__eq__zColumnCollection.__eq__Usw 66 ) )A* ) )##E**)HHQ%Z((( )x}a  rct|tjstjdtj||S)Nz'__contains__ requires a string argument) isinstancer string_typesrrJOrderedProperties __contains__rrs rr zColumnCollection.__contains__^sC%!233 O#$MNN N%224???rc |j|jdS)Nrrrrs r __getstate__zColumnCollection.__getstate__csT5FGGGrct|d|dt|d|ddS)Nrr)rr)rstates r __setstate__zColumnCollection.__setstate__fsA4%.9994~1FGGGGGrc.|t|jvSr)rcrrcols rcontains_columnz ColumnCollection.contains_columnjsc$+,,,,rc6t|j|jSr)ImmutableColumnCollectionrrrs r as_immutablezColumnCollection.as_immutablems(T5FGGGr)rr r!r" __slots__r6rrrrNrrLrrrr__hash__rrrr rrrr __classcell__)rs@rrrsjI ,,, - - -D " " "$$$$$$   8$$$   ;;;444 HT011!!21!@@@ HHHHHH---HHHHHHHrrc0eZdZdZejjxZZdS)rc~tj||t|d|dSr)rImmutablePropertiesr6rr)rdata all_columnss rr6z"ImmutableColumnCollection.__init__rs9  ))$5554=====rN) rr r!r6rr  _immutablerrrrrrrqs/>>>.99FVVVrrcXeZdZdZdZdZejddZdZ dS) ColumnSetc ||vSrrrs rrzColumnSet.contains_columnzs d{rc:|D]}||dSr)r)rrrs rrzColumnSet.extend}s,  C HHSMMMM  rc@t|t|zSr)rr s r__add__zColumnSet.__add__sDzzDKK''rrcg}|D]5}|D]0}||r|||k16|j|Sr)rrrrs rrzColumnSet.__eq__sh  ) )A ) )##E**)HHQ%Z((( )x}a  rcNttd|DS)Nc3K|]}|VdSrr)r&xs rrSz%ColumnSet.__hash__..s"**!******r)hashtuplers rrzColumnSet.__hash__s'E**T*****+++rN) rr r!rrr)rrrrrrrr%r%ysz(((T011!!21!,,,,,rr%c |j}|sV|jj}t|dt|dd}|r|d|}nd|z}|d|z}t j||S)Nfullnamerz object z %s objectzm%s is not bound to an Engine or Connection. Execution can not proceed without a database to execute against.)rrrrrr) schemaitemrrrritems r_bind_or_errorr4s ?D -#,  GJ$E$E    &%)TT551DD%D ;!"  ',,, Krr) r"r)rvisitorsrrrsymbolrr rr r% decoratorr1collections_abcMutableMappingr3r^rmrrrrr rr rordered_column_setr%r4rrrr<s  ######4;122 X          MMM9 9 9 9 9 d*99 9 9 x$$$$$d*9$$$@oCoCoCoCoCFoCoCoCd        ppppppppf88888888"44444M444 WHWHWHWHWHt-WHWHWHt::::: 8:J:::,,,,,',,,0rPK!33**$__pycache__/__init__.cpython-311.pycnu[ |oinddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZdd lm Z dd lm Z dd lm Z dd lm Z dd lm Z ddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZdd lm Z dd!lm!Z!dd"lm"Z"dd#lm#Z#dd$lm$Z$dd%lm%Z%dd&lm&Z&dd'lm'Z'dd(lm(Z(dd)lm)Z)dd*lm*Z*dd+lm+Z+dd,lm,Z,dd-lm-Z-dd.lm.Z.dd/lm/Z/dd0lm0Z0dd1lm1Z1dd2lm2Z2dd3lm3Z3dd4lm4Z4dd5lm5Z5dd6lm6Z6dd7lm7Z7dd8lm8Z8dd9lm9Z9dd:lm:Z:dd;lm;Z;ddlm>Z>dd?lm?Z?dd@lm@Z@ddAlmAZAddBlmBZBddClmCZCddDlmDZDddElEmFZFdFZGeGeHdGS)H)Alias)alias)all_)and_)any_)asc)between) bindparam)case)cast) ClauseElement)collate)column)ColumnCollection) ColumnElement)CompoundSelect)cte)Delete)delete)desc)distinct)except_) except_all)exists)extract)false)False_) FromClause)func) funcfilter)Insert)insert) intersect) intersect_all)Join)join)label)lateral)literal)literal_column)modifier)not_)null) nullsfirst) nullslast)or_) outerjoin)outparam)over) quoted_name)Select)select) Selectable)subquery)table) TableClause) TableSample) tablesample)text)true)True_)tuple_) type_coerce)union) union_all)Update)update) within_group) ClauseVisitorcNddlm}ddltfd|Daddlm}ddlm}ddl m }dd l m }dd l m }|t||t|||||jd dd lm}dS) N)utilc3vK|]3\}}|d|/|V4dS)_N) startswithismodule).0nameobj_inspects N/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/__init__.py z__go..Use D#$$)1(9(9#(>(> r)_prepare_annotations) Annotated)AnnotatedColumnElement) ClauseList)AnnotatedFromClausezsqlalchemy.sql)naming)rJinspectsorteditems__all__ annotationrWrXelementsrYrZ selectabler[rr dependencies resolve_allr\) lcls_sa_utilrWrXrYrZr[r\rSs @rT__goriOs%######G 100000%%%%%%000000$$$$$$//////(>???%8999Y/// %%&6777rVN)I expressionrrrrrrr r r r r rrrrrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r5r6r7r8r9r:r;r<r=r>r?r@rArBrCrDrErFvisitorsrGrilocalsrVrTrns !!!!!!%%%%%%((((((%%%%%%&&&&&& """"""""""""""""""!!!!!!%%%%%%&&&&&& """"""!!!!!!!!!!!! ######"""""" ########################!!!!!!$$$$$$######6VVXXrVPK!R%%&__pycache__/expression.cpython-311.pycnu[ |oi#p dZgdZddlmZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd lm Z dd lm Z dd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!dd lm"Z"dd!lm#Z#dd"lm$Z$dd#lm%Z%dd$lm&Z&dd%lm'Z'dd&lm(Z(dd'lm)Z)dd(lm*Z*dd)lm+Z+dd*lm,Z,dd+lm-Z-dd,lm.Z.dd-lm/Z/dd.lm0Z0dd/lm1Z1dd0lm2Z2dd1lm3Z3dd2lm4Z4dd3lm5Z5dd4lm6Z6dd5lm7Z7dd6lm8Z8dd7lm9Z9dd8lm:Z:dd9lm;Z;dd:lmZ>dd=lm?Z?dd>lm@Z@dd?lmAZAdd@lBmCZCddAlBmDZDddBlBmEZEddClBmFZFddDlGmHZHddElGmIZIddFlGmJZJddGlGmKZKddHlGmLZLddIlGmMZMddJlGmNZNddKlGmOZOddLlGmPZPddMlGmQZQddNlGmRZRddOlGmSZSddPlGmTZTddQlGmUZUddRlGmVZVddSlGmWZWddTlGmXZXddUlGmYZYddVlGmZZZddWlGm[Z[ddXlGm\Z\ddYl]m^Z^dZd[l_m`Z`e`e)jad\Zbe`e)jcd]Zde`e#jed^Zee`eIjfd_Zge`e[jfd`Zhe`eTjfdaZie`e#jjdbZje`e"dcZke`eVddZle`e;jmdeZne`eZdfZoe`e*dgZpe`e6dhZqe`eAdiZre`e0djZse`e$dkZte`e%dlZue`eKjfdmZve`e,dnZwe`e=doZxe`eJjydpZze`eJj{dqZ|e`eJj}drZ~e`eJjdsZe`eJjdtZe`eJjduZe`eLdvZe`e@jdwZe`e@jdxZe`e@jdyZe`e@jdzZe`e@jd{Ze`e?d|Ze`eZe,ZeLZe/ZeNZeUZdS)aDefines the public namespace for SQL expression constructs. Prior to version 0.9, this module contained all of "elements", "dml", "default_comparator" and "selectable". The module was broken up and most "factory" functions were moved to be grouped with their associated class. )@Aliasany_all_ ClauseElementColumnCollection ColumnElementCompoundSelectDelete FromClauseInsertJoinLateralSelect Selectable TableClauseUpdatealiasand_ascbetween bindparamcasecastcolumnctedeletedescdistinctexcept_ except_allexistsextractfuncmodifiercollateinsert intersect intersect_alljoinlabellateralliteralliteral_columnnot_null nullsfirst nullslastor_outparam outerjoinoverselectsubquerytabletexttuple_ type_coerce quoted_nameunion union_allupdate within_group TableSample tablesample) _from_objects)r) Executable) Generative)PARSE_AUTOCOMMIT)r )r )r) UpdateBase) ValuesBase)_clause_element_as_expr)_clone)_cloned_difference)_cloned_intersection)_column_as_key)_corresponding_column_or_error)_expression_literal_as_text) _is_column)_labeled)_literal_as_binds)_literal_as_column)_literal_as_label_reference)_literal_as_text)_only_column_elements)_select_iterables)_string_or_unprintable)_truncated_label)r)BinaryExpression) BindParameter)BooleanClauseList)Case)Cast)r) ClauseList)r$)CollectionAggregate) ColumnClause)r)Extract)False_)FunctionFilter)Grouping)Label)r+)r,)r-)Null)r2)Over)r;)ReleaseSavepointClause)RollbackToSavepointClause)SavepointClause) TextClause)True_)Tuple) TypeClause) TypeCoerce)UnaryExpression) WithinGroup)r")Function)FunctionElement)r#)_interpret_as_from)r)r)CTE)Exists)r ) FromGrouping)GenerativeSelect)HasCTE) HasPrefixes) HasSuffixes)r )r ) ScalarSelect)r)r) SelectBase)r6)r)r@) TextAsFrom) Visitable)public_factoryz.sql.expression.all_z.sql.expression.any_z.sql.expression.and_z.sql.expression.aliasz.sql.expression.tablesamplez.sql.expression.lateralz.sql.expression.or_z.sql.expression.bindparamz.sql.expression.selectz.sql.expression.textz.sql.expression.tablez.sql.expression.columnz.sql.expression.overz.sql.expression.within_groupz.sql.expression.labelz.sql.expression.casez.sql.expression.castz.sql.expression.ctez.sql.expression.extractz.sql.expression.tuple_z.sql.expression.except_z.sql.expression.except_allz.sql.expression.intersectz.sql.expression.intersect_allz.sql.expression.unionz.sql.expression.union_allz.sql.expression.existsz.sql.expression.nullsfirstz.sql.expression.nullslastz.sql.expression.ascz.sql.expression.descz.sql.expression.distinctz.sql.expression.type_coercez.sql.expression.truez.sql.expression.falsez.sql.expression.nullz.sql.expression.joinz.sql.expression.outerjoinz.sql.expression.insertz.sql.expression.updatez.sql.expression.deletez.sql.expression.funcfilterN)__doc____all__baserCrrDrErFdmlr r rrGrHelementsrIrJrKrLrMrNrOrPrQrRrSrTrUrVrWrXrYrrZr[r\r]r^rr_r$r`rarrbrcrdrerfr+r,r-rgr2rhr;rirjrkrlrmrnrorprqrr functionsr"rsrtr# selectablerurrrvrwr rxryrzr{r|r r r}rrr~r6rr@rvisitorsrutil.langhelpersr _create_allr _create_anyrr_factoryrrAr*r1rr5 _create_textr8r7rr4r?r)rrrr!r9_create_exceptr_create_except_allr_create_intersectr&_create_intersect_allr' _create_unionr<_create_union_allr=r _create_nullsfirstr/_create_nullslastr0 _create_ascr _create_descr_create_distinctrr: _instancetruefalser. _create_joinr(_create_outerjoinr3r%r>r funcfilter _Executable_BindParamClause_Label _SelectBase_BinaryExpression_Cast_Null_False_True _TextClause_UnaryExpression_Case_Tuple_Over _Generative _TypeClause_Extract_Exists _Grouping _FromGrouping _ScalarSelectP/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/expression.pyrsH A A A H """"""""""""------((((((******$$$$$$444444111111 ''''''((((((111111&&&&&&++++++'''''',,,,,,&&&&&&&&&&&&######''''''###### ))))))""""""######$$$$$$$$$$$$!!!!!!,,,,,,//////%%%%%%  %%%%%%!!!!!!&&&&&&******&&&&&&""""""$$$$$$((((((############$$$$$$"""""""""""" ############""""""------~)57MNN~)57MNN~',.DEEu~'>??n7  .)+D E En&*,ABB N=*E F F  8 9 9~j-/EFF{$;<<  &> ? ?~d233~k+IJJ u566~d233~d233nS\#899 ."; < < 7 8 8 .!#<  ^%'C  N$&A   (*I  ~35LMM N$&A     8 9 9 ^&(D  N%'B   n_02GHH~o24JKK >$&@  nZ)FGG ~eo'=>>v')@AA~dn&<==~d')?@@ N413N O O  8 9 9  8 9 9  8 9 9 ^N,H I I     $     "          rPK!_[xӤӤ __pycache__/util.cpython-311.pycnu[ |oiZudZddlmZddlmZddlmZddlmZddlm Z ddlm Z dd lm Z dd l m Z dd l mZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ddlm"Z"ddlm#Z#ddlm$Z$ddlm%Z%ddlm&Z&d d!lm'Z'd d"lm(Z(e(j)*e#j+d#Z,d$Z-d%Z.d&Z/d'Z0 dEd)Z1d*Z2d+Z3d,Z4d-Z5d.Z6d/Z7d0Z8dFd2Z9d3Z:d4Z;d5Z<Gd6d7e=Z>Gd8d9e>Z?Gd:d;e>Z@d<ZAdGd>ZBd?ZC dHd@ZDGdAdBejEZFGdCdDeFZGd=S)Iz;High level utilities which build upon other modules here. )deque)chain) operators)visitors)_deep_annotate)_deep_deannotate)_shallow_annotate) _from_objects) ColumnSet) sort_tables)_expand_cloned) _find_columns)_label_reference)_textual_label_reference) BindParameter) ColumnClause) ColumnElement)Grouping)Label)Null)UnaryExpression)Column)Alias) FromClause) FromGrouping)Join) ScalarSelect) SelectBase) TableClause)exc)utilz.sql.util.join_conditionctt|}g}t|D]4\}}|D],}||r||-5|S)aGiven a list of FROM clauses and a selectable, return the first index and element from the list of clauses which can be joined against the selectable. returns None, None if no match is found. e.g.:: clause1 = table1.join(table2) clause2 = table4.join(table5) join_to = table2.join(table3) find_join_source([clause1, clause2], join_to) == clause1 )listr enumerateis_derived_fromappend)clausesjoin_to selectablesidxifss J/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/util.pyfind_join_sourcer13sz"}W--..K C'""1  A  ##  1   Jctt|}g}t|D]6\}}|D].}||r||n/7t |dkrkg}|D]b}||}|D]U}t t|t|r||nVc|r|S|S)zGiven a list of FROM clauses and a selectable, return the indexes from the list of clauses which is derived from the selectable. r) r%r r&r'r(lensetsurface_selectables intersection) r) join_fromr+ liberal_idxr-r.r/conservative_idxr,s r0#find_left_clause_that_matches_givenr;Ms,}Y//00KK'""  1  A  ## ""1%%%  ;!  C A   *1--..;;'**%++C000E   $# # r2c g}tt|}tdkr|d}t|}nd}d}t D]\}}||gD]} |rWt|j| j|r| |n0[tj || s|| |nt|dkr/ttdD fd|D}|s|ttS|S)a Given a list of FROM clauses, a selectable, and optional ON clause, return a list of integer indexes from the clauses list indicating the clauses that can be joined from. The presence of an "onclause" indicates that at least one clause can definitely be joined from; if the list of clauses is of length one and the onclause is given, returns that index. If the list of clauses is more than length one, and the onclause is given, attempts to locate which clauses contain the same columns. rNTFc6g|]}t|jS)r _hide_froms).0r.s r0 z1find_left_clause_to_join_from..s"CCCaN1=11CCCr2c(g|]}|v |Sr>r>)r@r-r)toremoves r0rAz1find_left_clause_to_join_from..s'<<>!#&&112BCCJJqMMME1%% )= 1 *> 3xx!|| CC7CCC D  =<<<<#<<< 8'S\\""" r2cRgfdt|ddS)aProduce a traversal of the given expression, delivering column comparisons to the given function. The function is of the form:: def my_fn(binary, left, right) For each binary expression located which has a comparison operator, the product of "left" and "right" will be delivered to that function, in terms of that binary. Hence an expression like:: and_( (a + b) == q + func.sum(e + f), j == r ) would have the traversal:: a q a e a f b q b e b f j r That is, every combination of "left" and "right" that doesn't further contain a binary comparison is passed as pairs. c3Kt|tr|VdS|jdkrtj|jrd||jD](}|jD]}d||) d| D] }|dSt|tr|V| D]}|D]}|VdS)Nbinaryr) isinstancer__visit_name__r is_comparisonoperatorinsertleftrightpop get_childrenr)elementlrelemefnstackvisits r0raz#visit_binary_product..visitsf g| , , MMMMM  #x / /I4K  5 5 / LLG $ $ $U7<(( ' 'w}--''ABuQxA&&&&' IIaLLL,,..  d   '<00  ,,..  tAGGGG  r2N)r%)r_exprr`ras` @@r0visit_binary_productrcsQF E, t EEEr2Fcgi}|rjx|d<|d<|r j|d<|r j|d<|rfdx|d<x|d<|d<|r fd }||d <j|d <tj|d d i|S)z1locate Table objects within the given expression.selectcompound_selectjoinaliasc8|jSNr(table)enttabless r0zfind_tables..s ci00r2rUupdatedeletec<|jdSrjrk)columnrns r0 visit_columnz!find_tables..visit_columns MM&, ' ' ' ' 'r2rsrlcolumn_collectionsF)r(rtraverse) clause check_columnsinclude_aliases include_joinsinclude_selects include_crud _visitorsrtrns @r0 find_tablesr~sFIK=C]J (i(9:*"M &+#] '1 1 0 0 0 1 ( 1i1I 5 + ( ( ( ( (+ (Ig f3U;YGGG Mr2ctj}g}t|g}|rO|}t |t rt |t rtj|j st |trSt |j ts9|j }t |tr|j }||t |tr|j }t |t r||vr*||||n,|D]}|||O|S)zqBreak up an 'order by' expression into individual column-expressions, without DESC/ASC/NULLS FIRST/NULLS LAST)r# column_setrpopleftrQrrris_ordering_modifiermodifierrrZrrr(rraddrY)rwcolsresultr`trEs r0unwrap_order_byrsg ?  D F 6(OOE  MMOO a ' ' 1o.. 1!*== !U## J <-- Ia**" A Q!-.. I!688 }}  a   ^^%%   Q5  6 Mr2c4d}tj|i|S)NcLt|ttfr|jSdSrj)rQrrrZ)r]s r0replacez'unwrap_label_reference..replace8s- d-/GH I I <   r2)rreplacement_traverse)rZrs r0unwrap_label_referencer7s(     ("g > >>r2ctd|Dttd|D}fd|DS)zGiven the columns clause and ORDER BY of a selectable, return a list of column expressions that can be added to the collist corresponding to the ORDER BY, without repeating those already in the collist. c.g|]}|j|jn|Srj)_order_by_label_elementrZ)r@cols r0rAz4expand_column_list_from_order_by..Gs6   6BCKK   r2c,g|]}t|Sr>)r)r@os r0rAz4expand_column_list_from_order_by..Ms DDDaq11DDDr2cg|]}|v| Sr>r>)r@rcols_already_presents r0rAz4expand_column_list_from_order_by..Os$ J J JC#5I*I*IC*I*I*Ir2)r5r%r)collistorder_by to_look_forrs @r0 expand_column_list_from_order_byr?sn     uDD8DDDEFFK J J J J; J J JJr2c<t|D] }||krdS dS)zGiven a target clause and a second to search within, return True if the target is plainly present in the search without any subqueries or aliases involved. Basically descends through Joins. TF)r6)rwsearchr]s r0clause_is_presentrRs7$F++ T>>44 ur2c#Kt|tr8t|jD]}|Vt|jD]}|VdSt|t rt|jD]}|VdS|VdSrj)rQrtables_from_leftmostrVrWrrZ)rwrs r0rrbs&$ %fk22  AGGGG%fl33  AGGGG   FL ) )%fn55  AGGGG   r2c#K|g}|r|}|Vt|tr"||j|jfn/t|t r||j|dSdSrj) rXrQrextendrVrWrr(rZrwr`r]s r0r6r6os HE 'yy{{ dD ! ! ' LL$)TZ0 1 1 1 1 l + + ' LL & & & '''''r2c#K|g}|r|}t|ttfr|Vt|tr"||j|jfnrt|tr| |j nBt|tr'|j | |j n |Vn||V|dSdSrj) rXrQr rrrrVrWrr(rZrrlrs r0surface_selectables_onlyrzs HE yy{{ d[%0 1 1 JJJ dD ! !  LL$)TZ0 1 1 1 1 l + +  LL & & & & l + + z% TZ((((  JJJ r2Tc# Ktf}|s |tfz }t|g}|rY|}|V|D](}t ||r||)|WdSdS)ztraverse and yield only outer-exposed column elements, such as would be addressable in the WHERE clause of a SELECT if this element were in the columns clause.N)rrrrrYrQr()rwinclude_scalar_selectsfilter_r`r]subs r0surface_column_elementsrs oG !!J=  6(OOE }} $$&&  C#w''  LL     r2cttt|t|S)z:Return True if left/right have some overlapping selectable)boolr5r6r7)rVrWs r0selectables_overlaprsA   % %&&334G4N4NOO  r2cFgfd}tj|id|iS)zReturn an ordered list of "bound" values in the given clause. E.g.:: >>> expr = and_( ... table.c.foo==5, table.c.foo==7 ... ) >>> bind_values(expr) [5, 7] c<|jdSrj)r(effective_value)bindvs r0visit_bindparamz$bind_values..visit_bindparams %&&&&&r2 bindparam)rrv)rwrrs @r0 bind_valuesrsD A''''' fb;"@AAA Hr2ct|tjr|dd}d|zSt |S)N'z''z'%s')rQr# string_typesrrepr)rZs r0_quote_ddl_exprrsA'4,--//#t,,G}}r2c$eZdZdZdZdZdZdZdS) _repr_baserrr!) max_charsct|}t|}||jkr.|jdz}|d|d||jz zz|| dz}|S)Nr!rz# ... (%d characters truncated) ... )rr4r)selfvaluereplenrepsegment_lengths r0truncz_repr_base.truncsx5kkS DN " "!^q0NAn$%9.0 ~o&&' (  r2N)__name__ __module__ __qualname___LIST_TUPLE_DICT __slots__rr>r2r0rrs7 E F EI     r2rc$eZdZdZdZddZdZdS) _repr_rowzProvide a string view of a row.)row,c"||_||_dSrj)rr)rrrs r0__init__z_repr_row.__init__s"r2c|jddfd|jDt|jdkrdnddS)N(, c3.K|]}|VdSrjr>r@rrs r0 z%_repr_row.__repr__..s+99ueeEll999999r2r,))rrgrr4)rrs @r0__repr__z_repr_row.__repr__s^  II9999999 9 9 9tx==A%%CC2 - -  r2N)r)rrr__doc__rrrr>r2r0rrsB))I####     r2rc0eZdZdZdZd dZdZdZdZdS) _repr_paramszProvide a string view of bound parameters. Truncates display to a given numnber of 'multi' parameter sets, as well as long values to a given number of characters. )paramsbatchesismultirNc>||_||_||_||_dSrj)rrrr)rrrrrs r0rz_repr_params.__init__s"   "r2c &|j||jSt|jtr|j}n^t|jt r|j}n.(sD!!9?!!&)44!!!!!!r2r[%s]z(%s)) rQr%rrrrrtyperg)r multi_paramsrelementsrs` @r0rz_repr_params._repr_multis  ,q/400  J LOU33  K LOT22  J 9a))uyy!!!!!CO!!!HHH $*  H$ $H$ $r2cb|j||jur6ddfd|DzS||jurK|]\}}|d|VdS)z: Nr>)r@keyrrs r0rz,_repr_params._repr_params..7sN"U!$UU5\\\2r2rc3.K|]}|VdSrjr>rs r0rz,_repr_params._repr_params..>s+;;5%%,,;;;;;;r2rrrrrc3.K|]}|VdSrjr>rs r0rz,_repr_params._repr_params..Bs+&H&HuuU||&H&H&H&H&H&Hr2)rrrgitemsrr4)rrrrs @r0rz_repr_params._repr_params3s  $*   &,llnn  DK    ;;;;F;;;;;;6{{a''R//  TYY&H&H&H&H&H&H&HHHI Ir2)rN) rrrrrrrrrr>r2r0rrsk/I#### 777<%%%0JJJJJr2rc>fd}tj|id|iS)zWgiven criterion containing bind params, convert selected elements to IS NULL. ct|jtrQ|jjvrC|j|_t |_t j|_t j |_ dSt|jtrE|jjvr9t |_t j|_t j |_ dSdSdSrj) rQrVr_identifying_keyrWrris_rTisnotnegate)rPnullss r0 visit_binaryz-adapt_criterion_to_null..visit_binaryKs v{M 2 2 , ,55!,FK66FL'mFO%OFMMM v|] 3 3 , -6666FL'mFO%OFMMM  , ,66r2rP)rcloned_traverse)critrrs ` r0adapt_criterion_to_nullrEs8 ,,,,,$  #D"x.F G GGr2Nc||S|dfg}t|}d}|r|\}}t|trh||urd|}|||j|_||j |fn||}|||_ ||}||Srj) ClauseAdapterrXrQr_clone_reset_exportedrvrJr(rV)rVrWstop_onr`adapterret prevrights r0 splice_joinsr `s | T]OED!!G C  "YY[[ eT " " ,uG';';LLNNE  ! ! # # #$--en==EN LL%*e, - - - -$$U++E  "IN ;C   Jr2cz |dd}|dd tjtj D]}t d|jDD]~}D]y}||ur |j}n+#tj$r|rY#tj $r|rY6wxYw| |r) r|j |j kr |nz|r& fd}|D]} | tj| id|it S)aCgiven a list of columns, return a 'reduced' set based on natural equivalents. the set is reduced to the smallest list of columns which have no natural equivalent present in the list. A "natural equivalent" means that two columns will ultimately represent the same value because they are related by a foreign key. \*clauses is an optional list of join clauses which will be traversed to further identify columns that are "equivalent". \**kw may specify 'ignore_nonexistent_tables' to ignore foreign keys whose tables are not yet configured, or columns that aren't yet present. This function is primarily used to determine the most minimal "primary key" from a selectable, by reducing the set of primary key columns present in the selectable to just those that are not repeated. ignore_nonexistent_tablesF only_synonymscg|] }|j Sr>) foreign_keysr@rEs r0rAz"reduce_columns..s@@@Q!.@@@r2c|jtjkrtjt dD}|j|vrf|j|vr_tD]Q}| |jr/r|j |jj kr |dSLdSdSdSdS)Ncg|] }|j Sr>) proxy_setrs r0rAz8reduce_columns..visit_binary..sJJJAAKJJJr2) rTreqr#rrrDrVrWreversedshares_lineagenamer)rPrrEcolumnsomitr s r0rz$reduce_columns..visit_binarys),..JJ1C1CD1I1IJJJK;$&&6<4+?+?%g..""++FL99" -"126;;K1K1K HHQKKK!EE/.'&+?+?""r2NrP)rXr#ordered_column_setrrrrsr"NoReferencedColumnErrorNoReferencedTableErrorrrrrrvr rD) rr)kwr rfkrEfk_colrrwrr s ` @@r0reduce_columnsr ys(!#'BE J JFF?E22M%g..G ?  D@@#-@@@A  B  88YFF21 11  ((++%)*38););HHSMMME1 4H " " " " " " " H HF!!&"x.FGGG W''-- . ..s?BB/ B/ -B/ crrtjddfd}gtj|id|iS)z9traverse an expression and locate binary criterion pairs.zSCan only specify one of 'consider_as_foreign_keys' or 'consider_as_referenced_keys'c,||Srj)compare)abs r0col_isz"criterion_as_pairs..col_issyy||r2cs|jtjurdSt|jt rt|jt sdSr|jvrB|j|js |jvr#|j|jfdS|jvrB|j|js |jvr%|j|jfdSdSdSr|jvrB|j|js |jvr#|j|jfdS|jvrB|j|js |jvr%|j|jfdSdSdSt|jtrt|jtr|j |jr#|j|jfdS|j |jr'|j|jfdSdSdSdSrj) rTrrrQrVrrWr(r references)rP any_operatorr&consider_as_foreign_keysconsider_as_referenced_keyspairss r0rz(criterion_as_pairs..visit_binarys y| C C F&+}55 Z L-> >   F # >{666v|V[117<'??? flFK899999!999v{FL11:;&>>> fk6<899999 :9>>) >{999v|V[11:<'BBB fk6<899999!<<<v{FL11=;&AAA flFK899999 =<AA&+v.. >: f44 >;))&,77>LL&, !<=====\,,V[99>LL&+v|!<=====  > > > > >>r2rP)r" ArgumentErrorrrv) expressionr*r+r)rr&r,s ``` @@r0criterion_as_pairsr/s  $?  ,   %>%>%>%>%>%>%>%>%>N E j"x&>??? Lr2c>eZdZdZ ddZejfdZdZdS)ra5Clones and modifies clauses based on column correspondence. E.g.:: table1 = Table('sometable', metadata, Column('col1', Integer), Column('col2', Integer) ) table2 = Table('someothertable', metadata, Column('col1', Integer), Column('col2', Integer) ) condition = table1.c.col1 == table2.c.col1 make an alias of table1:: s = table1.alias('foo') calling ``ClauseAdapter(s).traverse(condition)`` converts condition to read:: s.c.col1 == table2.c.col1 NFc|g|d|_||_||_||_t j|pi|_||_dS)N)ranonymize_labels)__traverse_options__ selectable include_fn exclude_fnr# column_dict equivalentsadapt_on_names)rr4r8r5r6r9r2s r0rzClauseAdapter.__init__sX#| 0% % !%$$+K,=2>>,r2c:|j||}|O||jvrF||vrB|j|D]4}|||||g}||cS5|jr&|$|jj|j}|S)N)require_embedded)r;_seen) r4corresponding_columnr8_corresponding_columnrFr9rEgetr)rrr;r<newcolequivs r0r>z#ClauseAdapter._corresponding_column1s55 "26   >cT%555#U:J:J)#. " "33%5++se,,4 %!MMM&   56>_&**3844F r2c@t|tr!|j|r|jSt|tsdS|jr||sdS|jr||rdS||dS)NT)rQrr4r'rr5r6r>)rrs r0rzClauseAdapter.replaceDs c: & & 94?+J+J , , 9? "C// 94 _ 9T__S%9%9 94 _ 9!5!5 94--c488 8r2)NNNFF) rrrrrr# EMPTY_SETr>rr>r2r0rrsm:----(,0>& 9 9 9 9 9r2rcteZdZdZ d dZGddeZdZd ZeZ e j Z d Z d Zd ZdS) ColumnAdapteraExtends ClauseAdapter with extra utility functions. Key aspects of ColumnAdapter include: * Expressions that are adapted are stored in a persistent .columns collection; so that an expression E adapted into an expression E1, will return the same object E1 when adapted a second time. This is important in particular for things like Label objects that are anonymized, so that the ColumnAdapter can be used to present a consistent "adapted" view of things. * Exclusion of items from the persistent collection based on include/exclude rules, but also independent of hash identity. This because "annotated" items all have the same hash identity as their parent. * "wrapping" capability is added, so that the replacement of an expression E can proceed through a series of adapters. This differs from the visitor's "chaining" feature in that the resulting object is passed through all replacing functions unconditionally, rather than stopping at the first one that returns non-None. * An adapt_required option, used by eager loading to indicate that We don't trust a result row column that is not translated. This is to prevent a column from being interpreted as that of the child row in a self-referential scenario, see inheritance/test_basic.py->EagerTargetingTest.test_adapt_stringency NFTc  t|||||||tj|j|_|js|jr |||j|_||_ ||_ d|_ dS)N)r5r6r9r2) rrr#WeakPopulateDict _locate_colrr5r6_IncludeExcludeMappingadapt_requiredallow_label_resolve_wrap) rr4r8rJr5r6r9rKr2s r0rzColumnAdapter.__init__rs    !!)-    ,T-=>> ? Kdo K66tT\JJDL,#6  r2ceZdZdZdZdS)$ColumnAdapter._IncludeExcludeMappingc"||_||_dSrj)parentr)rrPrs r0rz-ColumnAdapter._IncludeExcludeMapping.__init__s DK"DLLLr2c|jjr|j|r&|jjr?|j|r%|jjr|jjj|S|S|j|Srj)rPr5r6rLr)rrs r0 __getitem__z0ColumnAdapter._IncludeExcludeMapping.__getitem__s & /3{/E/Ec/J/J +( -1[-C-CC-H-H ;$;,4S99J<$ $r2N)rrrrrRr>r2r0rIrNs2 # # # % % % % %r2rIc(|j|j}|j|j||_t j|j|_|j s|j r | ||j|_|Srj) __class____new____dict__rprLr#rGrHrr5r6rI)rracs r0wrapzColumnAdapter.wraps ^ # #DN 3 3 4=)))*2>:: = EBM E44RDDBJ r2c|j|Srj)r)robjs r0rvzColumnAdapter.traverses|C  r2ct||}|jr|j|}||}|jr||urdS|j|_|Srj)rrvrLrHrJrK_allow_label_resolve)rrrEc2s r0rHzColumnAdapter._locate_colsh  " "4 - - : ''**B~   1884!%!9r2c>|j}|d=|S)Nr)rVcopy)rds r0 __getstate__zColumnAdapter.__getstate__s! M    iLr2cv|j|tj|j|_dSrj)rVrpr#rGrHr)rstates r0 __setstate__zColumnAdapter.__setstate__s1 U###,T-=>> r2)NFNNFTF)rrrrrobjectrIrXrv adapt_clausercopy_and_process adapt_listrHrardr>r2r0rErESsB 8 % % % % % % % %!!!L/J  ?????r2rE)FFFFF)Trj)NNF)Hr collectionsr itertoolsrrrr annotationrr r baser r ddlr rrrrrrrrrrrrschemarr4rrrrrrr r"r# langhelperspublic_factory_join_conditionjoin_conditionr1r;rMrcr~rrrrrr6rrrrrrerrrrr r r/ReplacingCloningVisitorrrEr>r2r0rts&&&&&&(((((())))))$$$$$$######&&&&&&......######""""""######%%%%%%""""""$$$$$$$$$$$$""""""######!004 4'''T111h<<<B %%%%P"""J???KKK&      '''&&   *.        "UJUJUJUJUJ:UJUJUJpHHH62H/H/H/Z" $ <<<<~M9M9M9M9M9H4M9M9M9`q?q?q?q?q?Mq?q?q?q?q?r2PK! cPP$__pycache__/visitors.cpython-311.pycnu[ |oiD>dZddlmZddlZddlmZddlmZgdZGdd eZ d Z Gd d ej e e Z Gd de ZGddeZGddeZdZdZdZdZdZdZdZdS)a@Visitor/traversal interface and library functions. SQLAlchemy schema and expression constructs rely on a Python-centric version of the classic "visitor" pattern as the primary way in which they apply functionality. The most common use of this pattern is statement compilation, where individual expression classes match up to rendering methods that produce a string result. Beyond this, the visitor system is also used to inspect expressions for various information and patterns, as well as for the purposes of applying transformations to expressions. Examples of how the visit system is used can be seen in the source code of for example the ``sqlalchemy.sql.util`` and the ``sqlalchemy.sql.compiler`` modules. Some background on clause adaption is also at http://techspot.zzzeek.org/2008/01/23/expression-transformations/ . )dequeN)exc)util) VisitableType Visitable ClauseVisitorCloningVisitorReplacingCloningVisitoriterateiterate_depthfirsttraverse_usingtraversetraverse_depthfirstcloned_traversereplacement_traversec"eZdZdZfdZxZS)rarMetaclass which assigns a ``_compiler_dispatch`` method to classes having a ``__visit_name__`` attribute. The ``_compiler_dispatch`` attribute becomes an instance method which looks approximately like the following:: def _compiler_dispatch (self, visitor, **kw): '''Look for an attribute named "visit_" + self.__visit_name__ on the visitor, and call it with the same kw params.''' visit_attr = 'visit_%s' % self.__visit_name__ return getattr(visitor, visit_attr)(self, **kw) Classes having no ``__visit_name__`` attribute will remain unaffected. c|dkrt|drt|tt||||dS)Nr__visit_name__)hasattr_generate_dispatchsuperr__init__)clsclsnamebasesclsdict __class__s N/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/visitors.pyrzVisitableType.__init__BsT k ! !gc3C&D&D ! s # # # mS!!**7E7CCCCC)__name__ __module__ __qualname____doc__r __classcell__)rs@rrr1sK DDDDDDDDDr rcdjvrYj}t|tjjrt jd|zfd}nfd}d|_|_ dSdS)zZReturn an optimized visit dispatch function for the cls for use by the compiler. rvisit_%sc |}||fi|S#t$r4}tjtj||Yd}~dSd}~wwxYw)Nreplace_context)AttributeErrorrraise_rUnsupportedCompilationError)selfvisitorkwmetherrrgetters r_compiler_dispatchz._generate_dispatch.._compiler_dispatchWs,!6'??D 4+++++ &K7EE(+s  A)AAcd|jz} t||}||fi|S#t$r4}tjt j||Yd}~dSd}~wwxYw)Nr'r))rgetattrr+rr,rr-)r.r/r0 visit_attrr1r2rs rr4z._generate_dispatch.._compiler_dispatchfs'$*== ,"7J77D 4+++++ &K7EE(+s& A$)AA$zLook for an attribute named "visit_" + self.__visit_name__ on the visitor, and call it with the same kw params. N) __dict__r isinstancercompat string_typesoperator attrgetterr$r4)r visit_namer4r3s` @rrrIs 3<''' j$+": ; ; ,(j)@AAF , , , , , , , , , , , ,&""4O('r ceZdZdZdS)rzBase class for visitable objects, applies the :class:`.visitors.VisitableType` metaclass. The :class:`.Visitable` class is essentially at the base of the :class:`_expression.ClauseElement` hierarchy. N)r!r"r#r$r rrrxsr rcdeZdZdZiZdZdZdZej dZ e dZ dZ dS) r zBase class for visitor objects which can traverse using the :func:`.visitors.traverse` function. Direct usage of the :func:`.visitors.traverse` function is usually preferred. c f|jD](}t|d|jzd}|r ||fi|cS)dS)Nr')visitor_iteratorr6r)r.objr0vr1s rtraverse_singlezClauseVisitor.traverse_singles^& ' 'A1j3+==tDDD 'tC2&&& ' ' 'r c,t||jS)zaTraverse the given expression structure, returning an iterator of all elements. )r __traverse_options__r.rDs rr zClauseVisitor.iterates sD5666r c8t||j|jS2Traverse and visit the given expression structure.)rrH _visitor_dictrIs rrzClauseVisitor.traversesT68JKKKr ci}t|D]2}|drt||||dd<3|S)Nvisit_)dir startswithr6)r.visitorsnames rrMzClauseVisitor._visitor_dictsRII 9 9Dx(( 9%,T4%8%8abb"r c#DK|}|r|Vt|dd}|dSdS)z8Iterate through this visitor and each 'chained' visitor._nextN)r6)r.rEs rrCzClauseVisitor.visitor_iteratorsM  *GGG7D))A * * * * *r cHt|jd}||_|S)z'Chain' an additional ClauseVisitor onto this ClauseVisitor. The chained visitor will receive all visit events after this one. )listrCrV)r.r/tails rchainzClauseVisitor.chains% D)**2.  r N)r!r"r#r$rHrFr rrmemoized_propertyrMpropertyrCr[r@r rr r s''' 777LLL  **X*r r ceZdZdZdZdZdS)r zBase class for visitor objects which can traverse using the :func:`.visitors.cloned_traverse` function. Direct usage of the :func:`.visitors.cloned_traverse` function is usually preferred. c fd|DS)z`Apply cloned traversal to the given list of elements, and return the new list. c:g|]}|Sr@)r).0xr.s r z3CloningVisitor.copy_and_process..s%000Q a  000r r@)r.list_s` rcopy_and_processzCloningVisitor.copy_and_processs 1000%0000r c8t||j|jSrK)rrHrMrIs rrzCloningVisitor.traverses# *D,>   r N)r!r"r#r$rerr@r rr r s<111     r r ceZdZdZdZdZdS)r zBase class for visitor objects which can traverse using the :func:`.visitors.replacement_traverse` function. Direct usage of the :func:`.visitors.replacement_traverse` function is usually preferred. cdS)aReceive pre-copied elements during a cloning traversal. If the method returns a new element, the element is used instead of creating a simple copy of the element. Traversal will halt on the newly returned element if it is re-encountered. Nr@)r.elems rreplacezReplacingCloningVisitor.replaces tr c:fd}t|j|S)rLcRjD]}||}||cSdS)N)rCrj)rirEer.s rrjz1ReplacingCloningVisitor.traverse..replacesA*  IIdOO=HHH!  r )rrH)r.rDrjs` rrz ReplacingCloningVisitor.traverses3      $C)BGLLLr N)r!r"r#r$rjrr@r rr r sA M M M M Mr r c$|jdi|}|s|gSt}t|g}|rP|}|||jdi|D]}|||Pt |S)arTraverse the given expression structure, returning an iterator. Traversal is configured to be breadth-first. The central API feature used by the :func:`.visitors.iterate` and :func:`.visitors.iterate_depthfirst` functions is the :meth:`_expression.ClauseElement.get_children` method of :class:`_expression.ClauseElement` objects. This method should return all the :class:`_expression.ClauseElement` objects which are associated with a particular :class:`_expression.ClauseElement` object. For example, a :class:`.Case` structure will refer to a series of :class:`_expression.ColumnElement` objects within its "whens" and "else\_" member variables. :param obj: :class:`_expression.ClauseElement` structure to be traversed :param opts: dictionary of iteration options. This dictionary is usually empty in modern usage. r@) get_childrenrpopleftappenditer)rDoptschildren traversalstacktcs rr r s, s''$''H u I 3%LLE  MMOO''$''  A LLOOOO   ??r c$|jdi|}|s|gSt|g}t}|rP|}|||jdi|D]}|||Pt |S)aTraverse the given expression structure, returning an iterator. Traversal is configured to be depth-first. :param obj: :class:`_expression.ClauseElement` structure to be traversed :param opts: dictionary of iteration options. This dictionary is usually empty in modern usage. .. seealso:: :func:`.visitors.iterate` - includes a general overview of iteration. r@)rorpop appendleftrqrr)rDrsrtrvrurwrxs rr r s  s''$''H u 3%LLEI  IIKKQ''$''  A LLOOOO   ??r c`|D]*}||jd}|r ||+|S)aeVisit the given expression structure using the given iterator of objects. :func:`.visitors.traverse_using` is usually called internally as the result of the :func:`.visitors.traverse` or :func:`.visitors.traverse_depthfirst` functions. :param iterator: an iterable or sequence which will yield :class:`_expression.ClauseElement` structures; the iterator is assumed to be the product of the :func:`.visitors.iterate` or :func:`.visitors.iterate_depthfirst` functions. :param obj: the :class:`_expression.ClauseElement` that was used as the target of the :func:`.iterate` or :func:`.iterate_depthfirst` function. :param visitors: dictionary of visit functions. See :func:`.traverse` for details on this dictionary. .. seealso:: :func:`.traverse` :func:`.traverse_depthfirst` N)getr)iteratorrDrStargetr1s rrr5sD8||F1488   DLLL Jr c@tt||||S)aTraverse and visit the given expression structure using the default iterator. e.g.:: from sqlalchemy.sql import visitors stmt = select([some_table]).where(some_table.c.foo == 'bar') def visit_bindparam(bind_param): print("found bound value: %s" % bind_param.value) visitors.traverse(stmt, {}, {"bindparam": visit_bindparam}) The iteration of objects uses the :func:`.visitors.iterate` function, which does a breadth-first traversal using a stack. :param obj: :class:`_expression.ClauseElement` structure to be traversed :param opts: dictionary of iteration options. This dictionary is usually empty in modern usage. :param visitors: dictionary of visit functions. The dictionary should have strings as keys, each of which would correspond to the ``__visit_name__`` of a particular kind of SQL expression object, and callable functions as values, each of which represents a visitor function for that kind of object. )rr rDrsrSs rrrXs < '#t,,c8 < <.clones 7??K$xxv%%-1[[]]:r$xx 7''::e:r:::||G$:DAA"DMMM"T((# #r N)setr})rDrsrSrrrs `@@@rrrsn6F$((9b))**G $ $ $ $ $ $ $ $ eCjj E Jr c|id|dgDfd| |fi|}d|S)a]Clone the given expression structure, allowing element replacement by a given replacement function. This function is very similar to the :func:`.visitors.cloned_traverse` function, except instead of being passed a dictionary of visitors, all elements are unconditionally passed into the given replace function. The replace function then has the option to return an entirely new object which will replace the one given. If it returns ``None``, then the object is kept in place. The difference in usage between :func:`.visitors.cloned_traverse` and :func:`.visitors.replacement_traverse` is that in the former case, an already-cloned object is passed to the visitor function, and the visitor function can then manipulate the internal state of the object. In the case of the latter, the visitor function should only return an entirely different object, or do nothing. The use case for :func:`.visitors.replacement_traverse` is that of replacing a FROM clause inside of a SQL structure with a different one, as is a common use case within the ORM. c,h|]}t|Sr@)r)rarbs r z'replacement_traverse..s666r!uu666r rct|vs d|jvr|S|}|$t||S|vr(|x|<}|jddi||S)Nno_replacement_traverserr@)r _annotationsaddrr)rir0rrrrjrs rrz#replacement_traverse..clones tHH  (D,===KgdmmG" BwKK(((v%%-1[[]]:F4L7+G+>>%>2>>>d|#r N)r})rDrsrjrrrs `@@@rrrs~0F66dhhy"55666G$$$$$$$$" eC  4   E Jr )r$ collectionsrr<rr__all__typerrwith_metaclassobjectrr r r r r rrrrrr@r rrs$    DDDDDDDDD0,4,4,4^##M6::77777F777t     ]   2MMMMMnMMMZ=e ded?Z>e d@Z?e dAZ@dBZAe dCZBe dDZCdEZDdFZEdGZFdHZGdIZHdJZIdKZJdLZKdMZLdNZMdOZNdPZOe e%e&eefZPdQZQee ee e ee eiZRdRZSeTeEeegUeegZVeVTeeJeKgZW ejXdSdTUZYejXdVdWUZZejXdXdYUZ[ie!dZe"dZe6dZe7dZedZeJdZeKdZed[ed[ed[e d[ed[ed\ed\eEd]eDd]e?d^ie@d^e/d^e0d^e-d^e.d^e3d^e4d^e)d^e*d^ed^ed^e'd^e(d^eBd^eCd^ed^e d^ied^e d^e1d^e2d^e5d^e d^e%d^e&d^ed_edeAd`eFd_eGd_e+dae#d`e$deYdTeZeZe[e[iZ\dbZ]d,S)fz*Defines operators used in SQL expressions.)add)and_)contains)eq)ge)getitem)gt)inv)le)lshift)lt)mod)mul)ne)neg)or_)rshift)sub)truediv)util)divcFeZdZdZdZdZdZdZ d d Zdd Z d Z d Z dS) OperatorsaBase of comparison and logical operators. Implements base methods :meth:`~sqlalchemy.sql.operators.Operators.operate` and :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as :meth:`~sqlalchemy.sql.operators.Operators.__and__`, :meth:`~sqlalchemy.sql.operators.Operators.__or__`, :meth:`~sqlalchemy.sql.operators.Operators.__invert__`. Usually is used via its most common subclass :class:`.ColumnOperators`. c8|t|S)a-Implement the ``&`` operator. When used with SQL expressions, results in an AND operation, equivalent to :func:`_expression.and_`, that is:: a & b is equivalent to:: from sqlalchemy import and_ and_(a, b) Care should be taken when using ``&`` regarding operator precedence; the ``&`` operator has the highest precedence. The operands should be enclosed in parenthesis if they contain further sub expressions:: (a == 2) & (b == 4) )operaterselfothers O/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/operators.py__and__zOperators.__and__;s,||D%(((c8|t|S)a)Implement the ``|`` operator. When used with SQL expressions, results in an OR operation, equivalent to :func:`_expression.or_`, that is:: a | b is equivalent to:: from sqlalchemy import or_ or_(a, b) Care should be taken when using ``|`` regarding operator precedence; the ``|`` operator has the highest precedence. The operands should be enclosed in parenthesis if they contain further sub expressions:: (a == 2) | (b == 4) )rrrs r!__or__zOperators.__or__Ss,||C'''r#c6|tS)aImplement the ``~`` operator. When used with SQL expressions, results in a NOT operation, equivalent to :func:`_expression.not_`, that is:: ~a is equivalent to:: from sqlalchemy import not_ not_(a) )rr rs r! __invert__zOperators.__invert__ks||C   r#rFNc:t||||fd}|S)a!Produce a generic operator function. e.g.:: somecolumn.op("*")(5) produces:: somecolumn * 5 This function can also be used to make bitwise operators explicit. For example:: somecolumn.op('&')(0xff) is a bitwise AND of the value in ``somecolumn``. :param operator: a string which will be output as the infix operator between this element and the expression passed to the generated function. :param precedence: precedence to apply to the operator, when parenthesizing expressions. A lower number will cause the expression to be parenthesized when applied against another operator with higher precedence. The default value of ``0`` is lower than all operators except for the comma (``,``) and ``AS`` operators. A value of 100 will be higher or equal to all operators, and -100 will be lower than or equal to all operators. :param is_comparison: if True, the operator will be considered as a "comparison" operator, that is which evaluates to a boolean true/false value, like ``==``, ``>``, etc. This flag should be set so that ORM relationships can establish that the operator is a comparison operator when used in a custom join condition. .. versionadded:: 0.9.2 - added the :paramref:`.Operators.op.is_comparison` flag. :param return_type: a :class:`.TypeEngine` class or object that will force the return type of an expression produced by this operator to be of that type. By default, operators that specify :paramref:`.Operators.op.is_comparison` will resolve to :class:`.Boolean`, and those that do not will be of the same type as the left-hand operand. .. versionadded:: 1.2.0b3 - added the :paramref:`.Operators.op.return_type` argument. .. seealso:: :ref:`types_operators` :ref:`relationship_custom_operator` c|SNr)r operatorrs r!againstzOperators.op..againsts8D%(( (r#) custom_op)ropstring precedence is_comparison return_typer-r,s` @r!opz Operators.op|s?tXz=+NN ) ) ) ) ) )r#c2|||dS)a+Return a custom boolean operator. This method is shorthand for calling :meth:`.Operators.op` and passing the :paramref:`.Operators.op.is_comparison` flag with True. .. versionadded:: 1.2.0b3 .. seealso:: :meth:`.Operators.op` T)r0r1r3)rr/r0s r!bool_opzOperators.bool_opswwxJdwKKKr#c:tt|)a3Operate on an argument. This is the lowest level of operation, raises :class:`NotImplementedError` by default. Overriding this on a subclass can allow common behavior to be applied to all operations. For example, overriding :class:`.ColumnOperators` to apply ``func.lower()`` to the left and right side:: class MyComparator(ColumnOperators): def operate(self, op, other): return op(func.lower(self), func.lower(other)) :param op: Operator callable. :param \*other: the 'other' side of the operation. Will be a single scalar for most operations. :param \**kwargs: modifiers. These may be passed by special operators such as :meth:`ColumnOperators.contains`. NotImplementedErrorstrrr3r kwargss r!rzOperators.operates0"#b''***r#c :tt|)zXReverse operate on an argument. Usage is the same as :meth:`operate`. r8r;s r!reverse_operatezOperators.reverse_operates "#b''***r#)rFN)r) __name__ __module__ __qualname____doc__ __slots__r"r%r(r3r6rr>rr#r!rr*s  I)))0(((0!!!$HL????BLLLL"+++4+++++r#rc:eZdZdZdZ d dZdZdZdZdS) r.aRepresent a 'custom' operator. :class:`.custom_op` is normally instantiated when the :meth:`.Operators.op` or :meth:`.Operators.bool_op` methods are used to create a custom operator callable. The class can also be used directly when programmatically constructing expressions. E.g. to represent the "factorial" operation:: from sqlalchemy.sql import UnaryExpression from sqlalchemy.sql import operators from sqlalchemy import Numeric unary = UnaryExpression(table.c.somecolumn, modifier=operators.custom_op("!"), type_=Numeric) .. seealso:: :meth:`.Operators.op` :meth:`.Operators.bool_op` rFNc||_||_||_||_||_|r||nd|_dSr+)r/r0r1natural_self_precedenteager_grouping _to_instancer2)rr/r0r1r2rFrGs r!__init__zcustom_op.__init__ sS! $*&<#,5@ JK $ $[ 1 1 1d r#cLt|to|j|jkSr+) isinstancer.r/rs r!__eq__zcustom_op.__eq__s %++O$-0OOr#c t|Sr+)idr's r!__hash__zcustom_op.__hash__"s $xxr#c |j||fi|Sr+)r)rleftrightkws r!__call__zcustom_op.__call__%st|D%..2...r#)rFNFF)r?r@rArBrIrLrOrTrr#r!r.r.sz2H $    $PPP/////r#r.cNeZdZdZdZdZ dZdZej Z dZ dZ dZ d Z d Zd Zd Zd ZdZdZdZdZd4dZd4dZdZdZd4dZd4dZdZdZdZdZdZ dZ!dZ"dZ#d Z$d!Z%d"Z&d#Z'd$Z(d%Z)d&Z*d'Z+d5d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6dS)6ColumnOperatorsa"Defines boolean, comparison, and other operators for :class:`_expression.ColumnElement` expressions. By default, all methods call down to :meth:`.operate` or :meth:`.reverse_operate`, passing in the appropriate operator function from the Python builtin ``operator`` module or a SQLAlchemy-specific operator function from :mod:`sqlalchemy.expression.operators`. For example the ``__eq__`` function:: def __eq__(self, other): return self.operate(operators.eq, other) Where ``operators.eq`` is essentially:: def eq(a, b): return a == b The core column expression unit :class:`_expression.ColumnElement` overrides :meth:`.Operators.operate` and others to return further :class:`_expression.ColumnElement` constructs, so that the ``==`` operation above is replaced by a clause construct. .. seealso:: :ref:`types_operators` :attr:`.TypeEngine.comparator_factory` :class:`.ColumnOperators` :class:`.PropComparator` rNc8|t|S)zdImplement the ``<`` operator. In a column context, produces the clause ``a < b``. )rr rs r!__lt__zColumnOperators.__lt__T ||B&&&r#c8|t|S)zfImplement the ``<=`` operator. In a column context, produces the clause ``a <= b``. )rr rs r!__le__zColumnOperators.__le__\rYr#c8|t|S)zImplement the ``==`` operator. In a column context, produces the clause ``a = b``. If the target is ``None``, produces ``a IS NULL``. )rrrs r!rLzColumnOperators.__eq__f||B&&&r#c8|t|S)zImplement the ``!=`` operator. In a column context, produces the clause ``a != b``. If the target is ``None``, produces ``a IS NOT NULL``. )rrrs r!__ne__zColumnOperators.__ne__or]r#c8|t|S)zImplement the ``IS DISTINCT FROM`` operator. Renders "a IS DISTINCT FROM b" on most platforms; on some such as SQLite may render "a IS NOT b". .. versionadded:: 1.1 )ris_distinct_fromrs r!raz ColumnOperators.is_distinct_fromxs||,e444r#c8|t|S)zImplement the ``IS NOT DISTINCT FROM`` operator. Renders "a IS NOT DISTINCT FROM b" on most platforms; on some such as SQLite may render "a IS b". .. versionadded:: 1.1 )risnot_distinct_fromrs r!rcz#ColumnOperators.isnot_distinct_froms||/777r#c8|t|S)zdImplement the ``>`` operator. In a column context, produces the clause ``a > b``. )rr rs r!__gt__zColumnOperators.__gt__rYr#c8|t|S)zfImplement the ``>=`` operator. In a column context, produces the clause ``a >= b``. )rrrs r!__ge__zColumnOperators.__ge__rYr#c6|tS)zaImplement the ``-`` operator. In a column context, produces the clause ``-a``. )rrr's r!__neg__zColumnOperators.__neg__s ||C   r#c8|t|Sr+)rrrs r! __contains__zColumnOperators.__contains__s||He,,,r#c8|t|S)zImplement the [] operator. This can be used by some database-specific types such as PostgreSQL ARRAY and HSTORE. )rr)rindexs r! __getitem__zColumnOperators.__getitem__s||GU+++r#c8|t|S)zimplement the << operator. Not used by SQLAlchemy core, this is provided for custom operator systems which want to use << as an extension point. )rr rs r! __lshift__zColumnOperators.__lshift__||FE***r#c8|t|S)zimplement the >> operator. Not used by SQLAlchemy core, this is provided for custom operator systems which want to use >> as an extension point. )rrrs r! __rshift__zColumnOperators.__rshift__rqr#c8|t|S)zImplement the 'concat' operator. In a column context, produces the clause ``a || b``, or uses the ``concat()`` operator on MySQL. )r concat_oprs r!concatzColumnOperators.concats||Iu---r#c<|t||S)aImplement the ``like`` operator. In a column context, produces the expression:: a LIKE other E.g.:: stmt = select([sometable]).\ where(sometable.c.column.like("%foobar%")) :param other: expression to be compared :param escape: optional escape character, renders the ``ESCAPE`` keyword, e.g.:: somecolumn.like("foo/%bar", escape="/") .. seealso:: :meth:`.ColumnOperators.ilike` escape)rlike_oprr rys r!likezColumnOperators.likes.||GU6|:::r#c<|t||S)aImplement the ``ilike`` operator, e.g. case insensitive LIKE. In a column context, produces an expression either of the form:: lower(a) LIKE lower(other) Or on backends that support the ILIKE operator:: a ILIKE other E.g.:: stmt = select([sometable]).\ where(sometable.c.column.ilike("%foobar%")) :param other: expression to be compared :param escape: optional escape character, renders the ``ESCAPE`` keyword, e.g.:: somecolumn.ilike("foo/%bar", escape="/") .. seealso:: :meth:`.ColumnOperators.like` rx)rilike_opr{s r!ilikezColumnOperators.ilikes6||HeF|;;;r#c8|t|S)a Implement the ``in`` operator. In a column context, produces the clause ``column IN ``. The given parameter ``other`` may be: * A list of literal values, e.g.:: stmt.where(column.in_([1, 2, 3])) In this calling form, the list of items is converted to a set of bound parameters the same length as the list given:: WHERE COL IN (?, ?, ?) * A list of tuples may be provided if the comparison is against a :func:`.tuple_` containing multiple expressions:: from sqlalchemy import tuple_ stmt.where(tuple_(col1, col2).in_([(1, 10), (2, 20), (3, 30)])) * An empty list, e.g.:: stmt.where(column.in_([])) In this calling form, the expression renders a "false" expression, e.g.:: WHERE 1 != 1 This "false" expression has historically had different behaviors in older SQLAlchemy versions, see :paramref:`_sa.create_engine.empty_in_strategy` for behavioral options. .. versionchanged:: 1.2 simplified the behavior of "empty in" expressions * A bound parameter, e.g. :func:`.bindparam`, may be used if it includes the :paramref:`.bindparam.expanding` flag:: stmt.where(column.in_(bindparam('value', expanding=True))) In this calling form, the expression renders a special non-SQL placeholder expression that looks like:: WHERE COL IN ([EXPANDING_value]) This placeholder expression is intercepted at statement execution time to be converted into the variable number of bound parameter form illustrated earlier. If the statement were executed as:: connection.execute(stmt, {"value": [1, 2, 3]}) The database would be passed a bound parameter for each value:: WHERE COL IN (?, ?, ?) .. versionadded:: 1.2 added "expanding" bound parameters If an empty list is passed, a special "empty list" expression, which is specific to the database in use, is rendered. On SQLite this would be:: WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1) .. versionadded:: 1.3 "expanding" bound parameters now support empty lists * a :func:`_expression.select` construct, which is usually a correlated scalar select:: stmt.where( column.in_( select([othertable.c.y]). where(table.c.x == othertable.c.x) ) ) In this calling form, :meth:`.ColumnOperators.in_` renders as given:: WHERE COL IN (SELECT othertable.y FROM othertable WHERE othertable.x = table.x) :param other: a list of literals, a :func:`_expression.select` construct, or a :func:`.bindparam` construct that includes the :paramref:`.bindparam.expanding` flag set to True. )rin_oprs r!in_zColumnOperators.in_sx||E5)))r#c8|t|S)aimplement the ``NOT IN`` operator. This is equivalent to using negation with :meth:`.ColumnOperators.in_`, i.e. ``~x.in_(y)``. In the case that ``other`` is an empty sequence, the compiler produces an "empty not in" expression. This defaults to the expression "1 = 1" to produce true in all cases. The :paramref:`_sa.create_engine.empty_in_strategy` may be used to alter this behavior. .. versionchanged:: 1.2 The :meth:`.ColumnOperators.in_` and :meth:`.ColumnOperators.notin_` operators now produce a "static" expression for an empty IN sequence by default. .. seealso:: :meth:`.ColumnOperators.in_` )rnotin_oprs r!notin_zColumnOperators.notin_as,||He,,,r#c<|t||S)zimplement the ``NOT LIKE`` operator. This is equivalent to using negation with :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``. .. seealso:: :meth:`.ColumnOperators.like` rx)r notlike_opr{s r!notlikezColumnOperators.notlikeys||Jf|===r#c<|t||S)zimplement the ``NOT ILIKE`` operator. This is equivalent to using negation with :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``. .. seealso:: :meth:`.ColumnOperators.ilike` rx)r notilike_opr{s r!notilikezColumnOperators.notilikes||Kv|>>>r#c8|t|S)aVImplement the ``IS`` operator. Normally, ``IS`` is generated automatically when comparing to a value of ``None``, which resolves to ``NULL``. However, explicit usage of ``IS`` may be desirable if comparing to boolean values on certain platforms. .. seealso:: :meth:`.ColumnOperators.isnot` )ris_rs r!rzColumnOperators.is_s||C'''r#c8|t|S)a`Implement the ``IS NOT`` operator. Normally, ``IS NOT`` is generated automatically when comparing to a value of ``None``, which resolves to ``NULL``. However, explicit usage of ``IS NOT`` may be desirable if comparing to boolean values on certain platforms. .. seealso:: :meth:`.ColumnOperators.is_` )risnotrs r!rzColumnOperators.isnots||E5)))r#c *|jt|fi|S)a Implement the ``startswith`` operator. Produces a LIKE expression that tests against a match for the start of a string value:: column LIKE || '%' E.g.:: stmt = select([sometable]).\ where(sometable.c.column.startswith("foobar")) Since the operator uses ``LIKE``, wildcard characters ``"%"`` and ``"_"`` that are present inside the expression will behave like wildcards as well. For literal string values, the :paramref:`.ColumnOperators.startswith.autoescape` flag may be set to ``True`` to apply escaping to occurrences of these characters within the string value so that they match as themselves and not as wildcard characters. Alternatively, the :paramref:`.ColumnOperators.startswith.escape` parameter will establish a given character as an escape character which can be of use when the target expression is not a literal string. :param other: expression to be compared. This is usually a plain string value, but can also be an arbitrary SQL expression. LIKE wildcard characters ``%`` and ``_`` are not escaped by default unless the :paramref:`.ColumnOperators.startswith.autoescape` flag is set to True. :param autoescape: boolean; when True, establishes an escape character within the LIKE expression, then applies it to all occurrences of ``"%"``, ``"_"`` and the escape character itself within the comparison value, which is assumed to be a literal string and not a SQL expression. An expression such as:: somecolumn.startswith("foo%bar", autoescape=True) Will render as:: somecolumn LIKE :param || '%' ESCAPE '/' With the value of ``:param`` as ``"foo/%bar"``. .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The :paramref:`.ColumnOperators.startswith.autoescape` parameter is now a simple boolean rather than a character; the escape character itself is also escaped, and defaults to a forwards slash, which itself can be customized using the :paramref:`.ColumnOperators.startswith.escape` parameter. :param escape: a character which when given will render with the ``ESCAPE`` keyword to establish that character as the escape character. This character can then be placed preceding occurrences of ``%`` and ``_`` to allow them to act as themselves and not wildcard characters. An expression such as:: somecolumn.startswith("foo/%bar", escape="^") Will render as:: somecolumn LIKE :param || '%' ESCAPE '^' The parameter may also be combined with :paramref:`.ColumnOperators.startswith.autoescape`:: somecolumn.startswith("foo%bar^bat", escape="^", autoescape=True) Where above, the given literal parameter will be converted to ``"foo^%bar^^bat"`` before being passed to the database. .. seealso:: :meth:`.ColumnOperators.endswith` :meth:`.ColumnOperators.contains` :meth:`.ColumnOperators.like` )r startswith_oprr r<s r! startswithzColumnOperators.startswiths!lt|M5;;F;;;r#c *|jt|fi|S)a Implement the 'endswith' operator. Produces a LIKE expression that tests against a match for the end of a string value:: column LIKE '%' || E.g.:: stmt = select([sometable]).\ where(sometable.c.column.endswith("foobar")) Since the operator uses ``LIKE``, wildcard characters ``"%"`` and ``"_"`` that are present inside the expression will behave like wildcards as well. For literal string values, the :paramref:`.ColumnOperators.endswith.autoescape` flag may be set to ``True`` to apply escaping to occurrences of these characters within the string value so that they match as themselves and not as wildcard characters. Alternatively, the :paramref:`.ColumnOperators.endswith.escape` parameter will establish a given character as an escape character which can be of use when the target expression is not a literal string. :param other: expression to be compared. This is usually a plain string value, but can also be an arbitrary SQL expression. LIKE wildcard characters ``%`` and ``_`` are not escaped by default unless the :paramref:`.ColumnOperators.endswith.autoescape` flag is set to True. :param autoescape: boolean; when True, establishes an escape character within the LIKE expression, then applies it to all occurrences of ``"%"``, ``"_"`` and the escape character itself within the comparison value, which is assumed to be a literal string and not a SQL expression. An expression such as:: somecolumn.endswith("foo%bar", autoescape=True) Will render as:: somecolumn LIKE '%' || :param ESCAPE '/' With the value of ``:param`` as ``"foo/%bar"``. .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The :paramref:`.ColumnOperators.endswith.autoescape` parameter is now a simple boolean rather than a character; the escape character itself is also escaped, and defaults to a forwards slash, which itself can be customized using the :paramref:`.ColumnOperators.endswith.escape` parameter. :param escape: a character which when given will render with the ``ESCAPE`` keyword to establish that character as the escape character. This character can then be placed preceding occurrences of ``%`` and ``_`` to allow them to act as themselves and not wildcard characters. An expression such as:: somecolumn.endswith("foo/%bar", escape="^") Will render as:: somecolumn LIKE '%' || :param ESCAPE '^' The parameter may also be combined with :paramref:`.ColumnOperators.endswith.autoescape`:: somecolumn.endswith("foo%bar^bat", escape="^", autoescape=True) Where above, the given literal parameter will be converted to ``"foo^%bar^^bat"`` before being passed to the database. .. seealso:: :meth:`.ColumnOperators.startswith` :meth:`.ColumnOperators.contains` :meth:`.ColumnOperators.like` )r endswith_oprs r!endswithzColumnOperators.endswiths!lt|K99&999r#c *|jt|fi|S)a Implement the 'contains' operator. Produces a LIKE expression that tests against a match for the middle of a string value:: column LIKE '%' || || '%' E.g.:: stmt = select([sometable]).\ where(sometable.c.column.contains("foobar")) Since the operator uses ``LIKE``, wildcard characters ``"%"`` and ``"_"`` that are present inside the expression will behave like wildcards as well. For literal string values, the :paramref:`.ColumnOperators.contains.autoescape` flag may be set to ``True`` to apply escaping to occurrences of these characters within the string value so that they match as themselves and not as wildcard characters. Alternatively, the :paramref:`.ColumnOperators.contains.escape` parameter will establish a given character as an escape character which can be of use when the target expression is not a literal string. :param other: expression to be compared. This is usually a plain string value, but can also be an arbitrary SQL expression. LIKE wildcard characters ``%`` and ``_`` are not escaped by default unless the :paramref:`.ColumnOperators.contains.autoescape` flag is set to True. :param autoescape: boolean; when True, establishes an escape character within the LIKE expression, then applies it to all occurrences of ``"%"``, ``"_"`` and the escape character itself within the comparison value, which is assumed to be a literal string and not a SQL expression. An expression such as:: somecolumn.contains("foo%bar", autoescape=True) Will render as:: somecolumn LIKE '%' || :param || '%' ESCAPE '/' With the value of ``:param`` as ``"foo/%bar"``. .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The :paramref:`.ColumnOperators.contains.autoescape` parameter is now a simple boolean rather than a character; the escape character itself is also escaped, and defaults to a forwards slash, which itself can be customized using the :paramref:`.ColumnOperators.contains.escape` parameter. :param escape: a character which when given will render with the ``ESCAPE`` keyword to establish that character as the escape character. This character can then be placed preceding occurrences of ``%`` and ``_`` to allow them to act as themselves and not wildcard characters. An expression such as:: somecolumn.contains("foo/%bar", escape="^") Will render as:: somecolumn LIKE '%' || :param || '%' ESCAPE '^' The parameter may also be combined with :paramref:`.ColumnOperators.contains.autoescape`:: somecolumn.contains("foo%bar^bat", escape="^", autoescape=True) Where above, the given literal parameter will be converted to ``"foo^%bar^^bat"`` before being passed to the database. .. seealso:: :meth:`.ColumnOperators.startswith` :meth:`.ColumnOperators.endswith` :meth:`.ColumnOperators.like` )r contains_oprs r!rzColumnOperators.contains]s!nt|K99&999r#c *|jt|fi|S)aYImplements a database-specific 'match' operator. :meth:`~.ColumnOperators.match` attempts to resolve to a MATCH-like function or operator provided by the backend. Examples include: * PostgreSQL - renders ``x @@ to_tsquery(y)`` * MySQL - renders ``MATCH (x) AGAINST (y IN BOOLEAN MODE)`` * Oracle - renders ``CONTAINS(x, y)`` * other backends may provide special implementations. * Backends without any special implementation will emit the operator as "MATCH". This is compatible with SQLite, for example. )rmatch_oprs r!matchzColumnOperators.matchs t|He66v666r#c6|tS)zLProduce a :func:`_expression.desc` clause against the parent object.)rdesc_opr's r!desczColumnOperators.descs||G$$$r#c6|tS)zKProduce a :func:`_expression.asc` clause against the parent object.)rasc_opr's r!asczColumnOperators.ascs||F###r#c6|tS)zRProduce a :func:`_expression.nullsfirst` clause against the parent object.)r nullsfirst_opr's r! nullsfirstzColumnOperators.nullsfirsts||M***r#c6|tS)zQProduce a :func:`_expression.nullslast` clause against the parent object.)r nullslast_opr's r! nullslastzColumnOperators.nullslasts||L)))r#c8|t|S)zProduce a :func:`_expression.collate` clause against the parent object, given the collation string. .. seealso:: :func:`_expression.collate` )rcollate)r collations r!rzColumnOperators.collates||GY///r#c8|t|S)zaImplement the ``+`` operator in reverse. See :meth:`.ColumnOperators.__add__`. )r>rrs r!__radd__zColumnOperators.__radd__ ##C///r#c8|t|S)zaImplement the ``-`` operator in reverse. See :meth:`.ColumnOperators.__sub__`. )r>rrs r!__rsub__zColumnOperators.__rsub__rr#c8|t|S)zaImplement the ``*`` operator in reverse. See :meth:`.ColumnOperators.__mul__`. )r>rrs r!__rmul__zColumnOperators.__rmul__rr#c8|t|S)zaImplement the ``/`` operator in reverse. See :meth:`.ColumnOperators.__div__`. )r>rrs r!__rdiv__zColumnOperators.__rdiv__rr#c8|t|S)zaImplement the ``%`` operator in reverse. See :meth:`.ColumnOperators.__mod__`. )r>rrs r!__rmod__zColumnOperators.__rmod__rr#Fc>|t|||S)zzProduce a :func:`_expression.between` clause against the parent object, given the lower and upper range.  symmetric)r between_op)rcleftcrightrs r!betweenzColumnOperators.betweens ||Jv|KKKr#c6|tS)zZProduce a :func:`_expression.distinct` clause against the parent object. )r distinct_opr's r!distinctzColumnOperators.distincts ||K(((r#c6|tS)aProduce a :func:`_expression.any_` clause against the parent object. This operator is only appropriate against a scalar subquery object, or for some backends an column expression that is against the ARRAY type, e.g.:: # postgresql '5 = ANY (somearray)' expr = 5 == mytable.c.somearray.any_() # mysql '5 = ANY (SELECT value FROM table)' expr = 5 == select([table.c.value]).as_scalar().any_() .. seealso:: :func:`_expression.any_` - standalone version :func:`_expression.all_` - ALL operator .. versionadded:: 1.1 )rany_opr's r!any_zColumnOperators.any_.||F###r#c6|tS)aProduce a :func:`_expression.all_` clause against the parent object. This operator is only appropriate against a scalar subquery object, or for some backends an column expression that is against the ARRAY type, e.g.:: # postgresql '5 = ALL (somearray)' expr = 5 == mytable.c.somearray.all_() # mysql '5 = ALL (SELECT value FROM table)' expr = 5 == select([table.c.value]).as_scalar().all_() .. seealso:: :func:`_expression.all_` - standalone version :func:`_expression.any_` - ANY operator .. versionadded:: 1.1 )rall_opr's r!all_zColumnOperators.all_6rr#c8|t|S)a4Implement the ``+`` operator. In a column context, produces the clause ``a + b`` if the parent object has non-string affinity. If the parent object has a string affinity, produces the concatenation operator, ``a || b`` - see :meth:`.ColumnOperators.concat`. )rrrs r!__add__zColumnOperators.__add__Os||C'''r#c8|t|S)zdImplement the ``-`` operator. In a column context, produces the clause ``a - b``. )rrrs r!__sub__zColumnOperators.__sub__[ ||C'''r#c8|t|S)zdImplement the ``*`` operator. In a column context, produces the clause ``a * b``. )rrrs r!__mul__zColumnOperators.__mul__crr#c8|t|S)zdImplement the ``/`` operator. In a column context, produces the clause ``a / b``. )rrrs r!__div__zColumnOperators.__div__krr#c8|t|S)zdImplement the ``%`` operator. In a column context, produces the clause ``a % b``. )rrrs r!__mod__zColumnOperators.__mod__srr#c8|t|S)zeImplement the ``//`` operator. In a column context, produces the clause ``a / b``. )rrrs r! __truediv__zColumnOperators.__truediv__{s ||GU+++r#c8|t|S)zfImplement the ``//`` operator in reverse. See :meth:`.ColumnOperators.__truediv__`. )r>rrs r! __rtruediv__zColumnOperators.__rtruediv__s ##GU333r#r+F)7r?r@rArBrC timetuplerXr[rrOrLr_rarcrergrirkrnrprsrvr|rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#r!rVrV)s&##JIIB''''''!H'''''' 5 5 5 8 8 8''''''!!!---,,,++++++...;;;;2<<<<:\*\*\*|---0 > > > > ? ? ? ? ( ( ( * * *V<V<V|||Sr+r5)rr/rs r!r3r3s 144>>!  r#Nc0|||SNrx)r|rrrys r!rzrzs 66!F6 # ##r#c0|||Sr)rrs r!rrs 99Qv9 & &&r#c0|||Sr)rrs r!r~r~s 771V7 $ $$r#c0|||Sr)rrs r!rrs ::a: ' ''r#Fc2||||SNr)rrrcrs r!rrs 99QY9 / //r#c2||||Sr) notbetweenrs r! notbetween_oprs <<1 < 2 22r#c,||Sr+)rrs r!rrrr#c,||Sr+)rrs r!rrs 88A;;r#c*|Sr+)rrs r!rrs ::<<r#c*|Sr+)rrs r!rr 6688Or#c*|Sr+)rrs r!rrr r#cN|r|durtjd|d}t|tjjst d|dvr||||z}|d|dzd|dz}|||S) NTz;The autoescape parameter is now a simple boolean True/False/z*String value expected when autoescape=True)%_rrrx)rwarnrKcompat string_types TypeErrorreplace)rr ry autoescapes r!_escaped_like_implrsL T ! ! IM    >F%!9:: JHII I  # #MM&&6/::E c6C<0088fslKK 2eF # # ##r#c0t|j|||Sr+rrrrryrs r!rrs alAvz B BBr#c2t|j|||Sr+rrs r!notstartswith_oprs q|Q C C CCr#c0t|j|||Sr+rrrs r!rr! aj!VZ @ @@r#c2t|j|||Sr+rrs r!notendswith_opr!& qz1fj A A AAr#c0t|j|||Sr+rrrs r!rr+rr#c2t|j|||Sr+r$rs r!notcontains_opr&0r"r#c |j|fi|Sr+)rrrrSs r!rr5s 171    r#c |j|fi|Sr+)notmatchr(s r! notmatch_opr+:s 1:a  2  r#ctr+rrs r!comma_opr-?rr#ctr+rrs r! empty_in_opr/Crr#ctr+rrs r!empty_notin_opr1Hrr#ctr+rrs r! filter_opr3Mrr#c,||Sr+)rvrs r!ruruQs 88A;;r#c*|Sr+)rrs r!rrUr r#c*|Sr+)rrs r!rrYs 5577Nr#c*|Sr+)rrs r!rr]s <<>>r#c*|Sr+)rrs r!rras ;;==r#ctr+rrs r!json_getitem_opr:err#ctr+rrs r!json_path_getitem_opr<irr#cL|tvpt|to|jSr+)rrKr.r1r5s r!r1r1ms$   N 2y 9 9 Nb>NNr#c|tvSr+)rr5s r!is_commutativer?qs  r#c:|ttttfvSr+)rrrrr5s r!is_ordering_modifierrAus &'=,? ??r#cL|tvpt|to|jSr+)_natural_self_precedentrKr.rFr5s r!is_natural_self_precedentrDys- %% & b) $ $ &  %r#c2t|p|tvSr+)r1 _booleansr5s r! is_booleanrGs    /i/r#c8t||S)z[rotate a comparison operator 180 degrees. Note this is not the same as negation. )_mirrorgetr5s r!mirrorrKs ;;r2  r#_asbooli) canonical _smallesti_largestdc ||urt|rdSt|t|dtt|t|dt kS)NFr0)rD _PRECEDENCErJgetattrrNrO)r,r-s r! is_precedentr\sk78BBu gh i@@  __Wgg|X&N&N O OP Pr#r+r)NF)^rBr,rrrrrrr r r r r rrrrrrrrrpy2krobjectrr.rVrrrrrrrrrrrarcrrrr3rzrr~rrrrrrrrrrrrr!rr&rr+r-r/r1r3rurrrrr:r<r1r?rArDrFrGrIrKunion difference _associativerCsymbolrLrNrOrZr\rr#r!rdsU 109 CD+D+D+D+D+D+D+D+N5/5/5/5/5/5/5/5/p` 4` 4` 4` 4` 4i` 4` 4` 4FBS! 2r2r2&                     !!!$$$$$$$''''%%%%((((00003333$$$(CCCCDDDDAAAABBBBAAAABBBB                  OOO@@@&'4 - 000 r2r2r2r *!!9dC"899DDb"XNN &,, o34 $+i3 / / / DK t 4 4 4 4;zS 1 1 16 26r6 B6 B 6  R 6 R 6"66 Q666666q6 q!6" a#66$%6& a'6()6* Q+6,-6. 1/60 a162364 156676896:a;6<=6>?6@AA6BC6DE666FG6HI6JK6L1M6NO6PQ6R AS6T QU6V !W6XY6Z b[6\ Q]6^ A_6` Qa6bc6d Ae6f Sg66hy hk66 rPPPPPr#PK!!~##&__pycache__/annotation.cpython-311.pycnu[ |oiEddZddlmZddlmZGddeZiZd dZd d Zd Z d Z d Z dS)zThe :class:`.Annotated` class and related routines; creates hash-equivalent copies of SQL constructs which contain context-specific markers and associations. ) operators)utilcfeZdZdZdZdZdZdZddZd Z e d Z d Z d Z d ZdZdS) AnnotatedaEclones a ClauseElement and applies an 'annotations' dictionary. Unlike regular clones, this clone also mimics __hash__() and __cmp__() of the original element so that it takes its place in hashed collections. A reference to the original element is maintained, for the important reason of keeping its hash value current. When GC'ed, the hash value may be reused, causing conflicts. .. note:: The rationale for Annotated producing a brand new class, rather than placing the functionality directly within ClauseElement, is **performance**. The __hash__() method is absent on plain ClauseElement which leads to significantly reduced function call overhead, as the use of sets and dictionaries against ClauseElement objects is prevalent, but most are not "annotated". c|st|S|\}} t|j}n%#t$rt |j|}YnwxYwt|SN)object__new__annotated_classes __class__KeyError_new_annotation_type)clsargselementvaluess P/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/annotation.pyr zAnnotated.__new__&s '>>#&& &"OGV C'(9: C C C*7+>#&& &s6AAc|j|_||_||_t ||_dSr )__dict__copy_Annotated__element _annotationshash_hash)selfrrs r__init__zAnnotated.__init__4s8(--//  "']] c|j}||||Sr )rrupdate_with_annotations)rr_valuess r _annotatezAnnotated._annotate:s<#((**v%%g...rc|j|j}|j|_||_|Sr )r r rrr)rrclones rr!zAnnotated._with_annotations?s;&&t~66++--# rNTc||jS|j}|D]}||d||Sr )rrrpopr!)rrr%r"vs r _deannotatezAnnotated._deannotateEs] >> !',,..G % % At$$$$))'22 2rc 4|jjj||fi|Sr )rr _compiler_dispatch)rvisitorkws rr+zAnnotated._compiler_dispatchNs$:t~':4OOBOOOrc|jjSr )r _constructorrs rr/zAnnotated._constructorQs ~**rc|j}||jur|S|j|j|||jSr )r_clonerr r r)rr%s rr2zAnnotated._cloneUsX%%'' DN " "K N ! !$- 0 0 0>>%):;; ;rc,|j|j|jffSr )r rrr0s r __reduce__zAnnotated.__reduce__`s~0ABBBrc|jSr )rr0s r__hash__zAnnotated.__hash__cs zrct|jtjr |jj||St |t |kSr ) isinstancerrColumnOperatorsr __eq__r)rothers rr:zAnnotated.__eq__fsK dni&? @ @ ->+224?? ?;;$t**, ,r)NT)__name__ __module__ __qualname____doc__r rr#r!r)r+propertyr/r2r4r6r:rrrrs& ' ' '### ///  3333PPP++X+ < < <CCC-----rrNc8fd| |}d|S)zDeep copy the given ClauseElement, annotating each element with the given annotations dictionary. Elements within the exclude collection will be cloned but not annotated. cr?t|dr/|jr|}n#|jkr|}n|}||S)N proxy_setr%)hasattrrD intersectionr2rr#_copy_internals)elemnewelem annotationsr%excludes rr%z_deep_annotate..clone{s  k** ++G44  kkmmGG D- - -nn[11GGGe,,,rNrA)rrKrLr%s ``@r_deep_annotaterMssG       %.. E Nrc^tjfd| |}d|S)z2Deep copy the given element, removing annotations.cs|vr6|d}|s||<|S|S)NT)rr%rE)r)rH)rIrJr%clonedrs rr%z_deep_deannotate..clonesf  T''&&fD&AAG  # #% # 0 0 0 '&t N$< rN)r column_dict)rrr%rPs `@@r_deep_deannotaterRsW   F       %.. E NrcX||}||S)a Annotate the given ClauseElement and copy its internals so that internal objects refer to the new annotated object. Basically used to apply a "dont traverse" annotation to a selectable, without digging throughout the whole structure wasting time. )r#rH)rrKs r_shallow_annotaterTs. ,,G  Nrc t|tr|S|tvr t|S|jD]}|tvrt|}nt d|jz||fixt|<}|t d|jz<|S)Nz Annotated%s) issubclassrr __mro__typer<globals)rbase_clssuper_anno_clss rrrs#y!!& ! ! ! %%+ & & &(0H E ')- $xor))cX/7GIImcl*+ Orc|g}|rO|}||t|||MdSdSr )r'extend__subclasses__r)target_hierarchyrZstackrs r_prepare_annotationsrbsk  E ,iikk S''))***S(+++ ,,,,,rr ) r?rrr rr rMrRrTrrbrArrrds X-X-X-X-X-X-X-X-|86   *,,,,,rPK!Y++$__pycache__/sqltypes.cpython-311.pycnu[ |oiUZ dZddlZddlZddlZddlZddlmZddlmZddlm Z ddl m Z ddl m Z dd l m Z dd lmZdd lmZdd lmZdd lmZddlmZddl mZddl mZddl mZddl mZddl mZddl mZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm!Z!ej"rddl#Z#Gdde$Z%Gd d!e$Z&Gd"d#e$Z'Gd$d%e&eZ(Gd&d'e(Z)Gd(d)e(Z*Gd*d+e)Z+Gd,d-e%eZ,Gd.d/e,Z-Gd0d1e,Z.Gd2d3e%eZ/Gd4d5e/Z0Gd6d7e%eZ1Gd8d9e%eZ2Gd:d;e%eZ3Gd<d=eZ4Gd>d?e4Z5ej6d@dAGdBdCe5Z7GdDdEe Z8GdFdGee(e8Z9GdHdIeZ:GdJdKeee8Z;GdLdMe%eZ<GdNdOeeGdRdSe e'e&eZ?GdTdUe0Z@GdVdWe0ZAGdXdYe/ZBGdZd[e/ZCGd\d]e,ZDeDZEGd^d_e-ZFGd`dae.ZGGdbdce1ZHGdddee1ZIGdfdge2ZJGdhdie3ZKGdjdke)ZLGdldme)ZMGdndoe(ZNGdpdqe*ZOGdrdse(ZPGdtdue*ZQGdvdwe5ZRGdxdye4ZSGdzd{e4ZTGd|d}e;ZUGd~deZVGdde;ZWeVZXe;ZYe(ZZe,Z[eWZ\e]e,e^e0e_eYej`e/ejae2eje1ejbe3ejce=ejdeXi Zeejfre5eeeg<e*eeeh<ne*eeei<e(eeeh<eejjZkdZleYe _YeZe _Ze[e _[eXe _Xe\e _\e'e _mele _leYejn_YdS)zSQL specific types. N)elements) operators)type_api)_bind_or_error)NO_ARG)SchemaEventTarget)_literal_as_binds) _NONE_NAME) quoted_name)Slice) TypeCoerce)Emulated)NativeForEmulated) to_instance) TypeDecorator) TypeEngine)Variant)event)exc) inspection) processors)util)compat) langhelpers)picklecReZdZdZedZGddejZeZdS)_LookupExpressionAdapterzMixin expression adaptations based on lookup tables. These rules are currently used by the numeric, integer and date types which have detailed cross-expression coercion rules. ctNNotImplementedErrorselfs N/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/sqltypes.py_expression_adaptationsz0_LookupExpressionAdapter._expression_adaptations9s!###c2eZdZejZdZdS)#_LookupExpressionAdapter.Comparatorc|jj}|jj||j||j}||ur ||jfS||jjur ||jfS|t |fSr!)type_type_affinityr'get _blank_dictr)r%opother_comparator othertypelookups r&_adapt_expressionz5_LookupExpressionAdapter.Comparator._adapt_expression@s(-t|tjt jfrtj|jjfSttj| ||Sr!) radd isinstancer?r:NullType concat_opexprr,superr4)r%r0r1 __class__s r&r4z)Concatenable.Comparator._adapt_expressionUsoY]""z ((*=>(("!*DIN::\4d;;MM(r(r5r6r7r4 __classcell__rIs@r&r:rATs8         r(r:Nr5r6r7r;rr:r=r9r(r&r?r?OsO     Z*   $r(r?c<eZdZdZGddejZeZdS) IndexablezA mixin that marks a type as supporting indexing operations, such as array or JSON structures. .. versionadded:: 1.1.0 ceZdZdZdZdS)Indexable.Comparatorctr!r")r%indexs r&_setup_getitemz#Indexable.Comparator._setup_getitemns%'' 'r(cd||\}}}||||S)N) result_type)rToperate)r%rS adjusted_opadjusted_right_exprrVs r& __getitem__z Indexable.Comparator.__getitem__qsF ##E**  #<<0k  r(N)r5r6r7rTrZr9r(r&r:rQms2 ( ( (     r(r:NrMr9r(r&rOrOcsO     Z*   $r(rOceZdZdZdZejdd ddZd Zd Z d Z e d Z d Z edZdS)StringaThe base for all string and character types. In SQL, corresponds to VARCHAR. Can also take Python unicode objects and encode to the database's encoding in bind params (and the reverse for result sets.) The `length` field is usually required when the `String` type is used within a CREATE TABLE statement, as VARCHAR requires a length on most databases. string)1.3zThe :paramref:`.String.convert_unicode` parameter is deprecated and will be removed in a future release. All modern DBAPIs now support Python Unicode directly and this parameter is unnecessary.)r^zThe :paramref:`.String.unicode_errors` parameter is deprecated and will be removed in a future release. This parameter is unnecessary for modern Python DBAPIs and degrades performance significantly.)convert_unicode unicode_errorNFc||dkrtjd||_||_|p||_||_||_dS)aN Create a string-holding type. :param length: optional, a length for the column for use in DDL and CAST expressions. May be safely omitted if no ``CREATE TABLE`` will be issued. Certain databases may require a ``length`` for use in DDL, and will raise an exception when the ``CREATE TABLE`` DDL is issued if a ``VARCHAR`` with no length is included. Whether the value is interpreted as bytes or characters is database specific. :param collation: Optional, a column-level collation for use in DDL and CAST expressions. Renders using the COLLATE keyword supported by SQLite, MySQL, and PostgreSQL. E.g.:: >>> from sqlalchemy import cast, select, String >>> print(select([cast('some string', String(collation='utf8'))])) SELECT CAST(:param_1 AS VARCHAR COLLATE utf8) AS anon_1 :param convert_unicode: When set to ``True``, the :class:`.String` type will assume that input is to be passed as Python Unicode objects under Python 2, and results returned as Python Unicode objects. In the rare circumstance that the DBAPI does not support Python unicode under Python 2, SQLAlchemy will use its own encoder/decoder functionality on strings, referring to the value of the :paramref:`_sa.create_engine.encoding` parameter parameter passed to :func:`_sa.create_engine` as the encoding. For the extremely rare case that Python Unicode is to be encoded/decoded by SQLAlchemy on a backend that *does* natively support Python Unicode, the string value ``"force"`` can be passed here which will cause SQLAlchemy's encode/decode services to be used unconditionally. .. note:: SQLAlchemy's unicode-conversion flags and features only apply to Python 2; in Python 3, all string objects are Unicode objects. For this reason, as well as the fact that virtually all modern DBAPIs now support Unicode natively even under Python 2, the :paramref:`.String.convert_unicode` flag is inherently a legacy feature. .. note:: In the vast majority of cases, the :class:`.Unicode` or :class:`.UnicodeText` datatypes should be used for a :class:`_schema.Column` that expects to store non-ascii data. These datatypes will ensure that the correct types are used on the database side as well as set up the correct Unicode behaviors under Python 2. .. seealso:: :paramref:`_sa.create_engine.convert_unicode` - :class:`_engine.Engine`-wide parameter :param unicode_error: Optional, a method to use to handle Unicode conversion errors. Behaves like the ``errors`` keyword argument to the standard library's ``string.decode()`` functions, requires that :paramref:`.String.convert_unicode` is set to ``"force"`` Nforcez:convert_unicode must be 'force' when unicode_error is set.)r ArgumentErrorlength collation_expect_unicode_expect_unicode_error_warn_on_bytestring)r%rdrer_r`rhrfs r&__init__zString.__init__s`z  $G)C)C#O  ".A/%2"#6   r(cfd}|S)Nc~|dd}jjr|dd}d|zS)N'''%z%%'%s')replaceidentifier_preparer_double_percentsvaluedialects r&processz)String.literal_processor..processsAMM#t,,E*; 1 c400E> !r(r9r%rurvs ` r&literal_processorzString.literal_processors# " " " " "r(cjs|jrI|jrjdkrjrd}|SdSt j|jjfd}|SdS)Nrbct|tjr(tjdtj|f|S)N6Unicode type received non-unicode bind param value %r.)rDr binary_type warn_limitedellipses_stringrts r&rvz&String.bind_processor..process sI%eT-=>> -!7!%!5e! % r(ct|tjr|jdSr*|(tjdtj|f|S)Nrr{)rDr text_typergr}r~)rtencoderr%warn_on_bytestrings r&rvz&String.bind_processor..processsp!%88&wud.HII!LL+0A).!1%88: !Lr()rfr_supports_unicode_bindsrhcodecs getencoderencoding)r%rurvrrs` @@r&bind_processorzString.bind_processors  $ 7#:$ . !(G33+  %%%#N4 +G,<==%)%=" ! ! ! ! ! ! !N4r(c|jp|j}|o|jdup|jdv}|o|jo |jdk}|r@|rtj|j|jStj|j|jSdS)NT)rb force_nocheckr)rfr_returns_unicode_stringsr(to_conditional_unicode_processor_factoryrrgto_unicode_processor_factory)r%rucoltype wants_unicode needs_convertneeds_isinstances r&result_processorzString.result_processor)s,G0G %  +4 7 B#'AA   8/ 8$7    !J$d&@">$d&@4r(c6|jr tjStSr!)rfrrstrr$s r& python_typezString.python_type@s   > !Jr(c|jSr!)STRINGr%dbapis r&get_dbapi_typezString.get_dbapi_typeG |r(c.tjddS)NaThe convert_unicode on Engine and String as well as the unicode_error flag on String are deprecated. All modern DBAPIs now support Python Unicode natively under Python 2, and under Python 3 all strings are inherently Unicode. These flags will be removed in a future release.)rwarn_deprecated)clss r&_warn_deprecated_unicodezString._warn_deprecated_unicodeJs&  3     r()NNFNFF)r5r6r7r;__visit_name__rdeprecated_paramsrirxrrr<rr classmethodrr9r(r&r\r\~s  NT  $!W7W7W7! W7r   %%%N.X   [   r(r\ceZdZdZdZdS)TextajA variably sized string type. In SQL, usually corresponds to CLOB or TEXT. Can also take Python unicode objects and encode to the database's encoding in bind params (and the reverse for result sets.) In general, TEXT objects do not have a length; while some databases will accept a length argument here, it will be rejected by others. textNr5r6r7r;rr9r(r&rrUsNNNr(rc(eZdZdZdZdfd ZxZS)UnicodeaA variable length Unicode string type. The :class:`.Unicode` type is a :class:`.String` subclass that assumes input and output as Python ``unicode`` data, and in that regard is equivalent to the usage of the ``convert_unicode`` flag with the :class:`.String` type. However, unlike plain :class:`.String`, it also implies an underlying column type that is explicitly supporting of non-ASCII data, such as ``NVARCHAR`` on Oracle and SQL Server. This can impact the output of ``CREATE TABLE`` statements and ``CAST`` functions at the dialect level, and can also affect the handling of bound parameters in some specific DBAPI scenarios. The encoding used by the :class:`.Unicode` type is usually determined by the DBAPI itself; most modern DBAPIs feature support for Python ``unicode`` objects as bound values and result set values, and the encoding should be configured as detailed in the notes for the target DBAPI in the :ref:`dialect_toplevel` section. For those DBAPIs which do not support, or are not configured to accommodate Python ``unicode`` objects directly, SQLAlchemy does the encoding and decoding outside of the DBAPI. The encoding in this scenario is determined by the ``encoding`` flag passed to :func:`_sa.create_engine`. When using the :class:`.Unicode` type, it is only appropriate to pass Python ``unicode`` objects, and not plain ``str``. If a plain ``str`` is passed under Python 2, a warning is emitted. If you notice your application emitting these warnings but you're not sure of the source of them, the Python ``warnings`` filter, documented at http://docs.python.org/library/warnings.html, can be used to turn these warnings into exceptions which will illustrate a stack trace:: import warnings warnings.simplefilter('error') For an application that wishes to pass plain bytestrings and Python ``unicode`` objects to the ``Unicode`` type equally, the bytestrings must first be decoded into unicode. The recipe at :ref:`coerce_to_unicode` illustrates how this is done. .. seealso:: :class:`.UnicodeText` - unlengthed textual counterpart to :class:`.Unicode`. unicodeNc |dd|ddtt|jdd|i|dS)z Create a :class:`.Unicode` object. Parameters are the same as that of :class:`.String`, with the exception that ``convert_unicode`` defaults to ``True``. rfTrhrdNr9) setdefaultrHrrir%rdkwargsrIs r&rizUnicode.__init__sa +T222/666%gt%>>V>v>>>>>r(r!)r5r6r7r;rrirKrLs@r&rrdsO44lN ? ? ? ? ? ? ? ? ? ?r(rc.eZdZdZdZdfd ZdZxZS) UnicodeTexta#An unbounded-length Unicode string type. See :class:`.Unicode` for details on the unicode behavior of this object. Like :class:`.Unicode`, usage the :class:`.UnicodeText` type implies a unicode-capable type being used on the backend, such as ``NCLOB``, ``NTEXT``. unicode_textNc |dd|ddtt|jdd|i|dS)z Create a Unicode-converting Text type. Parameters are the same as that of :class:`_expression.TextClause`, with the exception that ``convert_unicode`` defaults to ``True``. rfTrhrdNr9)rrHrrirs r&rizUnicodeText.__init__sa +T222/666)k4  )BBB6BBBBBr(cdSr!r9r$s r&rz$UnicodeText._warn_deprecated_unicodes r(r!)r5r6r7r;rrirrKrLs@r&rrsc  $N C C C C C C       r(rcXeZdZdZdZdZedZdZe j dZ dS)IntegerzA type for ``int`` integers.integerc|jSr!NUMBERrs r&rzInteger.get_dbapi_typerr(ctSr!)intr$s r&rzInteger.python_types r(c d}|S)Nc t|Sr!rrs r&rvz*Integer.literal_processor..processu:: r(r9rws r&rxzInteger.literal_processor   r(c tjttt|jt t itjttt|jt t itjt|jt t itj t|jt t itj t|jt t iiSr!) rrCDaterrINumericmulIntervaldivtruedivsubr$s r&r'zInteger._expression_adaptationss Md M( MGT^WgF  'J MGT^WgF  r(N) r5r6r7r;rrr<rrxrmemoized_propertyr'r9r(r&rrsw&&NX       r(rceZdZdZdZdS) SmallIntegerzA type for smaller ``int`` integers. Typically generates a ``SMALLINT`` in DDL, and otherwise acts like a normal :class:`.Integer` on the Python side. small_integerNrr9r(r&rrs%NNNr(rceZdZdZdZdS) BigIntegerzA type for bigger ``int`` integers. Typically generates a ``BIGINT`` in DDL, and otherwise acts like a normal :class:`.Integer` on the Python side. big_integerNrr9r(r&rrs#NNNr(rceZdZdZdZdZ ddZedZdZ d Z ed Z d Z d Z ejd ZdS)raA type for fixed precision numbers, such as ``NUMERIC`` or ``DECIMAL``. This type returns Python ``decimal.Decimal`` objects by default, unless the :paramref:`.Numeric.asdecimal` flag is set to False, in which case they are coerced to Python ``float`` objects. .. note:: The :class:`.Numeric` type is designed to receive data from a database type that is explicitly known to be a decimal type (e.g. ``DECIMAL``, ``NUMERIC``, others) and not a floating point type (e.g. ``FLOAT``, ``REAL``, others). If the database column on the server is in fact a floating-point type, such as ``FLOAT`` or ``REAL``, use the :class:`.Float` type or a subclass, otherwise numeric coercion between ``float``/``Decimal`` may or may not function as expected. .. note:: The Python ``decimal.Decimal`` class is generally slow performing; cPython 3.3 has now switched to use the `cdecimal `_ library natively. For older Python versions, the ``cdecimal`` library can be patched into any application where it will replace the ``decimal`` library fully, however this needs to be applied globally and before any other modules have been imported, as follows:: import sys import cdecimal sys.modules["decimal"] = cdecimal Note that the ``cdecimal`` and ``decimal`` libraries are **not compatible with each other**, so patching ``cdecimal`` at the global level is the only way it can be used effectively with various DBAPIs that hardcode to import the ``decimal`` library. numeric NTc>||_||_||_||_dS)a Construct a Numeric. :param precision: the numeric precision for use in DDL ``CREATE TABLE``. :param scale: the numeric scale for use in DDL ``CREATE TABLE``. :param asdecimal: default True. Return whether or not values should be sent as Python Decimal objects, or as floats. Different DBAPIs send one or the other based on datatypes - the Numeric type will ensure that return values are one or the other across DBAPIs consistently. :param decimal_return_scale: Default scale to use when converting from floats to Python decimals. Floating point values will typically be much longer due to decimal inaccuracy, and most floating point database types don't have a notion of "scale", so by default the float type looks for the first ten decimal places when converting. Specifying this value will override that length. Types which do include an explicit ".scale" value, such as the base :class:`.Numeric` as well as the MySQL float types, will use the value of ".scale" as the default for decimal_return_scale, if not otherwise specified. .. versionadded:: 0.9.0 When using the ``Numeric`` type, care should be taken to ensure that the asdecimal setting is appropriate for the DBAPI in use - when Numeric applies a conversion from Decimal->float or float-> Decimal, this conversion incurs an additional performance overhead for all result columns received. DBAPIs that return Decimal natively (e.g. psycopg2) will have better accuracy and higher performance with a setting of ``True``, as the native translation to Decimal reduces the amount of floating- point issues at play, and the Numeric type itself doesn't need to apply any further conversions. However, another DBAPI which returns floats natively *will* incur an additional conversion overhead, and is still subject to floating point data loss - in which case ``asdecimal=False`` will at least remove the extra conversion overhead. N) precisionscaledecimal_return_scale asdecimal)r%rrrrs r&rizNumeric.__init__8s&f# $8!"r(c\|j|jSt|dd|jS|jS)Nr)rgetattrr_default_decimal_return_scaler$s r&_effective_decimal_return_scalez'Numeric._effective_decimal_return_scaleps7  $ 0, , T7D ) ) 5: 5 5r(c|jSr!rrs r&rzNumeric.get_dbapi_typeyrr(c d}|S)Nc t|Sr!rrs r&rvz*Numeric.literal_processor..process}rr(r9rws r&rxzNumeric.literal_processor|rr(c6|jr tjStSr!)rdecimalDecimalfloatr$s r&rzNumeric.python_types > ? "Lr(c,|jrdStjSr!)supports_native_decimalrto_floatr%rus r&rzNumeric.bind_processors  * '4& &r(c|jr`|jrdStjd|jd|jdt jtj |j |j n|j S|jr t j SdS)NzDialect +z does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.) rrrwarnnamedriverrto_decimal_processor_factoryrrrrrr%rurs r&rzNumeric.result_processors > . t #*,,, @">Oz-JJ; . !**tr(c tjttt|jt |jitjt|jt |jitjt|jt |jitjt|jt |jitj t|jt |jiiSr!) rrrrrIrrrrCrr$s r&r'zNumeric._expression_adaptationss M( MGT^WdnM    MGT^WdnM MGT^WdnM  r()NNNT)r5r6r7r;rrrir<rrrxrrrrrr'r9r(r&rr s$$LN$&!! 6#6#6#6#p66X6 X ''' :      r(rc*eZdZdZdZdZ ddZdZdS)Floata.Type representing floating point types, such as ``FLOAT`` or ``REAL``. This type returns Python ``float`` objects by default, unless the :paramref:`.Float.asdecimal` flag is set to True, in which case they are coerced to ``decimal.Decimal`` objects. .. note:: The :class:`.Float` type is designed to receive data from a database type that is explicitly known to be a floating point type (e.g. ``FLOAT``, ``REAL``, others) and not a decimal type (e.g. ``DECIMAL``, ``NUMERIC``, others). If the database column on the server is in fact a Numeric type, such as ``DECIMAL`` or ``NUMERIC``, use the :class:`.Numeric` type or a subclass, otherwise numeric coercion between ``float``/``Decimal`` may or may not function as expected. rNFc0||_||_||_dS)a Construct a Float. :param precision: the numeric precision for use in DDL ``CREATE TABLE``. :param asdecimal: the same flag as that of :class:`.Numeric`, but defaults to ``False``. Note that setting this flag to ``True`` results in floating point conversion. :param decimal_return_scale: Default scale to use when converting from floats to Python decimals. Floating point values will typically be much longer due to decimal inaccuracy, and most floating point database types don't have a notion of "scale", so by default the float type looks for the first ten decimal places when converting. Specifying this value will override that length. Note that the MySQL float types, which do include "scale", will use "scale" as the default for decimal_return_scale, if not otherwise specified. .. versionadded:: 0.9.0 N)rrr)r%rrrs r&rizFloat.__init__s 2#"$8!!!r(c|jr$tjtj|jS|jr tjSdSr!)rrrrrrrrrs r&rzFloat.result_processorsF > :!E  , & &4r()NFN)r5r6r7r;rrrirr9r(r&rrsT&N EEI9999:r(rcZeZdZdZdZd dZdZedZe j dZ dS) DateTimeaA type for ``datetime.datetime()`` objects. Date and time types return objects from the Python ``datetime`` module. Most DBAPIs have built in support for the datetime module, with the noted exception of SQLite. In the case of SQLite, date and time types are stored as strings which are then converted back to datetime objects when rows are returned. For the time representation within the datetime type, some backends include additional options, such as timezone support and fractional seconds support. For fractional seconds, use the dialect-specific datatype, such as :class:`.mysql.TIME`. For timezone support, use at least the :class:`_types.TIMESTAMP` datatype, if not the dialect-specific datatype object. datetimeFc||_dS)aConstruct a new :class:`.DateTime`. :param timezone: boolean. Indicates that the datetime type should enable timezone support, if available on the **base date/time-holding type only**. It is recommended to make use of the :class:`_types.TIMESTAMP` datatype directly when using this flag, as some databases include separate generic date/time-holding types distinct from the timezone-capable TIMESTAMP datatype, such as Oracle. Ntimezoner%rs r&rizDateTime.__init__s! r(c|jSr!DATETIMErs r&rzDateTime.get_dbapi_type# ~r(ctjSr!)dtrr$s r&rzDateTime.python_type&s {r(c~tjt|jitjt|jt tiiSr!)rrCrrIrrr$s r&r'z DateTime._expression_adaptations*s. MHdn5 MHdnhI  r(NF r5r6r7r;rrirr<rrrr'r9r(r&rrs" N ! ! ! !X      r(rcReZdZdZdZdZedZej dZ dS)rz'A type for ``datetime.date()`` objects.datec|jSr!rrs r&rzDate.get_dbapi_type<rr(ctjSr!)rrr$s r&rzDate.python_type? wr(c tjt|jtt t t itjt|jtttt t tiiSr!) rrCrrIrrTimerrr$s r&r'zDate._expression_adaptationsCsM M(h Mg((    r(N) r5r6r7r;rrr<rrrr'r9r(r&rr6sh11NX      r(rcZeZdZdZdZd dZdZedZe j dZ dS) rz'A type for ``datetime.time()`` objects.timeFc||_dSr!rrs r&riz Time.__init__bs   r(c|jSr!rrs r&rzTime.get_dbapi_typeerr(ctjSr!)rr r$s r&rzTime.python_typehrr(ctjttt|jitjttt|jiiSr!)rrCrrrrIrrr$s r&r'zTime._expression_adaptationsls2 MD(HdnE MD(HdnE  r(Nrrr9r(r&rr\s|11N!!!!X      r(rcneZdZdZd dZdZedZdZe j rdZ ndZ fd Z d Z xZS) _Binaryz&Define base behavior for binary types.Nc||_dSr!rdr%rds r&riz_Binary.__init__{s  r(cfd}|S)Ncj|jdd}d|zS)Nrlrmro)decoderrprss r&rvz*_Binary.literal_processor..processs1LL!122::3EEEE> !r(r9rws ` r&rxz_Binary.literal_processor~s# " " " " "r(ctjSr!)rr|r$s r&rz_Binary.python_types r(c<|jdS|jjfd}|S)Nc"| |SdSr!r9)rt DBAPIBinarys r&rvz'_Binary.bind_processor..processs "{5)))tr()rBinary)r%rurvrs @r&rz_Binary.bind_processors: = 4m*       r(c>tjrd}n tj}|S)Nc|=t|tjr|St|SdSr!)rDarraytostringrrs r&rvz)_Binary.result_processor..processs=(%eU[994#(>>#3#33"5zz)#tr()rjythonrto_strr%rurrvs r&rz_Binary.result_processors/{ ,$$$$%+Nr(c d}|S)Nc(|t|}|Sr!)bytesrs r&rvz)_Binary.result_processor..processs$!%LLE r(r9r"s r&rz_Binary.result_processors    Nr(ct|tjr|Stt|||Sz@See :meth:`.TypeEngine.coerce_compared_value` for a description.)rDr string_typesrHrcoerce_compared_value)r%r0rtrIs r&r)z_Binary.coerce_compared_values@ eT. / / IK$''==b%HH Hr(c|jSr!)BINARYrs r&rz_Binary.get_dbapi_typerr(r!)r5r6r7r;rirxr<rrrpy2krr)rrKrLs@r&rrws00  X   " y    "   IIIIIr(rceZdZdZdZddZdS) LargeBinarya A type for large binary byte data. The :class:`.LargeBinary` type corresponds to a large and/or unlengthed binary type for the target platform, such as BLOB on MySQL and BYTEA for PostgreSQL. It also handles the necessary conversions for the DBAPI. large_binaryNc>t||dS)z Construct a LargeBinary type. :param length: optional, a length for the column for use in DDL statements, for those binary types that accept a length, such as the MySQL BLOB type. rN)rrirs r&rizLargeBinary.__init__s# f-----r(r!)r5r6r7r;rrir9r(r&r.r.s9$N . . . . . .r(r.z0.6zsThe :class:`.Binary` class is deprecated and will be removed in a future relase. Please use :class:`.LargeBinary`.ceZdZdZdS)rc0tj|g|Ri|dSr!)r.rir%argkws r&rizBinary.__init__s)T.C...2.....r(N)r5r6r7rir9r(r&rrs# /////r(rceZdZdZ ddZdZdZdZd Zd Z d Z e d Z dd Z ddZdZdZdZdZdZdS) SchemaTypeabMark a type as possibly requiring schema-level DDL for usage. Supports types that must be explicitly created/dropped (i.e. PG ENUM type) as well as types that are complimented by table or schema level constraints, triggers, and other rules. :class:`.SchemaType` classes can also be targets for the :meth:`.DDLEvents.before_parent_attach` and :meth:`.DDLEvents.after_parent_attach` events, where the events fire off surrounding the association of the type object with a parent :class:`_schema.Column`. .. seealso:: :class:`.Enum` :class:`.Boolean` NFTc^|t|||_nd|_||_||_||_||_|rm|jrht j|jdtj |j t j|jdtj |j dSdSdS)N before_create after_drop) r rschemametadatainherit_schema_create_eventsrlistenrportable_instancemethod_on_metadata_create_on_metadata_drop)r%rr;r<r=quoter>s r&rizSchemaType.__init__s  #D%00DIIDI   ,,  dm  L ,T-EFF    L ,T-CDD         r(c.|||Sr!)r.)r%effective_schemamap_s r&_translate_schemazSchemaType._translate_schemasxx(*:;;;r(c ^|tj|jdSr!)_on_table_attachrr@ _set_tabler%columnr5s r& _set_parentzSchemaType._set_parents) rTrr?rr@_on_table_create_on_table_dropr<rArB)r%rLtablerSs r&rJzSchemaType._set_table(s?   ',DK"  F==fEE    (%(9?'K          (#&7%I      =  L,,&8    L,*&8      ! r(c :||jdS)NT)r>)adaptrIr%r5s r&rQzSchemaType.copySszz$.z>>>r(c |d|j}|d|j}|dd}|d|j||j||d|S)Nr;r<r>F)rr;r=r<r>r9)popr;r<rr=)r%impltyper5r;r<r>s r&rZzSchemaType.adaptVs|$+..66*dm44 0%88x .)       r(c,|jr |jjpdSr!)r<bindr$s r&r`zSchemaType.bindcs}3!3;t;r(c|t|}||j}|j|jur.t |t r|||dSdSdS)z.Issue CREATE DDL for this type, if applicable.Nr` checkfirst)r dialect_implrurIrDr7creater%r`rcts r&rezSchemaType.creategss <!$''D   dl + + ;dn , ,Az1J1J , HH$:H 6 6 6 6 6 - , , ,r(c|t|}||j}|j|jur.t |t r|||dSdSdS)z,Issue DROP DDL for this type, if applicable.Nrb)rrdrurIrDr7droprfs r&rizSchemaType.droppss <!$''D   dl + + ;dn , ,Az1J1J , FFF 4 4 4 4 4 - , , ,r(c ||j|sdS||j}|j|jur&t |t r|j||fi|dSdSdSr!)_is_impl_for_variantrurdrIrDr7rVr%targetr`r5rgs r&rVzSchemaType._on_table_createys((r::  F   dl + + ;dn , ,Az1J1J , A vt 2 2r 2 2 2 2 2 - , , ,r(c ||j|sdS||j}|j|jur&t |t r|j||fi|dSdSdSr!)rkrurdrIrDr7rWrls r&rWzSchemaType._on_table_drops((r::  F   dl + + ;dn , ,Az1J1J , A VT 0 0R 0 0 0 0 0 - , , ,r(c ||j|sdS||j}|j|jur&t |t r|j||fi|dSdSdSr!)rkrurdrIrDr7rArls r&rAzSchemaType._on_metadata_creates((r::  F   dl + + ;dn , ,Az1J1J , !A !&$ 5 5" 5 5 5 5 5 - , , ,r(c ||j|sdS||j}|j|jur&t |t r|j||fi|dSdSdSr!)rkrurdrIrDr7rBrls r&rBzSchemaType._on_metadata_drops((r::  F   dl + + ;dn , ,Az1J1J , A  3 3 3 3 3 3 3 - , , ,r(c|dd}|dS|j|vr||j|urdS|j|vr |d|uSdS)NrSTrO)r]r)r%rur5rSs r&rkzSchemaType._is_impl_for_variantsl&&!2D99  "4 LO + + -554 \ 0 0":.$6 61 0r()NNNFNTNF)r5r6r7r;rirGrMrTrJrQrZr<r`rerirVrWrArBrkr9r(r&r7r7s2.<<<<OOO)))V???    <<X<77775555333111666444 7 7 7 7 7r(r7cjeZdZdZdZejddZedZ fdZ dZ d Z ed Z ed Zd ZGd dejZeZdZdZdZfdZdZejddZfdZfdZfdZdZefdZxZS)EnumaT Generic Enum Type. The :class:`.Enum` type provides a set of possible string values which the column is constrained towards. The :class:`.Enum` type will make use of the backend's native "ENUM" type if one is available; otherwise, it uses a VARCHAR datatype and produces a CHECK constraint. Use of the backend-native enum type can be disabled using the :paramref:`.Enum.native_enum` flag, and the production of the CHECK constraint is configurable using the :paramref:`.Enum.create_constraint` flag. The :class:`.Enum` type also provides in-Python validation of string values during both read and write operations. When reading a value from the database in a result set, the string value is always checked against the list of possible values and a ``LookupError`` is raised if no match is found. When passing a value to the database as a plain string within a SQL statement, if the :paramref:`.Enum.validate_strings` parameter is set to True, a ``LookupError`` is raised for any string value that's not located in the given list of possible values; note that this impacts usage of LIKE expressions with enumerated values (an unusual use case). .. versionchanged:: 1.1 the :class:`.Enum` type now provides in-Python validation of input values as well as on data being returned by the database. The source of enumerated values may be a list of string values, or alternatively a PEP-435-compliant enumerated class. For the purposes of the :class:`.Enum` datatype, this class need only provide a ``__members__`` method. When using an enumerated class, the enumerated objects are used both for input and output, rather than strings as is the case with a plain-string enumerated type:: import enum class MyEnum(enum.Enum): one = 1 two = 2 three = 3 t = Table( 'data', MetaData(), Column('value', Enum(MyEnum)) ) connection.execute(t.insert(), {"value": MyEnum.two}) assert connection.scalar(t.select()) is MyEnum.two Above, the string names of each element, e.g. "one", "two", "three", are persisted to the database; the values of the Python Enum, here indicated as integers, are **not** used; the value of each enum can therefore be any kind of Python object whether or not it is persistable. In order to persist the values and not the names, the :paramref:`.Enum.values_callable` parameter may be used. The value of this parameter is a user-supplied callable, which is intended to be used with a PEP-435-compliant enumerated class and returns a list of string values to be persisted. For a simple enumeration that uses string values, a callable such as ``lambda x: [e.value for e in x]`` is sufficient. .. versionadded:: 1.1 - support for PEP-435-style enumerated classes. .. seealso:: :class:`_postgresql.ENUM` - PostgreSQL-specific type, which has additional functionality. :class:`.mysql.ENUM` - MySQL-specific type enum)r^zThe :paramref:`.Enum.convert_unicode` parameter is deprecated and will be removed in a future release. All modern DBAPIs now support Python Unicode directly and this parameter is unnecessary.)r_c2|||dS)aaConstruct an enum. Keyword arguments which don't apply to a specific backend are ignored by that backend. :param \*enums: either exactly one PEP-435 compliant enumerated type or one or more string or unicode enumeration labels. If unicode labels are present, the `convert_unicode` flag is auto-enabled. .. versionadded:: 1.1 a PEP-435 style enumerated class may be passed. :param convert_unicode: Enable unicode-aware bind parameter and result-set processing for this Enum's data. This is set automatically based on the presence of unicode label strings. :param create_constraint: defaults to True. When creating a non-native enumerated type, also build a CHECK constraint on the database against the valid values. .. versionadded:: 1.1 - added :paramref:`.Enum.create_constraint` which provides the option to disable the production of the CHECK constraint for a non-native enumerated type. :param metadata: Associate this type directly with a ``MetaData`` object. For types that exist on the target database as an independent schema construct (PostgreSQL), this type will be created and dropped within ``create_all()`` and ``drop_all()`` operations. If the type is not associated with any ``MetaData`` object, it will associate itself with each ``Table`` in which it is used, and will be created when any of those individual tables are created, after a check is performed for its existence. The type is only dropped when ``drop_all()`` is called for that ``Table`` object's metadata, however. :param name: The name of this type. This is required for PostgreSQL and any future supported database which requires an explicitly named type, or an explicitly named constraint in order to generate the type and/or a table that uses it. If a PEP-435 enumerated class was used, its name (converted to lower case) is used by default. :param native_enum: Use the database's native ENUM type when available. Defaults to True. When False, uses VARCHAR + check constraint for all backends. The VARCHAR length can be controlled with :paramref:`.Enum.length` :param length: Allows specifying a custom length for the VARCHAR when :paramref:`.Enum.native_enum` is False. By default it uses the length of the longest value. .. versionadded:: 1.3.16 :param schema: Schema name of this type. For types that exist on the target database as an independent schema construct (PostgreSQL), this parameter specifies the named schema in which the type is present. .. note:: The ``schema`` of the :class:`.Enum` type does not by default make use of the ``schema`` established on the owning :class:`_schema.Table`. If this behavior is desired, set the ``inherit_schema`` flag to ``True``. :param quote: Set explicit quoting preferences for the type's name. :param inherit_schema: When ``True``, the "schema" from the owning :class:`_schema.Table` will be copied to the "schema" attribute of this :class:`.Enum`, replacing whatever value was passed for the ``schema`` attribute. This also takes effect when using the :meth:`_schema.Table.tometadata` operation. :param validate_strings: when True, string values that are being passed to the database in a SQL statement will be checked for validity against the list of enumerated values. Unrecognized values will result in a ``LookupError`` being raised. .. versionadded:: 1.1.0b2 :param values_callable: A callable which will be passed the PEP-435 compliant enumerated type, which should then return a list of string values to be persisted. This allows for alternate usages such as using the string value of an enum to be persisted to the database instead of its name. .. versionadded:: 1.2.3 :param sort_key_function: a Python callable which may be used as the "key" argument in the Python ``sorted()`` built-in. The SQLAlchemy ORM requires that primary key columns which are mapped must be sortable in some way. When using an unsortable enumeration object such as a Python 3 ``Enum`` object, this parameter may be used to set a default sort key function for the objects. By default, the database value of the enumeration is used as the sorting function. .. versionadded:: 1.3.8 N) _enum_init)r%enumsr5s r&riz Enum.__init__sb r"""""r(c.|j|jgS|jSr!) enum_classrxr$s r&_enums_argumentzEnum._enums_argumentis ? &O$ $: r(c  |dd|_|dd|_|dd|_|dt|_|dt}|||\}}|||||dd}|d d |_|+|j D] }t|tj rd}n!d }n|}|j rtd |j D} nd } |js&|tur|| krtd |d| |} dx|jd<|jd<t#t$|| ||jr2|d|jjt0||dd|dd|dd|dd |dd|dddS)zinternal init for :class:`.Enum` and subclasses. friendly init helper used by subclasses to remove all the Enum-specific keyword arguments from kw. Allows all other arguments in kw to pass through. native_enumTcreate_constraintvalues_callableNsort_key_functionrdr_validate_stringsFc34K|]}t|VdSr!)len).0xs r& z"Enum._enum_init..s(44AQ444444r(rzYWhen provided, length must be larger or equal than the length of the longest enum value. z < )rdrfrr;r<r=rCr>)rr;r<r=rCr>)r]r}r~rr_sort_key_function_parse_into_values_setup_for_valuesrrxrDrrmax ValueError _valid_lookup_object_lookuprHrtrirzrr5lowerr7) r%rxr5 length_argvaluesobjectsr_erfrdrIs r&rwzEnum._enum_initps66-66!#(;T!B!B!vv&7>>"$&&)z+Enum._parse_into_values..s333awqz333r()r]rhasattrrzrrlist)r%rxr5rrrs @r&rzEnum._parse_into_valuess %RFF8$$E u::??wuQx???#AhDOo1G# '--do>>g33337333G7? ""DO%< r(c8t|_ttt |t |_tt||_jfd|DdS)NcDg|]}|jj|fSr9)rr)rrtr%s r&rz*Enum._setup_for_values..s>   *4+>u+EFG   r()rrxdictzipreversedrrupdate)r%rrr5s` r&rzEnum._setup_for_valuess&\\ !#hw&7&7&9I9I"J"JKK"3vw#7#788 !!    #        r(c:|jtur|jS|jSr!)rr_db_value_for_elemr$s r&rzEnum.sort_key_functions"  "f , ,* ** *r(c|jSr!)r}r$s r&nativez Enum.natives r(c . |j|S#t$r{}|js!t|tjr|cYd}~St jtd|d|j dtj |j |Yd}~dSd}~wwxYwNrlz3' is not among the defined enum values. Enum name: z. Possible values: )replace_context) rKeyErrorrrDrr(rraise_ LookupErrorrrrepr_tuple_namesrxr%elemerrs r&rzEnum._db_value_for_elems %d+ +   ( Zf)..   K!DD III'8DDD %(           s  B"BBABBceZdZfdZxZS)Enum.Comparatorcttj|||\}}|tjur%t |jj|jj }||fS)Nrf) rHrtr:r4rrFr\r,rdrf)r%r0r1typrIs r&r4z!Enum.Comparator._adapt_expressionslDOT22DD$GBY(((I$di6Os7Nr(rJrLs@r&r:rs8         r(r:c  |j|S#t$rS}tjt d|d|jdt j|j|Yd}~dSd}~wwxYwr) rrrrrrrrrxrs r&_object_value_for_elemzEnum._object_value_for_elems &t, ,    K  #4TZ@@@ !$           s  A,AA''A,cJtj|dgttgS)N)r}T) additional_kw to_inspect)r generic_reprrtr7r$s r&__repr__z Enum.__repr__s- 01j)    r(c f|d|j|d|j|d|j|d|j|d|j|d|j|dd|d |j|d |j|d |j |d |j d |vsJ|di|S)Nrfrrr;r=r<r>Fr}rr~rdrr9) rrfrrr;r=r<r}rr~rdr%r^r5s r&adapt_to_emulatedzEnum.adapt_to_emulateds ')=>>> ($*?@@@ fdi((( h ,,, &(;<<< j$-000 &... mT%5666 ')=>>> )4+ABBB h ,,,2~~~~x~~"~~r(c Z|j|d<tt|j|fi|S)Nr)r{rHrtrZ)r%r^r5rIs r&rZz Enum.adapt+s4+8 &uT4  &x662666r(c f||j|sdS|j p |jj Srr)rkrur}supports_native_enumr%compilerr5s r&_should_create_constraintzEnum._should_create_constraint/s>(()92>> 5 M(8(M$M r(sqlalchemy.sql.schemac ht||||jsdS||}|t |||j|jtn|jtj |j d|id}|j |usJdS)NrSTr _create_rule _type_bound)r7rJr~rTCheckConstraint type_coercein_rxrr rr@rrXr%r;rLrXrSrs r&rJzEnum._set_table6sdFE222%  F==fEE  " "  % % ) )$* 5 5#y0di5."O4 #  w%r(chtt|fd}|S)NcL|}r |}|Sr!rrtparent_processorr%s r&rvz'Enum.literal_processor..processM3++E22E 0((//Lr()rHrtrxr%rurvrrIs` @r&rxzEnum.literal_processorJsH t,,>>wGG       r(chfd}tt||S)NcL|}r |}|Sr!rrs r&rvz$Enum.bind_processor..processVrr()rHrtrrs` @r&rzEnum.bind_processorUsH       !t,,;;GDDr(cjtt||fd}|S)NcLr |}|}|Sr!)rrs r&rvz&Enum.result_processor..processbs3 0((////66ELr()rHrtr)r%rurrvrrIs` @r&rzEnum.result_processor_sJ t,,==gwOO      r(c &tj|fi|Sr!)r7rQr[s r&rQz Enum.copykst**r***r(cT|jr|jStt|jSr!)rzrHrtr)r%rIs r&rzEnum.python_typens( ? 1? "t$$0 0r() r5r6r7r;rrrrir<r{rwrrrrrr\r:r=rrrrZr dependenciesrJrxrrrQrrKrLs@r&rtrts7JJXNT h#h#h#TX = = = = = ~   "    ++X+   X <     V&   $"      77777   T.//  0/ &          +++1111X11111r(rtcPeZdZdZeZejddffd ZdZ dZ dZ dZ xZ S) PickleTypeaHolds Python objects, which are serialized using pickle. PickleType builds upon the Binary type to apply Python's ``pickle.dumps()`` to incoming objects, and ``pickle.loads()`` on the way out, allowing any pickleable Python object to be stored as a serialized binary field. To allow ORM change events to propagate for elements associated with :class:`.PickleType`, see :ref:`mutable_toplevel`. Nc||_|pt|_||_t t |dS)a Construct a PickleType. :param protocol: defaults to ``pickle.HIGHEST_PROTOCOL``. :param pickler: defaults to cPickle.pickle or pickle.pickle if cPickle is not available. May be any object with pickle-compatible ``dumps`` and ``loads`` methods. :param comparator: a 2-arg callable predicate used to compare values of this type. If left as ``None``, the Python "equals" operator is used to compare values. N)protocolrpickler comparatorrHrri)r%rrrrIs r&rizPickleType.__init__sA"! (& $ j$((*****r(c.t|jd|jffSr!)rrrr$s r& __reduce__zPickleType.__reduce__sDM4AAAr(c|j||jj|jrfd}nfd}|S)Nc6| |}|Sr!r9)rtdumpsimpl_processorrs r&rvz*PickleType.bind_processor..processs*$!E%22E%~e,,,r(c$| |}|Sr!r9)rtrrs r&rvz*PickleType.bind_processor..processs$!E%22E r()rRrrrr)r%rurvrrrs @@@r&rzPickleType.bind_processors11':: "=   - - - - - - - -       r(ct|j|||jjrfd}nfd}|S)Nc8|}|dS|Sr!r9)rtrloadss r&rvz,PickleType.result_processor..processs*&u--=4uU||#r(c"|dS|Sr!r9)rtrs r&rvz,PickleType.result_processor..processs=4uU||#r()rRrrr)r%rurrvrrs @@r&rzPickleType.result_processorsp33GWEE "  $ $ $ $ $ $ $ $ $ $ $ $ $ r(cH|jr|||S||kSr!)rr%rys r&compare_valueszPickleType.compare_valuess) ? ??1a(( (6Mr()r5r6r7r;r.rRrHIGHEST_PROTOCOLrirrrrrKrLs@r&rrvs   D.++++++,BBB((r(rceZdZdZdZdZddZdZej ddZ e d Z e gd Zd Zd Zd ZdZdS)BooleanaBA bool datatype. :class:`.Boolean` typically uses BOOLEAN or SMALLINT on the DDL side, and on the Python side deals in ``True`` or ``False``. The :class:`.Boolean` datatype currently has two levels of assertion that the values persisted are simple true/false values. For all backends, only the Python values ``None``, ``True``, ``False``, ``1`` or ``0`` are accepted as parameter values. For those backends that don't support a "native boolean" datatype, a CHECK constraint is also created on the target column. Production of the CHECK constraint can be disabled by passing the :paramref:`.Boolean.create_constraint` flag set to ``False``. .. versionchanged:: 1.2 the :class:`.Boolean` datatype now asserts that incoming Python values are already in pure boolean form. booleanTNc0||_||_||_dS)aLConstruct a Boolean. :param create_constraint: defaults to True. If the boolean is generated as an int/smallint, also create a CHECK constraint on the table that ensures 1 or 0 as a value. :param name: if a CHECK constraint is generated, specify the name of the constraint. N)r~rr>)r%r~rr>s r&rizBoolean.__init__s!"3 ,r(c n||j|sdS|jj o |jjSrr)rkrusupports_native_boolean#non_native_boolean_check_constraintrs r&rz!Boolean._should_create_constraintsB(()92>> 5 8 8 E D r(rc *|jsdS||}|t||ddg|jt n|jtj|j d|id}|j |usJdS)NrrrSTr) r~rTrrrrr rr@rrXrs r&rJzBoolean._set_tables%  F==fEE  " "  % % ) )1a& 1 1#y0di5."O4 #  w%r(ctSr!)boolr$s r&rzBoolean.python_type r()NTFc||jvr9t|tstd|zt d|z|S)NzNot a boolean value: %rz$Value %r is not None, True, or False) _strict_boolsrDr TypeErrorrr%rts r&_strict_as_boolzBoolean._strict_as_boolsW * * *eS))  9E ABBB :UB r(c||d}|d|dfd}|S)Nc6|rnSr!)r)rtfalser%trues r&rvz*Boolean.literal_processor..process$s //66A44E Ar()statement_compiler visit_true visit_false)r%rurrvrrs` @@r&rxzBoolean.literal_processorsq--gt<<""4(($$T** B B B B B B Br(cP|j|jrtntfd}|S)Nc8|}| |}|Sr!r9)rt_coercers r&rvz'Boolean.bind_processor..process0s*#OE**E Lr()rrrr)r%rurvr rs @@r&rzBoolean.bind_processor)sH.  * GGG       r(c,|jrdStjSr!)rrint_to_booleanrs r&rzBoolean.result_processor8s  * -4, ,r()TNT)r5r6r7r;rrrirrrrJr<r frozensetrrrxrrr9r(r&rrs(N F - - - -   T.//  0/ "XI11122M   -----r(rcJeZdZejdZedZdZdS)_AbstractIntervalc >tjttt|jttt t itjt|jitjt|jitj t|jitj t|jiiSr!) rrCrrrrIrrrrrrr$s r&r'z)_AbstractInterval._expression_adaptations@si Mh$.(d  MHdn5 MGT^4  8 MGT^4  r(ctSr!)rr$s r&r-z _AbstractInterval._type_affinityRsr(c8|j||Sr')rRr))r%r0rts r&r)z'_AbstractInterval.coerce_compared_valueVsy..r5999r(N) r5r6r7rrr'r<r-r)r9r(r&rr?s[    "X:::::r(rceZdZdZeZejdZ d fd Z e dZ dZ dZd ZxZS) raA type for ``datetime.timedelta()`` objects. The Interval type deals with ``datetime.timedelta`` objects. In PostgreSQL, the native ``INTERVAL`` type is used; for others, the value is stored as a date which is relative to the "epoch" (Jan. 1, 1970). Note that the ``Interval`` type does not currently provide date arithmetic operations on platforms which do not support interval types natively. Such operations usually require transformation of both sides of the expression (such as, conversion of both sides into integer epoch values first) which currently is a manual procedure (such as via :attr:`~sqlalchemy.sql.expression.func`). rTNctt|||_||_||_dS)a;Construct an Interval object. :param native: when True, use the actual INTERVAL type provided by the database, if supported (currently PostgreSQL, Oracle). Otherwise, represent the interval data as an epoch value regardless. :param second_precision: For native interval types which support a "fractional seconds precision" parameter, i.e. Oracle and PostgreSQL :param day_precision: for native interval types which support a "day precision" parameter, i.e. Oracle. N)rHrrirsecond_precision day_precision)r%rrrrIs r&rizInterval.__init__ps>" h&&((( 0*r(ctjSr!)r timedeltar$s r&rzInterval.python_types |r(c (tj||fi|Sr!)rrZrs r&rzInterval.adapt_to_emulateds &tX<<<<.processs"$!EME%~e,,,r(c||z}|Sr!r9rtrs r&rvz(Interval.bind_processor..processs$!EME r()rRrr)r%rurvrrs @@r&rzInterval.bind_processorsk11'::    - - - - - - -      r(cj|j|||jrfd}nfd}|S)Nc,|}|dS|z Sr!r9rs r&rvz*Interval.result_processor..processs&&u--=4u}$r(c|dS|z Sr!r9r s r&rvz*Interval.result_processor..processs=4u}$r()rRrr)r%rurrvrrs @@r&rzInterval.result_processorsm33GWEE   % % % % % % % % % % % % % r()TNN)r5r6r7r;rrRrrutcfromtimestamprrir<rrrrrKrLs@r&rr[s D K ( ( + +E++++++,X===&r(rcFeZdZdZdZdZejdZ ddZ Gdde Z Gdde Z Gd d e Z Gd d ejejZeZed ZedZejdZejdZdZdZdS)JSONaRepresent a SQL JSON type. .. note:: :class:`_types.JSON` is provided as a facade for vendor-specific JSON types. Since it supports JSON SQL operations, it only works on backends that have an actual JSON type, currently: * PostgreSQL * MySQL as of version 5.7 (MariaDB as of the 10.2 series does not) * SQLite as of version 3.9 :class:`_types.JSON` is part of the Core in support of the growing popularity of native JSON datatypes. The :class:`_types.JSON` type stores arbitrary JSON format data, e.g.:: data_table = Table('data_table', metadata, Column('id', Integer, primary_key=True), Column('data', JSON) ) with engine.connect() as conn: conn.execute( data_table.insert(), data = {"key1": "value1", "key2": "value2"} ) **JSON-Specific Expression Operators** The :class:`_types.JSON` datatype provides these additional SQL operations: * Keyed index operations:: data_table.c.data['some key'] * Integer index operations:: data_table.c.data[3] * Path index operations:: data_table.c.data[('key_1', 'key_2', 5, ..., 'key_n')] * Data casters for specific JSON element types, subsequent to an index or path operation being invoked:: data_table.c.data["some key"].as_integer() .. versionadded:: 1.3.11 Additional operations may be available from the dialect-specific versions of :class:`_types.JSON`, such as :class:`_postgresql.JSON` and :class:`_postgresql.JSONB` which both offer additional PostgreSQL-specific operations. **Casting JSON Elements to Other Types** Index operations, i.e. those invoked by calling upon the expression using the Python bracket operator as in ``some_column['some key']``, return an expression object whose type defaults to :class:`_types.JSON` by default, so that further JSON-oriented instructions may be called upon the result type. However, it is likely more common that an index operation is expected to return a specific scalar element, such as a string or integer. In order to provide access to these elements in a backend-agnostic way, a series of data casters are provided: * :meth:`.JSON.Comparator.as_string` - return the element as a string * :meth:`.JSON.Comparator.as_boolean` - return the element as a boolean * :meth:`.JSON.Comparator.as_float` - return the element as a float * :meth:`.JSON.Comparator.as_integer` - return the element as an integer These data casters are implemented by supporting dialects in order to assure that comparisons to the above types will work as expected, such as:: # integer comparison data_table.c.data["some_integer_key"].as_integer() == 5 # boolean comparison data_table.c.data["some_boolean"].as_boolean() == True .. versionadded:: 1.3.11 Added type-specific casters for the basic JSON data element types. .. note:: The data caster functions are new in version 1.3.11, and supersede the previous documented approaches of using CAST; for reference, this looked like:: from sqlalchemy import cast, type_coerce from sqlalchemy import String, JSON cast( data_table.c.data['some_key'], String ) == type_coerce(55, JSON) The above case now works directly as:: data_table.c.data['some_key'].as_integer() == 5 For details on the previous comparison approach within the 1.3.x series, see the documentation for SQLAlchemy 1.2 or the included HTML files in the doc/ directory of the version's distribution. **Detecting Changes in JSON columns when using the ORM** The :class:`_types.JSON` type, when used with the SQLAlchemy ORM, does not detect in-place mutations to the structure. In order to detect these, the :mod:`sqlalchemy.ext.mutable` extension must be used. This extension will allow "in-place" changes to the datastructure to produce events which will be detected by the unit of work. See the example at :class:`.HSTORE` for a simple example involving a dictionary. **Support for JSON null vs. SQL NULL** When working with NULL values, the :class:`_types.JSON` type recommends the use of two specific constants in order to differentiate between a column that evaluates to SQL NULL, e.g. no value, vs. the JSON-encoded string of ``"null"``. To insert or select against a value that is SQL NULL, use the constant :func:`.null`:: from sqlalchemy import null conn.execute(table.insert(), json_value=null()) To insert or select against a value that is JSON ``"null"``, use the constant :attr:`_types.JSON.NULL`:: conn.execute(table.insert(), json_value=JSON.NULL) The :class:`_types.JSON` type supports a flag :paramref:`_types.JSON.none_as_null` which when set to True will result in the Python constant ``None`` evaluating to the value of SQL NULL, and when set to False results in the Python constant ``None`` evaluating to the value of JSON ``"null"``. The Python value ``None`` may be used in conjunction with either :attr:`_types.JSON.NULL` and :func:`.null` in order to indicate NULL values, but care must be taken as to the value of the :paramref:`_types.JSON.none_as_null` in these cases. **Customizing the JSON Serializer** The JSON serializer and deserializer used by :class:`_types.JSON` defaults to Python's ``json.dumps`` and ``json.loads`` functions; in the case of the psycopg2 dialect, psycopg2 may be using its own custom loader function. In order to affect the serializer / deserializer, they are currently configurable at the :func:`_sa.create_engine` level via the :paramref:`_sa.create_engine.json_serializer` and :paramref:`_sa.create_engine.json_deserializer` parameters. For example, to turn off ``ensure_ascii``:: engine = create_engine( "sqlite://", json_serializer=lambda obj: json.dumps(obj, ensure_ascii=False)) .. versionchanged:: 1.3.7 SQLite dialect's ``json_serializer`` and ``json_deserializer`` parameters renamed from ``_json_serializer`` and ``_json_deserializer``. .. seealso:: :class:`_postgresql.JSON` :class:`_postgresql.JSONB` :class:`.mysql.JSON` :class:`_sqlite.JSON` .. versionadded:: 1.1 F JSON_NULLc||_dS)aConstruct a :class:`_types.JSON` type. :param none_as_null=False: if True, persist the value ``None`` as a SQL NULL value, not the JSON encoding of ``null``. Note that when this flag is False, the :func:`.null` construct can still be used to persist a NULL value:: from sqlalchemy import null conn.execute(table.insert(), data=null()) .. note:: :paramref:`_types.JSON.none_as_null` does **not** apply to the values passed to :paramref:`_schema.Column.default` and :paramref:`_schema.Column.server_default`; a value of ``None`` passed for these parameters means "no default present". .. seealso:: :attr:`.types.JSON.NULL` N none_as_null)r%r*s r&riz JSON.__init__s.)r(cReZdZdZeZeZdZdZ dZ dZ dS)JSON.JSONElementTypez?Common function for index / path elements in a JSON expression.c6|j|Sr!)_string_cached_bind_processorrs r&string_bind_processorz*JSON.JSONElementType.string_bind_processors<66w?? ?r(c6|j|Sr!)r._cached_literal_processorrs r&string_literal_processorz-JSON.JSONElementType.string_literal_processors<99'BB Br(ct|j|||fd}|S)Ncr!t|tr |}n'r%t|tjr |}|Sr!rDrrr(rt int_processorstring_processors r&rvz4JSON.JSONElementType.bind_processor..process^ 4Zs%;%;4)M%00EE%4*UD.processr:r()r;r2r3r<s @@r&rxz&JSON.JSONElementType.literal_processorsR MCCGLLM#<||jtj |tj }tj }|||jfS)N)bindparam_type)rDrr(rcollections_abcSequence_check_literalrGrjson_path_getitem_opr&rGjson_getitem_oprCr,)r%default_comparatorrSoperators r&rTzJSON.Comparator._setup_getitemseT%677 5Jv-6== 5+99I2#'#4 :%9*99I-#'#5 : %4UDI- -r(cF|tdS)aFCast an indexed value as boolean. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_boolean() ]).where( mytable.c.json_column['some_data'].as_boolean() == True ) .. versionadded:: 1.3.11 as_boolean)_binary_w_typerr$s r&rTzJSON.Comparator.as_boolean &&wyy,?? ?r(cF|tdS)a`Cast an indexed value as string. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_string() ]).where( mytable.c.json_column['some_data'].as_string() == 'some string' ) .. versionadded:: 1.3.11 as_string)rUr\r$s r&rXzJSON.Comparator.as_string s&&vxx== =r(cF|tdS)aCCast an indexed value as integer. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_integer() ]).where( mytable.c.json_column['some_data'].as_integer() == 5 ) .. versionadded:: 1.3.11 as_integer)rUrr$s r&rZzJSON.Comparator.as_integer( rVr(cF|tdS)aACast an indexed value as float. e.g.:: stmt = select([ mytable.c.json_column['some_data'].as_float() ]).where( mytable.c.json_column['some_data'].as_float() == 29.75 ) .. versionadded:: 1.3.11 as_float)rUrr$s r&r\zJSON.Comparator.as_float8 s&&uww ;; ;r(c|jS)a Cast an indexed value as JSON. This is the default behavior of indexed elements in any case. Note that comparison of full JSON structures may not be supported by all backends. .. versionadded:: 1.3.11 )rGr$s r&as_jsonzJSON.Comparator.as_jsonI s 9 r(ct|jtjr$|jjt jt jfvrtj d|d|d|j }||_ |S)NzThe JSON cast operator JSON.z9() only works with a JSON index expression e.g. col['q'].z()) rDrGrBinaryExpressionrRrrPrOrInvalidRequestError_cloner,)r%r method_namerGs r&rUzJSON.Comparator._binary_w_typeV s 84 #).,--#{{KKK1 9##%%DDIKr(N) r5r6r7r;rrrTrTrXrZr\r^rUr9r(r&r:rIsDD  > ? ? . . @ ? .. @ @ @  > > >" @ @ @  < < <"        r(r:ctSr!)rr$s r&rzJSON.python_typeh rr(c|j S)z)Alias of :attr:`_types.JSON.none_as_null`r)r$s r&should_evaluate_nonezJSON.should_evaluate_nonel s$$$r(c| |_dSr!r)rs r&rfzJSON.should_evaluate_noneq s %Ir(c"tdS)NTr)r\r$s r& _str_implzJSON._str_implu sd++++r(ctj||jp tjfd}|S)Nc|jurd}n%t|tjs | jrdS|}r |}|Sr!)NULLrDrNullr*)rt serializedjson_serializerr%string_processs r&rvz$JSON.bind_processor..process~ sh !!E8=11  $"3 t(//J 8+^J77  r()rir_json_serializerjsonr)r%rurvrorps` @@r&rzJSON.bind_processory sS66w??!2@dj       r(cr|j|||jp tjfd}|S)Nc<|dSr |}|Sr!r9)rtjson_deserializerrps r&rvz&JSON.result_processor..process s5}t .&u--$$U++ +r()rir_json_deserializerrrr)r%rurrvrurps @@r&rzJSON.result_processor sP88'JJ#6D$* , , , , , ,r(Nr)r5r6r7r;rhashablersymbolrlrirr?rCrGrOr:r?r=r<rrfsetterrrirrr9r(r&r&r&svvpNH 4;{ # #D)V))))2$$$$$*$$$L                xxxxxY)<+Bxxxt$ X%%X% &&! & ,,,(     r(r&ceZdZdZdZdZdZ Gddeje jZeZ d dZ e dZ e d Zd Zd Zfd ZxZS)ARRAYa Represent a SQL Array type. .. note:: This type serves as the basis for all ARRAY operations. However, currently **only the PostgreSQL backend has support for SQL arrays in SQLAlchemy**. It is recommended to use the :class:`_postgresql.ARRAY` type directly when using ARRAY types with PostgreSQL, as it provides additional operators specific to that backend. :class:`_types.ARRAY` is part of the Core in support of various SQL standard functions such as :class:`_functions.array_agg` which explicitly involve arrays; however, with the exception of the PostgreSQL backend and possibly some third-party dialects, no other SQLAlchemy built-in dialect has support for this type. An :class:`_types.ARRAY` type is constructed given the "type" of element:: mytable = Table("mytable", metadata, Column("data", ARRAY(Integer)) ) The above type represents an N-dimensional array, meaning a supporting backend such as PostgreSQL will interpret values with any number of dimensions automatically. To produce an INSERT construct that passes in a 1-dimensional array of integers:: connection.execute( mytable.insert(), data=[1,2,3] ) The :class:`_types.ARRAY` type can be constructed given a fixed number of dimensions:: mytable = Table("mytable", metadata, Column("data", ARRAY(Integer, dimensions=2)) ) Sending a number of dimensions is optional, but recommended if the datatype is to represent arrays of more than one dimension. This number is used: * When emitting the type declaration itself to the database, e.g. ``INTEGER[][]`` * When translating Python values to database values, and vice versa, e.g. an ARRAY of :class:`.Unicode` objects uses this number to efficiently access the string values inside of array structures without resorting to per-row type inspection * When used with the Python ``getitem`` accessor, the number of dimensions serves to define the kind of type that the ``[]`` operator should return, e.g. for an ARRAY of INTEGER with two dimensions:: >>> expr = table.c.column[5] # returns ARRAY(Integer, dimensions=1) >>> expr = expr[6] # returns Integer For 1-dimensional arrays, an :class:`_types.ARRAY` instance with no dimension parameter will generally assume single-dimensional behaviors. SQL expressions of type :class:`_types.ARRAY` have support for "index" and "slice" behavior. The Python ``[]`` operator works normally here, given integer indexes or slices. Arrays default to 1-based indexing. The operator produces binary expression constructs which will produce the appropriate SQL, both for SELECT statements:: select([mytable.c.data[5], mytable.c.data[2:7]]) as well as UPDATE statements when the :meth:`_expression.Update.values` method is used:: mytable.update().values({ mytable.c.data[5]: 7, mytable.c.data[2:7]: [1, 2, 3] }) The :class:`_types.ARRAY` type also provides for the operators :meth:`.types.ARRAY.Comparator.any` and :meth:`.types.ARRAY.Comparator.all`. The PostgreSQL-specific version of :class:`_types.ARRAY` also provides additional operators. .. versionadded:: 1.1.0 .. seealso:: :class:`_postgresql.ARRAY` TFceZdZdZdZdZejdddZejdddZ dS) ARRAY.ComparatorzDefine comparison operations for :class:`_types.ARRAY`. More operators are available on the dialect-specific form of this type. See :class:`.postgresql.ARRAY.Comparator`. c t|tr|j}|jjr&t|jdz|jdz|j}tt|j|j j tj t|j|j j tj t|j|j j tj }nh|jjr|dz }|jj |jj dkr |jj}n.d|jj dz i}|jj|jjfi|}t"j||fS)Nr)rtype_ dimensions)rDslicer, zero_indexesstartstopstepr r rGkeyr INTEGERTYPEr item_typerZrIrgetitem)r%rS return_typeadapt_kws r&rTzARRAY.Comparator._setup_getitem sW%'' "i 9)O!%+/5:>5:NNE% !Y]&2 & !Y]&2 & !Y]&2$9)QJE9'/493G13L3L"&)"5KK ,di.BQ.FGH"1$)/ +##/7##K$e[8 8r(c td)NzdARRAY.contains() not implemented for the base ARRAY type; please use the dialect-specific ARRAY typer"r3s r&containszARRAY.Comparator.contains- s%I r(zsqlalchemy.sql.elementsNc|r|n tj}|j|j||j|j|S)aReturn ``other operator ANY (array)`` clause. Argument places are switched, because ANY requires array expression to be on the right hand-side. E.g.:: from sqlalchemy.sql import operators conn.execute( select([table.c.data]).where( table.c.data.any(7, operator=operators.lt) ) ) :param other: expression to be compared :param operator: an operator object from the :mod:`sqlalchemy.sql.operators` package, defaults to :func:`.operators.eq`. .. seealso:: :func:`_expression.any_` :meth:`.types.ARRAY.Comparator.all` )reqr`r CollectionAggregate _create_anyrGr%rotherrRs r&anyzARRAY.Comparator.any3 V:$,=xxH-8,**511,88CC r(c|r|n tj}|j|j||j|j|S)aReturn ``other operator ALL (array)`` clause. Argument places are switched, because ALL requires array expression to be on the right hand-side. E.g.:: from sqlalchemy.sql import operators conn.execute( select([table.c.data]).where( table.c.data.all(7, operator=operators.lt) ) ) :param other: expression to be compared :param operator: an operator object from the :mod:`sqlalchemy.sql.operators` package, defaults to :func:`.operators.eq`. .. seealso:: :func:`_expression.all_` :meth:`.types.ARRAY.Comparator.any` )rrr`r r _create_allrGrs r&allzARRAY.Comparator.allZ rr(r!) r5r6r7r;rTrrrrrr9r(r&r:r} s  ! 9! 9! 9F     4 5 5$ $ $  6 5$ L  4 5 5$ $ $  6 5$ $ $ r(r:Nct|trtdt|tr |}||_||_||_||_dS)aConstruct an :class:`_types.ARRAY`. E.g.:: Column('myarray', ARRAY(Integer)) Arguments are: :param item_type: The data type of items of this array. Note that dimensionality is irrelevant here, so multi-dimensional arrays like ``INTEGER[][]``, are constructed as ``ARRAY(Integer)``, not as ``ARRAY(ARRAY(Integer))`` or such. :param as_tuple=False: Specify whether return results should be converted to tuples from lists. This parameter is not generally needed as a Python list corresponds well to a SQL array. :param dimensions: if non-None, the ARRAY will assume a fixed number of dimensions. This impacts how the array is declared on the database, how it goes about interpreting Python and result values, as well as how expression behavior in conjunction with the "getitem" operator works. See the description at :class:`_types.ARRAY` for additional detail. :param zero_indexes=False: when True, index values will be converted between Python zero-based and SQL one-based indexes, e.g. a value of one will be added to all index values before passing to the database. zUDo not nest ARRAY types; ARRAY(basetype) handles multi-dimensional arrays of basetypeN)rDr{rr,ras_tuplerr)r%rrrrs r&rizARRAY.__init__ spD i ' ' ?  i & & $! I"  $(r(c|jSr!)rr$s r&rwzARRAY.hashable s }r(ctSr!)rr$s r&rzARRAY.python_type rr(c||kSr!r9rs r&rzARRAY.compare_values s Av r(c dt|jtr|jj|fi|dSdSzSupport SchemaEventTargetN)rDrr rMrKs r&rMzARRAY._set_parent sF dn&7 8 8 5 &DN &v 4 4 4 4 4 4 4 5 5r(c tt||t|jt r|j|dSdSr)rHr{_set_parent_with_dispatchrDrr )r%parentr5rIs r&rzARRAY._set_parent_with_dispatch s^ eT44V<<< dn&7 8 8 = N 4 4V < < < < < = =r()FNF)r5r6r7r;r _is_arrayrrOr:r?r=rir<rwrrrMrrKrLs@r&r{r{ s[[zNIL#~~~~~Y)<+B~~~@$HM,),),),)\XX555 =========r(r{ceZdZdZdZdS)REALzThe SQL REAL type.Nrr9r(r&rr NNNr(rceZdZdZdZdS)FLOATzThe SQL FLOAT type.Nrr9r(r&rr NNNr(rceZdZdZdZdS)NUMERICzThe SQL NUMERIC type.Nrr9r(r&rr NNNr(rceZdZdZdZdS)DECIMALzThe SQL DECIMAL type.Nrr9r(r&rr rr(rceZdZdZdZdS)INTEGERzThe SQL INT or INTEGER type.Nrr9r(r&rr s&&NNNr(rceZdZdZdZdS)SMALLINTzThe SQL SMALLINT type.Nrr9r(r&rr   NNNr(rceZdZdZdZdS)BIGINTzThe SQL BIGINT type.Nrr9r(r&rr NNNr(rc.eZdZdZdZdfd ZdZxZS) TIMESTAMPaThe SQL TIMESTAMP type. :class:`_types.TIMESTAMP` datatypes have support for timezone storage on some backends, such as PostgreSQL and Oracle. Use the :paramref:`~types.TIMESTAMP.timezone` argument in order to enable "TIMESTAMP WITH TIMEZONE" for these backends. FcZtt||dS)amConstruct a new :class:`_types.TIMESTAMP`. :param timezone: boolean. Indicates that the TIMESTAMP type should enable timezone support, if available on the target database. On a per-dialect basis is similar to "TIMESTAMP WITH TIMEZONE". If the target database does not support timezones, this flag is ignored. rN)rHrri)r%rrIs r&rizTIMESTAMP.__init__ s, i''':::::r(c|jSr!)rrs r&rzTIMESTAMP.get_dbapi_type s r(r)r5r6r7r;rrirrKrLs@r&rr s]!N ; ; ; ; ; ;r(rceZdZdZdZdS)rzThe SQL DATETIME type.Nrr9r(r&rr rr(rceZdZdZdZdS)DATEzThe SQL DATE type.Nrr9r(r&rr$ rr(rceZdZdZdZdS)TIMEzThe SQL TIME type.Nrr9r(r&rr+ rr(rceZdZdZdZdS)TEXTzThe SQL TEXT type.Nrr9r(r&rr2 rr(rceZdZdZdZdS)CLOBzCThe CLOB type. This type is found in Oracle and Informix. Nrr9r(r&rr9 s NNNr(rceZdZdZdZdS)VARCHARzThe SQL VARCHAR type.Nrr9r(r&rrC rr(rceZdZdZdZdS)NVARCHARzThe SQL NVARCHAR type.Nrr9r(r&rrJ rr(rceZdZdZdZdS)CHARzThe SQL CHAR type.Nrr9r(r&rrQ rr(rceZdZdZdZdS)NCHARzThe SQL NCHAR type.Nrr9r(r&rrX rr(rceZdZdZdZdS)BLOBzThe SQL BLOB type.Nrr9r(r&rr_ rr(rceZdZdZdZdS)r+zThe SQL BINARY type.Nrr9r(r&r+r+f rr(r+ceZdZdZdZdS) VARBINARYzThe SQL VARBINARY type.Nrr9r(r&rrm s!! NNNr(rceZdZdZdZdS)BOOLEANzThe SQL BOOLEAN type.Nrr9r(r&rrt rr(rcNeZdZdZdZdZdZdZGddej Z e Z dS) rEaAn unknown type. :class:`.NullType` is used as a default type for those cases where a type cannot be determined, including: * During table reflection, when the type of a column is not recognized by the :class:`.Dialect` * When constructing SQL expressions using plain Python objects of unknown types (e.g. ``somecolumn == my_special_object``) * When a new :class:`_schema.Column` is created, and the given type is passed as ``None`` or is not passed at all. The :class:`.NullType` can be used within SQL expression invocation without issue, it just has no behavior either at the expression construction level or at the bind-parameter/result processing level. :class:`.NullType` will result in a :exc:`.CompileError` if the compiler is asked to render the type itself, such as if it is used in a :func:`.cast` operation or within a schema creation operation such as that invoked by :meth:`_schema.MetaData.create_all` or the :class:`.CreateTable` construct. nullTFc d}|S)NcdS)Nrlr9rs r&rvz+NullType.literal_processor..process s6r(r9rws r&rxzNullType.literal_processor s   r(ceZdZdZdS)NullType.Comparatorct|tjstj|s||jjfS|||Sr!)rDrEr:ris_commutativerGr,r4)r%r0r1s r&r4z%NullType.Comparator._adapt_expression sX ("5 D-b11 D49>))'99"dCCCr(N)r5r6r7r4r9r(r&r:r s( D D D D Dr(r:N) r5r6r7r;r_isnullrwrxrr:r=r9r(r&rErE{ sw2NGH DDDDDZ*DDD$r(rEceZdZdZdS) MatchTypeaDRefers to the return type of the MATCH operator. As the :meth:`.ColumnOperators.match` is probably the most open-ended operator in generic SQLAlchemy Core, we can't assume the return type at SQL evaluation time, as MySQL returns a floating point, not a boolean, and other backends might do something different. So this type acts as a placeholder, currently subclassing :class:`.Boolean`. The type allows dialects to inject result-processing functionality if needed, and on MySQL will return floating-point values. .. versionadded:: 1.0.0 NrBr9r(r&rr s    r(rctt|d}|durHtj|d}|*|jtjvrt jd|ztS|S)NFz-Object %r is not legal as a SQL literal value) _type_map_getr,rinspectrI _registrarsrrcNULLTYPE)rt _result_typeinsps r&_resolve_value_to_typer sx ee44Lu!%//   Nj4 4 4#?%G r()or;rrrrrrrrrbaserrr r r r r rrrrrrrrrrrrrrrrr robjectrr?rOr\rrrrrrrrrrrrr.deprecated_clsrr7rtrrrrr&r{rrrrrINTrrrrrrrrrrrrrr+rrrErr BOOLEANTYPE STRINGTYPEr MATCHTYPErrrrrr rNoneType _type_mappy3kr%rrr.rr INDEXABLEr:r9r(r&rs,    ######'''''' !!!!!!//////''''''!!!!!!###### ;LLL$$$$$v$$$>$$$$$6$$$($$$$$$$$6T T T T T \:T T T n     6   E?E?E?E?E?fE?E?E?P     $   @% % % % % & % % % P % % % % %7 % % % # # # # # # # #o o o o o & o o o d>>>>>G>>>B4 4 4 4 4 '4 4 4 n# # # # # #Z# # # L     #Z   6IIIIIjIIIX.....'...0 = /////[//  / 77777"777DL1L1L1L1L18VZL1L1L1^TTTTTTTTno-o-o-o-o-h Jo-o-o-d:::::0*:::8WWWWWx*MWWWtccccc9jcccLm=m=m=m=m= y, m=m=m=` 5Eggg     |   Z<     x   4444f     w   6G;W!!!!!!!!g0$0$0$0$0$z0$0$0$f         8::gii VXX gii IKK  5577+ OWWYYGTTVVKGTTVVL((**M8  9"{}}IeWYYIcNN IgVXXIcN ,# ""8$/ !!!r(PK!,IsIs __pycache__/crud.cpython-311.pycnu[ |oi[fjdZddlZddlmZddlmZddlmZddlmZejd d Zejd Z ejd Z ejd Z dZ dZ d&dZdZdZdZdZdZd'dZd'dZGddejZdZdZdZdZd Zd!Zd"Zd#Zd$Z d%Z!dS)(ziFunctions used by compiler.py to determine the parameters rendered within INSERT and UPDATE statements. N)dml)elements)exc)utilREQUIREDa8 Placeholder for the value within a :class:`.BindParameter` which is required to be present when the statement is passed to :meth:`_engine.Connection.execute`. This symbol is typically used when a :func:`_expression.insert` or :func:`_expression.update` statement is compiled without parameter values present. ISINSERTISUPDATEISDELETEc |j}|j}|j}|p|p|pt|jdkpd|v}|t urd|_d|_n5|t urd|_d|_n|tur |sd|_n Jd |t t fvr&t||fi||r||_||_||_SS |r||_||_||_dSdS#|r||_||_||_wxYw)Nr visiting_cteFTz(ISINSERT, ISUPDATE, or ISDELETE expected) isinsertisupdateisdeletelenstackr r r _get_crud_params)compilerstmtlocal_stmt_typekwrestore_isinsertrestore_isupdaterestore_isdeleteshould_restores J/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/crud.py_setup_crud_paramsr'st(((  A- A1A x~   " R  (""!  H $ $ ! H $ $ % $H @@@@u1 x2 2 2#Hd99b99  1 0H  0H  0H   1 3  1 0H  0H  0H    1 1> 1 0H  0H  0H  0 0 0 0s CC1c h g_g_g_g_j|jfd|jjDS|jr|jd n|j t|\ }}ji}n!t fdjD}g} t| ||i}j r|j r rt| |||||jr|jrt#||| |||| nt%||| |||| |ry rwt'| fd D|}|r4t-jddd|Dz|jrt3|||}|S) aPcreate a set of tuples representing column/string pairs for use in an INSERT or UPDATE statement. Also generates the Compiled object's postfetch, prefetch, and returning column collections, used for default handling and ultimately populating the ResultProxy's prefetch_cols() and postfetch_cols() collections. Nc :g|]}|t|ddfS)NT)required)_create_bind_param).0crs r z$_get_crud_params..[s@   "8QtDDD E   rc3HK|]}r|v|tfVdSN)r )r#key_column_as_keystmt_parameterss r z#_get_crud_params..ssS  " '*&@&@^C ( +&@&@&@&@  r&c3.K|]}|VdSr()r#kr*s rr,z#_get_crud_params..s-EE..++EEEEEEr&zUnconsumed column names: %sz, c3 K|] }d|zV dS)z%sNr.)r#r$s rr,z#_get_crud_params..s&55!TAX555555r&) postfetchinsert_prefetchupdate_prefetch returning column_keys parameterstablecolumns_has_multi_parameters_key_getters_for_crud_columndict_get_stmt_parameters_paramsr _extra_froms_get_multitable_paramsr select_names_scan_insert_from_select_cols _scan_colsset intersection differencer CompileErrorjoin_extend_values_for_multiparams) rrr_getattr_col_key_col_bind_namer6values check_columnscheckr*r+s ` @@rrrHsH!H!HH#(?    Z'     !*/!,/ %Xt44  #      +     F"# j/>62   M  T.  ?            T. %                      o   OO \EEEE_EEE E E Z & &   "-9955u555557   !L/$KK Mr&TFc ||j}tj|||j|}d|_|r|j|fi|}|S)N)type_r!T)r)r BindParametertype_is_crud_compiler_dispatch)rcolvalueprocessr!namer bindparams rr"r"se |w& e38hIIA0I0@@R@@ r&c|jr+|jr$t|jfd}fd}fd}n"tj}t jdx}}|||fS)Nc~tj|}t|dr|jvr|jj|fS|S)Nr7)rr*hasattrr7rV)r)str_key_ets rr*z4_key_getters_for_crud_column.._column_as_keysE-c22GsG$$ c)9)9 00r&cJ|jvr|jj|jfS|jSr(r7rVr)rSr\s rrHz6_key_getters_for_crud_column.._getattr_col_keys(yC 00wr&cP|jvr|jjd|jS|jS)N_r^r_s rrIz4_key_getters_for_crud_column.._col_bind_names.yC"%)...#''::wr&r))rr=rBrr*operator attrgetter)rrr*rHrIr\s @rr:r:sGT.G$#$$                 "0,4,?,F,FF> +^ ;;r&c t|\} } } } fdjD} j|_g}jr>t | }jjD]"}||vr|jr| |#| D]U}||}||vr1||vr-| || |dfBt||||V|rr| ||j |_t|jjtd|Dz|j_dSdS)NcFg|]}jj|Sr.r7r$)r#rVr*rs rr%z1_scan_insert_from_select_cols..s, M M M4DJL-- . M M Mr&c3 K|] \}}|V dSr(r.)r#rSexprs rr,z0_scan_insert_from_select_cols..s&8893$888888r&)_get_returning_modifiersr?select_insert_from_select#include_insert_from_select_defaultsrBr7r8defaultappendpop&_append_param_insert_select_hasdefaultextend _generatetuple _raw_columns)rrr6rHr*rIrKrJrneed_pksimplicit_returningimplicit_return_defaultspostfetch_lastrowidcolsadd_select_colscol_setrSr$col_keys ` ` rr@r@s" !400   N M M M M4;L M M MD#';H O /!d)):% ! !C'!!ck! C   ""1%% j WM%A%A NN7 # # # MM1d) $ $ $ $ 2$?B    9 o&&&'/'C'M'M'O'O$49  ( 55 5 88888 8 859$11199r&c t|\} } } } jrJfdjD} t| fd| DfdjjDz}n jj}|D]K}||}||vr||vrt |||||| | || /|jr|jr>| r<| s| r|jj ur*| rt||||gt||||{|j t||| |||jC| r|| vr|j||js|j|| r || vr|j||jr$|jj ur|jst'|0|jrt+||| ||MdS)Nc&g|] }|Sr.r.)r#r)r*s rr%z_scan_cols..2s0   $'NN3     r&c4g|]}jj|Sr.rf)r#r)rs rr%z_scan_cols..6s"@@@c S!@@@r&c&g|] }|jv |Sr.)r))r#r$ ordered_keyss rr%z_scan_cols..6s/D D D quL'@'@A'@'@'@r&)ri_parameter_orderingrBr7r$r8_append_param_parameterr primary_key_autoincrement_column!_append_param_insert_pk_returning_append_param_insert_pkrm_append_param_insert_hasdefaultserver_defaultr4rnr1nullable"_warn_pk_with_no_anticipated_valuer_append_param_update)rrr6rHr*rIrKrJrrurvrwrxparameter_orderingryr$r|rs ` ` @rrArAs" !400    "    +/+C   -.. @@@@-?@@@D D D D z|D D D  z! ;;""1%% j WM%A%A #"(     )  # 6# 6' # 6 / # 6  @@@&K5 $62,HdAvrJJJJ&/dA'?!-+15M0M0M&--a00001&--a000) 6a3K.K.K"))!,,,,  6TZ=== >31555    $#;VR   s;;r&c ||} tj| r9t||| f| tu|js ||n d||zd| } n t | tjr,| jj r | } |j| _|j r=|r;|j ||j| fi| } n|r?||vr;|j ||j| fi| } nA|j s|j ||j| fi| } | || fdS)Nz%s_m0r!rV)ror _is_literalr"r r9 isinstancerOrP_isnull_clonerr4rnrU self_groupr1) rrr$r|r6rIrvrwrJrrTs rrrzs NN7 # #EE""?"    h&--""">>!,,,       eX3 4 4 9K LLNNEEJ = ?/ ?   % %a ( ( ($H$U%5%5%7%7>>2>>EE % ?!/G*G*G   % %a ( ( ($H$U%5%5%7%7>>2>>EE = -"))!,,,$H$U%5%5%7%7>>2>>E MM1e*r&c|j|jjrj|jjrB|jjr |jjs*|j|jfi|}|||f|j|dS|jj r[|||j|jj fi|f|j|dS||t||fdS||j jus|j|j|dS|jst#|dSdS)aCreate a primary key expression in the INSERT statement and possibly a RETURNING clause for it. If the column has a Python-side default, we will create a bound parameter for it and "pre-execute" the Python function. If the column has a SQL expression default, or is a sequence, we will add it directly into the INSERT statement and add a RETURNING element to get the new value. If the column has a server side default or is marked as the "autoincrement" column, we will add a RETRUNING element to get at the value. If all the above tests fail, that indicates a primary key column with no noted default generation capabilities that has no parameter passed; raise an exception. N)rm is_sequencedialectsupports_sequencesoptionalsequences_optionalrUrnr4is_clause_elementargr"_create_insert_prefetch_bind_paramr7rrrrrrr$rJrprocs rrrs" y 9  P2 )I& )': )(x' 88R88 q$i(((   % %a ( ( ( ( ( Y ( P MM$H$QY]%=%=%?%?FF2FFG      % %a ( ( ( ( ( MM1@1MMN O O O O O dj. . .!2B2N!!!$$$$$ Z. +1-----..r&cbt||d||}|j||SN)rUrV)r"r2rnrr$rUrVparams rrr6 xD' M M ME ##A&&& Lr&cbt||d||}|j||Sr)r"r3rnrs r"_create_update_prefetch_bind_paramrrr&ceZdZdZdZdZdS)_multiparam_columnTcz||_d|j|dzfz|_||_|j|_|j|_dS)N%s_m%dr)indexr)originalrmrP)selfrrs r__init__z_multiparam_column.__init__s> x|UQY77  ' M r&clt|to|j|jko|j|jkSr()rrr)r)rothers r__eq__z_multiparam_column.__eq__s7 u0 1 1 0 TX% 0$-/ r&N)__name__ __module__ __qualname___is_multiparam_columnrrr.r&rrrs8 """     r&rc>|jstjd|z|jjr*|j|jjfi|St||}t|tj rt||St||S)NzINSERT value for column %s is explicitly rendered as a boundparameter in the VALUES clause; a Python-side value or SQL expression is required) rmrrErrUrrrrrInsertrr)rrr$rrrSs r _process_multiparam_default_bindrs 9 E @BC D    $Ex 8 8 : :AAbAAA E** dCJ ' ' E5hDD D5hDD Dr&c2|j|jjr2|jjs&||jjur?|jjs |jjr'||t||fdS|j|j |j st|dSdSdSdS)aCreate a bound parameter in the INSERT statement to receive a 'prefetched' default value. The 'prefetched' value indicates that we are to invoke a Python-side default function or expliclt SQL expression before the INSERT statement proceeds, so that we have a primary key value available. if the column has no noted default generation capabilities, it has no value passed in either; raise an exception. N) rmrrrr7r"preexecute_autoincrement_sequencesrnrrrr)rrr$rJrs rrrs  % 2  TZ ---   / . B .  q|r ||vr|j|dS|j|dS|r)|j dur"||vr |j|dSdSdSdS)NT) onupdaterrrnrUrrr4r1rserver_onupdate_return_defaults)rrr$rwrJrs rrrRs zaj&< : ' P MM$H$QZ^%>%>%@%@GGBGGH   ( -A1I,I,I"))!,,,,,"))!,,,,, MM1@1MMN O O O O O  & # )-E(E(E   % %a ( ( ( ( (   % %a ( ( ( ( ( %  ! - - ) ) )!!!$$$$$ %% - - ) )r&c td|D}t} |jD]} | jD]} | |vr| | | ||| <|| } t j| r%t|| | | tu|| } n:|j | |j | fi|} | | | f| D]} | jD]} | |vr| j| jjs| jjrZ| | |j | jj fi|f|j | | | t%|| || f| j|j | ӌdS)Nc3HK|]\}}tj||fVdSr()r_clause_element_as_expr)r#r$rs rr,z)_get_multitable_params..ysJ Au  )! , ,e4r&r)rV)r;itemsrBr=r$addrrr"r r1rnrUrrrrrrr) rrr+rKrIrHrJrnormalized_paramsaffected_tablestr$rTs rr>r>ns'--//eeO  ** * *A%%%##A&&&56 ..q112)!,'.. G. !&(!2+^A.. EE&--a000,H,U-=-=-?-?FF2FFE q%j)))! *&-- - -A%%%' 0F':/MM,H, !  9 9 ; ;?A&--a0000MM> (!..2C2C"."))!,,,1 ---r&c |}|g}t|jddD]\}}g}|D]\}} ||vs |j|vrs||vr|n|j} tj|| r%t |||| fdd|j|dzfzi|} n:|j|| fi|} nt|||||} | || f| ||S)NrrVr) enumerater6r)rrr"rUrrrn) rrrJrvalues_0irow extensionrSrr) new_params rrGrGsQHXFDOABB/00!!3 $ / /LS%czzSW^^ CZZccSW'C11 N 2 C!!&!a%(88 !  !!II!1 0S1D1D1F1F M M" M MII<dCB    c9- . . . . i    Mr&c|D]\}}||}||||)tj|r)|jtjd||jfi|}nM|jr&|jjr| |j}|j| fi|}| ||fdS)N)rN) r setdefaultrrrUrOrP_is_bind_parameterr_with_binary_element_typerrn) rr6r+r*rJrr/vcolkeys rr<r<s %%''""1""    ! !&! , , , , #A&& ;$H$*4!&AAAEG'rGr<rirr.r&rrsC 4;    4;z " " 4;z " " 4;z " "111Bqqqj>B    !<!<!e)Z6Gd?d@e6e3Z7GdAdBe7Z8GdCdDe7Z9GdEdFe7Z:GdGdHe7Z;GdIdJe e6e%Z<ej=dKdLiZ>GdMdNe%Z?GdOdPe?Z@GdQdRe)ZAeAdZBeAjCZCGdSdTe/e%ZDdS)Ua/The schema module provides the building blocks for database metadata. Each element within this module describes a database entity which can be created and dropped, or is otherwise part of such an entity. Examples include tables, columns, sequences, and indexes. All entities are subclasses of :class:`~sqlalchemy.schema.SchemaItem`, and as defined in this module they are intended to be agnostic of any vendor-specific constructs. A collection of entities are grouped into a unit called :class:`~sqlalchemy.schema.MetaData`. MetaData serves as a logical grouping of schema elements, and can also be associated with an actual database connection such that operations involving the contained elements can contact the database as needed. Two of the elements here also build upon their "syntactic" counterparts, which are defined in :class:`~sqlalchemy.sql.expression.`, specifically :class:`~sqlalchemy.schema.Table` and :class:`~sqlalchemy.schema.Column`. Since these objects are part of the SQL expression language, they are usable as components in SQL expressions. )absolute_importN)ddl)type_api)visitors)_bind_or_error)ColumnCollection) DialectKWArgs)SchemaEventTarget) _as_truncated)_document_text_coercion)_literal_as_text) ClauseElement) ColumnClause) ColumnElement) quoted_name) TextClause) TableClauseevent)exc) inspection)util retain_schema blank_schemazSymbol indicating that a :class:`_schema.Table` or :class:`.Sequence` should have 'None' for its schema, even if the parent :class:`_schema.MetaData` has specified a schema. .. versionadded:: 1.0.14 c||S|dz|zS)N.)nameschemas L/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/schema.py_get_table_keyr#Is ~ |d""cJ|Sfd}tj|i|S)Nct|tr)|jur |jjvrj|jSdSN) isinstanceColumntablekeyc)col source_table target_tables r"replacez!_copy_expression..replaceVsE sF # #  \))<>))>#'* *4r$)rreplacement_traverse) expressionr.r/r0s `` r"_copy_expressionr3RsJ|3  (R A AAr$ceZdZdZdZdZdZdZee j dddZ e j d Z d Zd Zd S) SchemaItemz3Base class for items that define a database schema. schema_itemc|D]Z}|V |j}||#t$r5}tjt jd|z|Yd}~Rd}~wwxYw[dS)z7Initialize the list of child items for this SchemaItem.NzJ'SchemaItem' object, such as a 'Column' or a 'Constraint' expected, got %r)replace_context)_set_parent_with_dispatchAttributeErrorrraise_r ArgumentError)selfargsitemspwderrs r" _init_itemszSchemaItem._init_itemsis  D 9DDJJJJ&K)<>BC),    s A+AAc gS)z"used to allow SchemaVisitor accessrr=kwargss r" get_childrenzSchemaItem.get_children{s r$c0tj|dgS)Ninfo) omit_kwargr generic_reprr=s r"__repr__zSchemaItem.__repr__s 6(;;;;r$0.9zThe :attr:`.SchemaItem.quote` attribute is deprecated and will be removed in a future release. Use the :attr:`.quoted_name.quote` attribute on the ``name`` field of the target schema item to retrievequoted status.c|jjS)zReturn the value of the ``quote`` flag passed to this schema object, for those schema items which have a ``name`` field. )r quoterLs r"rPzSchemaItem.quotesyr$ciS)aZInfo dictionary associated with the object, allowing user-defined data to be associated with this :class:`.SchemaItem`. The dictionary is automatically generated when first accessed. It can also be specified in the constructor of some objects, such as :class:`_schema.Table` and :class:`_schema.Column`. rrLs r"rHzSchemaItem.infos  r$cd|jvr|j|_|j|j|S)NrH)__dict__rHcopydispatch_update)r=r6s r"_schema_item_copyzSchemaItem._schema_item_copysB T] " "#y~~//K $$T]333r$c.|||Sr')get)r=effective_schemamap_s r"_translate_schemazSchemaItem._translate_schemasxx(*:;;;r$N)__name__ __module__ __qualname____doc____visit_name__rBrFrMpropertyr deprecatedrPmemoized_propertyrHrWr\rr$r"r5r5cs=="N$<<<T_  X     <<<<, )`` which will be passed to :func:`.event.listen` upon construction. This alternate hook to :func:`.event.listen` allows the establishment of a listener function specific to this :class:`_schema.Table` before the "autoload" process begins. Particularly useful for the :meth:`.DDLEvents.column_reflect` event:: def listen_for_reflect(table, column_info): "handle the column reflection event" # ... t = Table( 'sometable', autoload=True, listeners=[ ('column_reflect', listen_for_reflect) ]) :param mustexist: When ``True``, indicates that this Table must already be present in the given :class:`_schema.MetaData` collection, else an exception is raised. :param prefixes: A list of strings to insert after CREATE in the CREATE TABLE statement. They will be separated by spaces. :param quote: Force quoting of this table's name on or off, corresponding to ``True`` or ``False``. When left at its default of ``None``, the column identifier will be quoted according to whether the name is case sensitive (identifiers with at least one upper case character are treated as case sensitive), or if it's a reserved word. This flag is only needed to force quoting of a reserved word which is not known by the SQLAlchemy dialect. :param quote_schema: same as 'quote' but applies to the schema identifier. :param schema: The schema name for this table, which is required if the table resides in a schema other than the default selected schema for the engine's database connection. Defaults to ``None``. If the owning :class:`_schema.MetaData` of this :class:`_schema.Table` specifies its own :paramref:`_schema.MetaData.schema` parameter, then that schema name will be applied to this :class:`_schema.Table` if the schema parameter here is set to ``None``. To set a blank schema name on a :class:`_schema.Table` that would otherwise use the schema set on the owning :class:`_schema.MetaData`, specify the special symbol :attr:`.BLANK_SCHEMA`. .. versionadded:: 1.0.14 Added the :attr:`.BLANK_SCHEMA` symbol to allow a :class:`_schema.Table` to have a blank schema name even when the parent :class:`_schema.MetaData` specifies :paramref:`_schema.MetaData.schema`. The quoting rules for the schema name are the same as those for the ``name`` parameter, in that quoting is applied for reserved words or case-sensitive names; to enable unconditional quoting for the schema name, specify the flag ``quote_schema=True`` to the constructor, or use the :class:`.quoted_name` construct to specify the name. :param useexisting: the same as :paramref:`_schema.Table.extend_existing`. :param comment: Optional string that will render an SQL comment on table creation. .. versionadded:: 1.2 Added the :paramref:`_schema.Table.comment` parameter to :class:`_schema.Table`. :param \**kw: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. r*)0.7zThe :paramref:`_schema.Table.useexisting` parameter is deprecated and will be removed in a future release. Please use :paramref:`_schema.Table.extend_existing`.) useexistingc|st|S |d|d|dd}}}n#t$rtdwxYw|dd}||j}n |t urd}|dd}|dd}d |vr.|rd }tj ||d d}|r|rd }tj ||d d} t||} | |j vrH|s(|s&t|rtj d | z|j | } |r | j|i|| S| rtj d| zt|} | j| |||||  | j||g|Ri|| j| || S#t)j5|||dddYdS#1swxYwYYdSxYw)Nrrrz$Table() takes at least two argumentsr! keep_existingFextend_existingrhz/useexisting is synonymous with extend_existing.z9keep_existing and extend_existing are mutually exclusive. mustexistzTable '%s' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.zTable '%s' not defined)object__new__ IndexError TypeErrorrYr! BLANK_SCHEMApoprr<r#tablesboolInvalidRequestError_init_existingrUbefore_parent_attach _add_table_initafter_parent_attachr safe_reraise _remove_table) clsr>kwr metadatar!rjrkmsgrlr+r*s r"rnz Table.__new__s '>>#&& & D#'7DGT!""XD(DD D D DBCC C D$'' >_FF | # #F66 &&!2E:: B   -G',,, ff]E::O  )_ )MC#C(( (FF;.. T6** (/ ! !   T$ZZ --03 3OC(E 2$$d1b111L P-.F#.NOOONN3''E N / /x @ @ @   fe 4 4 4 9 D(8T888R888225(CCC  9&((99**488899999999999999999999s99A.HI H?1 I ?I I I I rNzThe :meth:`.SchemaItem.quote` method is deprecated and will be removed in a future release. Use the :attr:`.quoted_name.quote` attribute on the ``schema`` field of the target schema item to retrieve quoted status.c|jjS)zeReturn the value of the ``quote_schema`` flag passed to this :class:`_schema.Table`. )r!rPrLs r" quote_schemazTable.quote_schema5s{  r$cdS)zConstructor for :class:`_schema.Table`. This method is a no-op. See the top-level documentation for :class:`_schema.Table` for constructor arguments. Nr)r=r>r~s r"__init__zTable.__init__Dsr$c tt|t||dd||_|dd|_|j |j|_nF|jturd|_n0|dd}t|j||_t|_ t|_ t|_ td|t|_t|_|j|jd|j|_n |j|_|dd}|d|du}|d d|d d}|d d} |d d} |d d|_|dd|_d|vr|d|_d|vr3|d} | D]\} } t-j|| | |dg|_|jdi||r|||| || |j|dS)NrPr!rT)_implicit_generatedr autoload_withautoloadautoload_replace _extend_on resolve_fksinclude_columnsimplicit_returningcommentrH listenersprefixes)rrr)superrfrrrrrr!rqsetindexes constraintsr _columnsPrimaryKeyConstraintr9 foreign_keys_extra_dependenciesr fullnamerrrHrlisten _prefixes _extra_kwargs _autoloadrB)r=r rr>rErrrrrrrevtfn __class__s r"ryz Table._initOs eT## fjj$77 8 8   ! jj400 ; "/DKK [L ( (DKK!::nd;;L%dk<@@DKuu 55(**  $   # #D ) ) )EE#&55 ; "'+{{{DII>DMM IDM ?D99 ::j-t*CDD %t,,,ZZ d33 jj55  **%6=="(**-A4"H"Hzz)T22 V   6**DI &  ;//I$ , ,R T3++++J33$$V$$$   NN%'     $r$rTNc|r'||jj|||||dSt|d}||jj|||||dS)NrzNo engine is bound to this Table's MetaData. Pass an engine to the Table via autoload_with=, or associate the MetaData with an engine via metadata.bind=)r) run_callabledialect reflecttabler)r=rrrexclude_columnsrrbinds r"rzTable._autoloads    & &%2% '     "-D    )%      r$c0t|jdS)zTReturn the set of constraints as a list, sorted by creation order. c|jSr')_creation_order)r,s r"z+Table._sorted_constraints..s a6Gr$r+)sortedrrLs r"_sorted_constraintszTable._sorted_constraintss d&,G,GHHHHr$c>td|jDS)a :class:`_schema.ForeignKeyConstraint` objects referred to by this :class:`_schema.Table`. This list is produced from the collection of :class:`_schema.ForeignKey` objects currently associated. .. versionadded:: 1.0.0 c3$K|] }|jV dSr') constraint).0fkcs r" z0Table.foreign_key_constraints..s$??c3>??????r$)rrrLs r"foreign_key_constraintszTable.foreign_key_constraintss$??T->??????r$c@|dd}|d|du}|dd}|dd}|dd}|r'||jkrtjd|j|f|dd}|d d} |-|jD]%} | j|vr|j| &d D]} | |vrtjd d |vr|d d|_d |vr|d |_ |r6|sd|jD} nd} | |j ||| | ||j di||j |dS)NrrrTr!rz7Can't change schema of existing table from '%s' to '%s'rr)rPrz2Can't redefine 'quote' or 'quote_schema' argumentsrrHcg|] }|j Srr rr,s r" z(Table._init_existing..s":":":a16":":":r$rr)rrr!rr<r,r rremoverrHrrrrB) r=r>rErrrr!rrrr,r+rs r"rvzTable._init_existings ?D99 ::j-t*CDD!::&8$??Hd++ZZ d33  f ++#If%  !**%6==jj55  &V , ,600M((+++,  Cf}}'H   !::i66DL V   6**DI  # %#;":46":":":"$ NN %     $$V$$$$r$c 0||dSr'_validate_dialect_kwargsrDs r"rzTable._extra_kwargs %%f-----r$cdSr'rrLs r"_init_collectionszTable._init_collections r$cdSr'rrLs r"_reset_exportedzTable._reset_exported rr$c|jjSr') primary_key_autoincrement_columnrLs r"rzTable._autoincrement_column s55r$c6t|j|jS)aReturn the 'key' for this :class:`_schema.Table`. This value is used as the dictionary key within the :attr:`_schema.MetaData.tables` collection. It is typically the same as that of :attr:`_schema.Table.name` for a table with no :attr:`_schema.Table.schema` set; otherwise it is typically of the form ``schemaname.tablename``. )r#r r!rLs r"r+z Table.keysdi555r$cddtjgtjgzdjDzfddDzzS)Nz Table(%s), c,g|]}t|Srreprrxs r"rz"Table.__repr__..#s---1tAww---r$c Tg|]$}|dtt|%S=rgetattrrkr=s r"rz"Table.__repr__..$s7III!!!T'$"2"23334IIIr$r!)joinrr rcolumnsrLs`r"rMzTable.__repr__s{TYY $)__ DM""# $-- --- .JIIIjIII J    r$c6t|j|jSr')r# descriptionr!rLs r"__str__z Table.__str__'sd. <<s( ((.....r$c0||dS)aAppend a :class:`_schema.Constraint` to this :class:`_schema.Table`. This has the effect of the constraint being included in any future CREATE TABLE statement, assuming specific DDL creation events have not been associated with the given :class:`_schema.Constraint` object. Note that this does **not** produce the constraint within the relational database automatically, for a table that already exists in the database. To add a constraint to an existing relational database table, the SQL ALTER command must be used. SQLAlchemy also provides the :class:`.AddConstraint` construct which can produce this SQL when invoked as an executable clause. Nr)r=rs r"append_constraintzTable.append_constraintTs& ,,T22222r$rgzthe :meth:`_schema.Table.append_ddl_listener` method is deprecated and will be removed in a future release. Please refer to :class:`.DDLEvents`.cpfd}tj|dddz|dS)z.Append a DDL event listener to this ``Table``.c"||dSr'r)target connectionr~ event_namelisteners r"adapt_listenerz1Table.append_ddl_listener..adapt_listenerss HZ 4 4 4 4 4r$-_Nrrr0r=rrrs `` r"append_ddl_listenerzTable.append_ddl_listenerisS 5 5 5 5 5 5  T2 2 23 < <} | jr t-| jg fd| jDR| j d| j ? S)a Return a copy of this :class:`_schema.Table` associated with a different :class:`_schema.MetaData`. E.g.:: m1 = MetaData() user = Table('user', m1, Column('id', Integer, primary_key=True)) m2 = MetaData() user_copy = user.tometadata(m2) :param metadata: Target :class:`_schema.MetaData` object, into which the new :class:`_schema.Table` object will be created. :param schema: optional string name indicating the target schema. Defaults to the special symbol :attr:`.RETAIN_SCHEMA` which indicates that no change to the schema name should be made in the new :class:`_schema.Table`. If set to a string name, the new :class:`_schema.Table` will have this new name as the ``.schema``. If set to ``None``, the schema will be set to that of the schema set on the target :class:`_schema.MetaData`, which is typically ``None`` as well, unless set explicitly:: m2 = MetaData(schema='newschema') # user_copy_one will have "newschema" as the schema name user_copy_one = user.tometadata(m2, schema=None) m3 = MetaData() # schema defaults to None # user_copy_two will have None as the schema name user_copy_two = user.tometadata(m3, schema=None) :param referred_schema_fn: optional callable which can be supplied in order to provide for the schema name that should be assigned to the referenced table of a :class:`_schema.ForeignKeyConstraint`. The callable accepts this parent :class:`_schema.Table`, the target schema that we are changing to, the :class:`_schema.ForeignKeyConstraint` object, and the existing "target schema" of that constraint. The function should return the string schema name that should be applied. E.g.:: def referred_schema_fn(table, to_schema, constraint, referred_schema): if referred_schema == 'base_tables': return referred_schema else: return to_schema new_table = table.tometadata(m2, schema="alt_schema", referred_schema_fn=referred_schema_fn) .. versionadded:: 0.9.2 :param name: optional string name indicating the target table name. If not specified or None, the table name is retained. This allows a :class:`_schema.Table` to be copied to the same :class:`_schema.MetaData` target with a new name. .. versionadded:: 1.0.0 NzBTable '%s' already exists within the given MetaData - not copying.r)r!r)r!r/c2g|]}t|Sr)r3)rexprr=r*s r"rz$Table.tometadata..4s5%T477r$)unique_table)r RETAIN_SCHEMAr!r#rsrwarnrrappendrTrfrrErr(ForeignKeyConstraint_referred_schemar _type_bound _column_flagrIndex expressionsrrW) r=rr!referred_schema_fnr r+r>r,referred_schemafk_constraint_schemaindexr*s ` @r" tometadatazTable.tometadatasX <9D ] " "[FF ^_FT6** (/ ! ! I*,0,<=   ?3' ' / /A KKf-- . . . .      L   k   !  A!122 "#"4%+=+=fa,,(( #2T["@"@d)''FF"6UFKK] >''FF&uF==\  E!     % 1  |   ,    %%e,,,r$)rTN)TFr'NF)%r]r^r_r`rardeprecated_paramsrnrbrcrrryrrrrvrrrrr+rMrrrrrrrrFrr r rr  __classcell__rs@r"rfrfsFFP NT 696969pT_  "!!X!   B B B B B R####JIIXI @ @X @4 4 4 l...      66X6 6 6X 6   ===<<X< , , ,///,333*T_  NNN!!! 7<         L L L L J J J J"  K-K-K-K-K-K-K-K-r$rfcneZdZdZdZfdZdZdZdZdZ dZ d Z d Z d Z d Z ddZddZxZS)r)z(Represents a column in a database table.rc |dd}|dd}t|}|rKt|dtjr+|t jd|d}|rC|d}t|dr+|t jd|d}|%t||dd}nd|vrt jd tt| |||d ||_ |d d |_ |d |j |_|dd|_|dd|_|dd|_|dd|_|dd|_|dd |_|dd|_|dd|_|dd|_t1|_t1|_|dd|_d|_d|vr|d|_n4t|jt>r|j ||jt|jtBtDfr|#|jntI|jdd rDt|jtj%r%tj&d|j d|jd|#tC|j|jot|jtNr.|#|j(d n'|#tS|j|jet|jtBtDfr|#|jn)|#tC|jd|jqt|jtNr.|#|j(dn)|#tS|jd|j*|tj+|d |vr|d |_,|j-d!i|dS)"aI Construct a new ``Column`` object. :param name: The name of this column as represented in the database. This argument may be the first positional argument, or specified via keyword. Names which contain no upper case characters will be treated as case insensitive names, and will not be quoted unless they are a reserved word. Names with any number of upper case characters will be quoted and sent exactly. Note that this behavior applies even for databases which standardize upper case names as case insensitive such as Oracle. The name field may be omitted at construction time and applied later, at any time before the Column is associated with a :class:`_schema.Table`. This is to support convenient usage within the :mod:`~sqlalchemy.ext.declarative` extension. :param type\_: The column's type, indicated using an instance which subclasses :class:`~sqlalchemy.types.TypeEngine`. If no arguments are required for the type, the class of the type can be sent as well, e.g.:: # use a type with arguments Column('data', String(50)) # use no arguments Column('level', Integer) The ``type`` argument may be the second positional argument or specified by keyword. If the ``type`` is ``None`` or is omitted, it will first default to the special type :class:`.NullType`. If and when this :class:`_schema.Column` is made to refer to another column using :class:`_schema.ForeignKey` and/or :class:`_schema.ForeignKeyConstraint`, the type of the remote-referenced column will be copied to this column as well, at the moment that the foreign key is resolved against that remote :class:`_schema.Column` object. .. versionchanged:: 0.9.0 Support for propagation of type to a :class:`_schema.Column` from its :class:`_schema.ForeignKey` object has been improved and should be more reliable and timely. :param \*args: Additional positional arguments include various :class:`.SchemaItem` derived constructs which will be applied as options to the column. These include instances of :class:`.Constraint`, :class:`_schema.ForeignKey`, :class:`.ColumnDefault`, :class:`.Sequence`, :class:`.Computed`. In some cases an equivalent keyword argument is available such as ``server_default``, ``default`` and ``unique``. :param autoincrement: Set up "auto increment" semantics for an integer primary key column. The default value is the string ``"auto"`` which indicates that a single-column primary key that is of an INTEGER type with no stated client-side or python-side defaults should receive auto increment semantics automatically; all other varieties of primary key columns will not. This includes that :term:`DDL` such as PostgreSQL SERIAL or MySQL AUTO_INCREMENT will be emitted for this column during a table create, as well as that the column is assumed to generate new integer primary key values when an INSERT statement invokes which will be retrieved by the dialect. The flag may be set to ``True`` to indicate that a column which is part of a composite (e.g. multi-column) primary key should have autoincrement semantics, though note that only one column within a primary key may have this setting. It can also be set to ``True`` to indicate autoincrement semantics on a column that has a client-side or server-side default configured, however note that not all dialects can accommodate all styles of default as an "autoincrement". It can also be set to ``False`` on a single-column primary key that has a datatype of INTEGER in order to disable auto increment semantics for that column. .. versionchanged:: 1.1 The autoincrement flag now defaults to ``"auto"`` which indicates autoincrement semantics by default for single-column integer primary keys only; for composite (multi-column) primary keys, autoincrement is never implicitly enabled; as always, ``autoincrement=True`` will allow for at most one of those columns to be an "autoincrement" column. ``autoincrement=True`` may also be set on a :class:`_schema.Column` that has an explicit client-side or server-side default, subject to limitations of the backend database and dialect. The setting *only* has an effect for columns which are: * Integer derived (i.e. INT, SMALLINT, BIGINT). * Part of the primary key * Not referring to another column via :class:`_schema.ForeignKey`, unless the value is specified as ``'ignore_fk'``:: # turn on autoincrement for this column despite # the ForeignKey() Column('id', ForeignKey('other.id'), primary_key=True, autoincrement='ignore_fk') It is typically not desirable to have "autoincrement" enabled on a column that refers to another via foreign key, as such a column is required to refer to a value that originates from elsewhere. The setting has these two effects on columns that meet the above criteria: * DDL issued for the column will include database-specific keywords intended to signify this column as an "autoincrement" column, such as AUTO INCREMENT on MySQL, SERIAL on PostgreSQL, and IDENTITY on MS-SQL. It does *not* issue AUTOINCREMENT for SQLite since this is a special SQLite flag that is not required for autoincrementing behavior. .. seealso:: :ref:`sqlite_autoincrement` * The column will be considered to be available using an "autoincrement" method specific to the backend database, such as calling upon ``cursor.lastrowid``, using RETURNING in an INSERT statement to get at a sequence-generated value, or using special functions such as "SELECT scope_identity()". These methods are highly specific to the DBAPIs and databases in use and vary greatly, so care should be taken when associating ``autoincrement=True`` with a custom default generation function. :param default: A scalar, Python callable, or :class:`_expression.ColumnElement` expression representing the *default value* for this column, which will be invoked upon insert if this column is otherwise not specified in the VALUES clause of the insert. This is a shortcut to using :class:`.ColumnDefault` as a positional argument; see that class for full detail on the structure of the argument. Contrast this argument to :paramref:`_schema.Column.server_default` which creates a default generator on the database side. .. seealso:: :ref:`metadata_defaults_toplevel` :param doc: optional String that can be used by the ORM or similar to document attributes on the Python side. This attribute does **not** render SQL comments; use the :paramref:`_schema.Column.comment` parameter for this purpose. :param key: An optional string identifier which will identify this ``Column`` object on the :class:`_schema.Table`. When a key is provided, this is the only identifier referencing the ``Column`` within the application, including ORM attribute mapping; the ``name`` field is used only when rendering SQL. :param index: When ``True``, indicates that a :class:`_schema.Index` construct will be automatically generated for this :class:`_schema.Column`, which will result in a "CREATE INDEX" statement being emitted for the :class:`_schema.Table` when the DDL create operation is invoked. Using this flag is equivalent to making use of the :class:`_schema.Index` construct explicitly at the level of the :class:`_schema.Table` construct itself:: Table( "some_table", metadata, Column("x", Integer), Index("ix_some_table_x", "x") ) To add the :paramref:`_schema.Index.unique` flag to the :class:`_schema.Index`, set both the :paramref:`_schema.Column.unique` and :paramref:`_schema.Column.index` flags to True simultaneously, which will have the effect of rendering the "CREATE UNIQUE INDEX" DDL instruction instead of "CREATE INDEX". The name of the index is generated using the :ref:`default naming convention ` which for the :class:`_schema.Index` construct is of the form ``ix__``. As this flag is intended only as a convenience for the common case of adding a single-column, default configured index to a table definition, explicit use of the :class:`_schema.Index` construct should be preferred for most use cases, including composite indexes that encompass more than one column, indexes with SQL expressions or ordering, backend-specific index configuration options, and indexes that use a specific name. .. note:: the :attr:`_schema.Column.index` attribute on :class:`_schema.Column` **does not indicate** if this column is indexed or not, only if this flag was explicitly set here. To view indexes on a column, view the :attr:`_schema.Table.indexes` collection or use :meth:`_reflection.Inspector.get_indexes`. .. seealso:: :ref:`schema_indexes` :ref:`constraint_naming_conventions` :paramref:`_schema.Column.unique` :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. :param nullable: When set to ``False``, will cause the "NOT NULL" phrase to be added when generating DDL for the column. When ``True``, will normally generate nothing (in SQL this defaults to "NULL"), except in some very specific backend-specific edge cases where "NULL" may render explicitly. Defaults to ``True`` unless :paramref:`_schema.Column.primary_key` is also ``True``, in which case it defaults to ``False``. This parameter is only used when issuing CREATE TABLE statements. :param onupdate: A scalar, Python callable, or :class:`~sqlalchemy.sql.expression.ClauseElement` representing a default value to be applied to the column within UPDATE statements, which will be invoked upon update if this column is not present in the SET clause of the update. This is a shortcut to using :class:`.ColumnDefault` as a positional argument with ``for_update=True``. .. seealso:: :ref:`metadata_defaults` - complete discussion of onupdate :param primary_key: If ``True``, marks this column as a primary key column. Multiple columns can have this flag set to specify composite primary keys. As an alternative, the primary key of a :class:`_schema.Table` can be specified via an explicit :class:`.PrimaryKeyConstraint` object. :param server_default: A :class:`.FetchedValue` instance, str, Unicode or :func:`~sqlalchemy.sql.expression.text` construct representing the DDL DEFAULT value for the column. String types will be emitted as-is, surrounded by single quotes:: Column('x', Text, server_default="val") x TEXT DEFAULT 'val' A :func:`~sqlalchemy.sql.expression.text` expression will be rendered as-is, without quotes:: Column('y', DateTime, server_default=text('NOW()')) y DATETIME DEFAULT NOW() Strings and text() will be converted into a :class:`.DefaultClause` object upon initialization. Use :class:`.FetchedValue` to indicate that an already-existing column will generate a default value on the database side which will be available to SQLAlchemy for post-fetch after inserts. This construct does not specify any DDL and the implementation is left to the database, such as via a trigger. .. seealso:: :ref:`server_defaults` - complete discussion of server side defaults :param server_onupdate: A :class:`.FetchedValue` instance representing a database-side default generation function, such as a trigger. This indicates to SQLAlchemy that a newly generated value will be available after updates. This construct does not actually implement any kind of generation function within the database, which instead must be specified separately. .. warning:: This directive **does not** currently produce MySQL's "ON UPDATE CURRENT_TIMESTAMP()" clause. See :ref:`mysql_timestamp_onupdate` for background on how to produce this clause. .. seealso:: :ref:`triggered_columns` :param quote: Force quoting of this column's name on or off, corresponding to ``True`` or ``False``. When left at its default of ``None``, the column identifier will be quoted according to whether the name is case sensitive (identifiers with at least one upper case character are treated as case sensitive), or if it's a reserved word. This flag is only needed to force quoting of a reserved word which is not known by the SQLAlchemy dialect. :param unique: When ``True``, and the :paramref:`_schema.Column.index` parameter is left at its default value of ``False``, indicates that a :class:`_schema.UniqueConstraint` construct will be automatically generated for this :class:`_schema.Column`, which will result in a "UNIQUE CONSTRAINT" clause referring to this column being included in the ``CREATE TABLE`` statement emitted, when the DDL create operation for the :class:`_schema.Table` object is invoked. When this flag is ``True`` while the :paramref:`_schema.Column.index` parameter is simultaneously set to ``True``, the effect instead is that a :class:`_schema.Index` construct which includes the :paramref:`_schema.Index.unique` parameter set to ``True`` is generated. See the documentation for :paramref:`_schema.Column.index` for additional detail. Using this flag is equivalent to making use of the :class:`_schema.UniqueConstraint` construct explicitly at the level of the :class:`_schema.Table` construct itself:: Table( "some_table", metadata, Column("x", Integer), UniqueConstraint("x") ) The :paramref:`_schema.UniqueConstraint.name` parameter of the unique constraint object is left at its default value of ``None``; in the absence of a :ref:`naming convention ` for the enclosing :class:`_schema.MetaData`, the UNIQUE CONSTRAINT construct will be emitted as unnamed, which typically invokes a database-specific naming convention to take place. As this flag is intended only as a convenience for the common case of adding a single-column, default configured unique constraint to a table definition, explicit use of the :class:`_schema.UniqueConstraint` construct should be preferred for most use cases, including composite constraints that encompass more than one column, backend-specific index configuration options, and constraints that use a specific name. .. note:: the :attr:`_schema.Column.unique` attribute on :class:`_schema.Column` **does not indicate** if this column has a unique constraint or not, only if this flag was explicitly set here. To view indexes and unique constraints that may involve this column, view the :attr:`_schema.Table.indexes` and/or :attr:`_schema.Table.constraints` collections or use :meth:`_reflection.Inspector.get_indexes` and/or :meth:`_reflection.Inspector.get_unique_constraints` .. seealso:: :ref:`schema_unique_constraint` :ref:`constraint_naming_conventions` :paramref:`_schema.Column.index` :param system: When ``True``, indicates this is a "system" column, that is a column which is automatically made available by the database, and should not be included in the columns list for a ``CREATE TABLE`` statement. For more elaborate scenarios where columns should be conditionally rendered differently on different backends, consider custom compilation rules for :class:`.CreateColumn`. :param comment: Optional string that will render an SQL comment on table creation. .. versionadded:: 1.2 Added the :paramref:`_schema.Column.comment` parameter to :class:`_schema.Column`. r Ntype_rz0May not pass name positionally and as a keyword. _sqla_typez1May not pass type_ positionally and as a keyword.rPz9Explicit 'name' is required when sending 'quote' argumentr+rFnullabledefaultserver_defaultserver_onupdaterrsystemdoconupdate autoincrementautor_proxies_warn_on_bytestringzUnicode column 'z ' has non-unicode default value z specified.T for_updaterHr).rrrr(r string_typesrr<hasattrrrr)rr+rr)r*r+r,rrr-r.r/r0rrrrcomputedr2typer r9 ColumnDefaultSequencerr binary_typer FetchedValue_as_for_update DefaultClauserBset_creation_orderrHr)r=r>rEr r'coltypers r"rzColumn.__init__Cs H zz&$'' 7D))Dzz  #$q'4#455 ##+Jxx{{  $1gGw -- $$+K   tVZZ%>%>??DD   #N  fd$$T5111::eT**!::mU;; :43C/CDD zz)T22 $jj)94@@%zz*;TBB ZZ.. jj400 jj511 ::eT** :t44 #ZZ@@55EEzz)T22     "JJz22DMM  #4 5 5 6 I / / 5 5 5 < #$,(ABB 9 DL))))49&;UCC!$,0@AA  $xxx7  M$,77888   *$-|<< @ D/>>uEEFFFF M$*=>>??? = $$--)BCC K DM**** M$-DIIIJJJ   +$. ==  D0??EEFFFF !$"64HHH $ %%% V   6**DI$$V$$$$$r$c 0||dSr'rrDs r"rzColumn._extra_kwargs)rr$c|jdS|j*|jjr|jjdz|jzS|jS|jS)Nz (no name)r)r r*named_with_columnrrLs r"rzColumn.__str__0sN 9 ; Z #z+ (z-3d6FFF''# #r$ch|jD])}|jj|jrdS*dS)zOReturn True if this Column references the given column via foreign key.TF)rr proxy_set intersectionr=rfks r" referenceszColumn.references;sG#  By"//0@AA tt 5r$c0||dSr'r)r=rIs r"append_foreign_keyzColumn.append_foreign_keyEs $$T*****r$cg}jjkr|djr|djs|djr|djr|djr|djr|ddd tjgtj gzd j Dzd j Dzjdurd jjzpd gzfd|DzzS)Nr+rr)r/r*r+rz Column(%s)rc0g|]}|t|Sr'rrs r"rz#Column.__repr__..[sCCC1Q]tAww]]]r$c,g|]}t|Srrrs r"rz#Column.__repr__..\s1111tAww111r$z table=<%s>z table=Nonec Tg|]$}|dtt|%Srrrs r"rz#Column.__repr__..ds7DDD!!!T'$"2"23334DDDr$)r+r rrr)r/r*r+rrrr9rrr*r)r=kwargs` r"rMzColumn.__repr__Hs 8ty LL      ( LL ' ' '} % LL $ $ $ = % LL $ $ $ < $ LL # # #   + LL) * * * < $ LL # # #dii $)__ DI CC 1CCC D21 0111 2 Jd*>$tz'==$#  EDDDeDDD E    r$c |jstjd|j |j|_t |dd}|)|ur%tjd|jd|jd|jjvrtj|j}||urQ|jD]I}j ||j j vrj |j Jj ||_ |jrj|n3|jjvr%tjd|jdjd|jrqt%|jt&jrtjdt-d|jt/|jd nc|jr\t%|jt&jrtjd t3|jd |fd dS)NzfColumn must be constructed with a non-blank name or assign a non-blank .name before adding to a Table.r*zColumn object 'z' already assigned to Table ''z'Trying to redefine primary-key column 'z(' as a non-primary-key column on table 'zThe 'index' keyword argument on Column is boolean only. To create indexes with a specific name, create an explicit Index object external to the Table.T)rrzThe 'unique' keyword argument on Column is boolean only. To create unique constraints or indexes with a specific name, append an explicit UniqueConstraint to the Table's list of elements, or create an explicit Index object external to the Table.)rc.|Sr')_set_remote_table)rIr*s r"rz$Column._set_parent..sr/C/CE/J/Jr$)r rr<r+rrrrYrrrrr0r*r_replacerrr(rr6rrrtrUniqueConstraint_setup_on_memoized_fks)r=r*existingr-rIs ` r"rzColumn._set_parentgsy #E  8 yDH4$//  HE$9$9##888X1113  8u~ % %.$$TX..C$*@@B&--b111}(999)00??? t$$$      & &t , , , , X* * *##888U^^^-  : $*d&788 'C  # #$(4 +<+<4     [ $+t'899 ':  # # ===    ##$J$J$J$JKKKKKr$c|jj|jfdf|jj|jfdfg}|D]F\}}||jjjvr.|jjj|D]}|j|ur ||GdS)NFT)r*r+r r _fk_memos link_to_name)r=rfk_keysfk_keyr\rIs r"rXzColumn._setup_on_memoized_fkssjndh ' /jndi ($ / %,   FL,666*-7?B,662   r$cf|j|||jdStj|d|dS)Nrz)r*rr)r=rs r"_on_table_attachzColumn._on_table_attachs? : ! BtTZ L4b 9 9 9 9 9r$c fd|jDfd|jDz}i}|jD]9}|j|j}|D]\}}|||dz|z<:|j}|j} t|tr)dx}} | |jj di|j } t| tr | j di} |j ||j| |j|j|j|j|j|j|j|j||j| |j|jd|} || S)zuCreate a copy of this ``Column``, uninitialized. This is used in :meth:`_schema.Table.tometadata`. c8g|]}|j |jdiSr)rrTrr,r~s r"rzColumn.copy..s>   !- AFLLRLL   r$c8g|]}|j |jdiSrc)rrTrds r"rzColumn.copy..s. I I IaAL IVQV\\b\\ I I Ir$rN)r r'r+rr)rr-rr0r*r+r/r,r.rr)rrdialect_options _non_defaultsitemsr+r,r(ComputedrrTr9r _constructorr r+rr)rr-rr0r*r/r.rrW) r=r~r> column_kwargs dialect_namerfdialect_option_keydialect_option_valuer+r,r'r,s ` r"rTz Column.copys    "&"2   I I I I4#4 I I IJ   0 ) )L"2<@NO!&&(( ) )"$) 3&);;  ),. nh / / 8/3 3N_ KK0+066266 7 7 7  e. / / %EJ$$$$E D "!(];;*,L)]+L!  $%  (%%a(((r$NFc d|jD}||jtjd |j|rt |p|jn|p|j|jg|R|r|n |r|n|j|j|j |gd}nB#t$r5}tj td|j z|Yd}~nd}~wwxYw||_|j||j)|jj|j|_|jr|j||j|||S)a$Create a *proxy* for this column. This is a copy of this ``Column`` referenced by a different parent (such as an alias or select statement). The column should be used only in select scenarios, as its full DDL/default information is not transferred. cDg|]}t|j|jS)) _constraint) ForeignKeyrr)rfs r"rz&Column._make_proxy..s9    qxQ\ : : :   r$Nz^Cannot initialize a sub-selectable with this Column object until its 'name' has been assigned.)r+rr)r2zCould not create a copy of this %r object. Ensure the class includes a _constructor() attribute or method which accepts the standard Column constructor arguments, or references the Column class itself.from_)rr rrurjr r9r+rr)rprr;rr*rr _is_clone_ofrrYrUrz) r= selectabler r+name_is_truncatabler~rIr,rAs r" _make_proxyzColumn._make_proxys  &    CCD$>DDdh ,   AA    K:=AN K          """  " .'4<@@GGAN   *  " & &q ) ) ) &&q*555sAB C +B<<Cc |rBd|j|jfDt|jzt|jzSt j|fi|S)Ncg|]}||Sr'rrs r"rz'Column.get_children..-sKKKqQ]]]]r$)r*r/rrrrrF)r=rrEs r"rFzColumn.get_children*sj  =KKT\4=9KKKt())*t'(()   ,T<s22Nd%d%d%d%d%L... $ $ $+++   >BLBLBLH   ::: 6)6)6)rDI4444l========r$r)ceZdZdZdZ ddZdZddZddZe d Z d Z e eZ d Z d Zejd ZdZdZdZejdZdZdZdZdZdS)rra;Defines a dependency between two columns. ``ForeignKey`` is specified as an argument to a :class:`_schema.Column` object, e.g.:: t = Table("remote_table", metadata, Column("remote_id", ForeignKey("main_table.id")) ) Note that ``ForeignKey`` is only a marker object that defines a dependency between two columns. The actual constraint is in all cases represented by the :class:`_schema.ForeignKeyConstraint` object. This object will be generated automatically when a ``ForeignKey`` is associated with a :class:`_schema.Column` which in turn is associated with a :class:`_schema.Table`. Conversely, when :class:`_schema.ForeignKeyConstraint` is applied to a :class:`_schema.Table`, ``ForeignKey`` markers are automatically generated to be present on each associated :class:`_schema.Column`, which are also associated with the constraint object. Note that you cannot define a "composite" foreign key constraint, that is a constraint between a grouping of multiple parent/child columns, using ``ForeignKey`` objects. To define this grouping, the :class:`_schema.ForeignKeyConstraint` object must be used, and applied to the :class:`_schema.Table`. The associated ``ForeignKey`` objects are created automatically. The ``ForeignKey`` objects associated with an individual :class:`_schema.Column` object are available in the `foreign_keys` collection of that column. Further examples of foreign key configuration are in :ref:`metadata_foreignkeys`. foreign_keyNFc  ||_t|jtjrd|_nt |jdr|j|_n |j|_t|jtstj d|jzt|jj tj tfs!tj d|jj z||_ d|_||_||_||_||_||_||_| |_| |_| r| |_| |_dS)a Construct a column-level FOREIGN KEY. The :class:`_schema.ForeignKey` object when constructed generates a :class:`_schema.ForeignKeyConstraint` which is associated with the parent :class:`_schema.Table` object's collection of constraints. :param column: A single target column for the key relationship. A :class:`_schema.Column` object or a column name as a string: ``tablename.columnkey`` or ``schema.tablename.columnkey``. ``columnkey`` is the ``key`` which has been assigned to the column (defaults to the column name itself), unless ``link_to_name`` is ``True`` in which case the rendered name of the column is used. :param name: Optional string. An in-database name for the key if `constraint` is not provided. :param onupdate: Optional string. If set, emit ON UPDATE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param ondelete: Optional string. If set, emit ON DELETE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param link_to_name: if True, the string name given in ``column`` is the rendered name of the referenced column, not its locally assigned ``key``. :param use_alter: passed to the underlying :class:`_schema.ForeignKeyConstraint` to indicate the constraint should be generated/dropped externally from the CREATE TABLE/ DROP TABLE statement. See :paramref:`_schema.ForeignKeyConstraint.use_alter` for further description. .. seealso:: :paramref:`_schema.ForeignKeyConstraint.use_alter` :ref:`use_alter` :param match: Optional string. If set, emit MATCH when issuing DDL for this constraint. Typical values include SIMPLE, PARTIAL and FULL. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. The arguments are ultimately handled by a corresponding :class:`_schema.ForeignKeyConstraint`. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 N__clause_element__z9String, Column, or Column-bound argument expected, got %rz8ForeignKey received Column not bound to a Table, got: %r)_colspecr(rr6 _table_columnr7rrrr<r*NoneTyperrparent use_alterr r/ondelete deferrable initiallyr\matchrH_unvalidated_dialect_kw) r=rrqrr r/rrrr\rrH dialect_kws r"rzForeignKey.__init___sWj dmT%6 7 7 !%D  t}&:;; 3%)]%E%E%G%G""%)]"d0,?? '')-);< "(4=+*F '*,0,>,DE& "     $"(  DI'1$$$r$c0d|zS)NzForeignKey(%r)) _get_colspecrLs r"rMzForeignKey.__repr__s$"3"3"5"555r$c t||f|j|j|j|j|j|j|j|j d|j }| |S)aProduce a copy of this :class:`_schema.ForeignKey` object. The new :class:`_schema.ForeignKey` will not be bound to any :class:`_schema.Column`. This method is usually used by the internal copy procedures of :class:`_schema.Column`, :class:`_schema.Table`, and :class:`_schema.MetaData`. :param schema: The returned :class:`_schema.ForeignKey` will reference the original table and column name, qualified by the given string schema name. r)rr r/rrrr\r) rrrrr r/rrrr\rrrW)r=r!rIs r"rTzForeignKey.copys}    V  , ,  n]]n**   *   %%b)))r$c|r|j\}}}||}|d|d|S|r|j\}}}|r |d|d|S|d|S|j |jjjd|jjS|jS)zReturn a string based 'column specification' for this :class:`_schema.ForeignKey`. This is usually the equivalent of the string-based "tablename.colname" argument first passed to the object's constructor. Nr)_column_tokensrr*rr+r)r=r! table_name_schematnamecolnames r"rzForeignKey._get_colspecs  !&*&9 #GUG%"!'8 8  !%)%8 "FE7 7%+VVZZZAA",**gg66   +"(111"&&  = r$c|jdS)Nr)rrLs r"rzForeignKey._referred_schemas"1%%r$c|j|jjdS|jjjS|j\}}}t ||Sr')rr*r+rr#)r=r!rrs r" _table_keyzForeignKey._table_keysJ   )!'/t)/33%)%8 "FE7!%00 0r$c:||jduS)zrReturn True if the given :class:`_schema.Table` is referenced by this :class:`_schema.ForeignKey`.Ncorresponding_columnrrs r"rJzForeignKey.references)s ))$+66dBBr$c6||jS)aReturn the :class:`_schema.Column` in the given :class:`_schema.Table` referenced by this :class:`_schema.ForeignKey`. Returns None if this :class:`_schema.ForeignKey` does not reference the given :class:`_schema.Table`. rrs r" get_referentzForeignKey.get_referent0s))$+666r$c|d}|tjd|jzt |dkr|}d}n(|}|}t |dkrd|}nd}|||fS)z7parse a string-based _colspec into its component parts.rNz,Invalid foreign key column specification: %srr)rsplitrr<rlenrrr)r=mrrr!s r"rzForeignKey._column_tokens=s      % %c * * 9#>N  q66Q;;EEGGEGGeeggGEEGGE q66A::XXa[[FFFug%%r$cj|jtjd|jjtjd|jj}|jjD]$}t |t r |j|usJn%J|j\}}}||jj |jj }t||}|||fS)NzLthis ForeignKey object does not yet have a parent Column associated with it.zCthis ForeignKey's parent column is not yet associated with a Table.) rrrur* base_columnsr(r)rrr!r#)r= parenttabler,r!rrtablekeys r"_resolve_col_tokenszForeignKey._resolve_col_tokens\s ; )4  [  &)   k' )  A!V$$ w+----  5"&!4w >k29E )0F!%00Hg--r$c t|jds ||j_n|jj|usJd}|-|j}|j|jjd}n>|jr|}|jD]}|j|kr|}n|}|j|d}|7tj d|j d|jd|jd|d |j|| |dS)N_referred_table3Could not initialize target column for ForeignKey ' ' on table ' ': table '' has no column named 'rS) r7rrrr,rYr+r\r rNoReferencedColumnErrorr_set_target_column)r=rr*r_columnr+r,s r"_link_to_col_by_colstringz$ForeignKey._link_to_col_by_colstrings*t(9:: <.3DO + +?2e;;;; ? +Cgkk$+/488GG   1CW  6W$$G Cgkk'400G ?--===+"2"2"2EJJJE    (((((r$c|jjjrj|j_t|jjt rfd}|j||_dS)NcP|jjjrj|j_dSdSr')rr9_isnull)rIrs r"set_typez/ForeignKey._set_target_column..set_types+9>)1%+[BINNN11r$)rr9rr(r*rfrXr)r=rrs ` r"rzForeignKey._set_target_columnst ;  # +%{DK  dk' / / 9 1 1 1 1 1 K . .x 8 8 8 r$c t|jtjr|\}}}||jvr$t jd|jd|d|d||j |jvrt j d|zt j d|jd|j d|d |d ||t|jd r|j}|S|j}|S) aReturn the target :class:`_schema.Column` referenced by this :class:`_schema.ForeignKey`. If no target column has been established, an exception is raised. .. versionchanged:: 0.9.0 Foreign key target column resolution now occurs as soon as both the ForeignKey object and the remote Column to which it refers are both associated with the same MetaData object. z$Foreign key associated with column 'z' could not find table 'z9' with which to generate a foreign key to target column 'rSz9Table %s is no longer associated with its parent MetaDatarrrrr)r(rrr6rrrNoReferencedTableErrorrr+rurr r7r)r=rrrrs r"rzForeignKey.columns3 dmT%6 7 7 -1-E-E-G-G *K7{33300{{{HHHggg7  (<<<-&(34 11}}}k&6&6&6'''K T]$8 9 9 m6688GNmGNr$c|j|j|urtjd||_|jj||j|jdS)Nz&This ForeignKey already has a parent !)rrrurrr` _set_tablers r"rzForeignKey._set_parentsn ; "t{&'@'@)8    $$T*** $$T_55555r$c|\}}}|||||j|dSr')rrr_validate_dest_table)r=r*rrrs r"rUzForeignKey._set_remote_tablesN)-)A)A)C)C& Xw &&{E7CCC ,,U33333r$c|\}}}||f}||j|vr"|j||dSdSr')rr[r)r=rr table_keyrr^s r"_remove_from_metadataz ForeignKey._remove_from_metadatasa*.*B*B*D*D' YW% 8%f- - -  v & - -d 3 3 3 3 3 . -r$c |jt|trxtggf|j|j|j|j|j|j |j d|j |_|j |||j ||j|t|jt"jr|\}}}||f}||jjvr@|jj|} ||||n#t.j$rYnwxYw|jj||dSt7|jdr0|j}||dS|j}||dS)N)rr r/rrrrr)rr(rfrrr r/rrrrr_append_elementr9rrrrr6rrrsrrrr[rr7rr)r=rr*rrrr^rs r"rzForeignKey._set_tables ? "z%'?'? "2 .Y?.j  .  DO O + +FD 9 9 9 O 5 5e < < < t$$$ dmT%6 7 7 -.2.F.F.H.H +KG)FK0777#,3I>22;wOOOO2D  *6 2 9 9$ ? ? ? ? ? T]$8 9 9 -m6688G  # #G , , , , ,mG  # #G , , , , ,s D##D54D5) NFNNNNNFNNr'NN)r]r^r_r`rarrMrTrrbrrtarget_fullnamerJrrrdrrrrrrrUrrrr$r"rrrr5s%%N#N   |2|2|2|2|666****<!!!!6&&X&111h|,,OCCC 7 7 7 &&&) s43J3J3L3Lr$c*|Sr'rrLs r"rz_NotAColumnExpr.* s$*A*A*C*Cr$N)r]r^r_rr self_grouprb _from_objectsrr$r"rr" sA   'M&LLHCCDDMMMr$rcTeZdZdZdZdZdZdZd dZdZ d dZ dZ e d Z dS) DefaultGeneratorz'Base class for column *default* values.default_generatorFNc||_dSr'r4r=r5s r"rzDefaultGenerator.__init__6 $r$cV||_|jr||j_dS||j_dSr')rr5r/r*rs r"rzDefaultGenerator._set_parent9 s3 ? '#'DK "&DK   r$c @|t|}|j|fi|Sr')rexecute)r=rrEs r"rzDefaultGenerator.execute@ s. <!$''Dt|D++F+++r$c0||||Sr')_execute_default)r=r multiparamsparamss r"_execute_on_connectionz'DefaultGenerator._execute_on_connectionE s**4fEEEr$cJt|dd|jjjSdS)z4Return the connectable associated with this default.rN)rrr*rrLs r"rzDefaultGenerator.bindH s) 44 ( ( 4;$) )4r$r|r')r]r^r_r`ra is_sequenceis_server_defaultrrrrrrbrrr$r"rr- s11(NK F%%%%''',,,, FFFXr$rceZdZdZfdZejdZejdZejdZ ejej ddZ dZ d Z ee Zd ZxZS) r:aA plain default value on a column. This could correspond to a constant, a callable function, or a SQL clause. :class:`.ColumnDefault` is generated automatically whenever the ``default``, ``onupdate`` arguments of :class:`_schema.Column` are used. A :class:`.ColumnDefault` can be passed positionally as well. For example, the following:: Column('foo', Integer, default=50) Is equivalent to:: Column('foo', Integer, ColumnDefault(50)) c tt|jdi|t|trt jdtj|r| |}||_ dS)a{Construct a new :class:`.ColumnDefault`. :param arg: argument representing the default value. May be one of the following: * a plain non-callable Python value, such as a string, integer, boolean, or other simple type. The default value will be used as is each time. * a SQL expression, that is one which derives from :class:`_expression.ColumnElement`. The SQL expression will be rendered into the INSERT or UPDATE statement, or in the case of a primary key column when RETURNING is not used may be pre-executed before an INSERT within a SELECT. * A Python callable. The function will be invoked for each new row subject to an INSERT or UPDATE. The callable must accept exactly zero or one positional arguments. The one-argument form will receive an instance of the :class:`.ExecutionContext`, which provides contextual information as to the current :class:`_engine.Connection` in use as well as the current statement and parameters. z4ColumnDefault may not be a server-side default type.Nr) rr:rr(r=rr<rcallable_maybe_wrap_callablearg)r=rrErs r"rzColumnDefault.__init__g s4 ,mT""+55f555 c< ( ( #F  =   1++C00Cr$c4tj|jSr')rrrrLs r" is_callablezColumnDefault.is_callable s}TX&&&r$c6t|jtSr')r(rrrLs r"is_clause_elementzColumnDefault.is_clause_element s$(M222r$c2|j o|j o|j Sr')rrrrLs r" is_scalarzColumnDefault.is_scalar s.  %** %$$ r$zsqlalchemy.sql.sqltypescT|jr t|jj|j SdSr!)rr(rr9NullType)r=sqltypess r" _arg_is_typedzColumnDefault._arg_is_typed s.  ! !$(-1BCCC C5r$cj tjd}n(#t$rtjfdcYSwxYw|ddurt |dpd}t |d|z }|dkrtjfdS|dkrSt jd ) zWrap callables that don't accept a context. This is to allow easy compatibility with default callables that aren't specific to accepting of a context. T)no_selfcSr'rctxrs r"rz4ColumnDefault._maybe_wrap_callable.. ""$$r$NrcSr'rrs r"rz4ColumnDefault._maybe_wrap_callable.. rr$rzDColumnDefault Python function takes zero or one positional arguments)rget_callable_argspecrp wrap_callablerrr<)r=rargspec defaulted positionalss ` r"rz"ColumnDefault._maybe_wrap_callable s </DAAAGG < < <%&6&6&6&6;; ; ; ; <AJd*>s71:C! '!*oo 1 !  %&6&6&6&6;; ; A  I#' s "??c|jrdSdS)Ncolumn_onupdatecolumn_defaultr4rLs r" _visit_namezColumnDefault._visit_name s ? $$$##r$cd|jdS)NzColumnDefault())rrLs r"rMzColumnDefault.__repr__ s&*hhh00r$)r]r^r_r`rrrdrrr dependenciesrrrrbrarMr#r$s@r"r:r:Q s*!!!!!F ''' 333     T01121 4$$$ Xk**N1111111r$r:c,eZdZdZ ddZdS)IdentityOptionszDefines options for a named database sequence or an identity column. .. versionadded:: 1.3.18 .. seealso:: :class:`.Sequence` Nc ||_||_||_||_||_||_||_||_| |_dS)aiConstruct a :class:`.IdentityOptions` object. See the :class:`.Sequence` documentation for a complete description of the parameters :param start: the starting index of the sequence. :param increment: the increment value of the sequence. :param minvalue: the minimum value of the sequence. :param maxvalue: the maximum value of the sequence. :param nominvalue: no minimum value of the sequence. :param nomaxvalue: no maximum value of the sequence. :param cycle: allows the sequence to wrap around when the maxvalue or minvalue has been reached. :param cache: optional integer value; number of future values in the sequence which are calculated in advance. :param order: optional boolean value; if ``True``, renders the ORDER keyword. name. N start incrementminvaluemaxvalue nominvalue nomaxvaluecyclecacheorder) r=rrrrrrr r r s r"rzIdentityOptions.__init__ sG> "    $$   r$) NNNNNNNNNr]r^r_r`rrr$r"rr sO''''''r$rceZdZdZdZdZ ddZejdZ ejdZ ej d d Z fd Z d Zd ZedZddZddZdZxZS)r;aRepresents a named database sequence. The :class:`.Sequence` object represents the name and configurational parameters of a database sequence. It also represents a construct that can be "executed" by a SQLAlchemy :class:`_engine.Engine` or :class:`_engine.Connection`, rendering the appropriate "next value" function for the target database and returning a result. The :class:`.Sequence` is typically associated with a primary key column:: some_table = Table( 'some_table', metadata, Column('id', Integer, Sequence('some_table_seq'), primary_key=True) ) When CREATE TABLE is emitted for the above :class:`_schema.Table`, if the target platform supports sequences, a CREATE SEQUENCE statement will be emitted as well. For platforms that don't support sequences, the :class:`.Sequence` construct is ignored. .. seealso:: :class:`.CreateSequence` :class:`.DropSequence` sequenceTNFc t||t||||||||| |  t|| |_| |_| t ur dx|_} n/|| |jr|jx|_} nt| ||_||_t|| |_ |r| |dSdS)alConstruct a :class:`.Sequence` object. :param name: the name of the sequence. :param start: the starting index of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "START WITH" clause. If ``None``, the clause is omitted, which on most platforms indicates a starting value of 1. :param increment: the increment value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "INCREMENT BY" clause. If ``None``, the clause is omitted, which on most platforms indicates an increment of 1. :param minvalue: the minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "MINVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param maxvalue: the maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "MAXVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param nominvalue: no minimum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "NO MINVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a minvalue of 1 and -2^63-1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param nomaxvalue: no maximum value of the sequence. This value is used when the CREATE SEQUENCE command is emitted to the database as the value of the "NO MAXVALUE" clause. If ``None``, the clause is omitted, which on most platforms indicates a maxvalue of 2^63-1 and -1 for ascending and descending sequences, respectively. .. versionadded:: 1.0.7 :param cycle: allows the sequence to wrap around when the maxvalue or minvalue has been reached by an ascending or descending sequence respectively. This value is used when the CREATE SEQUENCE command is emitted to the database as the "CYCLE" clause. If the limit is reached, the next number generated will be the minvalue or maxvalue, respectively. If cycle=False (the default) any calls to nextval after the sequence has reached its maximum value will return an error. .. versionadded:: 1.0.7 :param schema: optional schema name for the sequence, if located in a schema other than the default. The rules for selecting the schema name when a :class:`_schema.MetaData` is also present are the same as that of :paramref:`_schema.Table.schema`. :param cache: optional integer value; number of future values in the sequence which are calculated in advance. Renders the CACHE keyword understood by Oracle and PostgreSQL. .. versionadded:: 1.1.12 :param order: optional boolean value; if ``True``, renders the ORDER keyword, understood by Oracle, indicating the sequence is definitively ordered. May be necessary to provide deterministic ordering using Oracle RAC. .. versionadded:: 1.1.12 :param optional: boolean value, when ``True``, indicates that this :class:`.Sequence` object only needs to be explicitly generated on backends that don't provide another way to generate primary key identifiers. Currently, it essentially means, "don't create this sequence on the PostgreSQL backend, where the SERIAL keyword creates a sequence for us automatically". :param quote: boolean value, when ``True`` or ``False``, explicitly forces quoting of the :paramref:`_schema.Sequence.name` on or off. When left at its default of ``None``, normal quoting rules based on casing and reserved words take place. :param quote_schema: Set the quoting preferences for the ``schema`` name. :param metadata: optional :class:`_schema.MetaData` object which this :class:`.Sequence` will be associated with. A :class:`.Sequence` that is associated with a :class:`_schema.MetaData` gains the following capabilities: * The :class:`.Sequence` will inherit the :paramref:`_schema.MetaData.schema` parameter specified to the target :class:`_schema.MetaData`, which affects the production of CREATE / DROP DDL, if any. * The :meth:`.Sequence.create` and :meth:`.Sequence.drop` methods automatically use the engine bound to the :class:`_schema.MetaData` object, if any. * The :meth:`_schema.MetaData.create_all` and :meth:`_schema.MetaData.drop_all` methods will emit CREATE / DROP for this :class:`.Sequence`, even if the :class:`.Sequence` is not associated with any :class:`_schema.Table` / :class:`_schema.Column` that's a member of this :class:`_schema.MetaData`. The above behaviors can only occur if the :class:`.Sequence` is explicitly associated with the :class:`_schema.MetaData` via this parameter. .. seealso:: :ref:`sequence_metadata` - full discussion of the :paramref:`.Sequence.metadata` parameter. :param for_update: Indicates this :class:`.Sequence`, when associated with a :class:`_schema.Column`, should be invoked for UPDATE statements on that column's table, rather than for INSERT statements, when no value is otherwise present for that column in the statement. r4rN) rrrrr optionalrqr!rr#_key _set_metadata)r=r rrrrrrr r!r r rrPrrr5s r"rzSequence.__init__ sl !!$:!>>>  !! !  e,,   \ ! !#' 'DK&&  !fnn#+? 2DK&&%fl;;DK  "400  )   x ( ( ( ( ( ) )r$cdSr!rrLs r"rzSequence.is_callable ur$cdSr!rrLs r"rzSequence.is_clause_element rr$zsqlalchemy.sql.functions.funcc:|||jS)zReturn a :class:`.next_value` function element which will render the appropriate increment function for this :class:`.Sequence` within any SQL expression. r) next_valuer)r=funcs r"rzSequence.next_value st$)444r$ctt||||jdSr')rr;rr`r)r=rrs r"rzSequence._set_parent s= h))&11100000r$c:||jdSr')rr)r=rr*s r"rzSequence._set_table s 5>*****r$c<||_||jj|j<dSr')r _sequencesrrs r"rzSequence._set_metadata s   .2  +++r$c,|jr |jjSdSr'rrLs r"rz Sequence.bind s = =% %4r$cl|t|}|tj||dS)z&Creates this sequence in the database.Nrrrs r"r zSequence.create s: <!$''D #-t KKKKKr$cl|t|}|tj||dS)z&Drops this sequence from the database.Nrr rs r"r z Sequence.drop s: <!$''D #+TjIIIIIr$cDtjd|jjz)NzThis %s cannot be used directly as a column expression. Use func.next_value(sequence) to produce a 'next value' function that's usable as a column element.rrLs r"rzSequence._not_a_column_expr s+% #&*^%< =   r$)NNNNNNNNNNFNNNF)NT)r]r^r_r`rarrrrdrrrrrrrrbrr r rr#r$s@r"r;r; sv< NK #n)n)n)n)`  T6775587511111+++333X LLLLJJJJ       r$r;c>eZdZdZdZdZdZd dZdZdZ dZ dZ d S) r=aA marker for a transparent database-side default. Use :class:`.FetchedValue` when the database is configured to provide some automatic default for a column. E.g.:: Column('foo', Integer, FetchedValue()) Would indicate that some trigger or default generator will create a new value for the ``foo`` column during an INSERT. .. seealso:: :ref:`triggered_columns` TFc||_dSr'r4rs r"rzFetchedValue.__init__# rr$cF||jkr|S||Sr')r5_cloners r"r>zFetchedValue._as_for_update& s&  ( (K;;z** *r$c|j|j}|j|j|jdd||_|S)Nr)rrnrSupdaterrr5)r=r5ns r"r%zFetchedValue._clone, sS N " "4> 2 2 $-((( x&&&! r$cV||_|jr||j_dS||j_dSr')rr5r,r+rs r"rzFetchedValue._set_parent3 s3 ? .*.DK ' ' ')-DK & & &r$c*tj|Sr'rJrLs r"rMzFetchedValue.__repr__: s &&&r$Nr|) r]r^r_r`r reflected has_argumentrr>r%rrMrr$r"r=r= s&IL%%%%+++ ...'''''r$r=c.eZdZdZdZdfd ZdZxZS)r?a>A DDL-specified DEFAULT column value. :class:`.DefaultClause` is a :class:`.FetchedValue` that also generates a "DEFAULT" clause when "CREATE TABLE" is emitted. :class:`.DefaultClause` is generated automatically whenever the ``server_default``, ``server_onupdate`` arguments of :class:`_schema.Column` are used. A :class:`.DefaultClause` can be passed positionally as well. For example, the following:: Column('foo', Integer, server_default="50") Is equivalent to:: Column('foo', Integer, DefaultClause("50")) TFctj|tjdttfdt t ||||_||_ dS)Nrr) rassert_arg_typer6rrrr?rrr+)r=rr5 _reflectedrs r"rzDefaultClause.__init__V s`  $#A& zBE    mT""++J777#r$c(d|jd|jdS)NzDefaultClause(z , for_update=r)rr5rLs r"rMzDefaultClause.__repr__^ s59XXXtOOr$)FF)r]r^r_r`r,rrMr#r$s@r"r?r?> sd*L$$$$$$PPPPPPPr$r?z0.6zy:class:`.PassiveDefault` is deprecated and will be removed in a future release. Please refer to :class:`.DefaultClause`.ceZdZdZdZdS)PassiveDefaultz%A DDL-specified DEFAULT column value.c0tj|g|Ri|dSr')r?r)r=rr~s r"rzPassiveDefault.__init__j s)t0c000R00000r$Nr rr$r"r3r3b s+ 0/11111r$r3cLeZdZdZdZ d dZedZdZdZ dS) ConstraintzA table-level SQL constraint.rNFc ||_||_||_|r||_||_||_t j|||dS)aCreate a SQL constraint. :param name: Optional, the in-database name of this ``Constraint``. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param _create_rule: a callable which is passed the DDLCompiler object during compilation. Returns True or False to signal inline generation of this Constraint. The AddConstraint and DropConstraint DDL constructs provide DDLElement's more comprehensive "conditional DDL" approach that is passed a database connection when DDL is being issued. _create_rule is instead called during any CREATE TABLE compilation, where there may not be any transaction/connection in progress. However, it allows conditional compilation of the constraint even for backends which do not support addition of constraints through ALTER TABLE, which currently includes SQLite. _create_rule is used by some types to create constraints. Currently, its call signature is subject to change at any time. :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. N) r rrrH _create_rulerrr@r)r=r rrr8rHrrs r"rzConstraint.__init__s sdh $"  DI(& %%% %%j11111r$c t|jtr|jSn#t$rYnwxYwt jd)NzdThis constraint is not bound to a table. Did you mean to call table.append_constraint(constraint) ?)r(rrfr:rrurLs r"r*zConstraint.table sc $+u-- #{" #    D % A   s $ 11cH||_|j|dSr')rrrr=rs r"rzConstraint._set_parent s& t$$$$$r$c tr')NotImplementedError)r=r~s r"rTzConstraint.copy s!###r$)NNNNNF) r]r^r_r`rarrbr*rrTrr$r"r6r6n s''!N <2<2<2<2|   X  %%%$$$$$r$r6ct|dr|}t|tst jd|S)Nrzschema.Column object expected)r7rr(r)rr<)elements r"_to_schema_columnr@ sPw,--/,,.. gv & &A ?@@@ Nr$c||St|dr|}t|tjt fzsd}t j||z|S)Nrz1Element %r is not a string name or column element)r7rr(rr6rrr<)r?rs r"_to_schema_column_or_stringrB sl . / //,,.. gt0M3CC D D/Ag ... Nr$cHeZdZdZ dZdZedZddZdZ dZ dS) ColumnCollectionMixinNFc|dd}|dd|_t|_d|D|_|r|jr|dSdSdS)N _autoattachTrFc,g|]}t|Sr)rBrs r"rz2ColumnCollectionMixin.__init__.. s.! ! ! /0 ' * *! ! ! r$)rrrr r_pending_colargs _check_attach)r=rr~rFs r"rzColumnCollectionMixin.__init__ sff]D11 FF>599')) ! ! 4;! ! !   !40 !     ! ! ! !r$c#K|D]}d}d}t|dr|}t|ttfs|}n)g}t j|id|ji|r|d}||n|}||||fVdS)Nrrr)r7rr(rrrtraverser)r}rrstrnamercols add_elements r""_extract_col_expression_collectionz8ColumnCollectionMixin._extract_col_expression_collection s 5 5DGFt122 1..00d]J$?@@ %!$Xt{,CDDD%!!WF$*$6&&GK4 4 4 4 4 5 5r$c djD}d|D}t|| rh|r JdtdjD|}|s) fd} _ D]}||dS|}d|D}t |dkr)|dSt |dkrijsd|dj fd |ddD} | rAtj d d d | Dd j ddSdSdS)Nc<g|]}t|t|Sr)r(r)rs r"rz7ColumnCollectionMixin._check_attach.. s'NNN! 1f8M8MNANNNr$cFg|]}t|jt|Sr)r(r*rfrs r"rz7ColumnCollectionMixin._check_attach.. s)JJJaz!'5/I/IJJJJr$z#Should not reach here on event callc3K|]}||V dSr'rrs r"rz6ColumnCollectionMixin._check_attach.. s+""AMMMMM""r$ct|tr/|sddSdSdS)NT)r)r(rfdiscardrI)rr* cols_wo_tabler=s r" _col_attachedz:ColumnCollectionMixin._check_attach.._col_attached sd"%//9%--f555,9 ..4.888889999r$ch|] }|j Srr*rs r" z6ColumnCollectionMixin._check_attach..$ s+++a!'+++r$rrc&g|] }|ju |SrrY)rr,r*s r"rz7ColumnCollectionMixin._check_attach..) s%EEEAu0D0Da0D0D0Dr$z Column(s) rc3 K|] }d|zV dSz'%s'Nrrs r"rz6ColumnCollectionMixin._check_attach... s&!=!=&1*!=!=!=!=!=!=r$z are not part of table ''.)rHr difference_cols_wo_tabler`rr9rr_allow_multiple_tablesr*rr<rr) r=rcol_objs cols_w_tablehas_string_colsrWr-rrsothersrVr*s ` @@r"rIz#ColumnCollectionMixin._check_attach sNNt4NNNJJ8JJJ H 00>>   A AA A A7"""0"""j"" # 999999'4#(88C((7777++7+++ v;;!    * *6::<< 8 8 8 8 8 [[1__T%@_AJ$EEEEEEEEF '' !=!=f!=!=!=====))) ___  r$c*fd|jDS)Ncbg|]+}t|tjr j|n|,Sr)r(rr6r,)rr-r*s r"rz:ColumnCollectionMixin._col_expressions..4 sE   'sD,=>> GEGCLLC   r$)rHrs `r"_col_expressionsz&ColumnCollectionMixin._col_expressions3 s1    ,    r$cn||D]}||j|dSr')rhrr)r=r*r-s r"rz!ColumnCollectionMixin._set_parent9 sE((// & &C   %%% & &r$r|) r]r^r_rrar classmethodrOrIrhrrr$r"rDrD sG#!!!55[5$////b   &&&&&r$rDcDeZdZdZdZdZ dZdZd dZdZ dZ d Z dS) ColumnCollectionConstraintz-A constraint that proxies a ColumnCollection.c|dd}|dd}tj|fi|tj|g|R||ddS)aZ :param \*columns: A sequence of column names or Column objects. :param name: Optional, the in-database name of this constraint. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param \**kw: other keyword arguments including dialect-specific arguments are propagated to the :class:`.Constraint` superclass. rFTrF)rFrN)rrr6rrD)r=rr~rFrs r"rz#ColumnCollectionConstraint.__init__B s(ff]D11 vvne44 D''B'''&    (3,      r$Ncrt||t||dSr')r6rrDrs r"rz&ColumnCollectionConstraint._set_parentc s4tU+++))$66666r$c||jvSr')r)r=rs r" __contains__z'ColumnCollectionConstraint.__contains__g sDL  r$c i}jD]9}j|j}|D]\}}|||dz|z<:jfdjDjjjd|}|S)Nrc<g|]}t|jSr)r3r)rrr=r/s r"rz3ColumnCollectionConstraint.copy..{ s7!t{LAAr$)r rr) rfrgrhrrr rrrW) r=r/r~constraint_kwargsrlrfrmrnr,s `` r"rTzColumnCollectionConstraint.copyj s 0 ) )L"2<@NO!&&(( ) )"$)" 3&);;  ) DN Ln   %%a(((r$c6|j|S)zReturn True if this constraint contains the given column. Note that this object also contains an attribute ``.columns`` which is a :class:`_expression.ColumnCollection` of :class:`_schema.Column` objects. )rcontains_columnr=r-s r"ruz*ColumnCollectionConstraint.contains_column s|++C000r$cB|jjfdjDS)Nc3(K|] }|V dSr'r)rr+ ordered_dicts r"rz6ColumnCollectionConstraint.__iter__.. s(@@c S!@@@@@@r$)r_data_list)r=rys @r"__iter__z#ColumnCollectionConstraint.__iter__ s,|) @@@@\-?@@@@r$c4t|jjSr')rrrzrLs r"__len__z"ColumnCollectionConstraint.__len__ s4<%&&&r$r') r]r^r_r`rrrrprTrur|r~rr$r"rlrl? s77   6G 777!!!))))2 1 1 1AAA'''''r$rlceZdZdZdZeddd d fd Zd ZeeZd d Z xZ S) CheckConstraintzlA table- or column-level CHECK constraint. Can be included in the definition of a Table or Column. Tsqltextz:class:`.CheckConstraint`z$:paramref:`.CheckConstraint.sqltext`NFc t|d|_g} tj|jid| jit t |j| |||||| |d| |||dSdS)aConstruct a CHECK constraint. :param sqltext: A string containing the constraint definition, which will be used verbatim, or a SQL expression construct. If given as a string, the object is converted to a :func:`_expression.text` object. If the textual string includes a colon character, escape this using a backslash:: CheckConstraint(r"foo ~ E'a(?\:b|c)d") :param name: Optional, the in-database name of the constraint. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 Tallow_coercion_to_textr)r rrr8rHrrFN) rrrrKrrrrr9) r=rr rrr*rHr8rFrr~rrs r"rzCheckConstraint.__init__ s^(MMM $,Xw~,FGGG-ot$$-!%##      * *5 1 1 1 1 1  r$c>t|jtrdSdS)Ncheck_constraintcolumn_check_constraint)r(rrfrLs r"razCheckConstraint.__visit_name__ s" dk5 ) ) -%%,,r$c |t|j|j|}n|j}t||j|j|j|j|d|j}| |S)NF)r rrr8r*rFr) r3rr*rr rrr8rrW)r=r/r~rr,s r"rTzCheckConstraint.copy sv  #'t|TZNNGGlG  n*( %%a(((r$)NNNNNNTFr') r]r^r_r`rar rrarbrTr#r$s@r"rr s "#. ;2;2;2;2;2  ;2z--- Xn--N))))))))r$rceZdZdZdZ ddZdZdZ dZ e dZ e dZ e d Z d Z e d Ze d Zd ZddZdS)raA table-level FOREIGN KEY constraint. Defines a single column or composite FOREIGN KEY ... REFERENCES constraint. For a no-frills, single column foreign key, adding a :class:`_schema.ForeignKey` to the definition of a :class:`_schema.Column` is a shorthand equivalent for an unnamed, single column :class:`_schema.ForeignKeyConstraint`. Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. foreign_key_constraintNFc  2tjf|||| d| |_|_| _|_| _tt|t|krUtt|t|krtj dtj dfd|D_ tjg|R| 2tdr | jusJ| dSdS)a- Construct a composite-capable FOREIGN KEY. :param columns: A sequence of local column names. The named columns must be defined and present in the parent Table. The names should match the ``key`` given to each column (defaults to the name) unless ``link_to_name`` is True. :param refcolumns: A sequence of foreign column names or Column objects. The columns must all be located within the same Table. :param name: Optional, the in-database name of the key. :param onupdate: Optional string. If set, emit ON UPDATE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param ondelete: Optional string. If set, emit ON DELETE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. :param link_to_name: if True, the string name given in ``column`` is the rendered name of the referenced column, not its locally assigned ``key``. :param use_alter: If True, do not emit the DDL for this constraint as part of the CREATE TABLE definition. Instead, generate it via an ALTER TABLE statement issued after the full collection of tables have been created, and drop it via an ALTER TABLE statement before the full collection of tables are dropped. The use of :paramref:`_schema.ForeignKeyConstraint.use_alter` is particularly geared towards the case where two or more tables are established within a mutually-dependent foreign key constraint relationship; however, the :meth:`_schema.MetaData.create_all` and :meth:`_schema.MetaData.drop_all` methods will perform this resolution automatically, so the flag is normally not needed. .. versionchanged:: 1.0.0 Automatic resolution of foreign key cycles has been added, removing the need to use the :paramref:`_schema.ForeignKeyConstraint.use_alter` in typical use cases. .. seealso:: :ref:`use_alter` :param match: Optional string. If set, emit MATCH when issuing DDL for this constraint. Typical values include SIMPLE, PARTIAL and FULL. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**dialect_kw: Additional keyword arguments are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 )r rrrHzOForeignKeyConstraint with duplicate source column references are not supported.z_ForeignKeyConstraint number of constrained columns must match the number of referenced columns.cg|]F}t|fjjjjjjjjd j GS)) rqr r/rrr\rrr) rrr r/rrr\rrrdialect_kwargs)rrefcolr=s r"rz1ForeignKeyConstraint.__init__.. s{      Y.!.j?.  %     r$Nr)r6rr/rr\rrrrrr<elementsrDr7rr9)r=r refcolumnsr r/rrrrr\rr*rHrs` r"rzForeignKeyConstraint.__init__ sln   !       !   (" s7||  J / /3w<<  CLL00'4'*    %    " &t6g6666  tX&& , ++++  * *5 1 1 1 1 1  r$cn|j||j|dSr')rrrrrHs r"rz$ForeignKeyConstraint._append_element s4     R     r$cZtjt|j|jSr')r OrderedDictzip column_keysrrLs r" _elementszForeignKeyConstraint._elements s$D$4dm D DEEEr$c*|jD] }|jcSdSr')rr)r=elems r"rz%ForeignKeyConstraint._referred_schema s'M  D( ( ( (4r$c0|jdjjS)alThe :class:`_schema.Table` object to which this :class:`_schema.ForeignKeyConstraint` references. This is a dynamically calculated attribute which may not be available if the constraint and/or parent table is not yet associated with a metadata collection that contains the referred table. .. versionadded:: 1.0.0 r)rrr*rLs r"referred_tablez#ForeignKeyConstraint.referred_table s}Q&,,r$c td|jD}d|vrWt|dkrFt|dd\}}t jd|jd|jd|d|dSdS) Nc6g|]}|Sr)r)rrs r"rz=ForeignKeyConstraint._validate_dest_table.. s"FFF$//++FFFr$rrrzForeignKeyConstraint on (z$) refers to multiple remote tables:  and )rrrrrr<r_col_description)r=r* table_keyselem0elem1s r"rz)ForeignKeyConstraint._validate_dest_table sFF FFFGG z ! !c*oo&9&9!*--ac2LE5##>>>4#8#8#8%%%H  " !&9&9r$cvt|dr|jSd|jDS)aReturn a list of string keys representing the local columns in this :class:`_schema.ForeignKeyConstraint`. This list is either the original string arguments sent to the constructor of the :class:`_schema.ForeignKeyConstraint`, or if the constraint has been initialized with :class:`_schema.Column` objects, is the string ``.key`` of each element. .. versionadded:: 1.0.0 rcdg|]-}t|tr|jnt|.Sr)r(rr+str)rr-s r"rz4ForeignKeyConstraint.column_keys.. sC&c=99Gs3xxr$)r7rkeysrHrLs r"rz ForeignKeyConstraint.column_keys sN 4 " " <$$&& &0 r$c6d|jS)Nr)rrrLs r"rz%ForeignKeyConstraint._col_description syy)***r$c t|| t||nV#t$rI}t jt jd|jd|j dd|Yd}~nd}~wwxYwt|j |j D]3\}}t|dr |j|ur||4||dS)Nz,Can't create ForeignKeyConstraint on table 'z': no column named 'rz ' is present.rtr)r6rrlKeyErrorrr;rr<rr>rrrr7rr9r)r=r*ker-rIs r"rz ForeignKeyConstraint._set_parent s/tU+++  & 2 24 ? ? ? ?    K!!160A0A0A271:::O            4<77 2 2GC2x(( 2BIS,@,@,,S111 !!%(((((s9 B ?BB c ^td|jDfd|jD|j|j|j|j|j|j|j|j  }t|j|jD]\}}| || |S)Nc&g|]}|jjSr)rr+rs r"rz-ForeignKeyConstraint.copy.. s 1 1 1aQX\ 1 1 1r$cg|]I}|.||jjjkrjndJS)N)r!r)rrrr*r+r )rrr!r/s r"rz-ForeignKeyConstraint.copy.. sq   !#/ !(.*<<< ,00    r$)r r/rrrrr\r) rrr r/rrrrr\rrrW)r=r!r/r~rself_fkother_fks `` r"rTzForeignKeyConstraint.copys" 1 14= 1 1 1        ]]nn**'   *"%T]CL!A!A 0 0 GX  % %h / / / /%%c***r$) NNNNNFFNNNr)r]r^r_r`rarrrrrbrrrrrrrrTrr$r"rr sA  .N  O2O2O2O2b!!!G HFFXFX  - -X -X(++X+)))*++++++r$rcreZdZdZdZfdZfdZdZdZe dZ e j dZ xZS) ra A table-level PRIMARY KEY constraint. The :class:`.PrimaryKeyConstraint` object is present automatically on any :class:`_schema.Table` object; it is assigned a set of :class:`_schema.Column` objects corresponding to those marked with the :paramref:`_schema.Column.primary_key` flag:: >>> my_table = Table('mytable', metadata, ... Column('id', Integer, primary_key=True), ... Column('version_id', Integer, primary_key=True), ... Column('data', String(50)) ... ) >>> my_table.primary_key PrimaryKeyConstraint( Column('id', Integer(), table=, primary_key=True, nullable=False), Column('version_id', Integer(), table=, primary_key=True, nullable=False) ) The primary key of a :class:`_schema.Table` can also be specified by using a :class:`.PrimaryKeyConstraint` object explicitly; in this mode of usage, the "name" of the constraint can also be specified, as well as other options which may be recognized by dialects:: my_table = Table('mytable', metadata, Column('id', Integer), Column('version_id', Integer), Column('data', String(50)), PrimaryKeyConstraint('id', 'version_id', name='mytable_pk') ) The two styles of column-specification should generally not be mixed. An warning is emitted if the columns present in the :class:`.PrimaryKeyConstraint` don't match the columns that were marked as ``primary_key=True``, if both are present; in this case, the columns are taken strictly from the :class:`.PrimaryKeyConstraint` declaration, and those columns otherwise marked as ``primary_key=True`` are ignored. This behavior is intended to be backwards compatible with previous behavior. .. versionchanged:: 0.9.2 Using a mixture of columns within a :class:`.PrimaryKeyConstraint` in addition to columns marked as ``primary_key=True`` now emits a warning if the lists don't match. The ultimate behavior of ignoring those columns marked with the flag only is currently maintained for backwards compatibility; this warning may raise an exception in a future release. For the use case where specific options are to be specified on the :class:`.PrimaryKeyConstraint`, but the usual style of using ``primary_key=True`` flags is still desirable, an empty :class:`.PrimaryKeyConstraint` may be specified, which will take on the primary key column collection from the :class:`_schema.Table` based on the flags:: my_table = Table('mytable', metadata, Column('id', Integer, primary_key=True), Column('version_id', Integer, primary_key=True), Column('data', String(50)), PrimaryKeyConstraint(name='mytable_pk', mssql_clustered=True) ) .. versionadded:: 0.9.2 an empty :class:`.PrimaryKeyConstraint` may now be specified for the purposes of establishing keyword arguments with the constraint, independently of the specification of "primary key" columns within the :class:`_schema.Table` itself; columns marked as ``primary_key=True`` will be gathered into the empty constraint's column collection. primary_key_constraintc~|dd|_tt|j|i|dS)NrF)rrrrrr)r=rr~rs r"rzPrimaryKeyConstraint.__init__osC#%66*?#G#G 2"D))2GBrBBBBBr$c  tt|||j|ur@|j|j||_|j|d|jD}|jr|rt|t|j krtj d|j ddd|Dddd|jDddd |jDd g|dd<|jD]}d |_d |_|j|dS) Nc g|] }|j | Sr)rrs r"rz4PrimaryKeyConstraint._set_parent..{s99911=9Q999r$zTable 'z' specifies columns rc3*K|]}d|jzVdSr]rrs r"rz3PrimaryKeyConstraint._set_parent..s(AA!fqvoAAAAAAr$z= as primary_key=True, not matching locally specified columns c3*K|]}d|jzVdSr]rrs r"rz3PrimaryKeyConstraint._set_parent..(DD!fqvoDDDDDDr$z-; setting the current primary key columns to c3*K|]}d|jzVdSr]rrs r"rz3PrimaryKeyConstraint._set_parent..rr$z:. This warning may become an exception in a future releaseTF)rrrrrrUrr,rrvaluesrrr rr)extend)r=r* table_pksr,rs r"rz PrimaryKeyConstraint._set_parentss "D))55e<<<  D ( (   % %e&7 8 8 8 $E    ! !$ ' ' '99999 L  I#dl&9&9&;&;"<"<<< II JJJIIAAyAAAAAAAIIDDt|DDDDDDDIIDDt|DDDDDDD    IaaaL  A AMAJJ I&&&&&r$c|D] }d|_ |j|tj|||jdS)aKrepopulate this :class:`.PrimaryKeyConstraint` given a set of columns. Existing columns in the table that are marked as primary_key=True are maintained. Also fires a new event. This is basically like putting a whole new :class:`.PrimaryKeyConstraint` object on the parent :class:`_schema.Table` object without actually replacing the object. The ordering of the given list of columns is also maintained; these columns will be appended to the list of columns after any which are already present. TN)rrrrr_resetr9r*)r=rr-s r"_reloadzPrimaryKeyConstraint._reloadse* # #C"COO G$$$299$??? &&tz22222r$ctj||j||j||dSr')rrrrr0rU'_sa_event_column_added_to_pk_constraintrvs r"rVzPrimaryKeyConstraint._replacesM299$??? S!!! ==dCHHHHHr$cl|jgfd|jDzSt|jS)Ncg|]}|u| Srr)rr,autoincs r"rz>PrimaryKeyConstraint.columns_autoinc_first..s#LLLa1G;K;K;K;K;Kr$)rrr)r=rs @r"columns_autoinc_firstz*PrimaryKeyConstraint.columns_autoinc_firstsE,  9LLLL4<LLLL L %% %r$chd}t|jdkrLt|jd}|jdur||d|S|jdvr||dr|SdSdSd}|jD]@}|jdur5||d|%t jd|jd|jd |}A|S) NcL|jj)t|jjtjjs$|r t jd|jd|ddSt|jtdtfs|sdS|j |sdS|j r |j dvrdSdS)Nz Column type z on column 'z+' is not compatible with autoincrement=TrueF)T ignore_fkT) r9_type_affinity issubclassr INTEGERTYPErr<r(r*r;r+rr0)r- autoinc_trues r"_validate_autoinczEPrimaryKeyConstraint._autoincrement_column.._validate_autoincsx&.j')=)L77. !++@C###O !5s{T$ZZ,BCC $ u#/ /u! c&7@''u4r$rrT)r1rFz=Only one Column may be marked autoincrement=True, found both rr)rrrr0rr<r )r=rr-rs r"rz*PrimaryKeyConstraint._autoincrement_columns%   2 t|   ! !t|$$Q'C D((!!#t,,, ! &%c511  G| & &$,,%%c4000*!// #xxx7 #&Nr$)r]r^r_r`rarrrrVrbrrrdrr#r$s@r"rr#sGGR.NCCCCC'''''B333:III &&X& 8888888r$rceZdZdZdZdS)rWaA table-level UNIQUE constraint. Defines a single column or composite UNIQUE constraint. For a no-frills, single column constraint, adding ``unique=True`` to the ``Column`` definition is a shorthand equivalent for an unnamed, single column UniqueConstraint. unique_constraintN)r]r^r_r`rarr$r"rWrWs)NNNr$rWcNeZdZdZdZdZdZedZd dZ d dZ d Z dS) ra A table-level INDEX. Defines a composite (one or more column) INDEX. E.g.:: sometable = Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)) ) Index("some_index", sometable.c.name) For a no-frills, single column index, adding :class:`_schema.Column` also supports ``index=True``:: sometable = Table("sometable", metadata, Column("name", String(50), index=True) ) For a composite index, multiple columns can be specified:: Index("some_index", sometable.c.name, sometable.c.address) Functional indexes are supported as well, typically by using the :data:`.func` construct in conjunction with table-bound :class:`_schema.Column` objects:: Index("some_index", func.lower(sometable.c.name)) An :class:`.Index` can also be manually associated with a :class:`_schema.Table`, either through inline declaration or using :meth:`_schema.Table.append_constraint`. When this approach is used, the names of the indexed columns can be specified as strings:: Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)), Index("some_index", "name", "address") ) To support functional or expression-based indexes in this form, the :func:`_expression.text` construct may be used:: from sqlalchemy import text Table("sometable", metadata, Column("name", String(50)), Column("address", String(100)), Index("some_index", text("lower(name)")) ) .. versionadded:: 0.9.5 the :func:`_expression.text` construct may be used to specify :class:`.Index` expressions, provided the :class:`.Index` is explicitly associated with the :class:`_schema.Table`. .. seealso:: :ref:`schema_indexes` - General information on :class:`.Index`. :ref:`postgresql_indexes` - PostgreSQL-specific options available for the :class:`.Index` construct. :ref:`mysql_indexes` - MySQL-specific options available for the :class:`.Index` construct. :ref:`mssql_indexes` - MSSQL-specific options available for the :class:`.Index` construct. rcddx|_}g}g}||D]1\}}} } || ||2||_t ||dd|_|dd|_|dd} d|vr|d|_d|vr|d}| |tj |g|Rd| i|| |dSdS)aConstruct an index object. :param name: The name of the index :param \*expressions: Column expressions to include in the index. The expressions are normally instances of :class:`_schema.Column`, but may also be arbitrary SQL expressions which ultimately refer to a :class:`_schema.Column`. :param unique=False: Keyword only argument; if True, create a unique index. :param quote=None: Keyword only argument; whether to apply quoting to the name of the index. Works in the same manner as that of :paramref:`_schema.Column.quote`. :param info=None: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param \**kw: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. NrPrFrrHr) r*rOrrrrrr rrHrrDrr) r=r rr~r*rprocessed_expressionsrrrLrNrs r"rzIndex.__init__Vsj@"! U "  4 4[ A A  / /     NN; ' ' ' ! ( ( . . . .0bffWd&;&;<< ffXu-- vvne44 R<<vDI r>>FF8$$E %%b))) &     )5        U # # # # #  r$c t|||j;||jur2tjd|jd|jjd|jd||_|j||j }| |}t|t|ksJdt||D|_ dS)NzIndex 'z' is against table 'z(', and cannot be associated with table 'r^cFg|]\}}t|tr|n|Sr)r(r)rrcolexprs r"rz%Index._set_parent..s?   gt]33 @DD   r$) rDrr*rr<r rrrrrhrr)r=r*rcol_expressionss r"rzIndex._set_parents))$666 : !e4:&=&=##999dj444e6G6G6GI    $& //66;3#7#77777  !$[/!B!B   r$c|jjS)z2Return the connectable associated with this Index.)r*rrLs r"rz Index.bindszr$Nch|t|}|tj||S)zIssue a ``CREATE`` statement for this :class:`.Index`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.create_all`. rrs r"r z Index.creates4 <!$''D #-t444 r$ch|t|}|tj|dS)zIssue a ``DROP`` statement for this :class:`.Index`, using the given :class:`.Connectable` for connectivity. .. seealso:: :meth:`_schema.MetaData.drop_all`. Nr rs r"r z Index.drops5 <!$''D #+T22222r$cddt|jgd|jDz|jrdgpgzzS)Nz Index(%s)rc,g|]}t|Srr)res r"rz"Index.__repr__..s555q477555r$z unique=True)rrr rrrLs r"rMzIndex.__repr__s] IIdi!55D$45556;2M?8b:    r$r') r]r^r_r`rarrrbrr r rMrr$r"rrsIIVNB$B$B$H   (X     3 3 3 3     r$rixzix_%(column_0_label)scTeZdZdZdZejd ddZdZ dZ d Z d Z d Z d Z d ZdZdZejddZeeeZdZdZedZ ddZejdddZddZddZdS)MetaDataaDA collection of :class:`_schema.Table` objects and their associated schema constructs. Holds a collection of :class:`_schema.Table` objects as well as an optional binding to an :class:`_engine.Engine` or :class:`_engine.Connection`. If bound, the :class:`_schema.Table` objects in the collection and their columns may participate in implicit SQL execution. The :class:`_schema.Table` objects themselves are stored in the :attr:`_schema.MetaData.tables` dictionary. :class:`_schema.MetaData` is a thread-safe object for read operations. Construction of new tables within a single :class:`_schema.MetaData` object, either explicitly or via reflection, may not be completely thread-safe. .. seealso:: :ref:`metadata_describing` - Introduction to database metadata r)z0.8zThe :paramref:`_schema.MetaData.reflect` flag is deprecated and will be removed in a future release. Please use the :meth:`_schema.MetaData.reflect` method.)reflectNFcltj|_t|||_|r|nt |_|r||_t|_ i|_ tj t|_||_|r,|st!jd|dSdS)aCreate a new MetaData object. :param bind: An Engine or Connection to bind to. May also be a string or URL instance, these are passed to :func:`_sa.create_engine` and this :class:`_schema.MetaData` will be bound to the resulting engine. :param reflect: Optional, automatically load all tables from the bound database. Defaults to False. :paramref:`_schema.MetaData.bind` is required when this option is set. :param schema: The default schema to use for the :class:`_schema.Table`, :class:`.Sequence`, and potentially other objects associated with this :class:`_schema.MetaData`. Defaults to ``None``. When this value is set, any :class:`_schema.Table` or :class:`.Sequence` which specifies ``None`` for the schema parameter will instead have this schema name defined. To build a :class:`_schema.Table` or :class:`.Sequence` that still has ``None`` for the schema even when this parameter is present, use the :attr:`.BLANK_SCHEMA` symbol. .. note:: As referred above, the :paramref:`_schema.MetaData.schema` parameter only refers to the **default value** that will be applied to the :paramref:`_schema.Table.schema` parameter of an incoming :class:`_schema.Table` object. It does not refer to how the :class:`_schema.Table` is catalogued within the :class:`_schema.MetaData`, which remains consistent vs. a :class:`_schema.MetaData` collection that does not define this parameter. The :class:`_schema.Table` within the :class:`_schema.MetaData` will still be keyed based on its schema-qualified name, e.g. ``my_metadata.tables["some_schema.my_table"]``. The current behavior of the :class:`_schema.ForeignKey` object is to circumvent this restriction, where it can locate a table given the table name alone, where the schema will be assumed to be present from this value as specified on the owning :class:`_schema.MetaData` collection. However, this implies that a table qualified with BLANK_SCHEMA cannot currently be referred to by string name from :class:`_schema.ForeignKey`. Other parts of SQLAlchemy such as Declarative may not have similar behaviors built in, however may do so in a future release, along with a consistent method of referring to a table in BLANK_SCHEMA. .. seealso:: :paramref:`_schema.Table.schema` :paramref:`.Sequence.schema` :param quote_schema: Sets the ``quote_schema`` flag for those :class:`_schema.Table`, :class:`.Sequence`, and other objects which make usage of the local ``schema`` name. :param info: Optional data dictionary which will be populated into the :attr:`.SchemaItem.info` attribute of this object. .. versionadded:: 1.0.0 :param naming_convention: a dictionary referring to values which will establish default naming conventions for :class:`.Constraint` and :class:`.Index` objects, for those objects which are not given a name explicitly. The keys of this dictionary may be: * a constraint or Index class, e.g. the :class:`.UniqueConstraint`, :class:`_schema.ForeignKeyConstraint` class, the :class:`.Index` class * a string mnemonic for one of the known constraint classes; ``"fk"``, ``"pk"``, ``"ix"``, ``"ck"``, ``"uq"`` for foreign key, primary key, index, check, and unique constraint, respectively. * the string name of a user-defined "token" that can be used to define new naming tokens. The values associated with each "constraint class" or "constraint mnemonic" key are string naming templates, such as ``"uq_%(table_name)s_%(column_0_name)s"``, which describe how the name should be composed. The values associated with user-defined "token" keys should be callables of the form ``fn(constraint, table)``, which accepts the constraint/index object and :class:`_schema.Table` as arguments, returning a string result. The built-in names are as follows, some of which may only be available for certain types of constraint: * ``%(table_name)s`` - the name of the :class:`_schema.Table` object associated with the constraint. * ``%(referred_table_name)s`` - the name of the :class:`_schema.Table` object associated with the referencing target of a :class:`_schema.ForeignKeyConstraint`. * ``%(column_0_name)s`` - the name of the :class:`_schema.Column` at index position "0" within the constraint. * ``%(column_0N_name)s`` - the name of all :class:`_schema.Column` objects in order within the constraint, joined without a separator. * ``%(column_0_N_name)s`` - the name of all :class:`_schema.Column` objects in order within the constraint, joined with an underscore as a separator. * ``%(column_0_label)s``, ``%(column_0N_label)s``, ``%(column_0_N_label)s`` - the label of either the zeroth :class:`_schema.Column` or all :class:`.Columns`, separated with or without an underscore * ``%(column_0_key)s``, ``%(column_0N_key)s``, ``%(column_0_N_key)s`` - the key of either the zeroth :class:`_schema.Column` or all :class:`.Columns`, separated with or without an underscore * ``%(referred_column_0_name)s``, ``%(referred_column_0N_name)s`` ``%(referred_column_0_N_name)s``, ``%(referred_column_0_key)s``, ``%(referred_column_0N_key)s``, ... column tokens which render the names/keys/labels of columns that are referenced by a :class:`_schema.ForeignKeyConstraint`. * ``%(constraint_name)s`` - a special key that refers to the existing name given to the constraint. When this key is present, the :class:`.Constraint` object's existing name will be replaced with one that is composed from template string that uses this token. When this token is present, it is required that the :class:`.Constraint` is given an explicit name ahead of time. * user-defined: any additional token may be implemented by passing it along with a ``fn(constraint, table)`` callable to the naming_convention dictionary. .. versionadded:: 1.3.0 - added new ``%(column_0N_name)s``, ``%(column_0_N_name)s``, and related tokens that produce concatenations of names, keys, or labels for all columns referred to by a given constraint. .. seealso:: :ref:`constraint_naming_conventions` - for detailed usage examples. z8A bind must be supplied in conjunction with reflect=TrueN)r immutabledictrsrr!DEFAULT_NAMING_CONVENTIONnaming_conventionrHr_schemasr collections defaultdictrr[rrr<r)r=rrr!rrrHs r"rzMetaData.__init__sn(** !&,77 ! +  *   DI $066   '( LLNNNNN   r$cd|jzS)NzMetaData(bind=%r)rrLs r"rMzMetaData.__repr__s"TY..r$cVt|tjs|j}||jvSr')r(rr6r+rs)r= table_or_keys r"rpzMetaData.__contains__s,,(9:: ,'+Lt{**r$ct||}t|j|||r|j|dSdSr')r#dict __setitem__rsrr)r=r r!r*r+s r"rxzMetaData._add_tablesYT6** c5111  & M  f % % % % % & &r$c&t||}t|j|d}||jD]}|||jr7td|jD|_dSdS)Nc*g|]}|j |jSr'r)rts r"rz*MetaData._remove_table..s,x+H+++r$) r#rrrrsrrrrr)r=r r!r+removedrIs r"r|zMetaData._remove_tablesT6**((4;T22  * / /((.... = ![//11DMMM  r$cP|j|j|j|j|j|jdS)N)rsr!schemas sequencesfk_memosr)rsr!rrr[rrLs r" __getstate__zMetaData.__getstate__s0kk}!%!7    r$c|d|_|d|_|d|_d|_|d|_|d|_|d|_dS)Nrsr!rrrr)rsr!r_bindrrr[)r=states r" __setstate__zMetaData.__setstate__sUHo Ho !&':!;  ,i( z*r$c|jduS)z:True if this MetaData is bound to an Engine or Connection.NrrLs r"is_boundzMetaData.is_boundsz%%r$c|jS)a-An :class:`_engine.Engine` or :class:`_engine.Connection` to which this :class:`_schema.MetaData` is bound. Typically, a :class:`_engine.Engine` is assigned to this attribute so that "implicit execution" may be used, or alternatively as a means of providing engine binding information to an ORM :class:`.Session` object:: engine = create_engine("someurl://") metadata.bind = engine .. seealso:: :ref:`dbengine_implicit` - background on "bound metadata" rrLs r"rz MetaData.bind s $zr$sqlalchemy.engine.urlct|tj|jfzrt j||_dS||_dS)z;Bind this MetaData to an Engine, Connection, string or URL.N)r(rr6URL sqlalchemy create_enginer)r=urlrs r"_bind_tozMetaData._bind_to!sC dD- : ; ; #1$77DJJJDJJJr$ct|j|j|jdS)z+Clear all Table objects from this MetaData.N)rclearrsrr[rLs r"rzMetaData.clear,sF 4;  r$cF||j|jdS)z1Remove the given Table object from this MetaData.N)r|r r!rs r"rzMetaData.remove3s$ 5:u|44444r$cxtjt|jdS)aReturns a list of :class:`_schema.Table` objects sorted in order of foreign key dependency. The sorting will place :class:`_schema.Table` objects that have dependencies first, before the dependencies themselves, representing the order in which they can be created. To get the order in which the tables would be dropped, use the ``reversed()`` Python built-in. .. warning:: The :attr:`.MetaData.sorted_tables` attribute cannot by itself accommodate automatic resolution of dependency cycles between tables, which are usually caused by mutually dependent foreign key constraints. When these cycles are detected, the foreign keys of these tables are omitted from consideration in the sort. A warning is emitted when this condition occurs, which will be an exception raise in a future release. Tables which are not part of the cycle will still be returned in dependency order. To resolve these cycles, the :paramref:`_schema.ForeignKeyConstraint.use_alter` parameter may be applied to those constraints which create a cycle. Alternatively, the :func:`_schema.sort_tables_and_constraints` function will automatically return foreign key constraints in a separate collection when cycles are detected so that they may be applied to a schema separately. .. versionchanged:: 1.3.17 - a warning is emitted when :attr:`.MetaData.sorted_tables` cannot perform a proper sort due to cyclical dependencies. This will be an exception in a future release. Additionally, the sort will continue to return other tables not involved in the cycle in dependency order which was not the case previously. .. seealso:: :func:`_schema.sort_tables` :func:`_schema.sort_tables_and_constraints` :attr:`_schema.MetaData.tables` :meth:`_reflection.Inspector.get_table_names` :meth:`_reflection.Inspector.get_sorted_table_and_fkc_names` c|jSr'r)rs r"rz(MetaData.sorted_tables..lsqur$r)r sort_tablesrrsrrLs r" sorted_tableszMetaData.sorted_tables8s9f 4;%%''__ = = =   r$Tc (|t}|5} d| ||td} | |j| d<t j|j| |r.|j | !t jfdD} n} tj fdt| D} nt j r fdt| D} n]fd D} | r>rd zpd }tjd |j|d d| dfdD} | D]G} t#|fi| #tj$r$}t jd|d|Yd}~@d}~wwxYw ddddS#1swxYwYdS)a Load all available table definitions from the database. Automatically creates ``Table`` entries in this ``MetaData`` for any table available in the database but not yet present in the ``MetaData``. May be called multiple times to pick up tables recently added to the database, however no special action is taken if a table in this ``MetaData`` no longer exists in the database. :param bind: A :class:`.Connectable` used to access the database; if None, uses the existing bind on this ``MetaData``, if any. :param schema: Optional, query and reflect tables from an alternate schema. If None, the schema associated with this :class:`_schema.MetaData` is used, if any. :param views: If True, also reflect views. :param only: Optional. Load only a sub-set of available named tables. May be specified as a sequence of names or a callable. If a sequence of names is provided, only those tables will be reflected. An error is raised if a table is requested but not available. Named tables already present in this ``MetaData`` are ignored. If a callable is provided, it will be used as a boolean predicate to filter the list of potential table names. The callable is called with a table name and this ``MetaData`` instance as positional arguments and should return a true value for any table to reflect. :param extend_existing: Passed along to each :class:`_schema.Table` as :paramref:`_schema.Table.extend_existing`. .. versionadded:: 0.9.1 :param autoload_replace: Passed along to each :class:`_schema.Table` as :paramref:`_schema.Table.autoload_replace`. .. versionadded:: 0.9.1 :param resolve_fks: if True, reflect :class:`_schema.Table` objects linked to :class:`_schema.ForeignKey` objects located in each :class:`_schema.Table`. For :meth:`_schema.MetaData.reflect`, this has the effect of reflecting related tables that might otherwise not be in the list of tables being reflected, for example if the referenced table is in a different schema or is omitted via the :paramref:`.MetaData.reflect.only` parameter. When False, :class:`_schema.ForeignKey` objects are not followed to the :class:`_schema.Table` in which they link, however if the related table is also part of the list of tables that would be reflected in any case, the :class:`_schema.ForeignKey` object will still resolve to its related :class:`_schema.Table` after the :meth:`_schema.MetaData.reflect` operation is complete. Defaults to True. .. versionadded:: 1.3.0 .. seealso:: :paramref:`_schema.Table.resolve_fks` :param \**dialect_kwargs: Additional keyword arguments not mentioned above are dialect specific, and passed in the form ``_``. See the documentation regarding an individual dialect at :ref:`dialect_toplevel` for detail on documented arguments. .. versionadded:: 0.9.2 - Added :paramref:`.MetaData.reflect.**dialect_kwargs` to support dialect-level reflection options for all :class:`_schema.Table` objects reflected. NT)rrrkrrrr!)rcg|] }d| S)rr)rr r!s r"rz$MetaData.reflect..s$DDD$-DDDr$c&g|] \}}s|v |Srr)rr schnamecurrentrks r"rz$MetaData.reflect..s<%g&+2*@*@*@*@*@r$c>g|]\}}s|v ||Srr)rr rrrkonlyr=s r"rz$MetaData.reflect..sQ%g',3'+A+AT4((,B+A+A+Ar$cg|]}|v| Srr)rr availables r"rz$MetaData.reflect..s#JJJDD 4I4I44I4I4Ir$z schema '%s'rz7Could not reflect: requested table(s) not available in z: (rrc g|] }s|v| Srr)rr rrks r"rz$MetaData.reflect..s8&+/g*=*=*=*=*=r$zSkipping table z: )rconnectrr'r!r OrderedSetengine table_namesrget_view_namesrsrrrrurrfUnreflectableTableErrorr)r=rr!viewsrrkrrrconn reflect_optsavailable_w_schemaloadmissingsr uerrrrs` ` `` @@r"rzMetaData.reflectossz <!$''D \\^^A Ft!!%#2$4*!ee L    / / /~!)/ X& ''4'@@I L  !.adapt_listeners+\F HUFJv > > > > > >r$rrrNrrs ` r"rzMetaData.append_ddl_listenersM ? ? ? ? ?  T2 2 23 < <))'+t$#'DL s>4A65A6cHt|jdo |jjduS)z(True if there is a bind for this thread.r4N)r7r1r4rLs r"rzThreadLocalMetaData.is_bounds* DL) , , 1 $D0 r$c|jD]&}t|dr|'dS)z2Dispose all bound engines, in all thread contexts.disposeN)r2rr7r8)r=rs r"r8zThreadLocalMetaData.disposesK&&((  Aq)$$    r$)r]r^r_r`rarrrrrrbrr8r#r$s@r"r-r-Ws   N44444666T.//((0/(" 8D( # #D   r$r-cReZdZdZdZejdZdZe dZ dS)_SchemaTranslateMapaProvide translation of schema names based on a mapping. Also provides helpers for producing cache keys and optimized access when no mapping is present. Used by the :paramref:`.Connection.execution_options.schema_translate_map` feature. .. versionadded:: 1.1 )r[__call__hash_key is_defaultr!c_Pfd}|_dfdttD_d_dSd_j_d_dS)Nc^|}||}|Sr')_default_schema_getterr\)objrZr[r=s r"schema_for_objectz7_SchemaTranslateMap.__init__..schema_for_objects:#'#>#>s#C#C ##8$d$$ ('r$;c32K|]}|d|VdS)rNr)rrr[s r"rz/_SchemaTranslateMap.__init__..sC%%+,111d1gg&%%%%%%r$rFrT)r[r;rrrr<r=r@)r=r[rBs`` r"rz_SchemaTranslateMap.__init__s   ( ( ( ( ( (.DMHH%%%%06t0E0E0E%%%DM$DOOODM 7DM"DOOOr$c`|tSt|tr|St|Sr')_default_schema_mapr(r:)r}r[s r"_schema_getterz"_SchemaTranslateMap._schema_getters3 <& & 1 2 2 -K&t,, ,r$N) r]r^r_r` __slots__operator attrgetterr@rrjrGrr$r"r:r:sb  =I0X0::###*--[---r$r:cXeZdZdZdZedddd dZdZd Zd d Z dS) riaDefines a generated column, i.e. "GENERATED ALWAYS AS" syntax. The :class:`.Computed` construct is an inline construct added to the argument list of a :class:`_schema.Column` object:: from sqlalchemy import Computed Table('square', meta, Column('side', Float, nullable=False), Column('area', Float, Computed('side * side')) ) See the linked documentation below for complete details. .. versionadded:: 1.3.11 .. seealso:: :ref:`computed_ddl` computed_columnrz:class:`.Computed`z:paramref:`.Computed.sqltext`NcNt|d|_||_d|_dS)a Construct a GENERATED ALWAYS AS DDL construct to accompany a :class:`_schema.Column`. :param sqltext: A string containing the column generation expression, which will be used verbatim, or a SQL expression construct, such as a :func:`_expression.text` object. If given as a string, the object is converted to a :func:`_expression.text` object. :param persisted: Optional, controls how this column should be persisted by the database. Possible values are: * ``None``, the default, it will use the default persistence defined by the database. * ``True``, will render ``GENERATED ALWAYS AS ... STORED``, or the equivalent for the target database if supported. * ``False``, will render ``GENERATED ALWAYS AS ... VIRTUAL``, or the equivalent for the target database if supported. Specifying ``True`` or ``False`` may raise an error when the DDL is emitted to the target database if the database does not support that persistence option. Leaving this parameter at its default of ``None`` is guaranteed to succeed for all databases that support ``GENERATED ALWAYS AS``. TrN)rr persistedr)r=rrNs r"rzComputed.__init__s+@(MMM " r$ct|jtdtfr)t|jtdtfst jd||_||_||j_||j_dS)NzPA generated column cannot specify a server_default or a server_onupdate argument) r(r+r9rir,rr<rr8r;s r"rzComputed._set_parent s  !DJJ#9   F2T$ZZ4JKK #+  &* #%) """r$c|Sr'rrs r"r>zComputed._as_for_updates r$c t|j|j |jjnd|}t ||j}||S)N)rN)r3rrr*rirNrW)r=r/r~rgs r"rTz Computed.copysW" L!%!8DK  d    W 7 7 7%%a(((r$r') r]r^r_r`rar rrr>rTrr$r"riris,'N')HB * * *))))))r$ri)Er` __future__rrrIrrrrrbaserr r r rr r rrrrrrrwrrrrrsymbolrrqr#r3_self_inspects Visitabler5rfr)rrrmrrr:rr;r=r?deprecated_clsr3r6r@rBrDrlrrrrWrrrrr-r:rFrGrirr$r"rYs_.'&&&&& """"""############------&&&&&&######""""""######!!!!!! ###### O,, t{   ###BBB" B<B<B<B<B<"H$6B<B<B , and apply any adaptations to the given operator. This method determines the type of a resulting binary expression given two source types and an operator. For example, two :class:`_schema.Column` objects, both of the type :class:`.Integer`, will produce a :class:`.BinaryExpression` that also has the type :class:`.Integer` when compared via the addition (``+``) operator. However, using the addition operator with an :class:`.Integer` and a :class:`.Date` object will produce a :class:`.Date`, assuming "days delta" behavior by the database (in reality, most databases other than PostgreSQL don't accept this particular operation). The method returns a tuple of the form , . The resulting operator and type will be those applied to the resulting :class:`.BinaryExpression` as the final operator and the right-hand side of the expression. Note that only a subset of operators make usage of :meth:`._adapt_expression`, including math operators and user-defined operators, but not boolean comparison or special SQL keywords like MATCH or BETWEEN. )r)rrother_comparators r_adapt_expressionz'TypeEngine.Comparator._adapt_expressionKs6ty= rc t|jffSr)_reconstitute_comparatorrrs r __reduce__z TypeEngine.Comparator.__reduce__hs+di\9 9r) r __module__ __qualname____doc__ __slots__rrr dependenciesr"r%r(r,rr Comparatorr 2s  # ! " " "  > ? ? C C @ ? C  > ? ? N N @ ? N ! ! !: : : : : :rr3Nc<|}d|_|S)aReturn a copy of this type which has the :attr:`.should_evaluate_none` flag set to True. E.g.:: Table( 'some_table', metadata, Column( String(50).evaluates_none(), nullable=True, server_default='no value') ) The ORM uses this flag to indicate that a positive value of ``None`` is passed to the column in an INSERT statement, rather than omitting the column from the INSERT statement which has the effect of firing off column-level defaults. It also allows for types which have special behavior associated with the Python None value to indicate that the value doesn't necessarily translate into SQL NULL; a prime example of this is a JSON type which may wish to persist the JSON value ``'null'``. In all cases, the actual NULL SQL value can be always be persisted in any column by using the :obj:`_expression.null` SQL construct in an INSERT statement or associated with an ORM-mapped attribute. .. note:: The "evaluates none" flag does **not** apply to a value of ``None`` passed to :paramref:`_schema.Column.default` or :paramref:`_schema.Column.server_default`; in these cases, ``None`` still means "no default". .. versionadded:: 1.1 .. seealso:: :ref:`session_forcing_null` - in the ORM documentation :paramref:`.postgresql.JSON.none_as_null` - PostgreSQL JSON interaction with this flag. :attr:`.TypeEngine.should_evaluate_none` - class-level flag T)copyshould_evaluate_none)rtyps revaluates_nonezTypeEngine.evaluates_nones`iikk#'  rc 6||jSr)adapt __class__)rkws rr5zTypeEngine.copyszz$.)))rcdS)aCompare this type against the given backend type. This function is currently not implemented for SQLAlchemy types, and for all built in types will return ``None``. However, it can be implemented by a user-defined type where it can be consumed by schema comparison tools such as Alembic autogenerate. A future release of SQLAlchemy will potentially implement this method for builtin types as well. The function should return True if this type is equivalent to the given type; the type is typically reflected from the database so should be database specific. The dialect in use is also passed. It can also return False to assert that the type is not equivalent. :param dialect: a :class:`.Dialect` that is involved in the comparison. :param conn_type: the type object reflected from the backend. .. versionadded:: 1.0.3 Nr2)rdialect conn_types rcompare_against_backendz"TypeEngine.compare_against_backends 2trc|Srr2)rvalues r copy_valuezTypeEngine.copy_values rcdS)azReturn a conversion function for processing literal values that are to be rendered directly without using binds. This function is used when the compiler makes use of the "literal_binds" flag, typically used in DDL generation as well as in certain scenarios where backends don't accept bound parameters. .. versionadded:: 0.9.0 Nr2rr>s rliteral_processorzTypeEngine.literal_processors trcdS)aeReturn a conversion function for processing bind values. Returns a callable which will receive a bind parameter value as the sole positional argument and will return a value to send to the DB-API. If processing is not necessary, the method should return ``None``. :param dialect: Dialect instance in use. Nr2rEs rbind_processorzTypeEngine.bind_processor s trcdS)aReturn a conversion function for processing result row values. Returns a callable which will receive a result row column value as the sole positional argument and will return a value to return to the user. If processing is not necessary, the method should return ``None``. :param dialect: Dialect instance in use. :param coltype: DBAPI coltype argument received in cursor.description. Nr2)rr>coltypes rresult_processorzTypeEngine.result_processors trcdS)aGiven a SELECT column expression, return a wrapping SQL expression. This is typically a SQL function that wraps a column expression as rendered in the columns clause of a SELECT statement. It is used for special data types that require columns to be wrapped in some special database function in order to coerce the value before being sent back to the application. It is the SQL analogue of the :meth:`.TypeEngine.result_processor` method. The method is evaluated at statement compile time, as opposed to statement construction time. .. seealso:: :ref:`types_sql_value_processing` Nr2)rcolexprs rcolumn_expressionzTypeEngine.column_expression+s (trcF|jjjtjjuSzmemoized boolean, check if column_expression is implemented. Allows the method to be skipped for the vast majority of expression types that don't use this feature. )r;rN__code__r r+s r_has_column_expressionz!TypeEngine._has_column_expressionAs" N , 5/8 9 rcdS)aGiven a bind value (i.e. a :class:`.BindParameter` instance), return a SQL expression in its place. This is typically a SQL function that wraps the existing bound parameter within the statement. It is used for special data types that require literals being wrapped in some special database function in order to coerce an application-level value into a database-specific format. It is the SQL analogue of the :meth:`.TypeEngine.bind_processor` method. The method is evaluated at statement compile time, as opposed to statement construction time. Note that this method, when implemented, should always return the exact same structure, without any conditional logic, as it may be used in an executemany() call against an arbitrary number of bound parameter sets. .. seealso:: :ref:`types_sql_value_processing` Nr2)r bindvalues rbind_expressionzTypeEngine.bind_expressionOs 0trcF|jjjtjjuS)zmemoized boolean, check if bind_expression is implemented. Allows the method to be skipped for the vast majority of expression types that don't use this feature. )r;rUrQr r+s r_has_bind_expressionzTypeEngine._has_bind_expressionis" N * 3-6 7 rc t|Sr) to_instance) cls_or_selfs r _to_instancezTypeEngine._to_instancews;'''rc||kS)z Compare two values for equality.r2rxys rcompare_valueszTypeEngine.compare_values{s Av rcdS)zReturn the corresponding type object from the underlying DB-API, if any. This can be useful for calling ``setinputsizes()``, for example. Nr2rdbapis rget_dbapi_typezTypeEngine.get_dbapi_types trct)aReturn the Python type object expected to be returned by instances of this type, if known. Basically, for those types which enforce a return type, or are known across the board to do such for all common DBAPIs (like ``int`` for example), will return that type. If a return type is not defined, raises ``NotImplementedError``. Note that any type also accommodates NULL in SQL which means you can also get back ``None`` from any type in practice. NotImplementedErrorr+s r python_typezTypeEngine.python_types""###rc@t||t|iS)aProduce a new type object that will utilize the given type when applied to the dialect of the given name. e.g.:: from sqlalchemy.types import String from sqlalchemy.dialects import mysql s = String() s = s.with_variant(mysql.VARCHAR(collation='foo'), 'mysql') The construction of :meth:`.TypeEngine.with_variant` is always from the "fallback" type to that which is dialect specific. The returned type is an instance of :class:`.Variant`, which itself provides a :meth:`.Variant.with_variant` that can be called repeatedly. :param type\_: a :class:`.TypeEngine` that will be selected as a variant from the originating type, when a dialect of the given name is in use. :param dialect_name: base name of the dialect which uses this type. (i.e. ``'postgresql'``, ``'mysql'``, etc.) )VariantrY)rtype_ dialect_names r with_variantzTypeEngine.with_variants!4tlK,>,>?@@@rcd}|jjD]4}|ttfvr|cSt |ttfr|}5|jS)zRReturn a rudimental 'affinity' value expressing the general class of type.N)r;__mro__r UserDefinedType issubclass)rr7ts r_type_affinityzTypeEngine._type_affinitys[ ' " "AZ111 A O<== > !rc |j|dS#t$r||dcYSwxYw)zYReturn a dialect-specific implementation for this :class:`.TypeEngine`. impl _type_memosKeyError _dialect_inforEs r dialect_implzTypeEngine.dialect_implsT  7&t,V4 4 7 7 7%%g..v6 6 6 6 7s %==c,||SaReturn the 'unwrapped' dialect impl for this type. For a type that applies wrapping logic (e.g. TypeDecorator), give us the real, actual dialect-level type that is used. This is used by TypeDecorator itself as well at least one case where dialects need to check that a particular specific dialect-level type is in use, within the :meth:`.DefaultDialect.set_input_sizes` method. )rzrEs r_unwrapped_dialect_implz"TypeEngine._unwrapped_dialect_impls  )))rc |j|dS#t$rYnwxYw||}|d|x|d<}|S)z:Return a dialect-specific literal processor for this type.literalru)rwrxryrF)rr>dlps r_cached_literal_processorz$TypeEngine._cached_literal_processorst &t,Y7 7    D    w ' 'fI77@@@) r  ""c |j|dS#t$rYnwxYw||}|d|x|d<}|S)z7Return a dialect-specific bind processor for this type.bindru)rwrxryrH)rr>rbps r_cached_bind_processorz!TypeEngine._cached_bind_processorst &t,V4 4    D    w ' '611':::& B rc |j||S#t$rYnwxYw||}|d||x||<}|S)z9Return a dialect-specific result processor for this type.ru)rwrxryrK)rr>rJrrps r_cached_result_processorz#TypeEngine._cached_result_processorsx &t,W5 5    D    w ' 'F)44WgFFF' R rc |j||S#t$rYnwxYw||}|d}||x||<}|S)Nrurv)rr>keyfnrruresults r_cached_custom_processorz#TypeEngine._cached_custom_processorss &t,S1 1    D    w ' 'y"T(("# rc||jvr |j|S||}||ur"|t|}||usJd|ix|j|<}|S)zReturn a dialect-specific registry which caches a dialect-specific implementation, bind processing function, and one or more result processing functions.ru)rw_gen_dialect_implr:r)rr>rurs rryzTypeEngine._dialect_infos 7& & &&t, ,))'22Dt||zz$t**--t####-3TN :G  %Hrc,||Sr)type_descriptorrEs rrzTypeEngine._gen_dialect_impl#s&&t,,,rc (tj||fi|S)zProduce an "adapted" form of this type, given an "impl" class to work with. This method is used internally to associate generic types with "implementation" types that are specific to a particular dialect. )r constructor_copy)rclsr<s rr:zTypeEngine.adapt&s$T355"555rcVt|}|tus|j|jur|S|S)aoSuggest a type for a 'coerced' Python value in an expression. Given an operator and value, gives the type a chance to return a type which the value should be coerced into. The default behavior here is conservative; if the right-hand side is already coerced into a SQL type based on its Python type, it is usually left alone. End-user functionality extension here should generally be via :class:`.TypeDecorator`, which provides more liberal behavior in that it defaults to coercing the other side of the expression into this type, thus applying special Python conversions above and beyond those needed by the DBAPI to both ides. It also provides the public method :meth:`.TypeDecorator.coerce_compared_value` which is intended for end-user customization of this behavior. )_resolve_value_to_typeNULLTYPErs)rrrB _coerced_types rcoerce_compared_valuez TypeEngine.coerce_compared_value0s8&/u55 X % %+t/BBBK rc|j|juSr)rs)rrs r_compare_type_affinityz!TypeEngine._compare_type_affinityLs"e&:::rcb|s|}|j|S)zProduce a string-compiled form of this :class:`.TypeEngine`. When called with no arguments, uses a "default" dialect to produce a string result. :param dialect: a :class:`.Dialect` instance. )_default_dialect type_compilerprocessrEs rcompilezTypeEngine.compileOs4 .++--G$,,T222rzsqlalchemy.engine.defaultcT|jjdrv|jjddd}d|}t t |j|dS| S)Nzsqlalchemy.dialects.r) r;r- startswithsplitjoingetattr __import__dialectsr>DefaultDialect)rdefaulttokensmods rrzTypeEngine._default_dialect`s > $ / /0E F F ,^.44S99!A#>F((6""C:c??3VBZ@@HHJJ J))++ +rctjr5t|ddSt |S)Nasciibackslashreplace)r py2kunicoderencodestrr+s r__str__zTypeEngine.__str__isR 9 '4<<>>**11+ t||~~&& &rc*tj|Sr)r generic_reprr+s r__repr__zTypeEngine.__repr__qs &&&rr)3rr-r.r/ _sqla_type_isnull _is_arrayrColumnOperatorsr3hashablecomparator_factorysort_key_functionr6r8r5r@rCrFrHrKrNr memoized_propertyrRrUrW staticmethodr[r`rdpropertyrhrmrsrzr}rrrrryrr:rrrr1rrrr2rrr r s  JGI7:7:7:7:7:Y.7:7:7:rH $.!,222h***6       ,      4      ((\( $$X$$AAA8  " " "777 * * *          ---666!!!8;;;3333"T233,,43,''''''''rr ceZdZdS)VisitableCheckKWArgN)rr-r.r2rrrrusDrrcJeZdZdZdZdZGddejZeZdZ dS)rpaBase for user defined types. This should be the base of new types. Note that for most cases, :class:`.TypeDecorator` is probably more appropriate:: import sqlalchemy.types as types class MyType(types.UserDefinedType): def __init__(self, precision = 8): self.precision = precision def get_col_spec(self, **kw): return "MYTYPE(%s)" % self.precision def bind_processor(self, dialect): def process(value): return value return process def result_processor(self, dialect, coltype): def process(value): return value return process Once the type is made, it's immediately usable:: table = Table('foo', meta, Column('id', Integer, primary_key=True), Column('data', MyType(16)) ) The ``get_col_spec()`` method will in most cases receive a keyword argument ``type_expression`` which refers to the owning expression of the type as being compiled, such as a :class:`_schema.Column` or :func:`.cast` construct. This keyword is only sent if the method accepts keyword arguments (e.g. ``**kw``) in its argument signature; introspection is used to check for this in order to support legacy forms of this function. .. versionadded:: 1.0.0 the owning expression is passed to the ``get_col_spec()`` method via the keyword argument ``type_expression``, if it receives ``**kw`` in its signature. user_defined get_col_specc"eZdZdZfdZxZS)UserDefinedType.Comparatorr2ct|jdr5tjd|j||jfSt t j|||S)Nadapt_operatorzUserDefinedType.adapt_operator is deprecated. Create a UserDefinedType.Comparator subclass instead which generates the desired expression constructs, given a particular operator.) hasattrrr warn_deprecatedrsuperrpr3r()rrr'r;s rr(z,UserDefinedType.Comparator._adapt_expressions|ty"233 :$+ y//33TY>>#.##B(899:r)rr-r.r0r( __classcell__r;s@rr3rs=  : : : : : : : : :rr3c|S)aSuggest a type for a 'coerced' Python value in an expression. Default behavior for :class:`.UserDefinedType` is the same as that of :class:`.TypeDecorator`; by default it returns ``self``, assuming the compared value should be coerced into the same type as this one. See :meth:`.TypeDecorator.coerce_compared_value` for more detail. r2rrrBs rrz%UserDefinedType.coerce_compared_values  rN) rr-r.r/__visit_name__ ensure_kwargr r3rrr2rrrprpyso,,\$N!L:::::Z*:::"$     rrpc,eZdZdZfdZfdZxZS)EmulatedaMixin for base types that emulate the behavior of a DB-native type. An :class:`.Emulated` type will use an available database type in conjunction with Python-side routines and/or database constraints in order to approximate the behavior of a database type that is provided natively by some backends. When a native-providing backend is in use, the native version of the type is used. This native version should include the :class:`.NativeForEmulated` mixin to allow it to be distinguished from :class:`.Emulated`. Current examples of :class:`.Emulated` are: :class:`.Interval`, :class:`.Enum`, :class:`.Boolean`. .. versionadded:: 1.2.0b3 c Ftt|j|fi|S)aGiven an impl class, adapt this type to the impl assuming "emulated". The impl should also be an "emulated" version of this type, most likely the same class as this type itself. e.g.: sqltypes.Enum adapts to the Enum class. )rrr:rimpltyper<r;s radapt_to_emulatedzEmulated.adapt_to_emulateds*+uXt$$*8::r:::rc t|dr|jr|j|fi|S|j}t ||jr|j|fi|St t|j|fi|S)Nadapt_emulated_to_native) rnativerr;rqrrrr:rs rr:zEmulated.adapts 87 8 8 *{ *9x8DDDDD > h / / ?)4)(99b99 9.54((.x>>2>> >r)rr-r.r/rr:rrs@rrrs[" ; ; ; ; ;?????????rrc(eZdZdZedZdS)NativeForEmulatedzgIndicates DB-native types supported by an :class:`.Emulated` type. .. versionadded:: 1.2.0b3 c |di|S)zGiven an impl, adapt this type's class to the impl assuming "native". The impl will be an :class:`.Emulated` class but not a :class:`.NativeForEmulated`. e.g.: postgresql.ENUM produces a type given an Enum instance. r2r2)rrur<s rrz*NativeForEmulated.adapt_emulated_to_nativessyyRyyrN)rr-r.r/ classmethodrr2rrrrs9   [   rrceZdZdZdZdZejfZ Gdde j Z e dZ dZ e dZd#fd Zfd Zd Zd ZdZdZdZdZdZejdZejdZdZdZejdZdZejdZdZ ejdZ!dZ"dZ#dZ$dZ%d Z&e d!Z'd"Z(xZ)S)$ TypeDecoratoraAllows the creation of types which add additional functionality to an existing type. This method is preferred to direct subclassing of SQLAlchemy's built-in types as it ensures that all required functionality of the underlying type is kept in place. Typical usage:: import sqlalchemy.types as types class MyType(types.TypeDecorator): '''Prefixes Unicode values with "PREFIX:" on the way in and strips it off on the way out. ''' impl = types.Unicode def process_bind_param(self, value, dialect): return "PREFIX:" + value def process_result_value(self, value, dialect): return value[7:] def copy(self, **kw): return MyType(self.impl.length) The class-level ``impl`` attribute is required, and can reference any :class:`.TypeEngine` class. Alternatively, the :meth:`load_dialect_impl` method can be used to provide different type classes based on the dialect given; in this case, the ``impl`` variable can reference ``TypeEngine`` as a placeholder. Types that receive a Python type that isn't similar to the ultimate type used may want to define the :meth:`TypeDecorator.coerce_compared_value` method. This is used to give the expression system a hint when coercing Python objects into bind parameters within expressions. Consider this expression:: mytable.c.somecol + datetime.date(2009, 5, 15) Above, if "somecol" is an ``Integer`` variant, it makes sense that we're doing date arithmetic, where above is usually interpreted by databases as adding a number of days to the given date. The expression system does the right thing by not attempting to coerce the "date()" value into an integer-oriented bind parameter. However, in the case of ``TypeDecorator``, we are usually changing an incoming Python type to something new - ``TypeDecorator`` by default will "coerce" the non-typed side to be the same type as itself. Such as below, we define an "epoch" type that stores a date value as an integer:: class MyEpochType(types.TypeDecorator): impl = types.Integer epoch = datetime.date(1970, 1, 1) def process_bind_param(self, value, dialect): return (value - self.epoch).days def process_result_value(self, value, dialect): return self.epoch + timedelta(days=value) Our expression of ``somecol + date`` with the above type will coerce the "date" on the right side to also be treated as ``MyEpochType``. This behavior can be overridden via the :meth:`~TypeDecorator.coerce_compared_value` method, which returns a type that should be used for the value of the expression. Below we set it such that an integer value will be treated as an ``Integer``, and any other value is assumed to be a date and will be treated as a ``MyEpochType``:: def coerce_compared_value(self, op, value): if isinstance(value, int): return Integer() else: return self .. warning:: Note that the **behavior of coerce_compared_value is not inherited by default from that of the base type**. If the :class:`.TypeDecorator` is augmenting a type that requires special logic for certain types of operators, this method **must** be overridden. A key example is when decorating the :class:`_postgresql.JSON` and :class:`_postgresql.JSONB` types; the default rules of :meth:`.TypeEngine.coerce_compared_value` should be used in order to deal with operators like index operations:: class MyJsonType(TypeDecorator): impl = postgresql.JSON def coerce_compared_value(self, op, value): return self.impl.coerce_compared_value(op, value) Without the above step, index operations such as ``mycol['foo']`` will cause the index value ``'foo'`` to be JSON encoded. type_decoratorct|jdstdt|jjg|Ri||_dS)aConstruct a :class:`.TypeDecorator`. Arguments sent here are passed to the constructor of the class assigned to the ``impl`` class level attribute, assuming the ``impl`` is a callable, and the resulting object is assigned to the ``self.impl`` instance attribute (thus overriding the class attribute of the same name). If the class level ``impl`` is not a callable (the unusual case), it will be assigned to the same instance attribute 'as-is', ignoring those arguments passed to the constructor. Subclasses can override this to customize the generation of ``self.impl`` entirely. ruzuTypeDecorator implementations require a class-level variable 'impl' which refers to the class of type being decoratedN)rr;AssertionErrorrYru)rargsr s rrzTypeDecorator.__init__wsY$t~v..  '    3EdEEEfEE rc0eZdZdZdZfdZfdZxZS)TypeDecorator.ComparatorzA :class:`.TypeEngine.Comparator` that is specific to :class:`.TypeDecorator`. User-defined :class:`.TypeDecorator` classes should not typically need to modify this. r2c~|jjj|d<ttj|j|g|Ri|SN_python_is_types)rrcoerce_to_is_typesrrr3r"rrrr r;s rr"z TypeDecorator.Comparator.operatesV)-)JF% &@51488@$ rc z|jjj|d<ttj|j||fi|Sr)rrrrrr3r%rs rr%z(TypeDecorator.Comparator.reverse_operatesK)-)JF% &H51488HE# r)rr-r.r/r0r"r%rrs@rr3rsb                  rr3ctj|jjjvr |jjSt dtj|jjfiS)N TDComparator)rr3rurrorr+s rrz TypeDecorator.comparator_factorysK  #ty'C'K K K9/ /)49+GH rc||}||ur|S||}|}t||jst d|d|j||_|S) #todo z Type object zQ does not properly implement the copy() method, it must return an object of type )rr}r5 isinstancer;rru)rr>adaptedtypedesctts rrzTypeDecorator._gen_dialect_impls))$// $  N //88 YY[["dn--  .26t~~G   rc|jjS)r)rursr+s rrszTypeDecorator._type_affinitys y''rFc tt|||s1t|jt r|jj|fddi|dSdSdS)Support SchemaEventTargetouterFN)rr _set_parentrrur)rcolumnrr<r;s rrzTypeDecorator._set_parents{ mT""..v666 =DI/@AA = !DI !& < < < < < < < < = = = =rctt||dt|jt r|j|dSdS)rT)rN)rr_set_parent_with_dispatchrrur)rparentr;s rrz'TypeDecorator._set_parent_with_dispatchsn mT""<< $ =    di!2 3 3 8 I / / 7 7 7 7 7 8 8rc||}t|t|s|S||S)asReturn a dialect-specific :class:`.TypeEngine` instance for this :class:`.TypeDecorator`. In most cases this returns a dialect-adapted form of the :class:`.TypeEngine` type represented by ``self.impl``. Makes usage of :meth:`dialect_impl`. Behavior can be customized here by overriding :meth:`load_dialect_impl`. )rrrload_dialect_impl)rr>rs r type_enginezTypeDecorator.type_enginesH))$//'4::.. 3N))'22 2rc|jS)aReturn a :class:`.TypeEngine` object corresponding to a dialect. This is an end-user override hook that can be used to provide differing types depending on the given dialect. It is used by the :class:`.TypeDecorator` implementation of :meth:`type_engine` to help determine what type should ultimately be returned for a given :class:`.TypeDecorator`. By default returns ``self.impl``. )rurEs rrzTypeDecorator.load_dialect_impls yrcR|||Sr|)rrzrEs rr}z%TypeDecorator._unwrapped_dialect_impls&%%g..;;GDDDrc,t|j|S)zMProxy all other undefined accessors to the underlying implementation.)rru)rrs r __getattr__zTypeDecorator.__getattr__"sty#&&&rct)aReceive a literal parameter value to be rendered inline within a statement. This method is used when the compiler renders a literal value without using binds, typically within DDL such as in the "server default" of a column or an expression within a CHECK constraint. The returned string will be rendered into the output string. .. versionadded:: 0.9.0 rfrrBr>s rprocess_literal_paramz#TypeDecorator.process_literal_param's"###rct)aReceive a bound parameter value to be converted. Subclasses override this method to return the value that should be passed along to the underlying :class:`.TypeEngine` object, and from there to the DBAPI ``execute()`` method. The operation could be anything desired to perform custom behavior, such as transforming or serializing data. This could also be used as a hook for validating logic. This operation should be designed with the reverse operation in mind, which would be the process_result_value method of this class. :param value: Data to operate upon, of any type expected by this method in the subclass. Can be ``None``. :param dialect: the :class:`.Dialect` in use. rfr s rprocess_bind_paramz TypeDecorator.process_bind_param7s,"###rct)aReceive a result-row column value to be converted. Subclasses should implement this method to operate on data fetched from the database. Subclasses override this method to return the value that should be passed back to the application, given a value that is already processed by the underlying :class:`.TypeEngine` object, originally from the DBAPI cursor method ``fetchone()`` or similar. The operation could be anything desired to perform custom behavior, such as transforming or serializing data. This could also be used as a hook for validating logic. :param value: Data to operate upon, of any type expected by this method in the subclass. Can be ``None``. :param dialect: the :class:`.Dialect` in use. This operation should be designed to be reversible by the "process_bind_param" method of this class. rfr s rprocess_result_valuez"TypeDecorator.process_result_valueOs2"###rcF|jjjtjjuS)zmemoized boolean, check if process_bind_param is implemented. Allows the base process_bind_param to raise NotImplementedError without needing to test an expensive exception throw. )r;rrQrr+s r_has_bind_processorz!TypeDecorator._has_bind_processorjs" N - 6 3< = rcF|jjjtjjuS)z@memoized boolean, check if process_literal_param is implemented.)r;r rQrr+s r_has_literal_processorz$TypeDecorator._has_literal_processorys# N 0 9 6? @ rc|jr|jn|jr|jndr,|jrfd}nfd}|S|jS)alProvide a literal processing function for the given :class:`.Dialect`. Subclasses here will typically override :meth:`.TypeDecorator.process_literal_param` instead of this method directly. By default, this method makes use of :meth:`.TypeDecorator.process_bind_param` if that method is implemented, where :meth:`.TypeDecorator.process_literal_param` is not. The rationale here is that :class:`.TypeDecorator` typically deals with Python conversions of data that are above the layer of database presentation. With the value converted by :meth:`.TypeDecorator.process_bind_param`, the underlying type will then handle whether it needs to be presented to the DBAPI as a bound parameter or to the database as an inline SQL value. .. versionadded:: 0.9.0 Nc.|Srr2rBr>impl_processor process_params rrz0TypeDecorator.literal_processor..process)>--w*G*GHHHrc|Srr2rBr>rs rrz0TypeDecorator.literal_processor..process(=888r)rr rrrurFrr>rrrs ` @@rrFzTypeDecorator.literal_processors*  & ! 6MM  % ! !3MM M  8!Y88AAN 9IIIIIIII 999999N9..w77 7rc|jr3|j|jrfd}nfd}|S|jS)aProvide a bound value processing function for the given :class:`.Dialect`. This is the method that fulfills the :class:`.TypeEngine` contract for bound value conversion. :class:`.TypeDecorator` will wrap a user-defined implementation of :meth:`process_bind_param` here. User-defined code can override this method directly, though its likely best to use :meth:`process_bind_param` so that the processing provided by ``self.impl`` is maintained. :param dialect: Dialect instance in use. This method is the reverse counterpart to the :meth:`result_processor` method of this class. c.|Srr2rs rrz-TypeDecorator.bind_processor..processrrc|Srr2rs rrz-TypeDecorator.bind_processor..processrr)rrrurHrs ` @@rrHzTypeDecorator.bind_processors&  # 5 3M!Y55g>>N 9IIIIIIII 999999N9++G44 4rcF|jjjtjjuS)zmemoized boolean, check if process_result_value is implemented. Allows the base process_result_value to raise NotImplementedError without needing to test an expensive exception throw. )r;rrQrr+s r_has_result_processorz#TypeDecorator._has_result_processors" N / 8 5> ? rc|jr4|j|j|rfd}nfd}|S|j|S)aProvide a result value processing function for the given :class:`.Dialect`. This is the method that fulfills the :class:`.TypeEngine` contract for result value conversion. :class:`.TypeDecorator` will wrap a user-defined implementation of :meth:`process_result_value` here. User-defined code can override this method directly, though its likely best to use :meth:`process_result_value` so that the processing provided by ``self.impl`` is maintained. :param dialect: Dialect instance in use. :param coltype: A SQLAlchemy data type This method is the reverse counterpart to the :meth:`bind_processor` method of this class. c.|Srr2)rBr>r process_values rrz/TypeDecorator.result_processor..processs(=)>)>HHHrc|Srr2)rBr>r's rrz/TypeDecorator.result_processor..processrr)r$rrurK)rr>rJrrr's ` @@rrKzTypeDecorator.result_processors(  % @ 5M!Y77IIN 9IIIIIIII 999999N9--gw?? ?rc^|jjjtjjup |jjSr)r;rUrQrrurWr+s rrWz"TypeDecorator._has_bind_expression s1 N * 3 09 :,Y + ,rc6|j|Sr)rurU)r bindparams rrUzTypeDecorator.bind_expressionsy((333rc^|jjjtjjup |jjSrP)r;rNrQrrurRr+s rrRz$TypeDecorator._has_column_expressions1 N , 5 2; <.Y - .rc6|j|Sr)rurN)rrs rrNzTypeDecorator.column_expression!sy**6222rc|S)a}Suggest a type for a 'coerced' Python value in an expression. By default, returns self. This method is called by the expression system when an object using this type is on the left or right side of an expression against a plain Python object which does not yet have a SQLAlchemy type assigned:: expr = table.c.somecolumn + 35 Where above, if ``somecolumn`` uses this type, this method will be called with the value ``operator.add`` and ``35``. The return value is whatever SQLAlchemy type should be used for ``35`` for this particular operation. r2rs rrz#TypeDecorator.coerce_compared_value$s  rc |j|j}|j|j|S)aGProduce a copy of this :class:`.TypeDecorator` instance. This is a shallow copy and is provided to fulfill part of the :class:`.TypeEngine` contract. It usually does not need to be overridden unless the user-defined :class:`.TypeDecorator` has local state that should be deep-copied. )r;__new____dict__update)rr<instances rr5zTypeDecorator.copy6s9>))$.99  ///rc6|j|S)zReturn the DBAPI type object represented by this :class:`.TypeDecorator`. By default this calls upon :meth:`.TypeEngine.get_dbapi_type` of the underlying "impl". )rurdrbs rrdzTypeDecorator.get_dbapi_typeDsy''...rc8|j||S)aGiven two values, compare them for equality. By default this calls upon :meth:`.TypeEngine.compare_values` of the underlying "impl", which in turn usually uses the Python equals operator ``==``. This function is used by the ORM to compare an original-loaded value with an intercepted "changed" value, to determine if a net change has occurred. )rur`r]s rr`zTypeDecorator.compare_valuesMsy''1---rc|jjSr)rurr+s rrzTypeDecorator.sort_key_function\s y**rc8tj||jS)N) to_inspect)r rrur+s rrzTypeDecorator.__repr__`s $)<<< ,##%% % ty'***rc|jjS)z5express comparison behavior in terms of the base type)rurr+s rrzVariant.comparator_factorysy++rN) rr-r.r/rrrrrrmrrr2rrrjrjds    ///777+++,,,X,,,rrjc|jSr) comparator) expressions rr*r*s   rcP|tStj|r||i|S|Sr)rr callable)typeobjargr<s rrYrYs8 }Ww"r"""rct|tr |}|jjddD]} ||}n#t$rYwxYw|St |j|r|S||S)Nrr)rrr;rorxrqr:)rNcolspecsrrrs r adapt_typerRs'4  '))   &qt ,   {H E    D   '#X.. == " ""sA A A)r/rr=rvisitorsrrrr BOOLEANTYPE INTEGERTYPEr STRINGTYPE MATCHTYPE INDEXABLErr EnsureKWArgTyperwith_metaclassrpobjectrrrrjr*rYrRr2rrr]s> ############      S 'S 'S 'S 'S 'S 'S 'S 'l     $.    QQQQQ)d)*=zJJQQQh,?,?,?,?,?v,?,?,?^(Q =Q =Q =Q =Q =%zQ =Q =Q =hN,N,N,N,N,mN,N,N,b!!!#####rPK!?-%__pycache__/functions.cpython-311.pycnu[ |oidZddlmZddlmZddlmZddlmZddlmZddlm Z ddlm Z dd l m Z dd l m Z dd l mZdd l mZdd l mZddl mZddl mZddl mZddl mZddl mZddl mZddl mZddl mZddl mZddlmZddlmZddlmZddlmZddlmZej e!Z"ej dZ#ej$ddZ%dud!Z&Gd"d#e eeZ'Gd$d%eZ(Gd&d'e)Z*e*Z+e*je+_e*d()Z,Gd*d+e'Z-Gd,d-eZ.Gd.d/ej/e.e-Z0e&d0ee&d1eGd2d3e0Z1Gd4d5e0Z2Gd6d7e0Z3Gd8d9e3Z4Gd:d;e3Z5Gd<d=e3Z6Gd>d?e3Z7Gd@dAe0Z8GdBdCe0Z9GdDdEe0Z:GdFdGe0Z;GdHdIe0Z<GdJdKe2Z=GdLdMe2Z>GdNdOe2Z?GdPdQe2Z@GdRdSe2ZAGdTdUe2ZBGdVdWe2ZCGdXdYe2ZDGdZd[e2ZEGd\d]e0ZFGd^d_e0ZGGd`daeGZHGdbdceGZIGdddeeGZJGdfdge0ZKGdhdie0ZLGdjdke0ZMGdldme0ZNGdndoe0ZOGdpdqe0ZPGdrdse0ZQdtS)vz6SQL function API, factories, and built-in functions. ) annotation) operators)schema)sqltypes)util)ColumnCollection) Executable)_clone_literal_as_binds)_type_from_args)BinaryExpression) BindParameter)Cast) ClauseList) ColumnElement)ExtractFunctionFilter)Grouping)literal_columnOver WithinGroup)Alias) FromClause)Select) VisitableTypec4tjtSN)r defaultdictdictO/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/functions.pyr((sD4DT4J4Jr&case_sensitive_functionzHSymbol to mark the functions that are switched into case-sensitive mode.)namedoc_defaultc t|}t|}|}tj|}||vr||t ur|||vr-tjd||||<ntjd|t|| dt ||<n||vr|||vrNtjdt|| |n-tjd|n|||<||||<dS)zAssociate a callable with a particular func. name. This is normally called by _GenericMeta, but is also available by itself so that a non-Function construct can be associated with the :data:`.func` accessor (i.e. CAST, EXTRACT). zMThe GenericFunction '{}' is already registered and is going to be overridden.zGenericFunction '{}' is already registered with different letter case, so the previously registered function '{}' is switched into case-sensitive mode. GenericFunction objects will be fully case-insensitive in a future release.zGenericFunction(s) '{}' are already registered with different letter cases and might interact with '{}'. GenericFunction objects will be fully case-insensitive in a future release.zLThe GenericFunction '{}' is already registered and is going to be overriden.N) _registry_case_sensitive_registryr text_typelower_CASE_SENSITIVEwarnformatwarn_deprecatedlistkeyssorted) identifierfnpackageregcase_sensitive_regraw_identifiers r'register_functionr@0s G C1':N ++1133JSS_OCC / ; ; ; I--3VJ-?-?   !C OO  "#)&"+J7<<>>??B##   .C OO ) ) ) !3J!? ? ?  "#)&-j9>>@@AA"##      I,,2F>,B,B    J68z">222r&ceZdZdZdZdZdZdZedZ e j dZ dd Z d Zd Zd Zed ZdZefdZdZddZdZdZdZddZdfd ZxZS)FunctionElementazBase for SQL function-oriented constructs. .. seealso:: :ref:`coretutorial_functions` - in the Core tutorial :class:`.Function` - named SQL function. :data:`.func` - namespace which produces registered or ad-hoc :class:`.Function` instances. :class:`.GenericFunction` - allows creation of registered function types. r%Fcfd|D}jpt|_t|tjdd_dS)aOConstruct a :class:`.FunctionElement`. :param \*clauses: list of column expressions that form the arguments of the SQL function call. :param \**kwargs: additional kwargs are typically consumed by subclasses. .. seealso:: :data:`.func` :class:`.Function` c:g|]}t|jSr%r r*.0cselfs r' z,FunctionElement.__init__..s&AAAA!!TY//AAAr&Toperatorgroup_contentsN) _has_argsboolrrcomma_op self_group clause_expr)rIclauseskwargsargss` r'__init__zFunctionElement.__init__sf BAAAAAA54::%?CY'   *,, r&c0||||Sr")_execute_function)rI connection multiparamsparamss r'_execute_on_connectionz&FunctionElement._execute_on_connections++D+vFFFr&cFt|dS)a?The set of columns exported by this :class:`.FunctionElement`. Function objects currently have no result column names built in; this method returns a single-element column collection with an anonymously named column. An interim approach to providing named columns for a function as a FROM clause is to build a :func:`_expression.select` with the desired columns:: from sqlalchemy.sql import column stmt = select([column('x'), column('y')]).\ select_from(func.myfunction()) N)rlabelrIs r'columnszFunctionElement.columnss&  4 0 0111r&c|jjS)z}Return the underlying :class:`.ClauseList` which contains the arguments for this :class:`.FunctionElement`. )rRelementr_s r'rSzFunctionElement.clausess ''r&Nc*t|||||S)aProduce an OVER clause against this function. Used against aggregate or so-called "window" functions, for database backends that support window functions. The expression:: func.row_number().over(order_by='x') is shorthand for:: from sqlalchemy import over over(func.row_number(), order_by='x') See :func:`_expression.over` for a full description. ) partition_byorder_byrowsrange_r)rIrdrerfrgs r'overzFunctionElement.overs*$ %     r&ct|g|RS)axProduce a WITHIN GROUP (ORDER BY expr) clause against this function. Used against so-called "ordered set aggregate" and "hypothetical set aggregate" functions, including :class:`.percentile_cont`, :class:`.rank`, :class:`.dense_rank`, etc. See :func:`_expression.within_group` for a full description. .. versionadded:: 1.1 r)rIres r' within_groupzFunctionElement.within_groups4+(++++r&c$|s|St|g|RS)aProduce a FILTER clause against this function. Used against aggregate and window functions, for database backends that support the "FILTER" clause. The expression:: func.count(1).filter(True) is shorthand for:: from sqlalchemy import funcfilter funcfilter(func.count(1), True) .. versionadded:: 1.0.0 .. seealso:: :class:`.FunctionFilter` :func:`.funcfilter` r)rI criterions r'filterzFunctionElement.filters'2 Kd/Y////r&c$t|||S)ai Interpret this expression as a boolean comparison between two values. A hypothetical SQL function "is_equal()" which compares to values for equality would be written in the Core expression language as:: expr = func.is_equal("a", "b") If "is_equal()" above is comparing "a" and "b" for equality, the :meth:`.FunctionElement.as_comparison` method would be invoked as:: expr = func.is_equal("a", "b").as_comparison(1, 2) Where above, the integer value "1" refers to the first argument of the "is_equal()" function and the integer value "2" refers to the second. This would create a :class:`.BinaryExpression` that is equivalent to:: BinaryExpression("a", "b", operator=op.eq) However, at the SQL level it would still render as "is_equal('a', 'b')". The ORM, when it loads a related object or collection, needs to be able to manipulate the "left" and "right" sides of the ON clause of a JOIN expression. The purpose of this method is to provide a SQL function construct that can also supply this information to the ORM, when used with the :paramref:`_orm.relationship.primaryjoin` parameter. The return value is a containment object called :class:`.FunctionAsBinary`. An ORM example is as follows:: class Venue(Base): __tablename__ = 'venue' id = Column(Integer, primary_key=True) name = Column(String) descendants = relationship( "Venue", primaryjoin=func.instr( remote(foreign(name)), name + "/" ).as_comparison(1, 2) == 1, viewonly=True, order_by=name ) Above, the "Venue" class can load descendant "Venue" objects by determining if the name of the parent Venue is contained within the start of the hypothetical descendant value's name, e.g. "parent1" would match up to "parent1/child1", but not to "parent2/child1". Possible use cases include the "materialized path" example given above, as well as making use of special SQL functions such as geometric functions to create join conditions. :param left_index: the integer 1-based index of the function argument that serves as the "left" side of the expression. :param right_index: the integer 1-based index of the function argument that serves as the "right" side of the expression. .. versionadded:: 1.3 )FunctionAsBinary)rI left_index right_indexs r' as_comparisonzFunctionElement.as_comparisons@ j+>>>r&c|jjSr")rS _from_objectsr_s r'rtzFunctionElement._from_objectsEs |))r&c |jfSr")rR)rIrTs r' get_childrenzFunctionElement.get_childrenIs ""r&c ||jfi||_|tj|dSr")rR_reset_exportedrBrS_reset)rIclonekws r'_copy_internalszFunctionElement._copy_internalsLsN 5!188R88 &&t,,,,,r&cdS)aFor types that define their return type as based on the criteria within a WITHIN GROUP (ORDER BY) expression, called by the :class:`.WithinGroup` construct. Returns None by default, in which case the function's normal ``.type`` is used. Nr%)rIrjs r'within_group_typez!FunctionElement.within_group_typeQs tr&c,tj||S)ajProduce a :class:`_expression.Alias` construct against this :class:`.FunctionElement`. This construct wraps the function in a named alias which is suitable for the FROM clause, in the style accepted for example by PostgreSQL. e.g.:: from sqlalchemy.sql import column stmt = select([column('data_view')]).\ select_from(SomeTable).\ select_from(func.unnest(SomeTable.data).alias('data_view') ) Would produce: .. sourcecode:: sql SELECT data_view FROM sometable, unnest(sometable.data) AS data_view .. versionadded:: 0.9.8 The :meth:`.FunctionElement.alias` method is now supported. Previously, this method's behavior was undefined and did not behave consistently across versions. )r _construct)rIr*flats r'aliaszFunctionElement.alias]s<d+++r&cXt|g}|jr|jdi|j}|S)zProduce a :func:`_expression.select` construct against this :class:`.FunctionElement`. This is shorthand for:: s = select([function_element]) r%)r_execution_optionsexecution_options)rIss r'selectzFunctionElement.select}s< D6NN  " ?##>>d&=>>Ar&cr|S)aExecute this :class:`.FunctionElement` against an embedded 'bind' and return a scalar value. This first calls :meth:`~.FunctionElement.select` to produce a SELECT construct. Note that :class:`.FunctionElement` can be passed to the :meth:`.Connectable.scalar` method of :class:`_engine.Connection` or :class:`_engine.Engine`. )rexecutescalarr_s r'rzFunctionElement.scalars*{{}}$$&&--///r&cN|S)agExecute this :class:`.FunctionElement` against an embedded 'bind'. This first calls :meth:`~.FunctionElement.select` to produce a SELECT construct. Note that :class:`.FunctionElement` can be passed to the :meth:`.Connectable.execute` method of :class:`_engine.Connection` or :class:`_engine.Engine`. )rrr_s r'rzFunctionElement.executes{{}}$$&&&r&c6td|||jd|S)NT)_compared_to_operator_compared_to_typeuniquetype_)rtyperIrLobjrs r' _bind_paramzFunctionElement._bind_params-  "*"i     r&c|tjur.t|jtjrt |Stt| |S)N)against) rgetitem isinstancerrARRAYrsuperrBrQ)rIr __class__s r'rQzFunctionElement.self_groupsZ i' ' 'J Ix~- - 'D>> !$//::7:KK Kr&)NNNN)NFr")__name__ __module__ __qualname____doc__ packagenamesrNrVr\propertyr`rmemoized_propertyrSrhrjrmrrrtrvr r|r~rrrrrrQ __classcell__rs@r'rBrBrs LI,GGG22X2( (((    4 , , ,000:@?@?@?D**X*###%+----   ,,,,@    0 0 0 ' ' '     L L L L L L L L L Lr&rBceZdZfdZedZejdZedZejdZfdZxZ S)roc|jj|dz }|jj|dz }||_||_||_t t |||tjtj dS)Nr)r) rS sql_functionrprqrrorVrfunction_as_comparison_opr BOOLEANTYPE)rIr;rprqleftrightrs r'rVzFunctionAsBinary.__init__sz!*q.1 ";?3$& %%..    /& /     r&c@|jjj|jdz SNrrrSrpr_s r'rzFunctionAsBinary.lefts (011DEEr&c>||jjj|jdz <dSrrrIvalues r'rzFunctionAsBinary.lefts"AF!)$/A*=>>>r&c@|jjj|jdz SrrrSrqr_s r'rzFunctionAsBinary.rights (01AA1EFFr&c>||jjj|jdz <dSrrrs r'rzFunctionAsBinary.rights#BG!)$*:Q*>???r&c |d}||jfi||_tt|jdi|dS)Nrzr%)poprrror|)rIr{rzrs r'r|z FunctionAsBinary._copy_internalssYw!E$"3::r::5%%5;;;;;;;r&) rrrrVrrsetterrr|rrs@r'roros      FFXF [GG[GGGXG \HH\H<<<<<<<<>> print(func.count(1)) count(:param_1) The returned object is an instance of :class:`.Function`, and is a column-oriented SQL element like any other, and is used in that way:: >>> print(select([func.count(table.c.id)])) SELECT count(sometable.id) FROM sometable Any name can be given to :data:`.func`. If the function name is unknown to SQLAlchemy, it will be rendered exactly as is. For common SQL functions which SQLAlchemy is aware of, the name may be interpreted as a *generic function* which will be compiled appropriately to the target database:: >>> print(func.current_timestamp()) CURRENT_TIMESTAMP To call functions which are present in dot-separated packages, specify them in the same manner:: >>> print(func.stats.yield_curve(5, 10)) stats.yield_curve(:yield_curve_1, :yield_curve_2) SQLAlchemy can be made aware of the return type of functions to enable type-specific lexical and result-based behavior. For example, to ensure that a string-based function returns a Unicode value and is similarly treated as a string in expressions, specify :class:`~sqlalchemy.types.Unicode` as the type: >>> print(func.my_string(u'hi', type_=Unicode) + ' ' + ... func.my_string(u'there', type_=Unicode)) my_string(:my_string_1) || :my_string_2 || my_string(:my_string_3) The object returned by a :data:`.func` call is usually an instance of :class:`.Function`. This object meets the "column" interface, including comparison and labeling functions. The object can also be passed the :meth:`~.Connectable.execute` method of a :class:`_engine.Connection` or :class:`_engine.Engine`, where it will be wrapped inside of a SELECT statement first:: print(connection.execute(func.current_timestamp()).scalar()) In a few exception cases, the :data:`.func` accessor will redirect a name to a built-in expression such as :func:`.cast` or :func:`.extract`, as these names have well-known meaning but are not exactly the same as "functions" from a SQLAlchemy perspective. Functions which are interpreted as "generic" functions know how to calculate their return type automatically. For a listing of known generic functions, see :ref:`generic_functions`. .. note:: The :data:`.func` construct has only limited support for calling standalone "stored procedures", especially those with special parameterization concerns. See the section :ref:`stored_procedures` for details on how to use the DBAPI-level ``callproc()`` method for fully traditional stored procedures. .. seealso:: :ref:`coretutorial_functions` - in the Core Tutorial :class:`.Function` c "g|_||_dSr")_FunctionGenerator__namesopts)rIrs r'rVz_FunctionGenerator.__init__1s  r&c |dr+ |j|S#t$rt|wxYw|dr |dd}t di|j}t|j|gz|_|S)N___r.r%) startswith__dict__KeyErrorAttributeErrorendswithrrr7r)rIr*fs r' __getattr__z_FunctionGenerator.__getattr__5s ??4   +}T** + + +$T*** +]]3   ":D  + + + +&&$/ s $>cH|j}||t|j}|dkr |j\}}n|dkrd|jd}}nd}|t ||}|turGt|}|||}|||i|St|jdg|Rd|jddi|S)Nr rr,r.rr) rcopyupdatelenrr/getr2r3r0Function) rIrHrTotokensr<fnamefuncr>s r'__call__z_FunctionGenerator.__call__Cs/ INN   T\"" Q;;!\NGUU q[['aUGGG  W%))%++--88D&&%=g%F")--ekkmm<<@@GGtQ}!}}$ L  @A   +/<"+= EF   r&N)rrrrrVrrr%r&r'rrsNJJX        r&rF)groupc$eZdZdZdZdZddZdS)raDescribe a named SQL function. The :class:`.Function` object is typically generated from the :data:`.func` generation object. :param \*clauses: list of column expressions that form the arguments of the SQL function call. :param type\_: optional :class:`.TypeEngine` datatype object that will be used as the return value of the column expression generated by this function call. :param packagenames: a string which indicates package prefix names to be prepended to the function name when the SQL is generated. The :data:`.func` generator creates these when it is called using dotted format, e.g.:: func.mypackage.some_function(col1, col2) .. seealso:: :ref:`coretutorial_functions` :data:`.func` - namespace which produces registered or ad-hoc :class:`.Function` instances. :class:`.GenericFunction` - allows creation of registered function types. functionc|ddpg|_||_|dd|_t j|dd|_tj |g|Ri|dS)zConstruct a :class:`.Function`. The :data:`.func` construct is normally used to construct new :class:`.Function` instances. rNbindr) rrr*r_bindr to_instancerrBrV)rIr*rSr{s r'rVzFunction.__init__sFF>488>B VVFD)) ()>)>??  6666266666r&Nc@t|j|||j|dS)NT)rrrr)rr*rrs r'rzFunction._bind_params/ I "*"i     r&r")rrrr__visit_name__rVrr%r&r'rrdsIB N 7 7 7      r&rceZdZfdZxZS) _GenericMetactj|jvr|d|x|_}|d|x|_}|dd}d|vr |d|_t|dd|_ |j rt|||nd|_ tt| |||dS)Nr*r:r<r,__return_type__ _registerT)r Annotated__mro__rr*r:rrgetattrrr@rrrV)clsclsnamebasesclsdictr*r:r<rs r'rVz_GenericMeta.__init__s  s{ 2 2%kk&':: :CHt*1++lD*I*I ICNZkk)Z88G G++"#45$Cd;;CM} %!*c7;;;;!%  lC  ))'5'BBBBBr&)rrrrVrrs@r'rrsACCCCCCCCCr&rc eZdZdZdZdZdZdS)GenericFunctiona Define a 'generic' function. A generic function is a pre-established :class:`.Function` class that is instantiated automatically when called by name from the :data:`.func` attribute. Note that calling any name from :data:`.func` has the effect that a new :class:`.Function` instance is created automatically, given that name. The primary use case for defining a :class:`.GenericFunction` class is so that a function of a particular name may be given a fixed return type. It can also include custom argument parsing schemes as well as additional methods. Subclasses of :class:`.GenericFunction` are automatically registered under the name of the class. For example, a user-defined function ``as_utc()`` would be available immediately:: from sqlalchemy.sql.functions import GenericFunction from sqlalchemy.types import DateTime class as_utc(GenericFunction): type = DateTime print(select([func.as_utc()])) User-defined generic functions can be organized into packages by specifying the "package" attribute when defining :class:`.GenericFunction`. Third party libraries containing many functions may want to use this in order to avoid name conflicts with other systems. For example, if our ``as_utc()`` function were part of a package "time":: class as_utc(GenericFunction): type = DateTime package = "time" The above function would be available from :data:`.func` using the package name ``time``:: print(select([func.time.as_utc()])) A final option is to allow the function to be accessed from one name in :data:`.func` but to render as a different name. The ``identifier`` attribute will override the name used to access the function as loaded from :data:`.func`, but will retain the usage of ``name`` as the rendered name:: class GeoBuffer(GenericFunction): type = Geometry package = "geo" name = "ST_Buffer" identifier = "buffer" The above function will render as follows:: >>> print(func.geo.buffer()) ST_Buffer() The name will be rendered as is, however without quoting unless the name contains special characters that require quoting. To force quoting on or off for the name, use the :class:`.sqlalchemy.sql.quoted_name` construct:: from sqlalchemy.sql import quoted_name class GeoBuffer(GenericFunction): type = Geometry package = "geo" name = quoted_name("ST_Buffer", True) identifier = "buffer" The above function will render as:: >>> print(func.geo.buffer()) "ST_Buffer"() .. versionadded:: 1.3.13 The :class:`.quoted_name` construct is now recognized for quoting when used with the "name" attribute of the object, so that quoting can be forced on or off for the function name. TFc|dd}|fd|D}jpt|_g_|dd_t |tjdd _ tj |ddptdd_dS)N _parsed_argsc:g|]}t|jSr%rErFs r'rJz,GenericFunction.__init__..s&IIIq,Q ::IIIr&rTrKrr)rrNrOrrrrrrPrQrRrrrr)rIrUrT parsed_argss` r'rVzGenericFunction.__init__sjj66  IIIIDIIIK<4 +<+<ZZ-- %?JY'   *,, ( JJw % % Dvt)D)D   r&N)rrrrcoerce_argumentsrrVr%r&r'rrs=TTlI      r&rcastextractcPeZdZdZejZdZdZe dZ dS) next_valueaRepresent the 'next value', given a :class:`.Sequence` as its single argument. Compiles into the appropriate function on each backend, or will raise NotImplementedError if used on a backend that does not provide support for sequences. c t|tjs Jd|dd|_||_dS)Nz0next_value() accepts a Sequence object as input.r)rrSequencerrsequence)rIseqr{s r'rVznext_value.__init__2sT    > > = > > VVFD))  r&cgSr"r%r_s r'rtznext_value._from_objects9s r&N) rrrrrIntegerrr*rVrrtr%r&r'rr%s_ 8   D DXr&rceZdZdZdS) AnsiFunctionc0tj|g|Ri|dSr"rrV)rIrUrTs r'rVzAnsiFunction.__init__?s) 777777777r&N)rrrrVr%r&r'rr>s#88888r&rc"eZdZdZfdZxZS)ReturnTypeFromArgszADefine a function whose return type is the same as its arguments.cfd|D}|dt|||d<ttj|i|dS)Nc:g|]}t|jSr%rErFs r'rJz/ReturnTypeFromArgs.__init__..Gs&>>>A!!TY//>>>r&rr) setdefaultr rrrV)rIrUrTrs` r'rVzReturnTypeFromArgs.__init__Fsn>>>>>>>'?4#8#8999!%~0 $''0$A&AAAAAr&)rrrrrVrrs@r'rrCsGKKBBBBBBBBBr&rceZdZdZdS)coalesceTNrrrrNr%r&r'rrMIIIr&rceZdZdS)maxNrrrr%r&r'rrQDr&rceZdZdS)minNrr%r&r'r r Ur r&r ceZdZdS)sumNrr%r&r'r r Yr r&r ceZdZejZdS)nowNrrrrDateTimerr%r&r'rr]  DDDr&rceZdZejZdS)concatNrrrrStringrr%r&r'rra ?DDDr&rc"eZdZejZdZdS) char_lengthc ,tj||fi|dSr"r)rIargrTs r'rVzchar_length.__init__hs# s55f55555r&N)rrrrrrrVr%r&r'rres+  D66666r&rceZdZdZdS)randomTNrr%r&r'rrlrr&rc2eZdZdZejZdfd ZxZS)countaThe ANSI COUNT aggregate function. With no arguments, emits COUNT \*. E.g.:: from sqlalchemy import func from sqlalchemy import select from sqlalchemy import table, column my_table = table('some_table', column('id')) stmt = select([func.count()]).select_from(my_table) Executing ``stmt`` would emit:: SELECT count(*) AS count_1 FROM some_table Nc l|td}tt|j|fi|dS)N*)rrrrV)rI expressionrTrs r'rVzcount.__init__sA  ',,J#eT#J99&99999r&r") rrrrrrrrVrrs@r'rrpsQ(  D::::::::::r&rceZdZejZdS) current_dateN)rrrrDaterr%r&r'r$r$ =DDDr&r$ceZdZejZdS) current_timeN)rrrrTimerr%r&r'r(r(r&r&r(ceZdZejZdS)current_timestampNrr%r&r'r+r+rr&r+ceZdZejZdS) current_userNrr%r&r'r-r-rr&r-ceZdZejZdS) localtimeNrr%r&r'r/r/rr&r/ceZdZejZdS)localtimestampNrr%r&r'r1r1rr&r1ceZdZejZdS) session_userNrr%r&r'r3r3rr&r3ceZdZejZdS)sysdateNrr%r&r'r5r5rr&r5ceZdZejZdS)userNrr%r&r'r7r7rr&r7c0eZdZdZejZfdZxZS) array_aggaSupport for the ARRAY_AGG function. The ``func.array_agg(expr)`` construct returns an expression of type :class:`_types.ARRAY`. e.g.:: stmt = select([func.array_agg(table.c.values)[2:5]]) .. versionadded:: 1.1 .. seealso:: :func:`_postgresql.array_agg` - PostgreSQL-specific version that returns :class:`_postgresql.ARRAY`, which has PG-specific operators added. c,d|D}|dtj}d|vr=t|}t |tjr||d<n|||d<||d<t t |j|i|dS)Nc,g|]}t|Sr%r )rGrHs r'rJz&array_agg.__init__..s!333!!$$333r&_default_array_typerr)rrrr rrr9rV)rIrUrTdefault_array_typetype_from_argsrs r'rVzarray_agg.__init__s33d333#ZZ(=x~NN & ,T22N.(.99 E"0w"4"4^"D"Dw!%~'i'888888r&) rrrrrrrrVrrs@r'r9r9sK& >D 9 9 9 9 9 9 9 9 9r&r9ceZdZdZdZdZdS) OrderedSetAggzDefine a function where the return type is based on the sort expression type as defined by the expression passed to the :meth:`.FunctionElement.within_group` method.Fc|jj}tj|j}|jr7t |jdkrtj |dj S|dj S)Nrr.) rRrbsqlutilunwrap_order_byrearray_for_multi_clauserrSrrr)rIrj func_clausesres r'r~zOrderedSetAgg.within_group_typesd'/ *<+@AA  & $3|/C+D+Dq+H+H>(1+"233 3A;# #r&N)rrrrrDr~r%r&r'r@r@s555#$$$$$r&r@ceZdZdZdS)modea*Implement the ``mode`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression. .. versionadded:: 1.1 N)rrrrr%r&r'rGrGs    r&rGceZdZdZdZdS)percentile_contaImplement the ``percentile_cont`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression, or if the arguments are an array, an :class:`_types.ARRAY` of the sort expression's type. .. versionadded:: 1.1 TNrrrrrDr%r&r'rIrI"  "r&rIceZdZdZdZdS)percentile_discaImplement the ``percentile_disc`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression, or if the arguments are an array, an :class:`_types.ARRAY` of the sort expression's type. .. versionadded:: 1.1 TNrJr%r&r'rMrMrKr&rMc0eZdZdZejZdS)ranka!Implement the ``rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Integer`. .. versionadded:: 1.1 Nrrrrrrrr%r&r'rOrO*   8   DDDr&rOc0eZdZdZejZdS) dense_ranka'Implement the ``dense_rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Integer`. .. versionadded:: 1.1 NrPr%r&r'rSrS$rQr&rSc0eZdZdZejZdS) percent_ranka)Implement the ``percent_rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Numeric`. .. versionadded:: 1.1 NrrrrrNumericrr%r&r'rUrU3rQr&rUc0eZdZdZejZdS) cume_dista&Implement the ``cume_dist`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Numeric`. .. versionadded:: 1.1 NrVr%r&r'rYrYBrQr&rYceZdZdZdZdS)cubeaYImplement the ``CUBE`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.cube(table.c.col_1, table.c.col_2)) .. versionadded:: 1.2 TNrrrrrNr%r&r'r[r[Q  IIIr&r[ceZdZdZdZdS)rollupaYImplement the ``ROLLUP`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.rollup(table.c.col_1, table.c.col_2)) .. versionadded:: 1.2 TNr\r%r&r'r_r_ar]r&r_ceZdZdZdZdS) grouping_setsa0Implement the ``GROUPING SETS`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.grouping_sets(table.c.col_1, table.c.col_2)) In order to group by multiple sets, use the :func:`.tuple_` construct:: from sqlalchemy import tuple_ stmt = select( [ func.sum(table.c.value), table.c.col_1, table.c.col_2, table.c.col_3] ).group_by( func.grouping_sets( tuple_(table.c.col_1, table.c.col_2), tuple_(table.c.value, table.c.col_3), ) ) .. versionadded:: 1.2 TNr\r%r&r'raraqs:IIIr&raN)r,)RrrrrrrrBbaserr elementsr r r rrrrrrrrrrr selectablerrrvisitorsrr#r$r/r0symbolr3r@rBroobjectrrmodifierrrwith_metaclassrrrrrrr r rrrrrr$r(r+r-r/r1r3r5r7r9r@rGrIrMrOrSrUrYr[r_rar%r&r'rksY """"""''''''%%%%%%&&&&&&###### ######$$$$$$$$$$$$!!!!!!""""""###### D T " " +4+,J,JKK$+ " ?8?8?8?8DILILILILILj-ILILILX #<#<#<#<#<'#<#<#zHUpdateBase._process_colparams..process_single..2s,NNgaQUDMNNNNNN) isinstancelisttupledictziptabler)pselfs r!process_singlez5UpdateBase._process_colparams..process_single0sI!dE]++ NNTZ\19M9MNNNNNNr#zOWhen preserve_parameter_order is True, values() only accepts a list of 2-tuplescg|]\}}|Srr)rrvalues r! z1UpdateBase._process_colparams..>s'I'I'I U'I'I'Ir#Fz8This construct does not support multiple parameter sets.c&g|] }|Srr)rr*r,s r!r0z1UpdateBase._process_colparams..Ns#:::!NN1%%:::r#T) _preserve_parameter_orderr$r%r& ValueError_parameter_orderingr'_supports_multi_parametersrInvalidRequestError)r+ parametersr,s` @r!_process_colparamszUpdateBase._process_colparams/s@       ) +j.Dj$//  #-jmU#C#C !?(J'Ij'I'I'ID $ ##U* * zD%= 1 1 5 5:a=4*=>> 5 2 -/ ;:::z:::D@ @!>*--u4 4r#c td)zSet the parameters for the statement. This method raises ``NotImplementedError`` on the base class, and is overridden by :class:`.ValuesBase` to provide the SET/VALUES clause of UPDATE and INSERT. zparams() is not supported for INSERT/UPDATE/DELETE statements. To set the values for an INSERT or UPDATE statement, use stmt.values(**parameters).)NotImplementedError)r+argkws r!paramszUpdateBase.paramsRs" *   r#c(|jp |jjS)zuReturn a 'bind' linked to this :class:`.UpdateBase` or a :class:`_schema.Table` associated with it. )_bindr)bind)r+s r!r@zUpdateBase.bind`s z,TZ_,r#c||_dSr)r?)r+r@s r! _set_bindzUpdateBase._set_bindgs  r#c|jrtjd|jrt jd||_dS)aAdd a :term:`RETURNING` or equivalent clause to this statement. e.g.:: stmt = table.update().\ where(table.c.data == 'value').\ values(status='X').\ returning(table.c.server_flag, table.c.updated_timestamp) for server_flag, updated_timestamp in connection.execute(stmt): print(server_flag, updated_timestamp) The given collection of column expressions should be derived from the table that is the target of the INSERT, UPDATE, or DELETE. While :class:`_schema.Column` objects are typical, the elements can also be expressions:: stmt = table.insert().returning( (table.c.first_name + " " + table.c.last_name). label('fullname')) Upon compilation, a RETURNING clause, or database equivalent, will be rendered within the statement. For INSERT and UPDATE, the values are the newly inserted/updated values. For DELETE, the values are those of the rows which were deleted. Upon execution, the values of the columns to be returned are made available via the result set and can be iterated using :meth:`_engine.ResultProxy.fetchone` and similar. For DBAPIs which do not natively support returning values (i.e. cx_oracle), SQLAlchemy will approximate this behavior at the result level so that a reasonable amount of behavioral neutrality is provided. Note that not all databases/DBAPIs support RETURNING. For those backends with no support, an exception is raised upon compilation and/or execution. For those who do support it, the functionality across backends varies greatly, including restrictions on executemany() and other statements which return multiple rows. Please read the documentation notes for the database in use in order to determine the availability of RETURNING. .. seealso:: :meth:`.ValuesBase.return_defaults` - an alternative method tailored towards efficient fetching of server-side defaults and triggers for single-row INSERTs or UPDATEs. z9return_defaults() is already configured on this statementzThe returning() method does not currently support multiple additive calls. The existing RETURNING clause being replaced by new columns.N)_return_defaultsrr6 _returningrwarnr+colss r! returningzUpdateBase.returninglsZl   )K  ?  I+    r#*c^||j}|j||f|i|_dS)aAdd a table hint for a single table to this INSERT/UPDATE/DELETE statement. .. note:: :meth:`.UpdateBase.with_hint` currently applies only to Microsoft SQL Server. For MySQL INSERT/UPDATE/DELETE hints, use :meth:`.UpdateBase.prefix_with`. The text of the hint is rendered in the appropriate location for the database backend in use, relative to the :class:`_schema.Table` that is the subject of this statement, or optionally to that of the given :class:`_schema.Table` passed as the ``selectable`` argument. The ``dialect_name`` option will limit the rendering of a particular hint to a particular backend. Such as, to add a hint that only takes effect for SQL Server:: mytable.insert().with_hint("WITH (PAGLOCK)", dialect_name="mssql") :param text: Text of the hint. :param selectable: optional :class:`_schema.Table` that specifies an element of the FROM clause within an UPDATE or DELETE to be the subject of the hint - applies only to certain backends. :param dialect_name: defaults to ``*``, if specified as the name of a particular dialect, will apply these hints only when that dialect is in use. N)r)_hintsunion)r+text selectable dialect_names r! with_hintzUpdateBase.with_hints7@  Jk''*l)CT(JKK r#)NrJ)__name__ __module__ __qualname____doc____visit_name__r_execution_optionsrMr immutabledictrLr4 _prefixesnamed_with_columnrDr8r=r@rBpropertyrrIrQrr#r!rrsON"N#6<< t T  ! !FI!5!5!5F    --- 8D) $ $D??[?B"L"L"L["L"L"Lr#rc\eZdZdZdZdZdZdZdZdZ dZ e dZ e dZ dS) ValuesBasezTSupplies support for :meth:`.ValuesBase.values` to INSERT and UPDATE constructs. values_baseFNct||_||\|_|_|r||dSdSr)rr)r8r7_has_multi_parameters_setup_prefixes)r+r)valuesprefixess r!__init__zValuesBase.__init__sa'.. 6:6M6M 7 7 33  +   * * * * * + +r#cj|jtjd|jr|rtjd|r0t |dkrtjd|d}ni}|j#||\|_|_n|jrlt|j|_||\}|_|jstjd|j |np|j |_||\}|_|jrtjd|j ||r7|jrtjd|j |dSdS) a&Specify a fixed VALUES clause for an INSERT statement, or the SET clause for an UPDATE. Note that the :class:`_expression.Insert` and :class:`_expression.Update` constructs support per-execution time formatting of the VALUES and/or SET clauses, based on the arguments passed to :meth:`_engine.Connection.execute`. However, the :meth:`.ValuesBase.values` method can be used to "fix" a particular set of parameters into the statement. Multiple calls to :meth:`.ValuesBase.values` will produce a new construct, each one with the parameter list modified to include the new parameters sent. In the typical case of a single dictionary of parameters, the newly passed keys will replace the same keys in the previous construct. In the case of a list-based "multiple values" construct, each new list of values is extended onto the existing list of values. :param \**kwargs: key value pairs representing the string key of a :class:`_schema.Column` mapped to the value to be rendered into the VALUES or SET clause:: users.insert().values(name="some name") users.update().where(users.c.id==5).values(name="some name") :param \*args: As an alternative to passing key/value parameters, a dictionary, tuple, or list of dictionaries or tuples can be passed as a single positional argument in order to form the VALUES or SET clause of the statement. The forms that are accepted vary based on whether this is an :class:`_expression.Insert` or an :class:`_expression.Update` construct. For either an :class:`_expression.Insert` or :class:`_expression.Update` construct, a single dictionary can be passed, which works the same as that of the kwargs form:: users.insert().values({"name": "some name"}) users.update().values({"name": "some new name"}) Also for either form but more typically for the :class:`_expression.Insert` construct, a tuple that contains an entry for every column in the table is also accepted:: users.insert().values((5, "some name")) The :class:`_expression.Insert` construct also supports being passed a list of dictionaries or full-table-tuples, which on the server will render the less common SQL syntax of "multiple values" - this syntax is supported on backends such as SQLite, PostgreSQL, MySQL, but not necessarily others:: users.insert().values([ {"name": "some name"}, {"name": "some other name"}, {"name": "yet another name"}, ]) The above form would render a multiple VALUES statement similar to:: INSERT INTO users (name) VALUES (:name_1), (:name_2), (:name_3) It is essential to note that **passing multiple values is NOT the same as using traditional executemany() form**. The above syntax is a **special** syntax not typically used. To emit an INSERT statement against multiple rows, the normal method is to pass a multiple values list to the :meth:`_engine.Connection.execute` method, which is supported by all database backends and is generally more efficient for a very large number of parameters. .. seealso:: :ref:`execute_multiple` - an introduction to the traditional Core method of multiple parameter set invocation for INSERTs and other statements. .. versionchanged:: 1.0.0 an INSERT that uses a multiple-VALUES clause, even a list of length one, implies that the :paramref:`_expression.Insert.inline` flag is set to True, indicating that the statement will not attempt to fetch the "last inserted primary key" or other defaults. The statement deals with an arbitrary number of rows, so the :attr:`_engine.ResultProxy.inserted_primary_key` accessor does not apply. .. versionchanged:: 1.0.0 A multiple-VALUES INSERT now supports columns with Python side default values and callables in the same way as that of an "executemany" style of invocation; the callable is invoked for each row. See :ref:`bug_3288` for other details. The :class:`_expression.Update` construct supports a special form which is a list of 2-tuples, which when provided must be passed in conjunction with the :paramref:`_expression.update.preserve_parameter_order` parameter. This form causes the UPDATE statement to render the SET clauses using the order of parameters given to :meth:`_expression.Update.values`, rather than the ordering of columns given in the :class:`_schema.Table`. .. versionadded:: 1.0.10 - added support for parameter-ordered UPDATE statements via the :paramref:`_expression.update.preserve_parameter_order` flag. .. seealso:: :ref:`updates_order_parameters` - full example of the :paramref:`_expression.update.preserve_parameter_order` flag .. seealso:: :ref:`inserts_and_updates` - SQL Expression Language Tutorial :func:`_expression.insert` - produce an ``INSERT`` statement :func:`_expression.update` - produce an ``UPDATE`` statement Nz,This construct already inserts from a SELECTz3This construct already has multiple parameter sets.rzWOnly a single dictionary/tuple or list of dictionaries/tuples is accepted positionally.r-zDCan't mix single-values and multiple values formats in one statementz   % & )E   4yy1}}'DQAAA ? "''** **) *"&t"7"7040G0G0J0J-4-1+3 &&q))))"&/"6"6"8"8040G0G0J0J-4--+3&&q)))  /) /'% &&v..... / /r#cN|jrtjd|pd|_dS)a Make use of a :term:`RETURNING` clause for the purpose of fetching server-side expressions and defaults. E.g.:: stmt = table.insert().values(data='newdata').return_defaults() result = connection.execute(stmt) server_created_at = result.returned_defaults['created_at'] When used against a backend that supports RETURNING, all column values generated by SQL expression or server-side-default will be added to any existing RETURNING clause, provided that :meth:`.UpdateBase.returning` is not used simultaneously. The column values will then be available on the result using the :attr:`_engine.ResultProxy.returned_defaults` accessor as a dictionary, referring to values keyed to the :class:`_schema.Column` object as well as its ``.key``. This method differs from :meth:`.UpdateBase.returning` in these ways: 1. :meth:`.ValuesBase.return_defaults` is only intended for use with an INSERT or an UPDATE statement that matches exactly one row. While the RETURNING construct in the general sense supports multiple rows for a multi-row UPDATE or DELETE statement, or for special cases of INSERT that return multiple rows (e.g. INSERT from SELECT, multi-valued VALUES clause), :meth:`.ValuesBase.return_defaults` is intended only for an "ORM-style" single-row INSERT/UPDATE statement. The row returned by the statement is also consumed implicitly when :meth:`.ValuesBase.return_defaults` is used. By contrast, :meth:`.UpdateBase.returning` leaves the RETURNING result-set intact with a collection of any number of rows. 2. It is compatible with the existing logic to fetch auto-generated primary key values, also known as "implicit returning". Backends that support RETURNING will automatically make use of RETURNING in order to fetch the value of newly generated primary keys; while the :meth:`.UpdateBase.returning` method circumvents this behavior, :meth:`.ValuesBase.return_defaults` leaves it intact. 3. It can be called against any backend. Backends that don't support RETURNING will skip the usage of the feature, rather than raising an exception. The return value of :attr:`_engine.ResultProxy.returned_defaults` will be ``None`` :meth:`.ValuesBase.return_defaults` is used by the ORM to provide an efficient implementation for the ``eager_defaults`` feature of :func:`.mapper`. :param cols: optional list of column key names or :class:`_schema.Column` objects. If omitted, all column expressions evaluated on the server are added to the returning list. .. versionadded:: 0.9.0 .. seealso:: :meth:`.UpdateBase.returning` :attr:`_engine.ResultProxy.returned_defaults` z1RETURNING is already configured on this statementTN)rErr6rDrGs r!return_defaultszValuesBase.return_defaultss;J ? )C !% r#)rRrSrTrUrVr5r`r2rf_post_values_clauserdrrbrprr#r!r]r]s%%#N!&! % F+++y/y/[y/vH-H-[H-H-H-r#r]cVeZdZdZdZdZ d dZdZed dZ e fd Z dS) InsertzRepresent an INSERT construct. The :class:`_expression.Insert` object is created using the :func:`_expression.insert()` function. .. seealso:: :ref:`coretutorial_insert_expressions` insertTNFc t||||||_dx|_|_d|_||_||_||||_ dS)aConstruct an :class:`_expression.Insert` object. Similar functionality is available via the :meth:`_expression.TableClause.insert` method on :class:`_schema.Table`. :param table: :class:`_expression.TableClause` which is the subject of the insert. :param values: collection of values to be inserted; see :meth:`_expression.Insert.values` for a description of allowed formats here. Can be omitted entirely; a :class:`_expression.Insert` construct will also dynamically render the VALUES clause at execution time based on the parameters passed to :meth:`_engine.Connection.execute`. :param inline: if True, no attempt will be made to retrieve the SQL-generated default values to be provided within the statement; in particular, this allows SQL expressions to be rendered 'inline' within the statement without the need to pre-execute them beforehand; for backends that support "returning", this turns off the "implicit returning" feature for the statement. If both `values` and compile-time bind parameters are present, the compile-time bind parameters override the information specified within `values` on a per-key basis. The keys within `values` can be either :class:`~sqlalchemy.schema.Column` objects or their string identifiers. Each key may reference one of: * a literal data value (i.e. string, number, etc.); * a Column object; * a SELECT statement. If a ``SELECT`` statement is specified which references this ``INSERT`` statement's table, the statement will be correlated against the ``INSERT`` statement. .. seealso:: :ref:`coretutorial_insert_expressions` - SQL Expression Tutorial :ref:`inserts_and_updates` - SQL Expression Tutorial NF) r]rdr?rf select_names#include_insert_from_select_defaultsinlinerE_validate_dialect_kwargsrD) r+r)rbrxr@rcrIrp dialect_kws r!rdzInsert.__init__smv D%::: *.. d'380 # %%j111 /r#c $|j|jfSdSNr)rfr+rms r! get_childrenzInsert.get_childrenDs ; "K> !2r#c|jrtjd|d|D\|_|_||_d|_||_t||_ dS)a Return a new :class:`_expression.Insert` construct which represents an ``INSERT...FROM SELECT`` statement. e.g.:: sel = select([table1.c.a, table1.c.b]).where(table1.c.c > 5) ins = table2.insert().from_select(['a', 'b'], sel) :param names: a sequence of string column names or :class:`_schema.Column` objects representing the target columns. :param select: a :func:`_expression.select` construct, :class:`_expression.FromClause` or other construct which resolves into a :class:`_expression.FromClause`, such as an ORM :class:`_query.Query` object, etc. The order of columns returned from this FROM clause should correspond to the order of columns sent as the ``names`` parameter; while this is not checked before passing along to the database, the database would normally raise an exception if these column lists don't correspond. :param include_defaults: if True, non-server default values and SQL expressions as specified on :class:`_schema.Column` objects (as documented in :ref:`metadata_defaults_toplevel`) not otherwise specified in the list of names will be rendered into the INSERT and SELECT statements, so that these values are also included in the data to be inserted. .. note:: A Python-side default that uses a Python callable function will only be invoked **once** for the whole statement, and **not per row**. .. versionadded:: 1.0.0 - :meth:`_expression.Insert.from_select` now renders Python-side and SQL expression column defaults into the SELECT statement for columns otherwise not included in the list of column names. .. versionchanged:: 1.0.0 an INSERT that uses FROM SELECT implies that the :paramref:`_expression.insert.inline` flag is set to True, indicating that the statement will not attempt to fetch the "last inserted primary key" or other defaults. The statement deals with an arbitrary number of rows, so the :attr:`_engine.ResultProxy.inserted_primary_key` accessor does not apply. z0This construct already inserts value expressionscFi|]}t|tSr)r r )rns r! z&Insert.from_select..s& 6 6 61^A   6 6 6r#TN) r7rr6r8r`rvrxrwrrf)r+namesrfinclude_defaultss r! from_selectzInsert.from_selectJsd ? )B 7;6M6M 6 6 6 6 67 7 33" 3C0*622 r#c |j|_|jt|j|_dSdSr)r7rjrfrr+cloner<s r!_copy_internalszInsert._copy_internalss</..00 ; " --DKKK # "r#)NFNNNF)T) rRrSrTrUrVr5rdr~rrrrrr#r!rsrss  N!%  B0B0B0B0H =3=3=3[=3~%+......r#rscjeZdZdZdZ d dZdZefdZe dZ e d Z dS) UpdatezRepresent an Update construct. The :class:`_expression.Update` object is created using the :func:`update()` function. rkNFc  | |_t||||||_||_|t ||_nd|_||_|| ||_ dS)a;Construct an :class:`_expression.Update` object. E.g.:: from sqlalchemy import update stmt = update(users).where(users.c.id==5).\ values(name='user #5') Similar functionality is available via the :meth:`_expression.TableClause.update` method on :class:`_schema.Table`:: stmt = users.update().\ where(users.c.id==5).\ values(name='user #5') :param table: A :class:`_schema.Table` object representing the database table to be updated. :param whereclause: Optional SQL expression describing the ``WHERE`` condition of the ``UPDATE`` statement; is equivalent to using the more modern :meth:`~Update.where()` method to specify the ``WHERE`` clause. :param values: Optional dictionary which specifies the ``SET`` conditions of the ``UPDATE``. If left as ``None``, the ``SET`` conditions are determined from those parameters passed to the statement during the execution and/or compilation of the statement. When compiled standalone without any parameters, the ``SET`` clause generates for all columns. Modern applications may prefer to use the generative :meth:`_expression.Update.values` method to set the values of the UPDATE statement. :param inline: if True, SQL defaults present on :class:`_schema.Column` objects via the ``default`` keyword will be compiled 'inline' into the statement and not pre-executed. This means that their values will not be available in the dictionary returned from :meth:`_engine.ResultProxy.last_updated_params`. :param preserve_parameter_order: if True, the update statement is expected to receive parameters **only** via the :meth:`_expression.Update.values` method, and they must be passed as a Python ``list`` of 2-tuples. The rendered UPDATE statement will emit the SET clause for each referenced column maintaining this order. .. versionadded:: 1.0.10 .. seealso:: :ref:`updates_order_parameters` - full example of the :paramref:`_expression.update.preserve_parameter_order` flag If both ``values`` and compile-time bind parameters are present, the compile-time bind parameters override the information specified within ``values`` on a per-key basis. The keys within ``values`` can be either :class:`_schema.Column` objects or their string identifiers (specifically the "key" of the :class:`_schema.Column`, normally but not necessarily equivalent to its "name"). Normally, the :class:`_schema.Column` objects used here are expected to be part of the target :class:`_schema.Table` that is the table to be updated. However when using MySQL, a multiple-table UPDATE statement can refer to columns from any of the tables referred to in the WHERE clause. The values referred to in ``values`` are typically: * a literal data value (i.e. string, number, etc.) * a SQL expression, such as a related :class:`_schema.Column`, a scalar-returning :func:`_expression.select` construct, etc. When combining :func:`_expression.select` constructs within the values clause of an :func:`_expression.update` construct, the subquery represented by the :func:`_expression.select` should be *correlated* to the parent table, that is, providing criterion which links the table inside the subquery to the outer table being updated:: users.update().values( name=select([addresses.c.email_address]).\ where(addresses.c.user_id==users.c.id).\ as_scalar() ) .. seealso:: :ref:`inserts_and_updates` - SQL Expression Language Tutorial N) r2r]rdr?rEr _whereclauserxryrD) r+r) whereclauserbrxr@rcrIrppreserve_parameter_orderrzs r!rdzUpdate.__init__sb*B&D%::: #  " 0 = =D   $D   %%j111 /r#c $|j|jfSdSr|rr}s r!r~zUpdate.get_children   (%' '2r#c h||jfi||_|j|_dSr)rr7rjrs r!rzUpdate._copy_internalss8!E$"3::r::/..00r#c|j)t|jt||_dSt||_dS)aReturn a new update() construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where` support multiple-table forms, including database-specific ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that don't have multiple-table support, a backend agnostic approach to using multiple tables is to make use of correlated subqueries. See the linked tutorial sections below for examples. .. seealso:: :ref:`tutorial_1x_correlated_updates` :ref:`multi_table_updates` :ref:`multi_table_deletes` Nrr r r+rs r!wherez Update.where$N,   ( $!#3K#@#@!!D   !1 = =D   r#cpg}ttj|j}|dh}|j`t |jD]K}||js||| |jL| |dd|S)Nr-r) r%sql_utiltables_from_leftmostr)rr intersection _cloned_setappendrkri)r+froms all_tablesseenitems r! _extra_fromszUpdate._extra_fromsAs(7 CCDD 1    (%d&788 . .(()9::'LL&&& D,---- Z^$$$ r#)NNFNNNFF) rRrSrTrUrVrdr~rrrrr[rrr#r!rrsN  !&{0{0{0{0z %+1111 >>[>8  X   r#rcbeZdZdZdZ d dZdZedZe dZ e fdZ dS) DeletezRepresent a DELETE construct. The :class:`_expression.Delete` object is created using the :func:`delete()` function. deleteNc ||_t||_||_|r|||t ||_nd|_||dS)a=Construct :class:`_expression.Delete` object. Similar functionality is available via the :meth:`_expression.TableClause.delete` method on :class:`_schema.Table`. :param table: The table to delete rows from. :param whereclause: Optional SQL expression describing the ``WHERE`` condition of the ``DELETE`` statement; is equivalent to using the more modern :meth:`~Delete.where()` method to specify the ``WHERE`` clause. .. seealso:: :ref:`deletes` - SQL Expression Tutorial N)r?rr)rErar rry)r+r)rr@rIrcrzs r!rdzDelete.__init__]sx6 '.. #  +   * * *  " 0 = =D   $D  %%j11111r#c $|j|jfSdSr|rr}s r!r~zDelete.get_childrenrr#c|j)t|jt||_dSt||_dS)aAdd the given WHERE clause to a newly returned delete construct. Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where` support multiple-table forms, including database-specific ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that don't have multiple-table support, a backend agnostic approach to using multiple tables is to make use of correlated subqueries. See the linked tutorial sections below for examples. .. seealso:: :ref:`tutorial_1x_correlated_updates` :ref:`multi_table_updates` :ref:`multi_table_deletes` Nrrs r!rz Delete.whererr#cg}|jh}|j`t|jD]K}||js||||jL|Sr)r)rrrrrrk)r+rrrs r!rzDelete._extra_fromss{ |   (%d&788 . .(()9::'LL&&& D,---- r#c ,||jfi||_dSrrrs r!rzDelete._copy_internalss%!E$"3::r::r#)NNNN) rRrSrTrUrVrdr~rrr[rrrrr#r!rrRsN   '2'2'2'2R >>[>8  X %+;;;;;;r#rN)rUrrbaserrrrelementsrr r r r r rOrrrrrrr]rsrrrr#r!rs^ $$$$$$&&&&&&######******,,,,,,######rLrLrLrLrL M; MrLrLrLjY-Y-Y-Y-Y-Y-Y-Y-x^.^.^.^.^.Z^.^.^.B~~~~~Z~~~Bf;f;f;f;f;Zf;f;f;f;f;r#PK!Csf0s0s$__pycache__/compiler.cpython-311.pycnu[ |oildZddlZddlZddlZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd lm Z d d lm Z d dlmZegdZejdejZejdejZdeddDdgZejdejZejdejZejdejZejdejZejdejZddddddZiejdej d ej!d!ej"d"ej#d#ej$d$ej%d%ej&d$ej'd&ej(d'ej)d(ej*d)ej+d*ej,d+ej-d,ej.d-ej/d.iej0d/ej1d0ej2d1ej3d2ej4d3ej5d4ej6d5ej7d6ej8d7ej9d8ej:d9ej;d:ej<d;ej=d<ej>d=ej?d>ej@d?ejAd@ejBdAejCdBiZDejEdCejFdDejGdEejHdFejIdGejJdHejKdIejLdJejMdKejNdLejOdMejPdNejQdOejRdPiZSdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`ZTe jUjVdae jUjWdbe jUjXdce jUjYdde jUjZdee jUj[dfiZ\Gdgdhe]Z^Gdidjej_ej`e]ZaGdkdle jbZcGdmdnedZeGdodpe^ZfGdqdrefZgGdsdte^ZhGdudveaZiGdwdxeiZjGdydze]ZkdS){a]Base SQL and DDL compiler implementations. Classes provided include: :class:`.compiler.SQLCompiler` - renders SQL strings :class:`.compiler.DDLCompiler` - renders DDL (data definition language) strings :class:`.compiler.GenericTypeCompiler` - renders type specification strings. To generate user-defined SQL strings, see :doc:`/ext/compiler`. N)crud)elements) functions) operators)schema) selectable)sqltypes)visitors)exc)util)^allanalyseanalyzeandanyarrayasasc asymmetric authorizationbetweenbinarybothcasecastcheckcollatecolumn constraintcreatecross current_date current_role current_timecurrent_timestamp current_userdefault deferrabledescdistinctdoelseendexceptfalseforforeignfreezefromfullgrantgrouphavingilikein initiallyinner intersectintoisisnulljoinleadingleftlikelimit localtimelocaltimestampnaturalnewnotnotnullnulloffoffsetoldononlyororderouteroverlapsplacingprimary referencesrightselect session_usersetsimilarsome symmetrictablethentotrailingtrueunionuniqueuserusingverbosewhenwherez ^[A-Z0-9_$]+$z^[A-Z0-9_ $]+$c,h|]}t|S)str).0xs N/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/compiler.py rss;;;c!ff;;; $z5^(?:RESTRICT|CASCADE|SET NULL|NO ACTION|SET DEFAULT)$z^(?:DEFERRED|IMMEDIATE)$z%(? z >= z = z IS DISTINCT FROM z IS NOT DISTINCT FROM z || z MATCH z NOT MATCH z IN z NOT IN ,  FROM  AS  IS z IS NOT z COLLATE zEXISTS DISTINCT zNOT zANY zALL z DESCz ASCz NULLS FIRSTz NULLS LASTcoalesce CURRENT_DATE CURRENT_TIMECURRENT_TIMESTAMP CURRENT_USER LOCALTIMELOCALTIMESTAMPrandomsysdate SESSION_USERUSERCUBEROLLUPz GROUPING SETSmonthdayyearsecondhourdoyminutequarterdowweekepoch milliseconds microseconds timezone_hourtimezone_minute)rrrrrrrrrrrrrrrUNIONz UNION ALLEXCEPTz EXCEPT ALL INTERSECTz INTERSECT ALLceZdZdZdZdZejZ ddejfdZ ej dddZ dZ e dZd Zd Zdd Ze d Zd ZdZdS)CompiledaRepresent a compiled SQL or DDL expression. The ``__str__`` method of the ``Compiled`` object should produce the actual text of the statement. ``Compiled`` objects are specific to their underlying database dialect, and also may or may not be specific to the columns referenced within a particular set of bind parameters. In no case should the ``Compiled`` object be dependent on the actual values of those bind parameters, even though it may reference those values as defaults. Nc||_||_|jj|_||_|r|j||_|@||_|j|_|jr |j |_ |j |jfi||_ dSdS)a|Construct a new :class:`.Compiled` object. :param dialect: :class:`.Dialect` to compile against. :param statement: :class:`_expression.ClauseElement` to be compiled. :param bind: Optional Engine or Connection to compile this statement against. :param schema_translate_map: dictionary of schema names to be translated when forming the resultant SQL .. versionadded:: 1.1 .. seealso:: :ref:`schema_translating` :param compile_kwargs: additional kwargs that will be passed to the initial call to :meth:`.Compiled.process`. N) dialectbindidentifier_preparerpreparerschema_translate_map_with_schema_translate statementsupports_execution can_execute_execution_optionsexecution_optionsprocessstring)selfrrrrcompile_kwargss rr__init__zCompiled.__init__s@   8 $8!   M@@$DM  &DN(;D  F)2)E&&$,t~HHHHDKKK ! rtz0.7zThe :meth:`.Compiled.compile` method is deprecated and will be removed in a future release. The :class:`.Compiled` object now runs its compilation within the constructor, and this method does nothing.cdS)z;Produce the internal string representation of this element.Nrnrs rrcompilezCompiled.compileDs  rtcp|jr||||Stj|jN)r_execute_compiledr ObjectNotExecutableErrorr)r connection multiparamsparamss rr_execute_on_connectionzCompiled._execute_on_connectionOs8   ?//k6JJ J.t~>> >rtct)zReturn a Compiled that is capable of processing SQL expressions. If this compiler is one, it would likely just return 'self'. NotImplementedErrorrs rr sql_compilerzCompiled.sql_compilerU"###rtc |j|fi|Sr_compiler_dispatch)robjkwargss rrrzCompiled.process_s%s%d55f555rtc|jpdS)z3Return the string text of the generated SQL or DDL.)rrs rr__str__zCompiled.__str__bs{ b rtct)zReturn the bind params for this compiled object. :param params: a dict of string/object pairs whose values will override bind values compiled in to the statement. rrrs rrconstruct_paramszCompiled.construct_paramsgrrtc*|S)z0Return the bind params for this compiled object.rrs rrrzCompiled.paramsqs$$&&&rtcn|j}|tjdd||||S)zExecute this compiled object.Nz>This Compiled object is not bound to any Engine or Connection.2aficode)rr UnboundExecutionErrorr)rrres rrexecutezCompiled.executevsL I 9+!  ""4f===rtc@|j|i|S)zJExecute this compiled object and return the result's scalar value.)rscalar)rrrs rrrzCompiled.scalars't|[3F33::<< > >=====rtrc"eZdZdZdZdZdZdS) TypeCompilerz2Produces DDL specification for TypeEngine objects.z visit_\w+c||_dSr)r)rrs rrrzTypeCompiler.__init__s  rtc |j|fi|Srrrtype_kws rrrzTypeCompiler.processs'u'33333rtN)rrrr ensure_kwargrrrnrtrrrrs=<<L44444rtrcTeZdZdZdZdZd dZedZedZ dZ d S) _CompileLabelz;lightweight label object which acts as an expression.Label.label)elementnamernc8||_||_|f|z|_dSr)rr _alt_names)rcolr alt_namess rrrz_CompileLabel.__init__s"  &9,rtc|jjSr)r proxy_setrs rrrz_CompileLabel.proxy_sets |%%rtc|jjSr)rtypers rrrz_CompileLabel.types |  rtc |Srrn)rrs rr self_groupz_CompileLabel.self_groups rtN)rn) rrrr__visit_name__ __slots__rrrrrrnrtrrrrs}EEN!I---- &&X&!!X!rtrceZdZdZdZdS)prefix_anon_mapacA map that creates new keys for missing key access. Considers keys of the form " " to produce new symbols "_", where "index" is an incrementing integer corresponding to . Inlines the approach taken by :class:`sqlalchemy.util.PopulateDict` which is otherwise usually used for this type of operation. c|dd\}}||d}|dz||<|dzt|z}|||<|S)N r_)splitgetro)rkeyidentderivedanonymous_countervalues rr __missing__zprefix_anon_map.__missing__sa99S!,, HHWa00)A-W # $5 6 66S  rtN)rrrrr rnrtrrrrs-rtrceZdZdZeZeZdxZxZ Z dZ dZ dZ dZ dZ dZ dZ dZ dZ dZ dxZZ ddZedZedZejd Zejd Z d Z!ej"d Z#d Z$edZ%ddZ&edZ'ej(ddZ)dZ*ddZ+ ddZ, ddZ- ddZ.dZ/ ddZ0dZ1dZ2dZ3dZ4dZ5dZ6d Z7 dd!Z8d"Z9d#Z:d$Z;d%Zd(Z?d)Z@d*ZAd+ZBd,ZCd-ZDdd.ZEd/ZFd0ZGd1ZH dd3ZId4ZJd5ZKd6ZLd7ZMd8ZNd9ZOd:ZPd;ZQd<ZR dd=ZSd>ZTd?ZUd@ZVdAZWdBZX ddCZYdDZZdEZ[ej"dFZ\dGZ]dHZ^dIZ_dJZ`dKZadLZbdMZcdNZddOZedPZfdQZgdRZh ddSZidTZjdUZkdVZldWZmdXZn ddYZo ddZZp dd[Zqd\Zrdd]Zsd^Ztd_Zu dd`ZvdaZwdbZxdcZyddZzdeZ{dfZ|dgZ}ej~dhefdiefgZddjZ ddkZdlZdmZdnZdoZdpZdqZdrZdsZdtZduZdvZdwZ ddxZddyZdzZdd{Zd|Zd}Zd~ZddZej"dZdZdZddZdZdZdZdS) SQLCompilerz~Default implementation of :class:`.Compiled`. Compiles :class:`_expression.ClauseElement` objects into SQL strings. FNTrnc L||_|pt|dd|_i|_t j|_g|_g|_|j |_ |j rg|_ |j dk|_ t|j |_d|_|jp|j|_t%|_i|_t+j|||fi||js|js|jr|jr |j|_|j r|j r|dSdSdS)aConstruct a new :class:`.SQLCompiler` object. :param dialect: :class:`.Dialect` to be used :param statement: :class:`_expression.ClauseElement` to be compiled :param column_keys: a list of column names to be compiled into an INSERT or UPDATE statement. :param inline: whether to generate INSERT statements as "inline", e.g. not formatted to return any generated defaults :param kwargs: additional keyword arguments to be consumed by the superclass. inlineFr{N) column_keysgetattrrbindsr column_dict bind_namesstack_result_columns positional positiontup paramstyle_numeric_bindsBIND_TEMPLATES bindtemplatectes label_lengthmax_identifier_lengthranon_maptruncated_namesrrisinsertisupdateisdelete _returning returning_apply_numbered_params)rrrrrrs rrrzSQLCompiler.__init__s_&'C 8U C C  *,, "", ? B!D ")"4 "AD *7+=>   AG$A  ())  "$==f=== M 2!] 2.2m 2" 2'1DN ? *t2 *  ' ' ) ) ) ) ) * * * *rtc |jddS#t$r.}tjtd|Yd}~dSd}~wwxYw)aReturn the current 'executable' that is being compiled. This is currently the :class:`_sql.Select`, :class:`_sql.Insert`, :class:`_sql.Update`, :class:`_sql.Delete`, :class:`_sql.CompoundSelect` object that is being compiled. Specifically it's assigned to the ``self.stack`` list of elements. When a statement like the above is being compiled, it normally is also assigned to the ``.statement`` attribute of the :class:`_sql.Compiler` object. However, all SQL constructs are ultimately nestable, and this attribute should never be consulted by a ``visit_`` method, as it is not guaranteed to be assigned nor guaranteed to correspond to the current statement being compiled. .. versionadded:: 1.3.21 For compatibility with previous versions, use the following recipe:: statement = getattr(self, "current_executable", False) if statement is False: statement = self.stack[-1]["selectable"] For versions 1.4 and above, ensure only .current_executable is used; the format of "self.stack" may change. r z$Compiler does not have a stack entryreplace_contextN)r IndexErrorrraise_)ries rrcurrent_executablezSQLCompiler.current_executableZs}< :b>,/ /    KABB "           s A #AA c:t|j|jzSr)listinsert_prefetchupdate_prefetchrs rrprefetchzSQLCompiler.prefetchsD(4+??@@@rtcrtj|_i|_d|_|jr i|_dSdS)zInitialize collections related to CTEs only if a CTE is located, to save on the overhead of these collections otherwise. FN)r OrderedDictr ctes_by_namectes_recursivercte_positionalrs rr_init_cte_statezSQLCompiler._init_cte_statesF$&& # ? %"$D    % %rtc#@K|j|j}}gdc|_|_ |jr|jd}d|d<nd}|j|jfV|r|d||c|_|_dS#|r|d||c|_|_wxYw)z;special API to support the use case of 'nested result sets'Fr(Tneed_result_map_for_nestedN)r_ordered_columnsrpop)rresult_columnsordered_columnsentrys rr_nested_resultzSQLCompiler._nested_results   !(79%3d3 z  26:233&(== = = = 8 6777 8D $"7"7"7 8 6777 8D $"7    s ,A55(Bcvtjdtjdfd|j|_dS)Nrz \[_POSITION\]cFttjSr)rornext)mposcounts rrz4SQLCompiler._apply_numbered_params..sDIh,?,?(@(@rt) itertoolscountresubr)rrFs @rrr&z"SQLCompiler._apply_numbered_paramss<?1%%f @@@@$+   rtcXtdfdjDDS)Nc3(K|] \}}|||fVdSrrn)rprr s rr z/SQLCompiler._bind_processors..s@   U %L!      rtc3pK|]0}j||jjfV1dSr)rr_cached_bind_processorr)rp bindparamrs rrrNz/SQLCompiler._bind_processors..sZ OI.N99$,GGrt)dictrrs`rr_bind_processorszSQLCompiler._bind_processorssX    "&       rtc2t|jdkSNr)lenrrs rr is_subqueryzSQLCompiler.is_subquerys4:""rtc|Srrnrs rrrzSQLCompiler.sql_compilers rtcl|ri}|jD]}|j|}|j|vr||j||<)||vr ||||<9|rG|jr@|r tjd|j|fzdtjd|jzd|jr |j||<|j||<|Si}|jD]}}|rG|jr@|r tjd|j|fzdtjd|jzd|jr|j||j|<h|j||j|<~|S)z5return a dictionary of bind parameter keys and valuesz@A value is required for bind parameter %r, in parameter group %dcd3xrz)A value is required for bind parameter %r)rrrequiredr InvalidRequestErrorcallableeffective_valuer )rr _group_number_checkpdrQrs rrrzSQLCompiler.construct_paramss 3 B!_ / / y1=F**%im4BtHHV^^%d|BtHH/ 2/$ !54(}m<="( "5G'm,!' '/(8BtHH(BtHHIB!_ E E  i0 $ !54(}m<="( "5G'm,!' %E5>5NBty1225>_Bty122Irtc.|dS)zoReturn the bind param dictionary embedded into this compiled object, for those values that are present.F)r`rrs rrrzSQLCompiler.paramss$$E$222rtzsqlalchemy.engine.resultc@|j|jS)z(utility method used for unit tests only.)ResultMetaData_create_result_mapr)rresults rrrezSQLCompiler._create_result_maps$778LMMMrtcdS)zCalled when a SELECT statement has no froms, and no FROM clause is to be appended. Gives Oracle a chance to tack on a ``FROM DUAL`` to the string output. rrnrs rr default_fromzSQLCompiler.default_froms rrtc 4d|jj|fi|zdzS)N()rr)rgroupingasfromrs rrvisit_groupingzSQLCompiler.visit_groupings+8X%8HHHHH3NNrtc (|jrw|jjrk|jdd}|j\}}}|r|}n|}|jj} | 8| j|vr/| || jr|jj|d<|j|jfd|i|S)Nr(r render_label_as_labelwithin_columns_clause) rrsupports_simple_order_by_label_label_resolve_dictr_order_by_label_elementrshares_lineager) rrrrrr with_cols only_froms only_cols resolve_dict order_by_elems rrvisit_label_referencez!SQLCompiler.visit_label_references : <$,E <B 5J/9/M ,Iz9$ )) ( $OCM)!&,66!00 !347O;+t| O  "7    rtc d|js||jS|jdd}|j\}}} |r||j}n ||j}||d<|j|fd|i|S#t $r2} t j|jtj d| Yd} ~ dSd} ~ wwxYw)Nr(r rqrrzECan't resolve label reference for ORDER BY / GROUP BY / DISTINCT etc.)err) rr _text_clausertrKeyErrorr_no_text_coercionr CompileError) rrrrrr rwrxryrkes rrvisit_textual_label_referencez)SQLCompiler.visit_textual_label_reference6sz 6<< 455 5Z^L1 +5+I( :y $ 1 10/2F* +4<+@DJ      & +            sA33 B/='B**B/c |o| }||u}|s|rBt|jtjr|d|j} n|j} |rn|"|| |j|| f|jz|j|jj|fddd|ttj z|j || zS|r|j || S|jj|fddi|S)NcolidentT)rrwithin_label_clauserrF) isinstancerr_truncated_label_truncated_identifierrrrr OPERATORSras_r format_label) rradd_to_result_maprrrrqrrender_label_with_asrender_label_only labelnames rr visit_labelzSQLCompiler.visit_labelRsa " =*=&= 2U:  ' 4 '%*h&?@@ ' 66z5:NN !J   ,!!JI&)99J 1 0*.(,  IM* +-,,UI>>?  =--eY?? ?35=3,157 rtc*tjd)Nz:Cannot compile Column object until its 'name' is assigned.r rrr s rr_fallback_column_namez!SQLCompiler._fallback_column_names K   rtc |jx}}|||}|j}|s0t|tjr|d|}|||||||jf|j|r| |}n|j |}|j }| |r|j s|S|j |} | r|j | dz} nd} |j} t| tjr|d| } | |j | zdz|zS)Nr.ralias)rr is_literalrrrrrrescape_literal_columnrquoteranamed_with_columnschema_for_object quote_schema) rr r include_tablerr orig_namerraeffective_schema schema_prefix tablenames rr visit_columnzSQLCompiler.visit_columns";&y <--f55D&  @jx/HII @--j$??D  (  i&$ !;V[     ---d33DD=&&t,,D  = =U5L=K#}>>uEE  #M../?@@3F !#  I)X%>?? K 66w JJ  4=#6#6y#A#AACG$N Nrtc @|j|jSr)rformat_collation collation)rrrs rrvisit_collationzSQLCompiler.visit_collations}--g.?@@@rtc |jSrr)r fromclausers rrvisit_fromclausezSQLCompiler.visit_fromclauses rtc |jSrr)rindexrs rr visit_indexzSQLCompiler.visit_indexs zrtc F||d<|jjj|jfi|S)Ntype_expression)r type_compilerrr)r typeclausers rrvisit_typeclausezSQLCompiler.visit_typeclauses/ * 1t|)1*/HHRHHHrtcJ|jjr|dd}|SN%%%r_double_percentsreplacertexts rrpost_process_textzSQLCompiler.post_process_text' = ) +<<T**D rtcJ|jjr|dd}|Srrrs rrrz!SQLCompiler.escape_literal_columnrrtc fd}jsd_tdt|jS)Nc|d}|jvrjj|fiSj|fiSrU)r8 _bindparamsrbindparam_string)rErrr textclauses rr do_bindparamz2SQLCompiler.visit_textclause..do_bindparams]771::Dz---#t|J$:4$@GGBGGG,t,T88R888rtTc,|dSrU)r8)rEs rrrGz.SQLCompiler.visit_textclause..saggajjrt)r isplaintextBIND_PARAMS_ESCrK BIND_PARAMSrr)rrrrs``` rrvisit_textclausezSQLCompiler.visit_textclauses 9 9 9 9 9 9 9z $#D "" OOd44Z_EE     rtc Z|j }|r|jn |jd}|p1|dko|ddp|dd}|r:|jx|_|_|jD]} || d|j |j|j fi|} |r|rd| z} | S) Nr(rneed_result_map_for_compoundFr;Trrr(%s)) r_default_stack_entryrrr<_textual_ordered_columns column_argsr_add_to_result_mapr) rtafcompound_indexrnparensrtoplevelr@populate_result_mapcrs rrvisit_text_as_fromzSQLCompiler.visit_text_as_fromsz>-5I))4:b>  >!#EII yy5u==    D !-_   *.&*&= t|CK..2..  !f !D=D rtc dS)NNULLrnrexprrs rr visit_nullzSQLCompiler.visit_nullvrtc "|jjrdSdS)Nre1rsupports_native_booleanrs rr visit_truezSQLCompiler.visit_trues < / 63rtc "|jjrdSdS)Nr10rrs rr visit_falsezSQLCompiler.visit_falses < / 73rtc |j}|d}nt|j}|dfd|jDD}|jrjjrd|z}|S)Nrc3K|]}||V dSrrnrpss rrrNz/SQLCompiler.visit_clauselist..s>          rtc34K|]}|jfiVdSrr)rprrrs rrrNz/SQLCompiler.visit_clauselist..sJ56$$T00R00rtzVALUES )operatorrrBclauses _tuple_valuesrtuple_in_values)r clauselistrseprs` ` rrvisit_clauselistzSQLCompiler.visit_clauselist s! ;CCJ/0Cxx  :D:L       # $ (D $t#D rtc d}|j||jj|fi|dzz }|jD].\}}|d|j|fi|zdz|j|fi|zdzz }/|j|d|jj|fi|zdzz }|dz }|S)NzCASE rzWHEN z THEN zELSE END)r rwhenselse_)rclauserrqcondrfs rr visit_casezSQLCompiler.visit_cases  < # 00@@@@3F FA"L  LD& )$)$99&99:,&+D;;F;;<  AA < # 9&,9$II&IIICO A U rtc (|jj|fi|Sr)typed_expressionr)r type_coercers rrvisit_type_coercezSQLCompiler.visit_type_coerce.s >{+>tJJrJJJrtc Xd|jj|fi|d|jj|fi|dS)NzCAST(rrk)rrr)rrrs rr visit_castzSQLCompiler.visit_cast1sN *DK *4 : :6 : : : : .DO .t > >v > > > >  rtc d|dtjurdn|dtjurdnj|ddkr6|jtjt |dfi|dn(|jtj|dfi|dd|dtjurdn|dtjurdnj|ddkr6|jtjt |dfi|dn(|jtj|dfi|dS) NrzUNBOUNDED PRECEDINGz CURRENT ROWz PRECEDINGz FOLLOWINGr}rzUNBOUNDED FOLLOWING)rRANGE_UNBOUNDED RANGE_CURRENTrliteralabs)rrange_rs rr_format_frame_clausez SQLCompiler._format_frame_clause7sayH444 " !ayH222ay1}}t|H,S^^<<CCCCCCFFt|H,VAY77>>2>>>>A A AayH444 " !ayH222ay1}}t|H,S^^<<CCCCCCFFt|H,VAY77>>2>>>>A A  rtc $|jrdj|jfiz}n |jrdj|jfiz}nd}|jjfiddfdd|jfd|jffD|r|gngzdS) NzRANGE BETWEEN %szROWS BETWEEN %sz OVER (rc ^g|])\}}|t||d|jfi*S)Nz BY )rVr)rpwordrrrs rr z*SQLCompiler.visit_over..]sc%f)c&kk) tt6V6tFFvFFFH *))rt PARTITIONORDERrk)rr rowsrrrB partition_byorder_by)roverrrs` ` rr visit_overzSQLCompiler.visit_overNs! ; '*C$*C ++%++FFY &)B)B **#**FFF ,DL +D ; ;F ; ; ; ; HH%d&78 $-0) &-F882 /      rtc V|jj|fi|d|jj|fi|dS)Nz WITHIN GROUP (ORDER BY rk)rrr)r withingrouprs rrvisit_withingroupzSQLCompiler.visit_withingroupjsN 2K  24 B B6 B B B B 3K 3D C CF C C C C  rtc V|jj|fi|d|jj|fi|dS)Nz FILTER (WHERE rk)funcr criterion)r funcfilterrs rrvisit_funcfilterzSQLCompiler.visit_funcfilterpsM .JO .t > >v > > > > 3J 3D C CF C C C C  rtc |j|j|j}d|d|jj|fi|dS)NzEXTRACT(rrk) extract_maprfieldrr)rextractrrs rr visit_extractzSQLCompiler.visit_extractvsQ $$W]GMBB EE +GL +D ; ;F ; ; ; ;  rtc >|||j|jd|jtd|jzd}|r ||fi|St|jdr |jrdz n\|jj sttj rj ndzdfd|jDgzdj|fi|izS)Nrnz visit_%s_funcz%(expr)srcg|]R}j|sttjrj|n|SSrn)r_requires_quotes_illegal_charsrr quoted_namer)rptokrrs rrr z.SQLCompiler.visit_function..so  =GGLL!%dH,@AA! ++C000! rtr)rrrlower FUNCTIONSr __class__ _has_argsrr$rrr%rrB packagenamesfunction_argspec)rrrrdisprs` @rrvisit_functionzSQLCompiler.visit_function}sv  (  diB B B Bt_ty/@/@@$GG  @4'''' '==66D )>'J&Dy}CCDII!$(<==DM''---  j(88 $0&   ..t>>v>>? @ @rtc 6||jSr)visit_sequencesequence)r next_valuers rrvisit_next_value_funcz!SQLCompiler.visit_next_value_funcs"":#6777rtc :td|jjz)Nz2Dialect '%s' does not support sequence increments.rrr)rr1rs rrr0zSQLCompiler.visit_sequences$! @l    rtc (|jj|fi|Sr) clause_exprr)rrrs rrr,zSQLCompiler.function_argspecs 2t24BB6BBBrtrc j }|rjn jd}|p|dko|dd}j|d|d||dj|j} d| zdzfd t|jD} | j |fitdd iz } | j |fiz } | |j dus |j durj|fipd z } jr|r| z} jdr |rd | zd zS| S)Nr(rrFcorrelate_froms asfrom_froms)r9r:r rrc3BK|]\}}|jfd|dVdS)F)rnrrNr)rpirrnrrs rrrNz4SQLCompiler.visit_compound_select..sl  Aq%$! #$         rtrnrrjrkrn)rrrappendcompound_keywordskeywordrB enumerateselectsgroup_by_clauserRorder_by_clause _limit_clause_offset_clause limit_clauser_render_cte_clauser=) rcsrnrrrrr@need_result_mapr?rs ` ` ` rrvisit_compound_selectz!SQLCompiler.visit_compound_selectsz>-5I))4:b>" a  A 8%@@  #():#; %n 5 0?      (,,RZ88g #))      &bj11       $$RII4+H+Hv+H+H+HIII $$R226222  T ) JR->d-J 0!!"////   9 4 4**,,t3D r  f :# #KrtcPd|jd||rd|znd}t||dS)Nvisit_rr)rr)r operator_ qualifier1 qualifier2attrnames rr_get_operator_dispatchz"SQLCompiler._get_operator_dispatchsE     J * 2C*   2  tXt,,,rtc |jrg|jrtjd||jdd}|r|||jfi|S|j|t |jfi|S|jrL||jdd}|r|||jfi|S|j|t |jfi|Stjd)NzFUnary expression does not support operator and modifier simultaneouslyunaryrmodifierz,Unary expression has no operator or modifier)rrTr rrQ _generate_generic_unary_operatorr _generate_generic_unary_modifier)rrSrr-s rr visit_unaryzSQLCompiler.visit_unarys@ > ~ &2..D tE5>88R88888R888 rtc z|js |jjr|j|jfi|Sd|j|jfi|zS)Nz%s = 1_is_implicitly_booleanrrrrrrrrs rrvisit_istrue_unary_operatorz'SQLCompiler.visit_istrue_unary_operators[  * B|3 B 4<66266 6ldl7?AAbAAA Artc |js |jjrd|j|jfi|zSd|j|jfi|zS)NNOT %sz%s = 0rYr[s rrvisit_isfalse_unary_operatorz(SQLCompiler.visit_isfalse_unary_operators`  * B|3 Bldl7?AAbAAA Aldl7?AAbAAA Artc Jd||tjzS)Nr^)override_operator) visit_binaryrmatch_oprrrrs rrvisit_notmatch_op_binaryz$SQLCompiler.visit_notmatch_op_binarys.$++ i&8,    rtc.tjddS)NzThe IN-predicate was invoked with an empty sequence. This results in a contradiction, which nonetheless can be expensive to evaluate. Consider alternative strategies for improved performance.)rwarnrs rr_emit_empty_in_warningz"SQLCompiler._emit_empty_in_warnings%  3     rtc |jjrdS|jjr|||j|jkS)Nz1 != 1r_use_static_in_warn_on_empty_inrhrrDrds rrvisit_empty_in_op_binaryz$SQLCompiler.visit_empty_in_op_binary%sN < & <8|- .++---<< v{ :;; ;rtc |jjrdS|jjr|||j|jkS)Nz1 = 1rjrds rrvisit_empty_notin_op_binaryz'SQLCompiler.visit_empty_notin_op_binary-sN < & <7|- .++---<< v{ :;; ;rtc:td|jjz)Nz3Dialect '%s' does not support empty set expression.r5)r element_typess rrvisit_empty_set_exprz SQLCompiler.visit_empty_set_expr5s$! Al    rtc |jrCt|jtjr$t|jtjrd|d<|p|j}||dd}|r |||fi|S t|}|j ||fi|S#t$r4}tj tj|||Yd}~dSd}~wwxYw)NT literal_bindsrr))ansi_bind_rulesrrDr BindParameterrZrrQr_generate_generic_binaryrrr,r UnsupportedCompilationError) rrraeager_groupingrrMr-opstringr~s rrrbzSQLCompiler.visit_binary;s+   '6;(>?? '6<)?@@ ' #'B %8 **9hEE  M4 00R00 0 M$Y/5t4VXLLLLL     3D)DD$' s8 B C)C  Cc (|j|jfi|Sr)r sql_functionr[s rr&visit_function_as_comparison_op_binaryz2SQLCompiler.visit_function_as_comparison_op_binaryVst|G077B777rtc |jjr*|j|jfi|dz|j|jfi|zS|j|jfi|dz|j|jfi|zS)Nz %% r~)rrrrDrZrds rrvisit_mod_binaryzSQLCompiler.visit_mod_binaryYs = )  V[//B//$,v|22r223  V[//B//$,v|22r223 rtc J|j|d<|j|d|jzdzfi|S)Nryr)ryrwrzr[s rrvisit_custom_op_binaryz"SQLCompiler.visit_custom_op_binarygsF'6 ,t, S8,,s2  68   rtc 0|j||jdzfi|SNr)rUrzr[s rrvisit_custom_op_unary_operatorz*SQLCompiler.visit_custom_op_unary_operatorms34t4 X&,  02   rtc 0|j|d|jzfi|Sr)rVrzr[s rrvisit_custom_op_unary_modifierz*SQLCompiler.visit_custom_op_unary_modifierrs34t4 S8,,  02   rtc |dd}d|d<|jj|fd|i||z|jj|fd|i|z}|r|rd|z}|S)N _in_binaryFTryr)rrDrrZ)rrrzryrrrs rrrwz$SQLCompiler._generate_generic_binarywsVVL%00 < *FK *  %3 79   .fl-%379     !. !D=D rtc .||jj|fi|zSrrlrrSrzrs rrrUz,SQLCompiler._generate_generic_unary_operators%:%-:4FF2FFFFrtc .|jj|fi||zSrrlrs rrrVz,SQLCompiler._generate_generic_unary_modifiers$/u}/;;;;hFFrtcBtjdtjS)Nz'%')r)rliteral_columnr STRINGTYPErs rr_like_percent_literalz!SQLCompiler._like_percent_literals&uH4GHHHHrtc |}|j}||j||_|j||fi|Sr_cloner__add__rZvisit_like_op_binaryrrrrpercents rrvisit_contains_op_binaryz$SQLCompiler.visit_contains_op_binarysW,v|44<..t|<>$-00 x==4,q0 0 0*..{A>>GS!2Q!6:::;g,,qrr"#  18! D  - - I4=k401rtc||jzSr)rrrs rr _anonymizezSQLCompiler._anonymizejsdm##rtc |jr2|||n|j||r d|_d|zS|jd|izS)NTz([EXPANDING_%s])r)rr=rcontains_expanding_parametersr)rrpositional_namesrrs rrrzSQLCompiler.bindparam_stringmso ? .+ ''---- ''---  615D .%, ,$~5 5rtc ||d<t|jtjrd|j}n|j}d}d} |jvrJj|} || u} || jvs|| urd}n)| |jvr j| =ntj d|z|s|rO|j D|j } |j j} t| tjrd| } n|} d} |r|j|<d|j j vr:djvr1jd|j j di_| jvrj| fi|| sP|jvrF|jrd_j||} |jrt|jt,jr|j}n4t|jt,jr|jjd}nJdt5j|jD}| d d fd |Dzz } jrgx|d <j|<| d j ||j!fi|d|jj"fddi|z } |j#r| dj ||j#fi|zz } | j|<|r|s| rj||S| rij|| } j$|rj%|}| &|z } | Sj||SdS)N visiting_cterTFz5Multiple, unrelated CTEs found with the same name: %r autocommitrcg|]}||Srrnrprs rrr z)SQLCompiler.visit_cte..s%"""=(==rtrrc3LK|]}j|VdSr)r format_column)rprrs rrrNz(SQLCompiler.visit_cte..sG"" %!M77>>""""""rtrr rnr)'r9rrrrrr6 _restatesrr r _cte_aliasrrrrf visit_cte recursiver7r format_aliasoriginalr SelectCompoundSelectrAr unique_list inner_columnsrBrr8_generate_prefixes _prefixesr _suffixes_requires_quotesrget_render_as_alias_suffix)rcternashint fromhintsrrcte_name is_new_cteembedded_in_current_named_cte existing_cte pre_alias_ctecte_pre_alias_namer col_source recur_colss` rrrzSQLCompiler.visit_cte{s !$~ ch 9 : : 11'38DDHHxH (-% t( ( (,X6L,8L,H )l,,,|0C0C" ..Il++&(*23  *Z *~) # %(^%8"0(2KLL)-)C)C!3**&!$ %)" : &*-D h ' >>> (>>>)-)?)E)E$ck&D('**&DI--}77777%' &#TY*>*>=/*.D'}11#x@@=!#, 0ABB%%(\ #CL*2KLL%%(\%9!%< $u""!%!1*2J!K!K"""J F """")3"""D?OLNNF-.1DS1I+D+CII&IIII3CL3%)-3=C"9$"9S]##.4##D"& #  A A"? A}11#x@@@! A}11#7IJJ=11(;;=#}228<4TDDVDD Drtc .d|d<d|j|fi|zS)NTlateralz LATERAL %s)r)rrrs rr visit_lateralzSQLCompiler.visit_laterals,9 .d.w=="====rtc |j|fddi|d|j|fi|}|j|d|jj|fi|zz }|S)NrnTz TABLESAMPLE z REPEATABLE (%s))r _get_methodrseed)r tablesamplernrrs rrvisit_tablesamplezSQLCompiler.visit_tablesamples D [ < < < < < < < 8K # # % % 8 D D D D D    ' &3  3D??B?? D rtc d|zS)Nrrn)ralias_name_texts rrrz&SQLCompiler.get_render_as_alias_suffix)s ''rtcB|j||||fdSr)rr=)rkeynamerobjectsrs rrrzSQLCompiler._add_to_result_map,s( ##WdGU$CDDDDDrtc  jj} | jr%|s|r!| } |rfd} nd} n} |rj} nd} |s| } nt tjr'| urt| j j f} nL| } nH||rt| |j f} n*|rwt tj r]jsVjOt jt js0t| tjj jf} nt tjsat tjrjr@t/drt t0jrt| j} n6| ur0t| tjj jf} n| } ||| | jfi|S)z.produce labeled columns present in a select().c@||f|z|dSr)r)rrrrr rs rrrz;SQLCompiler._label_select_column..add_to_result_mapEs5++y7':ErtN)rrr)rrr_has_column_expressioncolumn_expressionrrrLabelrrr _key_label ColumnClauserrar r _as_truncatedr TextClauseUnaryExpressionwraps_column_expressionhasattrrFunction anon_labelupdater) rr[r rrncolumn_clause_argsrrrneed_column_expressionsrcol_exprr result_exprs ` ` rr_label_select_columnz SQLCompiler._label_select_column/s{'' 55  & ) # )': )--f55H" ) %)!!H" )$($;!!$(!$0 #"KK  / /. #v%%+fkfn5F '  D '$6+<*>KK ! #68#899! #%! # (v|Z->??)(&v{33!:-KK 68#677 #vx'?@@ #1  #FF++ #fi&899 #(&2CDDKK V # #(&v{33!:-KK #K!!"7/ "   .{-dII6HIIIrtcF|||}|r|d|zz }|Sr)get_from_hint_text)rsqltextrahintrhinttexts rrrz!SQLCompiler.format_from_hint_texts2**5$77  & sX~ %GrtcdSrrn)rbyfromss rrget_select_hint_textz SQLCompiler.get_select_hint_texttrtcdSrrnrrars rrr%zSQLCompiler.get_from_hint_textr,rtcdSrrnr.s rrget_crud_hint_textzSQLCompiler.get_crud_hint_textr,rtc,d|SrrB)r hint_textss rrget_statement_hint_textz#SQLCompiler.get_statement_hint_textsxx ###rtc6iigfd|S)zRewrite any "a JOIN (b JOIN c)" expression as "a JOIN (select * from b JOIN c) AS anon", to support databases that can't parse a parenthesized join correctly (i.e. sqlite < 3.7.16). c| dvr d|S| vr |S|x} |<|jr|jrt|jt jrt| |jfi||_ |jfi|}t j |j gd }|j D]}|j |_|j|_t#t%|jj j |j }|||j j<|||j j<|||jj j<|||jj j<t' dD]\}}||vr|| d|< d|||_ |jfi||_n|jrd|d<|jdd i|nh|jrR|jrK|dddk} | r id|d<|jdd i|| r d=n|jdd i||S) Nr(T) use_labelsselect_containertransform_clueclone inside_selectrn)r is_selectable_is_joinrrZr FromGrouping_reset_exportedrDrrrrrrr_labelrRzipr0itemsronclause_is_from_container_copy_internals _is_selectrr=) rrnewelemrZ selectable_rtranslate_dictkvbarrier_selectclonedcolumn_translatevisits rrrOz=SQLCompiler._transform_select_for_nested_joins..visits*2...'+G44F""g&(/(8(8 8GfWo%D ;$D ;w}j.EFFD ; '')))$uW\88R88 gm22r22(/]O%''%&&A#$5AL vAHH!% -/??""6Au}126Au}23=Hw}49:>Iw}4:;!!1"!5!;!;!=!=>>DDDAqN**3A2C(,Q/ $++N;;; + #(5)9#@#@R#@#@  + ;(:#$''::e:r::::& ;7+= ;FF+T226HH "0$++B///'6#$''::e:r:::!-(,''::e:r:::Nrtrn)rr[rMrNrOs @@@rr"_transform_select_for_nested_joinsz.SQLCompiler._transform_select_for_nested_joinssO4O O O O O O O buV}}rtctd|jDtfd|jDfd|jD|_dS)Nc3(K|] }|j|fVdSrrrs rrrNzESQLCompiler._transform_result_map_for_nested_joins..s:  "#Q\1       rtc36K|]}|j|fVdSrrS)rpr inner_cols rrrNzESQLCompiler._transform_result_map_for_nested_joins..s/LL!)AL)1-LLLLLLrtcXg|]&\}}}}||tfd|D|f'S)c<g|]}||Srnr)rprds rrr zQSQLCompiler._transform_result_map_for_nested_joins...s%???3quuS#???rttuple)rprrobjstyprYs rrr zFSQLCompiler._transform_result_map_for_nested_joins..sW   $T4$????$???@@# F   rt)rRrr)rr[transformed_selectrYrUs @@rr&_transform_result_map_for_nested_joinsz2SQLCompiler._transform_result_map_for_nested_joinss  '9'G      LLLLv7KLLL L L    (,(<   rtr9r:c|j }|r|jn |jd}|d}|d}|r-|s+|||d}n|||}|S)Nr(r9r:rnexplicit_correlate_fromsimplicit_correlate_froms)rr_get_display_froms difference) rr[rnrrr@r9r:fromss rr_display_froms_for_selectz%SQLCompiler._display_froms_for_select s z>-5I))4:b> 12^,  ' --)8)C)C ***, .EE--)8)5.E rtc Fjo| oj o jj } | r)} j| f|||dd| } j } | rjn jd}| p+|ddp|ddx|dkrdsd| vr| d=| rr| | S ||}|  ddd d } j r# \}}|r| |d zz } nd}jr| jjfi| z } | jfi| z } d fd jDD}rU|St%t'djDd|jDfdjD_| |||| } jr0fdjD}|r| d |zz } jr| r| z} jr| d jjfi| zz } jds|r |rd| zdzS| S)NT)rnrrrnested_join_translationr(rFr;rr)rrrzSELECT rcg|]}||Srrnrs rrr z,SQLCompiler.visit_select..us)   } }}rtc Ng|]!\}}||"S))rr r#) rprr rnrr rr[rs rrr z,SQLCompiler.visit_select..wsY   !D&))'&,C*   rtcg|]\}}|Srnrnrprrs rrr z,SQLCompiler.visit_select..sHHHksDTHHHrtcg|]\}}|Srnrnrns rrr z,SQLCompiler.visit_select..s,'S$rtcXg|]&\}}}}||tfd|D|f'S)c3DK|]}||VdSrrX)rpo translates rrrNz6SQLCompiler.visit_select...s1!C!C!)--1"5"5!C!C!C!C!C!CrtrZ)rprrrrrss rrr z,SQLCompiler.visit_select..sW$$$)CsEdE!C!C!C!Cs!C!C!CCCUK$$$rtc:g|]\}}|djjfv|S*rr)rp dialect_namehtrs rrr z,SQLCompiler.visit_select..s<&\2C):#;;;;;;rtrjrk)r7rrsupports_right_nested_joinsrP visit_selectrrr__setup_select_stackcopyr_hints_setup_select_hintsrrget_select_precolumns_columns_plus_namesrRrAr_compose_select_body_statement_hintsr4rrGrr=)rr[rnrrrriselect_wraps_forrrneeds_nested_translationr^rrr@rf hint_textbyfromr per_dialectrr rrss``` @@@@rrr{zSQLCompiler.visit_select%sb   =++ =J =L<< ! $ !%!H!H"" %4$"#-(, Dz>-5I))4:b>  >yy7?? >yy5u== 5 A  "'  # ,':f'D'D*+ # " ;;.K((HH#[[]]!!$)E J J    =  $ 8 8 @ @ Iv ( C'F   P +D+FF4DOOOO OD **6<      "  #3#?HHV-GHHH+;+OI$$$$-1-A$$$D (( &-    " H*0*AK  Hd::;GGGG 9 4 4**,,t3D    C1$1(,2 D r  g 6 :# #Krtctfd|jD}|}||fS)Nc xg|]6\\}}}|djjfv||d|dizf7S)rvrT)rrrr)rpfrom_rr(rs rrr z3SQLCompiler._setup_select_hints..sn    /$UGhsDL$5666 u77T7JJKL 766rt)rRr~rBr+)rr[rrs` rrrzSQLCompiler._setup_select_hintssh     39-2E2E2G2G       --f55 &  rtcR|d}|d}|r-|s+|||d}n|||}ttj|}||} || |d} |j| |S)Nr9r:rnra)r:r9r )rdrer]r _from_objectsrfrr=) rr[r@rnrr9r:rfnew_correlate_fromsall_correlate_froms new_entrys rrr|zSQLCompiler._setup_select_stacks 12^,  ' --)8)C)C ***, .EE--)8)5.E "*":E"BCC177HH02   )$$$ rtc|d|z }|rY|dz }|jr'|dfd|Dz }n=|dfd|Dz }n|z }|j|jjfi}|r|d|zz }|jjr|j|fiz }|j|jjfi}|r|d|zz }|j jr|j |fiz }|j |j |j |fiz }|j|j|fiz }|S)Nrz FROM c2g|]}|jfddS)Trnrr)rpfrrrs rrr z4SQLCompiler._compose_select_body..sT-, )-CIrtc0g|]}|jfddiS)rnTr)rprrrs rrr z4SQLCompiler._compose_select_body..sC-,TII$I&IIrtz WHERE z HAVING )rBr~rh _whereclauser_group_by_clauserrB_having_order_by_clauserCrDrErF_for_update_argfor_update_clause)rrr[rrfrrts` `` rrrz SQLCompiler._compose_select_bodys  -(((  ( J D}  "'  !& D%%'' 'D   *6#6tFFvFFA ( a'  " * ; (D(::6:: :D > %11$AA&AAA ) q((  " * ; (D(::6:: :D  ,$0 %D%f7777 7D  ! - *D*6<. s]  $ #|t|7H'H'H &F %d 1 1b 1 1'H'H'H'H  rtr2)rstmtprefixesrrs` ` rrrzSQLCompiler._generate_prefixes sZ     (0        cMF rtc(jr.tfdjDgjz_jdz}|ddjDz }|dz }|S)Nc*g|]}j|Srn)r8)rprrs rrr z2SQLCompiler._render_cte_clause..$ s!CCC#T(-CCCrtr, cg|]}|Srnrn)rptxts rrr z2SQLCompiler._render_cte_clause..( s C C C C C Crtz )rsumrrget_cte_preambler7rBvalues)rcte_texts` rrrGzSQLCompiler._render_cte_clause! s ? CCCCCCCRHH"#  (()<==CFKK C C 0@0@0B0B C C CDDDErtc|rdSdS)NzWITH RECURSIVEWITHrn)rrs rrrzSQLCompiler.get_cte_preamble, s  ##6rtc |jrdpdS)zcCalled when building a ``SELECT`` statement, position is just before column list. rr) _distinctrr[rs rrrz!SQLCompiler.get_select_precolumns2 s /K525rtc :|jj|fi|}|rd|zSdS)z5allow dialects to customize how GROUP BY is rendered.z GROUP BY r)rr)rr[rgroup_bys rrrBzSQLCompiler.group_by_clause9 9>6*=dIIbII  (* *2rtc :|jj|fi|}|rd|zSdS)z5allow dialects to customize how ORDER BY is rendered.z ORDER BY r)rr)rr[rrs rrrCzSQLCompiler.order_by_clauseB rrtc dS)Nz FOR UPDATErnrs rrrzSQLCompiler.for_update_clauseK s}rtc*tjd)Nz@RETURNING is not supported by this dialect's statement compiler.r)rrreturning_colss rrreturning_clausezSQLCompiler.returning_clauseN s ,   rtc d}|j|d|j|jfi|zz }|j%|j|dz }|d|j|jfi|zz }|S)Nrz LIMIT z LIMIT -1z OFFSET )rDrrE)rr[rrs rrrFzSQLCompiler.limit_clauseT s}   + K,$,v/C"J"Jr"J"JJ JD  ,#+ % Jf.C!J!Jr!J!JJ JD rtc P|s|r|j|}|r@|r>|j|dz|j|jz} n|j|j} |r"||vr|| ||||} | SdS)Nrr)rrrrrr) rrarnrrr use_schemarrrs rr visit_tablezSQLCompiler.visit_table^ s  V #}>>uEE  6. 6M../?@@m))%*556 m))%*55 Ui//00 % 0&J2rtc |jrd}n |jrd}nd}|jj|fddi||z|jj|fddi|zdz|jj|fi|zS)Nz FULL OUTER JOIN z LEFT OUTER JOIN z JOIN rnT ON )r6isouterrDrrZrC)rrBrnr join_types rr visit_joinzSQLCompiler.visit_join{ s 9 !+II \ !+II I (DI ( E Ed Ef E E +dj+DHHHHH I /dm.t>>v>>  ? rtctfd|jD}|j|vr(||j||jd}||fS)NcDg|]\\}}}|djjfv||fSrurw)rprarrrs rrr z1SQLCompiler._setup_crud_hints.. sF   /$UGisDL$5666 "666rtT)rRr~rBrar)rr table_text dialect_hintss` rr_setup_crud_hintszSQLCompiler._setup_crud_hints s    37;3D3D3F3F      : & &33DJ dj(A4Jj((rtc |j }|jtt|dtj||tjfi|}|s9|jjs-|jjs!tj d|jj z|j r6|jj s!tj d|jj z|d}n|}|j|jj}d}|jr||j||jfi|z }|dz }|j} |jr||| \} } || z }|s|s'|ddfd |Dzz }|js|jr2|||jp|j} |jr|d | zz }nd} |jN|j|jfi|} |jr+|r)|jjr|d || z }np|d | zz }ng|s|r|d z }n]|j r&|d dd|Dzz }n0dd|D} |d| zz }|r| |_ |j!|j|j!fi|}|r|d |zz }| r|js|d | zz }|jr%|r#|jjs||z}|j"d|rd|zdzS|S)Nr9r:r zWThe '%s' dialect with current database version settings does not support empty inserts.zcThe '%s' dialect with current database version settings does not support in-place multirow inserts.rzINSERT zINTO z (%s)rcFg|]}|dS)r)r)rprrs rrr z,SQLCompiler.visit_insert.. s+JJJ!''!--JJJrtrz %sz DEFAULT VALUESz VALUES %sc3ZK|]&}ddd|DzV'dS)rrc3&K|] }|dV dS)rNrnrs rrrNz5SQLCompiler.visit_insert... s&'E'E!'E'E'E'E'E'ErtNr2)rpcrud_param_sets rrrNz+SQLCompiler.visit_insert.. sV&dii'E'En'E'E'EEEFrtcg|] }|d S)rrnrs rrr z,SQLCompiler.visit_insert.. s2M2M2MA1Q42M2M2Mrtz VALUES (%s)r(rjrk)#rr=r]r_setup_crud_paramsISINSERTrsupports_default_valuessupports_empty_insertr rr_has_multi_parameterssupports_multivalues_insertrrr format_tablerar~rrBr%r$rreturning_precedes_valuesr[r_insert_from_selectrcte_follows_insertrGinsert_single_values_expr_post_values_clauser=)r insert_stmtrnrr crud_paramscrud_params_singlerrrrr select_textrpost_values_clausers @rr visit_insertzSQLCompiler.visit_insert sQz> #&55 #)     - +t}  02   L8 L6  "!\./   , -<; &137<3DE "-Q  !, ="&,"F    +D+[268 D **;+<==   L 22; KKMAz   %<  GdiiJJJJ7IJJJ D > $[3 $#44T^E{/E   - /...#    )&$,t'?FF2FFKy ,X ,$,*I ,4#:#:#<#<#> >D K1J.  * 6!-/""35"" " 1000  +D$B + C** *D 9 4 4$,*I 4**,,t3D r  :# #KrtcdS)z3Provide a hook for MySQL to add LIMIT to the UPDATENrn)r update_stmts rrupdate_limit_clausezSQLCompiler.update_limit_clause strtc ,d|d<|j|fddi|S)z|Provide a hook to override the initial table clause in an UPDATE statement. MySQL overrides this. Trnrr)rr from_table extra_fromsrs rrupdate_tables_clausez SQLCompiler.update_tables_clause s-8 ,z,TEE$E"EEErtc td)z~Provide a hook to override the generation of an UPDATE..FROM clause. MySQL and MSSQL override this. zCThis backend does not support multiple-table criteria within UPDATErrrrr from_hintsrs rrupdate_from_clausezSQLCompiler.update_from_clause s" %   rtc j }|j}t|}|rJtt j|jfd|D}|}n g}|jh}j|||dd} |j r| j ||j fi|z } j ||j|fi|} tj |tjfi|} |jr|| \} } nd} | | z } | dz } |oj| dfd| Dz } js|jr/jr(| d|jp|jzz } |r j||j|| fi|} | r| d| zz } |jj|jfi|}|r| d|zz } |}|r| d|zz } js|jr/js(| d|jp|jzz } jr|r| z} jd |rd | zd zS| S) Ncg|]}|v| Srnrn)rpr main_fromss rrr z,SQLCompiler.visit_update..- s*"""!:*=*=*=*=*=rtrzUPDATE z SET rc3jK|]-}|ddz|dzV.dS)r)r=rNr)rprrrs rrrNz+SQLCompiler.visit_update..X sd   aD # #D # F F d       rtr WHERE r(rjrk)r _extra_fromsboolr]r rrarfr=rrrrrISUPDATEr~r'render_table_with_column_in_update_fromrBr%r$rrrrrrrrGr=)rrrnrrr is_multitablerender_extra_fromsr9rrrrextra_from_textrrFrrs` @@rr visit_updatezSQLCompiler.visit_update$ sz>!. [))  2Z5k6GHHIIJ""""&""" )..{;;OO!# *01O #2 /)         +D+[268 D/T. *,>  BD  - +t}  02     !(,(>(>Z)) %M::!M    JdJ        !        > [3 - d33!I;3I  .5d5!"   O .o--  # / [5<<< k4=GGBGGG!. &,-33K@@ #2 /)         +D+[268 D -- *K     !(,(>(>Z)) %M::!M   ! - d33!7  .;d;!   O .o--  # /; (;DGGBGGA & A %  ! $*H  C$//[3 D 9 4 4**,,t3D r  :# #Krtc<d|j|zS)Nz SAVEPOINT %srformat_savepointrsavepoint_stmts rrvisit_savepointzSQLCompiler.visit_savepoint s > >~ N NNNrtc<d|j|zS)NzROLLBACK TO SAVEPOINT %srrs rrvisit_rollback_to_savepointz'SQLCompiler.visit_rollback_to_savepoint s&)DM,J,J - -   rtc<d|j|zS)NzRELEASE SAVEPOINT %srrs rrvisit_release_savepointz#SQLCompiler.visit_release_savepoint s&% (F(F ) )   rt)NF)NNTF)NFFN)NT)NFTr)FTr)FFF)FFNN)FFFNNTF)FTNrFNF)FFFNT)rrrr EXTRACT_MAPrCOMPOUND_KEYWORDSr>r#r!r"rr%rrrrurr<rrr1r2rrr.r3rmemoized_instancemethodr9 contextlibcontextmanagerrAr&memoized_propertyrSrWrrr dependenciesrerhror|rrrrrrrrrrrrrrrrrrrr rrrr!r.r3r0r,rJrQrWr\r_rerhrmrorrrbr}rrrrrwrUrVrrrrrrrrrrrrrrrrrrrrrrrr rrr#rr+r%r0r4rPr_r frozensetrrgr{rr|rrrGrrrBrCrrrFrrrrrrrrrrrrr r r rnrtrrr r s  K)%**H*x( KI !&/4+ %*!O % N !%)+*Oo!#" ////b   =A&O&O&O&OPAAAIII     (>B@  $&KKK      .   8          @ @ @ @D888   CCC=>1111f--->BBBBBB      <<<<<<   >CMMMM6888            05*GGGGGG IIIAAA DDD AAA DDD AAA DDD                      $" ; ; ; ; z@@@&   &$$$6; 6 6 6 6" zAzAzAzA~ EEEEB>>>    (((EEE" %ZJZJZJZJx $$$[[[z    .4- YY[[ )NIIKK+HI8 %NNNN` ! ! !:444l    666   :      ) ) )nnnn`FFF    ddddL GGG   MMMHHHHTOOO        rtr cHeZdZdZdZdZdZdZdZdZ dZ d Z d Z d S) StrSQLCompileraA :class:`.SQLCompiler` subclass which allows a small selection of non-standard SQL features to render into a string value. The :class:`.StrSQLCompiler` is invoked whenever a Core expression element is directly stringified without calling upon the :meth:`_expression.ClauseElement.compile` method. It can render a limited set of non-standard SQL constructs to assist in basic stringification, however for more substantial custom or dialect-specific SQL constructs, it will be necessary to make use of :meth:`_expression.ClauseElement.compile` directly. .. seealso:: :ref:`faq_sql_expression_string` cdS)Nzrnrs rrrz$StrSQLCompiler._fallback_column_name srtc V|j|jfi|d|j|jfi|dS)N[])rrDrZrds rrvisit_getitem_binaryz#StrSQLCompiler.visit_getitem_binary sJ DL + + + + + + DL , , , , , ,  rtc |j||fi|Srrrds rrvisit_json_getitem_op_binaryz+StrSQLCompiler.visit_json_getitem_op_binary (t(@@R@@@rtc |j||fi|Srr rds rr!visit_json_path_getitem_op_binaryz0StrSQLCompiler.visit_json_path_getitem_op_binary r"rtc <d|j|zS)Nz)rformat_sequence)rseqrs rrr0zStrSQLCompiler.visit_sequence s*T]-J-J3-O-OOOrtctfdtj|D}dd|zS)Nc Bg|]}d|ddiSrrlrprrs rrr z3StrSQLCompiler.returning_clause.. s?     % %dAtUB ? ?   rtz RETURNING r)r_select_iterablesrB)rrrcolumnss` rrrzStrSQLCompiler.returning_clause sO    /??    dii0000rtc Tddfd|DzS)Nrrc3:K|]}|jfddVdSTrNrrprrrrs rrrNz4StrSQLCompiler.update_from_clause..* sS# #  !A  Odj O OB O O# # # # # # rtr2rs` ``rrrz!StrSQLCompiler.update_from_clause' sT# # # # # #  # # #     rtc Tddfd|DzS)Nrc3:K|]}|jfddVdSr/rr0s rrrNz:StrSQLCompiler.delete_extra_from_clause..2 sS   !A  Odj O OB O O      rtr2rs` ``rrrz'StrSQLCompiler.delete_extra_from_clause/ sTdii              rtc d|zS)Nz[%s]rnr.s rrr%z!StrSQLCompiler.get_from_hint_text7 s }rtN) rrrrrrr!r$r0rrrr%rnrtrrrr s&      AAAAAAPPP111      rtrc.eZdZejdZejdZd)dZdZdZ dZ dZ d*d Z d)d Z d Zd ZdZ d+dZdZd*dZdZdZdZdZdZdZdZdZdZdZdZdZdZ d Z!d!Z"d"Z#d#Z$d$Z%d%Z&d&Z'd'Z(d(Z)dS), DDLCompilercP|j|jd|jS)N)r)rstatement_compilerrrs rrrzDDLCompiler.sql_compiler< s-|.. L$T5N/   rtc|jjSr)rrrs rrrzDDLCompiler.type_compilerB s |))rtNcdSrrnrs rrrzDDLCompiler.construct_paramsF r,rtc |j}t|jtjr|}|j}||j}t|dkr |dd}}n|d|d}}| d|| d|| d| |j|j |j |zS)Nrrrr(rarfullname)contextrtargetrTabler}rformat_table_seqrV setdefaultrrrr)rddlrr<rpathraschs rr visit_ddlzDDLCompiler.visit_ddlI s+ cj&, / / NllnnG}H,,SZ88D4yyA~~!!Wbs!"XtAws   w . . .   x - - -   z8+@+@+L+L M M M 223=73JKKKrtcJ|j|j}d|zS)NzCREATE SCHEMA )r format_schemar)rr"rs rrvisit_create_schemazDDLCompiler.visit_create_schema\ s$,,V^<<&((rtcf|j|j}d|z}|jr|dz }|S)Nz DROP SCHEMA  CASCADE)rrFrcascade)rdroprrs rrvisit_drop_schemazDDLCompiler.visit_drop_schema` s<,,T\::& <  J D rtc |j}|j}d}|jr |d|jdzz }|d||zdzz }||}|r||dzz }|dz }d}d}|jD]}|j} ||| jo| } | ||z }d}|d | zz }| jrd }D#tj $r_} tj tj tj d |j| j| jd fz| Yd} ~ d} ~ wwxYw|||j} | r ||d z| zz }|d||zz }|S)Nz CREATE rzTABLE rjrFfirst_pkr Tz (in table '%s', column '%s'): %sr)r) _include_foreign_key_constraintsz )%s )rrrrBrcreate_table_suffixr,r primary_keyr rrr,u descriptionrargscreate_table_constraintsinclude_foreign_key_constraintspost_create_table) rr"rarrrR separatorrO create_columnr processedceconsts rrvisit_create_tablezDDLCompiler.visit_create_tableg s= ? 4 CHHU_--3 3D 800777#=="66u==  . '#- -D   #^  M"*F  LL!F,>,Ox<) (I%D &ID9,,D%$#H#    $ABB ,fk271:FG  -- -3-S.    - I$u, ,D d44U;;;; s9C  D7AD22D7Fc|j}|jrdS||}dfd|jD}|r|d|zz }|S)NrNrc3BK|]}|VdSr)rrpr!rs rrrNz2DDLCompiler.visit_create_column.. s@  )3DLL $ $      rt)rsystemget_column_specificationrB constraints)rr"rOr rr^s` rrvisit_create_columnzDDLCompiler.visit_create_column s = 4,,Vh,GG    7=7I       C%K D rtcLg}jr|jj}|||nt |fdjDddfd|DDS)Nc.g|]}|ju |v|Srn)rS)rpr omit_fkcsras rrr z8DDLCompiler.create_table_constraints.. s;   E---!92D2D2D2D2Drtz, c3K|]}||V dSrrn)rpps rrrNz7DDLCompiler.create_table_constraints.. s4  } }}}  rtc3K|]R}|j|jjrt|dd;|VSdS)N use_alterF) _create_rulersupports_alterrrrbs rrrNz7DDLCompiler.create_table_constraints.. s  +3!..t444 3 4 #:{EBB 4 Z((4333  rt)rSr=foreign_key_constraintsrer]extend_sorted_constraintsrB)rrarQreall_fkcsris`` @rrrWz$DDLCompiler.create_table_constraints s    2   u0 1 1 10 + 7 ++,LMMIII     2      }}      "-         rtcFd|j|jzS)Nz DROP TABLE rrrrrKs rrvisit_drop_tablezDDLCompiler.visit_drop_table s!;!;DL!I!IIIrtcFd|j|jzS)Nz DROP VIEW rurvs rrvisit_drop_viewzDDLCompiler.visit_drop_view s : :4< H HHHrtcL|jtjd|jzdS)Nz,Index '%s' is not associated with any table.)rar rrrrs rr_verify_index_tablezDDLCompiler._verify_index_table s1 ; "AEJN   rtTc d|j}|j}d}|jr|dz }|jt jd|d||d||j |dd fd |j Dd z }|S) NzCREATE zUNIQUE z0CREATE INDEX requires that the index have a namezINDEX include_schemarr (rc3RK|]!}j|ddV"dS)FTrrtN)rr)rprrs rrrNz1DDLCompiler.visit_create_index.. sX!))T*rtrk) rr|rrgrr r_prepared_index_namerrarB expressions)rr"rinclude_table_schemarrrs` rrvisit_create_indexzDDLCompiler.visit_create_index s   '''= <  I D : "B    % %eN % K K K K  ! ! (< "     II"-        rtcz|j}|jtjdd||dzS)Nz.DROP INDEX requires that the index have a namez DROP INDEX Tr~)rrr rr)rrKrs rrvisit_drop_indexzDDLCompiler.visit_drop_index sT  : "@ !:!: $";" "   rtc|j |j|j}nd}|r|r|j|}nd}|j|}|r|dz|z}|SNr)rarrr format_index)rrrr schema_name index_names rrrz DDLCompiler._prepared_index_name s ; "#}>>u{KK  #   . -445EFFKKK]//66  8$s*Z7Jrtcd|j|jjd||jS)N ALTER TABLE z ADD )rrrrarrr"s rrvisit_add_constraintz DDLCompiler.visit_add_constraint s@ M & &v~'; < < < < LL ( ( (  rtcd|j|jd|j|jjt jS)NzCOMMENT ON TABLE r)rrrrrcommentr Stringrs rrvisit_set_table_commentz#DDLCompiler.visit_set_table_comment sV M & &v~ 6 6 6 6   2 2&(9(9     rtcFd|j|jzS)NzCOMMENT ON TABLE %s IS NULLrurvs rrvisit_drop_table_commentz$DDLCompiler.visit_drop_table_comment! s(,t}/I/I L0 0   rtcd|j|jddd|j|jjt jS)NzCOMMENT ON COLUMN T) use_tablerr)rrrrrrr rrs rrvisit_set_column_commentz$DDLCompiler.visit_set_column_comment& sj M ' '$4 (       2 2&(9(9      rtcJd|j|jdzS)NzCOMMENT ON COLUMN %s IS NULLT)r)rrrrvs rrvisit_drop_column_commentz%DDLCompiler.visit_drop_column_comment0 s0- 0K0K LD1L1 1   rtcd|j|jz}|jj|d|jjzz }|jj|d|jjzz }|jj|d|jjzz }|jj|d|jjzz }|jj|dz }|jj|dz }|jj |d|jj zz }|jj d ur|d z }|jj |d z }|S) NzCREATE SEQUENCE %sz INCREMENT BY %dz START WITH %dz MINVALUE %dz MAXVALUE %dz NO MINVALUEz NO MAXVALUEz CACHE %dTz ORDERz CYCLE) rr&r incrementstartminvaluemaxvalue nominvalue nomaxvaluecacherTcycle)rr"rs rrvisit_create_sequencez!DDLCompiler.visit_create_sequence5 s"#dm&C&C N' '   > # / &)AA AD >  + $v~';; ;D > " . NV^%<< " . NV^%<< $ 0 N "D > $ 0 N "D >  + K&."66 6D > 4 ' ' H D >  + H D rtcFd|j|jzS)NzDROP SEQUENCE %s)rr&rrvs rrvisit_drop_sequencezDDLCompiler.visit_drop_sequenceM s!DM$A$A$,$O$OOOrtc|j}|j|j|}nd}|t jd|jzd|j|jjd||jrdpdS)Nz99 t088  e4 9     44Z@@@ rtcd}|j$|j|}||d|zz }|d|j|jddzz }|||z }|Srrrs rrvisit_column_check_constraintz)DDLCompiler.visit_column_check_constraint rrtc:t|dkrdSd}|j$j|}||d|zz }|dz }|ddfd|jr|jn|jDzz }||z }|S)Nrrrz PRIMARY KEY rrc3VK|]#}j|jV$dSrrrrr*s rrrNz;DDLCompiler.visit_primary_key_constraint.. sI# #  M   ' '# # # # # # rt) rVrrrrB_implicit_generatedcolumns_autoinc_firstr,rrs` rrvisit_primary_key_constraintz(DDLCompiler.visit_primary_key_constraint s z??a  2 ? &!]<99  # # # # 1( 00' # # #      44Z@@@ rtc  |jd}|j$|j|}||d|zz }t|jdjj}|ddfd|jDd|||ddfd |jDd z }|| |z }|| |z }|| |z }|S) Nrrrz FOREIGN KEY(rc3VK|]#}|jjV$dSr)rparentrrprrs rrrNz;DDLCompiler.visit_foreign_key_constraint.. D23qx}--rtz ) REFERENCES rc3VK|]#}|jjV$dSr)rr rrs rrrNz;DDLCompiler.visit_foreign_key_constraint.. rrtrk) rrrr0rr rarBdefine_constraint_remote_tabledefine_constraint_matchdefine_constraint_cascadesr)rr!rr remote_tablers @rrvisit_foreign_key_constraintz(DDLCompiler.visit_foreign_key_constraint sm= ? &!]<99J/003:@   II7A7J      / /L(     II7A7J       ,,Z888 // ;;; 44Z@@@ rtc,||S)z=Format the remote table clause of a CREATE CONSTRAINT clause.)r)rr!rars rrrz*DDLCompiler.define_constraint_remote_table s$$U+++rtc t|dkrdSd}|j$j|}||d|zz }|ddfd|Dzz }||z }|S)Nrrrz UNIQUE (%s)rc3VK|]#}j|jV$dSrrr*s rrrNz6DDLCompiler.visit_unique_constraint.. s5FFadm))!&11FFFFFFrt)rVrrrrBrrs` rrvisit_unique_constraintz#DDLCompiler.visit_unique_constraint s z??a  2 ? &!]<99 IIFFFF:FFF F F   44Z@@@ rtcd}|j+|d|j|jtzz }|j+|d|j|jt zz }|S)Nrz ON DELETE %sz ON UPDATE %s)ondeletervalidate_sql_phrase FK_ON_DELETEonupdate FK_ON_UPDATErr!rs rrrz&DDLCompiler.define_constraint_cascades s|   * Odm&G&G#\'' D   * Odm&G&G#\'' D rtcd}|j|jr|dz }n|dz }|j+|d|j|jtzz }|S)Nrz DEFERRABLEz NOT DEFERRABLEz INITIALLY %s)r*r<rr FK_INITIALLYrs rrrz+DDLCompiler.define_constraint_deferrability so  ,$ * %))   + Odm&G&G$l'' D rtc2d}|j |d|jzz }|S)Nrz MATCH %s)matchrs rrrz#DDLCompiler.define_constraint_match s'   ' K*"22 2D rtcd|j|jddz}|jdur|dz }n|jdur|dz }|S)NzGENERATED ALWAYS AS (%s)FTrz STOREDz VIRTUAL)rrr& persisted)r generatedrs rrvisit_computed_columnz!DDLCompiler.visit_computed_column sj)D,=,E,E  U$-F- -    $ & & I DD  E ) ) J D rtrr)FT)*rrrrrrrrrDrGrLr_rfrWrwryr|rrrrrrrrrrrrdrRrYrrrrrrrrrrrrnrtrrr5r5; s     ***LLL&)))000d     7;' ' ' ' RJJJIIIBF6                    0PPP   $&         (0,,,          rtr5c eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'd&Z(d'Z)d(Z*d)Z+d*Z,d+S),GenericTypeCompilerc dS)NFLOATrnrs rr visit_FLOATzGenericTypeCompiler.visit_FLOAT wrtc dS)NREALrnrs rr visit_REALzGenericTypeCompiler.visit_REAL rrtc ^|jdS|j dd|jizSd|j|jdzS)NNUMERICzNUMERIC(%(precision)s) precisionz!NUMERIC(%(precision)s, %(scale)s)rscalerrs rr visit_NUMERICz!GenericTypeCompiler.visit_NUMERIC J ? "9 [ +{EO.LL L6"_:: rtc ^|jdS|j dd|jizSd|j|jdzS)NDECIMALzDECIMAL(%(precision)s)rz!DECIMAL(%(precision)s, %(scale)s)rrrs rr visit_DECIMALz!GenericTypeCompiler.visit_DECIMAL rrtc dS)NINTEGERrnrs rr visit_INTEGERz!GenericTypeCompiler.visit_INTEGER& yrtc dS)NSMALLINTrnrs rrvisit_SMALLINTz"GenericTypeCompiler.visit_SMALLINT) zrtc dS)NBIGINTrnrs rr visit_BIGINTz GenericTypeCompiler.visit_BIGINT, sxrtc dS)N TIMESTAMPrnrs rrvisit_TIMESTAMPz#GenericTypeCompiler.visit_TIMESTAMP/ s{rtc dS)NDATETIMErnrs rrvisit_DATETIMEz"GenericTypeCompiler.visit_DATETIME2 rrtc dS)NDATErnrs rr visit_DATEzGenericTypeCompiler.visit_DATE5 rrtc dS)NTIMErnrs rr visit_TIMEzGenericTypeCompiler.visit_TIME8 rrtc dS)NCLOBrnrs rr visit_CLOBzGenericTypeCompiler.visit_CLOB; rrtc dS)NNCLOBrnrs rr visit_NCLOBzGenericTypeCompiler.visit_NCLOB> rrtcZ|}|jr |d|jzz }|jr |d|jzz }|S)N(%d)z COLLATE "%s")lengthr)rrrrs rr_render_string_typez'GenericTypeCompiler._render_string_typeA sB < * FU\) )D ? 6 Oeo5 5D rtc .||dS)NCHARrrs rr visit_CHARzGenericTypeCompiler.visit_CHARJ ''v666rtc .||dS)NNCHARr!rs rr visit_NCHARzGenericTypeCompiler.visit_NCHARM s''w777rtc .||dS)NVARCHARr!rs rr visit_VARCHARz!GenericTypeCompiler.visit_VARCHARP s''y999rtc .||dS)NNVARCHARr!rs rrvisit_NVARCHARz"GenericTypeCompiler.visit_NVARCHARS s''z:::rtc .||dS)NTEXTr!rs rr visit_TEXTzGenericTypeCompiler.visit_TEXTV r#rtc dS)NBLOBrnrs rr visit_BLOBzGenericTypeCompiler.visit_BLOBY rrtc .d|jr d|jzpdzS)NBINARYrrrrs rr visit_BINARYz GenericTypeCompiler.visit_BINARY\ s 5<AFU\,AGRHHrtc .d|jr d|jzpdzS)N VARBINARYrrr5rs rrvisit_VARBINARYz#GenericTypeCompiler.visit_VARBINARY_ s elDv /DJKKrtc dS)NBOOLEANrnrs rr visit_BOOLEANz!GenericTypeCompiler.visit_BOOLEANb rrtc |j|fi|Sr)r2rs rrvisit_large_binaryz&GenericTypeCompiler.visit_large_binarye tu+++++rtc |j|fi|Sr)r<rs rr visit_booleanz!GenericTypeCompiler.visit_booleanh !t!%..2...rtc |j|fi|Sr)rrs rr visit_timezGenericTypeCompiler.visit_timek r?rtc |j|fi|Sr)rrs rrvisit_datetimez"GenericTypeCompiler.visit_datetimen "t"5//B///rtc |j|fi|Sr)rrs rr visit_datezGenericTypeCompiler.visit_dateq r?rtc |j|fi|Sr)rrs rrvisit_big_integerz%GenericTypeCompiler.visit_big_integert s t --"---rtc |j|fi|Sr)rrs rrvisit_small_integerz'GenericTypeCompiler.visit_small_integerw rGrtc |j|fi|Sr)rrs rr visit_integerz!GenericTypeCompiler.visit_integerz rBrtc |j|fi|Sr)rrs rr visit_realzGenericTypeCompiler.visit_real} r?rtc |j|fi|Sr)rrs rr visit_floatzGenericTypeCompiler.visit_float st,,,,,rtc |j|fi|Sr)rrs rr visit_numericz!GenericTypeCompiler.visit_numeric rBrtc |j|fi|Srr)rs rr visit_stringz GenericTypeCompiler.visit_string rBrtc |j|fi|SrrWrs rr visit_unicodez!GenericTypeCompiler.visit_unicode rBrtc |j|fi|Srr/rs rr visit_textzGenericTypeCompiler.visit_text r?rtc |j|fi|Srr\rs rrvisit_unicode_textz&GenericTypeCompiler.visit_unicode_text r?rtc |j|fi|SrrWrs rr visit_enumzGenericTypeCompiler.visit_enum rBrtc 0tjd|z)NzKCan't generate DDL for %r; did you forget to specify a type on this Column?rrs rrrzGenericTypeCompiler.visit_null s$ #%* +   rtc N|j||jfi|Sr)r type_enginerrs rrvisit_type_decoratorz(GenericTypeCompiler.visit_type_decorator s,t|E--dl;;BBrBBBrtc |jdi|S)Nrn) get_col_specrs rrvisit_user_definedz&GenericTypeCompiler.visit_user_defined s!u!''B'''rtN)-rrrrrrrrrrr rrrrrrr"r&r)r,r/r2r6r9r<r>rArDrFrIrKrMrOrQrSrUrXrZr]r_rarrerhrnrtrrrr s      777888:::;;;777IIILLL,,,///,,,000,,,...000///,,,---/////////,,,,,,///   CCC(((((rtrceZdZdZdZdS)StrSQLTypeCompilercX|dr|jSt|)NrL) startswith_visit_unknownAttributeError)rrs rr __getattr__zStrSQLTypeCompiler.__getattr__ s- >>( # # && & %% %rtc d|jjzS)Nz%s)r)rrs rrrmz!StrSQLTypeCompiler._visit_unknown seo...rtN)rrrrormrnrtrrrjrj s2&&& /////rtrjc4eZdZdZeZeZeZ e j dZ ddZ dZdZd Zd Zd Zd Zd ZddZddZdZd dZddZddZddZejddZdZd!dZ dZ! d"dZ"d dZ#ej$dZ%dZ&dS)#IdentifierPreparerz@Handle quoting and case-folding of identifiers based on options.N"TFc||_||_|p|j|_||_|jdz|_||_||_i|_|jjdv|_ dS)asConstruct a new ``IdentifierPreparer`` object. initial_quote Character that begins a delimited identifier. final_quote Character that ends a delimited identifier. Defaults to `initial_quote`. omit_schema Prevent prepending schema name. Useful for databases that do not support schemae. r )rzrxN) r initial_quote final_quote escape_quoteescape_to_quote omit_schemaquote_case_sensitive_collations_stringsrr)rrrurvrwrzrys rrrzIdentifierPreparer.__init__ so. *&<$*<(#014&/N, $ 7< ! rtc|j|j}|j|jt j||_|Sr)r)__new____dict__rr_schema_getterr)rrpreps rrrz)IdentifierPreparer._with_schema_translate sJ~%%dn55 T]+++!'!67K!L!L rtc||j|j}|jr|dd}|S)zEscape an identifier. Subclasses should override this to provide database-dependent escaping behavior. rr)rrwrxrrr s rr_escape_identifierz%IdentifierPreparer._escape_identifier s@ d/1EFF   -MM#t,,E rtcB||j|jS)zCanonicalize an escaped identifier. Subclasses should override this to provide database-dependent unescaping behavior that reverses _escape_identifier. )rrxrwrs rr_unescape_identifierz'IdentifierPreparer._unescape_identifier s}}T143DEEErtct|5||s tjd|d|jd|S)zkeyword sequence filter. a filter for elements that are intended to represent keyword sequences, such as "INITIALLY", "INITIALLY DEFERRED", etc. no special characters should be present. .. versionadded:: 1.3 NzUnexpected SQL phrase: z (matching against rk)rr rpattern)rrregs rrrz&IdentifierPreparer.validate_sql_phrase sN  syy'9'9 ""77CKKK) rtcL|j||z|jzS)z~Quote an identifier. Subclasses should override this to provide database-dependent quoting behavior. )rurrvrs rrquote_identifierz#IdentifierPreparer.quote_identifier s0  %%e,, -  rtc|}||jvpA|d|jvp2|jt j| p||kS)z5Return True if the given identifier requires quoting.r)r'reserved_wordsillegal_initial_characterslegal_charactersrr text_type)rr lc_values rrrz#IdentifierPreparer._requires_quotessh;;== + + #Qx4:: #(..t~e/D/DEEE #E!  rtc\|jtj| S)zjReturn True if the given identifier requires quoting, but not taking case convention into account.)rrrrrs rrr$z1IdentifierPreparer._requires_quotes_illegal_chars"s((..t~e/D/DEEEErtcX|tjd||S)aConditionally quote a schema name. The name is quoted if it is a reserved word, contains quote-necessary characters, or is an instance of :class:`.quoted_name` which includes ``quote`` set to ``True``. Subclasses can override this to provide database-dependent quoting behavior for schema names. :param schema: string schema name :param force: unused .. deprecated:: 0.9 The :paramref:`.IdentifierPreparer.quote_schema.force` parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the :meth:`.IdentifierPreparer.quote` method; please refer to :class:`.quoted_name`. NzThe IdentifierPreparer.quote_schema.force parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the IdentifierPreparer.quote method; please refer to quoted_name().)rwarn_deprecatedr)rrforces rrrzIdentifierPreparer.quote_schema's:.    !   zz&!!!rtcF|tjdt|dd}|`||jvr |j|S||r|||j|<n ||j|<|j|S|r||S|S)aConditionally quote an identfier. The identifier is quoted if it is a reserved word, contains quote-necessary characters, or is an instance of :class:`.quoted_name` which includes ``quote`` set to ``True``. Subclasses can override this to provide database-dependent quoting behavior for identifier names. :param ident: string identifier :param force: unused .. deprecated:: 0.9 The :paramref:`.IdentifierPreparer.quote.force` parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the :meth:`.IdentifierPreparer.quote` method; please refer to :class:`.quoted_name`. NzThe IdentifierPreparer.quote.force parameter is deprecated and will be removed in a future release. This flag has no effect on the behavior of the IdentifierPreparer.quote method; please refer to quoted_name().r)rrrr{rr)rrrs rrrzIdentifierPreparer.quoteLs,    !   w-- = %%}U++((//1+/+@+@+G+GDM%((+0DM%(}U++  ((// /Lrtc>|jr||S|Sr)rzr)rcollation_names rrrz#IdentifierPreparer.format_collation~s%  / "::n-- -! !rtc||j}||}|js|r|||dz|z}|Sr)rrrryr)rr1rrrs rrr&z"IdentifierPreparer.format_sequenceskzz(-((11(;;  D D!,$$%566'    ' ' 1))%00E rtzsqlalchemy.sql.namingc|jtjur |||j}|dSn|j}t |tjr}|jdkr|jj p |jj }n|jj p |jj }t||kr-|d|dz dztj|ddz}n|j|||S)Nrrr)rr _NONE_NAME_constraint_name_for_tablerarrrrmax_index_name_lengthrmax_constraint_name_lengthrVrmd5_hexvalidate_identifierr)rnamingr!rmax_s rrrz$IdentifierPreparer.format_constraints ?h1 1 144J,D|t?D dH5 6 6 3(G33L6:|9 L;:|94yy4AqL)C/$,t2D2DRSS2II L , ,T 2 2 2zz$rtc,||Sr)rr{s rrrzIdentifierPreparer.format_indexs%%e,,,rtc||j}||}||}|js|r|r||dz|z}|S)z'Prepare a quoted table and schema name.Nr)rrrryr)rrarrrfrs rrrzIdentifierPreparer.format_tablesu <:DD!!11%88 HJ H3C H&&'7883>GF rtc,||S)zPrepare a quoted schema name.)rrs rrrFz IdentifierPreparer.format_schemaszz$rtc||j}t|ddsM|r6||j||dz||zS||S|r#||j||dz|zS|S)zPrepare a quoted column name.NrF)rrr)rrrrar)rr rr table_namers rrrz IdentifierPreparer.format_columns <;Dv|U33  (%% *&jj&& 'zz$'''  %% *&  rtc||}|js0|r.|r,||||dfS||dfS)z(Format table name and schema as a tuple.Fr)rryrr)rrarrs rrr?z#IdentifierPreparer.format_table_seqs 11%88 AJ A3C A!!"233!!%E!::  %%e%>>@ @rtcd|j|j||jfD\}}}tjd|||dz}|S)Nc6g|]}tj|Srn)rJrrs rrr z5IdentifierPreparer._r_identifiers..s0) ) )  IaLL) ) ) rtzM(?:(?:%(initial)s((?:%(escaped)s|[^%(final)s])+)%(final)s|([^\.]+))(?=\.|$))+)initialfinalescaped)rurvrrJr)rrr escaped_finalrs rr_r_identifiersz!IdentifierPreparer._r_identifiers s) ) " ''(899) ) ) %  J $"EmLL M   rtchj}fdd||DDS)z:Unpack 'schema.table.column'-like strings into components.c:g|]}|Srn)r)rpr<rs rrr z;IdentifierPreparer.unformat_identifiers..#s7     % %a ( (   rtcg|] \}}|p| Srnrn)rpabs rrr z;IdentifierPreparer.unformat_identifiers..%s @@@Aaf1@@@rt)rfindall)r identifiersrs` rrunformat_identifiersz'IdentifierPreparer.unformat_identifierssR      @@;)?)?@@@    rt)rsNrsTFr)T)TN)FNNF)'rrrrRESERVED_WORDSrLEGAL_CHARACTERSrILLEGAL_INITIAL_CHARACTERSrrrrrrrrrrrr$rrrr&rrrrrrrrrFrr?rrrrnrtrrrrrr s"JJ#N'!;--d33 (," " " " H   FFF$       FFF #"#"#"#"J0000d"""    ........T.//  0/ @---         $$$$LAAAA" "     rtrr)lrrrHrJrrrrrrr r r r rr]rrIrLEGAL_CHARACTERS_PLUS_SPACErangerfrrrrUNICODErrrand_or_addmulrKdivmodtruedivnegltlenegtgeeqis_distinct_fromisnot_distinct_from concat_oprc notmatch_opin_opnotin_opcomma_oprris_isnotrexists distinct_opinvany_opall_opdesc_opasc_op nullsfirst_op nullslast_oprrr$r&r'r(rGrHrrr\rhcuberollup grouping_setsr(rrr UNION_ALLr EXCEPT_ALLr INTERSECT_ALLrobjectrwith_metaclassEnsureKWArgTyper VisitablerrRrr rr5rrjrrrnrtrrrs$$ ___aaF2:.55(bj):BDAA;;eeArll;;;AA3%HHrzi?) @;A) BM6C) DfE) FfG) JwK) ) Lf ^ MQ) )  X  N N !4 N  . h y N NF NF h _  $       ""$( &#W'$h(,'+_ J=J=J=J=J=vJ=J=J=Z 4 4 4 4 4&4&t';VDD 4 4 4H&0d$w$ w$ w$ w$ w$ (w$ w$ w$ tI?????[???DKKKKK(KKK\W(W(W(W(W(,W(W(W(t/////,///x x x x x x x x x x rtPK!~$__pycache__/elements.cpython-311.pycnu[ |ois:dZddlmZddlZddlZddlZddlZddlmZddlm Z ddl m Z ddl m Z dd l mZdd l mZdd l mZdd l mZdd lmZddlmZddlmZddlmZddlmZddlmZdZdZdZddZddZddZdZej GddeZ!Gddej"e!Z#Gd d!e#Z$Gd"d#e!Z%Gd$d%ee!Z&Gd&d'e#Z'Gd(d)e#Z(Gd*d+e#Z)Gd,d-e!Z*Gd.d/e*e#Z+e+j,Z,e+j-Z-Gd0d1e*e#Z.Gd2d3e#Z/dd4Z0Gd5d6e#Z1Gd7d8e#Z2Gd9d:e#Z3Gd;de#Z5Gd?d@e#Z6GdAdBe6Z7GdCdDe6Z8GdEdFe#Z9GdGdHe#Z:GdIdJe9Z;GdKdLe#Z<ej=dMZ>ej=dNZ?GdOdPe#Z@GdQdRe#ZAGdSdTe#ZBGdUdVe#ZCGdWdXee#ZDGdYdZe#ZEGd[d\ee!ZFGd]d^eFZGGd_d`eFZHGdadbeFZIGdcddejJejKZLGdedfeLZMGdgdheMZNej=diZO eMZPGdjdkeMZQdlZRdmZSdnZTdoZUdpZVdqZWejXdrdsZYdtZZduZ[dvZ\dwZ]dxZ^dyZ_dzZ`d{Zadd|Zbd}Zcd~ZdejeddfdZfdZgdZhdZidZjddZkejldejmZndZodZpdZqddZrGdde ZsdS)zCore SQL expression elements, including :class:`_expression.ClauseElement`, :class:`_expression.ColumnElement`, and derived classes. )unicode_literalsN) operators)type_api Annotated) _generative) Executable) Immutable)NO_ARG)PARSE_AUTOCOMMIT)cloned_traverse)traverse) Visitable)exc) inspection)utilc *|SN_clone)elementkws N/opt/cloudlinux/venv/lib64/python3.11/site-packages/sqlalchemy/sql/elements.pyrr$s >>  c:tj|d|d|dS)Nz.. warning:: The z argument to z can be passed as a Python string argument, which will be treated as **trusted SQL text** and rendered as given. **DO NOT PASS UNTRUSTED INPUT TO THIS PARAMETER**.)radd_parameter_text) paramnamemeth_rst param_rsts r_document_text_coercionr"(s0  "  99hhh    rc~t|}t|t|tj|jS)aReturn the clause ``expression COLLATE collation``. e.g.:: collate(mycolumn, 'utf8_bin') produces:: mycolumn COLLATE utf8_bin The collation expression is also quoted if it is a case sensitive identifier, e.g. contains uppercase characters. .. versionchanged:: 1.2 quoting is automatically applied to COLLATE expressions if they are case sensitive. type_)_literal_as_bindsBinaryExpressionCollationClausercollatetype) expression collationexprs rr)r)6s>& Z ( (D  oi(()*;49   rFcPt|}||||S)axProduce a ``BETWEEN`` predicate clause. E.g.:: from sqlalchemy import between stmt = select([users_table]).where(between(users_table.c.id, 5, 7)) Would produce SQL resembling:: SELECT id, name FROM user WHERE id BETWEEN :id_1 AND :id_2 The :func:`.between` function is a standalone version of the :meth:`_expression.ColumnElement.between` method available on all SQL expressions, as in:: stmt = select([users_table]).where(users_table.c.id.between(5, 7)) All arguments passed to :func:`.between`, including the left side column expression, are coerced from Python scalar values if a the value is not a :class:`_expression.ColumnElement` subclass. For example, three fixed values can be compared as in:: print(between(5, 3, 7)) Which would produce:: :param_1 BETWEEN :param_2 AND :param_3 :param expr: a column expression, typically a :class:`_expression.ColumnElement` instance or alternatively a Python scalar expression to be coerced into a column expression, serving as the left side of the ``BETWEEN`` expression. :param lower_bound: a column or Python scalar expression serving as the lower bound of the right side of the ``BETWEEN`` expression. :param upper_bound: a column or Python scalar expression serving as the upper bound of the right side of the ``BETWEEN`` expression. :param symmetric: if True, will render " BETWEEN SYMMETRIC ". Note that not all databases support this syntax. .. versionadded:: 0.9.5 .. seealso:: :meth:`_expression.ColumnElement.between` ) symmetric)r&between)r- lower_bound upper_boundr/s rr0r0Os*h T " "D << [I< F FFrc(td||dS)aReturn a literal clause, bound to a bind parameter. Literal clauses are created automatically when non- :class:`_expression.ClauseElement` objects (such as strings, ints, dates, etc.) are used in a comparison operation with a :class:`_expression.ColumnElement` subclass, such as a :class:`~sqlalchemy.schema.Column` object. Use this function to force the generation of a literal clause, which will be created as a :class:`BindParameter` with a bound value. :param value: the value to be bound. Can be any Python object supported by the underlying DB-API, or is translatable via the given type argument. :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine` which will provide bind-parameter translation for this literal. NTr%unique BindParameter)valuer%s rliteralr9s& uE$ ? ? ??rc*t|d|ddS)awCreate an 'OUT' parameter for usage in functions (stored procedures), for databases which support them. The ``outparam`` can be used like a regular function parameter. The "output" value will be available from the :class:`~sqlalchemy.engine.ResultProxy` object via its ``out_parameters`` attribute, which returns a dictionary containing the values. NFT)r%r5 isoutparamr6)keyr%s routparamr=s d%$ O O OOrcDtjt|S)zReturn a negation of the given clause, i.e. ``NOT(clause)``. The ``~`` operator is also overloaded on all :class:`_expression.ColumnElement` subclasses to produce the same result. )rinvr&clauses rnot_rBs =*622 3 33rceZdZdZdZiZdZgZdZdZ dZ dZ dZ dZ dZdZedZejdZd Zd Zd Zd"d Zd ZdZdZdZdZefdZdZd#dZ ej!dd$dZ"dZ#dZ$ej%dddZ&ej%dddZ'dZ(dZ)d Z*e*Z+d!Z,dS)% ClauseElementzSBase class for elements of a programmatically constructed SQL expression. rAFNTc |j|j}|j|_tj|tj|||_ |S)zCreate a shallow copy of this ClauseElement. This method may be used by a generative API. Its also used as part of the "deep" copy afforded by a traversal that combines the _copy_internals() method. ) __class____new____dict__copyrD _cloned_set_reset ColumnElement comparator _is_clone_ofselfcs rrzClauseElement._clonesl N " "4> 2 2]'')) !((+++ ''***rc|jS)a.return the 'constructor' for this ClauseElement. This is for the purposes for creating a new object of this type. Usually, its just the element's __class__. However, the "Annotated" version of the object overrides to return the class of its proxied element. rFrPs r _constructorzClauseElement._constructors ~rcptj}|}||||j}||S)aReturn the set consisting all cloned ancestors of this ClauseElement. Includes this ClauseElement. This accessor tends to be used for FromClause objects to identify 'equivalent' FROM clauses, regardless of transformative operations. )r column_setaddrN)rPsfs rrJzClauseElement._cloned_setsA O   m EE!HHHAmrcd|j}|dd|S)NrN)rHrIpop)rPds r __getstate__zClauseElement.__getstate__s. M    nd###rc"t||S)zgReturn a copy of this ClauseElement with annotations updated by the given dictionary. rrPvaluess r _annotatezClauseElement._annotate v&&&rc"t||S)zhReturn a copy of this ClauseElement with annotations replaced by the given dictionary. rr`s r_with_annotationszClauseElement._with_annotationsrcrc2|r|S|S)zReturn a copy of this :class:`_expression.ClauseElement` with annotations removed. :param values: optional tuple of individual values to remove. r)rPraclones r _deannotatezClauseElement._deannotates#  ;;== Krcf|jr||||Stj|r)supports_execution_execute_clauseelementrObjectNotExecutableError)rP connection multiparamsparamss r_execute_on_connectionz$ClauseElement._execute_on_connection(s6  " 544T;OO O.t44 4rc0|d||S)aReturn a copy with :func:`_expression.bindparam` elements replaced. Same functionality as :meth:`_expression.ClauseElement.params`, except adds `unique=True` to affected bind parameters so that multiple statements can be used. T_paramsrP optionaldictkwargss r unique_paramszClauseElement.unique_params.s||D,777rc0|d||S)aReturn a copy with :func:`_expression.bindparam` elements replaced. Returns a copy of this ClauseElement with :func:`_expression.bindparam` elements replaced with values taken from the given dictionary:: >>> clause = column('x') + bindparam('foo') >>> print(clause.compile().params) {'foo':None} >>> print(clause.params({'foo':7}).compile().params) {'foo':7} Frrrts rrozClauseElement.params:s||E<888rct|dkr|dn't|dkrtjdfd}t |id|iS)Nrrz9params() takes zero or one positional dictionary argumentc||jvr|j|_d|_r|dSdSNF)r<r8required_convert_to_unique)bindrvr5s rvisit_bindparamz.ClauseElement._params..visit_bindparamSsOx6!!#DH- %  *''))))) * *r bindparam)lenupdater ArgumentErrorr)rPr5rurvrs ` ` rrszClauseElement._paramsKs |   ! ! MM,q/ * * * *    " "#K  * * * * * *tR+)GHHHrc ||uS)aCompare this :class:`_expression.ClauseElement` to the given :class:`_expression.ClauseElement`. Subclasses should override the default behavior, which is a straight identity comparison. \**kw are arguments consumed by subclass ``compare()`` methods and may be used to modify the criteria for comparison (see :class:`_expression.ColumnElement`). rPotherrs rcomparezClauseElement.compare\su}rc dS)atReassign internal elements to be clones of themselves. Called during a copy-and-traverse operation on newly shallow-copied elements to create a deep copy. The given clone function should be used, which may be applying additional transformations to the element (i.e. replacement traversal, cloned traversal, annotations). NrrPrgrs r_copy_internalszClauseElement._copy_internalsjs  rc gS)aReturn immediate child elements of this :class:`_expression.ClauseElement`. This is used for visit traversal. \**kwargs may contain flags that change the collection that is returned, for example to return a subset of items in order to cut down on larger traversals, or to return child items from a different context (such as schema-level collections instead of clause-level). rrPrvs r get_childrenzClauseElement.get_childrenws  rc|S)aApply a 'grouping' to this :class:`_expression.ClauseElement`. This method is overridden by subclasses to return a "grouping" construct, i.e. parenthesis. In particular it's used by "binary" expressions to provide a grouping around themselves when placed into a larger expression, as well as by :func:`_expression.select` constructs when placed into the FROM clause of another :func:`_expression.select`. (Note that subqueries should be normally created using the :meth:`_expression.Select.alias` method, as many platforms require nested SELECT statements to be named). As expressions are composed together, the application of :meth:`self_group` is automatic - end-user code should never need to use this method directly. Note that SQLAlchemy's clause constructs take operator precedence into account - so parenthesis might not be needed, for example, in an expression like ``x OR (y AND z)`` - AND takes precedence over OR. The base :meth:`self_group` method of :class:`_expression.ClauseElement` just returns self. rrPagainsts r self_groupzClauseElement.self_groups 2 rzsqlalchemy.engine.defaultc |s9|r|j}n/|jr|jj}|j}n|}|j|fd|i|S)a+ Compile this SQL expression. The return value is a :class:`~.Compiled` object. Calling ``str()`` or ``unicode()`` on the returned value will yield a string representation of the result. The :class:`~.Compiled` object also can return a dictionary of bind parameter names and values using the ``params`` accessor. :param bind: An ``Engine`` or ``Connection`` from which a ``Compiled`` will be acquired. This argument takes precedence over this :class:`_expression.ClauseElement`'s bound engine, if any. :param column_keys: Used for INSERT and UPDATE statements, a list of column names which should be present in the VALUES clause of the compiled statement. If ``None``, all columns from the target table object are rendered. :param dialect: A ``Dialect`` instance from which a ``Compiled`` will be acquired. This argument takes precedence over the `bind` argument as well as this :class:`_expression.ClauseElement` 's bound engine, if any. :param inline: Used for INSERT statements, for a dialect which does not support inline retrieval of newly generated primary key columns, will force the expression used to create the new primary key value to be rendered inline within the INSERT statement's VALUES clause. This typically refers to Sequence execution but may also refer to any server-side default generation function associated with a primary key `Column`. :param compile_kwargs: optional dictionary of additional parameters that will be passed through to the compiler within all "visit" methods. This allows any custom flag to be passed through to a custom compilation construct, for example. It is also used for the case of passing the ``literal_binds`` flag through:: from sqlalchemy.sql import table, column, select t = table('t', column('x')) s = select([t]).where(t.c.x == 5) print(s.compile(compile_kwargs={"literal_binds": True})) .. versionadded:: 0.9.0 .. seealso:: :ref:`faq_sql_expression_string` r~)dialectr~StrCompileDialect _compiler)rPdefaultr~rrs rcompilezClauseElement.compileskp 6 6, 6)+y!3355t~g77D7B777rc |j||fi|S)zNReturn a compiler appropriate for this ClauseElement, given a Dialect.)statement_compiler)rPrrs rrzClauseElement._compilers!*w)'4>>2>>>rctjr!t|St |ddSNasciibackslashreplace)rpy3kstrrunicodeencoderTs r__str__zClauseElement.__str__sP 9 t||~~&& &4<<>>**11+ r0.9zThe :meth:`_expression.ClauseElement.__and__` method is deprecated and will be removed in a future release. Conjunctions should only be used from a :class:`_expression.ColumnElement` subclass, e.g. :meth:`_expression.ColumnElement.__and__`.c"t||S)z!'and' at the ClauseElement level.and_rPrs r__and__zClauseElement.__and__sD%   rzThe :meth:`_expression.ClauseElement.__or__` method is deprecated and will be removed in a future release. Conjunctions should only be used from a :class:`_expression.ColumnElement` subclass, e.g. :meth:`_expression.ColumnElement.__or__`.c"t||S)z 'or' at the ClauseElement level.)or_rs r__or__zClauseElement.__or__s4rcXt|dr|jS|S)Nnegation_clause)hasattrr_negaterTs r __invert__zClauseElement.__invert__ s, 4* + + "' '<<>> !rcvt|tjtjdS)Nr)operatornegate)UnaryExpressionrrr?rTs rrzClauseElement._negates4 OOIMO 2 2]    rc td)N+Boolean value of this clause is not defined) TypeErrorrTs r__bool__zClauseElement.__bool__sEFFFrc|j}|t|Sd|j|jjt ||fzS)Nz<%s.%s at 0x%x; %s>) descriptionobject__repr__ __module__rF__name__id)rPfriendlys rrzClauseElement.__repr__sM#  ??4(( (('4 , rr{rNN)-rr __qualname____doc____visit_name__ _annotationsrj _from_objectsr~rN is_selectableis_clause_elementr_order_by_label_element_is_from_containerrpropertyrUrmemoized_propertyrJr^rbrerhrprwrorsrrrr dependenciesrrr deprecatedrrrrr __nonzero__rrrrrDrDsk NLM DLMK",  X  , ''''''$555 8 8 8999"III"   %+        6T233?8?8?843?8B??? T_  5!!!T_  4   """    GGGK     rrDc|eZdZdZdZdZgZdZdZ dZ dZ dZ dZ dZ dZdZddZfdZejd Zejd Zd Zd Zd ZddZedZedZejdZejdZdZdZ dZ! ddZ"ddZ#dZ$dZ%ejdZ&xZ'S)rLa+Represent a column-oriented SQL expression suitable for usage in the "columns" clause, WHERE clause etc. of a statement. While the most familiar kind of :class:`_expression.ColumnElement` is the :class:`_schema.Column` object, :class:`_expression.ColumnElement` serves as the basis for any unit that may be present in a SQL expression, including the expressions themselves, SQL functions, bound parameters, literal expressions, keywords such as ``NULL``, etc. :class:`_expression.ColumnElement` is the ultimate base class for all such elements. A wide variety of SQLAlchemy Core functions work at the SQL expression level, and are intended to accept instances of :class:`_expression.ColumnElement` as arguments. These functions will typically document that they accept a "SQL expression" as an argument. What this means in terms of SQLAlchemy usually refers to an input which is either already in the form of a :class:`_expression.ColumnElement` object, or a value which can be **coerced** into one. The coercion rules followed by most, but not all, SQLAlchemy Core functions with regards to SQL expressions are as follows: * a literal Python value, such as a string, integer or floating point value, boolean, datetime, ``Decimal`` object, or virtually any other Python object, will be coerced into a "literal bound value". This generally means that a :func:`.bindparam` will be produced featuring the given value embedded into the construct; the resulting :class:`.BindParameter` object is an instance of :class:`_expression.ColumnElement`. The Python value will ultimately be sent to the DBAPI at execution time as a parameterized argument to the ``execute()`` or ``executemany()`` methods, after SQLAlchemy type-specific converters (e.g. those provided by any associated :class:`.TypeEngine` objects) are applied to the value. * any special object value, typically ORM-level constructs, which feature a method called ``__clause_element__()``. The Core expression system looks for this method when an object of otherwise unknown type is passed to a function that is looking to coerce the argument into a :class:`_expression.ColumnElement` expression. The ``__clause_element__()`` method, if present, should return a :class:`_expression.ColumnElement` instance. The primary use of ``__clause_element__()`` within SQLAlchemy is that of class-bound attributes on ORM-mapped classes; a ``User`` class which contains a mapped attribute named ``.name`` will have a method ``User.name.__clause_element__()`` which when invoked returns the :class:`_schema.Column` called ``name`` associated with the mapped table. * The Python ``None`` value is typically interpreted as ``NULL``, which in SQLAlchemy Core produces an instance of :func:`.null`. A :class:`_expression.ColumnElement` provides the ability to generate new :class:`_expression.ColumnElement` objects using Python expressions. This means that Python operators such as ``==``, ``!=`` and ``<`` are overloaded to mimic SQL operations, and allow the instantiation of further :class:`_expression.ColumnElement` instances which are composed from other, more fundamental :class:`_expression.ColumnElement` objects. For example, two :class:`.ColumnClause` objects can be added together with the addition operator ``+`` to produce a :class:`.BinaryExpression`. Both :class:`.ColumnClause` and :class:`.BinaryExpression` are subclasses of :class:`_expression.ColumnElement`:: >>> from sqlalchemy.sql import column >>> column('a') + column('b') >>> print(column('a') + column('b')) a + b .. seealso:: :class:`_schema.Column` :func:`_expression.column` column_elementFrNTc&|tjtjtjfvrB|jjt jjur%t|tj tj S|tj tj fvrt|S|Sr)rrr_asboolr*_type_affinityr BOOLEANTYPE AsBooleanistrueisfalseany_opall_opGroupingrs rrzColumnElement.self_groupsp   y7HI I I (H,@,OOOT9#3Y5FGG G )9+;< < <D>> !Krc|jjtjjur%t |t jt jStt| Sr) r*rrrrrrrsuperrLrrPrFs rrzColumnElement._negatesM 9 #x';'J J JT9#4i6FGG G--5577 7rctjSrrNULLTYPErTs rr*zColumnElement.type   rc |jj}||S#t$r6}tjt d|jz|Yd}~dSd}~wwxYw)NzOObject %r associated with '.type' attribute is not a TypeEngine class or objectreplace_context)r*comparator_factoryAttributeErrorrraise_r)rPrerrs rrMzColumnElement.comparators ,!%!= &%d++ +    K:<@IF!$            s  A+AAc  t|j|S#t$r`}tjtdt |jdt |jjd||Yd}~dSd}~wwxYw)NzNeither z object nor z object has an attribute r)getattrrMrrrr*r)rPr<rs r __getattr__zColumnElement.__getattr__s 4?C00 0    KT +++T_--666 !$           s BAA<<Bc$||jg|Ri|SrrMrPoprrvs roperatezColumnElement.operates$r$/4E444V444rc |||jfi|Srrrs rreverse_operatezColumnElement.reverse_operatesr%33F333rc6td||||jdS)NT)_compared_to_operatorr%_compared_to_typer5)r7r*rProbjr%s r _bind_paramzColumnElement._bind_params-  "*"i     rc|S)z^Return a column expression. Part of the inspection interface; returns self. rrTs rr+zColumnElement.expression s  rc|fSrrrTs r_select_iterablezColumnElement._select_iterable wrcHtjd|jDS)Nc3(K|] }|j |VdSr)_proxies.0rQs r z-ColumnElement.base_columns..s)KKQ KqKKKKKKr)rrW proxy_setrTs r base_columnszColumnElement.base_columnss#KK$.KKKKKKrcxtj|g}|jD]}||j|Sr)rrWrrrrPrYrQs rrzColumnElement.proxy_sets@ OTF # # " "A HHQ[ ! ! ! !rctj|g}|jD])}||*|S)zAn 'uncached' version of proxy set. This is so that we can read annotations from the list of columns without breaking the caching of the above proxy_set. )rrWrr_uncached_proxy_setr s rr z!ColumnElement._uncached_proxy_set!sL OTF # # . .A HHQ**,, - - - -rcZt|j|jS)zReturn True if the given :class:`_expression.ColumnElement` has a common ancestor to this :class:`_expression.ColumnElement`.)boolr intersection)rP othercolumns rshares_lineagezColumnElement.shares_lineage-s%DN// 0EFFGGGrcbt|dot|do|j|jkS)zhReturn True if the given column element compares to this one when targeting within a result row.name)rrrs r_compare_name_for_resultz&ColumnElement._compare_name_for_result3s9 E6 " " (f%% ( di' rc r|C|j}|jr|j}n/ t|}n#tj$r |j}YnwxYw|}t |rt |n|t|dd|}|g|_|j $|j j ||_ ||j |<|S)zCreate a new :class:`_expression.ColumnElement` representing this :class:`_expression.ColumnElement` as it appears in the select list of a descending selectable. Nr*)r% _selectable) anon_labelr<rrUnsupportedCompilationError ColumnClause _as_truncatedrrrNcolumnsget_columns)rP selectablername_is_truncatablerr<cos r _make_proxyzColumnElement._make_proxy=s <?Dx *h*d))CC6***/CCC*C #6 @M$   D$--"    f  " .(5=AA#FFBO#% C  s*AAc |f}|r||vr|||}|D]?}|r||rdSt|t|krdS@dS)aCompare this ColumnElement to another. Special arguments understood: :param use_proxies: when True, consider two columns that share a common base column as equivalent (i.e. shares_lineage()) :param equivalents: a dictionary of columns as keys mapped to sets of columns. If the given "other" column is present in this dictionary, if any of the columns in the corresponding set() pass the comparison test, the result is True. This is used to expand the comparison to other columns that may be known to be equivalent to this one via foreign key or other criterion. TF)unionrhash)rPr use_proxies equivalentsr to_compareoths rrzColumnElement.compare^s X  >5K//$U+11*==J  C t22377 ttcd4jj((tt)5rc"t||S)a<Produce a type cast, i.e. ``CAST( AS )``. This is a shortcut to the :func:`_expression.cast` function. .. seealso:: :ref:`coretutorial_casts` :func:`_expression.cast` :func:`_expression.type_coerce` .. versionadded:: 1.0.7 )CastrPr%s rcastzColumnElement.castzs D%   rc.t|||jS)zProduce a column label, i.e. `` AS ``. This is a shortcut to the :func:`_expression.label` function. If 'name' is ``None``, an anonymous label name will be generated. )Labelr*)rPrs rlabelzColumnElement.labelsT4+++rc |j|j}|jtdt|t|ddfzS)a Provides a constant 'anonymous label' for this ColumnElement. This is a label() expression which will be named at compile time. The same label() is returned each time ``anon_label`` is called so that expressions can reference ``anon_label`` multiple times, producing the same label name at compile time. The compiler uses this function automatically at compile time for expressions that are known to be 'unnamed' like binary expressions and function calls. N %%(%d %s)sranon)rN_anonymous_labelrrrTs rrzColumnElement.anon_labelsS+$D+ BtHHgdFF&C&CD D   rrr{)FN)(rrrrr primary_key foreign_keysr_labelr< _key_label_render_label_in_columns_clause_resolve_label_allow_label_resolve_is_implicitly_boolean _alt_namesrrrrr*rMrrrrrr+rrrr rrr rr+r.r __classcell__rSs@rrLrL(sUOOb&NKLH F  CJ '+#N  #J    88888  !!!  , , , 555444    XX LLL    HHH    :?B8!!!$,,,        rrLc eZdZdZdZdZdZeddeddddddf dZdZ dZ e d Z d Z d Zd Zd ZdZdZdS)r7aRepresent a "bound expression". :class:`.BindParameter` is invoked explicitly using the :func:`.bindparam` function, as in:: from sqlalchemy import bindparam stmt = select([users_table]).\ where(users_table.c.name == bindparam('username')) Detailed discussion of how :class:`.BindParameter` is used is at :func:`.bindparam`. .. seealso:: :func:`.bindparam` rFrNc t|tr|j}|j}|tur |tuo|du}|turd}|t ||}|rRt dt||)tj dd| dndfz|_n&|pt dt|z|_|j|_ |pd|_ ||_ ||_||_| |_||_||_|:| | | ||_dSt)j||_dSt|tr||_dS||_dS)az$Produce a "bound expression". The return value is an instance of :class:`.BindParameter`; this is a :class:`_expression.ColumnElement` subclass which represents a so-called "placeholder" value in a SQL expression, the value of which is supplied at the point at which the statement in executed against a database connection. In SQLAlchemy, the :func:`.bindparam` construct has the ability to carry along the actual value that will be ultimately used at expression time. In this way, it serves not just as a "placeholder" for eventual population, but also as a means of representing so-called "unsafe" values which should not be rendered directly in a SQL statement, but rather should be passed along to the :term:`DBAPI` as values which need to be correctly escaped and potentially handled for type-safety. When using :func:`.bindparam` explicitly, the use case is typically one of traditional deferment of parameters; the :func:`.bindparam` construct accepts a name which can then be referred to at execution time:: from sqlalchemy import bindparam stmt = select([users_table]).\ where(users_table.c.name == bindparam('username')) The above statement, when rendered, will produce SQL similar to:: SELECT id, name FROM user WHERE name = :username In order to populate the value of ``:username`` above, the value would typically be applied at execution time to a method like :meth:`_engine.Connection.execute`:: result = connection.execute(stmt, username='wendy') Explicit use of :func:`.bindparam` is also common when producing UPDATE or DELETE statements that are to be invoked multiple times, where the WHERE criterion of the statement is to change on each invocation, such as:: stmt = (users_table.update(). where(user_table.c.name == bindparam('username')). values(fullname=bindparam('fullname')) ) connection.execute( stmt, [{"username": "wendy", "fullname": "Wendy Smith"}, {"username": "jack", "fullname": "Jack Jones"}, ] ) SQLAlchemy's Core expression system makes wide use of :func:`.bindparam` in an implicit sense. It is typical that Python literal values passed to virtually all SQL expression functions are coerced into fixed :func:`.bindparam` constructs. For example, given a comparison operation such as:: expr = users_table.c.name == 'Wendy' The above expression will produce a :class:`.BinaryExpression` construct, where the left side is the :class:`_schema.Column` object representing the ``name`` column, and the right side is a :class:`.BindParameter` representing the literal value:: print(repr(expr.right)) BindParameter('%(4327771088 name)s', 'Wendy', type_=String()) The expression above will render SQL such as:: user.name = :name_1 Where the ``:name_1`` parameter name is an anonymous name. The actual string ``Wendy`` is not in the rendered string, but is carried along where it is later used within statement execution. If we invoke a statement like the following:: stmt = select([users_table]).where(users_table.c.name == 'Wendy') result = connection.execute(stmt) We would see SQL logging output as:: SELECT "user".id, "user".name FROM "user" WHERE "user".name = %(name_1)s {'name_1': 'Wendy'} Above, we see that ``Wendy`` is passed as a parameter to the database, while the placeholder ``:name_1`` is rendered in the appropriate form for the target database, in this case the PostgreSQL database. Similarly, :func:`.bindparam` is invoked automatically when working with :term:`CRUD` statements as far as the "VALUES" portion is concerned. The :func:`_expression.insert` construct produces an ``INSERT`` expression which will, at statement execution time, generate bound placeholders based on the arguments passed, as in:: stmt = users_table.insert() result = connection.execute(stmt, name='Wendy') The above will produce SQL output as:: INSERT INTO "user" (name) VALUES (%(name)s) {'name': 'Wendy'} The :class:`_expression.Insert` construct, at compilation/execution time, rendered a single :func:`.bindparam` mirroring the column name ``name`` as a result of the single ``name`` parameter we passed to the :meth:`_engine.Connection.execute` method. :param key: the key (e.g. the name) for this bind param. Will be used in the generated SQL statement for dialects that use named parameters. This value may be modified when part of a compilation operation, if other :class:`BindParameter` objects exist with the same key, or if its length is too long and truncation is required. :param value: Initial value for this bind param. Will be used at statement execution time as the value for this parameter passed to the DBAPI, if no other value is indicated to the statement execution method for this particular parameter name. Defaults to ``None``. :param callable\_: A callable function that takes the place of "value". The function will be called at statement execution time to determine the ultimate value. Used for scenarios where the actual bind value cannot be determined at the point at which the clause construct is created, but embedded bind values are still desirable. :param type\_: A :class:`.TypeEngine` class or instance representing an optional datatype for this :func:`.bindparam`. If not passed, a type may be determined automatically for the bind, based on the given value; for example, trivial Python types such as ``str``, ``int``, ``bool`` may result in the :class:`.String`, :class:`.Integer` or :class:`.Boolean` types being automatically selected. The type of a :func:`.bindparam` is significant especially in that the type will apply pre-processing to the value before it is passed to the database. For example, a :func:`.bindparam` which refers to a datetime value, and is specified as holding the :class:`.DateTime` type, may apply conversion needed to the value (such as stringification on SQLite) before passing the value to the database. :param unique: if True, the key name of this :class:`.BindParameter` will be modified if another :class:`.BindParameter` of the same name already has been located within the containing expression. This flag is used generally by the internals when producing so-called "anonymous" bound expressions, it isn't generally applicable to explicitly-named :func:`.bindparam` constructs. :param required: If ``True``, a value is required at execution time. If not passed, it defaults to ``True`` if neither :paramref:`.bindparam.value` or :paramref:`.bindparam.callable` were passed. If either of these parameters are present, then :paramref:`.bindparam.required` defaults to ``False``. :param quote: True if this parameter name requires quoting and is not currently known as a SQLAlchemy reserved word; this currently only applies to the Oracle backend, where bound names must sometimes be quoted. :param isoutparam: if True, the parameter should be treated like a stored procedure "OUT" parameter. This applies to backends such as Oracle which support OUT parameters. :param expanding: if True, this parameter will be treated as an "expanding" parameter at execution time; the parameter value is expected to be a sequence, rather than a scalar value, and the string SQL statement will be transformed on a per-execution basis to accommodate the sequence with a variable number of parameter slots passed to the DBAPI. This is to allow statement caching to be used in conjunction with an IN clause. .. seealso:: :meth:`.ColumnOperators.in_` :ref:`baked_in` - with baked queries .. note:: The "expanding" feature does not support "executemany"- style parameter sets. .. versionadded:: 1.2 .. versionchanged:: 1.3 the "expanding" bound parameter feature now supports empty lists. .. seealso:: :ref:`coretutorial_bind_param` :ref:`coretutorial_insert_expressions` :func:`.outparam` Nr0z [%\(\) \$]+_paramz %%(%d param)s) isinstancerr*r<r quoted_namer2rresubstrip_identifying_key _orig_keyr5r8callabler;r| expandingcoerce_compared_valuer_resolve_value_to_type) rPr<r8r%r5r|quote callable_rIr;rrs r__init__zBindParameter.__init__sD c< ( ( HE'C v  <9+344::3??? DHHJ.D/IJJDH !%  ! $  " = ,-CC)5 %;EBB t $ $ DIIIDIIIrc<|}||_|S)zrReturn a copy of this :class:`.BindParameter` in the context of an expanding IN against a tuple. )r_expanding_in_types)rPtypescloneds r_with_expanding_in_typesz&BindParameter._with_expanding_in_typess %*" rc|}||_d|_d|_|jt jurt j||_|S)zYReturn a copy of this :class:`.BindParameter` with the given value set. NF)rr8rHr|r*rrrK)rPr8rRs r _with_valuezBindParameter._with_valuesM   ;(+ + +"9%@@FK rcF|jr|S|jS)zReturn the value of this bound parameter, taking into account if the ``callable`` parameter was set. The ``callable`` value will be evaluated and returned if present, else ``value``. )rHr8rTs reffective_valuezBindParameter.effective_values$ = ==?? ": rct|}|jr-tdt ||jpdfz|_|S)Nr0r@)rDrr5r2rrGr<rOs rrzBindParameter._clonesQ   & & ; $1q{'=g>>AErc|js6d|_tdt||jpdfz|_dSdS)NTr0r@)r5r2rrGr<rTs rr}z BindParameter._convert_to_uniquesL{ DK'4$.*CGDDDHHH  rc t|to>|j|jo|j|jko|j|jkS)zJCompare this :class:`BindParameter` to the given clause. )rAr7r*_compare_type_affinityr8rHrs rrzBindParameter.comparesT um , , 0 00<< 0 ek) 0 /  rc|j}|j}|jr|}d|d<||d<|S)z4Execute a deferred value for serialization purposes.NrHr8)rHrIr8rH)rPr]vs rr^zBindParameter.__getstate__sL M    J = ! A AjM' rc|ddr8tdt||ddfz|d<|j|dS)Nr5Fr0rGr@r<)rr2rrHrrPstates r __setstate__zBindParameter.__setstate__'sj 99Xu % % +4%))K*I*IJJE%L U#####rc8d|jd|jd|jdS)NzBindParameter(z, z, type_=))r<r8r*rTs rrzBindParameter.__repr__.s) HHH JJJ III  r)rrrrr_is_crudrPr rNrSrUrrWrr}rr^rarrrrr7r7s&!NH "TTTTl     X        $$$     rr7ceZdZdZdZdZdS) TypeClausezTHandle a type keyword in a SQL statement. Used by the ``Case`` statement. typeclausec||_dSrr*r*s rrNzTypeClause.__init__?s  rN)rrrrrrNrrrrfrf6s4 "NrrfceZdZdZdZejdejZe j de iZ dZ dZedZedZgZd xZxZZdZdd Zeejd d d eddd ddZedZejddZ edZ!edZ"ddZ#e$fdZ%dZ&dZ'd S) TextClauseaRepresent a literal SQL text fragment. E.g.:: from sqlalchemy import text t = text("SELECT * FROM users") result = connection.execute(t) The :class:`_expression.TextClause` construct is produced using the :func:`_expression.text` function; see that function for full documentation. .. seealso:: :func:`_expression.text` textclausez(?.replzsA+8+D+DD QWWQZZ (1771::% %r)_bindrt_bind_params_regexrDtext)rPryr~rvs` rrNzTextClause.__init__vsK  & & & & & +//d;; r)z0.6aThe :paramref:`_expression.text.autocommit` parameter is deprecated and will be removed in a future release. Please use the :paramref:`.Connection.execution_options.autocommit` parameter in conjunction with the :meth:`.Executable.execution_options` method.)rzThe :paramref:`_expression.text.bindparams` parameter is deprecated and will be removed in a future release. Please refer to the :meth:`_expression.TextClause.bindparams` method.)rzThe :paramref:`_expression.text.typemap` parameter is deprecated and will be removed in a future release. Please refer to the :meth:`_expression.TextClause.columns` method.)rm bindparamstypemapryz :func:`.text`z:paramref:`.text.text`ct||}|r |j|}|r |jdi|}|||}|S)aConstruct a new :class:`_expression.TextClause` clause, representing a textual SQL string directly. E.g.:: from sqlalchemy import text t = text("SELECT * FROM users") result = connection.execute(t) The advantages :func:`_expression.text` provides over a plain string are backend-neutral support for bind parameters, per-statement execution options, as well as bind parameter and result-column typing behavior, allowing SQLAlchemy type constructs to play a role when executing a statement that is specified literally. The construct can also be provided with a ``.c`` collection of column elements, allowing it to be embedded in other SQL expression constructs as a subquery. Bind parameters are specified by name, using the format ``:name``. E.g.:: t = text("SELECT * FROM users WHERE id=:user_id") result = connection.execute(t, user_id=12) For SQL statements where a colon is required verbatim, as within an inline string, use a backslash to escape:: t = text("SELECT * FROM users WHERE name='\:username'") The :class:`_expression.TextClause` construct includes methods which can provide information about the bound parameters as well as the column values which would be returned from the textual statement, assuming it's an executable SELECT type of statement. The :meth:`_expression.TextClause.bindparams` method is used to provide bound parameter detail, and :meth:`_expression.TextClause.columns` method allows specification of return columns including names and types:: t = text("SELECT * FROM users WHERE id=:user_id").\ bindparams(user_id=7).\ columns(id=Integer, name=String) for id, name in connection.execute(t): print(id, name) The :func:`_expression.text` construct is used in cases when a literal string SQL fragment is specified as part of a larger query, such as for the WHERE clause of a SELECT statement:: s = select([users.c.id, users.c.name]).where(text("id=:user_id")) result = connection.execute(s, user_id=12) :func:`_expression.text` is also used for the construction of a full, standalone statement using plain text. As such, SQLAlchemy refers to it as an :class:`.Executable` object, and it supports the :meth:`Executable.execution_options` method. For example, a :func:`_expression.text` construct that should be subject to "autocommit" can be set explicitly so using the :paramref:`.Connection.execution_options.autocommit` option:: t = text("EXEC my_procedural_thing()").\ execution_options(autocommit=True) Note that SQLAlchemy's usual "autocommit" behavior applies to :func:`_expression.text` constructs implicitly - that is, statements which begin with a phrase such as ``INSERT``, ``UPDATE``, ``DELETE``, or a variety of other phrases specific to certain backends, will be eligible for autocommit if no transaction is in progress. :param text: the text of the SQL statement to be created. Use ``:`` to specify bind parameters; they will be compiled to their engine-specific format. :param autocommit: whether or not to set the "autocommit" execution option for this :class:`_expression.TextClause` object. :param bind: an optional connection or engine to be used for this text query. :param bindparams: A list of :func:`.bindparam` instances used to provide information about parameters embedded in the statement. E.g.:: stmt = text("SELECT * FROM table WHERE id=:id", bindparams=[bindparam('id', value=5, type_=Integer)]) :param typemap: A dictionary mapping the names of columns represented in the columns clause of a ``SELECT`` statement to type objects. E.g.:: stmt = text("SELECT * FROM table", typemap={'id': Integer, 'name': String}, ) .. seealso:: :ref:`sqlexpression_text` - in the Core tutorial :ref:`orm_tutorial_literal_sql` - in the ORM tutorial )r~N)rmr)rkrzrexecution_options)rPryr~rzr{rmstmts r _create_textzTextClause._create_textsm\$T***  0"4?J/D  +4<**'**D  !))Z)@@D rc|jx|_}|D]a} ||j}|||j<#t$r:}t jt jd|jz|Yd}~Zd}~wwxYw|D]h\}} ||}| |||<'#t$r5}t jt jd|z|Yd}~ad}~wwxYwdS)aEstablish the values and/or types of bound parameters within this :class:`_expression.TextClause` construct. Given a text construct such as:: from sqlalchemy import text stmt = text("SELECT id, name FROM user WHERE name=:name " "AND timestamp=:timestamp") the :meth:`_expression.TextClause.bindparams` method can be used to establish the initial value of ``:name`` and ``:timestamp``, using simple keyword arguments:: stmt = stmt.bindparams(name='jack', timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5)) Where above, new :class:`.BindParameter` objects will be generated with the names ``name`` and ``timestamp``, and values of ``jack`` and ``datetime.datetime(2012, 10, 8, 15, 12, 5)``, respectively. The types will be inferred from the values given, in this case :class:`.String` and :class:`.DateTime`. When specific typing behavior is needed, the positional ``*binds`` argument can be used in which to specify :func:`.bindparam` constructs directly. These constructs must include at least the ``key`` argument, then an optional value and type:: from sqlalchemy import bindparam stmt = stmt.bindparams( bindparam('name', value='jack', type_=String), bindparam('timestamp', type_=DateTime) ) Above, we specified the type of :class:`.DateTime` for the ``timestamp`` bind, and the type of :class:`.String` for the ``name`` bind. In the case of ``name`` we also set the default value of ``"jack"``. Additional bound parameters can be supplied at statement execution time, e.g.:: result = connection.execute(stmt, timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5)) The :meth:`_expression.TextClause.bindparams` method can be called repeatedly, where it will re-use existing :class:`.BindParameter` objects to add new information. For example, we can call :meth:`_expression.TextClause.bindparams` first with typing information, and a second time with value information, and it will be combined:: stmt = text("SELECT id, name FROM user WHERE name=:name " "AND timestamp=:timestamp") stmt = stmt.bindparams( bindparam('name', type_=String), bindparam('timestamp', type_=DateTime) ) stmt = stmt.bindparams( name='jack', timestamp=datetime.datetime(2012, 10, 8, 15, 12, 5) ) The :meth:`_expression.TextClause.bindparams` method also supports the concept of **unique** bound parameters. These are parameters that are "uniquified" on name at statement compilation time, so that multiple :func:`_expression.text` constructs may be combined together without the names conflicting. To use this feature, specify the :paramref:`.BindParameter.unique` flag on each :func:`.bindparam` object:: stmt1 = text("select id from table where name=:name").bindparams( bindparam("name", value='name1', unique=True) ) stmt2 = text("select id from table where name=:name").bindparams( bindparam("name", value='name2', unique=True) ) union = union_all( stmt1.columns(column("id")), stmt2.columns(column("id")) ) The above statement will render as:: select id from table where name=:name_1 UNION ALL select id from table where name=:name_2 .. versionadded:: 1.3.11 Added support for the :paramref:`.BindParameter.unique` flag to work with :func:`_expression.text` constructs. z?This text() construct doesn't define a bound parameter named %rrN) rtrIrGKeyErrorrrrritemsrU) rPbindsnames_to_values new_paramsr~existingrr<r8s rrzzTextClause.bindparamssH)-(8(=(=(?(??: 6 6D 6&dn526 8-..    %359^D%(  *//11 > >JC >%c?#+"6"6u"="= 3    %3589%(   > >s- > B0A==BC C? +C::C?zsqlalchemy.sql.selectablecfd|D}dD}||||zt|o| S)aTurn this :class:`_expression.TextClause` object into a :class:`.TextAsFrom` object that can be embedded into another statement. This function essentially bridges the gap between an entirely textual SELECT statement and the SQL expression language concept of a "selectable":: from sqlalchemy.sql import column, text stmt = text("SELECT id, name FROM some_table") stmt = stmt.columns(column('id'), column('name')).alias('st') stmt = select([mytable]).\ select_from( mytable.join(stmt, mytable.c.name == stmt.c.name) ).where(stmt.c.id > 5) Above, we pass a series of :func:`_expression.column` elements to the :meth:`_expression.TextClause.columns` method positionally. These :func:`_expression.column` elements now become first class elements upon the :attr:`.TextAsFrom.c` column collection, just like any other selectable. The column expressions we pass to :meth:`_expression.TextClause.columns` may also be typed; when we do so, these :class:`.TypeEngine` objects become the effective return type of the column, so that SQLAlchemy's result-set-processing systems may be used on the return values. This is often needed for types such as date or boolean types, as well as for unicode processing on some dialect configurations:: stmt = text("SELECT id, name, timestamp FROM some_table") stmt = stmt.columns( column('id', Integer), column('name', Unicode), column('timestamp', DateTime) ) for id, name, timestamp in connection.execute(stmt): print(id, name, timestamp) As a shortcut to the above syntax, keyword arguments referring to types alone may be used, if only type conversion is needed:: stmt = text("SELECT id, name, timestamp FROM some_table") stmt = stmt.columns( id=Integer, name=Unicode, timestamp=DateTime ) for id, name, timestamp in connection.execute(stmt): print(id, name, timestamp) The positional form of :meth:`_expression.TextClause.columns` also provides the unique feature of **positional column targeting**, which is particularly useful when using the ORM with complex textual queries. If we specify the columns from our model to :meth:`_expression.TextClause.columns`, the result set will match to those columns positionally, meaning the name or origin of the column in the textual SQL doesn't matter:: stmt = text("SELECT users.id, addresses.id, users.id, " "users.name, addresses.email_address AS email " "FROM users JOIN addresses ON users.id=addresses.user_id " "WHERE users.id = 1").columns( User.id, Address.id, Address.user_id, User.name, Address.email_address ) query = session.query(User).from_statement(stmt).options( contains_eager(User.addresses)) .. versionadded:: 1.1 the :meth:`_expression.TextClause.columns` method now offers positional column targeting in the result set when the column expressions are passed purely positionally. The :meth:`_expression.TextClause.columns` method provides a direct route to calling :meth:`_expression.FromClause.alias` as well as :meth:`_expression.SelectBase.cte` against a textual SELECT statement:: stmt = stmt.columns(id=Integer, name=String).cte('st') stmt = select([sometable]).where(sometable.c.id == stmt.c.id) .. versionadded:: 0.9.0 :func:`_expression.text` can now be converted into a fully featured "selectable" construct using the :meth:`_expression.TextClause.columns` method. cg|]:}|jvr-t|j|jn|;Sr)r<rr\)rcolrQs r z&TextClause.columns..sZ! ! ! w% %))CG"4"4 5 5 5! ! ! rc4g|]\}}t||Srr)rr<r%s rrz&TextClause.columns.. s3   )3eLe $ $   r) positional)r TextAsFromr )rPrcolsrQpositional_input_colskeyed_input_colss ` rrzTextClause.columnssL! ! ! !  ! ! !    7<{{}}   $$  !$4 4122K;K7K%   rctjSrrrTs rr*zTextClause.typerrc6|j|Sr)r*rrTs rrMzTextClause.comparatorsy++D111rc@|tjurt|S|Sr)rin_oprrs rrzTextClause.self_groups io % %D>> !Krc ztfd|jD|_dS)Nc38K|]}|j|fifVdSr)r<)rbrgrs rrz-TextClause._copy_internals..$sI  ()QUEE!NNrNN #      r)dictrtrars ``rrzTextClause._copy_internals#sV     -1-=-D-D-F-F     rc Nt|jSr)listrtrars rrzTextClause.get_children(sD$++--...rcLt|to|j|jkSr)rArkryrs rrzTextClause.compare+s %,,Hty1HHrrNNNN)(rrrrrrCrUNICODErxr _execution_optionsr"r r:rrrr _hide_fromsr<r5r8r9rN classmethodrdeprecated_paramsr"rr rzrrr*rMrrrrrrrrrkrkCs&("N#$@"*MM#6<< '(#!!!XX K%)(C(&>  < < < <T   !.V_6NOOIM}}}PO/[2}~B>B>[B>HT233s s 43s j!!X!22X2 %+    ///IIIIIrrkcReZdZdZdZejdZedZ dZ dS)NullzRepresent the NULL keyword in a SQL statement. :class:`.Null` is accessed as a constant via the :func:`.null` function. nullctjSrrrTs rr*z Null.type9rrctS)z+Return a constant :class:`.Null` construct.)rclss r _instancezNull._instance=s vv rc,t|tSr)rArrs rrz Null.compareCs%&&&rN) rrrrrrrr*rrrrrrrr/slN !!![ '''''rrcXeZdZdZdZejdZdZe dZ dZ dS)False_zRepresent the ``false`` keyword, or equivalent, in a SQL statement. :class:`.False_` is accessed as a constant via the :func:`.false` function. falsectjSrrrrTs rr*z False_.typeQ ##rctSrTrue_rTs rrzFalse_._negateUs wwrctS)aReturn a :class:`.False_` construct. E.g.:: >>> from sqlalchemy import false >>> print(select([t.c.x]).where(false())) SELECT x FROM t WHERE false A backend which does not support true/false constants will render as an expression against 1 or 0:: >>> print(select([t.c.x]).where(false())) SELECT x FROM t WHERE 0 = 1 The :func:`.true` and :func:`.false` constants also feature "short circuit" operation within an :func:`.and_` or :func:`.or_` conjunction:: >>> print(select([t.c.x]).where(or_(t.c.x > 5, true()))) SELECT x FROM t WHERE true >>> print(select([t.c.x]).where(and_(t.c.x > 5, false()))) SELECT x FROM t WHERE false .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature better integrated behavior within conjunctions and on dialects that don't support true/false constants. .. seealso:: :func:`.true` rrs rrzFalse_._instanceXsHxxrc,t|tSr)rArrs rrzFalse_.compare~s%(((rN) rrrrrrrr*rrrrrrrrrGs|N $$$##[#J)))))rrcneZdZdZdZejdZdZe dZ e dZ dZ dS) rzRepresent the ``true`` keyword, or equivalent, in a SQL statement. :class:`.True_` is accessed as a constant via the :func:`.true` function. truectjSrrrTs rr*z True_.typerrctSrrrTs rrz True_._negates xxrc2||S|Sr)r)rrs r_ifnonez True_._ifnones ===?? "LrctS)aReturn a constant :class:`.True_` construct. E.g.:: >>> from sqlalchemy import true >>> print(select([t.c.x]).where(true())) SELECT x FROM t WHERE true A backend which does not support true/false constants will render as an expression against 1 or 0:: >>> print(select([t.c.x]).where(true())) SELECT x FROM t WHERE 1 = 1 The :func:`.true` and :func:`.false` constants also feature "short circuit" operation within an :func:`.and_` or :func:`.or_` conjunction:: >>> print(select([t.c.x]).where(or_(t.c.x > 5, true()))) SELECT x FROM t WHERE true >>> print(select([t.c.x]).where(and_(t.c.x > 5, false()))) SELECT x FROM t WHERE false .. versionchanged:: 0.9 :func:`.true` and :func:`.false` feature better integrated behavior within conjunctions and on dialects that don't support true/false constants. .. seealso:: :func:`.false` rrs rrzTrue_._instancesHwwrc,t|tSr)rArrs rrz True_.compares%'''rN) rrrrrrrr*rrrrrrrrrrsN $$$[ ##[#J(((((rrcxeZdZdZdZdZdZdZedZ dZ e fdZ d Z ed Zdd Zd Zd S) ClauseListzzDescribe a list of clauses, separated by an operator. By default, is comma-separated, such as a column listing. clauselistc|dtj_|dd_|dd_|dd_|dtjrfd|D_nfd |D_tj j_ dS) NrrsTgroup_contents _tuple_valuesF_literal_as_textcXg|]&}|j'Sr)rr)rrArPtext_converters rrz'ClauseList.__init__..sFv&&11$-1HHrc&g|] }|Srr)rrArs rrz'ClauseList.__init__..s#IIIvNN622IIIr) r\rcomma_oprrsrr_expression_literal_as_textclauses is_booleanr:)rPrrvrs` @rrNzClauseList.__init__s :y/ABB ZZ.. $jj)94@@#ZZ??  ;     J%DLL JIIIIIIDL&/&:4=&I&I###rc*t|jSr)iterrrTs r__iter__zClauseList.__iter__sDL!!!rc*t|jSr)rrrTs r__len__zClauseList.__len__s4<   rc t|Sr)rrTs rrzClauseList._select_iterablesDzzrc|jrB|jt||jdS|jt|dSNr)rrappendrrr)rPrAs rrzClauseList.appendsv   : L   ((33DM3JJ      L   0 8 8 9 9 9 9 9rc <fd|jD|_dS)Nc"g|] }|fi Srr)rrArgrs rrz.ClauseList._copy_internals..s+GGGf++++GGGrrrs ``rrzClauseList._copy_internalss(GGGGG$,GGG rc |jSrrrs rrzClauseList.get_childrens |rcVttjd|jDS)Ncg|] }|j Srrrs rrz,ClauseList._from_objects..s%L%L%L!ao%L%L%Lr)r itertoolschainrrTs rrzClauseList._from_objectss(IO%L%Lt|%L%L%LMNNNrNcf|jr)tj|j|rt |S|Sr)rsr is_precedentrrrs rrzClauseList.self_groups3 : )0HH D>> !Krc "t|ts1t|jdkr|jdj|fi|St|tr2t|jt|jkr|j|jur|jt jt jfvrt}|jD]Q}t|j |D]'}|j|fi|r| |n(Rt|t|jkStdt|jD])}|j|j|j|fi|sdS*dSdS)zCompare this :class:`.ClauseList` to the given :class:`.ClauseList`, including a comparison of all the clause items. rrFT) rArrrrrrrrset differencerXrange)rPrr completedrA other_clauseis rrzClauseList.compares %,, T\1B1Ba1G1G*4<?*577B77 7 uj ) ) DL!!S%7%777 //} ???EE "l""F(+EM(:(:(E(E!))"" *6>,=="=="%MM,777!E"9~~U]););;;q#dl"3"344  A24<?25=3CJJrJJ%$uu% 45rr)rrrrrrNrrrrrrrrrrrrrrrrs "NJJJ""""!!!X:::%+HHHHOOXO rrceZdZdZdZdZedZedZedZ e dZ d fd Z d Z xZS) BooleanClauseListrFc td)Nz+BooleanClauseList has a private constructor)NotImplementedError)rPargrs rrNzBooleanClauseList.__init__&s! 9   rcvg}dtj|D}|D]Z}t||rt||r"|tjcS||[t|dkr&|dtjS|s(|r&|dtjSfd|D}||}||_ d|_ |_ d|_ tj|_d|_|S)Nc,g|]}t|Sr)r)rrAs rrz0BooleanClauseList._construct../s0    ( / /   rrrrc<g|]}|Sr)r)rrQrs rrz0BooleanClauseList._construct..As4   /0ALLL * *   rT)rcoerce_generator_argrArrrrrrGrrsrrrrr*r:) rr continue_onskip_onrrconvert_clausesrArPs ` r _constructzBooleanClauseList._construct+sr  3G<<    + +F&+.. DFG,, D((1B(CCCCC  " "6 * * * *   1 $ $"1%009J0KK K  DW D1:((1B(CC C    4C   {{3&    "( &*# rcJ|jtjttg|RS)a+Produce a conjunction of expressions joined by ``AND``. E.g.:: from sqlalchemy import and_ stmt = select([users_table]).where( and_( users_table.c.name == 'wendy', users_table.c.enrolled == True ) ) The :func:`.and_` conjunction is also available using the Python ``&`` operator (though note that compound expressions need to be parenthesized in order to function with Python operator precedence behavior):: stmt = select([users_table]).where( (users_table.c.name == 'wendy') & (users_table.c.enrolled == True) ) The :func:`.and_` operation is also implicit in some cases; the :meth:`_expression.Select.where` method for example can be invoked multiple times against a statement, which will have the effect of each clause being combined using :func:`.and_`:: stmt = select([users_table]).\ where(users_table.c.name == 'wendy').\ where(users_table.c.enrolled == True) .. seealso:: :func:`.or_` )rrrrrrrs rrzBooleanClauseList.and_Ns%Ps~ineVFgFFFFrcJ|jtjttg|RS)adProduce a conjunction of expressions joined by ``OR``. E.g.:: from sqlalchemy import or_ stmt = select([users_table]).where( or_( users_table.c.name == 'wendy', users_table.c.name == 'jack' ) ) The :func:`.or_` conjunction is also available using the Python ``|`` operator (though note that compound expressions need to be parenthesized in order to function with Python operator precedence behavior):: stmt = select([users_table]).where( (users_table.c.name == 'wendy') | (users_table.c.name == 'jack') ) .. seealso:: :func:`.and_` )rrrrrrs rrzBooleanClauseList.or_xs$<s~imVUEWEEEErc|fSrrrTs rrz"BooleanClauseList._select_iterablerrNch|js|Stt||Sr)rrrr)rPrrFs rrzBooleanClauseList.self_groups5| NK*D11<XNNNNNN (((((((rrc@eZdZdZfdZedZddZxZS)TuplezRepresent a SQL tuple.cd|D}d|D|_|d|jr |jdn tj|_t t |j|i|dS)aReturn a :class:`.Tuple`. Main usage is to produce a composite IN construct using :meth:`.ColumnOperators.in_` :: from sqlalchemy import tuple_ tuple_(table.c.col1, table.c.col2).in_( [(1, 2), (5, 12), (10, 19)] ) .. versionchanged:: 1.3.6 Added support for SQLite IN tuples. .. warning:: The composite IN construct is not supported by all backends, and is currently known to work on PostgreSQL, MySQL, and SQLite. Unsupported backends will raise a subclass of :class:`~sqlalchemy.exc.DBAPIError` when such an expression is invoked. c,g|]}t|Sr)r&rs rrz"Tuple.__init__..s!999A$Q''999rcg|] }|j Srri)rrs rrz"Tuple.__init__..s888CH888rr%rN) _type_tupler\rrr*rrrN)rPrrrFs rrNzTuple.__init__s0:999988888FF #'#3 JD Q  9J   $eT#W333333rc|fSrrrTs rrzTuple._select_iterablerrNc|tfdt||jDS)Nc @g|]\}}td||dS)NT)rrr5r%r6)rocompared_to_typerr%s rrz%Tuple._bind_param..sQ   (A'*2&6    r)rziprrrs ` `rrzTuple._bind_paramsV     ,/sD4D+E+E      *,, rr) rrrrrNrrrr<rSs@rrrsn  44444BX        rrcDeZdZdZdZddZefdZdZe dZ dS) CaseaRepresent a ``CASE`` expression. :class:`.Case` is produced using the :func:`.case` factory function, as in:: from sqlalchemy import case stmt = select([users_table]). where( case( [ (users_table.c.name == 'wendy', 'W'), (users_table.c.name == 'jack', 'J') ], else_='E' ) ) Details on :class:`.Case` usage is at :func:`.case`. .. seealso:: :func:`.case` caseNch tj|}n#t$rYnwxYw| d|D}n d|D}|r!t|ddj}nd}|d|_nt ||_||_||_|t ||_dSd|_dS)aProduce a ``CASE`` expression. The ``CASE`` construct in SQL is a conditional object that acts somewhat analogously to an "if/then" construct in other languages. It returns an instance of :class:`.Case`. :func:`.case` in its usual form is passed a list of "when" constructs, that is, a list of conditions and results as tuples:: from sqlalchemy import case stmt = select([users_table]).\ where( case( [ (users_table.c.name == 'wendy', 'W'), (users_table.c.name == 'jack', 'J') ], else_='E' ) ) The above statement will produce SQL resembling:: SELECT id, name FROM user WHERE CASE WHEN (name = :name_1) THEN :param_1 WHEN (name = :name_2) THEN :param_2 ELSE :param_3 END When simple equality expressions of several values against a single parent column are needed, :func:`.case` also has a "shorthand" format used via the :paramref:`.case.value` parameter, which is passed a column expression to be compared. In this form, the :paramref:`.case.whens` parameter is passed as a dictionary containing expressions to be compared against keyed to result expressions. The statement below is equivalent to the preceding statement:: stmt = select([users_table]).\ where( case( {"wendy": "W", "jack": "J"}, value=users_table.c.name, else_='E' ) ) The values which are accepted as result values in :paramref:`.case.whens` as well as with :paramref:`.case.else_` are coerced from Python literals into :func:`.bindparam` constructs. SQL expressions, e.g. :class:`_expression.ColumnElement` constructs, are accepted as well. To coerce a literal string expression into a constant expression rendered inline, use the :func:`_expression.literal_column` construct, as in:: from sqlalchemy import case, literal_column case( [ ( orderline.c.qty > 100, literal_column("'greaterthan100'") ), ( orderline.c.qty > 10, literal_column("'greaterthan10'") ) ], else_=literal_column("'lessthan10'") ) The above will render the given constants without using bound parameters for the result values (but still for the comparison values), as in:: CASE WHEN (orderline.qty > :qty_1) THEN 'greaterthan100' WHEN (orderline.qty > :qty_2) THEN 'greaterthan10' ELSE 'lessthan10' END :param whens: The criteria to be compared against, :paramref:`.case.whens` accepts two different forms, based on whether or not :paramref:`.case.value` is used. In the first form, it accepts a list of 2-tuples; each 2-tuple consists of ``(, )``, where the SQL expression is a boolean expression and "value" is a resulting value, e.g.:: case([ (users_table.c.name == 'wendy', 'W'), (users_table.c.name == 'jack', 'J') ]) In the second form, it accepts a Python dictionary of comparison values mapped to a resulting value; this form requires :paramref:`.case.value` to be present, and values will be compared using the ``==`` operator, e.g.:: case( {"wendy": "W", "jack": "J"}, value=users_table.c.name ) :param value: An optional SQL expression which will be used as a fixed "comparison point" for candidate values within a dictionary passed to :paramref:`.case.whens`. :param else\_: An optional SQL expression which will be the evaluated result of the ``CASE`` construct if all expressions within :paramref:`.case.whens` evaluate to false. When omitted, most databases will produce a result of NULL if none of the "when" expressions evaluate to true. Nctg|]5\}}t|t|f6Sr)r&rrrQrs rrz!Case.__init__.. sNQ#1%%00224Ea4H4HIrctg|]5\}}t|t|f6Sr) _no_literalsrr&rs rrz!Case.__init__.. sLQa++--/@/C/CDr) rdictlike_iteritemsrrr*r8r&whenselse_)rPrr8rwhenlistr%s rrNz Case.__init__sv +E22EE    D   #HH #H  "&&r*/EEE =DJJ*511DJ   *511DJJJDJJJs  $$c |j|jfi|_fd|jD|_|j|jfi|_dSdS)Nc:g|]\}}|fi|fifSrr)rxyrgrs rrz(Case._copy_internals.. s>NNN41auuQ~~"~~uuQ~~"~~6NNNrr8rrrs ``rrzCase._copy_internals sv : !tz00R00DJNNNNN4:NNN : !tz00R00DJJJ " !rc+xK|j |jV|jD] \}}|V|V|j |jVdSdSrr)rPrvrrs rrzCase.get_children si : !*   J  DAqGGGGGGG : !*      " !rcpttjd|DS)Ncg|] }|j Srrrrs rrz&Case._from_objects.. sKKK!aoKKKr)rrrrrTs rrzCase._from_objects s9 OKKt7H7H7J7JKKK L   rr rrrrrrNrrrrrrrrr r s4NZZZZx%+1111  X   rr c&t||dS)aProduce a :class:`.ColumnClause` object that has the :paramref:`_expression.column.is_literal` flag set to True. :func:`_expression.literal_column` is similar to :func:`_expression.column`, except that it is more often used as a "standalone" column expression that renders exactly as stated; while :func:`_expression.column` stores a string name that will be assumed to be part of a table and may be quoted as such, :func:`_expression.literal_column` can be that, or any other arbitrary column-oriented expression. :param text: the text of the expression; can be any SQL expression. Quoting rules will not be applied. To specify a column-name expression which should be subject to quoting rules, use the :func:`column` function. :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine` object which will provide result-set translation and additional expression semantics for this column. If left as ``None`` the type will be :class:`.NullType`. .. seealso:: :func:`_expression.column` :func:`_expression.text` :ref:`sqlexpression_literal_column` T)r% is_literalr)ryr%s rliteral_columnr# sB Ed ; ; ;;rcBeZdZdZdZdZefdZdZe dZ dS)r)a`Represent a ``CAST`` expression. :class:`.Cast` is produced using the :func:`.cast` factory function, as in:: from sqlalchemy import cast, Numeric stmt = select([ cast(product_table.c.unit_price, Numeric(10, 4)) ]) Details on :class:`.Cast` usage is at :func:`.cast`. .. seealso:: :ref:`coretutorial_casts` :func:`.cast` :func:`.type_coerce` - an alternative to CAST that coerces the type on the Python side only, which is often sufficient to generate the correct SQL and data coercion. r+ctj||_t||j|_t |j|_dS)a(Produce a ``CAST`` expression. :func:`.cast` returns an instance of :class:`.Cast`. E.g.:: from sqlalchemy import cast, Numeric stmt = select([ cast(product_table.c.unit_price, Numeric(10, 4)) ]) The above statement will produce SQL resembling:: SELECT CAST(unit_price AS NUMERIC(10, 4)) FROM product The :func:`.cast` function performs two distinct functions when used. The first is that it renders the ``CAST`` expression within the resulting SQL string. The second is that it associates the given type (e.g. :class:`.TypeEngine` class or instance) with the column expression on the Python side, which means the expression will take on the expression operator behavior associated with that type, as well as the bound-value handling and result-row-handling behavior of the type. .. versionchanged:: 0.9.0 :func:`.cast` now applies the given type to the expression such that it takes effect on the bound-value, e.g. the Python-to-database direction, in addition to the result handling, e.g. database-to-Python, direction. An alternative to :func:`.cast` is the :func:`.type_coerce` function. This function performs the second task of associating an expression with a specific type, but does not render the ``CAST`` expression in SQL. :param expression: A SQL expression, such as a :class:`_expression.ColumnElement` expression or a Python string which will be coerced into a bound literal value. :param type\_: A :class:`.TypeEngine` class or instance indicating the type to which the ``CAST`` should apply. .. seealso:: :ref:`coretutorial_casts` :func:`.type_coerce` - an alternative to CAST that coerces the type on the Python side only, which is often sufficient to generate the correct SQL and data coercion. r$N)r to_instancer*r&rArfrgrPr+r%s rrNz Cast.__init__ sBl(// ' $)DDD $TY//rc R||jfi||_||jfi||_dSrrArgrs rrzCast._copy_internals, s<eDK..2.. %66266rc |j|jfSrr)rs rrzCast.get_children0 s{DO++rc|jjSrrArrTs rrzCast._from_objects3 {((rNr rrrr)r) sx2N808080t%+7777,,,))X)))rr)cjeZdZdZdZdZefdZdZe dZ e j dZ d d ZdS) TypeCoerceaRepresent a Python-side type-coercion wrapper. :class:`.TypeCoerce` supplies the :func:`_expression.type_coerce` function; see that function for usage details. .. versionchanged:: 1.1 The :func:`.type_coerce` function now produces a persistent :class:`.TypeCoerce` wrapper object rather than translating the given object in place. .. seealso:: :func:`_expression.type_coerce` :func:`.cast` type_coercecntj||_t||j|_dS)a Associate a SQL expression with a particular type, without rendering ``CAST``. E.g.:: from sqlalchemy import type_coerce stmt = select([type_coerce(log_table.date_string, StringDateTime())]) The above construct will produce a :class:`.TypeCoerce` object, which does not modify the rendering in any way on the SQL side, with the possible exception of a generated label if used in a columns clause context:: SELECT date_string AS anon_1 FROM log When result rows are fetched, the ``StringDateTime`` type processor will be applied to result rows on behalf of the ``date_string`` column. .. note:: the :func:`.type_coerce` construct does not render any SQL syntax of its own, including that it does not imply parenthesization. Please use :meth:`.TypeCoerce.self_group` if explicit parenthesization is required. In order to provide a named label for the expression, use :meth:`_expression.ColumnElement.label`:: stmt = select([ type_coerce(log_table.date_string, StringDateTime()).label('date') ]) A type that features bound-value handling will also have that behavior take effect when literal values or :func:`.bindparam` constructs are passed to :func:`.type_coerce` as targets. For example, if a type implements the :meth:`.TypeEngine.bind_expression` method or :meth:`.TypeEngine.bind_processor` method or equivalent, these functions will take effect at statement compilation/execution time when a literal value is passed, as in:: # bound-value handling of MyStringType will be applied to the # literal value "some string" stmt = select([type_coerce("some string", MyStringType)]) When using :func:`.type_coerce` with composed expressions, note that **parenthesis are not applied**. If :func:`.type_coerce` is being used in an operator context where the parenthesis normally present from CAST are necessary, use the :meth:`.TypeCoerce.self_group` method:: >>> some_integer = column("someint", Integer) >>> some_string = column("somestr", String) >>> expr = type_coerce(some_integer + 5, String) + some_string >>> print(expr) someint + :someint_1 || somestr >>> expr = type_coerce(some_integer + 5, String).self_group() + some_string >>> print(expr) (someint + :someint_1) || somestr :param expression: A SQL expression, such as a :class:`_expression.ColumnElement` expression or a Python string which will be coerced into a bound literal value. :param type\_: A :class:`.TypeEngine` class or instance indicating the type to which the expression is coerced. .. seealso:: :ref:`coretutorial_casts` :func:`.cast` r$N)rr&r*r&rAr's rrNzTypeCoerce.__init__L s1V(// ' $)DDD rc b||jfi||_|jdddS)Ntyped_expression)rArHr\rs rrzTypeCoerce._copy_internals s<eDK..2..  ,d33333rc |jfSrr@rs rrzTypeCoerce.get_children s  ~rc|jjSrr,rTs rrzTypeCoerce._from_objects r-rct|jtr'|j}|j|_|S|jSr)rArAr7rr*)rPbps rr3zTypeCoerce.typed_expression s? dk= 1 1 ##%%BiBGI; rNcx|j|}||jurt||jS|Sr)rArr/r*)rPrgroupeds rrzTypeCoerce.self_group s>+(((99 $+ % %gty11 1Krr)rrrrrrNrrrrrrrr3rrrrr/r/8 s"#NLELELE\%+4444))X) rr/cBeZdZdZdZdZefdZdZe dZ dS)Extractz=Represent a SQL EXTRACT clause, ``extract(field FROM expr)``.extractc `tj|_||_t |d|_dS)zReturn a :class:`.Extract` construct. This is typically available as :func:`.extract` as well as ``func.extract`` from the :data:`.func` namespace. N)r INTEGERTYPEr*fieldr&r-)rPr?r-rvs rrNzExtract.__init__ s*(  %dD11 rc ,||jfi||_dSrr-rs rrzExtract._copy_internals s!E$)**r** rc |jfSrrArs rrzExtract.get_children s  |rc|jjSr)r-rrTs rrzExtract._from_objects s y&&rNr rrrr;r; sqGGN 2 2 2%+++++''X'''rr;c<eZdZdZdZdZefdZedZ dS)_label_referenceaWrap a column expression as it appears in a 'reference' context. This expression is any that includes an _order_by_label_element, which is a Label, or a DESC / ASC construct wrapping a Label. The production of _label_reference() should occur when an expression is added to this context; this includes the ORDER BY or GROUP BY of a SELECT statement, as well as a few other places, such as the ORDER BY within an OVER clause. label_referencec||_dSrrrPrs rrNz_label_reference.__init__  rc ,||jfi||_dSrrHrs rrz _label_reference._copy_internals !uT\00R00 rcdS)NrrrTs rrz_label_reference._from_objects srrN) rrrrrrNrrrrrrrrErE sh  'N%+1111XrrEc8eZdZdZdZejdZdS)_textual_label_referencetextual_label_referencec||_dSrrHrIs rrNz!_textual_label_reference.__init__ rJrc@t|jSr)rkrrrTs r _text_clausez%_textual_label_reference._text_clause s&&t|444rN)rrrrrNrrrSrrrrOrO sG.N 55555rrOceZdZdZdZ ddZedZedZedZ ed Z ed Z e d Z e d Zefd ZdZdZdZddZdS)raDefine a 'unary' expression. A unary expression has a single column expression and an operator. The operator can be placed on the left (where it is called the 'operator') or right (where it is called the 'modifier') of the column expression. :class:`.UnaryExpression` is the basis for several unary operators including those used by :func:`.desc`, :func:`.asc`, :func:`.distinct`, :func:`.nullsfirst` and :func:`.nullslast`. unaryNFc||_||_||jp|j|_t j||_||_||_dSr) rmodifierrrrr&r*rwraps_column_expression)rPrrrWr%rrXs rrNzUnaryExpression.__init__ sc!   ))M2T]*   (//  '>$$$rcTtt|tjdS)aVProduce the ``NULLS FIRST`` modifier for an ``ORDER BY`` expression. :func:`.nullsfirst` is intended to modify the expression produced by :func:`.asc` or :func:`.desc`, and indicates how NULL values should be handled when they are encountered during ordering:: from sqlalchemy import desc, nullsfirst stmt = select([users_table]).order_by( nullsfirst(desc(users_table.c.name))) The SQL expression from the above would resemble:: SELECT id, name FROM user ORDER BY name DESC NULLS FIRST Like :func:`.asc` and :func:`.desc`, :func:`.nullsfirst` is typically invoked from the column expression itself using :meth:`_expression.ColumnElement.nullsfirst`, rather than as its standalone function version, as in:: stmt = select([users_table]).order_by( users_table.c.name.desc().nullsfirst()) .. seealso:: :func:`.asc` :func:`.desc` :func:`.nullslast` :meth:`_expression.Select.order_by` FrWrX)r_literal_as_label_referencer nullsfirst_oprcolumns r_create_nullsfirstz"UnaryExpression._create_nullsfirst s0L ' / /,$)    rcTtt|tjdS)aOProduce the ``NULLS LAST`` modifier for an ``ORDER BY`` expression. :func:`.nullslast` is intended to modify the expression produced by :func:`.asc` or :func:`.desc`, and indicates how NULL values should be handled when they are encountered during ordering:: from sqlalchemy import desc, nullslast stmt = select([users_table]).order_by( nullslast(desc(users_table.c.name))) The SQL expression from the above would resemble:: SELECT id, name FROM user ORDER BY name DESC NULLS LAST Like :func:`.asc` and :func:`.desc`, :func:`.nullslast` is typically invoked from the column expression itself using :meth:`_expression.ColumnElement.nullslast`, rather than as its standalone function version, as in:: stmt = select([users_table]).order_by( users_table.c.name.desc().nullslast()) .. seealso:: :func:`.asc` :func:`.desc` :func:`.nullsfirst` :meth:`_expression.Select.order_by` FrZ)rr[r nullslast_opr]s r_create_nullslastz!UnaryExpression._create_nullslastE s0L ' / /+$)    rcTtt|tjdS)aZProduce a descending ``ORDER BY`` clause element. e.g.:: from sqlalchemy import desc stmt = select([users_table]).order_by(desc(users_table.c.name)) will produce SQL as:: SELECT id, name FROM user ORDER BY name DESC The :func:`.desc` function is a standalone version of the :meth:`_expression.ColumnElement.desc` method available on all SQL expressions, e.g.:: stmt = select([users_table]).order_by(users_table.c.name.desc()) :param column: A :class:`_expression.ColumnElement` (e.g. scalar SQL expression) with which to apply the :func:`.desc` operation. .. seealso:: :func:`.asc` :func:`.nullsfirst` :func:`.nullslast` :meth:`_expression.Select.order_by` FrZ)rr[rdesc_opr]s r _create_desczUnaryExpression._create_descq s0J ' / /&$)    rcTtt|tjdS)aSProduce an ascending ``ORDER BY`` clause element. e.g.:: from sqlalchemy import asc stmt = select([users_table]).order_by(asc(users_table.c.name)) will produce SQL as:: SELECT id, name FROM user ORDER BY name ASC The :func:`.asc` function is a standalone version of the :meth:`_expression.ColumnElement.asc` method available on all SQL expressions, e.g.:: stmt = select([users_table]).order_by(users_table.c.name.asc()) :param column: A :class:`_expression.ColumnElement` (e.g. scalar SQL expression) with which to apply the :func:`.asc` operation. .. seealso:: :func:`.desc` :func:`.nullsfirst` :func:`.nullslast` :meth:`_expression.Select.order_by` FrZ)rr[rasc_opr]s r _create_asczUnaryExpression._create_asc s0H ' / /%$)    rcdt|}t|tj|jdS)aProduce an column-expression-level unary ``DISTINCT`` clause. This applies the ``DISTINCT`` keyword to an individual column expression, and is typically contained within an aggregate function, as in:: from sqlalchemy import distinct, func stmt = select([func.count(distinct(users_table.c.name))]) The above would produce an expression resembling:: SELECT COUNT(DISTINCT name) FROM user The :func:`.distinct` function is also available as a column-level method, e.g. :meth:`_expression.ColumnElement.distinct`, as in:: stmt = select([func.count(users_table.c.name.distinct())]) The :func:`.distinct` operator is different from the :meth:`_expression.Select.distinct` method of :class:`_expression.Select`, which produces a ``SELECT`` statement with ``DISTINCT`` applied to the result set as a whole, e.g. a ``SELECT DISTINCT`` expression. See that method for further information. .. seealso:: :meth:`_expression.ColumnElement.distinct` :meth:`_expression.Select.distinct` :data:`.func` Frr%rX)r&rr distinct_opr*rr-s r_create_distinctz UnaryExpression._create_distinct s:J!&& *)$)     rc\|jtjtjfvr |jjSdSr)rWrrdrgrrrTs rrz'UnaryExpression._order_by_label_element s* =Y. 0@A A A<7 74rc|jjSrrrrTs rrzUnaryExpression._from_objects |))rc ,||jfi||_dSrrHrs rrzUnaryExpression._copy_internals rLrc |jfSrrHrs rrzUnaryExpression.get_children  rc t|to7|j|jko'|j|jko|jj|jfi|S)zcCompare this :class:`UnaryExpression` against the given :class:`_expression.ClauseElement`.)rArrrWrrrs rrzUnaryExpression.compare s[ uo . . : / : / :% $U]99b99  rcz|j3t|j|j|j|j|j|jS|jjtj jurKt| tj tj tj |jdSt|S)N)rrrWr%rXr)rr%rXr)rrrrrWr*rXrrrrrr?rDrrTs rrzUnaryExpression._negate s ; "" }i(,(D  Y %)=)L L L" 66"*(,(D  !((.. .rcf|jr)tj|j|rt|S|Sr)rrrrrs rrzUnaryExpression.self_group$ s3 = Y3DM7KK D>> !Kr)NNNNFr)rrrrrrNrr_rbrerhrmrrrrrrrrrrrrrr sf  N  %????$) ) [) V) ) [) V( ( [( T' ' [' R* * [* XX **X*%+1111    ///*rrcJeZdZdZedZedZdZdZdS)CollectionAggregatea Forms the basis for right-hand collection operator modifiers ANY and ALL. The ANY and ALL keywords are available in different ways on different backends. On PostgreSQL, they only work for an ARRAY type. On MySQL, they only work for subqueries. ct|}|jr$t|dr|}|}t |t jtj dS)aProduce an ANY expression. This may apply to an array type for some dialects (e.g. postgresql), or to a subquery for others (e.g. mysql). e.g.:: # postgresql '5 = ANY (somearray)' expr = 5 == any_(mytable.c.somearray) # mysql '5 = ANY (SELECT value FROM table)' expr = 5 == any_(select([table.c.value])) .. versionadded:: 1.1 .. seealso:: :func:`_expression.all_` as_scalarFrj) r&rrr{rryrrrrrls r _create_anyzCollectionAggregate._create_any5 st*!&&   $'$ "<"< $>>##D  " %#$)     rct|}|jr$t|dr|}|}t |t jtj dS)aProduce an ALL expression. This may apply to an array type for some dialects (e.g. postgresql), or to a subquery for others (e.g. mysql). e.g.:: # postgresql '5 = ALL (somearray)' expr = 5 == all_(mytable.c.somearray) # mysql '5 = ALL (SELECT value FROM table)' expr = 5 == all_(select([table.c.value])) .. versionadded:: 1.1 .. seealso:: :func:`_expression.any_` r{Frj) r&rrr{rryrrrrrls r _create_allzCollectionAggregate._create_allV st*!&&   $'$ "<"< $>>##D  " %#$)     rctj|stjdd|d<|jjtj|g|Ri|S)N2Only comparison operators may be used with ANY/ALLTreverse)r is_comparisonrrrMrmirrorrs rrzCollectionAggregate.operatey si&r** #D !y&t&y'7';';NeNNNvNNNrc Vtj|rJtjd)Nr)rrrrrs rrz#CollectionAggregate.reverse_operate s1*2..... @   rN) rrrrrr|r~rrrrrryry+ sw  [ @  [ DOOO     rryc"eZdZdZddZdZdS)rc||_tj|_||_||_d|_d|_|j|_dS)NT) rrrr*rrrWrXr:)rPrrrs rrNzAsBoolean.__init__ sA (     '+$&-&D###rNc|Srrrs rrzAsBoolean.self_group  rct|jttfr|jSt |j|j|jSr)rArrrrrrrrTs rrzAsBoolean._negate sG dlUFO 4 4 G<'')) )T\4; FF Frr)rrrrNrrrrrrr sNEEEGGGGGrrceZdZdZdZdZ ddZdZeZe dZ e dZ e fd Z d Zd Zdd Zfd ZxZS)r'aRepresent an expression that is ``LEFT RIGHT``. A :class:`.BinaryExpression` is generated automatically whenever two column expressions are used in a Python binary expression:: >>> from sqlalchemy.sql import column >>> column('a') + column('b') >>> print(column('a') + column('b')) a + b binaryTNct|tjrtj|}||f|_|||_|||_||_ tj ||_ ||_ tj||_| i|_dS||_dSr)rAr string_typesr custom_op_origrleftrightrrr&r*rrr: modifiers)rPrrrr%rrs rrNzBinaryExpression.__init__ s h 1 2 2 5 *844HE] OOHO55 %%h%77   (//  &/&:8&D&D#  DNNN&DNNNrc|jtjtjfvrF|t|jdt|jdSt d)Nrrr)reqner#rrrTs rrzBinaryExpression.__bool__ sW =X[(+6 6 6==djm!4!4d4:a=6I6IJJ JIJJ Jrc4tj|jSr)rrrrTs rrzBinaryExpression.is_comparison s&t}555rc4|jj|jjzSr)rrrrTs rrzBinaryExpression._from_objects sy&)AAArc R||jfi||_||jfi||_dSrrrrs rrz BinaryExpression._copy_internals s<E$)**r** U4:,,,, rc |j|jfSrrrs rrzBinaryExpression.get_children sy$*$$rc >t|to|j|jkox|jj|jfi|r|jj|jfi|pHt j|jo/|jj|jfi|o|jj|jfi|S)z[Compare this :class:`BinaryExpression` against the given :class:`BinaryExpression`.)rAr'rrrrris_commutativers rrzBinaryExpression.compare s u. / /  / " !%*3333:&DJ&u{99b99,T];;=) )%+<<<<=* *5:<<<< rcXtj|j|rt|S|Sr)rrrrrs rrzBinaryExpression.self_group s*  !$- 9 9 D>> !Krc|j3t|j|j|j|j|j|jStt|S)N)rr%r) rr'rrrr*rrrrs rrzBinaryExpression._negate s_ ; "#   }i.  )40088:: :r)NNNr)rrrrrr:rNrrrrrrrrrrrr<rSs@rr'r' s   N! IM''''(KKK K 66X6BBXB%+----%%%   $ ; ; ; ; ; ; ; ; ;rr'c$eZdZdZdZdZddZdS)SlicezRepresent SQL for a Python array-slice object. This is not a specific SQL construct at this level, but may be interpreted by specific dialects, e.g. PostgreSQL. slicecR||_||_||_tj|_dSr)startstopsteprrr*)rPrrrs rrNzSlice.__init__ s%   % rNc&|tjusJ|Sr)rgetitemrs rrzSlice.self_group s(***** rr)rrrrrrNrrrrrr sHN&&& rrceZdZdZdS)IndexExpressionzJRepresent the class of expressions that are like an "index" operation.N)rrrrrrrrr s DrrceZdZdZdZdZddZejdZ e dZ e dZ e fd Zd Ze d Ze d Zd ZdZdZdZdS)rz/Represent a grouping within a column expressiongroupingcT||_t|dtj|_dSNr*)rrrrr*rIs rrNzGrouping.__init__% s# GVX->?? rNc|Srrrs rrzGrouping.self_group) rrc|jjSrrr:rTs rr:zGrouping._is_implicitly_boolean, |22rc|jSr)r5rTs rr6zGrouping._key_label0 s {rc<t|jddp|jS)Nr5)rrrrTs rr5zGrouping._label4 st|Xt44GGrc ,||jfi||_dSrrHrs rrzGrouping._copy_internals8 rLrc |jfSrrHrs rrzGrouping.get_children; rtrcJt|jtr|jgSgSr)rArrLrTs rrzGrouping._proxies> s% dlM 2 2 L> !Irc|jjSrrprTs rrzGrouping._from_objectsE rqrc,t|j|Sr)rr)rPattrs rrzGrouping.__getattr__I st|T***rc |j|jdS)Nrr*rrTs rr^zGrouping.__getstate__L s<;;;rc:|d|_|d|_dS)Nrr*rr_s rrazGrouping.__setstate__O sY' &M rc jt|to|j|jSr)rArrrrs rrzGrouping.compareS s2%** t|/C/C M0 0  rr)rrrrrrNrrrr:rr6r5rrrrrrr^rarrrrrr s799N@@@ 333XHHXH%+1111X **X*+++<<<"""     rrRANGE_UNBOUNDED RANGE_CURRENTceZdZdZdZdZdZdZ ddZdZ dZ e e j ddd Ze jd Zd Zefd Ze d ZdS)OveraRepresent an OVER clause. This is a special operator against a so-called "window" function, as well as any aggregate function, which produces results relative to the result set itself. It's supported only by certain database backends. overNc||_|(ttj|dti|_|(ttj|dti|_|r9|||_|rtj dd|_ dS|r#|||_ d|_dSdx|_ |_dS)aI Produce an :class:`.Over` object against a function. Used against aggregate or so-called "window" functions, for database backends that support window functions. :func:`_expression.over` is usually called using the :meth:`.FunctionElement.over` method, e.g.:: func.row_number().over(order_by=mytable.c.some_column) Would produce:: ROW_NUMBER() OVER(ORDER BY some_column) Ranges are also possible using the :paramref:`.expression.over.range_` and :paramref:`.expression.over.rows` parameters. These mutually-exclusive parameters each accept a 2-tuple, which contains a combination of integers and None:: func.row_number().over( order_by=my_table.c.some_column, range_=(None, 0)) The above would produce:: ROW_NUMBER() OVER(ORDER BY some_column RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) A value of ``None`` indicates "unbounded", a value of zero indicates "current row", and negative / positive integers indicate "preceding" and "following": * RANGE BETWEEN 5 PRECEDING AND 10 FOLLOWING:: func.row_number().over(order_by='x', range_=(-5, 10)) * ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:: func.row_number().over(order_by='x', rows=(None, 0)) * RANGE BETWEEN 2 PRECEDING AND UNBOUNDED FOLLOWING:: func.row_number().over(order_by='x', range_=(-2, None)) * RANGE BETWEEN 1 FOLLOWING AND 3 FOLLOWING:: func.row_number().over(order_by='x', range_=(1, 3)) .. versionadded:: 1.1 support for RANGE / ROWS within a window :param element: a :class:`.FunctionElement`, :class:`.WithinGroup`, or other compatible construct. :param partition_by: a column element or string, or a list of such, that will be used as the PARTITION BY clause of the OVER construct. :param order_by: a column element or string, or a list of such, that will be used as the ORDER BY clause of the OVER construct. :param range\_: optional range clause for the window. This is a tuple value which can contain integer values or ``None``, and will render a RANGE BETWEEN PRECEDING / FOLLOWING clause. .. versionadded:: 1.1 :param rows: optional rows clause for the window. This is a tuple value which can contain integer values or None, and will render a ROWS BETWEEN PRECEDING / FOLLOWING clause. .. versionadded:: 1.1 This function is also available from the :data:`~.expression.func` construct itself via the :meth:`.FunctionElement.over` method. .. seealso:: :data:`.expression.func` :func:`_expression.within_group` Nrz*'range_' and 'rows' are mutually exclusive) rrrto_listr[order_by partition_by_interpret_rangerange_rrrows)rPrrrrrs rrNz Over.__init__q sf  &h''!<DM  # *l++!!<!!D   +//77DK !'@!  +--d33DIDKKK&* *DI rcP|j|j|j|j|j|jffSr)rFrrrrrrTs r __reduce__zOver.__reduce__ s0~ L   M K I    rcNt|trt|dkrtjd|dt }nc t |d}|dkrt}n?#t$r2}tj tjd|Yd}~nd}~wwxYw|dt }nc t |d}|dkrt}n?#t$r2}tj tjd|Yd}~nd}~wwxYw||fS)Nrz2-tuple expected for range/rowsrz(Integer or None expected for range valuerr) rAtuplerrrrintr ValueErrorrr)rPrlowerruppers rrzOver._interpret_range s&%(( GCKK1,<,<#$EFF F !9 #EE *F1IA::)E    %B%(   !9 #EE *F1IA::)E    %B%(  e|s0A11 B-;(B((B-C$$ D .(DD z1.1zthe :attr:`.Over.func` member of the :class:`.Over` class is deprecated and will be removed in a future release. Please refer to the :attr:`.Over.element` attribute.c|jS)zIthe element referred to by this :class:`.Over` clause. rHrTs rfuncz Over.func s |rc|jjSrrrTs rr*z Over.types |  rc >d|j|j|jfDS)Ncg|]}||Srrrs rrz%Over.get_children..!s%   } }}rrrrrs rrzOver.get_children s1  lD$5t}E    rc ||jfi||_|j||jfi||_|j||jfi||_dSdSrrrs rrzOver._copy_internals'sruT\00R00   ( %d&7 > >2 > >D  = $!E$-66266DMMM % $rcpttjd|j|j|jfDS)Nc g|] }||j Srrrs rrz&Over._from_objects..2'}O$}}r)rrrrrrrTs rrzOver._from_objects.sH O"lD,=t}M    rr)rrrrrrrrrNrrrrrrrr*rrrrrrrrr] sNHLGLPk+k+k+k+Z   $$$LT_  ?  X !!!   %+7777   X    rrcneZdZdZdZdZdZd dZej dZ dZ e fdZ ed ZdS) WithinGroupaRepresent a WITHIN GROUP (ORDER BY) clause. This is a special operator against so-called "ordered set aggregate" and "hypothetical set aggregate" functions, including ``percentile_cont()``, ``rank()``, ``dense_rank()``, etc. It's supported only by certain database backends, such as PostgreSQL, Oracle and MS SQL Server. The :class:`.WithinGroup` construct extracts its type from the method :meth:`.FunctionElement.within_group_type`. If this returns ``None``, the function's ``.type`` is used. withingroupNcl||_|*ttj|dti|_dSdS)aProduce a :class:`.WithinGroup` object against a function. Used against so-called "ordered set aggregate" and "hypothetical set aggregate" functions, including :class:`.percentile_cont`, :class:`.rank`, :class:`.dense_rank`, etc. :func:`_expression.within_group` is usually called using the :meth:`.FunctionElement.within_group` method, e.g.:: from sqlalchemy import within_group stmt = select([ department.c.id, func.percentile_cont(0.5).within_group( department.c.salary.desc() ) ]) The above statement would produce SQL similar to ``SELECT department.id, percentile_cont(0.5) WITHIN GROUP (ORDER BY department.salary DESC)``. :param element: a :class:`.FunctionElement` construct, typically generated by :data:`~.expression.func`. :param \*order_by: one or more column elements that will be used as the ORDER BY clause of the WITHIN GROUP construct. .. versionadded:: 1.1 .. seealso:: :data:`.expression.func` :func:`_expression.over` Nr)rrrrr[r)rPrrs rrNzWithinGroup.__init__PsDH  &h''!<DMMM rc*t|||||S)zProduce an OVER clause against this :class:`.WithinGroup` construct. This function has the same signature as that of :meth:`.FunctionElement.over`. rrrrrrPrrrrs rrzWithinGroup.over{s* %     rcV|j|}||S|jjSr)rwithin_group_typer*)rPwgts rr*zWithinGroup.types,l,,T22 ?J<$ $rc 2d|j|jfDS)Ncg|]}||Srrrs rrz,WithinGroup.get_children..sJJJaAMMMMrrrrs rrzWithinGroup.get_childrensJJDL$-8JJJJrc d||jfi||_|j||jfi||_dSdSrrrs rrzWithinGroup._copy_internalssLuT\00R00 = $!E$-66266DMMM % $rcdttjd|j|jfDS)Nc g|] }||j Srrrs rrz-WithinGroup._from_objects..rr)rrrrrrTs rrzWithinGroup._from_objectssC O"lDM:    rr)rrrrrrrNrrrr*rrrrrrrrrr;s #NH)))V     %%%KKK%+7777    X    rrc|eZdZdZdZdZdZdZd dZd dZ e j dZ d Z efd Zed ZdS)FunctionFilteraRepresent a function FILTER clause. This is a special operator against aggregate and window functions, which controls which rows are passed to it. It's supported only by certain database backends. Invocation of :class:`.FunctionFilter` is via :meth:`.FunctionElement.filter`:: func.count(1).filter(True) .. versionadded:: 1.0.0 .. seealso:: :meth:`.FunctionElement.filter` funcfilterNc(||_|j|dS)aProduce a :class:`.FunctionFilter` object against a function. Used against aggregate and window functions, for database backends that support the "FILTER" clause. E.g.:: from sqlalchemy import funcfilter funcfilter(func.count(1), MyClass.name == 'some name') Would produce "COUNT(1) FILTER (WHERE myclass.name = 'some name')". This function is also available from the :data:`~.expression.func` construct itself via the :meth:`.FunctionElement.filter` method. .. versionadded:: 1.0.0 .. seealso:: :meth:`.FunctionElement.filter` N)rfilter)rPr criterions rrNzFunctionFilter.__init__s 0  Yrct|D]/}t|}|j|j|z|_(||_0|S)a Produce an additional FILTER against the function. This method adds additional criteria to the initial criteria set up by :meth:`.FunctionElement.filter`. Multiple criteria are joined together at SQL render time via ``AND``. )rrr)rPrs rrzFunctionFilter.filtersLi + +I3I>>I~)!%)!;!* rc*t|||||S)aProduce an OVER clause against this filtered function. Used against aggregate or so-called "window" functions, for database backends that support window functions. The expression:: func.rank().filter(MyClass.y > 5).over(order_by='x') is shorthand for:: from sqlalchemy import over, funcfilter over(funcfilter(func.rank(), MyClass.y > 5), order_by='x') See :func:`_expression.over` for a full description. rrrs rrzFunctionFilter.overs*$ %     rcbtjtj|rt|S|Sr)rr filter_oprrs rrzFunctionFilter.self_group s+  !)"5w ? ? D>> !Krc|jjSr)rr*rTs rr*zFunctionFilter.types y~rc 2d|j|jfDS)Ncg|]}||Srrrs rrz/FunctionFilter.get_children..sHHHa!----rrrrs rrzFunctionFilter.get_childrensHHDIt~6HHHHrc d||jfi||_|j||jfi||_dSdSrrrs rrzFunctionFilter._copy_internalssLE$)**r** > %"U4>88R88DNNN & %rcdttjd|j|jfDS)Nc g|] }||j Srrrs rrz0FunctionFilter._from_objects..!rr)rrrrrrTs rrzFunctionFilter._from_objectssC O"i8    rrr)rrrrrrrNrrrrrr*rrrrrrrrrrs&"NI   6,    4  III%+9999    X    rrc*eZdZdZdZddZdZejdZ ejdZ e dZ ejd Z ejd Zdd Zd Zd Ze dZe dZdZedfdZe dZddZdS)r-zRepresents a column label (AS). Represent a label, as typically applied to any column-level element using the ``AS`` sql keyword. r.Nc t|tr |j|_t|tr|j}t|t|r||_|j|_n5t dt|t|ddfz|_|jx|_ x|_|_ ||_ ||_ |g|_ dS)aReturn a :class:`Label` object for the given :class:`_expression.ColumnElement`. A label changes the name of an element in the columns clause of a ``SELECT`` statement, typically via the ``AS`` SQL keyword. This functionality is more conveniently available via the :meth:`_expression.ColumnElement.label` method on :class:`_expression.ColumnElement`. :param name: label name :param obj: a :class:`_expression.ColumnElement`. r0rr1N)rAr-r5r8rrr2rrr<r6_element_typer)rPrrr%s rrNzLabel.__init__4s" gu % % 1").D %(( &oG%(( &  DI"&)D  (4''66*J*JKKDI489<<4;    rc8|j|j|j|jffSr)rFrrrrTs rrzLabel.__reduce__Xs~ 4=$*EEErc|jjSrrrTs rr:zLabel._is_implicitly_boolean[rrc|jjSr)rr9rTs rr9zLabel._allow_label_resolve_s |00rc|SrrrTs rrzLabel._order_by_label_elementcs rc`tj|jpt|jddSr)rr&rrrrTs rr*z Label.typegs/# J >'$->>   rcL|jtjSr)rrras_rTs rrz Label.elementms}'' '>>>rcD||jj|Sr)_apply_to_innerrrrs rrzLabel.self_groupqs ##DM$b#nnn dm + +KtzBBB BKrc|jjSr)rr3rTs rr3zLabel.primary_key~s |''rc|jjSr)rr4rTs rr4zLabel.foreign_keyss |((rc |jfSrrHrs rrzLabel.get_childrenrtrFc V||jfi||_|jdd|jdd|r]tdt |t |jddfzx|_|_|jx|_ x|_ |_ dSdS)Nrr9r0rr1) rrHr\r2rrrrr8r<r5r6)rPrganonymize_labelsrs rrzLabel._copy_internalssdm22r22  )T*** 0$777  A.>d88WT\66BBCD// DI+8>>rTc|j}|jrdS|/|jr't|ddr-|jdddz|jzdz|z}n |jdz|z}t|dd8t|tr |j |_ n]t||j }nGt|jdd1t|trJt||jj }|r;||j vr2|}d}||j vr#|dzt|z}|dz }||j v#|}t|S|S)Nschema.r?rLr) rr"named_with_columnrr1replacerrArBrLrQrr)rPrr.r&r.r5counters rr)zColumnClause._gen_labelssj J ?) 4 ]q2]q(D)) ,((c22S816ACG$N t+tWd++7e[11;"&*EKK'tz::EE$//;&e[99999#E16<88 #AC<<"FG AC--!&s7||!;1 !AC--#E '' 'Krc@t|j|||j|dS)NT)rrr%r5)r7r<r*rs rrzColumnClause._bind_params/ H "*"i     rc `| o|jo|dup ||jk}||rt|p|jn|p|j|j||}| |j|_|g|_|j)|jj |j|_|r||j |j<|S)N)r%rr") r"rrUrr*r<rrNrrr) rPrrattachrrrr"rQs rr zColumnClause._make_proxys $ #    %49$    " %M$+$) , , ,#$))"!    <HAEV  " .'4<@@GGAN  +)*J  &r)NFN)Tr)NTFF)rrrrronupdaterserver_defaultserver_onupdate_is_multiparam_columnr!group_expirable_memoized_propertyr!rNrrr#rrrrrr6r5r7r/r)rr rrrrrs##JN<@@H@w@/!??AA_%_%_%_%B@@@*&&&''' HZ , ,E AAA  ***&&&??X?,,,,\    !! ))))))rrceZdZdZdZdS)r(r,c||_dSr)r,)rPr,s rrNzCollationClause.__init__s "rN)rrrrrNrrrr(r(s( N#####rr(cPeZdZdZejddiZdZdS)_IdentifiedClause identifiedrmFc||_dSr)ident)rPrDs rrNz_IdentifiedClause.__init__s  rN)rrrrr rr"rNrrrrArAsI!N#6<< urrAceZdZdZdS)SavepointClause savepointNrrrrrrrrFrFs NNNrrFceZdZdZdS)RollbackToSavepointClauserollback_to_savepointNrHrrrrJrJs,NNNrrJceZdZdZdS)ReleaseSavepointClauserelease_savepointNrHrrrrMrMs(NNNrrMc>eZdZdZdZfdZdZdZdZdZ xZ S)rBaRepresent a SQL identifier combined with quoting preferences. :class:`.quoted_name` is a Python unicode/str subclass which represents a particular identifier name along with a ``quote`` flag. This ``quote`` flag, when set to ``True`` or ``False``, overrides automatic quoting behavior for this identifier in order to either unconditionally quote or to not quote the name. If left at its default of ``None``, quoting behavior is applied to the identifier on a per-backend basis based on an examination of the token itself. A :class:`.quoted_name` object with ``quote=True`` is also prevented from being modified in the case of a so-called "name normalize" option. Certain database backends, such as Oracle, Firebird, and DB2 "normalize" case-insensitive names as uppercase. The SQLAlchemy dialects for these backends convert from SQLAlchemy's lower-case-means-insensitive convention to the upper-case-means-insensitive conventions of those backends. The ``quote=True`` flag here will prevent this conversion from occurring to support an identifier that's quoted as all lower case against such a backend. The :class:`.quoted_name` object is normally created automatically when specifying the name for key schema constructs such as :class:`_schema.Table`, :class:`_schema.Column`, and others. The class can also be passed explicitly as the name to any function that receives a name which can be quoted. Such as to use the :meth:`_engine.Engine.has_table` method with an unconditionally quoted name:: from sqlalchemy import create_engine from sqlalchemy.sql import quoted_name engine = create_engine("oracle+cx_oracle://some_dsn") engine.has_table(quoted_name("some_table", True)) The above logic will run the "has table" logic against the Oracle backend, passing the name exactly as ``"some_table"`` without converting to upper case. .. versionadded:: 0.9.0 .. versionchanged:: 1.2 The :class:`.quoted_name` construct is now importable from ``sqlalchemy.sql``, in addition to the previous location of ``sqlalchemy.sql.elements``. )rLrrc|dSt||r| |j|kr|Stt|||}||_|Sr)rArLrrBrG)rr8rLrPrFs rrGzquoted_name.__new__)sb =4 s # #  MU[E11L[#&&..sE::  rcFttj||jffSr)rBr text_typerLrTs rrzquoted_name.__reduce__:sT^D114:>>>rc`|jr|Stj|Sr)rLrrRrrTs r_memoized_method_lowerz"quoted_name._memoized_method_lower=- : 0K>$''--// /rc`|jr|Stj|Sr)rLrrRrrTs r_memoized_method_upperz"quoted_name._memoized_method_upperCrUrctjr<|dd}tjs|d}d|zSt|S)Nrrz'%s')rpy2krdecoderr)rP backslasheds rrzquoted_name.__repr__IsZ 9 &++g/ABBK9 :)0099 K' '<<%% %r) rrrr __slots__rGrrTrWrr<rSs@rrBrBs//b*I"???000 000 &&&&&&&rrBc4eZdZdZdZdfd ZdZdZxZS)_truncated_labelzVA unicode subclass used to identify symbolic " "names that may require truncation.rNczt|d|}tt||||S)NrL)rrr^rG)rr8rLrFs rrGz_truncated_label.__new__Ys7w..%s++33CFFFrcF|jtj||jffSr)rFrrRrLrTs rrz_truncated_label.__reduce__^s ~t 4 4djAAArc|SrrrPmap_s r apply_mapz_truncated_label.apply_maparrr) rrrrr\rGrrdr<rSs@rr^r^Ssu++IGGGGGG BBBrr^ceZdZdZdZdS)convaMark a string indicating that a name has already been converted by a naming convention. This is a string subclass that indicates a name that should not be subject to any further naming conventions. E.g. when we create a :class:`.Constraint` using a naming convention as follows:: m = MetaData(naming_convention={ "ck": "ck_%(table_name)s_%(constraint_name)s" }) t = Table('t', m, Column('x', Integer), CheckConstraint('x > 5', name='x5')) The name of the above constraint will be rendered as ``"ck_t_x5"``. That is, the existing name ``x5`` is used in the naming convention as the ``constraint_name`` token. In some situations, such as in migration scripts, we may be rendering the above :class:`.CheckConstraint` with a name that's already been converted. In order to make sure the name isn't double-modified, the new name is applied using the :func:`_schema.conv` marker. We can use this explicitly as follows:: m = MetaData(naming_convention={ "ck": "ck_%(table_name)s_%(constraint_name)s" }) t = Table('t', m, Column('x', Integer), CheckConstraint('x > 5', name=conv('ck_t_x5'))) Where above, the :func:`_schema.conv` marker indicates that the constraint name here is final, and the name will render as ``"ck_t_x5"`` and not ``"ck_t_ck_t_x5"`` .. versionadded:: 0.9.4 .. seealso:: :ref:`constraint_naming_conventions` rN)rrrrr\rrrrfrfes **XIIIrrf NONE_NAMEc(eZdZdZdZdZdZdZdS)r2zDA unicode subclass used to identify anonymously generated names.rc tttj|tj||jSrr2rBrrR__add__rLrs rrkz_anonymous_label.__add__sD &&tT^E-B-BCCTZ     rc tttjtj|||jSrrjrs r__radd__z_anonymous_label.__radd__sD &&t~e'<'.s===qQ]===rrrelementss r_expand_clonedrxs ?==H=== >>rc2tjd|DS)zXExpand tables into individual columns in the given list of column expressions. cg|] }|j Sr)rrs rrz%_select_iterables..sBBBAQ/BBBrrurvs r_select_iterablesr{s ?BBBBB CCrctt|t|tfd|DS)zReturn the intersection of sets a and b, counting any overlap between 'cloned' predecessors. The returned set is in terms of the entities present within 'a'. c3PK|] }|j|V!dSrrrJrelem all_overlaps rrz'_cloned_intersection..sMk66t7GHH rrrxrarrs @r_cloned_intersectionrshnQ''((55nQ6G6GHHK   rctt|t|tfd|DS)Nc3PK|] }|j|V!dSrr~rs rrz%_cloned_difference..sM+":":4;K"L"L rrrs @r_cloned_differencersfnQ''((55nQ6G6GHHK   rzsqlalchemy.sql.functionsczt|drt||jr|dS|S)Nr)rrAFunctionElementr.) functionsrs r_labeledrsF 7F # #z*((}}T"""rc,t|tS)zITrue if ``col`` is an instance of :class:`_expression.ColumnElement`.)rArL)rs r _is_columnrs c= ) ))rc\tj}t|id|ji|S)z2Locate Column objects within the given expression.r^)rrWrrX)rArs r _find_columnsr s/ ?  D VR(DH-... Krct|tjr|St|dr|} |jS#t $rYdSwxYwN__clause_element__)rArrrrr<rrHs r_column_as_keyrso'4,--w,--/,,..{ ttsA AAcNt|dr|S|Sr)rrrHs r_clause_element_as_exprr)s,w,--))+++rct|tjrt|St |dr|}t |Sr)rArrrOrrrrHs rr[r[0sW'4,--/'000 . / //,,.. G $ $$rct|tjrt|St |dr|}t|t r|jt|St|Sr) rArrrOrrrLrrErrHs r&_literal_and_labels_as_label_referencer:s'4,--/'000 . / //,,.. 7M**)  + 7((((((rc t|Sr)rrHs rrrJs G $ $$rcjt|tr|St|dr|St|tjr ||St|tjtfrt|Stj dt|z)Nrz=SQL expression object expected, got object of type %r instead) rArrrrrNoneTyper  _const_exprrrr*)r text_fallbacks r _literal_asrNs'9%%   . / /  ))+++ GT. / / }W%%% GdmT2 3 3 7### W  &   rcZ|rt|tSt|tSr)rrk_no_text_coercion)rallow_coercion_to_texts rrr^s+77J///7$5666rc,t|tSr)rrrHs r_literal_as_columnres w - --rct|}t| }tjdt j||rdnddz)NzTextual column expression %(column)r should be explicitly declared with text(%(column)r), or use %(literal_column)s(%(column)r) for more specificityr#r^)r^r#)r_guess_straight_columnmatchrrrellipses_string)rguess_is_literals r_no_column_coercionrisn'llG177@@@   *733..      rctj|dtj||rd|znddz|dS)NzX%(extra)sTextual SQL expression %(expr)r should be explicitly declared as text(%(expr)r)z%s )r-extrar)rrr)rexc_clsrrs rrrzso K 4,W55*/7R         rct|dr|St|tst jd|d|S)NrzAmbiguous literal: zl. Use the 'text()' function to indicate a SQL expression literal, or 'literal()' to indicate a bound value.)rrrArrrrHs rrrsfw,-- ))+++  + +&gg (   rcPt|t ot|d Sr)rArrrHs r _is_literalrs3'9-- - g%773rc*|dSt||Sr)_only_column_elementsrrs r_only_column_elements_or_nonerst$Wd333rc t|dr|}t|ts*t jd|d|dt ||S)Nrz6Column-based expression object expected for argument 'z '; got: 'z', type )rrrArLrrr*rs rrrstw,--/,,.. g} - - *.$$g H    Nrct|dr|St|ts#|t St |||dS|S)NrTr4)rrrArrr7)rrr%s rr&r&scw,--))+++  + + ?66M weDIII Irz^\w\S*$ct|tr|St|dr|St j|d}|1t|t jtfrt|Snt|dr|j S|dkrd}nGt|tj rtt|dSt|t||S)NrF)raiseerrr*T)r")rArrrrinspectrrr rrnumbersNumberrrr)rinsprs r_interpret_as_column_or_fromrs'9%%, . / /,))+++  g 6 6 6D | g t4 5 5 (w'' ' ( | $ $#~~ Ggn . .%CLLT::::G$$$ ,< = = ==rct|tttfr|S|tS|durtS|durtSt jd)NFTzExpected None, False, or True)rArrrrrrHs rrrsg'D&%011 A vv E  xx Dww ?@@@rcN|D]}|jjs |jcStjSr)r*_isnullrr)argsrs r_type_from_argsrs8 !!v~ 6MMM   rc |||}|2tjd|dt|ddd|jd|S)N)require_embeddedzGiven column 'z', attached to table 'rz7', failed to locate a corresponding column from table '')corresponding_columnrInvalidRequestErrorrr) fromclauser^rrQs r_corresponding_column_or_errorrsv''!1 (  A y%%vvwvw5555z7M7M7M O   HrceZdZdZfdZejdZejdZejdZ ejdZ ejdZ xZ S)AnnotatedColumnElementctj|||tj|dD]7}|j|d|j|8dS)N)rr<rF)rrNrLrMrKrHrr\)rPrrars rrNzAnnotatedColumnElement.__init__sv4&111 ''---, ( (D}  u--5 !!$''' ( (rctt||}tj||Sr)rrrerLrMrK)rPrargrFs rrez(AnnotatedColumnElement._with_annotationss=,d33EEfMM ''... rc|jjS)z'Pull 'name' from parent, if not present)_Annotated__elementrrTs rrzAnnotatedColumnElement.names',,rc|jjS)z(Pull 'table' from parent, if not present)rrrTs rrzAnnotatedColumnElement.table s'--rc|jjS)z&Pull 'key' from parent, if not present)rr<rTs rr<zAnnotatedColumnElement.keys'++rc|jjSr)rinforTs rrzAnnotatedColumnElement.infos',,rc|jjSr)rrrTs rrz!AnnotatedColumnElement.anon_labels'22r) rrrrNrerrrrr<rrr<rSs@rrrs(((  --- ... ,,, --- 3333333rr)Frr)tr __future__rrrrrCrrr annotationrbaser r r r r visitorsrrrrrrrr"r)r0r9r=rB_self_inspectsrDColumnOperatorsrLr7rfrkrrrrrrrrr r#r)r/r;rErOrryrr'rrrsymbolrrrrrr-rr(rArFrJrM MemoizedSlotsrRrBr^rf _NONE_NAME_generated_labelr2rrrrxr{rrrrrrrrr[rrrrrrrrrrrrr&rIrrrrrrrrrrs  (''''' !!!!!!""""""%%%%%%   25G5G5G5Gp@@@@, P P P P444 oooooIoood A A A A A I-}A A A H G G G G G MG G G T        iIiIiIiIiI]iIiIiIX'''''='''08)8)8)8)8)]8)8)8)v?(?(?(?(?(M?(?(?(DZZZZZZZZzB(B(B(B(B( MB(B(B(J55555J 555pM M M M M =M M M `!<!<!<!>>0 A A A!!!     "3"3"3"3"3Y"3"3"3"3"3rPK!L{[f[fcrud.pynu[# sql/crud.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Functions used by compiler.py to determine the parameters rendered within INSERT and UPDATE statements. """ import operator from . import dml from . import elements from .. import exc from .. import util REQUIRED = util.symbol( "REQUIRED", """ Placeholder for the value within a :class:`.BindParameter` which is required to be present when the statement is passed to :meth:`_engine.Connection.execute`. This symbol is typically used when a :func:`_expression.insert` or :func:`_expression.update` statement is compiled without parameter values present. """, ) ISINSERT = util.symbol("ISINSERT") ISUPDATE = util.symbol("ISUPDATE") ISDELETE = util.symbol("ISDELETE") def _setup_crud_params(compiler, stmt, local_stmt_type, **kw): restore_isinsert = compiler.isinsert restore_isupdate = compiler.isupdate restore_isdelete = compiler.isdelete should_restore = ( (restore_isinsert or restore_isupdate or restore_isdelete) or len(compiler.stack) > 1 or "visiting_cte" in kw ) if local_stmt_type is ISINSERT: compiler.isupdate = False compiler.isinsert = True elif local_stmt_type is ISUPDATE: compiler.isupdate = True compiler.isinsert = False elif local_stmt_type is ISDELETE: if not should_restore: compiler.isdelete = True else: assert False, "ISINSERT, ISUPDATE, or ISDELETE expected" try: if local_stmt_type in (ISINSERT, ISUPDATE): return _get_crud_params(compiler, stmt, **kw) finally: if should_restore: compiler.isinsert = restore_isinsert compiler.isupdate = restore_isupdate compiler.isdelete = restore_isdelete def _get_crud_params(compiler, stmt, **kw): """create a set of tuples representing column/string pairs for use in an INSERT or UPDATE statement. Also generates the Compiled object's postfetch, prefetch, and returning column collections, used for default handling and ultimately populating the ResultProxy's prefetch_cols() and postfetch_cols() collections. """ compiler.postfetch = [] compiler.insert_prefetch = [] compiler.update_prefetch = [] compiler.returning = [] # no parameters in the statement, no parameters in the # compiled params - return binds for all columns if compiler.column_keys is None and stmt.parameters is None: return [ (c, _create_bind_param(compiler, c, None, required=True)) for c in stmt.table.columns ] if stmt._has_multi_parameters: stmt_parameters = stmt.parameters[0] else: stmt_parameters = stmt.parameters # getters - these are normally just column.key, # but in the case of mysql multi-table update, the rules for # .key must conditionally take tablename into account ( _column_as_key, _getattr_col_key, _col_bind_name, ) = _key_getters_for_crud_column(compiler, stmt) # if we have statement parameters - set defaults in the # compiled params if compiler.column_keys is None: parameters = {} else: parameters = dict( (_column_as_key(key), REQUIRED) for key in compiler.column_keys if not stmt_parameters or key not in stmt_parameters ) # create a list of column assignment clauses as tuples values = [] if stmt_parameters is not None: _get_stmt_parameters_params( compiler, parameters, stmt_parameters, _column_as_key, values, kw ) check_columns = {} # special logic that only occurs for multi-table UPDATE # statements if compiler.isupdate and stmt._extra_froms and stmt_parameters: _get_multitable_params( compiler, stmt, stmt_parameters, check_columns, _col_bind_name, _getattr_col_key, values, kw, ) if compiler.isinsert and stmt.select_names: _scan_insert_from_select_cols( compiler, stmt, parameters, _getattr_col_key, _column_as_key, _col_bind_name, check_columns, values, kw, ) else: _scan_cols( compiler, stmt, parameters, _getattr_col_key, _column_as_key, _col_bind_name, check_columns, values, kw, ) if parameters and stmt_parameters: check = ( set(parameters) .intersection(_column_as_key(k) for k in stmt_parameters) .difference(check_columns) ) if check: raise exc.CompileError( "Unconsumed column names: %s" % (", ".join("%s" % c for c in check)) ) if stmt._has_multi_parameters: values = _extend_values_for_multiparams(compiler, stmt, values, kw) return values def _create_bind_param( compiler, col, value, process=True, required=False, name=None, **kw ): if name is None: name = col.key bindparam = elements.BindParameter( name, value, type_=col.type, required=required ) bindparam._is_crud = True if process: bindparam = bindparam._compiler_dispatch(compiler, **kw) return bindparam def _key_getters_for_crud_column(compiler, stmt): if compiler.isupdate and stmt._extra_froms: # when extra tables are present, refer to the columns # in those extra tables as table-qualified, including in # dictionaries and when rendering bind param names. # the "main" table of the statement remains unqualified, # allowing the most compatibility with a non-multi-table # statement. _et = set(stmt._extra_froms) def _column_as_key(key): str_key = elements._column_as_key(key) if hasattr(key, "table") and key.table in _et: return (key.table.name, str_key) else: return str_key def _getattr_col_key(col): if col.table in _et: return (col.table.name, col.key) else: return col.key def _col_bind_name(col): if col.table in _et: return "%s_%s" % (col.table.name, col.key) else: return col.key else: _column_as_key = elements._column_as_key _getattr_col_key = _col_bind_name = operator.attrgetter("key") return _column_as_key, _getattr_col_key, _col_bind_name def _scan_insert_from_select_cols( compiler, stmt, parameters, _getattr_col_key, _column_as_key, _col_bind_name, check_columns, values, kw, ): ( need_pks, implicit_returning, implicit_return_defaults, postfetch_lastrowid, ) = _get_returning_modifiers(compiler, stmt) cols = [stmt.table.c[_column_as_key(name)] for name in stmt.select_names] compiler._insert_from_select = stmt.select add_select_cols = [] if stmt.include_insert_from_select_defaults: col_set = set(cols) for col in stmt.table.columns: if col not in col_set and col.default: cols.append(col) for c in cols: col_key = _getattr_col_key(c) if col_key in parameters and col_key not in check_columns: parameters.pop(col_key) values.append((c, None)) else: _append_param_insert_select_hasdefault( compiler, stmt, c, add_select_cols, kw ) if add_select_cols: values.extend(add_select_cols) compiler._insert_from_select = compiler._insert_from_select._generate() compiler._insert_from_select._raw_columns = tuple( compiler._insert_from_select._raw_columns ) + tuple(expr for col, expr in add_select_cols) def _scan_cols( compiler, stmt, parameters, _getattr_col_key, _column_as_key, _col_bind_name, check_columns, values, kw, ): ( need_pks, implicit_returning, implicit_return_defaults, postfetch_lastrowid, ) = _get_returning_modifiers(compiler, stmt) if stmt._parameter_ordering: parameter_ordering = [ _column_as_key(key) for key in stmt._parameter_ordering ] ordered_keys = set(parameter_ordering) cols = [stmt.table.c[key] for key in parameter_ordering] + [ c for c in stmt.table.c if c.key not in ordered_keys ] else: cols = stmt.table.columns for c in cols: col_key = _getattr_col_key(c) if col_key in parameters and col_key not in check_columns: _append_param_parameter( compiler, stmt, c, col_key, parameters, _col_bind_name, implicit_returning, implicit_return_defaults, values, kw, ) elif compiler.isinsert: if ( c.primary_key and need_pks and ( implicit_returning or not postfetch_lastrowid or c is not stmt.table._autoincrement_column ) ): if implicit_returning: _append_param_insert_pk_returning( compiler, stmt, c, values, kw ) else: _append_param_insert_pk(compiler, stmt, c, values, kw) elif c.default is not None: _append_param_insert_hasdefault( compiler, stmt, c, implicit_return_defaults, values, kw ) elif c.server_default is not None: if implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) elif not c.primary_key: compiler.postfetch.append(c) elif implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) elif ( c.primary_key and c is not stmt.table._autoincrement_column and not c.nullable ): _warn_pk_with_no_anticipated_value(c) elif compiler.isupdate: _append_param_update( compiler, stmt, c, implicit_return_defaults, values, kw ) def _append_param_parameter( compiler, stmt, c, col_key, parameters, _col_bind_name, implicit_returning, implicit_return_defaults, values, kw, ): value = parameters.pop(col_key) if elements._is_literal(value): value = _create_bind_param( compiler, c, value, required=value is REQUIRED, name=_col_bind_name(c) if not stmt._has_multi_parameters else "%s_m0" % _col_bind_name(c), **kw ) else: if isinstance(value, elements.BindParameter) and value.type._isnull: value = value._clone() value.type = c.type if c.primary_key and implicit_returning: compiler.returning.append(c) value = compiler.process(value.self_group(), **kw) elif implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) value = compiler.process(value.self_group(), **kw) else: # postfetch specifically means, "we can SELECT the row we just # inserted by primary key to get back the server generated # defaults". so by definition this can't be used to get the primary # key value back, because we need to have it ahead of time. if not c.primary_key: compiler.postfetch.append(c) value = compiler.process(value.self_group(), **kw) values.append((c, value)) def _append_param_insert_pk_returning(compiler, stmt, c, values, kw): """Create a primary key expression in the INSERT statement and possibly a RETURNING clause for it. If the column has a Python-side default, we will create a bound parameter for it and "pre-execute" the Python function. If the column has a SQL expression default, or is a sequence, we will add it directly into the INSERT statement and add a RETURNING element to get the new value. If the column has a server side default or is marked as the "autoincrement" column, we will add a RETRUNING element to get at the value. If all the above tests fail, that indicates a primary key column with no noted default generation capabilities that has no parameter passed; raise an exception. """ if c.default is not None: if c.default.is_sequence: if compiler.dialect.supports_sequences and ( not c.default.optional or not compiler.dialect.sequences_optional ): proc = compiler.process(c.default, **kw) values.append((c, proc)) compiler.returning.append(c) elif c.default.is_clause_element: values.append( (c, compiler.process(c.default.arg.self_group(), **kw)) ) compiler.returning.append(c) else: values.append((c, _create_insert_prefetch_bind_param(compiler, c))) elif c is stmt.table._autoincrement_column or c.server_default is not None: compiler.returning.append(c) elif not c.nullable: # no .default, no .server_default, not autoincrement, we have # no indication this primary key column will have any value _warn_pk_with_no_anticipated_value(c) def _create_insert_prefetch_bind_param(compiler, c, process=True, name=None): param = _create_bind_param(compiler, c, None, process=process, name=name) compiler.insert_prefetch.append(c) return param def _create_update_prefetch_bind_param(compiler, c, process=True, name=None): param = _create_bind_param(compiler, c, None, process=process, name=name) compiler.update_prefetch.append(c) return param class _multiparam_column(elements.ColumnElement): _is_multiparam_column = True def __init__(self, original, index): self.index = index self.key = "%s_m%d" % (original.key, index + 1) self.original = original self.default = original.default self.type = original.type def __eq__(self, other): return ( isinstance(other, _multiparam_column) and other.key == self.key and other.original == self.original ) def _process_multiparam_default_bind(compiler, stmt, c, index, kw): if not c.default: raise exc.CompileError( "INSERT value for column %s is explicitly rendered as a bound" "parameter in the VALUES clause; " "a Python-side value or SQL expression is required" % c ) elif c.default.is_clause_element: return compiler.process(c.default.arg.self_group(), **kw) else: col = _multiparam_column(c, index) if isinstance(stmt, dml.Insert): return _create_insert_prefetch_bind_param(compiler, col) else: return _create_update_prefetch_bind_param(compiler, col) def _append_param_insert_pk(compiler, stmt, c, values, kw): """Create a bound parameter in the INSERT statement to receive a 'prefetched' default value. The 'prefetched' value indicates that we are to invoke a Python-side default function or expliclt SQL expression before the INSERT statement proceeds, so that we have a primary key value available. if the column has no noted default generation capabilities, it has no value passed in either; raise an exception. """ if ( # column has a Python-side default c.default is not None and ( # and it won't be a Sequence not c.default.is_sequence or compiler.dialect.supports_sequences ) ) or ( # column is the "autoincrement column" c is stmt.table._autoincrement_column and ( # and it's either a "sequence" or a # pre-executable "autoincrement" sequence compiler.dialect.supports_sequences or compiler.dialect.preexecute_autoincrement_sequences ) ): values.append((c, _create_insert_prefetch_bind_param(compiler, c))) elif c.default is None and c.server_default is None and not c.nullable: # no .default, no .server_default, not autoincrement, we have # no indication this primary key column will have any value _warn_pk_with_no_anticipated_value(c) def _append_param_insert_hasdefault( compiler, stmt, c, implicit_return_defaults, values, kw ): if c.default.is_sequence: if compiler.dialect.supports_sequences and ( not c.default.optional or not compiler.dialect.sequences_optional ): proc = compiler.process(c.default, **kw) values.append((c, proc)) if implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) elif not c.primary_key: compiler.postfetch.append(c) elif c.default.is_clause_element: proc = compiler.process(c.default.arg.self_group(), **kw) values.append((c, proc)) if implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) elif not c.primary_key: # don't add primary key column to postfetch compiler.postfetch.append(c) else: values.append((c, _create_insert_prefetch_bind_param(compiler, c))) def _append_param_insert_select_hasdefault(compiler, stmt, c, values, kw): if c.default.is_sequence: if compiler.dialect.supports_sequences and ( not c.default.optional or not compiler.dialect.sequences_optional ): proc = c.default values.append((c, proc.next_value())) elif c.default.is_clause_element: proc = c.default.arg.self_group() values.append((c, proc)) else: values.append( (c, _create_insert_prefetch_bind_param(compiler, c, process=False)) ) def _append_param_update( compiler, stmt, c, implicit_return_defaults, values, kw ): if c.onupdate is not None and not c.onupdate.is_sequence: if c.onupdate.is_clause_element: values.append( (c, compiler.process(c.onupdate.arg.self_group(), **kw)) ) if implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) else: compiler.postfetch.append(c) else: values.append((c, _create_update_prefetch_bind_param(compiler, c))) elif c.server_onupdate is not None: if implicit_return_defaults and c in implicit_return_defaults: compiler.returning.append(c) else: compiler.postfetch.append(c) elif ( implicit_return_defaults and stmt._return_defaults is not True and c in implicit_return_defaults ): compiler.returning.append(c) def _get_multitable_params( compiler, stmt, stmt_parameters, check_columns, _col_bind_name, _getattr_col_key, values, kw, ): normalized_params = dict( (elements._clause_element_as_expr(c), param) for c, param in stmt_parameters.items() ) affected_tables = set() for t in stmt._extra_froms: for c in t.c: if c in normalized_params: affected_tables.add(t) check_columns[_getattr_col_key(c)] = c value = normalized_params[c] if elements._is_literal(value): value = _create_bind_param( compiler, c, value, required=value is REQUIRED, name=_col_bind_name(c), ) else: compiler.postfetch.append(c) value = compiler.process(value.self_group(), **kw) values.append((c, value)) # determine tables which are actually to be updated - process onupdate # and server_onupdate for these for t in affected_tables: for c in t.c: if c in normalized_params: continue elif c.onupdate is not None and not c.onupdate.is_sequence: if c.onupdate.is_clause_element: values.append( ( c, compiler.process( c.onupdate.arg.self_group(), **kw ), ) ) compiler.postfetch.append(c) else: values.append( ( c, _create_update_prefetch_bind_param( compiler, c, name=_col_bind_name(c) ), ) ) elif c.server_onupdate is not None: compiler.postfetch.append(c) def _extend_values_for_multiparams(compiler, stmt, values, kw): values_0 = values values = [values] for i, row in enumerate(stmt.parameters[1:]): extension = [] for (col, param) in values_0: if col in row or col.key in row: key = col if col in row else col.key if elements._is_literal(row[key]): new_param = _create_bind_param( compiler, col, row[key], name="%s_m%d" % (col.key, i + 1), **kw ) else: new_param = compiler.process(row[key].self_group(), **kw) else: new_param = _process_multiparam_default_bind( compiler, stmt, col, i, kw ) extension.append((col, new_param)) values.append(extension) return values def _get_stmt_parameters_params( compiler, parameters, stmt_parameters, _column_as_key, values, kw ): for k, v in stmt_parameters.items(): colkey = _column_as_key(k) if colkey is not None: parameters.setdefault(colkey, v) else: # a non-Column expression on the left side; # add it to values() in an "as-is" state, # coercing right side to bound param if elements._is_literal(v): v = compiler.process( elements.BindParameter(None, v, type_=k.type), **kw ) else: if v._is_bind_parameter and v.type._isnull: # either unique parameter, or other bound parameters that # were passed in directly # set type to that of the column unconditionally v = v._with_binary_element_type(k.type) v = compiler.process(v.self_group(), **kw) values.append((k, v)) def _get_returning_modifiers(compiler, stmt): need_pks = ( compiler.isinsert and not compiler.inline and not stmt._returning and not stmt._has_multi_parameters ) implicit_returning = ( need_pks and compiler.dialect.implicit_returning and stmt.table.implicit_returning ) if compiler.isinsert: implicit_return_defaults = implicit_returning and stmt._return_defaults elif compiler.isupdate: implicit_return_defaults = ( compiler.dialect.implicit_returning and stmt.table.implicit_returning and stmt._return_defaults ) else: # this line is unused, currently we are always # isinsert or isupdate implicit_return_defaults = False # pragma: no cover if implicit_return_defaults: if stmt._return_defaults is True: implicit_return_defaults = set(stmt.table.c) else: implicit_return_defaults = set(stmt._return_defaults) postfetch_lastrowid = need_pks and compiler.dialect.postfetch_lastrowid return ( need_pks, implicit_returning, implicit_return_defaults, postfetch_lastrowid, ) def _warn_pk_with_no_anticipated_value(c): msg = ( "Column '%s.%s' is marked as a member of the " "primary key for table '%s', " "but has no Python-side or server-side default generator indicated, " "nor does it indicate 'autoincrement=True' or 'nullable=True', " "and no explicit value is passed. " "Primary key columns typically may not store NULL." % (c.table.fullname, c.name, c.table.fullname) ) if len(c.table.primary_key) > 1: msg += ( " Note that as of SQLAlchemy 1.1, 'autoincrement=True' must be " "indicated explicitly for composite (e.g. multicolumn) primary " "keys if AUTO_INCREMENT/SERIAL/IDENTITY " "behavior is expected for one of the columns in the primary key. " "CREATE TABLE statements are impacted by this change as well on " "most backends." ) util.warn(msg) PK!TTbase.pynu[# sql/base.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Foundational utilities common to many sql modules. """ import itertools import re from .visitors import ClauseVisitor from .. import exc from .. import util PARSE_AUTOCOMMIT = util.symbol("PARSE_AUTOCOMMIT") NO_ARG = util.symbol("NO_ARG") class Immutable(object): """mark a ClauseElement as 'immutable' when expressions are cloned.""" def unique_params(self, *optionaldict, **kwargs): raise NotImplementedError("Immutable objects do not support copying") def params(self, *optionaldict, **kwargs): raise NotImplementedError("Immutable objects do not support copying") def _clone(self): return self def _from_objects(*elements): return itertools.chain(*[element._from_objects for element in elements]) @util.decorator def _generative(fn, *args, **kw): """Mark a method as generative.""" self = args[0]._generate() fn(self, *args[1:], **kw) return self class _DialectArgView(util.collections_abc.MutableMapping): """A dictionary view of dialect-level arguments in the form _. """ def __init__(self, obj): self.obj = obj def _key(self, key): try: dialect, value_key = key.split("_", 1) except ValueError as err: util.raise_(KeyError(key), replace_context=err) else: return dialect, value_key def __getitem__(self, key): dialect, value_key = self._key(key) try: opt = self.obj.dialect_options[dialect] except exc.NoSuchModuleError as err: util.raise_(KeyError(key), replace_context=err) else: return opt[value_key] def __setitem__(self, key, value): try: dialect, value_key = self._key(key) except KeyError as err: util.raise_( exc.ArgumentError( "Keys must be of the form _" ), replace_context=err, ) else: self.obj.dialect_options[dialect][value_key] = value def __delitem__(self, key): dialect, value_key = self._key(key) del self.obj.dialect_options[dialect][value_key] def __len__(self): return sum( len(args._non_defaults) for args in self.obj.dialect_options.values() ) def __iter__(self): return ( util.safe_kwarg("%s_%s" % (dialect_name, value_name)) for dialect_name in self.obj.dialect_options for value_name in self.obj.dialect_options[ dialect_name ]._non_defaults ) class _DialectArgDict(util.collections_abc.MutableMapping): """A dictionary view of dialect-level arguments for a specific dialect. Maintains a separate collection of user-specified arguments and dialect-specified default arguments. """ def __init__(self): self._non_defaults = {} self._defaults = {} def __len__(self): return len(set(self._non_defaults).union(self._defaults)) def __iter__(self): return iter(set(self._non_defaults).union(self._defaults)) def __getitem__(self, key): if key in self._non_defaults: return self._non_defaults[key] else: return self._defaults[key] def __setitem__(self, key, value): self._non_defaults[key] = value def __delitem__(self, key): del self._non_defaults[key] class DialectKWArgs(object): """Establish the ability for a class to have dialect-specific arguments with defaults and constructor validation. The :class:`.DialectKWArgs` interacts with the :attr:`.DefaultDialect.construct_arguments` present on a dialect. .. seealso:: :attr:`.DefaultDialect.construct_arguments` """ @classmethod def argument_for(cls, dialect_name, argument_name, default): """Add a new kind of dialect-specific keyword argument for this class. E.g.:: Index.argument_for("mydialect", "length", None) some_index = Index('a', 'b', mydialect_length=5) The :meth:`.DialectKWArgs.argument_for` method is a per-argument way adding extra arguments to the :attr:`.DefaultDialect.construct_arguments` dictionary. This dictionary provides a list of argument names accepted by various schema-level constructs on behalf of a dialect. New dialects should typically specify this dictionary all at once as a data member of the dialect class. The use case for ad-hoc addition of argument names is typically for end-user code that is also using a custom compilation scheme which consumes the additional arguments. :param dialect_name: name of a dialect. The dialect must be locatable, else a :class:`.NoSuchModuleError` is raised. The dialect must also include an existing :attr:`.DefaultDialect.construct_arguments` collection, indicating that it participates in the keyword-argument validation and default system, else :class:`.ArgumentError` is raised. If the dialect does not include this collection, then any keyword argument can be specified on behalf of this dialect already. All dialects packaged within SQLAlchemy include this collection, however for third party dialects, support may vary. :param argument_name: name of the parameter. :param default: default value of the parameter. .. versionadded:: 0.9.4 """ construct_arg_dictionary = DialectKWArgs._kw_registry[dialect_name] if construct_arg_dictionary is None: raise exc.ArgumentError( "Dialect '%s' does have keyword-argument " "validation and defaults enabled configured" % dialect_name ) if cls not in construct_arg_dictionary: construct_arg_dictionary[cls] = {} construct_arg_dictionary[cls][argument_name] = default @util.memoized_property def dialect_kwargs(self): """A collection of keyword arguments specified as dialect-specific options to this construct. The arguments are present here in their original ``_`` format. Only arguments that were actually passed are included; unlike the :attr:`.DialectKWArgs.dialect_options` collection, which contains all options known by this dialect including defaults. The collection is also writable; keys are accepted of the form ``_`` where the value will be assembled into the list of options. .. versionadded:: 0.9.2 .. versionchanged:: 0.9.4 The :attr:`.DialectKWArgs.dialect_kwargs` collection is now writable. .. seealso:: :attr:`.DialectKWArgs.dialect_options` - nested dictionary form """ return _DialectArgView(self) @property def kwargs(self): """A synonym for :attr:`.DialectKWArgs.dialect_kwargs`.""" return self.dialect_kwargs @util.dependencies("sqlalchemy.dialects") def _kw_reg_for_dialect(dialects, dialect_name): dialect_cls = dialects.registry.load(dialect_name) if dialect_cls.construct_arguments is None: return None return dict(dialect_cls.construct_arguments) _kw_registry = util.PopulateDict(_kw_reg_for_dialect) def _kw_reg_for_dialect_cls(self, dialect_name): construct_arg_dictionary = DialectKWArgs._kw_registry[dialect_name] d = _DialectArgDict() if construct_arg_dictionary is None: d._defaults.update({"*": None}) else: for cls in reversed(self.__class__.__mro__): if cls in construct_arg_dictionary: d._defaults.update(construct_arg_dictionary[cls]) return d @util.memoized_property def dialect_options(self): """A collection of keyword arguments specified as dialect-specific options to this construct. This is a two-level nested registry, keyed to ```` and ````. For example, the ``postgresql_where`` argument would be locatable as:: arg = my_object.dialect_options['postgresql']['where'] .. versionadded:: 0.9.2 .. seealso:: :attr:`.DialectKWArgs.dialect_kwargs` - flat dictionary form """ return util.PopulateDict( util.portable_instancemethod(self._kw_reg_for_dialect_cls) ) def _validate_dialect_kwargs(self, kwargs): # validate remaining kwargs that they all specify DB prefixes if not kwargs: return for k in kwargs: m = re.match("^(.+?)_(.+)$", k) if not m: raise TypeError( "Additional arguments should be " "named _, got '%s'" % k ) dialect_name, arg_name = m.group(1, 2) try: construct_arg_dictionary = self.dialect_options[dialect_name] except exc.NoSuchModuleError: util.warn( "Can't validate argument %r; can't " "locate any SQLAlchemy dialect named %r" % (k, dialect_name) ) self.dialect_options[dialect_name] = d = _DialectArgDict() d._defaults.update({"*": None}) d._non_defaults[arg_name] = kwargs[k] else: if ( "*" not in construct_arg_dictionary and arg_name not in construct_arg_dictionary ): raise exc.ArgumentError( "Argument %r is not accepted by " "dialect %r on behalf of %r" % (k, dialect_name, self.__class__) ) else: construct_arg_dictionary[arg_name] = kwargs[k] class Generative(object): """Allow a ClauseElement to generate itself via the @_generative decorator. """ def _generate(self): s = self.__class__.__new__(self.__class__) s.__dict__ = self.__dict__.copy() return s class Executable(Generative): """Mark a :class:`_expression.ClauseElement` as supporting execution. :class:`.Executable` is a superclass for all "statement" types of objects, including :func:`select`, :func:`delete`, :func:`update`, :func:`insert`, :func:`text`. """ supports_execution = True _execution_options = util.immutabledict() _bind = None @_generative def execution_options(self, **kw): """Set non-SQL options for the statement which take effect during execution. Execution options can be set on a per-statement or per :class:`_engine.Connection` basis. Additionally, the :class:`_engine.Engine` and ORM :class:`~.orm.query.Query` objects provide access to execution options which they in turn configure upon connections. The :meth:`execution_options` method is generative. A new instance of this statement is returned that contains the options:: statement = select([table.c.x, table.c.y]) statement = statement.execution_options(autocommit=True) Note that only a subset of possible execution options can be applied to a statement - these include "autocommit" and "stream_results", but not "isolation_level" or "compiled_cache". See :meth:`_engine.Connection.execution_options` for a full list of possible options. .. seealso:: :meth:`_engine.Connection.execution_options` :meth:`_query.Query.execution_options` :meth:`.Executable.get_execution_options` """ if "isolation_level" in kw: raise exc.ArgumentError( "'isolation_level' execution option may only be specified " "on Connection.execution_options(), or " "per-engine using the isolation_level " "argument to create_engine()." ) if "compiled_cache" in kw: raise exc.ArgumentError( "'compiled_cache' execution option may only be specified " "on Connection.execution_options(), not per statement." ) self._execution_options = self._execution_options.union(kw) def get_execution_options(self): """Get the non-SQL options which will take effect during execution. .. versionadded:: 1.3 .. seealso:: :meth:`.Executable.execution_options` """ return self._execution_options def execute(self, *multiparams, **params): """Compile and execute this :class:`.Executable`.""" e = self.bind if e is None: label = getattr(self, "description", self.__class__.__name__) msg = ( "This %s is not directly bound to a Connection or Engine. " "Use the .execute() method of a Connection or Engine " "to execute this construct." % label ) raise exc.UnboundExecutionError(msg) return e._execute_clauseelement(self, multiparams, params) def scalar(self, *multiparams, **params): """Compile and execute this :class:`.Executable`, returning the result's scalar representation. """ return self.execute(*multiparams, **params).scalar() @property def bind(self): """Returns the :class:`_engine.Engine` or :class:`_engine.Connection` to which this :class:`.Executable` is bound, or None if none found. This is a traversal which checks locally, then checks among the "from" clauses of associated objects until a bound engine or connection is found. """ if self._bind is not None: return self._bind for f in _from_objects(self): if f is self: continue engine = f.bind if engine is not None: return engine else: return None class SchemaEventTarget(object): """Base class for elements that are the targets of :class:`.DDLEvents` events. This includes :class:`.SchemaItem` as well as :class:`.SchemaType`. """ def _set_parent(self, parent): """Associate with this SchemaEvent's parent object.""" def _set_parent_with_dispatch(self, parent, **kw): self.dispatch.before_parent_attach(self, parent) self._set_parent(parent, **kw) self.dispatch.after_parent_attach(self, parent) class SchemaVisitor(ClauseVisitor): """Define the visiting for ``SchemaItem`` objects.""" __traverse_options__ = {"schema_visitor": True} class ColumnCollection(util.OrderedProperties): """An ordered dictionary that stores a list of ColumnElement instances. Overrides the ``__eq__()`` method to produce SQL clauses between sets of correlated columns. """ __slots__ = "_all_columns" def __init__(self, *columns): super(ColumnCollection, self).__init__() object.__setattr__(self, "_all_columns", []) for c in columns: self.add(c) def __str__(self): return repr([str(c) for c in self]) def replace(self, column): """Add the given column to this collection, removing unaliased versions of this column as well as existing columns with the same key. E.g.:: t = Table('sometable', metadata, Column('col1', Integer)) t.columns.replace(Column('col1', Integer, key='columnone')) will remove the original 'col1' from the collection, and add the new column under the name 'columnname'. Used by schema.Column to override columns during table reflection. """ remove_col = None if column.name in self and column.key != column.name: other = self[column.name] if other.name == other.key: remove_col = other del self._data[other.key] if column.key in self._data: remove_col = self._data[column.key] self._data[column.key] = column if remove_col is not None: self._all_columns[:] = [ column if c is remove_col else c for c in self._all_columns ] else: self._all_columns.append(column) def add(self, column): """Add a column to this collection. The key attribute of the column will be used as the hash key for this dictionary. """ if not column.key: raise exc.ArgumentError( "Can't add unnamed column to column collection" ) self[column.key] = column def __delitem__(self, key): raise NotImplementedError() def __setattr__(self, key, obj): raise NotImplementedError() def __setitem__(self, key, value): if key in self: # this warning is primarily to catch select() statements # which have conflicting column names in their exported # columns collection existing = self[key] if existing is value: return if not existing.shares_lineage(value): util.warn( "Column %r on table %r being replaced by " "%r, which has the same key. Consider " "use_labels for select() statements." % (key, getattr(existing, "table", None), value) ) # pop out memoized proxy_set as this # operation may very well be occurring # in a _make_proxy operation util.memoized_property.reset(value, "proxy_set") self._all_columns.append(value) self._data[key] = value def clear(self): raise NotImplementedError() def remove(self, column): del self._data[column.key] self._all_columns[:] = [ c for c in self._all_columns if c is not column ] def update(self, iter_): cols = list(iter_) all_col_set = set(self._all_columns) self._all_columns.extend( c for label, c in cols if c not in all_col_set ) self._data.update((label, c) for label, c in cols) def extend(self, iter_): cols = list(iter_) all_col_set = set(self._all_columns) self._all_columns.extend(c for c in cols if c not in all_col_set) self._data.update((c.key, c) for c in cols) __hash__ = None @util.dependencies("sqlalchemy.sql.elements") def __eq__(self, elements, other): l = [] for c in getattr(other, "_all_columns", other): for local in self._all_columns: if c.shares_lineage(local): l.append(c == local) return elements.and_(*l) def __contains__(self, other): if not isinstance(other, util.string_types): raise exc.ArgumentError("__contains__ requires a string argument") return util.OrderedProperties.__contains__(self, other) def __getstate__(self): return {"_data": self._data, "_all_columns": self._all_columns} def __setstate__(self, state): object.__setattr__(self, "_data", state["_data"]) object.__setattr__(self, "_all_columns", state["_all_columns"]) def contains_column(self, col): return col in set(self._all_columns) def as_immutable(self): return ImmutableColumnCollection(self._data, self._all_columns) class ImmutableColumnCollection(util.ImmutableProperties, ColumnCollection): def __init__(self, data, all_columns): util.ImmutableProperties.__init__(self, data) object.__setattr__(self, "_all_columns", all_columns) extend = remove = util.ImmutableProperties._immutable class ColumnSet(util.ordered_column_set): def contains_column(self, col): return col in self def extend(self, cols): for col in cols: self.add(col) def __add__(self, other): return list(self) + list(other) @util.dependencies("sqlalchemy.sql.elements") def __eq__(self, elements, other): l = [] for c in other: for local in self: if c.shares_lineage(local): l.append(c == local) return elements.and_(*l) def __hash__(self): return hash(tuple(x for x in self)) def _bind_or_error(schemaitem, msg=None): bind = schemaitem.bind if not bind: name = schemaitem.__class__.__name__ label = getattr( schemaitem, "fullname", getattr(schemaitem, "name", None) ) if label: item = "%s object %r" % (name, label) else: item = "%s object" % name if msg is None: msg = ( "%s is not bound to an Engine or Connection. " "Execution can not proceed without a database to execute " "against." % item ) raise exc.UnboundExecutionError(msg) return bind PK!슗!! selectable.pynu[# sql/selectable.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """The :class:`_expression.FromClause` class of SQL expression elements, representing SQL tables and derived rowsets. """ import collections import itertools import operator from operator import attrgetter from sqlalchemy.sql.visitors import Visitable from . import operators from . import type_api from .annotation import Annotated from .base import _from_objects from .base import _generative from .base import ColumnCollection from .base import ColumnSet from .base import Executable from .base import Generative from .base import Immutable from .elements import _anonymous_label from .elements import _clause_element_as_expr from .elements import _clone from .elements import _cloned_difference from .elements import _cloned_intersection from .elements import _document_text_coercion from .elements import _expand_cloned from .elements import _interpret_as_column_or_from from .elements import _literal_and_labels_as_label_reference from .elements import _literal_as_label_reference from .elements import _literal_as_text from .elements import _no_text_coercion from .elements import _select_iterables from .elements import and_ from .elements import BindParameter from .elements import ClauseElement from .elements import ClauseList from .elements import Grouping from .elements import literal_column from .elements import True_ from .elements import UnaryExpression from .. import exc from .. import inspection from .. import util def _interpret_as_from(element): insp = inspection.inspect(element, raiseerr=False) if insp is None: if isinstance(element, util.string_types): _no_text_coercion(element) try: return insp.selectable except AttributeError as err: util.raise_( exc.ArgumentError("FROM expression expected"), replace_context=err ) def _interpret_as_select(element): element = _interpret_as_from(element) if isinstance(element, Alias): element = element.original if not isinstance(element, SelectBase): element = element.select() return element class _OffsetLimitParam(BindParameter): @property def _limit_offset_value(self): return self.effective_value def _offset_or_limit_clause(element, name=None, type_=None): """Convert the given value to an "offset or limit" clause. This handles incoming integers and converts to an expression; if an expression is already given, it is passed through. """ if element is None: return None elif hasattr(element, "__clause_element__"): return element.__clause_element__() elif isinstance(element, Visitable): return element else: value = util.asint(element) return _OffsetLimitParam(name, value, type_=type_, unique=True) def _offset_or_limit_clause_asint(clause, attrname): """Convert the "offset or limit" clause of a select construct to an integer. This is only possible if the value is stored as a simple bound parameter. Otherwise, a compilation error is raised. """ if clause is None: return None try: value = clause._limit_offset_value except AttributeError as err: util.raise_( exc.CompileError( "This SELECT structure does not use a simple " "integer value for %s" % attrname ), replace_context=err, ) else: return util.asint(value) def subquery(alias, *args, **kwargs): r"""Return an :class:`_expression.Alias` object derived from a :class:`_expression.Select`. :param alias: the alias name :param \*args, \**kwargs: all other arguments are delivered to the :func:`_expression.select` function. """ return Select(*args, **kwargs).alias(alias) class Selectable(ClauseElement): """Mark a class as being selectable.""" __visit_name__ = "selectable" is_selectable = True @property def selectable(self): return self class HasPrefixes(object): _prefixes = () @_generative @_document_text_coercion( "expr", ":meth:`_expression.HasPrefixes.prefix_with`", ":paramref:`.HasPrefixes.prefix_with.*expr`", ) def prefix_with(self, *expr, **kw): r"""Add one or more expressions following the statement keyword, i.e. SELECT, INSERT, UPDATE, or DELETE. Generative. This is used to support backend-specific prefix keywords such as those provided by MySQL. E.g.:: stmt = table.insert().prefix_with("LOW_PRIORITY", dialect="mysql") # MySQL 5.7 optimizer hints stmt = select([table]).prefix_with( "/*+ BKA(t1) */", dialect="mysql") Multiple prefixes can be specified by multiple calls to :meth:`_expression.HasPrefixes.prefix_with`. :param \*expr: textual or :class:`_expression.ClauseElement` construct which will be rendered following the INSERT, UPDATE, or DELETE keyword. :param \**kw: A single keyword 'dialect' is accepted. This is an optional string dialect name which will limit rendering of this prefix to only that dialect. """ dialect = kw.pop("dialect", None) if kw: raise exc.ArgumentError( "Unsupported argument(s): %s" % ",".join(kw) ) self._setup_prefixes(expr, dialect) def _setup_prefixes(self, prefixes, dialect=None): self._prefixes = self._prefixes + tuple( [ (_literal_as_text(p, allow_coercion_to_text=True), dialect) for p in prefixes ] ) class HasSuffixes(object): _suffixes = () @_generative @_document_text_coercion( "expr", ":meth:`_expression.HasSuffixes.suffix_with`", ":paramref:`.HasSuffixes.suffix_with.*expr`", ) def suffix_with(self, *expr, **kw): r"""Add one or more expressions following the statement as a whole. This is used to support backend-specific suffix keywords on certain constructs. E.g.:: stmt = select([col1, col2]).cte().suffix_with( "cycle empno set y_cycle to 1 default 0", dialect="oracle") Multiple suffixes can be specified by multiple calls to :meth:`_expression.HasSuffixes.suffix_with`. :param \*expr: textual or :class:`_expression.ClauseElement` construct which will be rendered following the target clause. :param \**kw: A single keyword 'dialect' is accepted. This is an optional string dialect name which will limit rendering of this suffix to only that dialect. """ dialect = kw.pop("dialect", None) if kw: raise exc.ArgumentError( "Unsupported argument(s): %s" % ",".join(kw) ) self._setup_suffixes(expr, dialect) def _setup_suffixes(self, suffixes, dialect=None): self._suffixes = self._suffixes + tuple( [ (_literal_as_text(p, allow_coercion_to_text=True), dialect) for p in suffixes ] ) class FromClause(Selectable): """Represent an element that can be used within the ``FROM`` clause of a ``SELECT`` statement. The most common forms of :class:`_expression.FromClause` are the :class:`_schema.Table` and the :func:`_expression.select` constructs. Key features common to all :class:`_expression.FromClause` objects include: * a :attr:`.c` collection, which provides per-name access to a collection of :class:`_expression.ColumnElement` objects. * a :attr:`.primary_key` attribute, which is a collection of all those :class:`_expression.ColumnElement` objects that indicate the ``primary_key`` flag. * Methods to generate various derivations of a "from" clause, including :meth:`_expression.FromClause.alias`, :meth:`_expression.FromClause.join`, :meth:`_expression.FromClause.select`. """ __visit_name__ = "fromclause" named_with_column = False _hide_froms = [] _is_join = False _is_select = False _is_from_container = False _is_lateral = False _textual = False """A marker that allows us to easily distinguish a :class:`.TextAsFrom` or similar object from other kinds of :class:`_expression.FromClause` objects.""" schema = None """Define the 'schema' attribute for this :class:`_expression.FromClause`. This is typically ``None`` for most objects except that of :class:`_schema.Table`, where it is taken as the value of the :paramref:`_schema.Table.schema` argument. """ def _translate_schema(self, effective_schema, map_): return effective_schema _memoized_property = util.group_expirable_memoized_property(["_columns"]) @util.deprecated( "1.1", message="The :meth:`.FromClause.count` method is deprecated, " "and will be removed in a future release. Please use the " ":class:`_functions.count` function available from the " ":attr:`.func` namespace.", ) @util.dependencies("sqlalchemy.sql.functions") def count(self, functions, whereclause=None, **params): """Return a SELECT COUNT generated against this :class:`_expression.FromClause`. .. seealso:: :class:`_functions.count` """ if self.primary_key: col = list(self.primary_key)[0] else: col = list(self.columns)[0] return Select( [functions.func.count(col).label("tbl_row_count")], whereclause, from_obj=[self], **params ) def select(self, whereclause=None, **params): """Return a SELECT of this :class:`_expression.FromClause`. .. seealso:: :func:`_expression.select` - general purpose method which allows for arbitrary column lists. """ return Select([self], whereclause, **params) def join(self, right, onclause=None, isouter=False, full=False): """Return a :class:`_expression.Join` from this :class:`_expression.FromClause` to another :class:`_expression.FromClause`. E.g.:: from sqlalchemy import join j = user_table.join(address_table, user_table.c.id == address_table.c.user_id) stmt = select([user_table]).select_from(j) would emit SQL along the lines of:: SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN. :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER JOIN. Implies :paramref:`.FromClause.join.isouter`. .. versionadded:: 1.1 .. seealso:: :func:`_expression.join` - standalone function :class:`_expression.Join` - the type of object produced """ return Join(self, right, onclause, isouter, full) def outerjoin(self, right, onclause=None, full=False): """Return a :class:`_expression.Join` from this :class:`_expression.FromClause` to another :class:`FromClause`, with the "isouter" flag set to True. E.g.:: from sqlalchemy import outerjoin j = user_table.outerjoin(address_table, user_table.c.id == address_table.c.user_id) The above is equivalent to:: j = user_table.join( address_table, user_table.c.id == address_table.c.user_id, isouter=True) :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param full: if True, render a FULL OUTER JOIN, instead of LEFT OUTER JOIN. .. versionadded:: 1.1 .. seealso:: :meth:`_expression.FromClause.join` :class:`_expression.Join` """ return Join(self, right, onclause, True, full) def alias(self, name=None, flat=False): """Return an alias of this :class:`_expression.FromClause`. E.g.:: a2 = some_table.alias('a2') The above code creates an :class:`_expression.Alias` object which can be used as a FROM clause in any SELECT statement. .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` """ return Alias._construct(self, name) def lateral(self, name=None): """Return a LATERAL alias of this :class:`_expression.FromClause`. The return value is the :class:`_expression.Lateral` construct also provided by the top-level :func:`_expression.lateral` function. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. """ return Lateral._construct(self, name) def tablesample(self, sampling, name=None, seed=None): """Return a TABLESAMPLE alias of this :class:`_expression.FromClause`. The return value is the :class:`_expression.TableSample` construct also provided by the top-level :func:`_expression.tablesample` function. .. versionadded:: 1.1 .. seealso:: :func:`_expression.tablesample` - usage guidelines and parameters """ return TableSample._construct(self, sampling, name, seed) def is_derived_from(self, fromclause): """Return ``True`` if this :class:`_expression.FromClause` is 'derived' from the given ``FromClause``. An example would be an Alias of a Table is derived from that Table. """ # this is essentially an "identity" check in the base class. # Other constructs override this to traverse through # contained elements. return fromclause in self._cloned_set def _is_lexical_equivalent(self, other): """Return ``True`` if this :class:`_expression.FromClause` and the other represent the same lexical identity. This tests if either one is a copy of the other, or if they are the same via annotation identity. """ return self._cloned_set.intersection(other._cloned_set) @util.dependencies("sqlalchemy.sql.util") def replace_selectable(self, sqlutil, old, alias): """Replace all occurrences of FromClause 'old' with the given Alias object, returning a copy of this :class:`_expression.FromClause`. """ return sqlutil.ClauseAdapter(alias).traverse(self) def correspond_on_equivalents(self, column, equivalents): """Return corresponding_column for the given column, or if None search for a match in the given dictionary. """ col = self.corresponding_column(column, require_embedded=True) if col is None and col in equivalents: for equiv in equivalents[col]: nc = self.corresponding_column(equiv, require_embedded=True) if nc: return nc return col def corresponding_column(self, column, require_embedded=False): """Given a :class:`_expression.ColumnElement`, return the exported :class:`_expression.ColumnElement` object from this :class:`expression.Selectable` which corresponds to that original :class:`~sqlalchemy.schema.Column` via a common ancestor column. :param column: the target :class:`_expression.ColumnElement` to be matched :param require_embedded: only return corresponding columns for the given :class:`_expression.ColumnElement`, if the given :class:`_expression.ColumnElement` is actually present within a sub-element of this :class:`_expression.FromClause`. Normally the column will match if it merely shares a common ancestor with one of the exported columns of this :class:`_expression.FromClause`. """ def embedded(expanded_proxy_set, target_set): for t in target_set.difference(expanded_proxy_set): if not set(_expand_cloned([t])).intersection( expanded_proxy_set ): return False return True # don't dig around if the column is locally present if self.c.contains_column(column): return column col, intersect = None, None target_set = column.proxy_set cols = self.c._all_columns for c in cols: expanded_proxy_set = set(_expand_cloned(c.proxy_set)) i = target_set.intersection(expanded_proxy_set) if i and ( not require_embedded or embedded(expanded_proxy_set, target_set) ): if col is None: # no corresponding column yet, pick this one. col, intersect = c, i elif len(i) > len(intersect): # 'c' has a larger field of correspondence than # 'col'. i.e. selectable.c.a1_x->a1.c.x->table.c.x # matches a1.c.x->table.c.x better than # selectable.c.x->table.c.x does. col, intersect = c, i elif i == intersect: # they have the same field of correspondence. see # which proxy_set has fewer columns in it, which # indicates a closer relationship with the root # column. Also take into account the "weight" # attribute which CompoundSelect() uses to give # higher precedence to columns based on vertical # position in the compound statement, and discard # columns that have no reference to the target # column (also occurs with CompoundSelect) col_distance = util.reduce( operator.add, [ sc._annotations.get("weight", 1) for sc in col._uncached_proxy_set() if sc.shares_lineage(column) ], ) c_distance = util.reduce( operator.add, [ sc._annotations.get("weight", 1) for sc in c._uncached_proxy_set() if sc.shares_lineage(column) ], ) if c_distance < col_distance: col, intersect = c, i return col @property def description(self): """A brief description of this :class:`_expression.FromClause`. Used primarily for error message formatting. """ return getattr(self, "name", self.__class__.__name__ + " object") def _reset_exported(self): """Delete memoized collections when a FromClause is cloned.""" self._memoized_property.expire_instance(self) @_memoized_property def columns(self): """A named-based collection of :class:`_expression.ColumnElement` objects maintained by this :class:`_expression.FromClause`. The :attr:`.columns`, or :attr:`.c` collection, is the gateway to the construction of SQL expressions using table-bound or other selectable-bound columns:: select([mytable]).where(mytable.c.somecolumn == 5) """ if "_columns" not in self.__dict__: self._init_collections() self._populate_column_collection() return self._columns.as_immutable() @_memoized_property def primary_key(self): """Return the collection of :class:`_schema.Column` objects which comprise the primary key of this FromClause. """ self._init_collections() self._populate_column_collection() return self.primary_key @_memoized_property def foreign_keys(self): """Return the collection of :class:`_schema.ForeignKey` objects which this FromClause references. """ self._init_collections() self._populate_column_collection() return self.foreign_keys c = property( attrgetter("columns"), doc="An alias for the :attr:`.columns` attribute.", ) _select_iterable = property(attrgetter("columns")) def _init_collections(self): assert "_columns" not in self.__dict__ assert "primary_key" not in self.__dict__ assert "foreign_keys" not in self.__dict__ self._columns = ColumnCollection() self.primary_key = ColumnSet() self.foreign_keys = set() @property def _cols_populated(self): return "_columns" in self.__dict__ def _populate_column_collection(self): """Called on subclasses to establish the .c collection. Each implementation has a different way of establishing this collection. """ def _refresh_for_new_column(self, column): """Given a column added to the .c collection of an underlying selectable, produce the local version of that column, assuming this selectable ultimately should proxy this column. this is used to "ping" a derived selectable to add a new column to its .c. collection when a Column has been added to one of the Table objects it ultimtely derives from. If the given selectable hasn't populated its .c. collection yet, it should at least pass on the message to the contained selectables, but it will return None. This method is currently used by Declarative to allow Table columns to be added to a partially constructed inheritance mapping that may have already produced joins. The method isn't public right now, as the full span of implications and/or caveats aren't yet clear. It's also possible that this functionality could be invoked by default via an event, which would require that selectables maintain a weak referencing collection of all derivations. """ if not self._cols_populated: return None elif column.key in self.columns and self.columns[column.key] is column: return column else: return None class Join(FromClause): """Represent a ``JOIN`` construct between two :class:`_expression.FromClause` elements. The public constructor function for :class:`_expression.Join` is the module-level :func:`_expression.join()` function, as well as the :meth:`_expression.FromClause.join` method of any :class:`_expression.FromClause` (e.g. such as :class:`_schema.Table`). .. seealso:: :func:`_expression.join` :meth:`_expression.FromClause.join` """ __visit_name__ = "join" _is_join = True def __init__(self, left, right, onclause=None, isouter=False, full=False): """Construct a new :class:`_expression.Join`. The usual entrypoint here is the :func:`_expression.join` function or the :meth:`_expression.FromClause.join` method of any :class:`_expression.FromClause` object. """ self.left = _interpret_as_from(left) self.right = _interpret_as_from(right).self_group() if onclause is None: self.onclause = self._match_primaries(self.left, self.right) else: self.onclause = onclause self.isouter = isouter self.full = full @classmethod def _create_outerjoin(cls, left, right, onclause=None, full=False): """Return an ``OUTER JOIN`` clause element. The returned object is an instance of :class:`_expression.Join`. Similar functionality is also available via the :meth:`_expression.FromClause.outerjoin` method on any :class:`_expression.FromClause`. :param left: The left side of the join. :param right: The right side of the join. :param onclause: Optional criterion for the ``ON`` clause, is derived from foreign key relationships established between left and right otherwise. To chain joins together, use the :meth:`_expression.FromClause.join` or :meth:`_expression.FromClause.outerjoin` methods on the resulting :class:`_expression.Join` object. """ return cls(left, right, onclause, isouter=True, full=full) @classmethod def _create_join( cls, left, right, onclause=None, isouter=False, full=False ): """Produce a :class:`_expression.Join` object, given two :class:`_expression.FromClause` expressions. E.g.:: j = join(user_table, address_table, user_table.c.id == address_table.c.user_id) stmt = select([user_table]).select_from(j) would emit SQL along the lines of:: SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id Similar functionality is available given any :class:`_expression.FromClause` object (e.g. such as a :class:`_schema.Table`) using the :meth:`_expression.FromClause.join` method. :param left: The left side of the join. :param right: the right side of the join; this is any :class:`_expression.FromClause` object such as a :class:`_schema.Table` object, and may also be a selectable-compatible object such as an ORM-mapped class. :param onclause: a SQL expression representing the ON clause of the join. If left at ``None``, :meth:`_expression.FromClause.join` will attempt to join the two tables based on a foreign key relationship. :param isouter: if True, render a LEFT OUTER JOIN, instead of JOIN. :param full: if True, render a FULL OUTER JOIN, instead of JOIN. .. versionadded:: 1.1 .. seealso:: :meth:`_expression.FromClause.join` - method form, based on a given left side. :class:`_expression.Join` - the type of object produced. """ return cls(left, right, onclause, isouter, full) @property def description(self): return "Join object on %s(%d) and %s(%d)" % ( self.left.description, id(self.left), self.right.description, id(self.right), ) def is_derived_from(self, fromclause): return ( fromclause is self or self.left.is_derived_from(fromclause) or self.right.is_derived_from(fromclause) ) def self_group(self, against=None): return FromGrouping(self) @util.dependencies("sqlalchemy.sql.util") def _populate_column_collection(self, sqlutil): columns = [c for c in self.left.columns] + [ c for c in self.right.columns ] self.primary_key.extend( sqlutil.reduce_columns( (c for c in columns if c.primary_key), self.onclause ) ) self._columns.update((col._label, col) for col in columns) self.foreign_keys.update( itertools.chain(*[col.foreign_keys for col in columns]) ) def _refresh_for_new_column(self, column): col = self.left._refresh_for_new_column(column) if col is None: col = self.right._refresh_for_new_column(column) if col is not None: if self._cols_populated: self._columns[col._label] = col self.foreign_keys.update(col.foreign_keys) if col.primary_key: self.primary_key.add(col) return col return None def _copy_internals(self, clone=_clone, **kw): self._reset_exported() self.left = clone(self.left, **kw) self.right = clone(self.right, **kw) self.onclause = clone(self.onclause, **kw) def get_children(self, **kwargs): return self.left, self.right, self.onclause def _match_primaries(self, left, right): if isinstance(left, Join): left_right = left.right else: left_right = None return self._join_condition(left, right, a_subset=left_right) @classmethod @util.deprecated_params( ignore_nonexistent_tables=( "0.9", "The :paramref:`.join_condition.ignore_nonexistent_tables` " "parameter is deprecated and will be removed in a future " "release. Tables outside of the two tables being handled " "are no longer considered.", ) ) def _join_condition( cls, a, b, ignore_nonexistent_tables=False, a_subset=None, consider_as_foreign_keys=None, ): """Create a join condition between two tables or selectables. e.g.:: join_condition(tablea, tableb) would produce an expression along the lines of:: tablea.c.id==tableb.c.tablea_id The join is determined based on the foreign key relationships between the two selectables. If there are multiple ways to join, or no way to join, an error is raised. :param ignore_nonexistent_tables: unused - tables outside of the two tables being handled are not considered. :param a_subset: An optional expression that is a sub-component of ``a``. An attempt will be made to join to just this sub-component first before looking at the full ``a`` construct, and if found will be successful even if there are other ways to join to ``a``. This allows the "right side" of a join to be passed thereby providing a "natural join". """ constraints = cls._joincond_scan_left_right( a, a_subset, b, consider_as_foreign_keys ) if len(constraints) > 1: cls._joincond_trim_constraints( a, b, constraints, consider_as_foreign_keys ) if len(constraints) == 0: if isinstance(b, FromGrouping): hint = ( " Perhaps you meant to convert the right side to a " "subquery using alias()?" ) else: hint = "" raise exc.NoForeignKeysError( "Can't find any foreign key relationships " "between '%s' and '%s'.%s" % (a.description, b.description, hint) ) crit = [(x == y) for x, y in list(constraints.values())[0]] if len(crit) == 1: return crit[0] else: return and_(*crit) @classmethod def _can_join(cls, left, right, consider_as_foreign_keys=None): if isinstance(left, Join): left_right = left.right else: left_right = None constraints = cls._joincond_scan_left_right( a=left, b=right, a_subset=left_right, consider_as_foreign_keys=consider_as_foreign_keys, ) return bool(constraints) @classmethod @util.dependencies("sqlalchemy.sql.util") def _joincond_scan_left_right( cls, sql_util, a, a_subset, b, consider_as_foreign_keys ): constraints = collections.defaultdict(list) for left in (a_subset, a): if left is None: continue for fk in sorted( b.foreign_keys, key=lambda fk: fk.parent._creation_order ): if ( consider_as_foreign_keys is not None and fk.parent not in consider_as_foreign_keys ): continue try: col = fk.get_referent(left) except exc.NoReferenceError as nrte: table_names = {t.name for t in sql_util.find_tables(left)} if nrte.table_name in table_names: raise else: continue if col is not None: constraints[fk.constraint].append((col, fk.parent)) if left is not b: for fk in sorted( left.foreign_keys, key=lambda fk: fk.parent._creation_order ): if ( consider_as_foreign_keys is not None and fk.parent not in consider_as_foreign_keys ): continue try: col = fk.get_referent(b) except exc.NoReferenceError as nrte: table_names = {t.name for t in sql_util.find_tables(b)} if nrte.table_name in table_names: raise else: continue if col is not None: constraints[fk.constraint].append((col, fk.parent)) if constraints: break return constraints @classmethod def _joincond_trim_constraints( cls, a, b, constraints, consider_as_foreign_keys ): # more than one constraint matched. narrow down the list # to include just those FKCs that match exactly to # "consider_as_foreign_keys". if consider_as_foreign_keys: for const in list(constraints): if set(f.parent for f in const.elements) != set( consider_as_foreign_keys ): del constraints[const] # if still multiple constraints, but # they all refer to the exact same end result, use it. if len(constraints) > 1: dedupe = set(tuple(crit) for crit in constraints.values()) if len(dedupe) == 1: key = list(constraints)[0] constraints = {key: constraints[key]} if len(constraints) != 1: raise exc.AmbiguousForeignKeysError( "Can't determine join between '%s' and '%s'; " "tables have more than one foreign key " "constraint relationship between them. " "Please specify the 'onclause' of this " "join explicitly." % (a.description, b.description) ) def select(self, whereclause=None, **kwargs): r"""Create a :class:`_expression.Select` from this :class:`_expression.Join`. The equivalent long-hand form, given a :class:`_expression.Join` object ``j``, is:: from sqlalchemy import select j = select([j.left, j.right], **kw).\ where(whereclause).\ select_from(j) :param whereclause: the WHERE criterion that will be sent to the :func:`select()` function :param \**kwargs: all other kwargs are sent to the underlying :func:`select()` function. """ collist = [self.left, self.right] return Select(collist, whereclause, from_obj=[self], **kwargs) @property def bind(self): return self.left.bind or self.right.bind @util.dependencies("sqlalchemy.sql.util") def alias(self, sqlutil, name=None, flat=False): r"""Return an alias of this :class:`_expression.Join`. The default behavior here is to first produce a SELECT construct from this :class:`_expression.Join`, then to produce an :class:`_expression.Alias` from that. So given a join of the form:: j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) The JOIN by itself would look like:: table_a JOIN table_b ON table_a.id = table_b.a_id Whereas the alias of the above, ``j.alias()``, would in a SELECT context look like:: (SELECT table_a.id AS table_a_id, table_b.id AS table_b_id, table_b.a_id AS table_b_a_id FROM table_a JOIN table_b ON table_a.id = table_b.a_id) AS anon_1 The equivalent long-hand form, given a :class:`_expression.Join` object ``j``, is:: from sqlalchemy import select, alias j = alias( select([j.left, j.right]).\ select_from(j).\ with_labels(True).\ correlate(False), name=name ) The selectable produced by :meth:`_expression.Join.alias` features the same columns as that of the two individual selectables presented under a single name - the individual columns are "auto-labeled", meaning the ``.c.`` collection of the resulting :class:`_expression.Alias` represents the names of the individual columns using a ``_`` scheme:: j.c.table_a_id j.c.table_b_a_id :meth:`_expression.Join.alias` also features an alternate option for aliasing joins which produces no enclosing SELECT and does not normally apply labels to the column names. The ``flat=True`` option will call :meth:`_expression.FromClause.alias` against the left and right sides individually. Using this option, no new ``SELECT`` is produced; we instead, from a construct as below:: j = table_a.join(table_b, table_a.c.id == table_b.c.a_id) j = j.alias(flat=True) we get a result like this:: table_a AS table_a_1 JOIN table_b AS table_b_1 ON table_a_1.id = table_b_1.a_id The ``flat=True`` argument is also propagated to the contained selectables, so that a composite join such as:: j = table_a.join( table_b.join(table_c, table_b.c.id == table_c.c.b_id), table_b.c.a_id == table_a.c.id ).alias(flat=True) Will produce an expression like:: table_a AS table_a_1 JOIN ( table_b AS table_b_1 JOIN table_c AS table_c_1 ON table_b_1.id = table_c_1.b_id ) ON table_a_1.id = table_b_1.a_id The standalone :func:`_expression.alias` function as well as the base :meth:`_expression.FromClause.alias` method also support the ``flat=True`` argument as a no-op, so that the argument can be passed to the ``alias()`` method of any selectable. .. versionadded:: 0.9.0 Added the ``flat=True`` option to create "aliases" of joins without enclosing inside of a SELECT subquery. :param name: name given to the alias. :param flat: if True, produce an alias of the left and right sides of this :class:`_expression.Join` and return the join of those two selectables. This produces join expression that does not include an enclosing SELECT. .. versionadded:: 0.9.0 .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` """ if flat: assert name is None, "Can't send name argument with flat" left_a, right_a = ( self.left.alias(flat=True), self.right.alias(flat=True), ) adapter = sqlutil.ClauseAdapter(left_a).chain( sqlutil.ClauseAdapter(right_a) ) return left_a.join( right_a, adapter.traverse(self.onclause), isouter=self.isouter, full=self.full, ) else: return self.select(use_labels=True, correlate=False).alias(name) @property def _hide_froms(self): return itertools.chain( *[_from_objects(x.left, x.right) for x in self._cloned_set] ) @property def _from_objects(self): return ( [self] + self.onclause._from_objects + self.left._from_objects + self.right._from_objects ) class Alias(FromClause): """Represents an table or selectable alias (AS). Represents an alias, as typically applied to any table or sub-select within a SQL statement using the ``AS`` keyword (or without the keyword on certain databases such as Oracle). This object is constructed from the :func:`_expression.alias` module level function as well as the :meth:`_expression.FromClause.alias` method available on all :class:`_expression.FromClause` subclasses. """ __visit_name__ = "alias" named_with_column = True _is_from_container = True def __init__(self, *arg, **kw): raise NotImplementedError( "The %s class is not intended to be constructed " "directly. Please use the %s() standalone " "function or the %s() method available from appropriate " "selectable objects." % ( self.__class__.__name__, self.__class__.__name__.lower(), self.__class__.__name__.lower(), ) ) @classmethod def _construct(cls, *arg, **kw): obj = cls.__new__(cls) obj._init(*arg, **kw) return obj @classmethod def _factory(cls, selectable, name=None, flat=False): """Return an :class:`_expression.Alias` object. An :class:`_expression.Alias` represents any :class:`_expression.FromClause` with an alternate name assigned within SQL, typically using the ``AS`` clause when generated, e.g. ``SELECT * FROM table AS aliasname``. Similar functionality is available via the :meth:`_expression.FromClause.alias` method available on all :class:`_expression.FromClause` subclasses. In terms of a SELECT object as generated from the :func:`_expression.select` function, the :meth:`_expression.SelectBase.alias` method returns an :class:`_expression.Alias` or similar object which represents a named, parenthesized subquery. When an :class:`_expression.Alias` is created from a :class:`_schema.Table` object, this has the effect of the table being rendered as ``tablename AS aliasname`` in a SELECT statement. For :func:`_expression.select` objects, the effect is that of creating a named subquery, i.e. ``(select ...) AS aliasname``. The ``name`` parameter is optional, and provides the name to use in the rendered SQL. If blank, an "anonymous" name will be deterministically generated at compile time. Deterministic means the name is guaranteed to be unique against other constructs used in the same statement, and will also be the same name for each successive compilation of the same statement object. :param selectable: any :class:`_expression.FromClause` subclass, such as a table, select statement, etc. :param name: string name to be assigned as the alias. If ``None``, a name will be deterministically generated at compile time. :param flat: Will be passed through to if the given selectable is an instance of :class:`_expression.Join` - see :meth:`_expression.Join.alias` for details. .. versionadded:: 0.9.0 """ return _interpret_as_from(selectable).alias(name=name, flat=flat) def _init(self, selectable, name=None): baseselectable = selectable while isinstance(baseselectable, Alias): baseselectable = baseselectable.element self.original = baseselectable self.supports_execution = baseselectable.supports_execution if self.supports_execution: self._execution_options = baseselectable._execution_options self.element = selectable if name is None: if self.original.named_with_column: name = getattr(self.original, "name", None) name = _anonymous_label("%%(%d %s)s" % (id(self), name or "anon")) self.name = name def self_group(self, against=None): if ( isinstance(against, CompoundSelect) and isinstance(self.original, Select) and self.original._needs_parens_for_grouping() ): return FromGrouping(self) return super(Alias, self).self_group(against=against) @property def description(self): if util.py3k: return self.name else: return self.name.encode("ascii", "backslashreplace") def as_scalar(self): try: return self.element.as_scalar() except AttributeError as err: util.raise_( AttributeError( "Element %s does not support " "'as_scalar()'" % self.element ), replace_context=err, ) def is_derived_from(self, fromclause): if fromclause in self._cloned_set: return True return self.element.is_derived_from(fromclause) def _populate_column_collection(self): for col in self.element.columns._all_columns: col._make_proxy(self) def _refresh_for_new_column(self, column): col = self.element._refresh_for_new_column(column) if col is not None: if not self._cols_populated: return None else: return col._make_proxy(self) else: return None def _copy_internals(self, clone=_clone, **kw): # don't apply anything to an aliased Table # for now. May want to drive this from # the given **kw. if isinstance(self.element, TableClause): return self._reset_exported() self.element = clone(self.element, **kw) baseselectable = self.element while isinstance(baseselectable, Alias): baseselectable = baseselectable.element self.original = baseselectable def get_children(self, column_collections=True, **kw): if column_collections: for c in self.c: yield c yield self.element @property def _from_objects(self): return [self] @property def bind(self): return self.element.bind class Lateral(Alias): """Represent a LATERAL subquery. This object is constructed from the :func:`_expression.lateral` module level function as well as the :meth:`_expression.FromClause.lateral` method available on all :class:`_expression.FromClause` subclasses. While LATERAL is part of the SQL standard, currently only more recent PostgreSQL versions provide support for this keyword. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. """ __visit_name__ = "lateral" _is_lateral = True @classmethod def _factory(cls, selectable, name=None): """Return a :class:`_expression.Lateral` object. :class:`_expression.Lateral` is an :class:`_expression.Alias` subclass that represents a subquery with the LATERAL keyword applied to it. The special behavior of a LATERAL subquery is that it appears in the FROM clause of an enclosing SELECT, but may correlate to other FROM clauses of that SELECT. It is a special case of subquery only supported by a small number of backends, currently more recent PostgreSQL versions. .. versionadded:: 1.1 .. seealso:: :ref:`lateral_selects` - overview of usage. """ return _interpret_as_from(selectable).lateral(name=name) class TableSample(Alias): """Represent a TABLESAMPLE clause. This object is constructed from the :func:`_expression.tablesample` module level function as well as the :meth:`_expression.FromClause.tablesample` method available on all :class:`_expression.FromClause` subclasses. .. versionadded:: 1.1 .. seealso:: :func:`_expression.tablesample` """ __visit_name__ = "tablesample" @classmethod def _factory(cls, selectable, sampling, name=None, seed=None): """Return a :class:`_expression.TableSample` object. :class:`_expression.TableSample` is an :class:`_expression.Alias` subclass that represents a table with the TABLESAMPLE clause applied to it. :func:`_expression.tablesample` is also available from the :class:`_expression.FromClause` class via the :meth:`_expression.FromClause.tablesample` method. The TABLESAMPLE clause allows selecting a randomly selected approximate percentage of rows from a table. It supports multiple sampling methods, most commonly BERNOULLI and SYSTEM. e.g.:: from sqlalchemy import func selectable = people.tablesample( func.bernoulli(1), name='alias', seed=func.random()) stmt = select([selectable.c.people_id]) Assuming ``people`` with a column ``people_id``, the above statement would render as:: SELECT alias.people_id FROM people AS alias TABLESAMPLE bernoulli(:bernoulli_1) REPEATABLE (random()) .. versionadded:: 1.1 :param sampling: a ``float`` percentage between 0 and 100 or :class:`_functions.Function`. :param name: optional alias name :param seed: any real-valued SQL expression. When specified, the REPEATABLE sub-clause is also rendered. """ return _interpret_as_from(selectable).tablesample( sampling, name=name, seed=seed ) def _init(self, selectable, sampling, name=None, seed=None): self.sampling = sampling self.seed = seed super(TableSample, self)._init(selectable, name=name) @util.dependencies("sqlalchemy.sql.functions") def _get_method(self, functions): if isinstance(self.sampling, functions.Function): return self.sampling else: return functions.func.system(self.sampling) class CTE(Generative, HasPrefixes, HasSuffixes, Alias): """Represent a Common Table Expression. The :class:`_expression.CTE` object is obtained using the :meth:`_expression.SelectBase.cte` method from any selectable. See that method for complete examples. """ __visit_name__ = "cte" @classmethod def _factory(cls, selectable, name=None, recursive=False): r"""Return a new :class:`_expression.CTE`, or Common Table Expression instance. Please see :meth:`_expression.HasCTE.cte` for detail on CTE usage. """ return _interpret_as_from(selectable).cte( name=name, recursive=recursive ) def _init( self, selectable, name=None, recursive=False, _cte_alias=None, _restates=frozenset(), _prefixes=None, _suffixes=None, ): self.recursive = recursive self._cte_alias = _cte_alias self._restates = _restates if _prefixes: self._prefixes = _prefixes if _suffixes: self._suffixes = _suffixes super(CTE, self)._init(selectable, name=name) def _copy_internals(self, clone=_clone, **kw): super(CTE, self)._copy_internals(clone, **kw) if self._cte_alias is not None: self._cte_alias = clone(self._cte_alias, **kw) self._restates = frozenset( [clone(elem, **kw) for elem in self._restates] ) @util.dependencies("sqlalchemy.sql.dml") def _populate_column_collection(self, dml): if isinstance(self.element, dml.UpdateBase): for col in self.element._returning: col._make_proxy(self) else: for col in self.element.columns._all_columns: col._make_proxy(self) def alias(self, name=None, flat=False): """Return an :class:`_expression.Alias` of this :class:`_expression.CTE`. This method is a CTE-specific specialization of the :meth:`_expression.FromClause.alias` method. .. seealso:: :ref:`core_tutorial_aliases` :func:`_expression.alias` """ return CTE._construct( self.original, name=name, recursive=self.recursive, _cte_alias=self, _prefixes=self._prefixes, _suffixes=self._suffixes, ) def union(self, other): return CTE._construct( self.original.union(other), name=self.name, recursive=self.recursive, _restates=self._restates.union([self]), _prefixes=self._prefixes, _suffixes=self._suffixes, ) def union_all(self, other): return CTE._construct( self.original.union_all(other), name=self.name, recursive=self.recursive, _restates=self._restates.union([self]), _prefixes=self._prefixes, _suffixes=self._suffixes, ) class HasCTE(object): """Mixin that declares a class to include CTE support. .. versionadded:: 1.1 """ def cte(self, name=None, recursive=False): r"""Return a new :class:`_expression.CTE`, or Common Table Expression instance. Common table expressions are a SQL standard whereby SELECT statements can draw upon secondary statements specified along with the primary statement, using a clause called "WITH". Special semantics regarding UNION can also be employed to allow "recursive" queries, where a SELECT statement can draw upon the set of rows that have previously been selected. CTEs can also be applied to DML constructs UPDATE, INSERT and DELETE on some databases, both as a source of CTE rows when combined with RETURNING, as well as a consumer of CTE rows. .. versionchanged:: 1.1 Added support for UPDATE/INSERT/DELETE as CTE, CTEs added to UPDATE/INSERT/DELETE. SQLAlchemy detects :class:`_expression.CTE` objects, which are treated similarly to :class:`_expression.Alias` objects, as special elements to be delivered to the FROM clause of the statement as well as to a WITH clause at the top of the statement. For special prefixes such as PostgreSQL "MATERIALIZED" and "NOT MATERIALIZED", the :meth:`_expression.CTE.prefix_with` method may be used to establish these. .. versionchanged:: 1.3.13 Added support for prefixes. In particular - MATERIALIZED and NOT MATERIALIZED. :param name: name given to the common table expression. Like :meth:`_expression.FromClause.alias`, the name can be left as ``None`` in which case an anonymous symbol will be used at query compile time. :param recursive: if ``True``, will render ``WITH RECURSIVE``. A recursive common table expression is intended to be used in conjunction with UNION ALL in order to derive rows from those already selected. The following examples include two from PostgreSQL's documentation at http://www.postgresql.org/docs/current/static/queries-with.html, as well as additional examples. Example 1, non recursive:: from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() orders = Table('orders', metadata, Column('region', String), Column('amount', Integer), Column('product', String), Column('quantity', Integer) ) regional_sales = select([ orders.c.region, func.sum(orders.c.amount).label('total_sales') ]).group_by(orders.c.region).cte("regional_sales") top_regions = select([regional_sales.c.region]).\ where( regional_sales.c.total_sales > select([ func.sum(regional_sales.c.total_sales)/10 ]) ).cte("top_regions") statement = select([ orders.c.region, orders.c.product, func.sum(orders.c.quantity).label("product_units"), func.sum(orders.c.amount).label("product_sales") ]).where(orders.c.region.in_( select([top_regions.c.region]) )).group_by(orders.c.region, orders.c.product) result = conn.execute(statement).fetchall() Example 2, WITH RECURSIVE:: from sqlalchemy import (Table, Column, String, Integer, MetaData, select, func) metadata = MetaData() parts = Table('parts', metadata, Column('part', String), Column('sub_part', String), Column('quantity', Integer), ) included_parts = select([ parts.c.sub_part, parts.c.part, parts.c.quantity]).\ where(parts.c.part=='our part').\ cte(recursive=True) incl_alias = included_parts.alias() parts_alias = parts.alias() included_parts = included_parts.union_all( select([ parts_alias.c.sub_part, parts_alias.c.part, parts_alias.c.quantity ]). where(parts_alias.c.part==incl_alias.c.sub_part) ) statement = select([ included_parts.c.sub_part, func.sum(included_parts.c.quantity). label('total_quantity') ]).\ group_by(included_parts.c.sub_part) result = conn.execute(statement).fetchall() Example 3, an upsert using UPDATE and INSERT with CTEs:: from datetime import date from sqlalchemy import (MetaData, Table, Column, Integer, Date, select, literal, and_, exists) metadata = MetaData() visitors = Table('visitors', metadata, Column('product_id', Integer, primary_key=True), Column('date', Date, primary_key=True), Column('count', Integer), ) # add 5 visitors for the product_id == 1 product_id = 1 day = date.today() count = 5 update_cte = ( visitors.update() .where(and_(visitors.c.product_id == product_id, visitors.c.date == day)) .values(count=visitors.c.count + count) .returning(literal(1)) .cte('update_cte') ) upsert = visitors.insert().from_select( [visitors.c.product_id, visitors.c.date, visitors.c.count], select([literal(product_id), literal(day), literal(count)]) .where(~exists(update_cte.select())) ) connection.execute(upsert) .. seealso:: :meth:`.orm.query.Query.cte` - ORM version of :meth:`_expression.HasCTE.cte`. """ return CTE._construct(self, name=name, recursive=recursive) class FromGrouping(FromClause): """Represent a grouping of a FROM clause""" __visit_name__ = "grouping" def __init__(self, element): self.element = element def _init_collections(self): pass @property def columns(self): return self.element.columns @property def primary_key(self): return self.element.primary_key @property def foreign_keys(self): return self.element.foreign_keys def is_derived_from(self, element): return self.element.is_derived_from(element) def alias(self, **kw): return FromGrouping(self.element.alias(**kw)) @property def _hide_froms(self): return self.element._hide_froms def get_children(self, **kwargs): return (self.element,) def _copy_internals(self, clone=_clone, **kw): self.element = clone(self.element, **kw) @property def _from_objects(self): return self.element._from_objects def __getattr__(self, attr): return getattr(self.element, attr) def __getstate__(self): return {"element": self.element} def __setstate__(self, state): self.element = state["element"] class TableClause(Immutable, FromClause): """Represents a minimal "table" construct. This is a lightweight table object that has only a name, a collection of columns, which are typically produced by the :func:`_expression.column` function, and a schema:: from sqlalchemy import table, column user = table("user", column("id"), column("name"), column("description"), ) The :class:`_expression.TableClause` construct serves as the base for the more commonly used :class:`_schema.Table` object, providing the usual set of :class:`_expression.FromClause` services including the ``.c.`` collection and statement generation methods. It does **not** provide all the additional schema-level services of :class:`_schema.Table`, including constraints, references to other tables, or support for :class:`_schema.MetaData`-level services. It's useful on its own as an ad-hoc construct used to generate quick SQL statements when a more fully fledged :class:`_schema.Table` is not on hand. """ __visit_name__ = "table" named_with_column = True implicit_returning = False """:class:`_expression.TableClause` doesn't support having a primary key or column -level defaults, so implicit returning doesn't apply.""" _autoincrement_column = None """No PK or default support so no autoincrement column.""" def __init__(self, name, *columns, **kw): """Produce a new :class:`_expression.TableClause`. The object returned is an instance of :class:`_expression.TableClause`, which represents the "syntactical" portion of the schema-level :class:`_schema.Table` object. It may be used to construct lightweight table constructs. .. versionchanged:: 1.0.0 :func:`_expression.table` can now be imported from the plain ``sqlalchemy`` namespace like any other SQL element. :param name: Name of the table. :param columns: A collection of :func:`_expression.column` constructs. :param schema: The schema name for this table. .. versionadded:: 1.3.18 :func:`_expression.table` can now accept a ``schema`` argument. """ super(TableClause, self).__init__() self.name = self.fullname = name self._columns = ColumnCollection() self.primary_key = ColumnSet() self.foreign_keys = set() for c in columns: self.append_column(c) schema = kw.pop("schema", None) if schema is not None: self.schema = schema if kw: raise exc.ArgumentError("Unsupported argument(s): %s" % list(kw)) def _init_collections(self): pass @util.memoized_property def description(self): if util.py3k: return self.name else: return self.name.encode("ascii", "backslashreplace") def append_column(self, c): existing = c.table if existing is not None and existing is not self: raise exc.ArgumentError( "column object '%s' already assigned to table %r" % (c.key, getattr(existing, "description", existing)) ) self._columns[c.key] = c c.table = self def get_children(self, column_collections=True, **kwargs): if column_collections: return [c for c in self.c] else: return [] @util.dependencies("sqlalchemy.sql.dml") def insert(self, dml, values=None, inline=False, **kwargs): """Generate an :func:`_expression.insert` construct against this :class:`_expression.TableClause`. E.g.:: table.insert().values(name='foo') See :func:`_expression.insert` for argument and usage information. """ return dml.Insert(self, values=values, inline=inline, **kwargs) @util.dependencies("sqlalchemy.sql.dml") def update( self, dml, whereclause=None, values=None, inline=False, **kwargs ): """Generate an :func:`_expression.update` construct against this :class:`_expression.TableClause`. E.g.:: table.update().where(table.c.id==7).values(name='foo') See :func:`_expression.update` for argument and usage information. """ return dml.Update( self, whereclause=whereclause, values=values, inline=inline, **kwargs ) @util.dependencies("sqlalchemy.sql.dml") def delete(self, dml, whereclause=None, **kwargs): """Generate a :func:`_expression.delete` construct against this :class:`_expression.TableClause`. E.g.:: table.delete().where(table.c.id==7) See :func:`_expression.delete` for argument and usage information. """ return dml.Delete(self, whereclause, **kwargs) @property def _from_objects(self): return [self] class ForUpdateArg(ClauseElement): @classmethod def parse_legacy_select(self, arg): """Parse the for_update argument of :func:`_expression.select`. :param mode: Defines the lockmode to use. ``None`` - translates to no lockmode ``'update'`` - translates to ``FOR UPDATE`` (standard SQL, supported by most dialects) ``'nowait'`` - translates to ``FOR UPDATE NOWAIT`` (supported by Oracle, PostgreSQL 8.1 upwards) ``'read'`` - translates to ``LOCK IN SHARE MODE`` (for MySQL), and ``FOR SHARE`` (for PostgreSQL) ``'read_nowait'`` - translates to ``FOR SHARE NOWAIT`` (supported by PostgreSQL). ``FOR SHARE`` and ``FOR SHARE NOWAIT`` (PostgreSQL). """ if arg in (None, False): return None nowait = read = False if arg == "nowait": nowait = True elif arg == "read": read = True elif arg == "read_nowait": read = nowait = True elif arg is not True: raise exc.ArgumentError("Unknown for_update argument: %r" % arg) return ForUpdateArg(read=read, nowait=nowait) @property def legacy_for_update_value(self): if self.read and not self.nowait: return "read" elif self.read and self.nowait: return "read_nowait" elif self.nowait: return "nowait" else: return True def __eq__(self, other): return ( isinstance(other, ForUpdateArg) and other.nowait == self.nowait and other.read == self.read and other.skip_locked == self.skip_locked and other.key_share == self.key_share and other.of is self.of ) def __hash__(self): return id(self) def _copy_internals(self, clone=_clone, **kw): if self.of is not None: self.of = [clone(col, **kw) for col in self.of] def __init__( self, nowait=False, read=False, of=None, skip_locked=False, key_share=False, ): """Represents arguments specified to :meth:`_expression.Select.for_update`. .. versionadded:: 0.9.0 """ self.nowait = nowait self.read = read self.skip_locked = skip_locked self.key_share = key_share if of is not None: self.of = [ _interpret_as_column_or_from(elem) for elem in util.to_list(of) ] else: self.of = None class SelectBase(HasCTE, Executable, FromClause): """Base class for SELECT statements. This includes :class:`_expression.Select`, :class:`_selectable.CompoundSelect` and :class:`.TextAsFrom`. """ def as_scalar(self): """Return a 'scalar' representation of this selectable, which can be used as a column expression. Typically, a select statement which has only one column in its columns clause is eligible to be used as a scalar expression. The returned object is an instance of :class:`ScalarSelect`. """ return ScalarSelect(self) def label(self, name): """Return a 'scalar' representation of this selectable, embedded as a subquery with a label. .. seealso:: :meth:`_expression.SelectBase.as_scalar`. """ return self.as_scalar().label(name) @_generative @util.deprecated( "0.6", message="The :meth:`.SelectBase.autocommit` method is deprecated, " "and will be removed in a future release. Please use the " "the :paramref:`.Connection.execution_options.autocommit` " "parameter in conjunction with the " ":meth:`.Executable.execution_options` method.", ) def autocommit(self): """Return a new selectable with the 'autocommit' flag set to True. """ self._execution_options = self._execution_options.union( {"autocommit": True} ) def _generate(self): """Override the default _generate() method to also clear out exported collections.""" s = self.__class__.__new__(self.__class__) s.__dict__ = self.__dict__.copy() s._reset_exported() return s @property def _from_objects(self): return [self] class GenerativeSelect(SelectBase): """Base class for SELECT statements where additional elements can be added. This serves as the base for :class:`_expression.Select` and :class:`_selectable.CompoundSelect` where elements such as ORDER BY, GROUP BY can be added and column rendering can be controlled. Compare to :class:`.TextAsFrom`, which, while it subclasses :class:`_expression.SelectBase` and is also a SELECT construct, represents a fixed textual string which cannot be altered at this level, only wrapped as a subquery. .. versionadded:: 0.9.0 :class:`_expression.GenerativeSelect` was added to provide functionality specific to :class:`_expression.Select` and :class:`_selectable.CompoundSelect` while allowing :class:`_expression.SelectBase` to be used for other SELECT-like objects, e.g. :class:`.TextAsFrom`. """ _order_by_clause = ClauseList() _group_by_clause = ClauseList() _limit_clause = None _offset_clause = None _for_update_arg = None def __init__( self, use_labels=False, for_update=False, limit=None, offset=None, order_by=None, group_by=None, bind=None, autocommit=None, ): self.use_labels = use_labels if for_update is not False: self._for_update_arg = ForUpdateArg.parse_legacy_select(for_update) if autocommit is not None: util.warn_deprecated( "The select.autocommit parameter is deprecated and will be " "removed in a future release. Please refer to the " "Select.execution_options.autocommit` parameter." ) self._execution_options = self._execution_options.union( {"autocommit": autocommit} ) if limit is not None: self._limit_clause = _offset_or_limit_clause(limit) if offset is not None: self._offset_clause = _offset_or_limit_clause(offset) self._bind = bind if order_by is not None: self._order_by_clause = ClauseList( *util.to_list(order_by), _literal_as_text=_literal_and_labels_as_label_reference ) if group_by is not None: self._group_by_clause = ClauseList( *util.to_list(group_by), _literal_as_text=_literal_as_label_reference ) @property def for_update(self): """Provide legacy dialect support for the ``for_update`` attribute.""" if self._for_update_arg is not None: return self._for_update_arg.legacy_for_update_value else: return None @for_update.setter def for_update(self, value): self._for_update_arg = ForUpdateArg.parse_legacy_select(value) @_generative def with_for_update( self, nowait=False, read=False, of=None, skip_locked=False, key_share=False, ): """Specify a ``FOR UPDATE`` clause for this :class:`_expression.GenerativeSelect`. E.g.:: stmt = select([table]).with_for_update(nowait=True) On a database like PostgreSQL or Oracle, the above would render a statement like:: SELECT table.a, table.b FROM table FOR UPDATE NOWAIT on other backends, the ``nowait`` option is ignored and instead would produce:: SELECT table.a, table.b FROM table FOR UPDATE When called with no arguments, the statement will render with the suffix ``FOR UPDATE``. Additional arguments can then be provided which allow for common database-specific variants. :param nowait: boolean; will render ``FOR UPDATE NOWAIT`` on Oracle and PostgreSQL dialects. :param read: boolean; will render ``LOCK IN SHARE MODE`` on MySQL, ``FOR SHARE`` on PostgreSQL. On PostgreSQL, when combined with ``nowait``, will render ``FOR SHARE NOWAIT``. :param of: SQL expression or list of SQL expression elements (typically :class:`_schema.Column` objects or a compatible expression) which will render into a ``FOR UPDATE OF`` clause; supported by PostgreSQL and Oracle. May render as a table or as a column depending on backend. :param skip_locked: boolean, will render ``FOR UPDATE SKIP LOCKED`` on Oracle and PostgreSQL dialects or ``FOR SHARE SKIP LOCKED`` if ``read=True`` is also specified. .. versionadded:: 1.1.0 :param key_share: boolean, will render ``FOR NO KEY UPDATE``, or if combined with ``read=True`` will render ``FOR KEY SHARE``, on the PostgreSQL dialect. .. versionadded:: 1.1.0 """ self._for_update_arg = ForUpdateArg( nowait=nowait, read=read, of=of, skip_locked=skip_locked, key_share=key_share, ) @_generative def apply_labels(self): """Return a new selectable with the 'use_labels' flag set to True. This will result in column expressions being generated using labels against their table name, such as "SELECT somecolumn AS tablename_somecolumn". This allows selectables which contain multiple FROM clauses to produce a unique set of column names regardless of name conflicts among the individual FROM clauses. """ self.use_labels = True @property def _limit(self): """Get an integer value for the limit. This should only be used by code that cannot support a limit as a BindParameter or other custom clause as it will throw an exception if the limit isn't currently set to an integer. """ return _offset_or_limit_clause_asint(self._limit_clause, "limit") @property def _simple_int_limit(self): """True if the LIMIT clause is a simple integer, False if it is not present or is a SQL expression. """ return isinstance(self._limit_clause, _OffsetLimitParam) @property def _simple_int_offset(self): """True if the OFFSET clause is a simple integer, False if it is not present or is a SQL expression. """ return isinstance(self._offset_clause, _OffsetLimitParam) @property def _offset(self): """Get an integer value for the offset. This should only be used by code that cannot support an offset as a BindParameter or other custom clause as it will throw an exception if the offset isn't currently set to an integer. """ return _offset_or_limit_clause_asint(self._offset_clause, "offset") @_generative def limit(self, limit): """Return a new selectable with the given LIMIT criterion applied. This is a numerical value which usually renders as a ``LIMIT`` expression in the resulting select. Backends that don't support ``LIMIT`` will attempt to provide similar functionality. .. versionchanged:: 1.0.0 - :meth:`_expression.Select.limit` can now accept arbitrary SQL expressions as well as integer values. :param limit: an integer LIMIT parameter, or a SQL expression that provides an integer result. """ self._limit_clause = _offset_or_limit_clause(limit) @_generative def offset(self, offset): """Return a new selectable with the given OFFSET criterion applied. This is a numeric value which usually renders as an ``OFFSET`` expression in the resulting select. Backends that don't support ``OFFSET`` will attempt to provide similar functionality. .. versionchanged:: 1.0.0 - :meth:`_expression.Select.offset` can now accept arbitrary SQL expressions as well as integer values. :param offset: an integer OFFSET parameter, or a SQL expression that provides an integer result. """ self._offset_clause = _offset_or_limit_clause(offset) @_generative def order_by(self, *clauses): r"""Return a new selectable with the given list of ORDER BY criterion applied. e.g.:: stmt = select([table]).order_by(table.c.id, table.c.name) :param \*clauses: a series of :class:`_expression.ColumnElement` constructs which will be used to generate an ORDER BY clause. .. seealso:: :ref:`core_tutorial_ordering` """ self.append_order_by(*clauses) @_generative def group_by(self, *clauses): r"""Return a new selectable with the given list of GROUP BY criterion applied. e.g.:: stmt = select([table.c.name, func.max(table.c.stat)]).\ group_by(table.c.name) :param \*clauses: a series of :class:`_expression.ColumnElement` constructs which will be used to generate an GROUP BY clause. .. seealso:: :ref:`core_tutorial_ordering` """ self.append_group_by(*clauses) def append_order_by(self, *clauses): """Append the given ORDER BY criterion applied to this selectable. The criterion will be appended to any pre-existing ORDER BY criterion. This is an **in-place** mutation method; the :meth:`_expression.GenerativeSelect.order_by` method is preferred, as it provides standard :term:`method chaining`. .. seealso:: :meth:`_expression.GenerativeSelect.order_by` """ if len(clauses) == 1 and clauses[0] is None: self._order_by_clause = ClauseList() else: if getattr(self, "_order_by_clause", None) is not None: clauses = list(self._order_by_clause) + list(clauses) self._order_by_clause = ClauseList( *clauses, _literal_as_text=_literal_and_labels_as_label_reference ) def append_group_by(self, *clauses): """Append the given GROUP BY criterion applied to this selectable. The criterion will be appended to any pre-existing GROUP BY criterion. This is an **in-place** mutation method; the :meth:`_expression.GenerativeSelect.group_by` method is preferred, as it provides standard :term:`method chaining`. .. seealso:: :meth:`_expression.GenerativeSelect.group_by` """ if len(clauses) == 1 and clauses[0] is None: self._group_by_clause = ClauseList() else: if getattr(self, "_group_by_clause", None) is not None: clauses = list(self._group_by_clause) + list(clauses) self._group_by_clause = ClauseList( *clauses, _literal_as_text=_literal_as_label_reference ) @property def _label_resolve_dict(self): raise NotImplementedError() def _copy_internals(self, clone=_clone, **kw): if self._limit_clause is not None: self._limit_clause = clone(self._limit_clause, **kw) if self._offset_clause is not None: self._offset_clause = clone(self._offset_clause, **kw) class CompoundSelect(GenerativeSelect): """Forms the basis of ``UNION``, ``UNION ALL``, and other SELECT-based set operations. .. seealso:: :func:`_expression.union` :func:`_expression.union_all` :func:`_expression.intersect` :func:`_expression.intersect_all` :func:`_expression.except` :func:`_expression.except_all` """ __visit_name__ = "compound_select" UNION = util.symbol("UNION") UNION_ALL = util.symbol("UNION ALL") EXCEPT = util.symbol("EXCEPT") EXCEPT_ALL = util.symbol("EXCEPT ALL") INTERSECT = util.symbol("INTERSECT") INTERSECT_ALL = util.symbol("INTERSECT ALL") _is_from_container = True def __init__(self, keyword, *selects, **kwargs): self._auto_correlate = kwargs.pop("correlate", False) self.keyword = keyword self.selects = [] numcols = None # some DBs do not like ORDER BY in the inner queries of a UNION, etc. for n, s in enumerate(selects): s = _clause_element_as_expr(s) if not numcols: numcols = len(s.c._all_columns) elif len(s.c._all_columns) != numcols: raise exc.ArgumentError( "All selectables passed to " "CompoundSelect must have identical numbers of " "columns; select #%d has %d columns, select " "#%d has %d" % ( 1, len(self.selects[0].c._all_columns), n + 1, len(s.c._all_columns), ) ) self.selects.append(s.self_group(against=self)) GenerativeSelect.__init__(self, **kwargs) @property def _label_resolve_dict(self): d = dict((c.key, c) for c in self.c) return d, d, d @classmethod def _create_union(cls, *selects, **kwargs): r"""Return a ``UNION`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. A similar :func:`union()` method is available on all :class:`_expression.FromClause` subclasses. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.UNION, *selects, **kwargs) @classmethod def _create_union_all(cls, *selects, **kwargs): r"""Return a ``UNION ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. A similar :func:`union_all()` method is available on all :class:`_expression.FromClause` subclasses. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.UNION_ALL, *selects, **kwargs) @classmethod def _create_except(cls, *selects, **kwargs): r"""Return an ``EXCEPT`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.EXCEPT, *selects, **kwargs) @classmethod def _create_except_all(cls, *selects, **kwargs): r"""Return an ``EXCEPT ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.EXCEPT_ALL, *selects, **kwargs) @classmethod def _create_intersect(cls, *selects, **kwargs): r"""Return an ``INTERSECT`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.INTERSECT, *selects, **kwargs) @classmethod def _create_intersect_all(cls, *selects, **kwargs): r"""Return an ``INTERSECT ALL`` of multiple selectables. The returned object is an instance of :class:`_selectable.CompoundSelect`. :param \*selects: a list of :class:`_expression.Select` instances. :param \**kwargs: available keyword arguments are the same as those of :func:`select`. """ return CompoundSelect(CompoundSelect.INTERSECT_ALL, *selects, **kwargs) def _scalar_type(self): return self.selects[0]._scalar_type() def self_group(self, against=None): return FromGrouping(self) def is_derived_from(self, fromclause): for s in self.selects: if s.is_derived_from(fromclause): return True return False def _populate_column_collection(self): for cols in zip(*[s.c._all_columns for s in self.selects]): # this is a slightly hacky thing - the union exports a # column that resembles just that of the *first* selectable. # to get at a "composite" column, particularly foreign keys, # you have to dig through the proxies collection which we # generate below. We may want to improve upon this, such as # perhaps _make_proxy can accept a list of other columns # that are "shared" - schema.column can then copy all the # ForeignKeys in. this would allow the union() to have all # those fks too. proxy = cols[0]._make_proxy( self, name=cols[0]._label if self.use_labels else None, key=cols[0]._key_label if self.use_labels else None, ) # hand-construct the "_proxies" collection to include all # derived columns place a 'weight' annotation corresponding # to how low in the list of select()s the column occurs, so # that the corresponding_column() operation can resolve # conflicts proxy._proxies = [ c._annotate({"weight": i + 1}) for (i, c) in enumerate(cols) ] def _refresh_for_new_column(self, column): for s in self.selects: s._refresh_for_new_column(column) if not self._cols_populated: return None raise NotImplementedError( "CompoundSelect constructs don't support " "addition of columns to underlying " "selectables" ) def _copy_internals(self, clone=_clone, **kw): super(CompoundSelect, self)._copy_internals(clone, **kw) self._reset_exported() self.selects = [clone(s, **kw) for s in self.selects] if hasattr(self, "_col_map"): del self._col_map for attr in ( "_order_by_clause", "_group_by_clause", "_for_update_arg", ): if getattr(self, attr) is not None: setattr(self, attr, clone(getattr(self, attr), **kw)) def get_children(self, column_collections=True, **kwargs): return ( (column_collections and list(self.c) or []) + [self._order_by_clause, self._group_by_clause] + list(self.selects) ) def bind(self): if self._bind: return self._bind for s in self.selects: e = s.bind if e: return e else: return None def _set_bind(self, bind): self._bind = bind bind = property(bind, _set_bind) class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """Represents a ``SELECT`` statement.""" __visit_name__ = "select" _prefixes = () _suffixes = () _hints = util.immutabledict() _statement_hints = () _distinct = False _from_cloned = None _correlate = () _correlate_except = None _memoized_property = SelectBase._memoized_property _is_select = True @util.deprecated_params( autocommit=( "0.6", "The :paramref:`_expression.select.autocommit` " "parameter is deprecated " "and will be removed in a future release. Please refer to " "the :paramref:`.Connection.execution_options.autocommit` " "parameter in conjunction with the the " ":meth:`.Executable.execution_options` method in order to " "affect the autocommit behavior for a statement.", ), for_update=( "0.9", "The :paramref:`_expression.select.for_update` " "parameter is deprecated and " "will be removed in a future release. Please refer to the " ":meth:`_expression.Select.with_for_update` to specify the " "structure of the ``FOR UPDATE`` clause.", ), ) def __init__( self, columns=None, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, prefixes=None, suffixes=None, **kwargs ): """Construct a new :class:`_expression.Select`. Similar functionality is also available via the :meth:`_expression.FromClause.select` method on any :class:`_expression.FromClause`. All arguments which accept :class:`_expression.ClauseElement` arguments also accept string arguments, which will be converted as appropriate into either :func:`_expression.text` or :func:`_expression.literal_column` constructs. .. seealso:: :ref:`coretutorial_selecting` - Core Tutorial description of :func:`_expression.select`. :param columns: A list of :class:`_expression.ColumnElement` or :class:`_expression.FromClause` objects which will form the columns clause of the resulting statement. For those objects that are instances of :class:`_expression.FromClause` (typically :class:`_schema.Table` or :class:`_expression.Alias` objects), the :attr:`_expression.FromClause.c` collection is extracted to form a collection of :class:`_expression.ColumnElement` objects. This parameter will also accept :class:`_expression.TextClause` constructs as given, as well as ORM-mapped classes. .. note:: The :paramref:`_expression.select.columns` parameter is not available in the method form of :func:`_expression.select`, e.g. :meth:`_expression.FromClause.select`. .. seealso:: :meth:`_expression.Select.column` :meth:`_expression.Select.with_only_columns` :param whereclause: A :class:`_expression.ClauseElement` expression which will be used to form the ``WHERE`` clause. It is typically preferable to add WHERE criterion to an existing :class:`_expression.Select` using method chaining with :meth:`_expression.Select.where`. .. seealso:: :meth:`_expression.Select.where` :param from_obj: A list of :class:`_expression.ClauseElement` objects which will be added to the ``FROM`` clause of the resulting statement. This is equivalent to calling :meth:`_expression.Select.select_from` using method chaining on an existing :class:`_expression.Select` object. .. seealso:: :meth:`_expression.Select.select_from` - full description of explicit FROM clause specification. :param autocommit: legacy autocommit parameter. :param bind=None: an :class:`_engine.Engine` or :class:`_engine.Connection` instance to which the resulting :class:`_expression.Select` object will be bound. The :class:`_expression.Select` object will otherwise automatically bind to whatever :class:`~.base.Connectable` instances can be located within its contained :class:`_expression.ClauseElement` members. :param correlate=True: indicates that this :class:`_expression.Select` object should have its contained :class:`_expression.FromClause` elements "correlated" to an enclosing :class:`_expression.Select` object. It is typically preferable to specify correlations on an existing :class:`_expression.Select` construct using :meth:`_expression.Select.correlate`. .. seealso:: :meth:`_expression.Select.correlate` - full description of correlation. :param distinct=False: when ``True``, applies a ``DISTINCT`` qualifier to the columns clause of the resulting statement. The boolean argument may also be a column expression or list of column expressions - this is a special calling form which is understood by the PostgreSQL dialect to render the ``DISTINCT ON ()`` syntax. ``distinct`` is also available on an existing :class:`_expression.Select` object via the :meth:`_expression.Select.distinct` method. .. seealso:: :meth:`_expression.Select.distinct` :param for_update=False: when ``True``, applies ``FOR UPDATE`` to the end of the resulting statement. ``for_update`` accepts various string values interpreted by specific backends, including: * ``"read"`` - on MySQL, translates to ``LOCK IN SHARE MODE``; on PostgreSQL, translates to ``FOR SHARE``. * ``"nowait"`` - on PostgreSQL and Oracle, translates to ``FOR UPDATE NOWAIT``. * ``"read_nowait"`` - on PostgreSQL, translates to ``FOR SHARE NOWAIT``. .. seealso:: :meth:`_expression.Select.with_for_update` - improved API for specifying the ``FOR UPDATE`` clause. :param group_by: a list of :class:`_expression.ClauseElement` objects which will comprise the ``GROUP BY`` clause of the resulting select. This parameter is typically specified more naturally using the :meth:`_expression.Select.group_by` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.group_by` :param having: a :class:`_expression.ClauseElement` that will comprise the ``HAVING`` clause of the resulting select when ``GROUP BY`` is used. This parameter is typically specified more naturally using the :meth:`_expression.Select.having` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.having` :param limit=None: a numerical value which usually renders as a ``LIMIT`` expression in the resulting select. Backends that don't support ``LIMIT`` will attempt to provide similar functionality. This parameter is typically specified more naturally using the :meth:`_expression.Select.limit` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.limit` :param offset=None: a numeric value which usually renders as an ``OFFSET`` expression in the resulting select. Backends that don't support ``OFFSET`` will attempt to provide similar functionality. This parameter is typically specified more naturally using the :meth:`_expression.Select.offset` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.offset` :param order_by: a scalar or list of :class:`_expression.ClauseElement` objects which will comprise the ``ORDER BY`` clause of the resulting select. This parameter is typically specified more naturally using the :meth:`_expression.Select.order_by` method on an existing :class:`_expression.Select`. .. seealso:: :meth:`_expression.Select.order_by` :param use_labels=False: when ``True``, the statement will be generated using labels for each column in the columns clause, which qualify each column with its parent table's (or aliases) name so that name conflicts between columns in different tables don't occur. The format of the label is ``_``. The "c" collection of the resulting :class:`_expression.Select` object will use these names as well for targeting column members. This parameter can also be specified on an existing :class:`_expression.Select` object using the :meth:`_expression.Select.apply_labels` method. .. seealso:: :meth:`_expression.Select.apply_labels` """ self._auto_correlate = correlate if distinct is not False: if distinct is True: self._distinct = True else: self._distinct = [ _literal_as_label_reference(e) for e in util.to_list(distinct) ] if from_obj is not None: self._from_obj = util.OrderedSet( _interpret_as_from(f) for f in util.to_list(from_obj) ) else: self._from_obj = util.OrderedSet() try: cols_present = bool(columns) except TypeError as err: util.raise_( exc.ArgumentError( "columns argument to select() must " "be a Python list or other iterable" ), replace_context=err, ) if cols_present: self._raw_columns = [] for c in columns: c = _interpret_as_column_or_from(c) if isinstance(c, ScalarSelect): c = c.self_group(against=operators.comma_op) self._raw_columns.append(c) else: self._raw_columns = [] if whereclause is not None: self._whereclause = _literal_as_text(whereclause).self_group( against=operators._asbool ) else: self._whereclause = None if having is not None: self._having = _literal_as_text(having).self_group( against=operators._asbool ) else: self._having = None if prefixes: self._setup_prefixes(prefixes) if suffixes: self._setup_suffixes(suffixes) GenerativeSelect.__init__(self, **kwargs) @property def _froms(self): # would love to cache this, # but there's just enough edge cases, particularly now that # declarative encourages construction of SQL expressions # without tables present, to just regen this each time. froms = [] seen = set() translate = self._from_cloned for item in itertools.chain( _from_objects(*self._raw_columns), _from_objects(self._whereclause) if self._whereclause is not None else (), self._from_obj, ): if item is self: raise exc.InvalidRequestError( "select() construct refers to itself as a FROM" ) if translate and item in translate: item = translate[item] if not seen.intersection(item._cloned_set): froms.append(item) seen.update(item._cloned_set) return froms def _get_display_froms( self, explicit_correlate_froms=None, implicit_correlate_froms=None ): """Return the full list of 'from' clauses to be displayed. Takes into account a set of existing froms which may be rendered in the FROM clause of enclosing selects; this Select may want to leave those absent if it is automatically correlating. """ froms = self._froms toremove = set( itertools.chain(*[_expand_cloned(f._hide_froms) for f in froms]) ) if toremove: # if we're maintaining clones of froms, # add the copies out to the toremove list. only include # clones that are lexical equivalents. if self._from_cloned: toremove.update( self._from_cloned[f] for f in toremove.intersection(self._from_cloned) if self._from_cloned[f]._is_lexical_equivalent(f) ) # filter out to FROM clauses not in the list, # using a list to maintain ordering froms = [f for f in froms if f not in toremove] if self._correlate: to_correlate = self._correlate if to_correlate: froms = [ f for f in froms if f not in _cloned_intersection( _cloned_intersection( froms, explicit_correlate_froms or () ), to_correlate, ) ] if self._correlate_except is not None: froms = [ f for f in froms if f not in _cloned_difference( _cloned_intersection( froms, explicit_correlate_froms or () ), self._correlate_except, ) ] if ( self._auto_correlate and implicit_correlate_froms and len(froms) > 1 ): froms = [ f for f in froms if f not in _cloned_intersection(froms, implicit_correlate_froms) ] if not len(froms): raise exc.InvalidRequestError( "Select statement '%s" "' returned no FROM clauses " "due to auto-correlation; " "specify correlate() " "to control correlation " "manually." % self ) return froms def _scalar_type(self): elem = self._raw_columns[0] cols = list(elem._select_iterable) return cols[0].type @property def froms(self): """Return the displayed list of FromClause elements.""" return self._get_display_froms() def with_statement_hint(self, text, dialect_name="*"): """Add a statement hint to this :class:`_expression.Select`. This method is similar to :meth:`_expression.Select.with_hint` except that it does not require an individual table, and instead applies to the statement as a whole. Hints here are specific to the backend database and may include directives such as isolation levels, file directives, fetch directives, etc. .. versionadded:: 1.0.0 .. seealso:: :meth:`_expression.Select.with_hint` :meth:`.Select.prefix_with` - generic SELECT prefixing which also can suit some database-specific HINT syntaxes such as MySQL optimizer hints """ return self.with_hint(None, text, dialect_name) @_generative def with_hint(self, selectable, text, dialect_name="*"): r"""Add an indexing or other executional context hint for the given selectable to this :class:`_expression.Select`. The text of the hint is rendered in the appropriate location for the database backend in use, relative to the given :class:`_schema.Table` or :class:`_expression.Alias` passed as the ``selectable`` argument. The dialect implementation typically uses Python string substitution syntax with the token ``%(name)s`` to render the name of the table or alias. E.g. when using Oracle, the following:: select([mytable]).\ with_hint(mytable, "index(%(name)s ix_mytable)") Would render SQL as:: select /*+ index(mytable ix_mytable) */ ... from mytable The ``dialect_name`` option will limit the rendering of a particular hint to a particular backend. Such as, to add hints for both Oracle and Sybase simultaneously:: select([mytable]).\ with_hint(mytable, "index(%(name)s ix_mytable)", 'oracle').\ with_hint(mytable, "WITH INDEX ix_mytable", 'sybase') .. seealso:: :meth:`_expression.Select.with_statement_hint` """ if selectable is None: self._statement_hints += ((dialect_name, text),) else: self._hints = self._hints.union({(selectable, dialect_name): text}) @property def type(self): raise exc.InvalidRequestError( "Select objects don't have a type. " "Call as_scalar() on this Select " "object to return a 'scalar' version " "of this Select." ) @_memoized_property.method def locate_all_froms(self): """Return a Set of all :class:`_expression.FromClause` elements referenced by this Select. This set is a superset of that returned by the ``froms`` property, which is specifically for those FromClause elements that would actually be rendered. """ froms = self._froms return froms + list(_from_objects(*froms)) @property def inner_columns(self): """An iterator of all :class:`_expression.ColumnElement` expressions which would be rendered into the columns clause of the resulting SELECT statement. """ return _select_iterables(self._raw_columns) @_memoized_property def _label_resolve_dict(self): with_cols = dict( (c._resolve_label or c._label or c.key, c) for c in _select_iterables(self._raw_columns) if c._allow_label_resolve ) only_froms = dict( (c.key, c) for c in _select_iterables(self.froms) if c._allow_label_resolve ) only_cols = with_cols.copy() for key, value in only_froms.items(): with_cols.setdefault(key, value) return with_cols, only_froms, only_cols def is_derived_from(self, fromclause): if self in fromclause._cloned_set: return True for f in self.locate_all_froms(): if f.is_derived_from(fromclause): return True return False def _copy_internals(self, clone=_clone, **kw): super(Select, self)._copy_internals(clone, **kw) # Select() object has been cloned and probably adapted by the # given clone function. Apply the cloning function to internal # objects # 1. keep a dictionary of the froms we've cloned, and what # they've become. This is consulted later when we derive # additional froms from "whereclause" and the columns clause, # which may still reference the uncloned parent table. # as of 0.7.4 we also put the current version of _froms, which # gets cleared on each generation. previously we were "baking" # _froms into self._from_obj. self._from_cloned = from_cloned = dict( (f, clone(f, **kw)) for f in self._from_obj.union(self._froms) ) # 3. update persistent _from_obj with the cloned versions. self._from_obj = util.OrderedSet( from_cloned[f] for f in self._from_obj ) # the _correlate collection is done separately, what can happen # here is the same item is _correlate as in _from_obj but the # _correlate version has an annotation on it - (specifically # RelationshipProperty.Comparator._criterion_exists() does # this). Also keep _correlate liberally open with its previous # contents, as this set is used for matching, not rendering. self._correlate = set(clone(f, **kw) for f in self._correlate).union( self._correlate ) # do something similar for _correlate_except - this is a more # unusual case but same idea applies if self._correlate_except: self._correlate_except = set( clone(f, **kw) for f in self._correlate_except ).union(self._correlate_except) # 4. clone other things. The difficulty here is that Column # objects are not actually cloned, and refer to their original # .table, resulting in the wrong "from" parent after a clone # operation. Hence _from_cloned and _from_obj supersede what is # present here. self._raw_columns = [clone(c, **kw) for c in self._raw_columns] for attr in ( "_whereclause", "_having", "_order_by_clause", "_group_by_clause", "_for_update_arg", ): if getattr(self, attr) is not None: setattr(self, attr, clone(getattr(self, attr), **kw)) # erase exported column list, _froms collection, # etc. self._reset_exported() def get_children(self, column_collections=True, **kwargs): """Return child elements as per the ClauseElement specification.""" return ( (column_collections and list(self.columns) or []) + self._raw_columns + list(self._froms) + [ x for x in ( self._whereclause, self._having, self._order_by_clause, self._group_by_clause, ) if x is not None ] ) @_generative def column(self, column): """Return a new :func:`_expression.select` construct with the given column expression added to its columns clause. E.g.:: my_select = my_select.column(table.c.new_column) See the documentation for :meth:`_expression.Select.with_only_columns` for guidelines on adding /replacing the columns of a :class:`_expression.Select` object. """ self.append_column(column) @util.dependencies("sqlalchemy.sql.util") def reduce_columns(self, sqlutil, only_synonyms=True): """Return a new :func:`_expression.select` construct with redundantly named, equivalently-valued columns removed from the columns clause. "Redundant" here means two columns where one refers to the other either based on foreign key, or via a simple equality comparison in the WHERE clause of the statement. The primary purpose of this method is to automatically construct a select statement with all uniquely-named columns, without the need to use table-qualified labels as :meth:`_expression.Select.apply_labels` does. When columns are omitted based on foreign key, the referred-to column is the one that's kept. When columns are omitted based on WHERE equivalence, the first column in the columns clause is the one that's kept. :param only_synonyms: when True, limit the removal of columns to those which have the same name as the equivalent. Otherwise, all columns that are equivalent to another are removed. """ return self.with_only_columns( sqlutil.reduce_columns( self.inner_columns, only_synonyms=only_synonyms, *(self._whereclause,) + tuple(self._from_obj) ) ) @_generative def with_only_columns(self, columns): r"""Return a new :func:`_expression.select` construct with its columns clause replaced with the given columns. This method is exactly equivalent to as if the original :func:`_expression.select` had been called with the given columns clause. I.e. a statement:: s = select([table1.c.a, table1.c.b]) s = s.with_only_columns([table1.c.b]) should be exactly equivalent to:: s = select([table1.c.b]) This means that FROM clauses which are only derived from the column list will be discarded if the new column list no longer contains that FROM:: >>> table1 = table('t1', column('a'), column('b')) >>> table2 = table('t2', column('a'), column('b')) >>> s1 = select([table1.c.a, table2.c.b]) >>> print(s1) SELECT t1.a, t2.b FROM t1, t2 >>> s2 = s1.with_only_columns([table2.c.b]) >>> print(s2) SELECT t2.b FROM t1 The preferred way to maintain a specific FROM clause in the construct, assuming it won't be represented anywhere else (i.e. not in the WHERE clause, etc.) is to set it using :meth:`_expression.Select.select_from`:: >>> s1 = select([table1.c.a, table2.c.b]).\ ... select_from(table1.join(table2, ... table1.c.a==table2.c.a)) >>> s2 = s1.with_only_columns([table2.c.b]) >>> print(s2) SELECT t2.b FROM t1 JOIN t2 ON t1.a=t2.a Care should also be taken to use the correct set of column objects passed to :meth:`_expression.Select.with_only_columns`. Since the method is essentially equivalent to calling the :func:`_expression.select` construct in the first place with the given columns, the columns passed to :meth:`_expression.Select.with_only_columns` should usually be a subset of those which were passed to the :func:`_expression.select` construct, not those which are available from the ``.c`` collection of that :func:`_expression.select`. That is:: s = select([table1.c.a, table1.c.b]).select_from(table1) s = s.with_only_columns([table1.c.b]) and **not**:: # usually incorrect s = s.with_only_columns([s.c.b]) The latter would produce the SQL:: SELECT b FROM (SELECT t1.a AS a, t1.b AS b FROM t1), t1 Since the :func:`_expression.select` construct is essentially being asked to select both from ``table1`` as well as itself. """ self._reset_exported() rc = [] for c in columns: c = _interpret_as_column_or_from(c) if isinstance(c, ScalarSelect): c = c.self_group(against=operators.comma_op) rc.append(c) self._raw_columns = rc @_generative def where(self, whereclause): """Return a new :func:`_expression.select` construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. """ self.append_whereclause(whereclause) @_generative def having(self, having): """Return a new :func:`_expression.select` construct with the given expression added to its HAVING clause, joined to the existing clause via AND, if any. """ self.append_having(having) @_generative def distinct(self, *expr): r"""Return a new :func:`_expression.select` construct which will apply DISTINCT to its columns clause. :param \*expr: optional column expressions. When present, the PostgreSQL dialect will render a ``DISTINCT ON (>)`` construct. """ if expr: expr = [_literal_as_label_reference(e) for e in expr] if isinstance(self._distinct, list): self._distinct = self._distinct + expr else: self._distinct = expr else: self._distinct = True @_generative def select_from(self, fromclause): r"""Return a new :func:`_expression.select` construct with the given FROM expression(s) merged into its list of FROM objects. E.g.:: table1 = table('t1', column('a')) table2 = table('t2', column('b')) s = select([table1.c.a]).\ select_from( table1.join(table2, table1.c.a==table2.c.b) ) The "from" list is a unique set on the identity of each element, so adding an already present :class:`_schema.Table` or other selectable will have no effect. Passing a :class:`_expression.Join` that refers to an already present :class:`_schema.Table` or other selectable will have the effect of concealing the presence of that selectable as an individual element in the rendered FROM list, instead rendering it into a JOIN clause. While the typical purpose of :meth:`_expression.Select.select_from` is to replace the default, derived FROM clause with a join, it can also be called with individual table elements, multiple times if desired, in the case that the FROM clause cannot be fully derived from the columns clause:: select([func.count('*')]).select_from(table1) """ self.append_from(fromclause) @_generative def correlate(self, *fromclauses): r"""Return a new :class:`_expression.Select` which will correlate the given FROM clauses to that of an enclosing :class:`_expression.Select`. Calling this method turns off the :class:`_expression.Select` object's default behavior of "auto-correlation". Normally, FROM elements which appear in a :class:`_expression.Select` that encloses this one via its :term:`WHERE clause`, ORDER BY, HAVING or :term:`columns clause` will be omitted from this :class:`_expression.Select` object's :term:`FROM clause`. Setting an explicit correlation collection using the :meth:`_expression.Select.correlate` method provides a fixed list of FROM objects that can potentially take place in this process. When :meth:`_expression.Select.correlate` is used to apply specific FROM clauses for correlation, the FROM elements become candidates for correlation regardless of how deeply nested this :class:`_expression.Select` object is, relative to an enclosing :class:`_expression.Select` which refers to the same FROM object. This is in contrast to the behavior of "auto-correlation" which only correlates to an immediate enclosing :class:`_expression.Select`. Multi-level correlation ensures that the link between enclosed and enclosing :class:`_expression.Select` is always via at least one WHERE/ORDER BY/HAVING/columns clause in order for correlation to take place. If ``None`` is passed, the :class:`_expression.Select` object will correlate none of its FROM entries, and all will render unconditionally in the local FROM clause. :param \*fromclauses: a list of one or more :class:`_expression.FromClause` constructs, or other compatible constructs (i.e. ORM-mapped classes) to become part of the correlate collection. .. seealso:: :meth:`_expression.Select.correlate_except` :ref:`correlated_subqueries` """ self._auto_correlate = False if fromclauses and fromclauses[0] is None: self._correlate = () else: self._correlate = set(self._correlate).union( _interpret_as_from(f) for f in fromclauses ) @_generative def correlate_except(self, *fromclauses): r"""Return a new :class:`_expression.Select` which will omit the given FROM clauses from the auto-correlation process. Calling :meth:`_expression.Select.correlate_except` turns off the :class:`_expression.Select` object's default behavior of "auto-correlation" for the given FROM elements. An element specified here will unconditionally appear in the FROM list, while all other FROM elements remain subject to normal auto-correlation behaviors. If ``None`` is passed, the :class:`_expression.Select` object will correlate all of its FROM entries. :param \*fromclauses: a list of one or more :class:`_expression.FromClause` constructs, or other compatible constructs (i.e. ORM-mapped classes) to become part of the correlate-exception collection. .. seealso:: :meth:`_expression.Select.correlate` :ref:`correlated_subqueries` """ self._auto_correlate = False if fromclauses and fromclauses[0] is None: self._correlate_except = () else: self._correlate_except = set(self._correlate_except or ()).union( _interpret_as_from(f) for f in fromclauses ) def append_correlation(self, fromclause): """Append the given correlation expression to this :func:`_expression.select` construct. This is an **in-place** mutation method; the :meth:`_expression.Select.correlate` method is preferred, as it provides standard :term:`method chaining`. """ self._auto_correlate = False self._correlate = set(self._correlate).union( _interpret_as_from(f) for f in fromclause ) def append_column(self, column): """Append the given column expression to the columns clause of this :func:`_expression.select` construct. E.g.:: my_select.append_column(some_table.c.new_column) This is an **in-place** mutation method; the :meth:`_expression.Select.column` method is preferred, as it provides standard :term:`method chaining`. See the documentation for :meth:`_expression.Select.with_only_columns` for guidelines on adding /replacing the columns of a :class:`_expression.Select` object. """ self._reset_exported() column = _interpret_as_column_or_from(column) if isinstance(column, ScalarSelect): column = column.self_group(against=operators.comma_op) self._raw_columns = self._raw_columns + [column] def append_prefix(self, clause): """Append the given columns clause prefix expression to this :func:`_expression.select` construct. This is an **in-place** mutation method; the :meth:`_expression.Select.prefix_with` method is preferred, as it provides standard :term:`method chaining`. """ clause = _literal_as_text(clause) self._prefixes = self._prefixes + (clause,) def append_whereclause(self, whereclause): """Append the given expression to this :func:`_expression.select` construct's WHERE criterion. The expression will be joined to existing WHERE criterion via AND. This is an **in-place** mutation method; the :meth:`_expression.Select.where` method is preferred, as it provides standard :term:`method chaining`. """ self._reset_exported() self._whereclause = and_(True_._ifnone(self._whereclause), whereclause) def append_having(self, having): """Append the given expression to this :func:`_expression.select` construct's HAVING criterion. The expression will be joined to existing HAVING criterion via AND. This is an **in-place** mutation method; the :meth:`_expression.Select.having` method is preferred, as it provides standard :term:`method chaining`. """ self._reset_exported() self._having = and_(True_._ifnone(self._having), having) def append_from(self, fromclause): """Append the given FromClause expression to this :func:`_expression.select` construct's FROM clause. This is an **in-place** mutation method; the :meth:`_expression.Select.select_from` method is preferred, as it provides standard :term:`method chaining`. """ self._reset_exported() fromclause = _interpret_as_from(fromclause) self._from_obj = self._from_obj.union([fromclause]) @_memoized_property def _columns_plus_names(self): if self.use_labels: names = set() def name_for_col(c): if c._label is None or not c._render_label_in_columns_clause: return (None, c) name = c._label if name in names: name = c.anon_label else: names.add(name) return name, c return [ name_for_col(c) for c in util.unique_list(_select_iterables(self._raw_columns)) ] else: return [ (None, c) for c in util.unique_list(_select_iterables(self._raw_columns)) ] def _populate_column_collection(self): for name, c in self._columns_plus_names: if not hasattr(c, "_make_proxy"): continue if name is None: key = None elif self.use_labels: key = c._key_label if key is not None and key in self.c: key = c.anon_label else: key = None c._make_proxy(self, key=key, name=name, name_is_truncatable=True) def _refresh_for_new_column(self, column): for fromclause in self._froms: col = fromclause._refresh_for_new_column(column) if col is not None: if col in self.inner_columns and self._cols_populated: our_label = col._key_label if self.use_labels else col.key if our_label not in self.c: return col._make_proxy( self, name=col._label if self.use_labels else None, key=col._key_label if self.use_labels else None, name_is_truncatable=True, ) return None return None def _needs_parens_for_grouping(self): return ( self._limit_clause is not None or self._offset_clause is not None or bool(self._order_by_clause.clauses) ) def self_group(self, against=None): """Return a 'grouping' construct as per the :class:`_expression.ClauseElement` specification. This produces an element that can be embedded in an expression. Note that this method is called automatically as needed when constructing expressions and should not require explicit use. """ if ( isinstance(against, CompoundSelect) and not self._needs_parens_for_grouping() ): return self return FromGrouping(self) def union(self, other, **kwargs): """Return a SQL ``UNION`` of this select() construct against the given selectable. """ return CompoundSelect._create_union(self, other, **kwargs) def union_all(self, other, **kwargs): """Return a SQL ``UNION ALL`` of this select() construct against the given selectable. """ return CompoundSelect._create_union_all(self, other, **kwargs) def except_(self, other, **kwargs): """Return a SQL ``EXCEPT`` of this select() construct against the given selectable. """ return CompoundSelect._create_except(self, other, **kwargs) def except_all(self, other, **kwargs): """Return a SQL ``EXCEPT ALL`` of this select() construct against the given selectable. """ return CompoundSelect._create_except_all(self, other, **kwargs) def intersect(self, other, **kwargs): """Return a SQL ``INTERSECT`` of this select() construct against the given selectable. """ return CompoundSelect._create_intersect(self, other, **kwargs) def intersect_all(self, other, **kwargs): """Return a SQL ``INTERSECT ALL`` of this select() construct against the given selectable. """ return CompoundSelect._create_intersect_all(self, other, **kwargs) def bind(self): if self._bind: return self._bind froms = self._froms if not froms: for c in self._raw_columns: e = c.bind if e: self._bind = e return e else: e = list(froms)[0].bind if e: self._bind = e return e return None def _set_bind(self, bind): self._bind = bind bind = property(bind, _set_bind) class ScalarSelect(Generative, Grouping): _from_objects = [] _is_from_container = True _is_implicitly_boolean = False def __init__(self, element): self.element = element self.type = element._scalar_type() @property def columns(self): raise exc.InvalidRequestError( "Scalar Select expression has no " "columns; use this object directly " "within a column-level expression." ) c = columns @_generative def where(self, crit): """Apply a WHERE clause to the SELECT statement referred to by this :class:`_expression.ScalarSelect`. """ self.element = self.element.where(crit) def self_group(self, **kwargs): return self class Exists(UnaryExpression): """Represent an ``EXISTS`` clause.""" __visit_name__ = UnaryExpression.__visit_name__ _from_objects = [] def __init__(self, *args, **kwargs): """Construct a new :class:`_expression.Exists` against an existing :class:`_expression.Select` object. Calling styles are of the following forms:: # use on an existing select() s = select([table.c.col1]).where(table.c.col2==5) s_e = exists(s) # an exists is usually used in a where of another select # to produce a WHERE EXISTS (SELECT ... ) select([table.c.col1]).where(s_e) # but can also be used in a select to produce a # SELECT EXISTS (SELECT ... ) query select([s_e]) # construct a select() at once exists(['*'], **select_arguments).where(criterion) # columns argument is optional, generates "EXISTS (SELECT *)" # by default. exists().where(table.c.col2==5) """ if args and isinstance(args[0], (SelectBase, ScalarSelect)): s = args[0] else: if not args: args = ([literal_column("*")],) s = Select(*args, **kwargs).as_scalar().self_group() UnaryExpression.__init__( self, s, operator=operators.exists, type_=type_api.BOOLEANTYPE, wraps_column_expression=True, ) def select(self, whereclause=None, **params): return Select([self], whereclause, **params) def correlate(self, *fromclause): e = self._clone() e.element = self.element.correlate(*fromclause).self_group() return e def correlate_except(self, *fromclause): e = self._clone() e.element = self.element.correlate_except(*fromclause).self_group() return e def select_from(self, clause): """Return a new :class:`_expression.Exists` construct, applying the given expression to the :meth:`_expression.Select.select_from` method of the select statement contained. """ e = self._clone() e.element = self.element.select_from(clause).self_group() return e def where(self, clause): """Return a new :func:`_expression.exists` construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. """ e = self._clone() e.element = self.element.where(clause).self_group() return e class TextAsFrom(SelectBase): """Wrap a :class:`_expression.TextClause` construct within a :class:`_expression.SelectBase` interface. This allows the :class:`_expression.TextClause` object to gain a ``.c`` collection and other FROM-like capabilities such as :meth:`_expression.FromClause.alias`, :meth:`_expression.SelectBase.cte`, etc. The :class:`.TextAsFrom` construct is produced via the :meth:`_expression.TextClause.columns` method - see that method for details. .. versionadded:: 0.9.0 .. seealso:: :func:`_expression.text` :meth:`_expression.TextClause.columns` """ __visit_name__ = "text_as_from" _textual = True def __init__(self, text, columns, positional=False): self.element = text self.column_args = columns self.positional = positional @property def _bind(self): return self.element._bind @_generative def bindparams(self, *binds, **bind_as_values): self.element = self.element.bindparams(*binds, **bind_as_values) def _populate_column_collection(self): for c in self.column_args: c._make_proxy(self) def _copy_internals(self, clone=_clone, **kw): self._reset_exported() self.element = clone(self.element, **kw) def _scalar_type(self): return self.column_args[0].type class AnnotatedFromClause(Annotated): def __init__(self, element, values): # force FromClause to generate their internal # collections into __dict__ element.c Annotated.__init__(self, element, values) PK!ỶXXdml.pynu[# sql/dml.py # Copyright (C) 2009-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """ Provide :class:`_expression.Insert`, :class:`_expression.Update` and :class:`_expression.Delete`. """ from . import util as sql_util from .base import _from_objects from .base import _generative from .base import DialectKWArgs from .base import Executable from .elements import _clone from .elements import _column_as_key from .elements import _literal_as_text from .elements import and_ from .elements import ClauseElement from .elements import Null from .selectable import _interpret_as_from from .selectable import _interpret_as_select from .selectable import HasCTE from .selectable import HasPrefixes from .. import exc from .. import util class UpdateBase( HasCTE, DialectKWArgs, HasPrefixes, Executable, ClauseElement ): """Form the base for ``INSERT``, ``UPDATE``, and ``DELETE`` statements.""" __visit_name__ = "update_base" _execution_options = Executable._execution_options.union( {"autocommit": True} ) _hints = util.immutabledict() _parameter_ordering = None _prefixes = () named_with_column = False _return_defaults = None def _process_colparams(self, parameters): def process_single(p): if isinstance(p, (list, tuple)): return dict((c.key, pval) for c, pval in zip(self.table.c, p)) else: return p if self._preserve_parameter_order and parameters is not None: if not isinstance(parameters, list) or ( parameters and not isinstance(parameters[0], tuple) ): raise ValueError( "When preserve_parameter_order is True, " "values() only accepts a list of 2-tuples" ) self._parameter_ordering = [key for key, value in parameters] return dict(parameters), False if ( isinstance(parameters, (list, tuple)) and parameters and isinstance(parameters[0], (list, tuple, dict)) ): if not self._supports_multi_parameters: raise exc.InvalidRequestError( "This construct does not support " "multiple parameter sets." ) return [process_single(p) for p in parameters], True else: return process_single(parameters), False def params(self, *arg, **kw): """Set the parameters for the statement. This method raises ``NotImplementedError`` on the base class, and is overridden by :class:`.ValuesBase` to provide the SET/VALUES clause of UPDATE and INSERT. """ raise NotImplementedError( "params() is not supported for INSERT/UPDATE/DELETE statements." " To set the values for an INSERT or UPDATE statement, use" " stmt.values(**parameters)." ) def bind(self): """Return a 'bind' linked to this :class:`.UpdateBase` or a :class:`_schema.Table` associated with it. """ return self._bind or self.table.bind def _set_bind(self, bind): self._bind = bind bind = property(bind, _set_bind) @_generative def returning(self, *cols): r"""Add a :term:`RETURNING` or equivalent clause to this statement. e.g.:: stmt = table.update().\ where(table.c.data == 'value').\ values(status='X').\ returning(table.c.server_flag, table.c.updated_timestamp) for server_flag, updated_timestamp in connection.execute(stmt): print(server_flag, updated_timestamp) The given collection of column expressions should be derived from the table that is the target of the INSERT, UPDATE, or DELETE. While :class:`_schema.Column` objects are typical, the elements can also be expressions:: stmt = table.insert().returning( (table.c.first_name + " " + table.c.last_name). label('fullname')) Upon compilation, a RETURNING clause, or database equivalent, will be rendered within the statement. For INSERT and UPDATE, the values are the newly inserted/updated values. For DELETE, the values are those of the rows which were deleted. Upon execution, the values of the columns to be returned are made available via the result set and can be iterated using :meth:`_engine.ResultProxy.fetchone` and similar. For DBAPIs which do not natively support returning values (i.e. cx_oracle), SQLAlchemy will approximate this behavior at the result level so that a reasonable amount of behavioral neutrality is provided. Note that not all databases/DBAPIs support RETURNING. For those backends with no support, an exception is raised upon compilation and/or execution. For those who do support it, the functionality across backends varies greatly, including restrictions on executemany() and other statements which return multiple rows. Please read the documentation notes for the database in use in order to determine the availability of RETURNING. .. seealso:: :meth:`.ValuesBase.return_defaults` - an alternative method tailored towards efficient fetching of server-side defaults and triggers for single-row INSERTs or UPDATEs. """ if self._return_defaults: raise exc.InvalidRequestError( "return_defaults() is already configured on this statement" ) if self._returning: util.warn( "The returning() method does not currently support multiple " "additive calls. The existing RETURNING clause being " "replaced by new columns." ) self._returning = cols @_generative def with_hint(self, text, selectable=None, dialect_name="*"): """Add a table hint for a single table to this INSERT/UPDATE/DELETE statement. .. note:: :meth:`.UpdateBase.with_hint` currently applies only to Microsoft SQL Server. For MySQL INSERT/UPDATE/DELETE hints, use :meth:`.UpdateBase.prefix_with`. The text of the hint is rendered in the appropriate location for the database backend in use, relative to the :class:`_schema.Table` that is the subject of this statement, or optionally to that of the given :class:`_schema.Table` passed as the ``selectable`` argument. The ``dialect_name`` option will limit the rendering of a particular hint to a particular backend. Such as, to add a hint that only takes effect for SQL Server:: mytable.insert().with_hint("WITH (PAGLOCK)", dialect_name="mssql") :param text: Text of the hint. :param selectable: optional :class:`_schema.Table` that specifies an element of the FROM clause within an UPDATE or DELETE to be the subject of the hint - applies only to certain backends. :param dialect_name: defaults to ``*``, if specified as the name of a particular dialect, will apply these hints only when that dialect is in use. """ if selectable is None: selectable = self.table self._hints = self._hints.union({(selectable, dialect_name): text}) class ValuesBase(UpdateBase): """Supplies support for :meth:`.ValuesBase.values` to INSERT and UPDATE constructs.""" __visit_name__ = "values_base" _supports_multi_parameters = False _has_multi_parameters = False _preserve_parameter_order = False select = None _post_values_clause = None def __init__(self, table, values, prefixes): self.table = _interpret_as_from(table) self.parameters, self._has_multi_parameters = self._process_colparams( values ) if prefixes: self._setup_prefixes(prefixes) @_generative def values(self, *args, **kwargs): r"""Specify a fixed VALUES clause for an INSERT statement, or the SET clause for an UPDATE. Note that the :class:`_expression.Insert` and :class:`_expression.Update` constructs support per-execution time formatting of the VALUES and/or SET clauses, based on the arguments passed to :meth:`_engine.Connection.execute`. However, the :meth:`.ValuesBase.values` method can be used to "fix" a particular set of parameters into the statement. Multiple calls to :meth:`.ValuesBase.values` will produce a new construct, each one with the parameter list modified to include the new parameters sent. In the typical case of a single dictionary of parameters, the newly passed keys will replace the same keys in the previous construct. In the case of a list-based "multiple values" construct, each new list of values is extended onto the existing list of values. :param \**kwargs: key value pairs representing the string key of a :class:`_schema.Column` mapped to the value to be rendered into the VALUES or SET clause:: users.insert().values(name="some name") users.update().where(users.c.id==5).values(name="some name") :param \*args: As an alternative to passing key/value parameters, a dictionary, tuple, or list of dictionaries or tuples can be passed as a single positional argument in order to form the VALUES or SET clause of the statement. The forms that are accepted vary based on whether this is an :class:`_expression.Insert` or an :class:`_expression.Update` construct. For either an :class:`_expression.Insert` or :class:`_expression.Update` construct, a single dictionary can be passed, which works the same as that of the kwargs form:: users.insert().values({"name": "some name"}) users.update().values({"name": "some new name"}) Also for either form but more typically for the :class:`_expression.Insert` construct, a tuple that contains an entry for every column in the table is also accepted:: users.insert().values((5, "some name")) The :class:`_expression.Insert` construct also supports being passed a list of dictionaries or full-table-tuples, which on the server will render the less common SQL syntax of "multiple values" - this syntax is supported on backends such as SQLite, PostgreSQL, MySQL, but not necessarily others:: users.insert().values([ {"name": "some name"}, {"name": "some other name"}, {"name": "yet another name"}, ]) The above form would render a multiple VALUES statement similar to:: INSERT INTO users (name) VALUES (:name_1), (:name_2), (:name_3) It is essential to note that **passing multiple values is NOT the same as using traditional executemany() form**. The above syntax is a **special** syntax not typically used. To emit an INSERT statement against multiple rows, the normal method is to pass a multiple values list to the :meth:`_engine.Connection.execute` method, which is supported by all database backends and is generally more efficient for a very large number of parameters. .. seealso:: :ref:`execute_multiple` - an introduction to the traditional Core method of multiple parameter set invocation for INSERTs and other statements. .. versionchanged:: 1.0.0 an INSERT that uses a multiple-VALUES clause, even a list of length one, implies that the :paramref:`_expression.Insert.inline` flag is set to True, indicating that the statement will not attempt to fetch the "last inserted primary key" or other defaults. The statement deals with an arbitrary number of rows, so the :attr:`_engine.ResultProxy.inserted_primary_key` accessor does not apply. .. versionchanged:: 1.0.0 A multiple-VALUES INSERT now supports columns with Python side default values and callables in the same way as that of an "executemany" style of invocation; the callable is invoked for each row. See :ref:`bug_3288` for other details. The :class:`_expression.Update` construct supports a special form which is a list of 2-tuples, which when provided must be passed in conjunction with the :paramref:`_expression.update.preserve_parameter_order` parameter. This form causes the UPDATE statement to render the SET clauses using the order of parameters given to :meth:`_expression.Update.values`, rather than the ordering of columns given in the :class:`_schema.Table`. .. versionadded:: 1.0.10 - added support for parameter-ordered UPDATE statements via the :paramref:`_expression.update.preserve_parameter_order` flag. .. seealso:: :ref:`updates_order_parameters` - full example of the :paramref:`_expression.update.preserve_parameter_order` flag .. seealso:: :ref:`inserts_and_updates` - SQL Expression Language Tutorial :func:`_expression.insert` - produce an ``INSERT`` statement :func:`_expression.update` - produce an ``UPDATE`` statement """ if self.select is not None: raise exc.InvalidRequestError( "This construct already inserts from a SELECT" ) if self._has_multi_parameters and kwargs: raise exc.InvalidRequestError( "This construct already has multiple parameter sets." ) if args: if len(args) > 1: raise exc.ArgumentError( "Only a single dictionary/tuple or list of " "dictionaries/tuples is accepted positionally." ) v = args[0] else: v = {} if self.parameters is None: ( self.parameters, self._has_multi_parameters, ) = self._process_colparams(v) else: if self._has_multi_parameters: self.parameters = list(self.parameters) p, self._has_multi_parameters = self._process_colparams(v) if not self._has_multi_parameters: raise exc.ArgumentError( "Can't mix single-values and multiple values " "formats in one statement" ) self.parameters.extend(p) else: self.parameters = self.parameters.copy() p, self._has_multi_parameters = self._process_colparams(v) if self._has_multi_parameters: raise exc.ArgumentError( "Can't mix single-values and multiple values " "formats in one statement" ) self.parameters.update(p) if kwargs: if self._has_multi_parameters: raise exc.ArgumentError( "Can't pass kwargs and multiple parameter sets " "simultaneously" ) else: self.parameters.update(kwargs) @_generative def return_defaults(self, *cols): """Make use of a :term:`RETURNING` clause for the purpose of fetching server-side expressions and defaults. E.g.:: stmt = table.insert().values(data='newdata').return_defaults() result = connection.execute(stmt) server_created_at = result.returned_defaults['created_at'] When used against a backend that supports RETURNING, all column values generated by SQL expression or server-side-default will be added to any existing RETURNING clause, provided that :meth:`.UpdateBase.returning` is not used simultaneously. The column values will then be available on the result using the :attr:`_engine.ResultProxy.returned_defaults` accessor as a dictionary, referring to values keyed to the :class:`_schema.Column` object as well as its ``.key``. This method differs from :meth:`.UpdateBase.returning` in these ways: 1. :meth:`.ValuesBase.return_defaults` is only intended for use with an INSERT or an UPDATE statement that matches exactly one row. While the RETURNING construct in the general sense supports multiple rows for a multi-row UPDATE or DELETE statement, or for special cases of INSERT that return multiple rows (e.g. INSERT from SELECT, multi-valued VALUES clause), :meth:`.ValuesBase.return_defaults` is intended only for an "ORM-style" single-row INSERT/UPDATE statement. The row returned by the statement is also consumed implicitly when :meth:`.ValuesBase.return_defaults` is used. By contrast, :meth:`.UpdateBase.returning` leaves the RETURNING result-set intact with a collection of any number of rows. 2. It is compatible with the existing logic to fetch auto-generated primary key values, also known as "implicit returning". Backends that support RETURNING will automatically make use of RETURNING in order to fetch the value of newly generated primary keys; while the :meth:`.UpdateBase.returning` method circumvents this behavior, :meth:`.ValuesBase.return_defaults` leaves it intact. 3. It can be called against any backend. Backends that don't support RETURNING will skip the usage of the feature, rather than raising an exception. The return value of :attr:`_engine.ResultProxy.returned_defaults` will be ``None`` :meth:`.ValuesBase.return_defaults` is used by the ORM to provide an efficient implementation for the ``eager_defaults`` feature of :func:`.mapper`. :param cols: optional list of column key names or :class:`_schema.Column` objects. If omitted, all column expressions evaluated on the server are added to the returning list. .. versionadded:: 0.9.0 .. seealso:: :meth:`.UpdateBase.returning` :attr:`_engine.ResultProxy.returned_defaults` """ if self._returning: raise exc.InvalidRequestError( "RETURNING is already configured on this statement" ) self._return_defaults = cols or True class Insert(ValuesBase): """Represent an INSERT construct. The :class:`_expression.Insert` object is created using the :func:`_expression.insert()` function. .. seealso:: :ref:`coretutorial_insert_expressions` """ __visit_name__ = "insert" _supports_multi_parameters = True def __init__( self, table, values=None, inline=False, bind=None, prefixes=None, returning=None, return_defaults=False, **dialect_kw ): """Construct an :class:`_expression.Insert` object. Similar functionality is available via the :meth:`_expression.TableClause.insert` method on :class:`_schema.Table`. :param table: :class:`_expression.TableClause` which is the subject of the insert. :param values: collection of values to be inserted; see :meth:`_expression.Insert.values` for a description of allowed formats here. Can be omitted entirely; a :class:`_expression.Insert` construct will also dynamically render the VALUES clause at execution time based on the parameters passed to :meth:`_engine.Connection.execute`. :param inline: if True, no attempt will be made to retrieve the SQL-generated default values to be provided within the statement; in particular, this allows SQL expressions to be rendered 'inline' within the statement without the need to pre-execute them beforehand; for backends that support "returning", this turns off the "implicit returning" feature for the statement. If both `values` and compile-time bind parameters are present, the compile-time bind parameters override the information specified within `values` on a per-key basis. The keys within `values` can be either :class:`~sqlalchemy.schema.Column` objects or their string identifiers. Each key may reference one of: * a literal data value (i.e. string, number, etc.); * a Column object; * a SELECT statement. If a ``SELECT`` statement is specified which references this ``INSERT`` statement's table, the statement will be correlated against the ``INSERT`` statement. .. seealso:: :ref:`coretutorial_insert_expressions` - SQL Expression Tutorial :ref:`inserts_and_updates` - SQL Expression Tutorial """ ValuesBase.__init__(self, table, values, prefixes) self._bind = bind self.select = self.select_names = None self.include_insert_from_select_defaults = False self.inline = inline self._returning = returning self._validate_dialect_kwargs(dialect_kw) self._return_defaults = return_defaults def get_children(self, **kwargs): if self.select is not None: return (self.select,) else: return () @_generative def from_select(self, names, select, include_defaults=True): """Return a new :class:`_expression.Insert` construct which represents an ``INSERT...FROM SELECT`` statement. e.g.:: sel = select([table1.c.a, table1.c.b]).where(table1.c.c > 5) ins = table2.insert().from_select(['a', 'b'], sel) :param names: a sequence of string column names or :class:`_schema.Column` objects representing the target columns. :param select: a :func:`_expression.select` construct, :class:`_expression.FromClause` or other construct which resolves into a :class:`_expression.FromClause`, such as an ORM :class:`_query.Query` object, etc. The order of columns returned from this FROM clause should correspond to the order of columns sent as the ``names`` parameter; while this is not checked before passing along to the database, the database would normally raise an exception if these column lists don't correspond. :param include_defaults: if True, non-server default values and SQL expressions as specified on :class:`_schema.Column` objects (as documented in :ref:`metadata_defaults_toplevel`) not otherwise specified in the list of names will be rendered into the INSERT and SELECT statements, so that these values are also included in the data to be inserted. .. note:: A Python-side default that uses a Python callable function will only be invoked **once** for the whole statement, and **not per row**. .. versionadded:: 1.0.0 - :meth:`_expression.Insert.from_select` now renders Python-side and SQL expression column defaults into the SELECT statement for columns otherwise not included in the list of column names. .. versionchanged:: 1.0.0 an INSERT that uses FROM SELECT implies that the :paramref:`_expression.insert.inline` flag is set to True, indicating that the statement will not attempt to fetch the "last inserted primary key" or other defaults. The statement deals with an arbitrary number of rows, so the :attr:`_engine.ResultProxy.inserted_primary_key` accessor does not apply. """ if self.parameters: raise exc.InvalidRequestError( "This construct already inserts value expressions" ) self.parameters, self._has_multi_parameters = self._process_colparams( {_column_as_key(n): Null() for n in names} ) self.select_names = names self.inline = True self.include_insert_from_select_defaults = include_defaults self.select = _interpret_as_select(select) def _copy_internals(self, clone=_clone, **kw): # TODO: coverage self.parameters = self.parameters.copy() if self.select is not None: self.select = _clone(self.select) class Update(ValuesBase): """Represent an Update construct. The :class:`_expression.Update` object is created using the :func:`update()` function. """ __visit_name__ = "update" def __init__( self, table, whereclause=None, values=None, inline=False, bind=None, prefixes=None, returning=None, return_defaults=False, preserve_parameter_order=False, **dialect_kw ): r"""Construct an :class:`_expression.Update` object. E.g.:: from sqlalchemy import update stmt = update(users).where(users.c.id==5).\ values(name='user #5') Similar functionality is available via the :meth:`_expression.TableClause.update` method on :class:`_schema.Table`:: stmt = users.update().\ where(users.c.id==5).\ values(name='user #5') :param table: A :class:`_schema.Table` object representing the database table to be updated. :param whereclause: Optional SQL expression describing the ``WHERE`` condition of the ``UPDATE`` statement; is equivalent to using the more modern :meth:`~Update.where()` method to specify the ``WHERE`` clause. :param values: Optional dictionary which specifies the ``SET`` conditions of the ``UPDATE``. If left as ``None``, the ``SET`` conditions are determined from those parameters passed to the statement during the execution and/or compilation of the statement. When compiled standalone without any parameters, the ``SET`` clause generates for all columns. Modern applications may prefer to use the generative :meth:`_expression.Update.values` method to set the values of the UPDATE statement. :param inline: if True, SQL defaults present on :class:`_schema.Column` objects via the ``default`` keyword will be compiled 'inline' into the statement and not pre-executed. This means that their values will not be available in the dictionary returned from :meth:`_engine.ResultProxy.last_updated_params`. :param preserve_parameter_order: if True, the update statement is expected to receive parameters **only** via the :meth:`_expression.Update.values` method, and they must be passed as a Python ``list`` of 2-tuples. The rendered UPDATE statement will emit the SET clause for each referenced column maintaining this order. .. versionadded:: 1.0.10 .. seealso:: :ref:`updates_order_parameters` - full example of the :paramref:`_expression.update.preserve_parameter_order` flag If both ``values`` and compile-time bind parameters are present, the compile-time bind parameters override the information specified within ``values`` on a per-key basis. The keys within ``values`` can be either :class:`_schema.Column` objects or their string identifiers (specifically the "key" of the :class:`_schema.Column`, normally but not necessarily equivalent to its "name"). Normally, the :class:`_schema.Column` objects used here are expected to be part of the target :class:`_schema.Table` that is the table to be updated. However when using MySQL, a multiple-table UPDATE statement can refer to columns from any of the tables referred to in the WHERE clause. The values referred to in ``values`` are typically: * a literal data value (i.e. string, number, etc.) * a SQL expression, such as a related :class:`_schema.Column`, a scalar-returning :func:`_expression.select` construct, etc. When combining :func:`_expression.select` constructs within the values clause of an :func:`_expression.update` construct, the subquery represented by the :func:`_expression.select` should be *correlated* to the parent table, that is, providing criterion which links the table inside the subquery to the outer table being updated:: users.update().values( name=select([addresses.c.email_address]).\ where(addresses.c.user_id==users.c.id).\ as_scalar() ) .. seealso:: :ref:`inserts_and_updates` - SQL Expression Language Tutorial """ self._preserve_parameter_order = preserve_parameter_order ValuesBase.__init__(self, table, values, prefixes) self._bind = bind self._returning = returning if whereclause is not None: self._whereclause = _literal_as_text(whereclause) else: self._whereclause = None self.inline = inline self._validate_dialect_kwargs(dialect_kw) self._return_defaults = return_defaults def get_children(self, **kwargs): if self._whereclause is not None: return (self._whereclause,) else: return () def _copy_internals(self, clone=_clone, **kw): # TODO: coverage self._whereclause = clone(self._whereclause, **kw) self.parameters = self.parameters.copy() @_generative def where(self, whereclause): """Return a new update() construct with the given expression added to its WHERE clause, joined to the existing clause via AND, if any. Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where` support multiple-table forms, including database-specific ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that don't have multiple-table support, a backend agnostic approach to using multiple tables is to make use of correlated subqueries. See the linked tutorial sections below for examples. .. seealso:: :ref:`tutorial_1x_correlated_updates` :ref:`multi_table_updates` :ref:`multi_table_deletes` """ if self._whereclause is not None: self._whereclause = and_( self._whereclause, _literal_as_text(whereclause) ) else: self._whereclause = _literal_as_text(whereclause) @property def _extra_froms(self): froms = [] all_tables = list(sql_util.tables_from_leftmost(self.table)) seen = {all_tables[0]} if self._whereclause is not None: for item in _from_objects(self._whereclause): if not seen.intersection(item._cloned_set): froms.append(item) seen.update(item._cloned_set) froms.extend(all_tables[1:]) return froms class Delete(UpdateBase): """Represent a DELETE construct. The :class:`_expression.Delete` object is created using the :func:`delete()` function. """ __visit_name__ = "delete" def __init__( self, table, whereclause=None, bind=None, returning=None, prefixes=None, **dialect_kw ): r"""Construct :class:`_expression.Delete` object. Similar functionality is available via the :meth:`_expression.TableClause.delete` method on :class:`_schema.Table`. :param table: The table to delete rows from. :param whereclause: Optional SQL expression describing the ``WHERE`` condition of the ``DELETE`` statement; is equivalent to using the more modern :meth:`~Delete.where()` method to specify the ``WHERE`` clause. .. seealso:: :ref:`deletes` - SQL Expression Tutorial """ self._bind = bind self.table = _interpret_as_from(table) self._returning = returning if prefixes: self._setup_prefixes(prefixes) if whereclause is not None: self._whereclause = _literal_as_text(whereclause) else: self._whereclause = None self._validate_dialect_kwargs(dialect_kw) def get_children(self, **kwargs): if self._whereclause is not None: return (self._whereclause,) else: return () @_generative def where(self, whereclause): """Add the given WHERE clause to a newly returned delete construct. Both :meth:`_dml.Update.where` and :meth:`_dml.Delete.where` support multiple-table forms, including database-specific ``UPDATE...FROM`` as well as ``DELETE..USING``. For backends that don't have multiple-table support, a backend agnostic approach to using multiple tables is to make use of correlated subqueries. See the linked tutorial sections below for examples. .. seealso:: :ref:`tutorial_1x_correlated_updates` :ref:`multi_table_updates` :ref:`multi_table_deletes` """ if self._whereclause is not None: self._whereclause = and_( self._whereclause, _literal_as_text(whereclause) ) else: self._whereclause = _literal_as_text(whereclause) @property def _extra_froms(self): froms = [] seen = {self.table} if self._whereclause is not None: for item in _from_objects(self._whereclause): if not seen.intersection(item._cloned_set): froms.append(item) seen.update(item._cloned_set) return froms def _copy_internals(self, clone=_clone, **kw): # TODO: coverage self._whereclause = clone(self._whereclause, **kw) PK!@e functions.pynu[# sql/functions.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """SQL function API, factories, and built-in functions. """ from . import annotation from . import operators from . import schema from . import sqltypes from . import util as sqlutil from .base import ColumnCollection from .base import Executable from .elements import _clone from .elements import _literal_as_binds from .elements import _type_from_args from .elements import BinaryExpression from .elements import BindParameter from .elements import Cast from .elements import ClauseList from .elements import ColumnElement from .elements import Extract from .elements import FunctionFilter from .elements import Grouping from .elements import literal_column from .elements import Over from .elements import WithinGroup from .selectable import Alias from .selectable import FromClause from .selectable import Select from .visitors import VisitableType from .. import util _registry = util.defaultdict(dict) _case_sensitive_registry = util.defaultdict(lambda: util.defaultdict(dict)) _CASE_SENSITIVE = util.symbol( name="case_sensitive_function", doc="Symbol to mark the functions that are switched into case-sensitive " "mode.", ) def register_function(identifier, fn, package="_default"): """Associate a callable with a particular func. name. This is normally called by _GenericMeta, but is also available by itself so that a non-Function construct can be associated with the :data:`.func` accessor (i.e. CAST, EXTRACT). """ reg = _registry[package] case_sensitive_reg = _case_sensitive_registry[package] raw_identifier = identifier identifier = util.text_type(identifier).lower() # Check if a function with the same lowercase identifier is registered. if identifier in reg and reg[identifier] is not _CASE_SENSITIVE: if raw_identifier in case_sensitive_reg[identifier]: util.warn( "The GenericFunction '{}' is already registered and " "is going to be overridden.".format(identifier) ) reg[identifier] = fn else: # If a function with the same lowercase identifier is registered, # then these 2 functions are considered as case-sensitive. # Note: This case should raise an error in a later release. util.warn_deprecated( "GenericFunction '{}' is already registered with " "different letter case, so the previously registered function " "'{}' is switched into case-sensitive mode. " "GenericFunction objects will be fully case-insensitive in a " "future release.".format( raw_identifier, list(case_sensitive_reg[identifier].keys())[0], ) ) reg[identifier] = _CASE_SENSITIVE # Check if a function with different letter case identifier is registered. elif identifier in case_sensitive_reg: # Note: This case will be removed in a later release. if raw_identifier not in case_sensitive_reg[identifier]: util.warn_deprecated( "GenericFunction(s) '{}' are already registered with " "different letter cases and might interact with '{}'. " "GenericFunction objects will be fully case-insensitive in a " "future release.".format( sorted(case_sensitive_reg[identifier].keys()), raw_identifier, ) ) else: util.warn( "The GenericFunction '{}' is already registered and " "is going to be overriden.".format(raw_identifier) ) # Register by default else: reg[identifier] = fn # Always register in case-sensitive registry case_sensitive_reg[identifier][raw_identifier] = fn class FunctionElement(Executable, ColumnElement, FromClause): """Base for SQL function-oriented constructs. .. seealso:: :ref:`coretutorial_functions` - in the Core tutorial :class:`.Function` - named SQL function. :data:`.func` - namespace which produces registered or ad-hoc :class:`.Function` instances. :class:`.GenericFunction` - allows creation of registered function types. """ packagenames = () _has_args = False def __init__(self, *clauses, **kwargs): r"""Construct a :class:`.FunctionElement`. :param \*clauses: list of column expressions that form the arguments of the SQL function call. :param \**kwargs: additional kwargs are typically consumed by subclasses. .. seealso:: :data:`.func` :class:`.Function` """ args = [_literal_as_binds(c, self.name) for c in clauses] self._has_args = self._has_args or bool(args) self.clause_expr = ClauseList( operator=operators.comma_op, group_contents=True, *args ).self_group() def _execute_on_connection(self, connection, multiparams, params): return connection._execute_function(self, multiparams, params) @property def columns(self): r"""The set of columns exported by this :class:`.FunctionElement`. Function objects currently have no result column names built in; this method returns a single-element column collection with an anonymously named column. An interim approach to providing named columns for a function as a FROM clause is to build a :func:`_expression.select` with the desired columns:: from sqlalchemy.sql import column stmt = select([column('x'), column('y')]).\ select_from(func.myfunction()) """ return ColumnCollection(self.label(None)) @util.memoized_property def clauses(self): """Return the underlying :class:`.ClauseList` which contains the arguments for this :class:`.FunctionElement`. """ return self.clause_expr.element def over(self, partition_by=None, order_by=None, rows=None, range_=None): """Produce an OVER clause against this function. Used against aggregate or so-called "window" functions, for database backends that support window functions. The expression:: func.row_number().over(order_by='x') is shorthand for:: from sqlalchemy import over over(func.row_number(), order_by='x') See :func:`_expression.over` for a full description. """ return Over( self, partition_by=partition_by, order_by=order_by, rows=rows, range_=range_, ) def within_group(self, *order_by): """Produce a WITHIN GROUP (ORDER BY expr) clause against this function. Used against so-called "ordered set aggregate" and "hypothetical set aggregate" functions, including :class:`.percentile_cont`, :class:`.rank`, :class:`.dense_rank`, etc. See :func:`_expression.within_group` for a full description. .. versionadded:: 1.1 """ return WithinGroup(self, *order_by) def filter(self, *criterion): """Produce a FILTER clause against this function. Used against aggregate and window functions, for database backends that support the "FILTER" clause. The expression:: func.count(1).filter(True) is shorthand for:: from sqlalchemy import funcfilter funcfilter(func.count(1), True) .. versionadded:: 1.0.0 .. seealso:: :class:`.FunctionFilter` :func:`.funcfilter` """ if not criterion: return self return FunctionFilter(self, *criterion) def as_comparison(self, left_index, right_index): """Interpret this expression as a boolean comparison between two values. A hypothetical SQL function "is_equal()" which compares to values for equality would be written in the Core expression language as:: expr = func.is_equal("a", "b") If "is_equal()" above is comparing "a" and "b" for equality, the :meth:`.FunctionElement.as_comparison` method would be invoked as:: expr = func.is_equal("a", "b").as_comparison(1, 2) Where above, the integer value "1" refers to the first argument of the "is_equal()" function and the integer value "2" refers to the second. This would create a :class:`.BinaryExpression` that is equivalent to:: BinaryExpression("a", "b", operator=op.eq) However, at the SQL level it would still render as "is_equal('a', 'b')". The ORM, when it loads a related object or collection, needs to be able to manipulate the "left" and "right" sides of the ON clause of a JOIN expression. The purpose of this method is to provide a SQL function construct that can also supply this information to the ORM, when used with the :paramref:`_orm.relationship.primaryjoin` parameter. The return value is a containment object called :class:`.FunctionAsBinary`. An ORM example is as follows:: class Venue(Base): __tablename__ = 'venue' id = Column(Integer, primary_key=True) name = Column(String) descendants = relationship( "Venue", primaryjoin=func.instr( remote(foreign(name)), name + "/" ).as_comparison(1, 2) == 1, viewonly=True, order_by=name ) Above, the "Venue" class can load descendant "Venue" objects by determining if the name of the parent Venue is contained within the start of the hypothetical descendant value's name, e.g. "parent1" would match up to "parent1/child1", but not to "parent2/child1". Possible use cases include the "materialized path" example given above, as well as making use of special SQL functions such as geometric functions to create join conditions. :param left_index: the integer 1-based index of the function argument that serves as the "left" side of the expression. :param right_index: the integer 1-based index of the function argument that serves as the "right" side of the expression. .. versionadded:: 1.3 """ return FunctionAsBinary(self, left_index, right_index) @property def _from_objects(self): return self.clauses._from_objects def get_children(self, **kwargs): return (self.clause_expr,) def _copy_internals(self, clone=_clone, **kw): self.clause_expr = clone(self.clause_expr, **kw) self._reset_exported() FunctionElement.clauses._reset(self) def within_group_type(self, within_group): """For types that define their return type as based on the criteria within a WITHIN GROUP (ORDER BY) expression, called by the :class:`.WithinGroup` construct. Returns None by default, in which case the function's normal ``.type`` is used. """ return None def alias(self, name=None, flat=False): r"""Produce a :class:`_expression.Alias` construct against this :class:`.FunctionElement`. This construct wraps the function in a named alias which is suitable for the FROM clause, in the style accepted for example by PostgreSQL. e.g.:: from sqlalchemy.sql import column stmt = select([column('data_view')]).\ select_from(SomeTable).\ select_from(func.unnest(SomeTable.data).alias('data_view') ) Would produce: .. sourcecode:: sql SELECT data_view FROM sometable, unnest(sometable.data) AS data_view .. versionadded:: 0.9.8 The :meth:`.FunctionElement.alias` method is now supported. Previously, this method's behavior was undefined and did not behave consistently across versions. """ return Alias._construct(self, name) def select(self): """Produce a :func:`_expression.select` construct against this :class:`.FunctionElement`. This is shorthand for:: s = select([function_element]) """ s = Select([self]) if self._execution_options: s = s.execution_options(**self._execution_options) return s def scalar(self): """Execute this :class:`.FunctionElement` against an embedded 'bind' and return a scalar value. This first calls :meth:`~.FunctionElement.select` to produce a SELECT construct. Note that :class:`.FunctionElement` can be passed to the :meth:`.Connectable.scalar` method of :class:`_engine.Connection` or :class:`_engine.Engine`. """ return self.select().execute().scalar() def execute(self): """Execute this :class:`.FunctionElement` against an embedded 'bind'. This first calls :meth:`~.FunctionElement.select` to produce a SELECT construct. Note that :class:`.FunctionElement` can be passed to the :meth:`.Connectable.execute` method of :class:`_engine.Connection` or :class:`_engine.Engine`. """ return self.select().execute() def _bind_param(self, operator, obj, type_=None): return BindParameter( None, obj, _compared_to_operator=operator, _compared_to_type=self.type, unique=True, type_=type_, ) def self_group(self, against=None): # for the moment, we are parenthesizing all array-returning # expressions against getitem. This may need to be made # more portable if in the future we support other DBs # besides postgresql. if against is operators.getitem and isinstance( self.type, sqltypes.ARRAY ): return Grouping(self) else: return super(FunctionElement, self).self_group(against=against) class FunctionAsBinary(BinaryExpression): def __init__(self, fn, left_index, right_index): left = fn.clauses.clauses[left_index - 1] right = fn.clauses.clauses[right_index - 1] self.sql_function = fn self.left_index = left_index self.right_index = right_index super(FunctionAsBinary, self).__init__( left, right, operators.function_as_comparison_op, type_=sqltypes.BOOLEANTYPE, ) @property def left(self): return self.sql_function.clauses.clauses[self.left_index - 1] @left.setter def left(self, value): self.sql_function.clauses.clauses[self.left_index - 1] = value @property def right(self): return self.sql_function.clauses.clauses[self.right_index - 1] @right.setter def right(self, value): self.sql_function.clauses.clauses[self.right_index - 1] = value def _copy_internals(self, **kw): clone = kw.pop("clone") self.sql_function = clone(self.sql_function, **kw) super(FunctionAsBinary, self)._copy_internals(**kw) class _FunctionGenerator(object): """Generate SQL function expressions. :data:`.func` is a special object instance which generates SQL functions based on name-based attributes, e.g.:: >>> print(func.count(1)) count(:param_1) The returned object is an instance of :class:`.Function`, and is a column-oriented SQL element like any other, and is used in that way:: >>> print(select([func.count(table.c.id)])) SELECT count(sometable.id) FROM sometable Any name can be given to :data:`.func`. If the function name is unknown to SQLAlchemy, it will be rendered exactly as is. For common SQL functions which SQLAlchemy is aware of, the name may be interpreted as a *generic function* which will be compiled appropriately to the target database:: >>> print(func.current_timestamp()) CURRENT_TIMESTAMP To call functions which are present in dot-separated packages, specify them in the same manner:: >>> print(func.stats.yield_curve(5, 10)) stats.yield_curve(:yield_curve_1, :yield_curve_2) SQLAlchemy can be made aware of the return type of functions to enable type-specific lexical and result-based behavior. For example, to ensure that a string-based function returns a Unicode value and is similarly treated as a string in expressions, specify :class:`~sqlalchemy.types.Unicode` as the type: >>> print(func.my_string(u'hi', type_=Unicode) + ' ' + ... func.my_string(u'there', type_=Unicode)) my_string(:my_string_1) || :my_string_2 || my_string(:my_string_3) The object returned by a :data:`.func` call is usually an instance of :class:`.Function`. This object meets the "column" interface, including comparison and labeling functions. The object can also be passed the :meth:`~.Connectable.execute` method of a :class:`_engine.Connection` or :class:`_engine.Engine`, where it will be wrapped inside of a SELECT statement first:: print(connection.execute(func.current_timestamp()).scalar()) In a few exception cases, the :data:`.func` accessor will redirect a name to a built-in expression such as :func:`.cast` or :func:`.extract`, as these names have well-known meaning but are not exactly the same as "functions" from a SQLAlchemy perspective. Functions which are interpreted as "generic" functions know how to calculate their return type automatically. For a listing of known generic functions, see :ref:`generic_functions`. .. note:: The :data:`.func` construct has only limited support for calling standalone "stored procedures", especially those with special parameterization concerns. See the section :ref:`stored_procedures` for details on how to use the DBAPI-level ``callproc()`` method for fully traditional stored procedures. .. seealso:: :ref:`coretutorial_functions` - in the Core Tutorial :class:`.Function` """ def __init__(self, **opts): self.__names = [] self.opts = opts def __getattr__(self, name): # passthru __ attributes; fixes pydoc if name.startswith("__"): try: return self.__dict__[name] except KeyError: raise AttributeError(name) elif name.endswith("_"): name = name[0:-1] f = _FunctionGenerator(**self.opts) f.__names = list(self.__names) + [name] return f def __call__(self, *c, **kwargs): o = self.opts.copy() o.update(kwargs) tokens = len(self.__names) if tokens == 2: package, fname = self.__names elif tokens == 1: package, fname = "_default", self.__names[0] else: package = None if package is not None: func = _registry[package].get(fname.lower()) if func is _CASE_SENSITIVE: case_sensitive_reg = _case_sensitive_registry[package] func = case_sensitive_reg.get(fname.lower()).get(fname) if func is not None: return func(*c, **o) return Function( self.__names[-1], packagenames=self.__names[0:-1], *c, **o ) func = _FunctionGenerator() func.__doc__ = _FunctionGenerator.__doc__ modifier = _FunctionGenerator(group=False) class Function(FunctionElement): r"""Describe a named SQL function. The :class:`.Function` object is typically generated from the :data:`.func` generation object. :param \*clauses: list of column expressions that form the arguments of the SQL function call. :param type\_: optional :class:`.TypeEngine` datatype object that will be used as the return value of the column expression generated by this function call. :param packagenames: a string which indicates package prefix names to be prepended to the function name when the SQL is generated. The :data:`.func` generator creates these when it is called using dotted format, e.g.:: func.mypackage.some_function(col1, col2) .. seealso:: :ref:`coretutorial_functions` :data:`.func` - namespace which produces registered or ad-hoc :class:`.Function` instances. :class:`.GenericFunction` - allows creation of registered function types. """ __visit_name__ = "function" def __init__(self, name, *clauses, **kw): """Construct a :class:`.Function`. The :data:`.func` construct is normally used to construct new :class:`.Function` instances. """ self.packagenames = kw.pop("packagenames", None) or [] self.name = name self._bind = kw.get("bind", None) self.type = sqltypes.to_instance(kw.get("type_", None)) FunctionElement.__init__(self, *clauses, **kw) def _bind_param(self, operator, obj, type_=None): return BindParameter( self.name, obj, _compared_to_operator=operator, _compared_to_type=self.type, type_=type_, unique=True, ) class _GenericMeta(VisitableType): def __init__(cls, clsname, bases, clsdict): if annotation.Annotated not in cls.__mro__: cls.name = name = clsdict.get("name", clsname) cls.identifier = identifier = clsdict.get("identifier", name) package = clsdict.pop("package", "_default") # legacy if "__return_type__" in clsdict: cls.type = clsdict["__return_type__"] # Check _register attribute status cls._register = getattr(cls, "_register", True) # Register the function if required if cls._register: register_function(identifier, cls, package) else: # Set _register to True to register child classes by default cls._register = True super(_GenericMeta, cls).__init__(clsname, bases, clsdict) class GenericFunction(util.with_metaclass(_GenericMeta, Function)): """Define a 'generic' function. A generic function is a pre-established :class:`.Function` class that is instantiated automatically when called by name from the :data:`.func` attribute. Note that calling any name from :data:`.func` has the effect that a new :class:`.Function` instance is created automatically, given that name. The primary use case for defining a :class:`.GenericFunction` class is so that a function of a particular name may be given a fixed return type. It can also include custom argument parsing schemes as well as additional methods. Subclasses of :class:`.GenericFunction` are automatically registered under the name of the class. For example, a user-defined function ``as_utc()`` would be available immediately:: from sqlalchemy.sql.functions import GenericFunction from sqlalchemy.types import DateTime class as_utc(GenericFunction): type = DateTime print(select([func.as_utc()])) User-defined generic functions can be organized into packages by specifying the "package" attribute when defining :class:`.GenericFunction`. Third party libraries containing many functions may want to use this in order to avoid name conflicts with other systems. For example, if our ``as_utc()`` function were part of a package "time":: class as_utc(GenericFunction): type = DateTime package = "time" The above function would be available from :data:`.func` using the package name ``time``:: print(select([func.time.as_utc()])) A final option is to allow the function to be accessed from one name in :data:`.func` but to render as a different name. The ``identifier`` attribute will override the name used to access the function as loaded from :data:`.func`, but will retain the usage of ``name`` as the rendered name:: class GeoBuffer(GenericFunction): type = Geometry package = "geo" name = "ST_Buffer" identifier = "buffer" The above function will render as follows:: >>> print(func.geo.buffer()) ST_Buffer() The name will be rendered as is, however without quoting unless the name contains special characters that require quoting. To force quoting on or off for the name, use the :class:`.sqlalchemy.sql.quoted_name` construct:: from sqlalchemy.sql import quoted_name class GeoBuffer(GenericFunction): type = Geometry package = "geo" name = quoted_name("ST_Buffer", True) identifier = "buffer" The above function will render as:: >>> print(func.geo.buffer()) "ST_Buffer"() .. versionadded:: 1.3.13 The :class:`.quoted_name` construct is now recognized for quoting when used with the "name" attribute of the object, so that quoting can be forced on or off for the function name. """ coerce_arguments = True _register = False def __init__(self, *args, **kwargs): parsed_args = kwargs.pop("_parsed_args", None) if parsed_args is None: parsed_args = [_literal_as_binds(c, self.name) for c in args] self._has_args = self._has_args or bool(parsed_args) self.packagenames = [] self._bind = kwargs.get("bind", None) self.clause_expr = ClauseList( operator=operators.comma_op, group_contents=True, *parsed_args ).self_group() self.type = sqltypes.to_instance( kwargs.pop("type_", None) or getattr(self, "type", None) ) register_function("cast", Cast) register_function("extract", Extract) class next_value(GenericFunction): """Represent the 'next value', given a :class:`.Sequence` as its single argument. Compiles into the appropriate function on each backend, or will raise NotImplementedError if used on a backend that does not provide support for sequences. """ type = sqltypes.Integer() name = "next_value" def __init__(self, seq, **kw): assert isinstance( seq, schema.Sequence ), "next_value() accepts a Sequence object as input." self._bind = kw.get("bind", None) self.sequence = seq @property def _from_objects(self): return [] class AnsiFunction(GenericFunction): def __init__(self, *args, **kwargs): GenericFunction.__init__(self, *args, **kwargs) class ReturnTypeFromArgs(GenericFunction): """Define a function whose return type is the same as its arguments.""" def __init__(self, *args, **kwargs): args = [_literal_as_binds(c, self.name) for c in args] kwargs.setdefault("type_", _type_from_args(args)) kwargs["_parsed_args"] = args super(ReturnTypeFromArgs, self).__init__(*args, **kwargs) class coalesce(ReturnTypeFromArgs): _has_args = True class max(ReturnTypeFromArgs): # noqa pass class min(ReturnTypeFromArgs): # noqa pass class sum(ReturnTypeFromArgs): # noqa pass class now(GenericFunction): # noqa type = sqltypes.DateTime class concat(GenericFunction): type = sqltypes.String class char_length(GenericFunction): type = sqltypes.Integer def __init__(self, arg, **kwargs): GenericFunction.__init__(self, arg, **kwargs) class random(GenericFunction): _has_args = True class count(GenericFunction): r"""The ANSI COUNT aggregate function. With no arguments, emits COUNT \*. E.g.:: from sqlalchemy import func from sqlalchemy import select from sqlalchemy import table, column my_table = table('some_table', column('id')) stmt = select([func.count()]).select_from(my_table) Executing ``stmt`` would emit:: SELECT count(*) AS count_1 FROM some_table """ type = sqltypes.Integer def __init__(self, expression=None, **kwargs): if expression is None: expression = literal_column("*") super(count, self).__init__(expression, **kwargs) class current_date(AnsiFunction): type = sqltypes.Date class current_time(AnsiFunction): type = sqltypes.Time class current_timestamp(AnsiFunction): type = sqltypes.DateTime class current_user(AnsiFunction): type = sqltypes.String class localtime(AnsiFunction): type = sqltypes.DateTime class localtimestamp(AnsiFunction): type = sqltypes.DateTime class session_user(AnsiFunction): type = sqltypes.String class sysdate(AnsiFunction): type = sqltypes.DateTime class user(AnsiFunction): type = sqltypes.String class array_agg(GenericFunction): """Support for the ARRAY_AGG function. The ``func.array_agg(expr)`` construct returns an expression of type :class:`_types.ARRAY`. e.g.:: stmt = select([func.array_agg(table.c.values)[2:5]]) .. versionadded:: 1.1 .. seealso:: :func:`_postgresql.array_agg` - PostgreSQL-specific version that returns :class:`_postgresql.ARRAY`, which has PG-specific operators added. """ type = sqltypes.ARRAY def __init__(self, *args, **kwargs): args = [_literal_as_binds(c) for c in args] default_array_type = kwargs.pop("_default_array_type", sqltypes.ARRAY) if "type_" not in kwargs: type_from_args = _type_from_args(args) if isinstance(type_from_args, sqltypes.ARRAY): kwargs["type_"] = type_from_args else: kwargs["type_"] = default_array_type(type_from_args) kwargs["_parsed_args"] = args super(array_agg, self).__init__(*args, **kwargs) class OrderedSetAgg(GenericFunction): """Define a function where the return type is based on the sort expression type as defined by the expression passed to the :meth:`.FunctionElement.within_group` method.""" array_for_multi_clause = False def within_group_type(self, within_group): func_clauses = self.clause_expr.element order_by = sqlutil.unwrap_order_by(within_group.order_by) if self.array_for_multi_clause and len(func_clauses.clauses) > 1: return sqltypes.ARRAY(order_by[0].type) else: return order_by[0].type class mode(OrderedSetAgg): """Implement the ``mode`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression. .. versionadded:: 1.1 """ class percentile_cont(OrderedSetAgg): """Implement the ``percentile_cont`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression, or if the arguments are an array, an :class:`_types.ARRAY` of the sort expression's type. .. versionadded:: 1.1 """ array_for_multi_clause = True class percentile_disc(OrderedSetAgg): """Implement the ``percentile_disc`` ordered-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is the same as the sort expression, or if the arguments are an array, an :class:`_types.ARRAY` of the sort expression's type. .. versionadded:: 1.1 """ array_for_multi_clause = True class rank(GenericFunction): """Implement the ``rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Integer`. .. versionadded:: 1.1 """ type = sqltypes.Integer() class dense_rank(GenericFunction): """Implement the ``dense_rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Integer`. .. versionadded:: 1.1 """ type = sqltypes.Integer() class percent_rank(GenericFunction): """Implement the ``percent_rank`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Numeric`. .. versionadded:: 1.1 """ type = sqltypes.Numeric() class cume_dist(GenericFunction): """Implement the ``cume_dist`` hypothetical-set aggregate function. This function must be used with the :meth:`.FunctionElement.within_group` modifier to supply a sort expression to operate upon. The return type of this function is :class:`.Numeric`. .. versionadded:: 1.1 """ type = sqltypes.Numeric() class cube(GenericFunction): r"""Implement the ``CUBE`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.cube(table.c.col_1, table.c.col_2)) .. versionadded:: 1.2 """ _has_args = True class rollup(GenericFunction): r"""Implement the ``ROLLUP`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.rollup(table.c.col_1, table.c.col_2)) .. versionadded:: 1.2 """ _has_args = True class grouping_sets(GenericFunction): r"""Implement the ``GROUPING SETS`` grouping operation. This function is used as part of the GROUP BY of a statement, e.g. :meth:`_expression.Select.group_by`:: stmt = select( [func.sum(table.c.value), table.c.col_1, table.c.col_2] ).group_by(func.grouping_sets(table.c.col_1, table.c.col_2)) In order to group by multiple sets, use the :func:`.tuple_` construct:: from sqlalchemy import tuple_ stmt = select( [ func.sum(table.c.value), table.c.col_1, table.c.col_2, table.c.col_3] ).group_by( func.grouping_sets( tuple_(table.c.col_1, table.c.col_2), tuple_(table.c.value, table.c.col_3), ) ) .. versionadded:: 1.2 """ _has_args = True PK!ZuZuutil.pynu[# sql/util.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """High level utilities which build upon other modules here. """ from collections import deque from itertools import chain from . import operators from . import visitors from .annotation import _deep_annotate # noqa from .annotation import _deep_deannotate # noqa from .annotation import _shallow_annotate # noqa from .base import _from_objects from .base import ColumnSet from .ddl import sort_tables # noqa from .elements import _expand_cloned from .elements import _find_columns # noqa from .elements import _label_reference from .elements import _textual_label_reference from .elements import BindParameter from .elements import ColumnClause from .elements import ColumnElement from .elements import Grouping from .elements import Label from .elements import Null from .elements import UnaryExpression from .schema import Column from .selectable import Alias from .selectable import FromClause from .selectable import FromGrouping from .selectable import Join from .selectable import ScalarSelect from .selectable import SelectBase from .selectable import TableClause from .. import exc from .. import util join_condition = util.langhelpers.public_factory( Join._join_condition, ".sql.util.join_condition" ) def find_join_source(clauses, join_to): """Given a list of FROM clauses and a selectable, return the first index and element from the list of clauses which can be joined against the selectable. returns None, None if no match is found. e.g.:: clause1 = table1.join(table2) clause2 = table4.join(table5) join_to = table2.join(table3) find_join_source([clause1, clause2], join_to) == clause1 """ selectables = list(_from_objects(join_to)) idx = [] for i, f in enumerate(clauses): for s in selectables: if f.is_derived_from(s): idx.append(i) return idx def find_left_clause_that_matches_given(clauses, join_from): """Given a list of FROM clauses and a selectable, return the indexes from the list of clauses which is derived from the selectable. """ selectables = list(_from_objects(join_from)) liberal_idx = [] for i, f in enumerate(clauses): for s in selectables: # basic check, if f is derived from s. # this can be joins containing a table, or an aliased table # or select statement matching to a table. This check # will match a table to a selectable that is adapted from # that table. With Query, this suits the case where a join # is being made to an adapted entity if f.is_derived_from(s): liberal_idx.append(i) break # in an extremely small set of use cases, a join is being made where # there are multiple FROM clauses where our target table is represented # in more than one, such as embedded or similar. in this case, do # another pass where we try to get a more exact match where we aren't # looking at adaption relationships. if len(liberal_idx) > 1: conservative_idx = [] for idx in liberal_idx: f = clauses[idx] for s in selectables: if set(surface_selectables(f)).intersection( surface_selectables(s) ): conservative_idx.append(idx) break if conservative_idx: return conservative_idx return liberal_idx def find_left_clause_to_join_from(clauses, join_to, onclause): """Given a list of FROM clauses, a selectable, and optional ON clause, return a list of integer indexes from the clauses list indicating the clauses that can be joined from. The presence of an "onclause" indicates that at least one clause can definitely be joined from; if the list of clauses is of length one and the onclause is given, returns that index. If the list of clauses is more than length one, and the onclause is given, attempts to locate which clauses contain the same columns. """ idx = [] selectables = set(_from_objects(join_to)) # if we are given more than one target clause to join # from, use the onclause to provide a more specific answer. # otherwise, don't try to limit, after all, "ON TRUE" is a valid # on clause if len(clauses) > 1 and onclause is not None: resolve_ambiguity = True cols_in_onclause = _find_columns(onclause) else: resolve_ambiguity = False cols_in_onclause = None for i, f in enumerate(clauses): for s in selectables.difference([f]): if resolve_ambiguity: if set(f.c).union(s.c).issuperset(cols_in_onclause): idx.append(i) break elif Join._can_join(f, s) or onclause is not None: idx.append(i) break if len(idx) > 1: # this is the same "hide froms" logic from # Selectable._get_display_froms toremove = set( chain(*[_expand_cloned(f._hide_froms) for f in clauses]) ) idx = [i for i in idx if clauses[i] not in toremove] # onclause was given and none of them resolved, so assume # all indexes can match if not idx and onclause is not None: return range(len(clauses)) else: return idx def visit_binary_product(fn, expr): """Produce a traversal of the given expression, delivering column comparisons to the given function. The function is of the form:: def my_fn(binary, left, right) For each binary expression located which has a comparison operator, the product of "left" and "right" will be delivered to that function, in terms of that binary. Hence an expression like:: and_( (a + b) == q + func.sum(e + f), j == r ) would have the traversal:: a q a e a f b q b e b f j r That is, every combination of "left" and "right" that doesn't further contain a binary comparison is passed as pairs. """ stack = [] def visit(element): if isinstance(element, ScalarSelect): # we don't want to dig into correlated subqueries, # those are just column elements by themselves yield element elif element.__visit_name__ == "binary" and operators.is_comparison( element.operator ): stack.insert(0, element) for l in visit(element.left): for r in visit(element.right): fn(stack[0], l, r) stack.pop(0) for elem in element.get_children(): visit(elem) else: if isinstance(element, ColumnClause): yield element for elem in element.get_children(): for e in visit(elem): yield e list(visit(expr)) visit = None # remove gc cycles def find_tables( clause, check_columns=False, include_aliases=False, include_joins=False, include_selects=False, include_crud=False, ): """locate Table objects within the given expression.""" tables = [] _visitors = {} if include_selects: _visitors["select"] = _visitors["compound_select"] = tables.append if include_joins: _visitors["join"] = tables.append if include_aliases: _visitors["alias"] = tables.append if include_crud: _visitors["insert"] = _visitors["update"] = _visitors[ "delete" ] = lambda ent: tables.append(ent.table) if check_columns: def visit_column(column): tables.append(column.table) _visitors["column"] = visit_column _visitors["table"] = tables.append visitors.traverse(clause, {"column_collections": False}, _visitors) return tables def unwrap_order_by(clause): """Break up an 'order by' expression into individual column-expressions, without DESC/ASC/NULLS FIRST/NULLS LAST""" cols = util.column_set() result = [] stack = deque([clause]) while stack: t = stack.popleft() if isinstance(t, ColumnElement) and ( not isinstance(t, UnaryExpression) or not operators.is_ordering_modifier(t.modifier) ): if isinstance(t, Label) and not isinstance( t.element, ScalarSelect ): t = t.element if isinstance(t, Grouping): t = t.element stack.append(t) continue if isinstance(t, _label_reference): t = t.element if isinstance(t, (_textual_label_reference)): continue if t not in cols: cols.add(t) result.append(t) else: for c in t.get_children(): stack.append(c) return result def unwrap_label_reference(element): def replace(elem): if isinstance(elem, (_label_reference, _textual_label_reference)): return elem.element return visitors.replacement_traverse(element, {}, replace) def expand_column_list_from_order_by(collist, order_by): """Given the columns clause and ORDER BY of a selectable, return a list of column expressions that can be added to the collist corresponding to the ORDER BY, without repeating those already in the collist. """ cols_already_present = set( [ col.element if col._order_by_label_element is not None else col for col in collist ] ) to_look_for = list(chain(*[unwrap_order_by(o) for o in order_by])) return [col for col in to_look_for if col not in cols_already_present] def clause_is_present(clause, search): """Given a target clause and a second to search within, return True if the target is plainly present in the search without any subqueries or aliases involved. Basically descends through Joins. """ for elem in surface_selectables(search): if clause == elem: # use == here so that Annotated's compare return True else: return False def tables_from_leftmost(clause): if isinstance(clause, Join): for t in tables_from_leftmost(clause.left): yield t for t in tables_from_leftmost(clause.right): yield t elif isinstance(clause, FromGrouping): for t in tables_from_leftmost(clause.element): yield t else: yield clause def surface_selectables(clause): stack = [clause] while stack: elem = stack.pop() yield elem if isinstance(elem, Join): stack.extend((elem.left, elem.right)) elif isinstance(elem, FromGrouping): stack.append(elem.element) def surface_selectables_only(clause): stack = [clause] while stack: elem = stack.pop() if isinstance(elem, (TableClause, Alias)): yield elem if isinstance(elem, Join): stack.extend((elem.left, elem.right)) elif isinstance(elem, FromGrouping): stack.append(elem.element) elif isinstance(elem, ColumnClause): if elem.table is not None: stack.append(elem.table) else: yield elem elif elem is not None: yield elem def surface_column_elements(clause, include_scalar_selects=True): """traverse and yield only outer-exposed column elements, such as would be addressable in the WHERE clause of a SELECT if this element were in the columns clause.""" filter_ = (FromGrouping,) if not include_scalar_selects: filter_ += (SelectBase,) stack = deque([clause]) while stack: elem = stack.popleft() yield elem for sub in elem.get_children(): if isinstance(sub, filter_): continue stack.append(sub) def selectables_overlap(left, right): """Return True if left/right have some overlapping selectable""" return bool( set(surface_selectables(left)).intersection(surface_selectables(right)) ) def bind_values(clause): """Return an ordered list of "bound" values in the given clause. E.g.:: >>> expr = and_( ... table.c.foo==5, table.c.foo==7 ... ) >>> bind_values(expr) [5, 7] """ v = [] def visit_bindparam(bind): v.append(bind.effective_value) visitors.traverse(clause, {}, {"bindparam": visit_bindparam}) return v def _quote_ddl_expr(element): if isinstance(element, util.string_types): element = element.replace("'", "''") return "'%s'" % element else: return repr(element) class _repr_base(object): _LIST = 0 _TUPLE = 1 _DICT = 2 __slots__ = ("max_chars",) def trunc(self, value): rep = repr(value) lenrep = len(rep) if lenrep > self.max_chars: segment_length = self.max_chars // 2 rep = ( rep[0:segment_length] + ( " ... (%d characters truncated) ... " % (lenrep - self.max_chars) ) + rep[-segment_length:] ) return rep class _repr_row(_repr_base): """Provide a string view of a row.""" __slots__ = ("row",) def __init__(self, row, max_chars=300): self.row = row self.max_chars = max_chars def __repr__(self): trunc = self.trunc return "(%s%s)" % ( ", ".join(trunc(value) for value in self.row), "," if len(self.row) == 1 else "", ) class _repr_params(_repr_base): """Provide a string view of bound parameters. Truncates display to a given numnber of 'multi' parameter sets, as well as long values to a given number of characters. """ __slots__ = "params", "batches", "ismulti" def __init__(self, params, batches, max_chars=300, ismulti=None): self.params = params self.ismulti = ismulti self.batches = batches self.max_chars = max_chars def __repr__(self): if self.ismulti is None: return self.trunc(self.params) if isinstance(self.params, list): typ = self._LIST elif isinstance(self.params, tuple): typ = self._TUPLE elif isinstance(self.params, dict): typ = self._DICT else: return self.trunc(self.params) if self.ismulti and len(self.params) > self.batches: msg = " ... displaying %i of %i total bound parameter sets ... " return " ".join( ( self._repr_multi(self.params[: self.batches - 2], typ)[ 0:-1 ], msg % (self.batches, len(self.params)), self._repr_multi(self.params[-2:], typ)[1:], ) ) elif self.ismulti: return self._repr_multi(self.params, typ) else: return self._repr_params(self.params, typ) def _repr_multi(self, multi_params, typ): if multi_params: if isinstance(multi_params[0], list): elem_type = self._LIST elif isinstance(multi_params[0], tuple): elem_type = self._TUPLE elif isinstance(multi_params[0], dict): elem_type = self._DICT else: assert False, "Unknown parameter type %s" % ( type(multi_params[0]) ) elements = ", ".join( self._repr_params(params, elem_type) for params in multi_params ) else: elements = "" if typ == self._LIST: return "[%s]" % elements else: return "(%s)" % elements def _repr_params(self, params, typ): trunc = self.trunc if typ is self._DICT: return "{%s}" % ( ", ".join( "%r: %s" % (key, trunc(value)) for key, value in params.items() ) ) elif typ is self._TUPLE: return "(%s%s)" % ( ", ".join(trunc(value) for value in params), "," if len(params) == 1 else "", ) else: return "[%s]" % (", ".join(trunc(value) for value in params)) def adapt_criterion_to_null(crit, nulls): """given criterion containing bind params, convert selected elements to IS NULL. """ def visit_binary(binary): if ( isinstance(binary.left, BindParameter) and binary.left._identifying_key in nulls ): # reverse order if the NULL is on the left side binary.left = binary.right binary.right = Null() binary.operator = operators.is_ binary.negate = operators.isnot elif ( isinstance(binary.right, BindParameter) and binary.right._identifying_key in nulls ): binary.right = Null() binary.operator = operators.is_ binary.negate = operators.isnot return visitors.cloned_traverse(crit, {}, {"binary": visit_binary}) def splice_joins(left, right, stop_on=None): if left is None: return right stack = [(right, None)] adapter = ClauseAdapter(left) ret = None while stack: (right, prevright) = stack.pop() if isinstance(right, Join) and right is not stop_on: right = right._clone() right._reset_exported() right.onclause = adapter.traverse(right.onclause) stack.append((right.left, right)) else: right = adapter.traverse(right) if prevright is not None: prevright.left = right if ret is None: ret = right return ret def reduce_columns(columns, *clauses, **kw): r"""given a list of columns, return a 'reduced' set based on natural equivalents. the set is reduced to the smallest list of columns which have no natural equivalent present in the list. A "natural equivalent" means that two columns will ultimately represent the same value because they are related by a foreign key. \*clauses is an optional list of join clauses which will be traversed to further identify columns that are "equivalent". \**kw may specify 'ignore_nonexistent_tables' to ignore foreign keys whose tables are not yet configured, or columns that aren't yet present. This function is primarily used to determine the most minimal "primary key" from a selectable, by reducing the set of primary key columns present in the selectable to just those that are not repeated. """ ignore_nonexistent_tables = kw.pop("ignore_nonexistent_tables", False) only_synonyms = kw.pop("only_synonyms", False) columns = util.ordered_column_set(columns) omit = util.column_set() for col in columns: for fk in chain(*[c.foreign_keys for c in col.proxy_set]): for c in columns: if c is col: continue try: fk_col = fk.column except exc.NoReferencedColumnError: # TODO: add specific coverage here # to test/sql/test_selectable ReduceTest if ignore_nonexistent_tables: continue else: raise except exc.NoReferencedTableError: # TODO: add specific coverage here # to test/sql/test_selectable ReduceTest if ignore_nonexistent_tables: continue else: raise if fk_col.shares_lineage(c) and ( not only_synonyms or c.name == col.name ): omit.add(col) break if clauses: def visit_binary(binary): if binary.operator == operators.eq: cols = util.column_set( chain(*[c.proxy_set for c in columns.difference(omit)]) ) if binary.left in cols and binary.right in cols: for c in reversed(columns): if c.shares_lineage(binary.right) and ( not only_synonyms or c.name == binary.left.name ): omit.add(c) break for clause in clauses: if clause is not None: visitors.traverse(clause, {}, {"binary": visit_binary}) return ColumnSet(columns.difference(omit)) def criterion_as_pairs( expression, consider_as_foreign_keys=None, consider_as_referenced_keys=None, any_operator=False, ): """traverse an expression and locate binary criterion pairs.""" if consider_as_foreign_keys and consider_as_referenced_keys: raise exc.ArgumentError( "Can only specify one of " "'consider_as_foreign_keys' or " "'consider_as_referenced_keys'" ) def col_is(a, b): # return a is b return a.compare(b) def visit_binary(binary): if not any_operator and binary.operator is not operators.eq: return if not isinstance(binary.left, ColumnElement) or not isinstance( binary.right, ColumnElement ): return if consider_as_foreign_keys: if binary.left in consider_as_foreign_keys and ( col_is(binary.right, binary.left) or binary.right not in consider_as_foreign_keys ): pairs.append((binary.right, binary.left)) elif binary.right in consider_as_foreign_keys and ( col_is(binary.left, binary.right) or binary.left not in consider_as_foreign_keys ): pairs.append((binary.left, binary.right)) elif consider_as_referenced_keys: if binary.left in consider_as_referenced_keys and ( col_is(binary.right, binary.left) or binary.right not in consider_as_referenced_keys ): pairs.append((binary.left, binary.right)) elif binary.right in consider_as_referenced_keys and ( col_is(binary.left, binary.right) or binary.left not in consider_as_referenced_keys ): pairs.append((binary.right, binary.left)) else: if isinstance(binary.left, Column) and isinstance( binary.right, Column ): if binary.left.references(binary.right): pairs.append((binary.right, binary.left)) elif binary.right.references(binary.left): pairs.append((binary.left, binary.right)) pairs = [] visitors.traverse(expression, {}, {"binary": visit_binary}) return pairs class ClauseAdapter(visitors.ReplacingCloningVisitor): """Clones and modifies clauses based on column correspondence. E.g.:: table1 = Table('sometable', metadata, Column('col1', Integer), Column('col2', Integer) ) table2 = Table('someothertable', metadata, Column('col1', Integer), Column('col2', Integer) ) condition = table1.c.col1 == table2.c.col1 make an alias of table1:: s = table1.alias('foo') calling ``ClauseAdapter(s).traverse(condition)`` converts condition to read:: s.c.col1 == table2.c.col1 """ def __init__( self, selectable, equivalents=None, include_fn=None, exclude_fn=None, adapt_on_names=False, anonymize_labels=False, ): self.__traverse_options__ = { "stop_on": [selectable], "anonymize_labels": anonymize_labels, } self.selectable = selectable self.include_fn = include_fn self.exclude_fn = exclude_fn self.equivalents = util.column_dict(equivalents or {}) self.adapt_on_names = adapt_on_names def _corresponding_column( self, col, require_embedded, _seen=util.EMPTY_SET ): newcol = self.selectable.corresponding_column( col, require_embedded=require_embedded ) if newcol is None and col in self.equivalents and col not in _seen: for equiv in self.equivalents[col]: newcol = self._corresponding_column( equiv, require_embedded=require_embedded, _seen=_seen.union([col]), ) if newcol is not None: return newcol if self.adapt_on_names and newcol is None: newcol = self.selectable.c.get(col.name) return newcol def replace(self, col): if isinstance(col, FromClause) and self.selectable.is_derived_from( col ): return self.selectable elif not isinstance(col, ColumnElement): return None elif self.include_fn and not self.include_fn(col): return None elif self.exclude_fn and self.exclude_fn(col): return None else: return self._corresponding_column(col, True) class ColumnAdapter(ClauseAdapter): """Extends ClauseAdapter with extra utility functions. Key aspects of ColumnAdapter include: * Expressions that are adapted are stored in a persistent .columns collection; so that an expression E adapted into an expression E1, will return the same object E1 when adapted a second time. This is important in particular for things like Label objects that are anonymized, so that the ColumnAdapter can be used to present a consistent "adapted" view of things. * Exclusion of items from the persistent collection based on include/exclude rules, but also independent of hash identity. This because "annotated" items all have the same hash identity as their parent. * "wrapping" capability is added, so that the replacement of an expression E can proceed through a series of adapters. This differs from the visitor's "chaining" feature in that the resulting object is passed through all replacing functions unconditionally, rather than stopping at the first one that returns non-None. * An adapt_required option, used by eager loading to indicate that We don't trust a result row column that is not translated. This is to prevent a column from being interpreted as that of the child row in a self-referential scenario, see inheritance/test_basic.py->EagerTargetingTest.test_adapt_stringency """ def __init__( self, selectable, equivalents=None, adapt_required=False, include_fn=None, exclude_fn=None, adapt_on_names=False, allow_label_resolve=True, anonymize_labels=False, ): ClauseAdapter.__init__( self, selectable, equivalents, include_fn=include_fn, exclude_fn=exclude_fn, adapt_on_names=adapt_on_names, anonymize_labels=anonymize_labels, ) self.columns = util.WeakPopulateDict(self._locate_col) if self.include_fn or self.exclude_fn: self.columns = self._IncludeExcludeMapping(self, self.columns) self.adapt_required = adapt_required self.allow_label_resolve = allow_label_resolve self._wrap = None class _IncludeExcludeMapping(object): def __init__(self, parent, columns): self.parent = parent self.columns = columns def __getitem__(self, key): if ( self.parent.include_fn and not self.parent.include_fn(key) ) or (self.parent.exclude_fn and self.parent.exclude_fn(key)): if self.parent._wrap: return self.parent._wrap.columns[key] else: return key return self.columns[key] def wrap(self, adapter): ac = self.__class__.__new__(self.__class__) ac.__dict__.update(self.__dict__) ac._wrap = adapter ac.columns = util.WeakPopulateDict(ac._locate_col) if ac.include_fn or ac.exclude_fn: ac.columns = self._IncludeExcludeMapping(ac, ac.columns) return ac def traverse(self, obj): return self.columns[obj] adapt_clause = traverse adapt_list = ClauseAdapter.copy_and_process def _locate_col(self, col): c = ClauseAdapter.traverse(self, col) if self._wrap: c2 = self._wrap._locate_col(c) if c2 is not None: c = c2 if self.adapt_required and c is col: return None c._allow_label_resolve = self.allow_label_resolve return c def __getstate__(self): d = self.__dict__.copy() del d["columns"] return d def __setstate__(self, state): self.__dict__.update(state) self.columns = util.WeakPopulateDict(self._locate_col) PK!//default_comparator.pynu[# sql/default_comparator.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Default implementation of SQL comparison operations. """ from . import operators from . import type_api from .elements import _clause_element_as_expr from .elements import _const_expr from .elements import _is_literal from .elements import _literal_as_text from .elements import and_ from .elements import BinaryExpression from .elements import BindParameter from .elements import ClauseElement from .elements import ClauseList from .elements import collate from .elements import CollectionAggregate from .elements import ColumnElement from .elements import False_ from .elements import Null from .elements import or_ from .elements import TextClause from .elements import True_ from .elements import Tuple from .elements import UnaryExpression from .elements import Visitable from .selectable import Alias from .selectable import ScalarSelect from .selectable import Selectable from .selectable import SelectBase from .. import exc from .. import util def _boolean_compare( expr, op, obj, negate=None, reverse=False, _python_is_types=(util.NoneType, bool), result_type=None, **kwargs ): if result_type is None: result_type = type_api.BOOLEANTYPE if isinstance(obj, _python_is_types + (Null, True_, False_)): # allow x ==/!= True/False to be treated as a literal. # this comes out to "== / != true/false" or "1/0" if those # constants aren't supported and works on all platforms if op in (operators.eq, operators.ne) and isinstance( obj, (bool, True_, False_) ): return BinaryExpression( expr, _literal_as_text(obj), op, type_=result_type, negate=negate, modifiers=kwargs, ) elif op in (operators.is_distinct_from, operators.isnot_distinct_from): return BinaryExpression( expr, _literal_as_text(obj), op, type_=result_type, negate=negate, modifiers=kwargs, ) else: # all other None/True/False uses IS, IS NOT if op in (operators.eq, operators.is_): return BinaryExpression( expr, _const_expr(obj), operators.is_, negate=operators.isnot, type_=result_type, ) elif op in (operators.ne, operators.isnot): return BinaryExpression( expr, _const_expr(obj), operators.isnot, negate=operators.is_, type_=result_type, ) else: raise exc.ArgumentError( "Only '=', '!=', 'is_()', 'isnot()', " "'is_distinct_from()', 'isnot_distinct_from()' " "operators can be used with None/True/False" ) else: obj = _check_literal(expr, op, obj) if reverse: return BinaryExpression( obj, expr, op, type_=result_type, negate=negate, modifiers=kwargs ) else: return BinaryExpression( expr, obj, op, type_=result_type, negate=negate, modifiers=kwargs ) def _custom_op_operate(expr, op, obj, reverse=False, result_type=None, **kw): if result_type is None: if op.return_type: result_type = op.return_type elif op.is_comparison: result_type = type_api.BOOLEANTYPE return _binary_operate( expr, op, obj, reverse=reverse, result_type=result_type, **kw ) def _binary_operate(expr, op, obj, reverse=False, result_type=None, **kw): obj = _check_literal(expr, op, obj) if reverse: left, right = obj, expr else: left, right = expr, obj if result_type is None: op, result_type = left.comparator._adapt_expression( op, right.comparator ) return BinaryExpression(left, right, op, type_=result_type, modifiers=kw) def _conjunction_operate(expr, op, other, **kw): if op is operators.and_: return and_(expr, other) elif op is operators.or_: return or_(expr, other) else: raise NotImplementedError() def _scalar(expr, op, fn, **kw): return fn(expr) def _in_impl(expr, op, seq_or_selectable, negate_op, **kw): seq_or_selectable = _clause_element_as_expr(seq_or_selectable) if isinstance(seq_or_selectable, ScalarSelect): return _boolean_compare(expr, op, seq_or_selectable, negate=negate_op) elif isinstance(seq_or_selectable, SelectBase): # TODO: if we ever want to support (x, y, z) IN (select x, # y, z from table), we would need a multi-column version of # as_scalar() to produce a multi- column selectable that # does not export itself as a FROM clause return _boolean_compare( expr, op, seq_or_selectable.as_scalar(), negate=negate_op, **kw ) elif isinstance(seq_or_selectable, (Selectable, TextClause)): return _boolean_compare( expr, op, seq_or_selectable, negate=negate_op, **kw ) elif isinstance(seq_or_selectable, ClauseElement): if ( isinstance(seq_or_selectable, BindParameter) and seq_or_selectable.expanding ): if isinstance(expr, Tuple): seq_or_selectable = seq_or_selectable._with_expanding_in_types( [elem.type for elem in expr] ) return _boolean_compare( expr, op, seq_or_selectable, negate=negate_op ) else: raise exc.InvalidRequestError( "in_() accepts" " either a list of expressions, " 'a selectable, or an "expanding" bound parameter: %r' % seq_or_selectable ) # Handle non selectable arguments as sequences args = [] for o in seq_or_selectable: if not _is_literal(o): if not isinstance(o, operators.ColumnOperators): raise exc.InvalidRequestError( "in_() accepts" " either a list of expressions, " 'a selectable, or an "expanding" bound parameter: %r' % o ) elif o is None: o = Null() else: o = expr._bind_param(op, o) args.append(o) if len(args) == 0: op, negate_op = ( (operators.empty_in_op, operators.empty_notin_op) if op is operators.in_op else (operators.empty_notin_op, operators.empty_in_op) ) return _boolean_compare( expr, op, ClauseList(_tuple_values=isinstance(expr, Tuple), *args).self_group( against=op ), negate=negate_op, ) def _getitem_impl(expr, op, other, **kw): if isinstance(expr.type, type_api.INDEXABLE): other = _check_literal(expr, op, other) return _binary_operate(expr, op, other, **kw) else: _unsupported_impl(expr, op, other, **kw) def _unsupported_impl(expr, op, *arg, **kw): raise NotImplementedError( "Operator '%s' is not supported on " "this expression" % op.__name__ ) def _inv_impl(expr, op, **kw): """See :meth:`.ColumnOperators.__inv__`.""" if hasattr(expr, "negation_clause"): return expr.negation_clause else: return expr._negate() def _neg_impl(expr, op, **kw): """See :meth:`.ColumnOperators.__neg__`.""" return UnaryExpression(expr, operator=operators.neg, type_=expr.type) def _match_impl(expr, op, other, **kw): """See :meth:`.ColumnOperators.match`.""" return _boolean_compare( expr, operators.match_op, _check_literal(expr, operators.match_op, other), result_type=type_api.MATCHTYPE, negate=operators.notmatch_op if op is operators.match_op else operators.match_op, **kw ) def _distinct_impl(expr, op, **kw): """See :meth:`.ColumnOperators.distinct`.""" return UnaryExpression( expr, operator=operators.distinct_op, type_=expr.type ) def _between_impl(expr, op, cleft, cright, **kw): """See :meth:`.ColumnOperators.between`.""" return BinaryExpression( expr, ClauseList( _check_literal(expr, operators.and_, cleft), _check_literal(expr, operators.and_, cright), operator=operators.and_, group=False, group_contents=False, ), op, negate=operators.notbetween_op if op is operators.between_op else operators.between_op, modifiers=kw, ) def _collate_impl(expr, op, other, **kw): return collate(expr, other) # a mapping of operators with the method they use, along with # their negated operator for comparison operators operator_lookup = { "and_": (_conjunction_operate,), "or_": (_conjunction_operate,), "inv": (_inv_impl,), "add": (_binary_operate,), "mul": (_binary_operate,), "sub": (_binary_operate,), "div": (_binary_operate,), "mod": (_binary_operate,), "truediv": (_binary_operate,), "custom_op": (_custom_op_operate,), "json_path_getitem_op": (_binary_operate,), "json_getitem_op": (_binary_operate,), "concat_op": (_binary_operate,), "any_op": (_scalar, CollectionAggregate._create_any), "all_op": (_scalar, CollectionAggregate._create_all), "lt": (_boolean_compare, operators.ge), "le": (_boolean_compare, operators.gt), "ne": (_boolean_compare, operators.eq), "gt": (_boolean_compare, operators.le), "ge": (_boolean_compare, operators.lt), "eq": (_boolean_compare, operators.ne), "is_distinct_from": (_boolean_compare, operators.isnot_distinct_from), "isnot_distinct_from": (_boolean_compare, operators.is_distinct_from), "like_op": (_boolean_compare, operators.notlike_op), "ilike_op": (_boolean_compare, operators.notilike_op), "notlike_op": (_boolean_compare, operators.like_op), "notilike_op": (_boolean_compare, operators.ilike_op), "contains_op": (_boolean_compare, operators.notcontains_op), "startswith_op": (_boolean_compare, operators.notstartswith_op), "endswith_op": (_boolean_compare, operators.notendswith_op), "desc_op": (_scalar, UnaryExpression._create_desc), "asc_op": (_scalar, UnaryExpression._create_asc), "nullsfirst_op": (_scalar, UnaryExpression._create_nullsfirst), "nullslast_op": (_scalar, UnaryExpression._create_nullslast), "in_op": (_in_impl, operators.notin_op), "notin_op": (_in_impl, operators.in_op), "is_": (_boolean_compare, operators.is_), "isnot": (_boolean_compare, operators.isnot), "collate": (_collate_impl,), "match_op": (_match_impl,), "notmatch_op": (_match_impl,), "distinct_op": (_distinct_impl,), "between_op": (_between_impl,), "notbetween_op": (_between_impl,), "neg": (_neg_impl,), "getitem": (_getitem_impl,), "lshift": (_unsupported_impl,), "rshift": (_unsupported_impl,), "contains": (_unsupported_impl,), } def _check_literal(expr, operator, other, bindparam_type=None): if isinstance(other, (ColumnElement, TextClause)): if isinstance(other, BindParameter) and other.type._isnull: other = other._clone() other.type = expr.type return other elif hasattr(other, "__clause_element__"): other = other.__clause_element__() elif isinstance(other, type_api.TypeEngine.Comparator): other = other.expr if isinstance(other, (SelectBase, Alias)): return other.as_scalar() elif not isinstance(other, Visitable): return expr._bind_param(operator, other, type_=bindparam_type) else: return other PK!P~-ss elements.pynu[# sql/elements.py # Copyright (C) 2005-2021 the SQLAlchemy authors and contributors # # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Core SQL expression elements, including :class:`_expression.ClauseElement`, :class:`_expression.ColumnElement`, and derived classes. """ from __future__ import unicode_literals import itertools import numbers import operator import re from . import operators from . import type_api from .annotation import Annotated from .base import _generative from .base import Executable from .base import Immutable from .base import NO_ARG from .base import PARSE_AUTOCOMMIT from .visitors import cloned_traverse from .visitors import traverse from .visitors import Visitable from .. import exc from .. import inspection from .. import util def _clone(element, **kw): return element._clone() def _document_text_coercion(paramname, meth_rst, param_rst): return util.add_parameter_text( paramname, ( ".. warning:: " "The %s argument to %s can be passed as a Python string argument, " "which will be treated " "as **trusted SQL text** and rendered as given. **DO NOT PASS " "UNTRUSTED INPUT TO THIS PARAMETER**." ) % (param_rst, meth_rst), ) def collate(expression, collation): """Return the clause ``expression COLLATE collation``. e.g.:: collate(mycolumn, 'utf8_bin') produces:: mycolumn COLLATE utf8_bin The collation expression is also quoted if it is a case sensitive identifier, e.g. contains uppercase characters. .. versionchanged:: 1.2 quoting is automatically applied to COLLATE expressions if they are case sensitive. """ expr = _literal_as_binds(expression) return BinaryExpression( expr, CollationClause(collation), operators.collate, type_=expr.type ) def between(expr, lower_bound, upper_bound, symmetric=False): """Produce a ``BETWEEN`` predicate clause. E.g.:: from sqlalchemy import between stmt = select([users_table]).where(between(users_table.c.id, 5, 7)) Would produce SQL resembling:: SELECT id, name FROM user WHERE id BETWEEN :id_1 AND :id_2 The :func:`.between` function is a standalone version of the :meth:`_expression.ColumnElement.between` method available on all SQL expressions, as in:: stmt = select([users_table]).where(users_table.c.id.between(5, 7)) All arguments passed to :func:`.between`, including the left side column expression, are coerced from Python scalar values if a the value is not a :class:`_expression.ColumnElement` subclass. For example, three fixed values can be compared as in:: print(between(5, 3, 7)) Which would produce:: :param_1 BETWEEN :param_2 AND :param_3 :param expr: a column expression, typically a :class:`_expression.ColumnElement` instance or alternatively a Python scalar expression to be coerced into a column expression, serving as the left side of the ``BETWEEN`` expression. :param lower_bound: a column or Python scalar expression serving as the lower bound of the right side of the ``BETWEEN`` expression. :param upper_bound: a column or Python scalar expression serving as the upper bound of the right side of the ``BETWEEN`` expression. :param symmetric: if True, will render " BETWEEN SYMMETRIC ". Note that not all databases support this syntax. .. versionadded:: 0.9.5 .. seealso:: :meth:`_expression.ColumnElement.between` """ expr = _literal_as_binds(expr) return expr.between(lower_bound, upper_bound, symmetric=symmetric) def literal(value, type_=None): r"""Return a literal clause, bound to a bind parameter. Literal clauses are created automatically when non- :class:`_expression.ClauseElement` objects (such as strings, ints, dates, etc.) are used in a comparison operation with a :class:`_expression.ColumnElement` subclass, such as a :class:`~sqlalchemy.schema.Column` object. Use this function to force the generation of a literal clause, which will be created as a :class:`BindParameter` with a bound value. :param value: the value to be bound. Can be any Python object supported by the underlying DB-API, or is translatable via the given type argument. :param type\_: an optional :class:`~sqlalchemy.types.TypeEngine` which will provide bind-parameter translation for this literal. """ return BindParameter(None, value, type_=type_, unique=True) def outparam(key, type_=None): """Create an 'OUT' parameter for usage in functions (stored procedures), for databases which support them. The ``outparam`` can be used like a regular function parameter. The "output" value will be available from the :class:`~sqlalchemy.engine.ResultProxy` object via its ``out_parameters`` attribute, which returns a dictionary containing the values. """ return BindParameter(key, None, type_=type_, unique=False, isoutparam=True) def not_(clause): """Return a negation of the given clause, i.e. ``NOT(clause)``. The ``~`` operator is also overloaded on all :class:`_expression.ColumnElement` subclasses to produce the same result. """ return operators.inv(_literal_as_binds(clause)) @inspection._self_inspects class ClauseElement(Visitable): """Base class for elements of a programmatically constructed SQL expression. """ __visit_name__ = "clause" _annotations = {} supports_execution = False _from_objects = [] bind = None _is_clone_of = None is_selectable = False is_clause_element = True description = None _order_by_label_element = None _is_from_container = False def _clone(self): """Create a shallow copy of this ClauseElement. This method may be used by a generative API. Its also used as part of the "deep" copy afforded by a traversal that combines the _copy_internals() method. """ c = self.__class__.__new__(self.__class__) c.__dict__ = self.__dict__.copy() ClauseElement._cloned_set._reset(c) ColumnElement.comparator._reset(c) # this is a marker that helps to "equate" clauses to each other # when a Select returns its list of FROM clauses. the cloning # process leaves around a lot of remnants of the previous clause # typically in the form of column expressions still attached to the # old table. c._is_clone_of = self return c @property def _constructor(self): """return the 'constructor' for this ClauseElement. This is for the purposes for creating a new object of this type. Usually, its just the element's __class__. However, the "Annotated" version of the object overrides to return the class of its proxied element. """ return self.__class__ @util.memoized_property def _cloned_set(self): """Return the set consisting all cloned ancestors of this ClauseElement. Includes this ClauseElement. This accessor tends to be used for FromClause objects to identify 'equivalent' FROM clauses, regardless of transformative operations. """ s = util.column_set() f = self # note this creates a cycle, asserted in test_memusage. however, # turning this into a plain @property adds tends of thousands of method # calls to Core / ORM performance tests, so the small overhead # introduced by the relatively small amount of short term cycles # produced here is preferable while f is not None: s.add(f) f = f._is_clone_of return s def __getstate__(self): d = self.__dict__.copy() d.pop("_is_clone_of", None) return d def _annotate(self, values): """Return a copy of this ClauseElement with annotations updated by the given dictionary. """ return Annotated(self, values) def _with_annotations(self, values): """Return a copy of this ClauseElement with annotations replaced by the given dictionary. """ return Annotated(self, values) def _deannotate(self, values=None, clone=False): """Return a copy of this :class:`_expression.ClauseElement` with annotations removed. :param values: optional tuple of individual values to remove. """ if clone: # clone is used when we are also copying # the expression for a deep deannotation return self._clone() else: # if no clone, since we have no annotations we return # self return self def _execute_on_connection(self, connection, multiparams, params): if self.supports_execution: return connection._execute_clauseelement(self, multiparams, params) else: raise exc.ObjectNotExecutableError(self) def unique_params(self, *optionaldict, **kwargs): """Return a copy with :func:`_expression.bindparam` elements replaced. Same functionality as :meth:`_expression.ClauseElement.params`, except adds `unique=True` to affected bind parameters so that multiple statements can be used. """ return self._params(True, optionaldict, kwargs) def params(self, *optionaldict, **kwargs): """Return a copy with :func:`_expression.bindparam` elements replaced. Returns a copy of this ClauseElement with :func:`_expression.bindparam` elements replaced with values taken from the given dictionary:: >>> clause = column('x') + bindparam('foo') >>> print(clause.compile().params) {'foo':None} >>> print(clause.params({'foo':7}).compile().params) {'foo':7} """ return self._params(False, optionaldict, kwargs) def _params(self, unique, optionaldict, kwargs): if len(optionaldict) == 1: kwargs.update(optionaldict[0]) elif len(optionaldict) > 1: raise exc.ArgumentError( "params() takes zero or one positional dictionary argument" ) def visit_bindparam(bind): if bind.key in kwargs: bind.value = kwargs[bind.key] bind.required = False if unique: bind._convert_to_unique() return cloned_traverse(self, {}, {"bindparam": visit_bindparam}) def compare(self, other, **kw): r"""Compare this :class:`_expression.ClauseElement` to the given :class:`_expression.ClauseElement`. Subclasses should override the default behavior, which is a straight identity comparison. \**kw are arguments consumed by subclass ``compare()`` methods and may be used to modify the criteria for comparison (see :class:`_expression.ColumnElement`). """ return self is other def _copy_internals(self, clone=_clone, **kw): """Reassign internal elements to be clones of themselves. Called during a copy-and-traverse operation on newly shallow-copied elements to create a deep copy. The given clone function should be used, which may be applying additional transformations to the element (i.e. replacement traversal, cloned traversal, annotations). """ pass def get_children(self, **kwargs): r"""Return immediate child elements of this :class:`_expression.ClauseElement`. This is used for visit traversal. \**kwargs may contain flags that change the collection that is returned, for example to return a subset of items in order to cut down on larger traversals, or to return child items from a different context (such as schema-level collections instead of clause-level). """ return [] def self_group(self, against=None): """Apply a 'grouping' to this :class:`_expression.ClauseElement`. This method is overridden by subclasses to return a "grouping" construct, i.e. parenthesis. In particular it's used by "binary" expressions to provide a grouping around themselves when placed into a larger expression, as well as by :func:`_expression.select` constructs when placed into the FROM clause of another :func:`_expression.select`. (Note that subqueries should be normally created using the :meth:`_expression.Select.alias` method, as many platforms require nested SELECT statements to be named). As expressions are composed together, the application of :meth:`self_group` is automatic - end-user code should never need to use this method directly. Note that SQLAlchemy's clause constructs take operator precedence into account - so parenthesis might not be needed, for example, in an expression like ``x OR (y AND z)`` - AND takes precedence over OR. The base :meth:`self_group` method of :class:`_expression.ClauseElement` just returns self. """ return self @util.dependencies("sqlalchemy.engine.default") def compile(self, default, bind=None, dialect=None, **kw): """Compile this SQL expression. The return value is a :class:`~.Compiled` object. Calling ``str()`` or ``unicode()`` on the returned value will yield a string representation of the result. The :class:`~.Compiled` object also can return a dictionary of bind parameter names and values using the ``params`` accessor. :param bind: An ``Engine`` or ``Connection`` from which a ``Compiled`` will be acquired. This argument takes precedence over this :class:`_expression.ClauseElement`'s bound engine, if any. :param column_keys: Used for INSERT and UPDATE statements, a list of column names which should be present in the VALUES clause of the compiled statement. If ``None``, all columns from the target table object are rendered. :param dialect: A ``Dialect`` instance from which a ``Compiled`` will be acquired. This argument takes precedence over the `bind` argument as well as this :class:`_expression.ClauseElement` 's bound engine, if any. :param inline: Used for INSERT statements, for a dialect which does not support inline retrieval of newly generated primary key columns, will force the expression used to create the new primary key value to be rendered inline within the INSERT statement's VALUES clause. This typically refers to Sequence execution but may also refer to any server-side default generation function associated with a primary key `Column`. :param compile_kwargs: optional dictionary of additional parameters that will be passed through to the compiler within all "visit" methods. This allows any custom flag to be passed through to a custom compilation construct, for example. It is also used for the case of passing the ``literal_binds`` flag through:: from sqlalchemy.sql import table, column, select t = table('t', column('x')) s = select([t]).where(t.c.x == 5) print(s.compile(compile_kwargs={"literal_binds": True})) .. versionadded:: 0.9.0 .. seealso:: :ref:`faq_sql_expression_string` """ if not dialect: if bind: dialect = bind.dialect elif self.bind: dialect = self.bind.dialect bind = self.bind else: dialect = default.StrCompileDialect() return self._compiler(dialect, bind=bind, **kw) def _compiler(self, dialect, **kw): """Return a compiler appropriate for this ClauseElement, given a Dialect.""" return dialect.statement_compiler(dialect, self, **kw) def __str__(self): if util.py3k: return str(self.compile()) else: return unicode(self.compile()).encode( # noqa "ascii", "backslashreplace" ) # noqa @util.deprecated( "0.9", "The :meth:`_expression.ClauseElement.__and__` " "method is deprecated and will " "be removed in a future release. Conjunctions should only be " "used from a :class:`_expression.ColumnElement` subclass, e.g. " ":meth:`_expression.ColumnElement.__and__`.", ) def __and__(self, other): """'and' at the ClauseElement level.""" return and_(self, other) @util.deprecated( "0.9", "The :meth:`_expression.ClauseElement.__or__` " "method is deprecated and will " "be removed in a future release. Conjunctions should only be " "used from a :class:`_expression.ColumnElement` subclass, e.g. " ":meth:`_expression.ColumnElement.__or__`.", ) def __or__(self, other): """'or' at the ClauseElement level.""" return or_(self, other) def __invert__(self): if hasattr(self, "negation_clause"): return self.negation_clause else: return self._negate() def _negate(self): return UnaryExpression( self.self_group(against=operators.inv), operator=operators.inv, negate=None, ) def __bool__(self): raise TypeError("Boolean value of this clause is not defined") __nonzero__ = __bool__ def __repr__(self): friendly = self.description if friendly is None: return object.__repr__(self) else: return "<%s.%s at 0x%x; %s>" % ( self.__module__, self.__class__.__name__, id(self), friendly, ) class ColumnElement(operators.ColumnOperators, ClauseElement): """Represent a column-oriented SQL expression suitable for usage in the "columns" clause, WHERE clause etc. of a statement. While the most familiar kind of :class:`_expression.ColumnElement` is the :class:`_schema.Column` object, :class:`_expression.ColumnElement` serves as the basis for any unit that may be present in a SQL expression, including the expressions themselves, SQL functions, bound parameters, literal expressions, keywords such as ``NULL``, etc. :class:`_expression.ColumnElement` is the ultimate base class for all such elements. A wide variety of SQLAlchemy Core functions work at the SQL expression level, and are intended to accept instances of :class:`_expression.ColumnElement` as arguments. These functions will typically document that they accept a "SQL expression" as an argument. What this means in terms of SQLAlchemy usually refers to an input which is either already in the form of a :class:`_expression.ColumnElement` object, or a value which can be **coerced** into one. The coercion rules followed by most, but not all, SQLAlchemy Core functions with regards to SQL expressions are as follows: * a literal Python value, such as a string, integer or floating point value, boolean, datetime, ``Decimal`` object, or virtually any other Python object, will be coerced into a "literal bound value". This generally means that a :func:`.bindparam` will be produced featuring the given value embedded into the construct; the resulting :class:`.BindParameter` object is an instance of :class:`_expression.ColumnElement`. The Python value will ultimately be sent to the DBAPI at execution time as a parameterized argument to the ``execute()`` or ``executemany()`` methods, after SQLAlchemy type-specific converters (e.g. those provided by any associated :class:`.TypeEngine` objects) are applied to the value. * any special object value, typically ORM-level constructs, which feature a method called ``__clause_element__()``. The Core expression system looks for this method when an object of otherwise unknown type is passed to a function that is looking to coerce the argument into a :class:`_expression.ColumnElement` expression. The ``__clause_element__()`` method, if present, should return a :class:`_expression.ColumnElement` instance. The primary use of ``__clause_element__()`` within SQLAlchemy is that of class-bound attributes on ORM-mapped classes; a ``User`` class which contains a mapped attribute named ``.name`` will have a method ``User.name.__clause_element__()`` which when invoked returns the :class:`_schema.Column` called ``name`` associated with the mapped table. * The Python ``None`` value is typically interpreted as ``NULL``, which in SQLAlchemy Core produces an instance of :func:`.null`. A :class:`_expression.ColumnElement` provides the ability to generate new :class:`_expression.ColumnElement` objects using Python expressions. This means that Python operators such as ``==``, ``!=`` and ``<`` are overloaded to mimic SQL operations, and allow the instantiation of further :class:`_expression.ColumnElement` instances which are composed from other, more fundamental :class:`_expression.ColumnElement` objects. For example, two :class:`.ColumnClause` objects can be added together with the addition operator ``+`` to produce a :class:`.BinaryExpression`. Both :class:`.ColumnClause` and :class:`.BinaryExpression` are subclasses of :class:`_expression.ColumnElement`:: >>> from sqlalchemy.sql import column >>> column('a') + column('b') >>> print(column('a') + column('b')) a + b .. seealso:: :class:`_schema.Column` :func:`_expression.column` """ __visit_name__ = "column_element" primary_key = False foreign_keys = [] _proxies = () _label = None """The named label that can be used to target this column in a result set. This label is almost always the label used when rendering AS