From dd20f56bc9a32f0c3afc545ed519dce8b028792c Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 30 Mar 2016 17:27:53 -0400 Subject: [PATCH] - make sure negative row indexes are based on the size of the number of columns we're actually reporting on - add more tests for negative row index - changelog/migration --- doc/build/changelog/changelog_11.rst | 12 ++++++++++ doc/build/changelog/migration_11.rst | 15 ++++++++++++ lib/sqlalchemy/engine/result.py | 5 +++- test/engine/test_execute.py | 36 +++++++++++++++++----------- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 2a0e609b62..18d6d1f749 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,18 @@ .. changelog:: :version: 1.1.0b1 + .. change:: + :tags: feature, sql + :pullreq: github:231 + + Negative integer indexes are now accommodated by rows + returned from a :class:`.ResultProxy`. Pull request courtesy + Emanuele Gaifas. + + .. seealso:: + + :ref:`change_gh_231` + .. change:: :tags: feature, sqlite :tickets: 3629 diff --git a/doc/build/changelog/migration_11.rst b/doc/build/changelog/migration_11.rst index 64ed2d9e25..6f0da37809 100644 --- a/doc/build/changelog/migration_11.rst +++ b/doc/build/changelog/migration_11.rst @@ -1179,6 +1179,21 @@ string values:: :ticket:`3292` +.. _change_gh_231: + +Negative integer indexes accommodated by Core result rows +--------------------------------------------------------- + +The :class:`.RowProxy` object now accomodates single negative integer indexes +like a regular Python sequence, both in the pure Python and C-extension +version. Previously, negative values would only work in slices:: + + >>> from sqlalchemy import create_engine + >>> e = create_engine("sqlite://") + >>> row = e.execute("select 1, 2, 3").first() + >>> row[-1], row[-2], row[1], row[-2:2] + 3 2 2 (2,) + .. _change_3095: The ``Enum`` type now does in-Python validation of values diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py index afa6b4dcaf..0333d9ec23 100644 --- a/lib/sqlalchemy/engine/result.py +++ b/lib/sqlalchemy/engine/result.py @@ -220,11 +220,14 @@ class ResultMetaData(object): # implementation to avoid an expensive # isinstance(key, util.int_types) in the most common # case path + + len_raw = len(raw) + self._keymap.update([ (elem[0], (elem[3], elem[4], elem[0])) for elem in raw ] + [ - (elem[0] - num_ctx_cols, (elem[3], elem[4], elem[0])) + (elem[0] - len_raw, (elem[3], elem[4], elem[0])) for elem in raw ]) diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index aadd170f38..66903bef3c 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -951,24 +951,32 @@ class ResultProxyTest(fixtures.TestBase): {'key': (None, None, 0), 0: (None, None, 0)}) assert isinstance(row, collections.Sequence) - def test_rowproxy_getitem(self): - metadata = MetaData() - metadata.bind = 'sqlite://' - values = Table('users', metadata, + @testing.provide_metadata + def test_rowproxy_getitem_indexes_compiled(self): + values = Table('users', self.metadata, Column('key', String(10), primary_key=True), Column('value', String(10))) values.create() - values.insert().execute(key='One', value='Uno') - row = values.select().execute().fetchone() - - assert row['key'] == 'One' - assert row['value'] == 'Uno' - assert row[0] == 'One' - assert row[1] == 'Uno' - assert row[-2] == 'One' - assert row[-1] == 'Uno' - assert row[1:0:-1] == ('Uno',) + testing.db.execute(values.insert(), dict(key='One', value='Uno')) + row = testing.db.execute(values.select()).first() + eq_(row['key'], 'One') + eq_(row['value'], 'Uno') + eq_(row[0], 'One') + eq_(row[1], 'Uno') + eq_(row[-2], 'One') + eq_(row[-1], 'Uno') + eq_(row[1:0:-1], ('Uno',)) + + def test_rowproxy_getitem_indexes_raw(self): + row = testing.db.execute("select 'One' as key, 'Uno' as value").first() + eq_(row['key'], 'One') + eq_(row['value'], 'Uno') + eq_(row[0], 'One') + eq_(row[1], 'Uno') + eq_(row[-2], 'One') + eq_(row[-1], 'Uno') + eq_(row[1:0:-1], ('Uno',)) @testing.requires.cextensions def test_row_c_sequence_check(self): -- 2.47.2