aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py')
-rwxr-xr-xlib/python2.7/site-packages/SQLAlchemy-0.7.0-py2.7-linux-x86_64.egg/sqlalchemy/sql/compiler.py1793
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)]]