summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2016-01-13 18:40:36 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2016-01-13 18:40:36 -0500
commit5d12891fefa187a15e7dd6f6539c90ce1813aea9 (patch)
tree1fbbfeb21ada1f027ab7d18daee479acc2d16887
parentb1c045b40ff48d377aaf689121cfa2d4ab38cc08 (diff)
downloadsqlalchemy-5d12891fefa187a15e7dd6f6539c90ce1813aea9.tar.gz
- some changelog / migration stuff, still needs proofreading
-rw-r--r--doc/build/changelog/changelog_11.rst20
-rw-r--r--doc/build/changelog/migration_11.rst92
-rw-r--r--doc/build/core/tutorial.rst2
-rw-r--r--lib/sqlalchemy/sql/elements.py2
4 files changed, 114 insertions, 2 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst
index 975badc36..5fbcca45a 100644
--- a/doc/build/changelog/changelog_11.rst
+++ b/doc/build/changelog/changelog_11.rst
@@ -22,6 +22,26 @@
:version: 1.1.0b1
.. change::
+ :tags: feature, sql
+ :tickets: 3501
+
+ A deep improvement to the recently added :meth:`.TextClause.columns`
+ method, and its interaction with result-row processing, now allows
+ the columns passed to the method to be positionally matched with the
+ result columns in the statement, rather than matching on name alone.
+ The advantage to this includes that when linking a textual SQL statement
+ to an ORM or Core table model, no system of labeling or de-duping of
+ common column names needs to occur, which also means there's no need
+ to worry about how label names match to ORM columns and so-forth. In
+ addition, the :class:`.ResultProxy` has been further enhanced to
+ map column and string keys to a row with greater precision in some
+ cases.
+
+ .. seealso::
+
+ :ref:`change_3501`
+
+ .. change::
:tags: feature, engine
:tickets: 2685
diff --git a/doc/build/changelog/migration_11.rst b/doc/build/changelog/migration_11.rst
index b87e7207b..6ee8293f4 100644
--- a/doc/build/changelog/migration_11.rst
+++ b/doc/build/changelog/migration_11.rst
@@ -445,6 +445,59 @@ will not have much impact on the behavior of the column during an INSERT.
:ticket:`3216`
+.. _change_3501:
+
+Positional matching of result columns when using textual SQL
+------------------------------------------------------------
+
+A series of improvements were made to the :class:`.ResultProxy` system
+in the 1.0 series as part of :ticket:`918`, which reorganizes the internals
+to match cursor-bound result columns with table/ORM metadata positionally,
+rather than by matching names, for compiled SQL constructs that contain full
+information about the result rows to be returned. This allows a dramatic savings
+on Python overhead as well as much greater accuracy in linking ORM and Core
+SQL expressions to result rows. In 1.1, this reorganization has been taken
+much further internally, and also has been made available to pure-text SQL
+constructs via the use of the recently added :meth:`.TextClause.columns` method.
+
+The method now accepts column-based arguments positionally which will be matched
+to the target result set positionally as well. The key advantage here is that
+textual SQL can now be linked to an ORM-level result set without the need to
+deal with ambiguous or duplicate column names, or with having to match labeling
+schemes to ORM-level column names. All that's needed now is the position::
+
+
+ from sqlalchemy import text
+ stmt = text("SELECT users.id, addresses.id, users.id, "
+ "users.name, addresses.email_address AS email "
+ "FROM users JOIN addresses ON users.id=addresses.user_id "
+ "WHERE users.id = 1").columns(
+ User.id,
+ Address.id,
+ Address.user_id,
+ User.name,
+ Address.email_address
+ )
+
+ query = session.query(User).from_statement(text).\
+ options(contains_eager(User.addresses))
+ result = query.all()
+
+Above, the textual SQL contains the column "id" three times, which would
+normally be ambiguous. Using the new feature, we can apply the mapped
+columns from the ``User`` and ``Address`` class directly, even linking
+the ``Address.user_id`` column to the ``users.id`` column in textual SQL
+for fun, and the :class:`.Query` object will receive rows that are correctly
+targetable as needed, including for an eager load.
+
+.. seealso::
+
+ :ref:`sqlexpression_text_columns`
+
+ :ref:`behavior_change_3501`
+
+:ticket:`3501`
+
.. _change_2528:
A UNION or similar of SELECTs with LIMIT/OFFSET/ORDER BY now parenthesizes the embedded selects
@@ -896,6 +949,45 @@ Key Behavioral Changes - ORM
Key Behavioral Changes - Core
=============================
+.. _behavior_change_3501:
+
+The new behavior of the :meth:`.TextClause.columns` method is that when
+columns are passed positionally only, they are linked to the ultimate result set
+columns positionally, and no longer on name. Therefore an application that was
+using this very recently added method by passing :class:`.Column` objects
+to it positionally must ensure that the position of those :class:`.Column`
+objects matches the position in which these columns are stated in the
+textual SQL.
+
+E.g., code like the following::
+
+ stmt = text("SELECT id, name, description FROM table")
+
+ # no longer matches by name
+ stmt = stmt.columns(my_table.c.name, my_table.c.description, my_table.c.id)
+
+Would no longer work as expected; the order of the columns given is now
+significant::
+
+ # correct version
+ stmt = stmt.columns(my_table.c.id, my_table.c.name, my_table.c.description)
+
+Possibly more likely, a statement that worked like this::
+
+ stmt = text("SELECT * FROM table")
+ stmt = stmt.columns(my_table.c.id, my_table.c.name, my_table.c.description)
+
+is now slightly risky, as the "*" specification will generally deliver columns
+in the order in which they are present in the table itself. If the structure
+of the table changes due to a migration, this ordering may no longer be the same.
+Therefore when using :meth:`.TextClause.columns`, it's advised to list out
+the desired columns explicitly, though it's no longer necessary to worry about
+duplicate names or names matching.
+
+
+.. seealso::
+
+ :ref:`change_3501`
Dialect Improvements and Changes - Postgresql
=============================================
diff --git a/doc/build/core/tutorial.rst b/doc/build/core/tutorial.rst
index 053229b8e..0a1398055 100644
--- a/doc/build/core/tutorial.rst
+++ b/doc/build/core/tutorial.rst
@@ -814,6 +814,8 @@ or special SQL-side processing provided by the datatype.
:meth:`.TextClause.bindparams` - full method description
+.. _sqlexpression_text_columns:
+
Specifying Result-Column Behaviors
----------------------------------------------
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index f18a9cdcd..7fa8f42f8 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -1528,8 +1528,6 @@ class TextClause(Executable, ClauseElement):
the result set will match to those columns positionally, meaning the
name or origin of the column in the textual SQL doesn't matter::
- stmt = text("SELECT users.id, addresses.id, users.name, )
-
stmt = text("SELECT users.id, addresses.id, users.id, "
"users.name, addresses.email_address AS email "
"FROM users JOIN addresses ON users.id=addresses.user_id "