# sql/elements.py # Copyright (C) 2005-2017 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:`.ClauseElement`, :class:`.ColumnElement`, and derived classes. """ from __future__ import unicode_literals from .. import util, exc, inspection from . import type_api from . import operators from .visitors import Visitable, cloned_traverse, traverse from .annotation import Annotated import itertools from .base import Executable, PARSE_AUTOCOMMIT, Immutable, NO_ARG from .base import _generative import numbers import re import operator def _clone(element, **kw): return element._clone() def collate(expression, collation): """Return the clause ``expression COLLATE collation``. e.g.:: collate(mycolumn, 'utf8_bin') produces:: mycolumn COLLATE utf8_bin """ expr = _literal_as_binds(expression) return BinaryExpression( expr, _literal_as_text(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:`.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:`.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:`.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:`.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:`.ClauseElement` objects (such as strings, ints, dates, etc.) are used in a comparison operation with a :class:`.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:`.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 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:`.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:`bindparam()` elements replaced. Same functionality as ``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:`bindparam()` elements replaced. Returns a copy of this ClauseElement with :func:`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 ClauseElement to the given 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:`.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:`.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:`.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:`.select` constructs when placed into the FROM clause of another :func:`.select`. (Note that subqueries should be normally created using the :meth:`.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:`.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:`.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:`.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('ascii', 'backslashreplace') def __and__(self, other): """'and' at the ClauseElement level. .. deprecated:: 0.9.5 - conjunctions are intended to be at the :class:`.ColumnElement`. level """ return and_(self, other) def __or__(self, other): """'or' at the ClauseElement level. .. deprecated:: 0.9.5 - conjunctions are intended to be at the :class:`.ColumnElement`. 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:`.ColumnElement` is the :class:`.Column` object, :class:`.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:`.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:`.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:`.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:`.ColumnElement`. The Python value will ultimately be sent to the DBAPI at execution time as a paramterized 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:`.ColumnElement` expression. The ``__clause_element__()`` method, if present, should return a :class:`.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:`.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:`.ColumnElement` provides the ability to generate new :class:`.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:`.ColumnElement` instances which are composed from other, more fundamental :class:`.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:`.ColumnElement`:: >>> from sqlalchemy.sql import column >>> column('a') + column('b') >>> print column('a') + column('b') a + b .. seealso:: :class:`.Column` :func:`.expression.column` """ __visit_name__ = 'column' primary_key = False foreign_keys = [] _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