raise NotImplementedError()
- def get_rowcount(self):
- """Return the count of rows updated/deleted for an UPDATE/DELETE statement."""
-
- raise NotImplementedError()
-
def should_autocommit_compiled(self, compiled):
"""return True if the given Compiled object refers to a "committable" statement."""
self.__echo = context.engine._should_log_info
if context.returns_rows:
self._init_metadata()
- self._rowcount = None
else:
- self._rowcount = context.get_rowcount()
self.close()
@property
def rowcount(self):
- if self._rowcount is not None:
- return self._rowcount
- else:
- return self.context.get_rowcount()
+ return self.context.get_rowcount()
@property
def lastrowid(self):
return self.context.out_parameters
def _init_metadata(self):
- self.__props = {}
- self._key_cache = self._create_key_cache()
+ self._props = util.PopulateDict(None)
+ self._props.creator = self.__key_fallback()
self.keys = []
metadata = self.cursor.description
rec = (type_, type_.dialect_impl(self.dialect).result_processor(self.dialect), i)
- if self.__props.setdefault(name.lower(), rec) is not rec:
- self.__props[name.lower()] = (type_, self.__ambiguous_processor(name), 0)
+ if self._props.setdefault(name.lower(), rec) is not rec:
+ self._props[name.lower()] = (type_, self.__ambiguous_processor(name), 0)
# store the "origname" if we truncated (sqlite only)
if origname:
- if self.__props.setdefault(origname.lower(), rec) is not rec:
- self.__props[origname.lower()] = (type_, self.__ambiguous_processor(origname), 0)
+ if self._props.setdefault(origname.lower(), rec) is not rec:
+ self._props[origname.lower()] = (type_, self.__ambiguous_processor(origname), 0)
self.keys.append(colname)
- self.__props[i] = rec
+ self._props[i] = rec
if obj:
for o in obj:
- self.__props[o] = rec
+ self._props[o] = rec
if self.__echo:
self.context.engine.logger.debug(
"Col " + repr(tuple(x[0] for x in metadata)))
-
- def _create_key_cache(self):
- # local copies to avoid circular ref against 'self'
- props = self.__props
- def lookup_key(key):
- """Given a key, which could be a ColumnElement, string, etc.,
- matches it to the appropriate key we got from the result set's
- metadata; then cache it locally for quick re-access."""
-
+
+ def __key_fallback(self):
+ # create a closure without 'self' to avoid circular references
+ props = self._props
+
+ def fallback(key):
if isinstance(key, basestring):
key = key.lower()
- try:
- rec = props[key]
- except KeyError:
- # fallback for targeting a ColumnElement to a textual expression
- # this is a rare use case which only occurs when matching text()
- # constructs to ColumnElements
- if isinstance(key, expression.ColumnElement):
- if key._label and key._label.lower() in props:
- return props[key._label.lower()]
- elif hasattr(key, 'name') and key.name.lower() in props:
- return props[key.name.lower()]
- raise exc.NoSuchColumnError("Could not locate column in row for column '%s'" % (str(key)))
-
- return rec
- return util.PopulateDict(lookup_key)
+ if key in props:
+ return props[key]
+
+ # fallback for targeting a ColumnElement to a textual expression
+ # this is a rare use case which only occurs when matching text()
+ # constructs to ColumnElements
+ if isinstance(key, expression.ColumnElement):
+ if key._label and key._label.lower() in props:
+ return props[key._label.lower()]
+ elif hasattr(key, 'name') and key.name.lower() in props:
+ return props[key.name.lower()]
+
+ raise exc.NoSuchColumnError("Could not locate column in row for column '%s'" % (str(key)))
+ return fallback
def __ambiguous_processor(self, colname):
def process(value):
try:
# _key_cache uses __missing__ in 2.5, so not much alternative
# to catching KeyError
- self._key_cache[key]
+ self._props[key]
return True
except KeyError:
return False
def _get_col(self, row, key):
try:
- type_, processor, index = self._key_cache[key]
+ type_, processor, index = self._props[key]
except TypeError:
# the 'slice' use case is very infrequent,
# so we use an exception catch to reduce conditionals in _get_col
def _get_col(self, row, key):
try:
- rec = self._key_cache[key]
+ rec = self._props[key]
return row[rec[2]]
except TypeError:
# the 'slice' use case is very infrequent,
def should_autocommit_text(self, statement):
return AUTOCOMMIT_REGEXP.match(statement)
-
def create_cursor(self):
return self._connection.connection.cursor()
return self._rowcount
else:
return self.cursor.rowcount
-
+
def supports_sane_rowcount(self):
return self.dialect.supports_sane_rowcount
self._connection_record = None
class _CursorFairy(object):
- __slots__ = '__parent', 'cursor'
+ __slots__ = '__parent', 'cursor', 'execute'
def __init__(self, parent, cursor):
self.__parent = parent
self.cursor = cursor
-
+ self.execute = cursor.execute
+
def invalidate(self, e=None):
self.__parent.invalidate(e=e)
functions.user: 'USER'
}
+
+class _CompileLabel(object):
+ """lightweight label object which acts as an expression._Label."""
+
+ __metaclass__ = sql._FigureVisitName
+ __visit_name__ = 'label'
+ __slots__ = 'element', 'name'
+
+ def __init__(self, col, name):
+ self.element = col
+ self.name = name
+
+ @property
+ def quote(self):
+ return self.element.quote
+
class DefaultCompiler(engine.Compiled):
"""Default implementation of Compiled.
self.string = self.process(self.statement)
def process(self, obj, **kwargs):
- meth = getattr(self, "visit_%s" % obj.__visit_name__, None)
- if meth:
- return meth(obj, **kwargs)
+ return obj._compiler_dispatch(self, **kwargs)
def is_subquery(self):
return self.stack and len(self.stack) > 1 and self.stack[-1].get('from')
if result_map is not None:
result_map[name.lower()] = (name, (column, ), column.type)
-
- if getattr(column, "is_literal", False):
+
+ if column.is_literal:
name = self.escape_literal_column(name)
else:
name = self.preparer.quote(name, column.quote)
if column.table is None or not column.table.named_with_column:
return name
else:
- if getattr(column.table, 'schema', None):
+ if column.table.schema:
schema_prefix = self.preparer.quote(column.table.schema, column.table.quote_schema) + '.'
else:
schema_prefix = ''
if isinstance(column, sql._Label):
return column
- if select.use_labels and getattr(column, '_label', None):
- return column.label(column._label)
+ if select.use_labels and column._label:
+ return _CompileLabel(column, column._label)
if \
asfrom and \
not column.is_literal and \
column.table is not None and \
not isinstance(column.table, sql.Select):
- return column.label(column.name)
+ return _CompileLabel(column, column.name)
elif not isinstance(column, (sql._UnaryExpression, sql._TextClause, sql._BindParamClause)) and (not hasattr(column, 'name') or isinstance(column, sql._Function)):
- return column.label(column.anon_label)
+ return _CompileLabel(column, column.anon_label)
else:
return column
"""True if ``col`` is an instance of ``ColumnElement``."""
return isinstance(col, ColumnElement)
-
class _FigureVisitName(type):
def __init__(cls, clsname, bases, dict):
if not '__visit_name__' in cls.__dict__:
x = m.group(1)
x = re.sub(r'(?!^)[A-Z]', lambda m:'_'+m.group(0).lower(), x)
cls.__visit_name__ = x.lower()
+
+ # set up an optimized visit dispatch function
+ # for use by the compiler
+ visit_name = cls.__dict__["__visit_name__"]
+ if isinstance(visit_name, str):
+ func_text = "def _compiler_dispatch(self, visitor, **kw):\n"\
+ " return visitor.visit_%s(self, **kw)" % visit_name
+ else:
+ func_text = "def _compiler_dispatch(self, visitor, **kw):\n"\
+ " return getattr(visitor, 'visit_%s' % self.__visit_name__)(self, **kw)"
+
+ env = locals().copy()
+ exec func_text in env
+ cls._compiler_dispatch = env['_compiler_dispatch']
+
super(_FigureVisitName, cls).__init__(clsname, bases, dict)
class ClauseElement(object):
named_with_column = False
_hide_froms = []
quote = None
+ schema = None
def _get_from_objects(self, **modifiers):
return []
def __init__(self, name, element, type_=None):
while isinstance(element, _Label):
element = element.element
- self.name = name or "{ANON %d %s}" % (id(self), getattr(element, 'name', 'anon'))
- self.element = element.self_group(against=operators.as_)
- self.type = sqltypes.to_instance(type_ or getattr(element, 'type', None))
+ self.name = self.key = self._label = name or "{ANON %d %s}" % (id(self), getattr(element, 'name', 'anon'))
+ self._element = element
+ self._type = type_
self.quote = element.quote
-
- @property
- def key(self):
- return self.name
-
- @property
- def _label(self):
- return self.name
-
+
+ @util.memoized_property
+ def type(self):
+ return sqltypes.to_instance(self._type or getattr(element, 'type', None))
+
+ @util.memoized_property
+ def element(self):
+ return self._element.self_group(against=operators.as_)
+
def _proxy_attr(name):
get = attrgetter(name)
def attr(self):
"""
named_with_column = True
-
+
def __init__(self, name, *columns):
super(TableClause, self).__init__()
self.name = self.fullname = name
def cursor(self):
return MockCursor()
class MockCursor(object):
+ def execute(self, *args, **kw):
+ pass
def close(self):
pass
mock_dbapi = MockDBAPI()
def test_update(self):
t1.update().compile()
- @profiling.function_call_count(228, versions={'2.4':131})
+ @profiling.function_call_count(211, versions={'2.4':131})
def test_select(self):
s = select([t1], t1.c.c2==t2.c.c1)
s.compile()
def test_profile_2_insert(self):
self.test_baseline_2_insert()
- @profiling.function_call_count(4662, {'2.4': 2557})
+ @profiling.function_call_count(4178, {'2.4': 2557})
def test_profile_3_properties(self):
self.test_baseline_3_properties()
- @profiling.function_call_count(17098, {'2.4': 10549})
+ @profiling.function_call_count(15869, {'2.4': 10549})
def test_profile_4_expressions(self):
self.test_baseline_4_expressions()
def test_profile_6_editing(self):
self.test_baseline_6_editing()
- @profiling.function_call_count(3614, {'2.4': 2198})
+ @profiling.function_call_count(3276, {'2.4': 2198})
def test_profile_7_multiview(self):
self.test_baseline_7_multiview()
def test_profile_2_insert(self):
self.test_baseline_2_insert()
- @profiling.function_call_count(8097)
+ @profiling.function_call_count(7305)
def test_profile_3_properties(self):
self.test_baseline_3_properties()
- @profiling.function_call_count(28211)
+ @profiling.function_call_count(25760)
def test_profile_4_expressions(self):
self.test_baseline_4_expressions()
def test_profile_5_aggregates(self):
self.test_baseline_5_aggregates()
- @profiling.function_call_count(3985)
+ @profiling.function_call_count(3752)
def test_profile_6_editing(self):
self.test_baseline_6_editing()
stats.print_stats(limit)
else:
stats.print_stats()
-
os.unlink(filename)
return result
return _function_named(profiled, fn.__name__)
if testlib.config.options.verbose:
stats.sort_stats('calls', 'cumulative')
stats.print_stats()
-
+ #stats.print_callers()
deviance = int(count * variance)
if (calls < (count - deviance) or
calls > (count + deviance)):