]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- properly handle negative indexes in RowProxy.__getitem__()
authorLele Gaifax <lele@metapensiero.it>
Thu, 28 Jan 2016 08:04:40 +0000 (09:04 +0100)
committerLele Gaifax <lele@metapensiero.it>
Thu, 28 Jan 2016 08:04:40 +0000 (09:04 +0100)
lib/sqlalchemy/cextension/resultproxy.c
lib/sqlalchemy/engine/result.py
test/engine/test_execute.py

index a87fe7b56542e4b439a7f421ce2cd0b2bcfb4dfe..331fae2b2a8bd1d256e0f5fdc60d1f56a65e4a50 100644 (file)
@@ -263,6 +263,8 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
 #if PY_MAJOR_VERSION < 3
     if (PyInt_CheckExact(key)) {
         index = PyInt_AS_LONG(key);
+        if (index < 0)
+            index += BaseRowProxy_length(self);
     } else
 #endif
 
@@ -271,6 +273,8 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
         if ((index == -1) && PyErr_Occurred())
             /* -1 can be either the actual value, or an error flag. */
             return NULL;
+        if (index < 0)
+            index += BaseRowProxy_length(self);
     } else if (PySlice_Check(key)) {
         values = PyObject_GetItem(self->row, key);
         if (values == NULL)
index 39f4fc50c903d58ad8ec23dcbab7fa3d306d0c5e..9208686e1bc1f881d849ebb5af6b5cf62378143f 100644 (file)
@@ -215,10 +215,17 @@ class ResultMetaData(object):
 
         self._keymap = {}
         if not _baserowproxy_usecext:
-            # keymap indexes by integer index...
+            # keymap indexes by integer index: this is only used
+            # in the pure Python BaseRowProxy.__getitem__
+            # implementation to avoid an expensive
+            # isinstance(key, util.int_types) in the most common
+            # case path
             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]))
+                for elem in raw
             ])
 
         # processors in key order for certain per-row
index 5ea5d3515f7d0e369020bd2a2d9b71b70fdc20fa..aadd170f38a5efb2e70861cc9285ce449114f5c1 100644 (file)
@@ -951,6 +951,25 @@ 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,
+                       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.requires.cextensions
     def test_row_c_sequence_check(self):
         import csv