diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-06-12 10:31:05 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-06-12 10:31:05 -0400 |
commit | 05fcf8b137fa098934f5572bf93b5b5bb5eb1639 (patch) | |
tree | 64053391a35b8938ffcd126d3b6cfeb63a4147bb | |
parent | 38cb8b367bfb8b6b4e70503a91af6c63c7e39b1a (diff) | |
download | sqlalchemy-05fcf8b137fa098934f5572bf93b5b5bb5eb1639.tar.gz |
- rewrite rowcount documentation to be as absolutely clear as possible
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 17 | ||||
-rw-r--r-- | lib/sqlalchemy/engine/base.py | 70 |
2 files changed, 66 insertions, 21 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 319e8ef47..485911ae5 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -152,6 +152,23 @@ available. update(..., mysql_limit=10) +rowcount Support +---------------- + +SQLAlchemy standardizes the DBAPI ``cursor.rowcount`` attribute to be the +usual definition of "number of rows matched by an UPDATE or DELETE" statement. +This is in contradiction to the default setting on most MySQL DBAPI drivers, +which is "number of rows actually modified/deleted". For this reason, the +SQLAlchemy MySQL dialects always set the ``constants.CLIENT.FOUND_ROWS`` flag, +or whatever is equivalent for the DBAPI in use, on connect, unless the flag value +is overridden using DBAPI-specific options +(such as ``client_flag`` for the MySQL-Python driver, ``found_rows`` for the +OurSQL driver). + +See also: + +:attr:`.ResultProxy.rowcount` + Troubleshooting --------------- diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index c1be4f237..e70ecc018 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -654,13 +654,10 @@ class ExecutionContext(object): raise NotImplementedError() def get_rowcount(self): - """Return the number of rows produced (by a SELECT query) - or affected (by an INSERT/UPDATE/DELETE statement). - - Note that this row count may not be properly implemented - in some dialects; this is indicated by the - ``supports_sane_rowcount`` and ``supports_sane_multi_rowcount`` - dialect attributes. + """Return the DBAPI ``cursor.rowcount`` value, or in some + cases an interpreted value. + + See :attr:`.ResultProxy.rowcount` for details on this. """ @@ -2288,18 +2285,41 @@ class ResultProxy(object): def rowcount(self): """Return the 'rowcount' for this result. - The 'rowcount' reports the number of rows affected - by an UPDATE or DELETE statement. It has *no* other - uses and is not intended to provide the number of rows - present from a SELECT. - - Note that this row count may not be properly implemented in some - dialects; this is indicated by - :meth:`~sqlalchemy.engine.base.ResultProxy.supports_sane_rowcount()` - and - :meth:`~sqlalchemy.engine.base.ResultProxy.supports_sane_multi_rowcount()`. - ``rowcount()`` also may not work at this time for a statement that - uses ``returning()``. + The 'rowcount' reports the number of rows *matched* + by the WHERE criterion of an UPDATE or DELETE statement. + + .. note:: + + Notes regarding :attr:`.ResultProxy.rowcount`: + + + * This attribute returns the number of rows *matched*, + which is not necessarily the same as the number of rows + that were actually *modified* - an UPDATE statement, for example, + may have no net change on a given row if the SET values + given are the same as those present in the row already. + Such a row would be matched but not modified. + On backends that feature both styles, such as MySQL, + rowcount is configured by default to return the match + count in all cases. + + * :attr:`.ResultProxy.rowcount` is *only* useful in conjunction + with an UPDATE or DELETE statement. Contrary to what the Python + DBAPI says, it does *not* return the + number of rows available from the results of a SELECT statement + as DBAPIs cannot support this functionality when rows are + unbuffered. + + * :attr:`.ResultProxy.rowcount` may not be fully implemented by + all dialects. In particular, most DBAPIs do not support an + aggregate rowcount result from an executemany call. + The :meth:`.ResultProxy.supports_sane_rowcount` and + :meth:`.ResultProxy.supports_sane_multi_rowcount` methods + will report from the dialect if each usage is known to be + supported. + + * Statements that use RETURNING may not return a correct + rowcount. """ return self.context.rowcount @@ -2476,12 +2496,20 @@ class ResultProxy(object): return self.context.prefetch_cols def supports_sane_rowcount(self): - """Return ``supports_sane_rowcount`` from the dialect.""" + """Return ``supports_sane_rowcount`` from the dialect. + + See :attr:`.ResultProxy.rowcount` for background. + + """ return self.dialect.supports_sane_rowcount def supports_sane_multi_rowcount(self): - """Return ``supports_sane_multi_rowcount`` from the dialect.""" + """Return ``supports_sane_multi_rowcount`` from the dialect. + + See :attr:`.ResultProxy.rowcount` for background. + + """ return self.dialect.supports_sane_multi_rowcount |