diff options
Diffstat (limited to 'lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py')
-rwxr-xr-x | lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py | 1793 |
1 files changed, 0 insertions, 1793 deletions
diff --git a/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py b/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py deleted file mode 100755 index 829adeba..00000000 --- a/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py +++ /dev/null @@ -1,1793 +0,0 @@ -# sql/compiler.py -# Copyright (C) 2005-2011 the SQLAlchemy authors and contributors <see AUTHORS file> -# -# 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:`~sqlalchemy.sql.compiler.SQLCompiler` - renders SQL -strings - -:class:`~sqlalchemy.sql.compiler.DDLCompiler` - renders DDL -(data definition language) strings - -:class:`~sqlalchemy.sql.compiler.GenericTypeCompiler` - renders -type specification strings. - -To generate user-defined SQL strings, see -:module:`~sqlalchemy.ext.compiler`. - -""" - -import re -from sqlalchemy import schema, engine, util, exc -from sqlalchemy.sql import operators, functions, util as sql_util, \ - visitors -from sqlalchemy.sql import expression as sql -import decimal - -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) -ILLEGAL_INITIAL_CHARACTERS = set([str(x) for x in xrange(0, 10)]).union(['$']) - -BIND_PARAMS = re.compile(r'(?<![:\w\$\x5c]):([\w\$]+)(?![:\w\$])', re.UNICODE) -BIND_PARAMS_ESC = re.compile(r'\x5c(:[\w\$]+)(?![:\w\$])', re.UNICODE) - -BIND_TEMPLATES = { - 'pyformat':"%%(%(name)s)s", - 'qmark':"?", - 'format':"%%s", - 'numeric':":%(position)s", - 'named':":%(name)s" -} - - -OPERATORS = { - # binary - operators.and_ : ' AND ', - operators.or_ : ' OR ', - operators.add : ' + ', - operators.mul : ' * ', - operators.sub : ' - ', - # Py2K - operators.div : ' / ', - # end Py2K - operators.mod : ' % ', - operators.truediv : ' / ', - operators.neg : '-', - operators.lt : ' < ', - operators.le : ' <= ', - operators.ne : ' != ', - operators.gt : ' > ', - operators.ge : ' >= ', - operators.eq : ' = ', - operators.concat_op : ' || ', - operators.between_op : ' BETWEEN ', - operators.match_op : ' 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 ', - - # modifiers - operators.desc_op : ' DESC', - operators.asc_op : ' ASC', - operators.nullsfirst_op : ' NULLS FIRST', - operators.nullslast_op : ' NULLS LAST', -} - -FUNCTIONS = { - functions.coalesce : 'coalesce%(expr)s', - 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%(expr)s', - functions.sysdate: 'sysdate', - functions.session_user :'SESSION_USER', - functions.user: 'USER' -} - -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 = { - sql.CompoundSelect.UNION : 'UNION', - sql.CompoundSelect.UNION_ALL : 'UNION ALL', - sql.CompoundSelect.EXCEPT : 'EXCEPT', - sql.CompoundSelect.EXCEPT_ALL : 'EXCEPT ALL', - sql.CompoundSelect.INTERSECT : 'INTERSECT', - sql.CompoundSelect.INTERSECT_ALL : 'INTERSECT ALL' -} - -class _CompileLabel(visitors.Visitable): - """lightweight label object which acts as an expression._Label.""" - - __visit_name__ = 'label' - __slots__ = 'element', 'name' - - def __init__(self, col, name): - self.element = col - self.name = name - - @property - def type(self): - return self.element.type - - @property - def quote(self): - return self.element.quote - -class SQLCompiler(engine.Compiled): - """Default implementation of Compiled. - - Compiles ClauseElements into SQL strings. Uses a similar visit - paradigm as visitors.ClauseVisitor but implements its own traversal. - - """ - - extract_map = EXTRACT_MAP - - compound_keywords = COMPOUND_KEYWORDS - - # class-level defaults which can be set at the instance - # level to define if this Compiled instance represents - # INSERT/UPDATE/DELETE - isdelete = isinsert = isupdate = False - - # holds the "returning" collection of columns if - # the statement is CRUD and defines returning columns - # either implicitly or explicitly - returning = None - - # set to True classwide to generate RETURNING - # clauses before the VALUES or WHERE clause (i.e. MSSQL) - returning_precedes_values = 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 - ansi_bind_rules = False - - def __init__(self, dialect, statement, column_keys=None, - inline=False, **kwargs): - """Construct a new ``DefaultCompiler`` object. - - dialect - Dialect to be used - - statement - ClauseElement to be compiled - - column_keys - a list of column names to be compiled into an INSERT or UPDATE - statement. - - """ - 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 _BindParamClause - # instances. - self.binds = {} - - # a dictionary of _BindParamClause 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_map = {} - - # true if the paramstyle is positional - self.positional = dialect.positional - if self.positional: - self.positiontup = [] - self.bindtemplate = BIND_TEMPLATES[dialect.paramstyle] - - # an IdentifierPreparer that formats the quoting of identifiers - self.preparer = dialect.identifier_preparer - 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 = util.PopulateDict(self._process_anon) - - # a map which tracks "truncated" names based on - # dialect.label_length or dialect.max_identifier_length - self.truncated_names = {} - engine.Compiled.__init__(self, dialect, statement, **kwargs) - - - - @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): - """return a dictionary of bind parameter keys and values""" - - if params: - pd = {} - for bindparam, name in self.bind_names.iteritems(): - if bindparam.key in params: - pd[name] = params[bindparam.key] - elif name in params: - pd[name] = params[name] - elif bindparam.required: - if _group_number: - raise exc.InvalidRequestError( - "A value is required for bind parameter %r, " - "in parameter group %d" % - (bindparam.key, _group_number)) - else: - raise exc.InvalidRequestError( - "A value is required for bind parameter %r" - % bindparam.key) - elif bindparam.callable: - pd[name] = bindparam.callable() - else: - pd[name] = bindparam.value - return pd - else: - pd = {} - for bindparam in self.bind_names: - if bindparam.callable: - pd[self.bind_names[bindparam]] = bindparam.callable() - else: - pd[self.bind_names[bindparam]] = bindparam.value - return pd - - params = property(construct_params, doc=""" - Return the bind params for this compiled object. - - """) - - 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(self, label, result_map=None, - within_label_clause=False, - within_columns_clause=False, **kw): - # only render labels within the columns clause - # or ORDER BY clause of a select. dialect-specific compilers - # can modify this behavior. - if within_columns_clause and not within_label_clause: - if isinstance(label.name, sql._generated_label): - labelname = self._truncated_identifier("colident", label.name) - else: - labelname = label.name - - if result_map is not None: - result_map[labelname.lower()] = \ - (label.name, (label, label.element, labelname),\ - 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) - else: - return label.element._compiler_dispatch(self, - within_columns_clause=False, - **kw) - - def visit_column(self, column, result_map=None, **kwargs): - name = column.name - if name is None: - raise exc.CompileError("Cannot compile Column object until " - "it's 'name' is assigned.") - - is_literal = column.is_literal - if not is_literal and isinstance(name, sql._generated_label): - name = self._truncated_identifier("colident", name) - - if result_map is not None: - result_map[name.lower()] = (name, (column, ), column.type) - - if is_literal: - name = self.escape_literal_column(name) - else: - name = self.preparer.quote(name, column.quote) - - table = column.table - if table is None or not table.named_with_column: - return name - else: - if table.schema: - schema_prefix = self.preparer.quote_schema( - table.schema, - table.quote_schema) + '.' - else: - schema_prefix = '' - tablename = table.name - if isinstance(tablename, sql._generated_label): - tablename = self._truncated_identifier("alias", tablename) - - return schema_prefix + \ - self.preparer.quote(tablename, table.quote) + \ - "." + name - - def escape_literal_column(self, text): - """provide escaping for the literal_column() construct.""" - - # TODO: some dialects might need different behavior here - return text.replace('%', '%%') - - def visit_fromclause(self, fromclause, **kwargs): - return fromclause.name - - def visit_index(self, index, **kwargs): - return index.name - - def visit_typeclause(self, typeclause, **kwargs): - return self.dialect.type_compiler.process(typeclause.type) - - def post_process_text(self, text): - return text - - def visit_textclause(self, textclause, **kwargs): - if textclause.typemap is not None: - for colname, type_ in textclause.typemap.iteritems(): - self.result_map[colname.lower()] = (colname, None, type_) - - def do_bindparam(m): - name = m.group(1) - if name in textclause.bindparams: - return self.process(textclause.bindparams[name]) - else: - return self.bindparam_string(name) - - # 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_null(self, expr, **kw): - return 'NULL' - - def visit_true(self, expr, **kw): - return 'true' - - def visit_false(self, expr, **kw): - return 'false' - - def visit_clauselist(self, clauselist, **kwargs): - sep = clauselist.operator - if sep is None: - sep = " " - else: - sep = OPERATORS[clauselist.operator] - return sep.join( - s for s in - (c._compiler_dispatch(self, **kwargs) - for c in clauselist.clauses) - if s is not None) - - 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_cast(self, cast, **kwargs): - return "CAST(%s AS %s)" % \ - (cast.clause._compiler_dispatch(self, **kwargs), - cast.typeclause._compiler_dispatch(self, **kwargs)) - - def visit_over(self, over, **kwargs): - x ="%s OVER (" % over.func._compiler_dispatch(self, **kwargs) - if over.partition_by is not None: - x += "PARTITION BY %s" % \ - over.partition_by._compiler_dispatch(self, **kwargs) - if over.order_by is not None: - x += " " - if over.order_by is not None: - x += "ORDER BY %s" % \ - over.order_by._compiler_dispatch(self, **kwargs) - x += ")" - return x - - 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, result_map=None, **kwargs): - if result_map is not None: - result_map[func.name.lower()] = (func.name, None, func.type) - - disp = getattr(self, "visit_%s_func" % func.name.lower(), None) - if disp: - return disp(func, **kwargs) - else: - name = FUNCTIONS.get(func.__class__, func.name + "%(expr)s") - return ".".join(list(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): - 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=1, **kwargs): - entry = self.stack and self.stack[-1] or {} - self.stack.append({'from':entry.get('from', None), 'iswrapper':True}) - - 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)) - ) - - group_by = cs._group_by_clause._compiler_dispatch( - self, asfrom=asfrom, **kwargs) - if group_by: - text += " GROUP BY " + group_by - - text += self.order_by_clause(cs, **kwargs) - text += (cs._limit is not None or cs._offset is not None) and \ - self.limit_clause(cs) or "" - - self.stack.pop(-1) - if asfrom and parens: - return "(" + text + ")" - else: - return text - - def visit_unary(self, unary, **kw): - s = unary.element._compiler_dispatch(self, **kw) - if unary.operator: - s = OPERATORS[unary.operator] + s - if unary.modifier: - s = s + OPERATORS[unary.modifier] - return s - - def visit_binary(self, binary, **kw): - # don't allow "? = ?" to render - if self.ansi_bind_rules and \ - isinstance(binary.left, sql._BindParamClause) and \ - isinstance(binary.right, sql._BindParamClause): - kw['literal_binds'] = True - - return self._operator_dispatch(binary.operator, - binary, - lambda opstr: binary.left._compiler_dispatch(self, **kw) + - opstr + - binary.right._compiler_dispatch( - self, **kw), - **kw - ) - - def visit_like_op(self, binary, **kw): - escape = binary.modifiers.get("escape", None) - return '%s LIKE %s' % ( - binary.left._compiler_dispatch(self, **kw), - binary.right._compiler_dispatch(self, **kw)) \ - + (escape and - (' ESCAPE ' + self.render_literal_value(escape, None)) - or '') - - def visit_notlike_op(self, binary, **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 and - (' ESCAPE ' + self.render_literal_value(escape, None)) - or '') - - def visit_ilike_op(self, binary, **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 and - (' ESCAPE ' + self.render_literal_value(escape, None)) - or '') - - def visit_notilike_op(self, binary, **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 and - (' ESCAPE ' + self.render_literal_value(escape, None)) - or '') - - def _operator_dispatch(self, operator, element, fn, **kw): - if util.callable(operator): - disp = getattr(self, "visit_%s" % operator.__name__, None) - if disp: - return disp(element, **kw) - else: - return fn(OPERATORS[operator]) - else: - return fn(" " + operator + " ") - - def visit_bindparam(self, bindparam, within_columns_clause=False, - literal_binds=False, **kwargs): - - if literal_binds or \ - (within_columns_clause and \ - self.ansi_bind_rules): - if bindparam.value is None: - raise exc.CompileError("Bind parameter without a " - "renderable value not allowed here.") - 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: - raise exc.CompileError( - "Bind parameter '%s' conflicts with " - "unique bind parameter of the same name" % - bindparam.key - ) - elif getattr(existing, '_is_crud', False) or \ - getattr(bindparam, '_is_crud', False): - 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) - - def render_literal_bindparam(self, bindparam, **kw): - value = bindparam.value - processor = bindparam.type._cached_bind_processor(self.dialect) - if processor: - value = processor(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 paramters - on the target driver/database. - - This should be implemented by subclasses using the quoting services - of the DBAPI. - - """ - if isinstance(value, basestring): - value = value.replace("'", "''") - return "'%s'" % value - elif value is None: - return "NULL" - elif isinstance(value, (float, int, long)): - return repr(value) - elif isinstance(value, decimal.Decimal): - return str(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, sql._generated_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 % self.anon_map - - if len(anonname) > self.label_length: - 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 _process_anon(self, key): - (ident, derived) = key.split(' ', 1) - anonymous_counter = self.anon_map.get(derived, 1) - self.anon_map[derived] = anonymous_counter + 1 - return derived + "_" + str(anonymous_counter) - - def bindparam_string(self, name): - if self.positional: - self.positiontup.append(name) - return self.bindtemplate % { - 'name':name, 'position':len(self.positiontup)} - else: - return self.bindtemplate % {'name':name} - - def visit_alias(self, alias, asfrom=False, ashint=False, - fromhints=None, **kwargs): - if asfrom or ashint: - if isinstance(alias.name, sql._generated_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) + \ - " AS " + \ - self.preparer.format_alias(alias, alias_name) - - if fromhints and alias in fromhints: - hinttext = self.get_from_hint_text(alias, fromhints[alias]) - if hinttext: - ret += " " + hinttext - - return ret - else: - return alias.original._compiler_dispatch(self, **kwargs) - - def label_select_column(self, select, column, asfrom): - """label columns present in a select().""" - - if isinstance(column, sql._Label): - return column - - elif select is not None and select.use_labels and column._label: - return _CompileLabel(column, column._label) - - elif \ - asfrom and \ - isinstance(column, sql.ColumnClause) and \ - not column.is_literal and \ - column.table is not None and \ - not isinstance(column.table, sql.Select): - return _CompileLabel(column, sql._generated_label(column.name)) - elif not isinstance(column, - (sql._UnaryExpression, sql._TextClause)) \ - and (not hasattr(column, 'name') or \ - isinstance(column, sql.Function)): - return _CompileLabel(column, column.anon_label) - else: - return column - - def get_select_hint_text(self, byfroms): - return None - - def get_from_hint_text(self, table, text): - return None - - def visit_select(self, select, asfrom=False, parens=True, - iswrapper=False, fromhints=None, - compound_index=1, **kwargs): - - entry = self.stack and self.stack[-1] or {} - - existingfroms = entry.get('from', None) - - froms = select._get_display_froms(existingfroms) - - correlate_froms = set(sql._from_objects(*froms)) - - # TODO: might want to propagate existing froms for - # select(select(select)) where innermost select should correlate - # to outermost if existingfroms: correlate_froms = - # correlate_froms.union(existingfroms) - - self.stack.append({'from': correlate_froms, 'iswrapper' - : iswrapper}) - - if compound_index==1 and not entry or entry.get('iswrapper', False): - column_clause_args = {'result_map':self.result_map} - else: - column_clause_args = {} - - # the actual list of columns to print in the SELECT column list. - inner_columns = [ - c for c in [ - self.label_select_column(select, co, asfrom=asfrom).\ - _compiler_dispatch(self, - within_columns_clause=True, - **column_clause_args) - for co in util.unique_list(select.inner_columns) - ] - if c is not None - ] - - text = "SELECT " # we're off to a good start ! - - if select._hints: - byfrom = dict([ - (from_, hinttext % { - 'name':from_._compiler_dispatch( - self, ashint=True) - }) - for (from_, dialect), hinttext in - select._hints.iteritems() - if dialect in ('*', self.dialect.name) - ]) - hint_text = self.get_select_hint_text(byfrom) - if hint_text: - text += hint_text + " " - - if select._prefixes: - text += " ".join( - x._compiler_dispatch(self, **kwargs) - for x in select._prefixes) + " " - text += self.get_select_precolumns(select) - 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: - group_by = select._group_by_clause._compiler_dispatch( - self, **kwargs) - if group_by: - text += " GROUP BY " + group_by - - 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 is not None or select._offset is not None: - text += self.limit_clause(select) - if select.for_update: - text += self.for_update_clause(select) - - self.stack.pop(-1) - - if asfrom and parens: - return "(" + text + ")" - else: - return text - - def get_select_precolumns(self, select): - """Called when building a ``SELECT`` statement, position is just - before column list. - - """ - return select._distinct and "DISTINCT " or "" - - def order_by_clause(self, select, **kw): - 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): - if select.for_update: - return " FOR UPDATE" - else: - return "" - - def limit_clause(self, select): - text = "" - if select._limit is not None: - text += "\n LIMIT " + self.process(sql.literal(select._limit)) - if select._offset is not None: - if select._limit is None: - text += "\n LIMIT -1" - text += " OFFSET " + self.process(sql.literal(select._offset)) - return text - - def visit_table(self, table, asfrom=False, ashint=False, - fromhints=None, **kwargs): - if asfrom or ashint: - if getattr(table, "schema", None): - ret = self.preparer.quote_schema(table.schema, - table.quote_schema) + \ - "." + self.preparer.quote(table.name, - table.quote) - else: - ret = self.preparer.quote(table.name, table.quote) - if fromhints and table in fromhints: - hinttext = self.get_from_hint_text(table, fromhints[table]) - if hinttext: - ret += " " + hinttext - return ret - else: - return "" - - def visit_join(self, join, asfrom=False, **kwargs): - return ( - join.left._compiler_dispatch(self, asfrom=True, **kwargs) + - (join.isouter and " LEFT OUTER JOIN " or " JOIN ") + - join.right._compiler_dispatch(self, asfrom=True, **kwargs) + - " ON " + - join.onclause._compiler_dispatch(self, **kwargs) - ) - - def visit_insert(self, insert_stmt): - self.isinsert = True - colparams = self._get_colparams(insert_stmt) - - if not colparams and \ - not self.dialect.supports_default_values and \ - not self.dialect.supports_empty_insert: - raise exc.CompileError("The version of %s you are using does " - "not support empty inserts." % - self.dialect.name) - - preparer = self.preparer - supports_default_values = self.dialect.supports_default_values - - text = "INSERT" - - prefixes = [self.process(x) for x in insert_stmt._prefixes] - if prefixes: - text += " " + " ".join(prefixes) - - text += " INTO " + preparer.format_table(insert_stmt.table) - - if colparams or not supports_default_values: - text += " (%s)" % ', '.join([preparer.format_column(c[0]) - for c in colparams]) - - if self.returning or insert_stmt._returning: - self.returning = self.returning or insert_stmt._returning - returning_clause = self.returning_clause( - insert_stmt, self.returning) - - if self.returning_precedes_values: - text += " " + returning_clause - - if not colparams and supports_default_values: - text += " DEFAULT VALUES" - else: - text += " VALUES (%s)" % \ - ', '.join([c[1] for c in colparams]) - - if self.returning and not self.returning_precedes_values: - text += " " + returning_clause - - return text - - def visit_update(self, update_stmt): - self.stack.append({'from': set([update_stmt.table])}) - - self.isupdate = True - colparams = self._get_colparams(update_stmt) - - text = "UPDATE " + self.preparer.format_table(update_stmt.table) - - text += ' SET ' + \ - ', '.join( - self.preparer.quote(c[0].name, c[0].quote) + - '=' + c[1] - for c in colparams - ) - - if update_stmt._returning: - self.returning = update_stmt._returning - if self.returning_precedes_values: - text += " " + self.returning_clause( - update_stmt, update_stmt._returning) - - if update_stmt._whereclause is not None: - text += " WHERE " + self.process(update_stmt._whereclause) - - if self.returning and not self.returning_precedes_values: - text += " " + self.returning_clause( - update_stmt, update_stmt._returning) - - self.stack.pop(-1) - - return text - - def _create_crud_bind_param(self, col, value, required=False): - bindparam = sql.bindparam(col.key, value, - type_=col.type, required=required) - bindparam._is_crud = True - return bindparam._compiler_dispatch(self) - - - def _get_colparams(self, stmt): - """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. - - """ - - self.postfetch = [] - self.prefetch = [] - self.returning = [] - - # no parameters in the statement, no parameters in the - # compiled params - return binds for all columns - if self.column_keys is None and stmt.parameters is None: - return [ - (c, self._create_crud_bind_param(c, - None, required=True)) - for c in stmt.table.columns - ] - - required = object() - - # if we have statement parameters - set defaults in the - # compiled params - if self.column_keys is None: - parameters = {} - else: - parameters = dict((sql._column_as_key(key), required) - for key in self.column_keys - if not stmt.parameters or - key not in stmt.parameters) - - if stmt.parameters is not None: - for k, v in stmt.parameters.iteritems(): - parameters.setdefault(sql._column_as_key(k), v) - - # create a list of column assignment clauses as tuples - values = [] - - need_pks = self.isinsert and \ - not self.inline and \ - not stmt._returning - - implicit_returning = need_pks and \ - self.dialect.implicit_returning and \ - stmt.table.implicit_returning - - postfetch_lastrowid = need_pks and self.dialect.postfetch_lastrowid - - # iterating through columns at the top to maintain ordering. - # otherwise we might iterate through individual sets of - # "defaults", "primary key cols", etc. - for c in stmt.table.columns: - if c.key in parameters: - value = parameters[c.key] - if sql._is_literal(value): - value = self._create_crud_bind_param( - c, value, required=value is required) - elif c.primary_key and implicit_returning: - self.returning.append(c) - value = self.process(value.self_group()) - else: - self.postfetch.append(c) - value = self.process(value.self_group()) - values.append((c, value)) - - elif self.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: - if c.default is not None: - if c.default.is_sequence: - if self.dialect.supports_sequences and \ - (not c.default.optional or \ - not self.dialect.sequences_optional): - proc = self.process(c.default) - values.append((c, proc)) - self.returning.append(c) - elif c.default.is_clause_element: - values.append( - (c, - self.process(c.default.arg.self_group())) - ) - self.returning.append(c) - else: - values.append( - (c, self._create_crud_bind_param(c, None)) - ) - self.prefetch.append(c) - else: - self.returning.append(c) - else: - if c.default is not None or \ - c is stmt.table._autoincrement_column and ( - self.dialect.supports_sequences or - self.dialect.preexecute_autoincrement_sequences - ): - - values.append( - (c, self._create_crud_bind_param(c, None)) - ) - - self.prefetch.append(c) - - elif c.default is not None: - if c.default.is_sequence: - if self.dialect.supports_sequences and \ - (not c.default.optional or \ - not self.dialect.sequences_optional): - proc = self.process(c.default) - values.append((c, proc)) - if not c.primary_key: - self.postfetch.append(c) - elif c.default.is_clause_element: - values.append( - (c, self.process(c.default.arg.self_group())) - ) - - if not c.primary_key: - # dont add primary key column to postfetch - self.postfetch.append(c) - else: - values.append( - (c, self._create_crud_bind_param(c, None)) - ) - self.prefetch.append(c) - elif c.server_default is not None: - if not c.primary_key: - self.postfetch.append(c) - - elif self.isupdate: - if c.onupdate is not None and not c.onupdate.is_sequence: - if c.onupdate.is_clause_element: - values.append( - (c, self.process(c.onupdate.arg.self_group())) - ) - self.postfetch.append(c) - else: - values.append( - (c, self._create_crud_bind_param(c, None)) - ) - self.prefetch.append(c) - elif c.server_onupdate is not None: - self.postfetch.append(c) - return values - - def visit_delete(self, delete_stmt): - self.stack.append({'from': set([delete_stmt.table])}) - self.isdelete = True - - text = "DELETE FROM " + self.preparer.format_table(delete_stmt.table) - - if delete_stmt._returning: - self.returning = delete_stmt._returning - if self.returning_precedes_values: - text += " " + self.returning_clause( - delete_stmt, delete_stmt._returning) - - if delete_stmt._whereclause is not None: - text += " WHERE " + self.process(delete_stmt._whereclause) - - if self.returning and not self.returning_precedes_values: - text += " " + self.returning_clause( - delete_stmt, delete_stmt._returning) - - self.stack.pop(-1) - - 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 DDLCompiler(engine.Compiled): - - @util.memoized_property - def sql_compiler(self): - return self.dialect.statement_compiler(self.dialect, None) - - @property - def preparer(self): - return self.dialect.identifier_preparer - - 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.dialect.identifier_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_table(self, create): - table = create.element - preparer = self.dialect.identifier_preparer - - text = "\n" + " ".join(['CREATE'] + \ - table._prefixes + \ - ['TABLE', - preparer.format_table(table), - "("]) - separator = "\n" - - # if only one primary key, specify it along with the column - first_pk = False - for column in table.columns: - text += separator - separator = ", \n" - text += "\t" + self.get_column_specification( - column, - first_pk=column.primary_key and \ - not first_pk - ) - if column.primary_key: - first_pk = True - const = " ".join(self.process(constraint) \ - for constraint in column.constraints) - if const: - text += " " + const - - const = self.create_table_constraints(table) - if const: - text += ", \n\t" + const - - text += "\n)%s\n\n" % self.post_create_table(table) - return text - - def create_table_constraints(self, table): - - # 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) - - constraints.extend([c for c in table._sorted_constraints - if c is not table.primary_key]) - - 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 _index_identifier(self, ident): - if isinstance(ident, sql._generated_label): - max = self.dialect.max_index_name_length or \ - self.dialect.max_identifier_length - if len(ident) > max: - return ident[0:max - 8] + \ - "_" + util.md5_hex(ident)[-4:] - else: - return ident - else: - self.dialect.validate_identifier(ident) - return ident - - def visit_create_index(self, create): - index = create.element - preparer = self.preparer - text = "CREATE " - if index.unique: - text += "UNIQUE " - text += "INDEX %s ON %s (%s)" \ - % (preparer.quote(self._index_identifier(index.name), - index.quote), - preparer.format_table(index.table), - ', '.join(preparer.quote(c.name, c.quote) - for c in index.columns)) - return text - - def visit_drop_index(self, drop): - index = drop.element - return "\nDROP INDEX " + \ - self.preparer.quote( - self._index_identifier(index.name), index.quote) - - def visit_add_constraint(self, create): - preparer = self.preparer - return "ALTER TABLE %s ADD %s" % ( - self.preparer.format_table(create.element.table), - self.process(create.element) - ) - - 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 - return text - - def visit_drop_sequence(self, drop): - return "DROP SEQUENCE %s" % \ - self.preparer.format_sequence(drop.element) - - def visit_drop_constraint(self, drop): - preparer = self.preparer - return "ALTER TABLE %s DROP CONSTRAINT %s%s" % ( - self.preparer.format_table(drop.element.table), - self.preparer.format_constraint(drop.element), - 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) - default = self.get_column_default_string(column) - if default is not None: - colspec += " DEFAULT " + default - - if not column.nullable: - colspec += " NOT NULL" - return colspec - - 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, basestring): - return "'%s'" % column.server_default.arg - else: - return self.sql_compiler.process(column.server_default.arg) - else: - return None - - def visit_check_constraint(self, constraint): - text = "" - if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) - sqltext = sql_util.expression_as_ddl(constraint.sqltext) - text += "CHECK (%s)" % self.sql_compiler.process(sqltext) - text += self.define_constraint_deferrability(constraint) - return text - - def visit_column_check_constraint(self, constraint): - text = "CHECK (%s)" % constraint.sqltext - 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: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) - text += "PRIMARY KEY " - text += "(%s)" % ', '.join(self.preparer.quote(c.name, c.quote) - for c in constraint) - text += self.define_constraint_deferrability(constraint) - return text - - def visit_foreign_key_constraint(self, constraint): - preparer = self.dialect.identifier_preparer - text = "" - if constraint.name is not None: - text += "CONSTRAINT %s " % \ - preparer.format_constraint(constraint) - remote_table = list(constraint._elements.values())[0].column.table - text += "FOREIGN KEY(%s) REFERENCES %s (%s)" % ( - ', '.join(preparer.quote(f.parent.name, f.parent.quote) - for f in constraint._elements.values()), - self.define_constraint_remote_table( - constraint, remote_table, preparer), - ', '.join(preparer.quote(f.column.name, f.column.quote) - for f in constraint._elements.values()) - ) - 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): - text = "" - if constraint.name is not None: - text += "CONSTRAINT %s " % \ - self.preparer.format_constraint(constraint) - text += "UNIQUE (%s)" % ( - ', '.join(self.preparer.quote(c.name, c.quote) - 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" % constraint.ondelete - if constraint.onupdate is not None: - text += " ON UPDATE %s" % constraint.onupdate - 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" % constraint.initially - return text - - -class GenericTypeCompiler(engine.TypeCompiler): - def visit_CHAR(self, type_): - return "CHAR" + (type_.length and "(%d)" % type_.length or "") - - def visit_NCHAR(self, type_): - return "NCHAR" + (type_.length and "(%d)" % type_.length or "") - - def visit_FLOAT(self, type_): - return "FLOAT" - - def visit_REAL(self, type_): - return "REAL" - - def visit_NUMERIC(self, type_): - 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_): - return "DECIMAL" - - def visit_INTEGER(self, type_): - return "INTEGER" - - def visit_SMALLINT(self, type_): - return "SMALLINT" - - def visit_BIGINT(self, type_): - return "BIGINT" - - def visit_TIMESTAMP(self, type_): - return 'TIMESTAMP' - - def visit_DATETIME(self, type_): - return "DATETIME" - - def visit_DATE(self, type_): - return "DATE" - - def visit_TIME(self, type_): - return "TIME" - - def visit_CLOB(self, type_): - return "CLOB" - - def visit_NCLOB(self, type_): - return "NCLOB" - - def visit_VARCHAR(self, type_): - return "VARCHAR" + (type_.length and "(%d)" % type_.length or "") - - def visit_NVARCHAR(self, type_): - return "NVARCHAR" + (type_.length and "(%d)" % type_.length or "") - - def visit_BLOB(self, type_): - return "BLOB" - - def visit_BINARY(self, type_): - return "BINARY" + (type_.length and "(%d)" % type_.length or "") - - def visit_VARBINARY(self, type_): - return "VARBINARY" + (type_.length and "(%d)" % type_.length or "") - - def visit_BOOLEAN(self, type_): - return "BOOLEAN" - - def visit_TEXT(self, type_): - return "TEXT" - - def visit_large_binary(self, type_): - return self.visit_BLOB(type_) - - def visit_boolean(self, type_): - return self.visit_BOOLEAN(type_) - - def visit_time(self, type_): - return self.visit_TIME(type_) - - def visit_datetime(self, type_): - return self.visit_DATETIME(type_) - - def visit_date(self, type_): - return self.visit_DATE(type_) - - def visit_big_integer(self, type_): - return self.visit_BIGINT(type_) - - def visit_small_integer(self, type_): - return self.visit_SMALLINT(type_) - - def visit_integer(self, type_): - return self.visit_INTEGER(type_) - - def visit_real(self, type_): - return self.visit_REAL(type_) - - def visit_float(self, type_): - return self.visit_FLOAT(type_) - - def visit_numeric(self, type_): - return self.visit_NUMERIC(type_) - - def visit_string(self, type_): - return self.visit_VARCHAR(type_) - - def visit_unicode(self, type_): - return self.visit_VARCHAR(type_) - - def visit_text(self, type_): - return self.visit_TEXT(type_) - - def visit_unicode_text(self, type_): - return self.visit_TEXT(type_) - - def visit_enum(self, type_): - return self.visit_VARCHAR(type_) - - def visit_null(self, type_): - raise NotImplementedError("Can't generate DDL for the null type") - - def visit_type_decorator(self, type_): - return self.process(type_.type_engine(self.dialect)) - - def visit_user_defined(self, type_): - return type_.get_col_spec() - -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 - - def __init__(self, dialect, initial_quote='"', - final_quote=None, escape_quote='"', 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._strings = {} - - def _escape_identifier(self, value): - """Escape an identifier. - - Subclasses should override this to provide database-dependent - escaping behavior. - """ - - return value.replace(self.escape_quote, self.escape_to_quote) - - 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 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(unicode(value)) - or (lc_value != value)) - - def quote_schema(self, schema, force): - """Quote a schema. - - Subclasses should override this to provide database-dependent - quoting behavior. - """ - return self.quote(schema, force) - - def quote(self, ident, force): - 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_sequence(self, sequence, use_schema=True): - name = self.quote(sequence.name, sequence.quote) - if not self.omit_schema and use_schema and \ - sequence.schema is not None: - name = self.quote_schema(sequence.schema, sequence.quote) + \ - "." + name - return name - - def format_label(self, label, name=None): - return self.quote(name or label.name, label.quote) - - def format_alias(self, alias, name=None): - return self.quote(name or alias.name, alias.quote) - - def format_savepoint(self, savepoint, name=None): - return self.quote(name or savepoint.ident, savepoint.quote) - - def format_constraint(self, constraint): - return self.quote(constraint.name, constraint.quote) - - 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, table.quote) - if not self.omit_schema and use_schema \ - and getattr(table, "schema", None): - result = self.quote_schema(table.schema, table.quote_schema) + \ - "." + result - return result - - def format_column(self, column, use_table=False, - name=None, table_name=None): - """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=False, - name=table_name) + "." + \ - self.quote(name, column.quote) - else: - return self.quote(name, column.quote) - else: - # literal textual elements get stuck into ColumnClause alot, - # which shouldnt get quoted - - if use_table: - return self.format_table(column.table, - use_schema=False, 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. - - if not self.omit_schema and use_schema and \ - getattr(table, 'schema', None): - return (self.quote_schema(table.schema, table.quote_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)]] |