summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2016-03-30 17:27:53 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2016-03-30 17:27:53 -0400
commitdd20f56bc9a32f0c3afc545ed519dce8b028792c (patch)
tree698d70dc7613979599910edb0b2815d98acbea6f
parent4df1e07bb9c43ed8d1927a90c75f3142beaa403a (diff)
downloadsqlalchemy-dd20f56bc9a32f0c3afc545ed519dce8b028792c.tar.gz
- 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
-rw-r--r--doc/build/changelog/changelog_11.rst12
-rw-r--r--doc/build/changelog/migration_11.rst15
-rw-r--r--lib/sqlalchemy/engine/result.py5
-rw-r--r--test/engine/test_execute.py36
4 files changed, 53 insertions, 15 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst
index 2a0e609b6..18d6d1f74 100644
--- a/doc/build/changelog/changelog_11.rst
+++ b/doc/build/changelog/changelog_11.rst
@@ -22,6 +22,18 @@
: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 64ed2d9e2..6f0da3780 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 afa6b4dca..0333d9ec2 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 aadd170f3..66903bef3 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):