mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-26 02:22:13 -04:00
Repair _execute_scalar for WITH_UNICODE mode
cx_Oracle 5.3 seems to code this flag ON now, so remove the warning and ensure WITH_UNICODE handling works. Additionally, the XE setup on jenkins is having more problems here, in particular low-connections mode is causing cx_Oracle to fail more frequently now. Turning off low-connections fixes those but then we get the TNS errors, so adding an emergency "retry" flag that is not yet a feature available to users. Real world applications are not dropping/creating thousands of tables the way our test suite is. Change-Id: Ie95b0e697276c404d3264c2e624e870463d966d6 Fixes: #3937
This commit is contained in:
Vendored
+15
@@ -15,6 +15,21 @@
|
||||
.. include:: changelog_07.rst
|
||||
:start-line: 5
|
||||
|
||||
|
||||
.. changelog::
|
||||
:version: 1.0.18
|
||||
|
||||
.. change:: 3937
|
||||
:tags: bug, oracle
|
||||
:tickets: 3937
|
||||
:versions: 1.1.7
|
||||
|
||||
A fix to cx_Oracle's WITH_UNICODE mode which was uncovered by the
|
||||
fact that cx_Oracle 5.3 now seems to hardcode this flag on in
|
||||
the build; an internal method that uses this mode wasn't using
|
||||
the correct signature.
|
||||
|
||||
|
||||
.. changelog::
|
||||
:version: 1.0.17
|
||||
:released: January 17, 2017
|
||||
|
||||
@@ -298,6 +298,7 @@ import random
|
||||
import collections
|
||||
import decimal
|
||||
import re
|
||||
import time
|
||||
|
||||
|
||||
class _OracleNumeric(sqltypes.Numeric):
|
||||
@@ -621,9 +622,9 @@ class OracleExecutionContext_cx_oracle_with_unicode(
|
||||
OracleExecutionContext_cx_oracle.__init__(self, *arg, **kw)
|
||||
self.statement = util.text_type(self.statement)
|
||||
|
||||
def _execute_scalar(self, stmt):
|
||||
def _execute_scalar(self, stmt, type_):
|
||||
return super(OracleExecutionContext_cx_oracle_with_unicode, self).\
|
||||
_execute_scalar(util.text_type(stmt))
|
||||
_execute_scalar(util.text_type(stmt), type_)
|
||||
|
||||
|
||||
class ReturningResultProxy(_result.FullyBufferedResultProxy):
|
||||
@@ -692,7 +693,8 @@ class OracleDialect_cx_oracle(OracleDialect):
|
||||
allow_twophase=True,
|
||||
coerce_to_decimal=True,
|
||||
coerce_to_unicode=False,
|
||||
arraysize=50, **kwargs):
|
||||
arraysize=50, _retry_on_12516=False,
|
||||
**kwargs):
|
||||
OracleDialect.__init__(self, **kwargs)
|
||||
self.threaded = threaded
|
||||
self.arraysize = arraysize
|
||||
@@ -701,6 +703,7 @@ class OracleDialect_cx_oracle(OracleDialect):
|
||||
hasattr(self.dbapi, 'TIMESTAMP')
|
||||
self.auto_setinputsizes = auto_setinputsizes
|
||||
self.auto_convert_lobs = auto_convert_lobs
|
||||
self._retry_on_12516 = _retry_on_12516
|
||||
|
||||
if hasattr(self.dbapi, 'version'):
|
||||
self.cx_oracle_ver = tuple([int(x) for x in
|
||||
@@ -748,18 +751,8 @@ class OracleDialect_cx_oracle(OracleDialect):
|
||||
|
||||
if util.py2k:
|
||||
# There's really no reason to run with WITH_UNICODE under
|
||||
# Python 2.x. Give the user a hint.
|
||||
util.warn(
|
||||
"cx_Oracle is compiled under Python 2.xx using the "
|
||||
"WITH_UNICODE flag. Consider recompiling cx_Oracle "
|
||||
"without this flag, which is in no way necessary for "
|
||||
"full support of Unicode. Otherwise, all string-holding "
|
||||
"bind parameters must be explicitly typed using "
|
||||
"SQLAlchemy's String type or one of its subtypes,"
|
||||
"or otherwise be passed as Python unicode. "
|
||||
"Plain Python strings passed as bind parameters will be "
|
||||
"silently corrupted by cx_Oracle."
|
||||
)
|
||||
# Python 2.x. However as of cx_oracle 5.3 it seems to be
|
||||
# set to ON for default builds
|
||||
self.execution_ctx_cls = \
|
||||
OracleExecutionContext_cx_oracle_with_unicode
|
||||
else:
|
||||
@@ -785,6 +778,22 @@ class OracleDialect_cx_oracle(OracleDialect):
|
||||
import cx_Oracle
|
||||
return cx_Oracle
|
||||
|
||||
def connect(self, *cargs, **cparams):
|
||||
if self._retry_on_12516:
|
||||
# emergency flag for the SQLAlchemy test suite, which has
|
||||
# decreased in stability since cx_oracle 5.3; generalized
|
||||
# "retry on connect" functionality is part of an upcoming
|
||||
# SQLAlchemy feature
|
||||
try:
|
||||
return self.dbapi.connect(*cargs, **cparams)
|
||||
except self.dbapi.DatabaseError as err:
|
||||
if "ORA-12516" in str(err):
|
||||
time.sleep(2)
|
||||
return self.dbapi.connect(*cargs, **cparams)
|
||||
else:
|
||||
return super(OracleDialect_cx_oracle, self).connect(
|
||||
*cargs, **cparams)
|
||||
|
||||
def initialize(self, connection):
|
||||
super(OracleDialect_cx_oracle, self).initialize(connection)
|
||||
if self._is_oracle_8:
|
||||
|
||||
@@ -126,6 +126,7 @@ def _mssql_update_db_opts(db_url, db_opts):
|
||||
db_opts['legacy_schema_aliasing'] = False
|
||||
|
||||
|
||||
|
||||
@_follower_url_from_main.for_db("sqlite")
|
||||
def _sqlite_follower_url_from_main(url, ident):
|
||||
url = sa_url.make_url(url)
|
||||
@@ -270,6 +271,11 @@ def _oracle_drop_db(cfg, eng, ident):
|
||||
_ora_drop_ignore(conn, "%s_ts2" % ident)
|
||||
|
||||
|
||||
@_update_db_opts.for_db("oracle")
|
||||
def _oracle_update_db_opts(db_url, db_opts):
|
||||
db_opts['_retry_on_12516'] = True
|
||||
|
||||
|
||||
def reap_oracle_dbs(eng, idents_file):
|
||||
log.info("Reaping Oracle dbs...")
|
||||
with eng.connect() as conn:
|
||||
|
||||
@@ -1706,10 +1706,10 @@ class TypesTest(fixtures.TestBase):
|
||||
@testing.provide_metadata
|
||||
def test_reflect_nvarchar(self):
|
||||
metadata = self.metadata
|
||||
Table('t', metadata, Column('data', sqltypes.NVARCHAR(255)))
|
||||
Table('tnv', metadata, Column('data', sqltypes.NVARCHAR(255)))
|
||||
metadata.create_all()
|
||||
m2 = MetaData(testing.db)
|
||||
t2 = Table('t', m2, autoload=True)
|
||||
t2 = Table('tnv', m2, autoload=True)
|
||||
assert isinstance(t2.c.data.type, sqltypes.NVARCHAR)
|
||||
|
||||
if testing.against('oracle+cx_oracle'):
|
||||
|
||||
@@ -54,7 +54,7 @@ setenv=
|
||||
sqlite: SQLITE=--db sqlite
|
||||
postgresql: POSTGRESQL=--db postgresql
|
||||
mysql: MYSQL=--db mysql --db pymysql
|
||||
oracle: ORACLE=--db oracle --low-connections --write-idents oracle_idents.txt
|
||||
oracle: ORACLE=--db oracle --write-idents oracle_idents.txt
|
||||
mssql: MSSQL=--db pyodbc --db pymssql
|
||||
backendonly: BACKENDONLY=--backend-only
|
||||
|
||||
|
||||
Reference in New Issue
Block a user