diff options
-rw-r--r-- | CHANGES | 15 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/base.py | 182 | ||||
-rw-r--r-- | test/profiling/zoomark.py | 14 |
3 files changed, 106 insertions, 105 deletions
@@ -5,21 +5,24 @@ CHANGES 0.4.0beta7 ---------- -- Added partial index support for PostgreSQL. Use the postgres_where - keyword on the Index. +- Added partial index support for PostgreSQL. Use the postgres_where keyword + on the Index. - The IdentifierPreprarer's _requires_quotes test is now regex based. Any out-of-tree dialects that provide custom sets of legal_characters or illegal_initial_characters will need to move to regexes or override _requires_quotes. -- firebird has supports_sane_rowcount and supports_sane_multi_rowcount set +- Firebird has supports_sane_rowcount and supports_sane_multi_rowcount set to False due to ticket #370 (right way). -- fixed three- and multi-level select and deferred inheritance - loading (i.e. abc inheritance with no select_table), [ticket:795] +- Fixed three- and multi-level select and deferred inheritance loading + (i.e. abc inheritance with no select_table), [ticket:795] -- ident passed to id_chooser in shard.py always a list +- Ident passed to id_chooser in shard.py always a list. + +- The no-arg ResultProxy._row_processor() is now the class attribute + `_process_row`. 0.4.0beta6 ---------- diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index e385072ad..fa58657dc 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1188,6 +1188,89 @@ class Engine(Connectable): return self.pool.unique_connection() + +class RowProxy(object): + """Proxy a single cursor row for a parent ResultProxy. + + Mostly follows "ordered dictionary" behavior, mapping result + values to the string-based column name, the integer position of + the result in the row, as well as Column instances which can be + mapped to the original Columns that produced this result set (for + results that correspond to constructed SQL expressions). + """ + + def __init__(self, parent, row): + """RowProxy objects are constructed by ResultProxy objects.""" + + self.__parent = parent + self.__row = row + if self.__parent._ResultProxy__echo: + self.__parent.context.engine.logger.debug("Row " + repr(row)) + + def close(self): + """Close the parent ResultProxy.""" + + self.__parent.close() + + def __contains__(self, key): + return self.__parent._has_key(self.__row, key) + + def __len__(self): + return len(self.__row) + + def __iter__(self): + for i in xrange(len(self.__row)): + yield self.__parent._get_col(self.__row, i) + + def __eq__(self, other): + return ((other is self) or + (other == tuple([self.__parent._get_col(self.__row, key) + for key in xrange(len(self.__row))]))) + + def __repr__(self): + return repr(tuple(self)) + + def has_key(self, key): + """Return True if this RowProxy contains the given key.""" + + return self.__parent._has_key(self.__row, key) + + def __getitem__(self, key): + if isinstance(key, slice): + indices = key.indices(len(self)) + return tuple([self.__parent._get_col(self.__row, i) + for i in xrange(*indices)]) + else: + return self.__parent._get_col(self.__row, key) + + def __getattr__(self, name): + try: + return self.__parent._get_col(self.__row, name) + except KeyError, e: + raise AttributeError(e.args[0]) + + def items(self): + """Return a list of tuples, each tuple containing a key/value pair.""" + + return [(key, getattr(self, key)) for key in self.keys()] + + def keys(self): + """Return the list of keys as strings represented by this RowProxy.""" + + return self.__parent.keys + + def values(self): + """Return the values represented by this RowProxy as a list.""" + + return list(self) + + +class BufferedColumnRow(RowProxy): + def __init__(self, parent, row): + row = [ResultProxy._get_col(parent, row, i) for i in xrange(len(row))] + super(BufferedColumnRow, self).__init__(parent, row) + + class ResultProxy(object): """Wraps a DB-API cursor object to provide easier access to row columns. @@ -1210,10 +1293,7 @@ class ResultProxy(object): to obtain information from the underlying ExecutionContext. """ - def __ambiguous_processor(self, colname): - def process(value): - raise exceptions.InvalidRequestError("Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % colname) - return process + _process_row = RowProxy def __init__(self, context): """ResultProxy objects are constructed via the execute() method on SQLEngine.""" @@ -1222,7 +1302,6 @@ class ResultProxy(object): self.closed = False self.cursor = context.cursor self.__echo = context.engine._should_log_info - self._process_row = self._row_processor() if context.is_select(): self._init_metadata() self._rowcount = None @@ -1296,6 +1375,11 @@ class ResultProxy(object): return rec return util.PopulateDict(lookup_key) + def __ambiguous_processor(self, colname): + def process(value): + raise exceptions.InvalidRequestError("Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % colname) + return process + def close(self): """Close this ResultProxy, and the underlying DB-API cursor corresponding to the execution. @@ -1394,9 +1478,6 @@ class ResultProxy(object): def _fetchall_impl(self): return self.cursor.fetchall() - def _row_processor(self): - return RowProxy - def fetchall(self): """Fetch all rows, just like DB-API ``cursor.fetchall()``.""" @@ -1500,14 +1581,12 @@ class BufferedColumnResultProxy(ResultProxy): cx_Oracle LOB objects, but this behavior is known to exist in other DB-APIs as well (Pygresql, currently unsupported). """ + _process_row = BufferedColumnRow def _get_col(self, row, key): rec = self._key_cache[key] return row[rec[2]] - def _row_processor(self): - return BufferedColumnRow - def fetchall(self): l = [] while True: @@ -1528,87 +1607,6 @@ class BufferedColumnResultProxy(ResultProxy): l.append(row) return l -class RowProxy(object): - """Proxy a single cursor row for a parent ResultProxy. - - Mostly follows "ordered dictionary" behavior, mapping result - values to the string-based column name, the integer position of - the result in the row, as well as Column instances which can be - mapped to the original Columns that produced this result set (for - results that correspond to constructed SQL expressions). - """ - - def __init__(self, parent, row): - """RowProxy objects are constructed by ResultProxy objects.""" - - self.__parent = parent - self.__row = row - if self.__parent._ResultProxy__echo: - self.__parent.context.engine.logger.debug("Row " + repr(row)) - - def close(self): - """Close the parent ResultProxy.""" - - self.__parent.close() - - def __contains__(self, key): - return self.__parent._has_key(self.__row, key) - - def __len__(self): - return len(self.__row) - - def __iter__(self): - for i in range(0, len(self.__row)): - yield self.__parent._get_col(self.__row, i) - - def __eq__(self, other): - return ((other is self) or - (other == tuple([self.__parent._get_col(self.__row, key) - for key in range(len(self.__row))]))) - - def __repr__(self): - return repr(tuple([self.__parent._get_col(self.__row, key) - for key in range(len(self.__row))])) - - def has_key(self, key): - """Return True if this RowProxy contains the given key.""" - - return self.__parent._has_key(self.__row, key) - - def __getitem__(self, key): - if isinstance(key, slice): - indices = key.indices(len(self)) - return tuple([self.__parent._get_col(self.__row, i) - for i in range(*indices)]) - else: - return self.__parent._get_col(self.__row, key) - - def __getattr__(self, name): - try: - return self.__parent._get_col(self.__row, name) - except KeyError, e: - raise AttributeError(e.args[0]) - - def items(self): - """Return a list of tuples, each tuple containing a key/value pair.""" - - return [(key, getattr(self, key)) for key in self.keys()] - - def keys(self): - """Return the list of keys as strings represented by this RowProxy.""" - - return self.__parent.keys - - def values(self): - """Return the values represented by this RowProxy as a list.""" - - return list(self) - - -class BufferedColumnRow(RowProxy): - def __init__(self, parent, row): - row = [ResultProxy._get_col(parent, row, i) for i in xrange(len(row))] - super(BufferedColumnRow, self).__init__(parent, row) class SchemaIterator(schema.SchemaVisitor): """A visitor that can gather text into a buffer and execute the contents of the buffer.""" diff --git a/test/profiling/zoomark.py b/test/profiling/zoomark.py index 410c7756f..4feab2fc8 100644 --- a/test/profiling/zoomark.py +++ b/test/profiling/zoomark.py @@ -44,7 +44,7 @@ class ZooMarkTest(testing.AssertMixin): metadata.create_all() @testing.supported('postgres') - @profiling.profiled('populate', call_range=(4350, 4410), always=True) + @profiling.profiled('populate', call_range=(4340, 4400), always=True) def test_1a_populate(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -112,7 +112,7 @@ class ZooMarkTest(testing.AssertMixin): MotherID=bai_yun) @testing.supported('postgres') - @profiling.profiled('insert', call_range=(230, 250), always=True) + @profiling.profiled('insert', call_range=(230, 250), always=True) def test_2_insert(self): Animal = metadata.tables['Animal'] i = Animal.insert() @@ -120,7 +120,7 @@ class ZooMarkTest(testing.AssertMixin): tick = i.execute(Species='Tick', Name='Tick %d' % x, Legs=8) @testing.supported('postgres') - @profiling.profiled('properties', call_range=(3430, 3440), always=True) + @profiling.profiled('properties', call_range=(3420, 3430), always=True) def test_3_properties(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -143,7 +143,7 @@ class ZooMarkTest(testing.AssertMixin): ticks = fullobject(Animal.select(Animal.c.Species=='Tick')) @testing.supported('postgres') - @profiling.profiled('expressions', call_range=(12595, 12605), always=True) + @profiling.profiled('expressions', call_range=(12570, 12580), always=True) def test_4_expressions(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] @@ -197,7 +197,7 @@ class ZooMarkTest(testing.AssertMixin): assert len(fulltable(Animal.select(func.date_part('day', Animal.c.LastEscape) == 21))) == 1 @testing.supported('postgres') - @profiling.profiled('aggregates', call_range=(1220, 1230), always=True) + @profiling.profiled('aggregates', call_range=(1220, 1230), always=True) def test_5_aggregates(self): Animal = metadata.tables['Animal'] Zoo = metadata.tables['Zoo'] @@ -239,7 +239,7 @@ class ZooMarkTest(testing.AssertMixin): legs.sort() @testing.supported('postgres') - @profiling.profiled('editing', call_range=(1380, 1390), always=True) + @profiling.profiled('editing', call_range=(1370, 1380), always=True) def test_6_editing(self): Zoo = metadata.tables['Zoo'] @@ -268,7 +268,7 @@ class ZooMarkTest(testing.AssertMixin): assert SDZ['Founded'] == datetime.date(1935, 9, 13) @testing.supported('postgres') - @profiling.profiled('multiview', call_range=(3090, 3100), always=True) + @profiling.profiled('multiview', call_range=(3080, 3090), always=True) def test_7_multiview(self): Zoo = metadata.tables['Zoo'] Animal = metadata.tables['Animal'] |