]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- make sure negative row indexes are based on the size of the
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 30 Mar 2016 21:27:53 +0000 (17:27 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 30 Mar 2016 21:27:53 +0000 (17:27 -0400)
number of columns we're actually reporting on
- add more tests for negative row index
- changelog/migration

doc/build/changelog/changelog_11.rst
doc/build/changelog/migration_11.rst
lib/sqlalchemy/engine/result.py
test/engine/test_execute.py

index 2a0e609b62143e2796444429a3079e1bbaa2dbe4..18d6d1f7495ed18ae096aa081cd63a4d44c8229f 100644 (file)
 .. 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
index 64ed2d9e25bc7631b4731f3a50465aff8023d7d4..6f0da37809c48b46a4c391dc0933808e5f20198f 100644 (file)
@@ -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
index afa6b4dcaffbe95343b3bddb7967291173374927..0333d9ec238fd2e4b7a6f6365e873bcc2db43e17 100644 (file)
@@ -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
             ])
 
index aadd170f38a5efb2e70861cc9285ce449114f5c1..66903bef3c10e818669b5828b44a06cd4db72357 100644 (file)
@@ -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):