summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/cextension/resultproxy.c2
-rw-r--r--lib/sqlalchemy/engine/base.py32
-rw-r--r--lib/sqlalchemy/sql/compiler.py4
-rw-r--r--lib/sqlalchemy/sql/expression.py14
4 files changed, 41 insertions, 11 deletions
diff --git a/lib/sqlalchemy/cextension/resultproxy.c b/lib/sqlalchemy/cextension/resultproxy.c
index 5af94771b..cfc0e3530 100644
--- a/lib/sqlalchemy/cextension/resultproxy.c
+++ b/lib/sqlalchemy/cextension/resultproxy.c
@@ -278,7 +278,7 @@ BaseRowProxy_subscript(BaseRowProxy *self, PyObject *key)
return NULL;
}
- indexobject = PyTuple_GetItem(record, 1);
+ indexobject = PyTuple_GetItem(record, 2);
if (indexobject == NULL)
return NULL;
diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py
index 3c6127845..36365e524 100644
--- a/lib/sqlalchemy/engine/base.py
+++ b/lib/sqlalchemy/engine/base.py
@@ -2461,9 +2461,9 @@ except ImportError:
def __getitem__(self, key):
try:
- processor, index = self._keymap[key]
+ processor, obj, index = self._keymap[key]
except KeyError:
- processor, index = self._parent._key_fallback(key)
+ processor, obj, index = self._parent._key_fallback(key)
except TypeError:
if isinstance(key, slice):
l = []
@@ -2596,7 +2596,7 @@ class ResultMetaData(object):
processor = type_._cached_result_processor(dialect, coltype)
processors.append(processor)
- rec = (processor, i)
+ rec = (processor, obj, i)
# indexes as keys. This is only needed for the Python version of
# RowProxy (the C version uses a faster path for integer indexes).
@@ -2608,7 +2608,7 @@ class ResultMetaData(object):
# columns colliding by name is not a problem as long as the
# user does not try to access them (ie use an index directly,
# or the more precise ColumnElement)
- keymap[name.lower()] = (processor, None)
+ keymap[name.lower()] = (processor, obj, None)
if dialect.requires_name_normalize:
colname = dialect.normalize_name(colname)
@@ -2630,9 +2630,9 @@ class ResultMetaData(object):
row.
"""
- rec = (processor, i) = self._keymap[origname.lower()]
+ rec = (processor, obj, i) = self._keymap[origname.lower()]
if self._keymap.setdefault(name, rec) is not rec:
- self._keymap[name] = (processor, None)
+ self._keymap[name] = (processor, obj, None)
def _key_fallback(self, key, raiseerr=True):
map = self._keymap
@@ -2646,7 +2646,17 @@ class ResultMetaData(object):
if key._label and key._label.lower() in map:
result = map[key._label.lower()]
elif hasattr(key, 'name') and key.name.lower() in map:
+ # match is only on name. search
+ # extra hard to make sure this isn't a column/
+ # label name overlap
result = map[key.name.lower()]
+
+ if result[1] is not None:
+ for obj in result[1]:
+ if key._compare_name_for_result(obj):
+ break
+ else:
+ result = None
if result is None:
if raiseerr:
raise exc.NoSuchColumnError(
@@ -2668,7 +2678,7 @@ class ResultMetaData(object):
return {
'_pickled_keymap': dict(
(key, index)
- for key, (processor, index) in self._keymap.iteritems()
+ for key, (processor, obj, index) in self._keymap.iteritems()
if isinstance(key, (basestring, int))
),
'keys': self.keys
@@ -2680,7 +2690,9 @@ class ResultMetaData(object):
self._processors = [None for _ in xrange(len(state['keys']))]
self._keymap = keymap = {}
for key, index in state['_pickled_keymap'].iteritems():
- keymap[key] = (None, index)
+ # not preserving "obj" here, unfortunately our
+ # proxy comparison fails with the unpickle
+ keymap[key] = (None, None, index)
self.keys = state['keys']
self._echo = False
@@ -3213,8 +3225,8 @@ class BufferedColumnResultProxy(ResultProxy):
# replace the all type processors by None processors.
metadata._processors = [None for _ in xrange(len(metadata.keys))]
keymap = {}
- for k, (func, index) in metadata._keymap.iteritems():
- keymap[k] = (None, index)
+ for k, (func, obj, index) in metadata._keymap.iteritems():
+ keymap[k] = (None, obj, index)
self._metadata._keymap = keymap
def fetchall(self):
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 724e7dc2a..c63ae1aea 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -158,6 +158,10 @@ class _CompileLabel(visitors.Visitable):
self.name = name
@property
+ def proxy_set(self):
+ return self.element.proxy_set
+
+ @property
def type(self):
return self.element.type
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 9f2a16195..bff086e4b 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -2087,6 +2087,13 @@ class ColumnElement(ClauseElement, _CompareMixin):
return bool(self.proxy_set.intersection(othercolumn.proxy_set))
+ def _compare_name_for_result(self, other):
+ """Return True if the given column element compares to this one
+ when targeting within a result row."""
+
+ return hasattr(other, 'name') and hasattr(self, 'name') and \
+ other.name == self.name
+
def _make_proxy(self, selectable, name=None):
"""Create a new :class:`.ColumnElement` representing this
:class:`.ColumnElement` as it appears in the select list of a
@@ -3919,6 +3926,13 @@ class ColumnClause(_Immutable, ColumnElement):
self.type = sqltypes.to_instance(type_)
self.is_literal = is_literal
+ def _compare_name_for_result(self, other):
+ if self.table is not None and hasattr(other, 'proxy_set'):
+ return other.proxy_set.intersection(self.proxy_set)
+ else:
+ return super(ColumnClause, self).\
+ _compare_name_for_result(other)
+
def _get_table(self):
return self.__dict__['table']
def _set_table(self, table):