summaryrefslogtreecommitdiff
path: root/doc/build/core
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-06-04 17:29:20 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2020-02-21 17:53:33 -0500
commitf559f378c47811b5528ad1769cb86925e85fd1e5 (patch)
treefd8325501a96cf1e4280c15f267f63b2af7b5f97 /doc/build/core
parent93b7767d00267ebe149cabcae7246b6796352eb8 (diff)
downloadsqlalchemy-f559f378c47811b5528ad1769cb86925e85fd1e5.tar.gz
Result initial introduction
This builds on cc718cccc0bf8a01abdf4068c7ea4f3 which moved RowProxy to Row, allowing Row to be more like a named tuple. - KeyedTuple in ORM is replaced with Row - ResultSetMetaData broken out into "simple" and "cursor" versions for ORM and Core, as well as LegacyCursor version. - Row now has _mapping attribute that supplies full mapping behavior. Row and SimpleRow both have named tuple behavior otherwise. LegacyRow has some mapping features on the tuple which emit deprecation warnings (e.g. keys(), values(), etc). the biggest change for mapping->tuple is the behavior of __contains__ which moves from testing of "key in row" to "value in row". - ResultProxy breaks into ResultProxy and FutureResult (interim), the latter has the newer APIs. Made available to dialects using execution options. - internal reflection methods and most tests move off of implicit Row mapping behavior and move to row._mapping, result.mappings() method using future result - a new strategy system for cursor handling replaces the various subclasses of RowProxy - some execution context adjustments. We will leave EC in but refined things like get_result_proxy() and out parameter handling. Dialects for 1.4 will need to adjust from get_result_proxy() to get_result_cursor_strategy(), if they are using this method - out parameter handling now accommodated by get_out_parameter_values() EC method. Oracle changes for this. external dialect for DB2 for example will also need to adjust for this. - deprecate case_insensitive flag for engine / result, this feature is not used mapping-methods on Row are deprecated, and replaced with Row._mapping.<meth>, including: row.keys() -> use row._mapping.keys() row.items() -> use row._mapping.items() row.values() -> use row._mapping.values() key in row -> use key in row._mapping int in row -> use int < len(row) Fixes: #4710 Fixes: #4878 Change-Id: Ieb9085e9bcff564359095b754da9ae0af55679f0
Diffstat (limited to 'doc/build/core')
-rw-r--r--doc/build/core/connections.rst11
-rw-r--r--doc/build/core/future.rst13
-rw-r--r--doc/build/core/index.rst1
-rw-r--r--doc/build/core/tutorial.rst77
4 files changed, 92 insertions, 10 deletions
diff --git a/doc/build/core/connections.rst b/doc/build/core/connections.rst
index e205a37b5..5619377de 100644
--- a/doc/build/core/connections.rst
+++ b/doc/build/core/connections.rst
@@ -635,6 +635,9 @@ The above will respond to ``create_engine("mysql+foodialect://")`` and load the
Connection / Engine API
=======================
+.. autoclass:: BaseResult
+ :members:
+
.. autoclass:: Connection
:members:
@@ -650,14 +653,22 @@ Connection / Engine API
.. autoclass:: ExceptionContext
:members:
+.. autoclass:: LegacyRow
+ :members:
+
.. autoclass:: NestedTransaction
:members:
.. autoclass:: ResultProxy
:members:
+ :inherited-members:
.. autoclass:: Row
:members:
+ :private-members: _fields, _mapping
+
+.. autoclass:: RowMapping
+ :members:
.. autoclass:: Transaction
:members:
diff --git a/doc/build/core/future.rst b/doc/build/core/future.rst
new file mode 100644
index 000000000..ffe8b67a3
--- /dev/null
+++ b/doc/build/core/future.rst
@@ -0,0 +1,13 @@
+.. _core_future_toplevel:
+
+SQLAlchemy 2.0 Future (Core)
+============================
+
+.. module:: sqlalchemy.future
+
+
+.. autofunction:: sqlalchemy.future.select
+
+.. autoclass:: sqlalchemy.future.Result
+ :members:
+ :inherited-members:
diff --git a/doc/build/core/index.rst b/doc/build/core/index.rst
index 26c26af07..a3574341a 100644
--- a/doc/build/core/index.rst
+++ b/doc/build/core/index.rst
@@ -17,3 +17,4 @@ Language provides a schema-centric usage paradigm.
types
engines_connections
api_basics
+ future \ No newline at end of file
diff --git a/doc/build/core/tutorial.rst b/doc/build/core/tutorial.rst
index 9b58222f2..89316bcb9 100644
--- a/doc/build/core/tutorial.rst
+++ b/doc/build/core/tutorial.rst
@@ -408,10 +408,40 @@ of :class:`.Row` objects:
(2, u'wendy', u'Wendy Williams')
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:
+tuple-like result. The most canonical way in Python to access the values
+of these tuples as rows are fetched is through tuple assignment:
+
+.. sourcecode:: pycon+sql
+
+ {sql}>>> result = conn.execute(s)
+ SELECT users.id, users.name, users.fullname
+ FROM users
+ ()
+
+ {stop}>>> for id, name, fullname in result:
+ ... print("name:", name, "; fullname: ", fullname)
+ name: jack ; fullname: Jack Jones
+ name: wendy ; fullname: Wendy Williams
+
+The :class:`.Row` object actually behaves like a Python named tuple, so
+we may also access these attributes from the row itself using attribute
+access:
+
+.. sourcecode:: pycon+sql
+
+ {sql}>>> result = conn.execute(s)
+ SELECT users.id, users.name, users.fullname
+ FROM users
+ ()
+
+ {stop}>>> for row in result:
+ ... print("name:", row.name, "; fullname: ", row.fullname)
+ name: jack ; fullname: Jack Jones
+ name: wendy ; fullname: Wendy Williams
+
+To access columns via name using strings, either when the column name is
+progammatically generated, or contains non-ascii characters, the
+:attr:`.Row._mapping` view may be used that provides dictionary-like access:
.. sourcecode:: pycon+sql
@@ -421,10 +451,28 @@ as a Python mapping of strings, using the string names of columns:
()
{stop}>>> row = result.fetchone()
- >>> print("name:", row['name'], "; fullname:", row['fullname'])
+ >>> print("name:", row._mapping['name'], "; fullname:", row._mapping['fullname'])
name: jack ; fullname: Jack Jones
-Another way is as a Python sequence, using integer indexes:
+.. deprecated:: 1.4
+
+ In versions of SQLAlchemy prior to 1.4, the above access using
+ :attr:`.Row._mapping` would proceed against the row object itself, that
+ is::
+
+ row = result.fetchone()
+ name, fullname = row["name"], row["fullname"]
+
+ This pattern is now deprecated and will be removed in SQLAlchemy 2.0, so
+ that the :class:`.Row` object may now behave fully like a Python named
+ tuple.
+
+.. versionchanged:: 1.4 Added :attr:`.Row._mapping` which provides for
+ dictionary-like access to a :class:`.Row`, superseding the use of string/
+ column keys against the :class:`.Row` object directly.
+
+As the :class:`.Row` is a tuple, sequence (i.e. integer or slice) access
+may be used as well:
.. sourcecode:: pycon+sql
@@ -435,18 +483,27 @@ Another way is as a Python sequence, using integer indexes:
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:
+SELECT directly as keys in conjunction with the :attr:`.Row._mapping`
+collection:
.. sourcecode:: pycon+sql
{sql}>>> for row in conn.execute(s):
- ... print("name:", row[users.c.name], "; fullname:", row[users.c.fullname])
+ ... print("name:", row._mapping[users.c.name], "; fullname:", row._mapping[users.c.fullname])
SELECT users.id, users.name, users.fullname
FROM users
()
{stop}name: jack ; fullname: Jack Jones
name: wendy ; fullname: Wendy Williams
+.. sidebar:: Rows are changing
+
+ The :class:`.Row` class was known as :class:`.RowProxy` for all
+ SQLAlchemy versions through 1.3. In 1.4, the objects returned by
+ :class:`.ResultProxy` are actually a subclass of :class:`.Row` known as
+ :class:`.LegacyRow`. See :ref:`change_4710_core` for background on this
+ change.
+
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
@@ -897,14 +954,14 @@ when the result-columns are fetched using the actual column object as a key.
Fetching the ``email_address`` column would be::
>>> row = result.fetchone()
- >>> row[addresses.c.email_address]
+ >>> row._mapping[addresses.c.email_address]
'jack@yahoo.com'
If on the other hand we used a string column key, the usual rules of name-
based matching still apply, and we'd get an ambiguous column error for
the ``id`` value::
- >>> row["id"]
+ >>> row._mapping["id"]
Traceback (most recent call last):
...
InvalidRequestError: Ambiguous column name 'id' in result set column descriptions