Mike Bayer <[email protected]> writes:
> Let's consider going with the third option I mentioned, I dont think
> this will add too much expense if you could test this out please
Here is the diff implementing the third option: it still need to touch also
the C implementation, because that does not use the metadata keymap when the
key is an integer.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c
index 9c4d0c7..331fae2 100644
--- a/lib/sqlalchemy/cextension/resultproxy.c
+++ b/lib/sqlalchemy/cextension/resultproxy.c
@@ -263,7 +263,9 @@ 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
if (PyLong_CheckExact(key)) {
@@ -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)
diff --git a/lib/sqlalchemy/engine/result.py b/lib/sqlalchemy/engine/result.py
index cc4ac74..47245e7 100644
--- a/lib/sqlalchemy/engine/result.py
+++ b/lib/sqlalchemy/engine/result.py
@@ -210,10 +210,17 @@ class ResultMetaData(object):
context, cursor_description, result_columns,
num_ctx_cols, cols_are_ordered, textual_ordered)
- # keymap indexes by integer index...
+ # keymap indexes by integer index: we add also negative
+ # indexes to handle the row[-x] case in the pure Python
+ # BaseRowProxy.__getitem__ implementation, avoiding an
+ # expensive isinstance(key, util.int_types) in the most
+ # common case path
self._keymap = dict([
(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
diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py
index 5ea5d35..aadd170 100644
--- a/test/engine/test_execute.py
+++ b/test/engine/test_execute.py
@@ -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
Given these differences between the two implementation, is there a way to
explicitly perform the tests both with and without the C speedups? For now, I
manually removed the *.so compiled thingies and re-executed the test suite.
BTW, even if it seems unrelated to my diff, I'm seeing several errors/failures
when running the tests under Py3 *without* C speedups:
$ py.test test/
platform linux -- Python 3.5.1+, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 --
/home/lele/wip/sqlalchemy/env/bin/python3
cachedir: .cache
rootdir: /home/lele/wip/sqlalchemy, inifile: setup.cfg
collected 7556 items
test/aaa_profiling/test_compiler.py::CompileTest_sqlite_pysqlite::test_insert
SKIPPED
test/aaa_profiling/test_compiler.py::CompileTest_sqlite_pysqlite::test_select
SKIPPED
...
============================= FAILURES ==============================
___________ QueuePoolTest.test_recycle_on_soft_invalidate ___________
Traceback (most recent call last):
File "/home/lele/wip/sqlalchemy/test/engine/test_pool.py", line 1424, in
test_recycle_on_soft_invalidate
assert id(c3.connection) != c_id
AssertionError: assert 139915463276696 != 139915463276696
+ where 139915463276696 = id(<Mock id='139915463276696'>)
+ where <Mock id='139915463276696'> = <sqlalchemy.pool._ConnectionFairy
object at 0x7f409b7cb8d0>.connection
!!!!!!!!!!!!!! Interrupted: stopping after 25 failures !!!!!!!!!!!!!!
=== 1 failed, 1161 passed, 617 skipped, 24 error in 67.09 seconds ===
Py3 *with* C speedups, and Py2 in either contexts do not exhibit these
errors/failures...
Let me know which of the options you like most, or if there is anything else I
can do/try.
Thanks for the feedback,
ciao, lele.
--
nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
[email protected] | -- Fortunato Depero, 1929.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.