: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:`.RowProxy` class. The
+result object can be iterated directly in order to provide an iterator
+of :class:`.RowProxy` 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:`.RowProxy` produces a simple
+tuple-like result. The :class:`.RowProxy` 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 RowProxy(BaseRowProxy):
- """Proxy values from a single cursor row.
+ """Represent a single result row.
+
+ The :class:`.RowProxy` object is retrieved from a database result, from the
+ :class:`.ResultProxy` object using methods like
+ :meth:`.ResultProxy.fetchall`.
+
+ The :class:`.RowProxy` object seeks to act mostly like a Python named
+ tuple, but also provides some Python dictionary behaviors at the same time.
+
+ .. seealso::
+
+ :ref:`coretutorial_selecting` - includes examples of selecting
+ rows from SELECT statements.
- Mostly follows "ordered dictionary" behavior, mapping result
- values to the string-based column name, the integer position of
- the result in the row, as well as Column instances which can be
- mapped to the original Columns that produced this result set (for
- results that correspond to constructed SQL expressions).
"""
__slots__ = ()
return repr(sql_util._repr_row(self))
def has_key(self, key):
- """Return True if this RowProxy contains the given key."""
+ """Return True if this :class:`.RowProxy` contains the given key.
+
+ Through the SQLAlchemy 1.x series, the ``__contains__()`` method
+ of :class:`.RowProxy` also links to :meth:`.RowProxy.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)
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 RowProxy."""
+ """Return the list of keys as strings represented by this
+ :class:`.RowProxy`.
+
+ This method is analogous to the Python dictionary ``.keys()`` method,
+ except that it returns a list, not an iterator.
+
+ """
return self._parent.keys
def iterkeys(self):
+ """Return a an iterator against the :meth:`.RowProxy.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:`.RowProxy.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 :class:`.RowProxy` as a list.
+
+ This method is analogous to the Python dictionary ``.values()`` method,
+ except that it returns a list, not an iterator.
+
+ """
+ return super(RowProxy, self).values()
+
try:
# Register RowProxy with Sequence,
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()
+ """A facade around a DBAPI cursor object.
- col1 = row[0] # access via integer position
+ Returns database rows via the :class:`.RowProxy` class, which provides
+ additional API features and behaviors on top of the raw data returned
+ by the DBAPI.
- col2 = row['col2'] # access via name
-
- 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:`.RowProxy` 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:`.RowProxy`."""
+
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:`.RowProxy` 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:`.RowProxy` 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:`.RowProxy` 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:`.RowProxy` 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: