.. changelog::
:version: 1.2.0b1
+ .. change:: 3932
+ :tags: bug, oracle
+ :tickets: 3932
+
+ The cx_Oracle dialect now supports "sane multi rowcount", that is,
+ when a series of parameter sets are executed via DBAPI
+ ``cursor.executemany()``, we can make use of ``cursor.rowcount`` to
+ verify the number of rows matched. This has an impact within the
+ ORM when detecting concurrent modification scenarios, in that
+ some simple conditions can now be detected even when the ORM
+ is batching statements, as well as when the more strict versioning
+ feature is used, the ORM can still use statement batching. The
+ flag is enabled for cx_Oracle assuming at least version 5.0, which
+ is now commonplace.
.. change:: 3276
:tags: bug, oracle
execution_ctx_cls = OracleExecutionContext_cx_oracle
statement_compiler = OracleCompiler_cx_oracle
+ supports_sane_rowcount = True
+ supports_sane_multi_rowcount = True
+
driver = "cx_oracle"
colspecs = colspecs = {
self._cx_oracle_binary_types = types("BFILE", "CLOB", "NCLOB", "BLOB")
self.supports_unicode_binds = self.cx_oracle_ver >= (5, 0)
+ self.supports_sane_multi_rowcount = self.cx_oracle_ver >= (5, 0)
+
self.coerce_to_unicode = (
self.cx_oracle_ver >= (5, 0) and
coerce_to_unicode
# WHERE matches 3, 3 rows changed
department = employees_table.c.department
r = employees_table.update(department == 'C').execute(department='Z')
- print("expecting 3, dialect reports %s" % r.rowcount)
assert r.rowcount == 3
def test_update_rowcount2(self):
# WHERE matches 3, 0 rows changed
department = employees_table.c.department
r = employees_table.update(department == 'C').execute(department='C')
- print("expecting 3, dialect reports %s" % r.rowcount)
assert r.rowcount == 3
def test_raw_sql_rowcount(self):
# WHERE matches 3, 3 rows deleted
department = employees_table.c.department
r = employees_table.delete(department == 'C').execute()
- print("expecting 3, dialect reports %s" % r.rowcount)
assert r.rowcount == 3
+
+ @testing.requires.sane_multi_rowcount
+ def test_multi_update_rowcount(self):
+ stmt = employees_table.update().\
+ where(employees_table.c.name == bindparam('emp_name')).\
+ values(department="C")
+
+ r = testing.db.execute(
+ stmt,
+ [{"emp_name": "Bob"}, {"emp_name": "Cynthia"},
+ {"emp_name": "nonexistent"}]
+ )
+
+ eq_(
+ r.rowcount, 2
+ )
+
+ @testing.requires.sane_multi_rowcount
+ def test_multi_delete_rowcount(self):
+ stmt = employees_table.delete().\
+ where(employees_table.c.name == bindparam('emp_name'))
+
+ r = testing.db.execute(
+ stmt,
+ [{"emp_name": "Bob"}, {"emp_name": "Cynthia"},
+ {"emp_name": "nonexistent"}]
+ )
+
+ eq_(
+ r.rowcount, 2
+ )