:class:`~sqlalchemy.engine.ResultProxy` object, which acts much like a
DBAPI cursor, including methods such as
:func:`~sqlalchemy.engine.ResultProxy.fetchone` and
-:func:`~sqlalchemy.engine.ResultProxy.fetchall`. The easiest way to get
-rows from it is to just iterate:
+:func:`~sqlalchemy.engine.ResultProxy.fetchall`. These methods return
+row objects, which are provided via the :class:`.Row` class. The
+result object can be iterated directly in order to provide an iterator
+of :class:`.Row` objects:
.. sourcecode:: pycon+sql
(1, u'jack', u'Jack Jones')
(2, u'wendy', u'Wendy Williams')
-Above, we see that printing each row produces a simple tuple-like result. We
-have more options at accessing the data in each row. One very common way is
-through dictionary access, using the string names of columns:
+Above, we see that printing each :class:`.Row` produces a simple
+tuple-like result. The :class:`.Row` behaves like a hybrid between
+a Python mapping and tuple, with several methods of retrieving the data
+in each column. One common way is
+as a Python mapping of strings, using the string names of columns:
.. sourcecode:: pycon+sql
>>> print("name:", row['name'], "; fullname:", row['fullname'])
name: jack ; fullname: Jack Jones
-Integer indexes work as well:
+Another way is as a Python sequence, using integer indexes:
.. sourcecode:: pycon+sql
>>> print("name:", row[1], "; fullname:", row[2])
name: wendy ; fullname: Wendy Williams
-But another way, whose usefulness will become apparent later on, is to use the
-:class:`~sqlalchemy.schema.Column` objects directly as keys:
+A more specialized method of column access is to use the SQL construct that
+directly corresponds to a particular column as the mapping key; in this
+example, it means we would use the :class:`.Column` objects selected in our
+SELECT directly as keys:
.. sourcecode:: pycon+sql
{stop}name: jack ; fullname: Jack Jones
name: wendy ; fullname: Wendy Williams
-Result sets which have pending rows remaining should be explicitly closed
-before discarding. While the cursor and connection resources referenced by the
-:class:`~sqlalchemy.engine.ResultProxy` will be respectively closed and
-returned to the connection pool when the object is garbage collected, it's
-better to make it explicit as some database APIs are very picky about such
-things:
+The :class:`.ResultProxy` object features "auto-close" behavior that closes the
+underlying DBAPI ``cursor`` object when all pending result rows have been
+fetched. If a :class:`.ResultProxy` is to be discarded before such an
+autoclose has occurred, it can be explicitly closed using the
+:meth:`.ResultProxy.close` method:
.. sourcecode:: pycon+sql
>>> result.close()
+Selecting Specific Columns
+===========================
+
If we'd like to more carefully control the columns which are placed in the
COLUMNS clause of the select, we reference individual
:class:`~sqlalchemy.schema.Column` objects from our
class Row(BaseRow, collections_abc.Sequence):
"""Represent a single result row.
+ The :class:`.Row` object is retrieved from a database result, from the
+ :class:`.ResultProxy` object using methods like
+ :meth:`.ResultProxy.fetchall`.
+
The :class:`.Row` object seeks to act mostly like a Python named
- tuple, but also provides for mapping-oriented access via the
- :attr:`.Row._mapping` attribute.
+ tuple, but also provides some Python dictionary behaviors at the same time.
.. seealso::
return repr(sql_util._repr_row(self))
def has_key(self, key):
- """Return True if this Row contains the given key."""
+ """Return True if this :class:`.Row` contains the given key.
+
+ Through the SQLAlchemy 1.x series, the ``__contains__()`` method
+ of :class:`.Row` also links to :meth:`.Row.has_key`, in that
+ an expression such as ::
+
+ "some_col" in row
+
+ Will return True if the row contains a column named ``"some_col"``,
+ in the way that a Python mapping works.
+
+ However, it is planned that the 2.0 series of SQLAlchemy will reverse
+ this behavior so that ``__contains__()`` will refer to a value being
+ present in the row, in the way that a Python tuple works.
+
+ """
return self._parent._has_key(key)
return self._get_by_key_impl(key)
def items(self):
- """Return a list of tuples, each tuple containing a key/value pair."""
- # TODO: no coverage here
+ """Return a list of tuples, each tuple containing a key/value pair.
+
+ This method is analogous to the Python dictionary ``.items()`` method,
+ except that it returns a list, not an iterator.
+
+ """
+
return [(key, self[key]) for key in self.keys()]
def keys(self):
- """Return the list of keys as strings represented by this Row."""
+ """Return the list of keys as strings represented by this
+ :class:`.Row`.
+
+ This method is analogous to the Python dictionary ``.keys()`` method,
+ except that it returns a list, not an iterator.
+
+ """
return [k for k in self._parent.keys if k is not None]
def iterkeys(self):
+ """Return a an iterator against the :meth:`.Row.keys` method.
+
+ This method is analogous to the Python-2-only dictionary
+ ``.iterkeys()`` method.
+
+ """
return iter(self._parent.keys)
def itervalues(self):
+ """Return a an iterator against the :meth:`.Row.values` method.
+
+ This method is analogous to the Python-2-only dictionary
+ ``.itervalues()`` method.
+
+ """
return iter(self)
def values(self):
- """Return the values represented by this Row as a list."""
+ """Return the values represented by this :class:`.Row` as a list.
+
+ This method is analogous to the Python dictionary ``.values()`` method,
+ except that it returns a list, not an iterator.
+
+ """
+
return self._values_impl()
class ResultProxy(object):
- """Wraps a DB-API cursor object to provide easier access to row columns.
-
- Individual columns may be accessed by their integer position,
- case-insensitive column name, or by ``schema.Column``
- object. e.g.::
-
- row = fetchone()
-
- col1 = row[0] # access via integer position
+ """A facade around a DBAPI cursor object.
- col2 = row['col2'] # access via name
+ Returns database rows via the :class:`.Row` class, which provides
+ additional API features and behaviors on top of the raw data returned
+ by the DBAPI.
- col3 = row[mytable.c.mycol] # access via Column object.
+ .. seealso::
- ``ResultProxy`` also handles post-processing of result column
- data using ``TypeEngine`` objects, which are referenced from
- the originating SQL statement that produced this result set.
+ :ref:`coretutorial_selecting` - introductory material for accessing
+ :class:`.ResultProxy` and :class:`.Row` objects.
"""
)
def keys(self):
- """Return the current set of string keys for rows."""
+ """Return the list of string keys that would represented by each
+ :class:`.Row`."""
+
if self._metadata:
return self._metadata.keys
else:
:ref:`connections_toplevel`
- :meth:`.ResultProxy._soft_close`
-
"""
if not self.closed:
yield row
def __next__(self):
- """Implement the next() protocol.
+ """Implement the Python next() protocol.
+
+ This method, mirrored as both ``.next()`` and ``.__next__()``, is part
+ of Python's API for producing iterator-like behavior.
.. versionadded:: 1.2
an empty list. After the :meth:`.ResultProxy.close` method is
called, the method will raise :class:`.ResourceClosedError`.
- .. versionchanged:: 1.0.0 - Added "soft close" behavior which
- allows the result to be used in an "exhausted" state prior to
- calling the :meth:`.ResultProxy.close` method.
+ :return: a list of :class:`.Row` objects
"""
an empty list. After the :meth:`.ResultProxy.close` method is
called, the method will raise :class:`.ResourceClosedError`.
- .. versionchanged:: 1.0.0 - Added "soft close" behavior which
- allows the result to be used in an "exhausted" state prior to
- calling the :meth:`.ResultProxy.close` method.
+ :return: a list of :class:`.Row` objects
"""
After the :meth:`.ResultProxy.close` method is
called, the method will raise :class:`.ResourceClosedError`.
- .. versionchanged:: 1.0.0 - Added "soft close" behavior which
- allows the result to be used in an "exhausted" state prior to
- calling the :meth:`.ResultProxy.close` method.
+ :return: a :class:`.Row` object, or None if no rows remain
"""
try:
def first(self):
"""Fetch the first row and then close the result set unconditionally.
- Returns None if no row is present.
-
After calling this method, the object is fully closed,
e.g. the :meth:`.ResultProxy.close` method will have been called.
+ :return: a :class:`.Row` object, or None if no rows remain
+
"""
if self._metadata is None:
return self._non_result(None)
def scalar(self):
"""Fetch the first column of the first row, and close the result set.
- Returns None if no row is present.
-
After calling this method, the object is fully closed,
e.g. the :meth:`.ResultProxy.close` method will have been called.
+ :return: a Python scalar value , or None if no rows remain
+
"""
row = self.first()
if row is not None: