- "out" parameters require a type that is supported by
cx_oracle. An error will be raised if no cx_oracle
type can be found.
+
- Oracle 'DATE' now does not perform any result processing,
as the DATE type in Oracle stores full date+time objects,
that's what you'll get. Note that the generic types.Date
type *will* still call value.date() on incoming values,
however. When reflecting a table, the reflected type
will be 'DATE'.
+
+ - Added preliminary support for Oracle's WITH_UNICODE
+ mode. At the very least this establishes initial
+ support for cx_Oracle with Python 3.
+ [ticket:1670]
- sqlite
- Added "native_datetime=True" flag to create_engine().
def normalize_name(self, name):
if name is None:
return None
- elif (name.upper() == name and
- not self.identifier_preparer._requires_quotes(name.lower().decode(self.encoding))):
- return name.lower().decode(self.encoding)
+ # Py2K
+ if isinstance(name, str):
+ name = name.decode(self.encoding)
+ # end Py2K
+ if name.upper() == name and \
+ not self.identifier_preparer._requires_quotes(name.lower()):
+ return name.lower()
else:
- return name.decode(self.encoding)
+ return name
def denormalize_name(self, name):
if name is None:
return None
elif name.lower() == name and not self.identifier_preparer._requires_quotes(name.lower()):
- return name.upper().encode(self.encoding)
+ name = name.upper()
+ # Py2K
+ if not self.supports_unicode_binds:
+ name = name.encode(self.encoding)
else:
- return name.encode(self.encoding)
+ name = unicode(name)
+ # end Py2K
+ return name
def _get_default_schema_name(self, connection):
- return self.normalize_name(connection.execute('SELECT USER FROM DUAL').scalar())
+ return self.normalize_name(connection.execute(u'SELECT USER FROM DUAL').scalar())
def table_names(self, connection, schema):
# note that table_names() isnt loading DBLINKed or synonym'ed tables
resolve_synonyms=False, dblink='', **kw):
if resolve_synonyms:
- actual_name, owner, dblink, synonym = self._resolve_synonym(connection, desired_owner=self.denormalize_name(schema), desired_synonym=self.denormalize_name(table_name))
+ actual_name, owner, dblink, synonym = self._resolve_synonym(
+ connection,
+ desired_owner=self.denormalize_name(schema),
+ desired_synonym=self.denormalize_name(table_name)
+ )
else:
actual_name, owner, dblink, synonym = None, None, None, None
if not actual_name:
def result_processor(self, dialect, coltype):
# if we know cx_Oracle will return unicode,
# don't process results
- if self.convert_unicode != 'force' and \
+ if dialect._cx_oracle_with_unicode:
+ return None
+ elif self.convert_unicode != 'force' and \
dialect._cx_oracle_native_nvarchar and \
coltype == dialect.dbapi.UNICODE:
return None
# on String, including that outparams/RETURNING
# breaks for varchars
self.set_input_sizes(quoted_bind_names,
- exclude_types=[
- self.dialect.dbapi.STRING,
- self.dialect.dbapi.UNICODE])
+ exclude_types=self.dialect._cx_oracle_string_types
+ )
if len(self.compiled_parameters) == 1:
for key in self.compiled.binds:
if self.cursor.description is not None:
for column in self.cursor.description:
type_code = column[1]
- if type_code in self.dialect.ORACLE_BINARY_TYPES:
+ if type_code in self.dialect._cx_oracle_binary_types:
result = base.BufferedColumnResultProxy(self)
if result is None:
cx_oracle_ver = vers(self.dbapi.version)
self.supports_unicode_binds = cx_oracle_ver >= (5, 0)
self._cx_oracle_native_nvarchar = cx_oracle_ver >= (5, 0)
-
- if self.dbapi is None or not self.auto_convert_lobs or not 'CLOB' in self.dbapi.__dict__:
+
+ if self.dbapi is not None and not hasattr(self.dbapi, 'UNICODE'):
+ # cx_Oracle WITH_UNICODE mode. *only* python
+ # unicode objects accepted for anything
+ self._cx_oracle_string_types = set([self.dbapi.STRING])
+ self.supports_unicode_statements = True
+ self.supports_unicode_binds = True
+ self._cx_oracle_with_unicode = True
+ else:
+ self._cx_oracle_with_unicode = False
+ if self.dbapi is not None:
+ self._cx_oracle_string_types = set([self.dbapi.UNICODE, self.dbapi.STRING])
+ else:
+ self._cx_oracle_string_types = set()
+
+ if self.dbapi is None or \
+ not self.auto_convert_lobs or \
+ not hasattr(self.dbapi, 'CLOB'):
self.dbapi_type_map = {}
- self.ORACLE_BINARY_TYPES = []
+ self._cx_oracle_binary_types = set()
else:
# only use this for LOB objects. using it for strings, dates
# etc. leads to a little too much magic, reflection doesn't know if it should
self.dbapi.BLOB: oracle.BLOB(),
self.dbapi.BINARY: oracle.RAW(),
}
- self.ORACLE_BINARY_TYPES = [getattr(self.dbapi, k) for k in ["BFILE", "CLOB", "NCLOB", "BLOB"] if hasattr(self.dbapi, k)]
+ self._cx_oracle_binary_types = set([getattr(self.dbapi, k) for k in
+ ["BFILE", "CLOB", "NCLOB", "BLOB"]
+ if hasattr(self.dbapi, k)])
@classmethod
def dbapi(cls):
threaded=self.threaded,
twophase=self.allow_twophase,
)
+
+ # Py2K
+ if self._cx_oracle_with_unicode:
+ for k, v in opts.items():
+ if isinstance(v, str):
+ opts[k] = unicode(v)
+ # end Py2K
+
if 'mode' in url.query:
opts['mode'] = url.query['mode']
if isinstance(opts['mode'], basestring):