diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-02 14:23:42 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-02 14:23:42 -0500 |
commit | 350aed3fdb9f1e73e69655e53f44ca6a91c196da (patch) | |
tree | 3d2a128667b5f6ca6d0b4e1f4865fc98aac6b60b /lib/sqlalchemy/dialects | |
parent | 71f92436bdc86f30e2c21d8f5244733601e8c39e (diff) | |
download | sqlalchemy-350aed3fdb9f1e73e69655e53f44ca6a91c196da.tar.gz |
- whitespace removal bonanza
Diffstat (limited to 'lib/sqlalchemy/dialects')
31 files changed, 480 insertions, 480 deletions
diff --git a/lib/sqlalchemy/dialects/access/base.py b/lib/sqlalchemy/dialects/access/base.py index dfeaf23c2..0dd09cebf 100644 --- a/lib/sqlalchemy/dialects/access/base.py +++ b/lib/sqlalchemy/dialects/access/base.py @@ -153,7 +153,7 @@ class AccessDialect(default.DefaultDialect): supports_sane_multi_rowcount = False ported_sqla_06 = False - + def type_descriptor(self, typeobj): newobj = types.adapt_type(typeobj, self.colspecs) return newobj @@ -341,7 +341,7 @@ class AccessCompiler(compiler.SQLCompiler): 'dow': 'w', 'week': 'ww' }) - + def visit_select_precolumns(self, select): """Access puts TOP, it's version of LIMIT here """ s = select.distinct and "DISTINCT " or "" diff --git a/lib/sqlalchemy/dialects/firebird/__init__.py b/lib/sqlalchemy/dialects/firebird/__init__.py index 1fdedbafa..e87b5bb5c 100644 --- a/lib/sqlalchemy/dialects/firebird/__init__.py +++ b/lib/sqlalchemy/dialects/firebird/__init__.py @@ -12,11 +12,11 @@ from sqlalchemy.dialects.firebird.base import \ SMALLINT, BIGINT, FLOAT, FLOAT, DATE, TIME, \ TEXT, NUMERIC, FLOAT, TIMESTAMP, VARCHAR, CHAR, BLOB,\ dialect - + __all__ = ( 'SMALLINT', 'BIGINT', 'FLOAT', 'FLOAT', 'DATE', 'TIME', 'TEXT', 'NUMERIC', 'FLOAT', 'TIMESTAMP', 'VARCHAR', 'CHAR', 'BLOB', 'dialect' ) - - + + diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py index d6939777b..de880171f 100644 --- a/lib/sqlalchemy/dialects/firebird/base.py +++ b/lib/sqlalchemy/dialects/firebird/base.py @@ -194,7 +194,7 @@ class FBTypeCompiler(compiler.GenericTypeCompiler): def visit_VARCHAR(self, type_): basic = super(FBTypeCompiler, self).visit_VARCHAR(type_) return self._extend_string(type_, basic) - + class FBCompiler(sql.compiler.SQLCompiler): diff --git a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py index a2624534c..ad8d44262 100644 --- a/lib/sqlalchemy/dialects/firebird/kinterbasdb.py +++ b/lib/sqlalchemy/dialects/firebird/kinterbasdb.py @@ -13,7 +13,7 @@ The connection URL is of the form Kinterbasedb backend specific keyword arguments are: -* type_conv - select the kind of mapping done on the types: by default +* type_conv - select the kind of mapping done on the types: by default SQLAlchemy uses 200 with Unicode, datetime and decimal support (see details__). @@ -34,11 +34,11 @@ Kinterbasedb backend specific keyword arguments are: SQLAlchemy ORM to ignore its usage. The behavior can also be controlled on a per-execution basis using the `enable_rowcount` option with :meth:`execution_options()`:: - + conn = engine.connect().execution_options(enable_rowcount=True) r = conn.execute(stmt) print r.rowcount - + __ http://sourceforge.net/projects/kinterbasdb __ http://firebirdsql.org/index.php?op=devel&sub=python __ http://kinterbasdb.sourceforge.net/dist_docs/usage.html#adv_param_conv_dynamic_type_translation @@ -66,23 +66,23 @@ class FBExecutionContext_kinterbasdb(FBExecutionContext): return self.cursor.rowcount else: return -1 - + class FBDialect_kinterbasdb(FBDialect): driver = 'kinterbasdb' supports_sane_rowcount = False supports_sane_multi_rowcount = False execution_ctx_cls = FBExecutionContext_kinterbasdb - + supports_native_decimal = True - + colspecs = util.update_copy( FBDialect.colspecs, { sqltypes.Numeric:_FBNumeric_kinterbasdb } - + ) - + def __init__(self, type_conv=200, concurrency_level=1, enable_rowcount=True, **kwargs): super(FBDialect_kinterbasdb, self).__init__(**kwargs) @@ -91,7 +91,7 @@ class FBDialect_kinterbasdb(FBDialect): self.concurrency_level = concurrency_level if enable_rowcount: self.supports_sane_rowcount = True - + @classmethod def dbapi(cls): k = __import__('kinterbasdb') @@ -103,13 +103,13 @@ class FBDialect_kinterbasdb(FBDialect): opts['host'] = "%s/%s" % (opts['host'], opts['port']) del opts['port'] opts.update(url.query) - + util.coerce_kw_type(opts, 'type_conv', int) - + type_conv = opts.pop('type_conv', self.type_conv) concurrency_level = opts.pop('concurrency_level', self.concurrency_level) - + if self.dbapi is not None: initialized = getattr(self.dbapi, 'initialized', None) if initialized is None: diff --git a/lib/sqlalchemy/dialects/informix/base.py b/lib/sqlalchemy/dialects/informix/base.py index a97b445a3..1ea8d4e39 100644 --- a/lib/sqlalchemy/dialects/informix/base.py +++ b/lib/sqlalchemy/dialects/informix/base.py @@ -218,7 +218,7 @@ class InformixDialect(default.DefaultDialect): name = 'informix' max_identifier_length = 128 # adjusts at runtime based on server version - + type_compiler = InfoTypeCompiler statement_compiler = InfoSQLCompiler ddl_compiler = InfoDDLCompiler @@ -232,13 +232,13 @@ class InformixDialect(default.DefaultDialect): def initialize(self, connection): super(InformixDialect, self).initialize(connection) - + # http://www.querix.com/support/knowledge-base/error_number_message/error_200 if self.server_version_info < (9, 2): self.max_identifier_length = 18 else: self.max_identifier_length = 128 - + def do_begin(self, connection): cu = connection.cursor() cu.execute('SET LOCK MODE TO WAIT') @@ -327,7 +327,7 @@ class InformixDialect(default.DefaultDialect): util.warn("Did not recognize type '%s' of column '%s'" % (coltype, name)) coltype = sqltypes.NULLTYPE - + column_info = dict(name=name, type=coltype, nullable=not not_nullable, default=default, autoincrement=autoincrement, primary_key=primary_key) diff --git a/lib/sqlalchemy/dialects/informix/informixdb.py b/lib/sqlalchemy/dialects/informix/informixdb.py index 150a69d7f..c81983816 100644 --- a/lib/sqlalchemy/dialects/informix/informixdb.py +++ b/lib/sqlalchemy/dialects/informix/informixdb.py @@ -10,7 +10,7 @@ Support for the informixdb DBAPI. informixdb is available at: http://informixdb.sourceforge.net/ - + Connecting ^^^^^^^^^^ diff --git a/lib/sqlalchemy/dialects/maxdb/base.py b/lib/sqlalchemy/dialects/maxdb/base.py index 4ca81b24c..abc7ff10b 100644 --- a/lib/sqlalchemy/dialects/maxdb/base.py +++ b/lib/sqlalchemy/dialects/maxdb/base.py @@ -323,7 +323,7 @@ class MaxDBTypeCompiler(compiler.GenericTypeCompiler): def visit_large_binary(self, type_): return "LONG BYTE" - + def visit_numeric(self, type_): if type_.scale and type_.precision: return 'FIXED(%s, %s)' % (type_.precision, type_.scale) @@ -331,10 +331,10 @@ class MaxDBTypeCompiler(compiler.GenericTypeCompiler): return 'FIXED(%s)' % type_.precision else: return 'INTEGER' - + def visit_BOOLEAN(self, type_): return "BOOLEAN" - + colspecs = { sqltypes.Numeric: MaxNumeric, sqltypes.DateTime: MaxTimestamp, @@ -480,7 +480,7 @@ class MaxDBCompiler(compiler.SQLCompiler): def visit_mod(self, binary, **kw): return "mod(%s, %s)" % \ (self.process(binary.left), self.process(binary.right)) - + def default_from(self): return ' FROM DUAL' @@ -768,7 +768,7 @@ class MaxDBDDLCompiler(compiler.DDLCompiler): Defaults to False. If true, sets NOCACHE. """ sequence = create.element - + if (not sequence.optional and (not self.checkfirst or not self.dialect.has_sequence(self.connection, sequence.name))): @@ -825,7 +825,7 @@ class MaxDBDialect(default.DefaultDialect): colspecs = colspecs ischema_names = ischema_names - + # MaxDB-specific datetimeformat = 'internal' diff --git a/lib/sqlalchemy/dialects/maxdb/sapdb.py b/lib/sqlalchemy/dialects/maxdb/sapdb.py index 4fd9dd418..da04d809f 100644 --- a/lib/sqlalchemy/dialects/maxdb/sapdb.py +++ b/lib/sqlalchemy/dialects/maxdb/sapdb.py @@ -8,7 +8,7 @@ from sqlalchemy.dialects.maxdb.base import MaxDBDialect class MaxDBDialect_sapdb(MaxDBDialect): driver = 'sapdb' - + @classmethod def dbapi(cls): from sapdb import dbapi as _dbapi diff --git a/lib/sqlalchemy/dialects/mssql/adodbapi.py b/lib/sqlalchemy/dialects/mssql/adodbapi.py index d18880931..355214d89 100644 --- a/lib/sqlalchemy/dialects/mssql/adodbapi.py +++ b/lib/sqlalchemy/dialects/mssql/adodbapi.py @@ -31,7 +31,7 @@ class MSDialect_adodbapi(MSDialect): supports_unicode = sys.maxunicode == 65535 supports_unicode_statements = True driver = 'adodbapi' - + @classmethod def import_dbapi(cls): import adodbapi as module diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index dda63080d..290cd1019 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -18,7 +18,7 @@ Auto Increment Behavior ``schema.Sequence()`` objects. In other words:: from sqlalchemy import Table, Integer, Sequence, Column - + Table('test', metadata, Column('id', Integer, Sequence('blah',100,10), primary_key=True), @@ -261,7 +261,7 @@ class SMALLDATETIME(_DateTimeBase, sqltypes.DateTime): class DATETIME2(_DateTimeBase, sqltypes.DateTime): __visit_name__ = 'DATETIME2' - + def __init__(self, precision=None, **kw): super(DATETIME2, self).__init__(**kw) self.precision = precision @@ -270,7 +270,7 @@ class DATETIME2(_DateTimeBase, sqltypes.DateTime): # TODO: is this not an Interval ? class DATETIMEOFFSET(sqltypes.TypeEngine): __visit_name__ = 'DATETIMEOFFSET' - + def __init__(self, precision=None, **kwargs): self.precision = precision @@ -298,7 +298,7 @@ class NTEXT(_StringType, sqltypes.UnicodeText): characters.""" __visit_name__ = 'NTEXT' - + def __init__(self, length=None, collation=None, **kw): """Construct a NTEXT. @@ -405,7 +405,7 @@ class IMAGE(sqltypes.LargeBinary): class BIT(sqltypes.TypeEngine): __visit_name__ = 'BIT' - + class MONEY(sqltypes.TypeEngine): __visit_name__ = 'MONEY' @@ -487,13 +487,13 @@ class MSTypeCompiler(compiler.GenericTypeCompiler): collation = 'COLLATE %s' % type_.collation else: collation = None - + if not length: length = type_.length - + if length: spec = spec + "(%s)" % length - + return ' '.join([c for c in (spec, collation) if c is not None]) @@ -535,10 +535,10 @@ class MSTypeCompiler(compiler.GenericTypeCompiler): def visit_unicode(self, type_): return self.visit_NVARCHAR(type_) - + def visit_unicode_text(self, type_): return self.visit_NTEXT(type_) - + def visit_NTEXT(self, type_): return self._extend("NTEXT", type_) @@ -570,7 +570,7 @@ class MSTypeCompiler(compiler.GenericTypeCompiler): return self.visit_DATETIME(type_) else: return self.visit_TIME(type_) - + def visit_large_binary(self, type_): return self.visit_IMAGE(type_) @@ -600,7 +600,7 @@ class MSExecutionContext(default.DefaultExecutionContext): _select_lastrowid = False _result_proxy = None _lastrowid = None - + def pre_exec(self): """Activate IDENTITY_INSERT if needed.""" @@ -608,25 +608,25 @@ class MSExecutionContext(default.DefaultExecutionContext): tbl = self.compiled.statement.table seq_column = tbl._autoincrement_column insert_has_sequence = seq_column is not None - + if insert_has_sequence: self._enable_identity_insert = \ seq_column.key in self.compiled_parameters[0] else: self._enable_identity_insert = False - + self._select_lastrowid = insert_has_sequence and \ not self.compiled.returning and \ not self._enable_identity_insert and \ not self.executemany - + if self._enable_identity_insert: self.cursor.execute("SET IDENTITY_INSERT %s ON" % self.dialect.identifier_preparer.format_table(tbl)) def post_exec(self): """Disable IDENTITY_INSERT if enabled.""" - + if self._select_lastrowid: if self.dialect.use_scope_identity: self.cursor.execute( @@ -640,17 +640,17 @@ class MSExecutionContext(default.DefaultExecutionContext): if (self.isinsert or self.isupdate or self.isdelete) and \ self.compiled.returning: self._result_proxy = base.FullyBufferedResultProxy(self) - + if self._enable_identity_insert: self.cursor.execute( - "SET IDENTITY_INSERT %s OFF" % + "SET IDENTITY_INSERT %s OFF" % self.dialect.identifier_preparer. format_table(self.compiled.statement.table) ) - + def get_lastrowid(self): return self._lastrowid - + def handle_dbapi_exception(self, e): if self._enable_identity_insert: try: @@ -670,7 +670,7 @@ class MSExecutionContext(default.DefaultExecutionContext): class MSSQLCompiler(compiler.SQLCompiler): returning_precedes_values = True - + extract_map = util.update_copy( compiler.SQLCompiler.extract_map, { @@ -686,31 +686,31 @@ class MSSQLCompiler(compiler.SQLCompiler): def visit_now_func(self, fn, **kw): return "CURRENT_TIMESTAMP" - + def visit_current_date_func(self, fn, **kw): return "GETDATE()" - + def visit_length_func(self, fn, **kw): return "LEN%s" % self.function_argspec(fn, **kw) - + def visit_char_length_func(self, fn, **kw): return "LEN%s" % self.function_argspec(fn, **kw) - + def visit_concat_op(self, binary, **kw): return "%s + %s" % \ (self.process(binary.left, **kw), self.process(binary.right, **kw)) - + def visit_match_op(self, binary, **kw): return "CONTAINS (%s, %s)" % ( self.process(binary.left, **kw), self.process(binary.right, **kw)) - + def get_select_precolumns(self, select): """ MS-SQL puts TOP, it's version of LIMIT here """ if select._distinct or select._limit: s = select._distinct and "DISTINCT " or "" - + # ODBC drivers and possibly others # don't support bind params in the SELECT clause on SQL Server. # so have to use literal here. @@ -743,7 +743,7 @@ class MSSQLCompiler(compiler.SQLCompiler): sql.literal_column("ROW_NUMBER() OVER (ORDER BY %s)" \ % orderby).label("mssql_rn") ).order_by(None).alias() - + mssql_rn = sql.column('mssql_rn') limitselect = sql.select([c for c in select.c if c.key!='mssql_rn']) @@ -853,7 +853,7 @@ class MSSQLCompiler(compiler.SQLCompiler): target = stmt.table.alias("inserted") else: target = stmt.table.alias("deleted") - + adapter = sql_util.ClauseAdapter(target) def col_label(col): adapted = adapter.traverse(col) @@ -861,7 +861,7 @@ class MSSQLCompiler(compiler.SQLCompiler): return adapted.label(c.key) else: return self.label_select_column(None, adapted, asfrom=False) - + columns = [ self.process( col_label(c), @@ -896,10 +896,10 @@ class MSSQLCompiler(compiler.SQLCompiler): class MSSQLStrictCompiler(MSSQLCompiler): """A subclass of MSSQLCompiler which disables the usage of bind parameters where not allowed natively by MS-SQL. - + A dialect may use this compiler on a platform where native binds are used. - + """ ansi_bind_rules = True @@ -927,9 +927,9 @@ class MSSQLStrictCompiler(MSSQLCompiler): format acceptable to MSSQL. That seems to be the so-called ODBC canonical date format which looks like this: - + yyyy-mm-dd hh:mi:ss.mmm(24h) - + For other data types, call the base class implementation. """ # datetime and date are both subclasses of datetime.date @@ -950,12 +950,12 @@ class MSDDLCompiler(compiler.DDLCompiler): colspec += " NOT NULL" else: colspec += " NULL" - + if column.table is None: raise exc.InvalidRequestError( "mssql requires Table-bound columns " "in order to generate DDL") - + seq_col = column.table._autoincrement_column # install a IDENTITY Sequence if we have an implicit IDENTITY column @@ -1015,13 +1015,13 @@ class MSDialect(default.DefaultDialect): } ischema_names = ischema_names - + supports_native_boolean = False supports_unicode_binds = True postfetch_lastrowid = True - + server_version_info = () - + statement_compiler = MSSQLCompiler ddl_compiler = MSDDLCompiler type_compiler = MSTypeCompiler @@ -1039,7 +1039,7 @@ class MSDialect(default.DefaultDialect): self.max_identifier_length = int(max_identifier_length or 0) or \ self.max_identifier_length super(MSDialect, self).__init__(**opts) - + def do_savepoint(self, connection, name): util.warn("Savepoint support in mssql is experimental and " "may lead to data loss.") @@ -1048,7 +1048,7 @@ class MSDialect(default.DefaultDialect): def do_release_savepoint(self, connection, name): pass - + def initialize(self, connection): super(MSDialect, self).initialize(connection) if self.server_version_info[0] not in range(8, 17): @@ -1064,7 +1064,7 @@ class MSDialect(default.DefaultDialect): if self.server_version_info >= MS_2005_VERSION and \ 'implicit_returning' not in self.__dict__: self.implicit_returning = True - + def _get_default_schema_name(self, connection): user_name = connection.scalar("SELECT user_name() as user_name;") if user_name is not None: @@ -1138,7 +1138,7 @@ class MSDialect(default.DefaultDialect): # below MS 2005 if self.server_version_info < MS_2005_VERSION: return [] - + current_schema = schema or self.default_schema_name full_tname = "%s.%s" % (current_schema, tablename) @@ -1186,7 +1186,7 @@ class MSDialect(default.DefaultDialect): for row in rp: if row['index_id'] in indexes: indexes[row['index_id']]['column_names'].append(row['name']) - + return indexes.values() @reflection.cache @@ -1315,7 +1315,7 @@ class MSDialect(default.DefaultDialect): # the constrained column C = ischema.key_constraints.alias('C') # information_schema.constraint_column_usage: - # the referenced column + # the referenced column R = ischema.key_constraints.alias('R') # Primary key constraints @@ -1337,7 +1337,7 @@ class MSDialect(default.DefaultDialect): #information_schema.referential_constraints RR = ischema.ref_constraints # information_schema.table_constraints - TC = ischema.constraints + TC = ischema.constraints # information_schema.constraint_column_usage: # the constrained column C = ischema.key_constraints.alias('C') @@ -1361,12 +1361,12 @@ class MSDialect(default.DefaultDialect): order_by = [ RR.c.constraint_name, R.c.ordinal_position]) - + # group rows by constraint ID, to handle multi-column FKs fkeys = [] fknm, scols, rcols = (None, [], []) - + def fkey_rec(): return { 'name' : None, @@ -1377,7 +1377,7 @@ class MSDialect(default.DefaultDialect): } fkeys = util.defaultdict(fkey_rec) - + for r in connection.execute(s).fetchall(): scol, rschema, rtbl, rcol, rfknm, fkmatch, fkuprule, fkdelrule = r @@ -1388,11 +1388,11 @@ class MSDialect(default.DefaultDialect): if schema is not None or current_schema != rschema: rec['referred_schema'] = rschema - + local_cols, remote_cols = \ rec['constrained_columns'],\ rec['referred_columns'] - + local_cols.append(scol) remote_cols.append(rcol) diff --git a/lib/sqlalchemy/dialects/mssql/information_schema.py b/lib/sqlalchemy/dialects/mssql/information_schema.py index 5806ebfa8..87dd0a167 100644 --- a/lib/sqlalchemy/dialects/mssql/information_schema.py +++ b/lib/sqlalchemy/dialects/mssql/information_schema.py @@ -13,12 +13,12 @@ ischema = MetaData() class CoerceUnicode(TypeDecorator): impl = Unicode - + def process_bind_param(self, value, dialect): if isinstance(value, str): value = value.decode(dialect.encoding) return value - + schemata = Table("SCHEMATA", ischema, Column("CATALOG_NAME", CoerceUnicode, key="catalog_name"), Column("SCHEMA_NAME", CoerceUnicode, key="schema_name"), @@ -74,8 +74,8 @@ ref_constraints = Table("REFERENTIAL_CONSTRAINTS", ischema, Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"), # TODO: is CATLOG misspelled ? Column("UNIQUE_CONSTRAINT_CATLOG", CoerceUnicode, - key="unique_constraint_catalog"), - + key="unique_constraint_catalog"), + Column("UNIQUE_CONSTRAINT_SCHEMA", CoerceUnicode, key="unique_constraint_schema"), Column("UNIQUE_CONSTRAINT_NAME", CoerceUnicode, diff --git a/lib/sqlalchemy/dialects/mssql/mxodbc.py b/lib/sqlalchemy/dialects/mssql/mxodbc.py index ba695ef08..6a830509a 100644 --- a/lib/sqlalchemy/dialects/mssql/mxodbc.py +++ b/lib/sqlalchemy/dialects/mssql/mxodbc.py @@ -20,7 +20,7 @@ Connecting Connection is via DSN:: mssql+mxodbc://<username>:<password>@<dsnname> - + Execution Modes ~~~~~~~~~~~~~~~ @@ -72,7 +72,7 @@ class MSExecutionContext_mxodbc(MSExecutionContext_pyodbc): # won't work. class MSDialect_mxodbc(MxODBCConnector, MSDialect): - + # TODO: may want to use this only if FreeTDS is not in use, # since FreeTDS doesn't seem to use native binds. statement_compiler = MSSQLStrictCompiler diff --git a/lib/sqlalchemy/dialects/mssql/pymssql.py b/lib/sqlalchemy/dialects/mssql/pymssql.py index aa3bf45d2..192e63366 100644 --- a/lib/sqlalchemy/dialects/mssql/pymssql.py +++ b/lib/sqlalchemy/dialects/mssql/pymssql.py @@ -12,10 +12,10 @@ This dialect supports pymssql 1.0 and greater. pymssql is available at: http://pymssql.sourceforge.net/ - + Connecting ^^^^^^^^^^ - + Sample connect string:: mssql+pymssql://<username>:<password>@<freetds_name> @@ -53,7 +53,7 @@ class MSDialect_pymssql(MSDialect): supports_sane_rowcount = False max_identifier_length = 30 driver = 'pymssql' - + colspecs = util.update_copy( MSDialect.colspecs, { @@ -67,7 +67,7 @@ class MSDialect_pymssql(MSDialect): # pymmsql doesn't have a Binary method. we use string # TODO: monkeypatching here is less than ideal module.Binary = str - + client_ver = tuple(int(x) for x in module.__version__.split(".")) if client_ver < (1, ): util.warn("The pymssql dialect expects at least " diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 90a43889e..9b88dce2a 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -86,15 +86,15 @@ import decimal class _MSNumeric_pyodbc(sqltypes.Numeric): """Turns Decimals with adjusted() < 0 or > 7 into strings. - + This is the only method that is proven to work with Pyodbc+MSSQL without crashing (floats can be used but seem to cause sporadic crashes). - + """ def bind_processor(self, dialect): - + super_process = super(_MSNumeric_pyodbc, self).\ bind_processor(dialect) @@ -104,7 +104,7 @@ class _MSNumeric_pyodbc(sqltypes.Numeric): def process(value): if self.asdecimal and \ isinstance(value, decimal.Decimal): - + adjusted = value.adjusted() if adjusted < 0: return self._small_dec_to_string(value) @@ -116,10 +116,10 @@ class _MSNumeric_pyodbc(sqltypes.Numeric): else: return value return process - + # these routines needed for older versions of pyodbc. # as of 2.1.8 this logic is integrated. - + def _small_dec_to_string(self, value): return "%s0.%s%s" % ( (value < 0 and '-' or ''), @@ -147,24 +147,24 @@ class _MSNumeric_pyodbc(sqltypes.Numeric): "".join( [str(s) for s in _int][0:value.adjusted() + 1])) return result - - + + class MSExecutionContext_pyodbc(MSExecutionContext): _embedded_scope_identity = False - + def pre_exec(self): """where appropriate, issue "select scope_identity()" in the same statement. - + Background on why "scope_identity()" is preferable to "@@identity": http://msdn.microsoft.com/en-us/library/ms190315.aspx - + Background on why we attempt to embed "scope_identity()" into the same statement as the INSERT: http://code.google.com/p/pyodbc/wiki/FAQs#How_do_I_retrieve_autogenerated/identity_values? - + """ - + super(MSExecutionContext_pyodbc, self).pre_exec() # don't embed the scope_identity select into an @@ -173,7 +173,7 @@ class MSExecutionContext_pyodbc(MSExecutionContext): self.dialect.use_scope_identity and \ len(self.parameters[0]): self._embedded_scope_identity = True - + self.statement += "; select scope_identity()" def post_exec(self): @@ -185,13 +185,13 @@ class MSExecutionContext_pyodbc(MSExecutionContext): try: # fetchall() ensures the cursor is consumed # without closing it (FreeTDS particularly) - row = self.cursor.fetchall()[0] + row = self.cursor.fetchall()[0] break except self.dialect.dbapi.Error, e: # no way around this - nextset() consumes the previous set # so we need to just keep flipping self.cursor.nextset() - + self._lastrowid = int(row[0]) else: super(MSExecutionContext_pyodbc, self).post_exec() @@ -202,14 +202,14 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect): execution_ctx_cls = MSExecutionContext_pyodbc pyodbc_driver_name = 'SQL Server' - + colspecs = util.update_copy( MSDialect.colspecs, { sqltypes.Numeric:_MSNumeric_pyodbc } ) - + def __init__(self, description_encoding='latin-1', **params): super(MSDialect_pyodbc, self).__init__(**params) self.description_encoding = description_encoding @@ -217,5 +217,5 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect): hasattr(self.dbapi.Cursor, 'nextset') self._need_decimal_fix = self.dbapi and \ tuple(self.dbapi.version.split(".")) < (2, 1, 8) - + dialect = MSDialect_pyodbc diff --git a/lib/sqlalchemy/dialects/mysql/__init__.py b/lib/sqlalchemy/dialects/mysql/__init__.py index 6eb54588a..fe1ef49b2 100644 --- a/lib/sqlalchemy/dialects/mysql/__init__.py +++ b/lib/sqlalchemy/dialects/mysql/__init__.py @@ -18,7 +18,7 @@ from sqlalchemy.dialects.mysql.base import \ NVARCHAR, NUMERIC, SET, SMALLINT, REAL, TEXT, TIME, TIMESTAMP, \ TINYBLOB, TINYINT, TINYTEXT,\ VARBINARY, VARCHAR, YEAR, dialect - + __all__ = ( 'BIGINT', 'BINARY', 'BIT', 'BLOB', 'BOOLEAN', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'DOUBLE', 'ENUM', 'DECIMAL', 'FLOAT', 'INTEGER', 'INTEGER', 'LONGBLOB', 'LONGTEXT', 'MEDIUMBLOB', 'MEDIUMINT', diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 6585c4016..e26d83f0a 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -39,7 +39,7 @@ Connecting ---------- See the API documentation on individual drivers for details on connecting. - + Connection Timeouts ------------------- @@ -235,7 +235,7 @@ class _NumericType(object): self.unsigned = unsigned self.zerofill = zerofill super(_NumericType, self).__init__(**kw) - + class _FloatType(_NumericType, sqltypes.Float): def __init__(self, precision=None, scale=None, asdecimal=True, **kw): if isinstance(self, (REAL, DOUBLE)) and \ @@ -274,7 +274,7 @@ class _StringType(sqltypes.String): self.binary = binary self.national = national super(_StringType, self).__init__(**kw) - + def __repr__(self): attributes = inspect.getargspec(self.__init__)[0][1:] attributes.extend(inspect.getargspec(_StringType.__init__)[0][1:]) @@ -291,9 +291,9 @@ class _StringType(sqltypes.String): class NUMERIC(_NumericType, sqltypes.NUMERIC): """MySQL NUMERIC type.""" - + __visit_name__ = 'NUMERIC' - + def __init__(self, precision=None, scale=None, asdecimal=True, **kw): """Construct a NUMERIC. @@ -315,9 +315,9 @@ class NUMERIC(_NumericType, sqltypes.NUMERIC): class DECIMAL(_NumericType, sqltypes.DECIMAL): """MySQL DECIMAL type.""" - + __visit_name__ = 'DECIMAL' - + def __init__(self, precision=None, scale=None, asdecimal=True, **kw): """Construct a DECIMAL. @@ -337,7 +337,7 @@ class DECIMAL(_NumericType, sqltypes.DECIMAL): super(DECIMAL, self).__init__(precision=precision, scale=scale, asdecimal=asdecimal, **kw) - + class DOUBLE(_FloatType): """MySQL DOUBLE type.""" @@ -538,12 +538,12 @@ class BIT(sqltypes.TypeEngine): def result_processor(self, dialect, coltype): """Convert a MySQL's 64 bit, variable length binary string to a long. - + TODO: this is MySQL-db, pyodbc specific. OurSQL and mysqlconnector already do this, so this logic should be moved to those dialects. - + """ - + def process(value): if value is not None: v = 0L @@ -710,7 +710,7 @@ class LONGTEXT(_StringType): """ super(LONGTEXT, self).__init__(**kwargs) - + class VARCHAR(_StringType, sqltypes.VARCHAR): """MySQL VARCHAR type, for variable-length character data.""" @@ -818,7 +818,7 @@ class NCHAR(_StringType, sqltypes.NCHAR): class TINYBLOB(sqltypes._Binary): """MySQL TINYBLOB type, for binary data up to 2^8 bytes.""" - + __visit_name__ = 'TINYBLOB' class MEDIUMBLOB(sqltypes._Binary): @@ -886,7 +886,7 @@ class ENUM(sqltypes.Enum, _StringType): """ self.quoting = kw.pop('quoting', 'auto') - + if self.quoting == 'auto' and len(enums): # What quoting character are we using? q = None @@ -919,7 +919,7 @@ class ENUM(sqltypes.Enum, _StringType): kw.pop('native_enum', None) _StringType.__init__(self, length=length, **kw) sqltypes.Enum.__init__(self, *enums) - + @classmethod def _strip_enums(cls, enums): strip_enums = [] @@ -929,7 +929,7 @@ class ENUM(sqltypes.Enum, _StringType): a = a[1:-1].replace(a[0] * 2, a[0]) strip_enums.append(a) return strip_enums - + def bind_processor(self, dialect): super_convert = super(ENUM, self).bind_processor(dialect) def process(value): @@ -941,7 +941,7 @@ class ENUM(sqltypes.Enum, _StringType): else: return value return process - + def adapt(self, impltype, **kw): kw['strict'] = self.strict return sqltypes.Enum.adapt(self, impltype, **kw) @@ -1121,19 +1121,19 @@ class MySQLCompiler(compiler.SQLCompiler): extract_map.update ({ 'milliseconds': 'millisecond', }) - + def visit_random_func(self, fn, **kw): return "rand%s" % self.function_argspec(fn) - + def visit_utc_timestamp_func(self, fn, **kw): return "UTC_TIMESTAMP" - + def visit_sysdate_func(self, fn, **kw): return "SYSDATE()" - + def visit_concat_op(self, binary, **kw): return "concat(%s, %s)" % (self.process(binary.left), self.process(binary.right)) - + def visit_match_op(self, binary, **kw): return "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)" % (self.process(binary.left), self.process(binary.right)) @@ -1170,7 +1170,7 @@ class MySQLCompiler(compiler.SQLCompiler): # No cast until 4, no decimals until 5. if not self.dialect._supports_cast: return self.process(cast.clause) - + type_ = self.process(cast.typeclause) if type_ is None: return self.process(cast.clause) @@ -1182,7 +1182,7 @@ class MySQLCompiler(compiler.SQLCompiler): if self.dialect._backslash_escapes: value = value.replace('\\', '\\\\') return value - + def get_select_precolumns(self, select): if isinstance(select._distinct, basestring): return select._distinct.upper() + " " @@ -1274,7 +1274,7 @@ class MySQLDDLCompiler(compiler.DDLCompiler): def create_table_constraints(self, table): """Get table constraints.""" constraint_string = super(MySQLDDLCompiler, self).create_table_constraints(table) - + is_innodb = table.kwargs.has_key('mysql_engine') and \ table.kwargs['mysql_engine'].lower() == 'innodb' @@ -1287,7 +1287,7 @@ class MySQLDDLCompiler(compiler.DDLCompiler): constraint_string += ", \n\t" constraint_string += "KEY `idx_autoinc_%s`(`%s`)" % (auto_inc_column.name, \ self.preparer.format_column(auto_inc_column)) - + return constraint_string @@ -1301,7 +1301,7 @@ class MySQLDDLCompiler(compiler.DDLCompiler): default = self.get_column_default_string(column) if default is not None: colspec.append('DEFAULT ' + default) - + is_timestamp = isinstance(column.type, sqltypes.TIMESTAMP) if not column.nullable and not is_timestamp: colspec.append('NOT NULL') @@ -1349,7 +1349,7 @@ class MySQLDDLCompiler(compiler.DDLCompiler): def visit_drop_index(self, drop): index = drop.element - + return "\nDROP INDEX %s ON %s" % \ (self.preparer.quote(self._index_identifier(index.name), index.quote), self.preparer.format_table(index.table)) @@ -1390,10 +1390,10 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): COLLATE annotations and MySQL specific extensions. """ - + def attr(name): return getattr(type_, name, defaults.get(name)) - + if attr('charset'): charset = 'CHARACTER SET %s' % attr('charset') elif attr('ascii'): @@ -1416,10 +1416,10 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): if c is not None]) return ' '.join([c for c in (spec, charset, collation) if c is not None]) - + def _mysql_type(self, type_): return isinstance(type_, (_StringType, _NumericType)) - + def visit_NUMERIC(self, type_): if type_.precision is None: return self._extend_numeric(type_, "NUMERIC") @@ -1451,7 +1451,7 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): 'scale' : type_.scale}) else: return self._extend_numeric(type_, 'REAL') - + def visit_FLOAT(self, type_): if self._mysql_type(type_) and type_.scale is not None and type_.precision is not None: return self._extend_numeric(type_, "FLOAT(%s, %s)" % (type_.precision, type_.scale)) @@ -1459,19 +1459,19 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): return self._extend_numeric(type_, "FLOAT(%s)" % (type_.precision,)) else: return self._extend_numeric(type_, "FLOAT") - + def visit_INTEGER(self, type_): if self._mysql_type(type_) and type_.display_width is not None: return self._extend_numeric(type_, "INTEGER(%(display_width)s)" % {'display_width': type_.display_width}) else: return self._extend_numeric(type_, "INTEGER") - + def visit_BIGINT(self, type_): if self._mysql_type(type_) and type_.display_width is not None: return self._extend_numeric(type_, "BIGINT(%(display_width)s)" % {'display_width': type_.display_width}) else: return self._extend_numeric(type_, "BIGINT") - + def visit_MEDIUMINT(self, type_): if self._mysql_type(type_) and type_.display_width is not None: return self._extend_numeric(type_, "MEDIUMINT(%(display_width)s)" % {'display_width': type_.display_width}) @@ -1495,7 +1495,7 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): return "BIT(%s)" % type_.length else: return "BIT" - + def visit_DATETIME(self, type_): return "DATETIME" @@ -1513,34 +1513,34 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): return "YEAR" else: return "YEAR(%s)" % type_.display_width - + def visit_TEXT(self, type_): if type_.length: return self._extend_string(type_, {}, "TEXT(%d)" % type_.length) else: return self._extend_string(type_, {}, "TEXT") - + def visit_TINYTEXT(self, type_): return self._extend_string(type_, {}, "TINYTEXT") def visit_MEDIUMTEXT(self, type_): return self._extend_string(type_, {}, "MEDIUMTEXT") - + def visit_LONGTEXT(self, type_): return self._extend_string(type_, {}, "LONGTEXT") - + def visit_VARCHAR(self, type_): if type_.length: return self._extend_string(type_, {}, "VARCHAR(%d)" % type_.length) else: raise exc.InvalidRequestError("VARCHAR requires a length when rendered on MySQL") - + def visit_CHAR(self, type_): if type_.length: return self._extend_string(type_, {}, "CHAR(%(length)s)" % {'length' : type_.length}) else: return self._extend_string(type_, {}, "CHAR") - + def visit_NVARCHAR(self, type_): # We'll actually generate the equiv. "NATIONAL VARCHAR" instead # of "NVARCHAR". @@ -1548,32 +1548,32 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): return self._extend_string(type_, {'national':True}, "VARCHAR(%(length)s)" % {'length': type_.length}) else: raise exc.InvalidRequestError("NVARCHAR requires a length when rendered on MySQL") - + def visit_NCHAR(self, type_): # We'll actually generate the equiv. "NATIONAL CHAR" instead of "NCHAR". if type_.length: return self._extend_string(type_, {'national':True}, "CHAR(%(length)s)" % {'length': type_.length}) else: return self._extend_string(type_, {'national':True}, "CHAR") - + def visit_VARBINARY(self, type_): return "VARBINARY(%d)" % type_.length - + def visit_large_binary(self, type_): return self.visit_BLOB(type_) - + def visit_enum(self, type_): if not type_.native_enum: return super(MySQLTypeCompiler, self).visit_enum(type_) else: return self.visit_ENUM(type_) - + def visit_BLOB(self, type_): if type_.length: return "BLOB(%d)" % type_.length else: return "BLOB" - + def visit_TINYBLOB(self, type_): return "TINYBLOB" @@ -1588,13 +1588,13 @@ class MySQLTypeCompiler(compiler.GenericTypeCompiler): for e in type_.enums: quoted_enums.append("'%s'" % e.replace("'", "''")) return self._extend_string(type_, {}, "ENUM(%s)" % ",".join(quoted_enums)) - + def visit_SET(self, type_): return self._extend_string(type_, {}, "SET(%s)" % ",".join(type_._ddl_values)) def visit_BOOLEAN(self, type): return "BOOL" - + class MySQLIdentifierPreparer(compiler.IdentifierPreparer): @@ -1604,7 +1604,7 @@ class MySQLIdentifierPreparer(compiler.IdentifierPreparer): if not server_ansiquotes: quote = "`" else: - quote = '"' + quote = '"' super(MySQLIdentifierPreparer, self).__init__( dialect, @@ -1618,34 +1618,34 @@ class MySQLIdentifierPreparer(compiler.IdentifierPreparer): class MySQLDialect(default.DefaultDialect): """Details of the MySQL dialect. Not used directly in application code.""" - + name = 'mysql' supports_alter = True - + # identifiers are 64, however aliases can be 255... max_identifier_length = 255 max_index_name_length = 64 - + supports_native_enum = True - + supports_sane_rowcount = True supports_sane_multi_rowcount = False - + default_paramstyle = 'format' colspecs = colspecs - + statement_compiler = MySQLCompiler ddl_compiler = MySQLDDLCompiler type_compiler = MySQLTypeCompiler ischema_names = ischema_names preparer = MySQLIdentifierPreparer - + # default SQL compilation settings - # these are modified upon initialize(), # i.e. first connect _backslash_escapes = True _server_ansiquotes = False - + def __init__(self, use_ansiquotes=None, **kwargs): default.DefaultDialect.__init__(self, **kwargs) @@ -1705,7 +1705,7 @@ class MySQLDialect(default.DefaultDialect): if isinstance(e, self.dbapi.OperationalError): return self._extract_error_code(e) in \ (2006, 2013, 2014, 2045, 2055) - elif isinstance(e, self.dbapi.InterfaceError): + elif isinstance(e, self.dbapi.InterfaceError): # if underlying connection is closed, # this is the error you get return "(0, '')" in str(e) @@ -1729,7 +1729,7 @@ class MySQLDialect(default.DefaultDialect): def _extract_error_code(self, exception): raise NotImplementedError() - + def _get_default_schema_name(self, connection): return connection.execute('SELECT DATABASE()').scalar() @@ -1764,7 +1764,7 @@ class MySQLDialect(default.DefaultDialect): finally: if rs: rs.close() - + def initialize(self, connection): default.DefaultDialect.initialize(self, connection) self._connection_charset = self._detect_charset(connection) @@ -1781,7 +1781,7 @@ class MySQLDialect(default.DefaultDialect): def _supports_cast(self): return self.server_version_info is None or \ self.server_version_info >= (4, 0, 2) - + @reflection.cache def get_schema_names(self, connection, **kw): rp = connection.execute("SHOW schemas") @@ -1806,7 +1806,7 @@ class MySQLDialect(default.DefaultDialect): return [row[0] for row in self._compat_fetchall(rp, charset=charset)\ if row[1] == 'BASE TABLE'] - + @reflection.cache def get_view_names(self, connection, schema=None, **kw): charset = self._connection_charset @@ -1848,7 +1848,7 @@ class MySQLDialect(default.DefaultDialect): parsed_state = self._parsed_state_or_create(connection, table_name, schema, **kw) default_schema = None - + fkeys = [] for spec in parsed_state.constraints: @@ -1886,7 +1886,7 @@ class MySQLDialect(default.DefaultDialect): def get_indexes(self, connection, table_name, schema=None, **kw): parsed_state = self._parsed_state_or_create(connection, table_name, schema, **kw) - + indexes = [] for spec in parsed_state.keys: unique = False @@ -1926,14 +1926,14 @@ class MySQLDialect(default.DefaultDialect): schema, info_cache=kw.get('info_cache', None) ) - + @util.memoized_property def _tabledef_parser(self): """return the MySQLTableDefinitionParser, generate if needed. - + The deferred creation ensures that the dialect has retrieved server version information first. - + """ if (self.server_version_info < (4, 1) and self._server_ansiquotes): # ANSI_QUOTES doesn't affect SHOW CREATE TABLE on < 4.1 @@ -1941,7 +1941,7 @@ class MySQLDialect(default.DefaultDialect): else: preparer = self.identifier_preparer return MySQLTableDefinitionParser(self, preparer) - + @reflection.cache def _setup_parser(self, connection, table_name, schema=None, **kw): charset = self._connection_charset @@ -1956,7 +1956,7 @@ class MySQLDialect(default.DefaultDialect): full_name=full_name) sql = parser._describe_to_create(table_name, columns) return parser.parse(sql, charset) - + def _adjust_casing(self, table, charset=None): """Adjust Table name to the server case sensitivity, if needed.""" @@ -2030,10 +2030,10 @@ class MySQLDialect(default.DefaultDialect): mode = (mode_no | 4 == mode_no) and 'ANSI_QUOTES' or '' self._server_ansiquotes = 'ANSI_QUOTES' in mode - + # as of MySQL 5.0.1 self._backslash_escapes = 'NO_BACKSLASH_ESCAPES' not in mode - + def _show_create_table(self, connection, table, charset=None, full_name=None): """Run SHOW CREATE TABLE for a ``Table``.""" @@ -2082,17 +2082,17 @@ class MySQLDialect(default.DefaultDialect): class ReflectedState(object): """Stores raw information about a SHOW CREATE TABLE statement.""" - + def __init__(self): self.columns = [] self.table_options = {} self.table_name = None self.keys = [] self.constraints = [] - + class MySQLTableDefinitionParser(object): """Parses the results of a SHOW CREATE TABLE statement.""" - + def __init__(self, dialect, preparer): self.dialect = dialect self.preparer = preparer @@ -2125,9 +2125,9 @@ class MySQLTableDefinitionParser(object): state.constraints.append(spec) else: pass - + return state - + def _parse_constraints(self, line): """Parse a KEY or CONSTRAINT line. @@ -2278,7 +2278,7 @@ class MySQLTableDefinitionParser(object): if default == 'NULL': # eliminates the need to deal with this later. default = None - + col_d = dict(name=name, type=type_instance, default=default) col_d.update(col_kw) state.columns.append(col_d) diff --git a/lib/sqlalchemy/dialects/mysql/mysqldb.py b/lib/sqlalchemy/dialects/mysql/mysqldb.py index ced873039..e9e1cdbba 100644 --- a/lib/sqlalchemy/dialects/mysql/mysqldb.py +++ b/lib/sqlalchemy/dialects/mysql/mysqldb.py @@ -9,7 +9,7 @@ MySQL-Python is available at: http://sourceforge.net/projects/mysql-python - + At least version 1.2.1 or 1.2.2 should be used. Connecting @@ -18,7 +18,7 @@ Connecting Connect string format:: mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> - + Character Sets -------------- @@ -42,7 +42,7 @@ Known Issues ------------- MySQL-python at least as of version 1.2.2 has a serious memory leak related -to unicode conversion, a feature which is disabled via ``use_unicode=0``. +to unicode conversion, a feature which is disabled via ``use_unicode=0``. The recommended connection form with SQLAlchemy is:: engine = create_engine('mysql://scott:tiger@localhost/test?charset=utf8&use_unicode=0', pool_recycle=3600) @@ -60,25 +60,25 @@ from sqlalchemy import exc, log, schema, sql, types as sqltypes, util from sqlalchemy import processors class MySQLExecutionContext_mysqldb(MySQLExecutionContext): - + @property def rowcount(self): if hasattr(self, '_rowcount'): return self._rowcount else: return self.cursor.rowcount - - + + class MySQLCompiler_mysqldb(MySQLCompiler): def visit_mod(self, binary, **kw): return self.process(binary.left) + " %% " + self.process(binary.right) - + def post_process_text(self, text): return text.replace('%', '%%') class MySQLIdentifierPreparer_mysqldb(MySQLIdentifierPreparer): - + def _escape_identifier(self, value): value = value.replace(self.escape_quote, self.escape_to_quote) return value.replace("%", "%%") @@ -95,13 +95,13 @@ class MySQLDialect_mysqldb(MySQLDialect): execution_ctx_cls = MySQLExecutionContext_mysqldb statement_compiler = MySQLCompiler_mysqldb preparer = MySQLIdentifierPreparer_mysqldb - + colspecs = util.update_copy( MySQLDialect.colspecs, { } ) - + @classmethod def dbapi(cls): return __import__('MySQLdb') @@ -149,7 +149,7 @@ class MySQLDialect_mysqldb(MySQLDialect): pass opts['client_flag'] = client_flag return [[], opts] - + def _get_server_version_info(self, connection): dbapi_con = connection.connection version = [] diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py index b4d9485d3..d3ef839b1 100644 --- a/lib/sqlalchemy/dialects/mysql/oursql.py +++ b/lib/sqlalchemy/dialects/mysql/oursql.py @@ -9,7 +9,7 @@ OurSQL is available at: http://packages.python.org/oursql/ - + Connecting ----------- @@ -61,7 +61,7 @@ class MySQLExecutionContext_oursql(MySQLExecutionContext): @property def plain_query(self): return self.execution_options.get('_oursql_plain_query', False) - + class MySQLDialect_oursql(MySQLDialect): driver = 'oursql' # Py3K @@ -70,9 +70,9 @@ class MySQLDialect_oursql(MySQLDialect): supports_unicode_binds = True supports_unicode_statements = True # end Py2K - + supports_native_decimal = True - + supports_sane_rowcount = True supports_sane_multi_rowcount = True execution_ctx_cls = MySQLExecutionContext_oursql @@ -132,7 +132,7 @@ class MySQLDialect_oursql(MySQLDialect): if not is_prepared: self.do_prepare_twophase(connection, xid) self._xa_query(connection, 'XA COMMIT "%s"', xid) - + # Q: why didn't we need all these "plain_query" overrides earlier ? # am i on a newer/older version of OurSQL ? def has_table(self, connection, table_name, schema=None): @@ -140,7 +140,7 @@ class MySQLDialect_oursql(MySQLDialect): connection.connect().\ execution_options(_oursql_plain_query=True), table_name, schema) - + def get_table_options(self, connection, table_name, schema=None, **kw): return MySQLDialect.get_table_options(self, connection.connect().\ @@ -159,7 +159,7 @@ class MySQLDialect_oursql(MySQLDialect): schema=schema, **kw ) - + def get_view_names(self, connection, schema=None, **kw): return MySQLDialect.get_view_names(self, connection.connect().\ @@ -167,27 +167,27 @@ class MySQLDialect_oursql(MySQLDialect): schema=schema, **kw ) - + def get_table_names(self, connection, schema=None, **kw): return MySQLDialect.get_table_names(self, connection.connect().\ execution_options(_oursql_plain_query=True), schema ) - + def get_schema_names(self, connection, **kw): return MySQLDialect.get_schema_names(self, connection.connect().\ execution_options(_oursql_plain_query=True), **kw ) - + def initialize(self, connection): return MySQLDialect.initialize( self, connection.execution_options(_oursql_plain_query=True) ) - + def _show_create_table(self, connection, table, charset=None, full_name=None): return MySQLDialect._show_create_table(self, @@ -196,7 +196,7 @@ class MySQLDialect_oursql(MySQLDialect): table, charset, full_name) def is_disconnect(self, e): - if isinstance(e, self.dbapi.ProgrammingError): + if isinstance(e, self.dbapi.ProgrammingError): return e.errno is None and 'cursor' not in e.args[1] and e.args[1].endswith('closed') else: return e.errno in (2006, 2013, 2014, 2045, 2055) @@ -240,7 +240,7 @@ class MySQLDialect_oursql(MySQLDialect): def _detect_charset(self, connection): """Sniff out the character set in use for connection results.""" - + return connection.connection.charset def _compat_fetchall(self, rp, charset=None): diff --git a/lib/sqlalchemy/dialects/mysql/pyodbc.py b/lib/sqlalchemy/dialects/mysql/pyodbc.py index d103c56c8..84d43cf27 100644 --- a/lib/sqlalchemy/dialects/mysql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mysql/pyodbc.py @@ -47,7 +47,7 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect): execution_ctx_cls = MySQLExecutionContext_pyodbc pyodbc_driver_name = "MySQL" - + def __init__(self, **kw): # deal with http://code.google.com/p/pyodbc/issues/detail?id=25 kw.setdefault('convert_unicode', True) @@ -70,7 +70,7 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect): util.warn("Could not detect the connection character set. Assuming latin1.") return 'latin1' - + def _extract_error_code(self, exception): m = re.compile(r"\((\d+)\)").search(str(exception.args)) c = m.group(1) diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index defab2947..bacad3704 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -132,7 +132,7 @@ from sqlalchemy.sql import operators as sql_operators, functions as sql_function from sqlalchemy import types as sqltypes from sqlalchemy.types import VARCHAR, NVARCHAR, CHAR, DATE, DATETIME, \ BLOB, CLOB, TIMESTAMP, FLOAT - + RESERVED_WORDS = set('SHARE RAW DROP BETWEEN FROM DESC OPTION PRIOR LONG THEN ' 'DEFAULT ALTER IS INTO MINUS INTEGER NUMBER GRANT IDENTIFIED ' 'ALL TO ORDER ON FLOAT DATE HAVING CLUSTER NOWAIT RESOURCE ANY ' @@ -155,33 +155,33 @@ NVARCHAR2 = NVARCHAR class NUMBER(sqltypes.Numeric, sqltypes.Integer): __visit_name__ = 'NUMBER' - + def __init__(self, precision=None, scale=None, asdecimal=None): if asdecimal is None: asdecimal = bool(scale and scale > 0) - + super(NUMBER, self).__init__(precision=precision, scale=scale, asdecimal=asdecimal) - + def adapt(self, impltype): ret = super(NUMBER, self).adapt(impltype) # leave a hint for the DBAPI handler ret._is_oracle_number = True return ret - + @property def _type_affinity(self): if bool(self.scale and self.scale > 0): return sqltypes.Numeric else: return sqltypes.Integer - - + + class DOUBLE_PRECISION(sqltypes.Numeric): __visit_name__ = 'DOUBLE_PRECISION' def __init__(self, precision=None, scale=None, asdecimal=None): if asdecimal is None: asdecimal = False - + super(DOUBLE_PRECISION, self).__init__(precision=precision, scale=scale, asdecimal=asdecimal) class BFILE(sqltypes.LargeBinary): @@ -192,44 +192,44 @@ class LONG(sqltypes.Text): class INTERVAL(sqltypes.TypeEngine): __visit_name__ = 'INTERVAL' - + def __init__(self, day_precision=None, second_precision=None): """Construct an INTERVAL. - + Note that only DAY TO SECOND intervals are currently supported. This is due to a lack of support for YEAR TO MONTH intervals within available DBAPIs (cx_oracle and zxjdbc). - + :param day_precision: the day precision value. this is the number of digits to store for the day field. Defaults to "2" :param second_precision: the second precision value. this is the number of digits to store for the fractional seconds field. Defaults to "6". - + """ self.day_precision = day_precision self.second_precision = second_precision - + @classmethod def _adapt_from_generic_interval(cls, interval): return INTERVAL(day_precision=interval.day_precision, second_precision=interval.second_precision) - + @property def _type_affinity(self): return sqltypes.Interval class ROWID(sqltypes.TypeEngine): """Oracle ROWID type. - + When used in a cast() or similar, generates ROWID. - + """ __visit_name__ = 'ROWID' - - - + + + class _OracleBoolean(sqltypes.Boolean): def get_dbapi_type(self, dbapi): return dbapi.NUMBER @@ -264,19 +264,19 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): # Oracle DATE == DATETIME # Oracle does not allow milliseconds in DATE # Oracle does not support TIME columns - + def visit_datetime(self, type_): return self.visit_DATE(type_) - + def visit_float(self, type_): return self.visit_FLOAT(type_) - + def visit_unicode(self, type_): if self.dialect._supports_nchar: return self.visit_NVARCHAR(type_) else: return self.visit_VARCHAR(type_) - + def visit_INTERVAL(self, type_): return "INTERVAL DAY%s TO SECOND%s" % ( type_.day_precision is not None and @@ -295,24 +295,24 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): def visit_DOUBLE_PRECISION(self, type_): return self._generate_numeric(type_, "DOUBLE PRECISION") - + def visit_NUMBER(self, type_, **kw): return self._generate_numeric(type_, "NUMBER", **kw) - + def _generate_numeric(self, type_, name, precision=None, scale=None): if precision is None: precision = type_.precision - + if scale is None: scale = getattr(type_, 'scale', None) - + if precision is None: return name elif scale is None: return "%(name)s(%(precision)s)" % {'name':name,'precision': precision} else: return "%(name)s(%(precision)s, %(scale)s)" % {'name':name,'precision': precision, 'scale' : scale} - + def visit_VARCHAR(self, type_): if self.dialect._supports_char_length: return "VARCHAR(%(length)s CHAR)" % {'length' : type_.length} @@ -321,7 +321,7 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): def visit_NVARCHAR(self, type_): return "NVARCHAR2(%(length)s)" % {'length' : type_.length} - + def visit_text(self, type_): return self.visit_CLOB(type_) @@ -336,29 +336,29 @@ class OracleTypeCompiler(compiler.GenericTypeCompiler): def visit_big_integer(self, type_): return self.visit_NUMBER(type_, precision=19) - + def visit_boolean(self, type_): return self.visit_SMALLINT(type_) - + def visit_RAW(self, type_): return "RAW(%(length)s)" % {'length' : type_.length} def visit_ROWID(self, type_): return "ROWID" - + class OracleCompiler(compiler.SQLCompiler): """Oracle compiler modifies the lexical structure of Select statements to work under non-ANSI configured Oracle databases, if the use_ansi flag is False. """ - + compound_keywords = util.update_copy( compiler.SQLCompiler.compound_keywords, - { + { expression.CompoundSelect.EXCEPT : 'MINUS' } ) - + def __init__(self, *args, **kwargs): super(OracleCompiler, self).__init__(*args, **kwargs) self.__wheres = {} @@ -366,27 +366,27 @@ class OracleCompiler(compiler.SQLCompiler): def visit_mod(self, binary, **kw): return "mod(%s, %s)" % (self.process(binary.left), self.process(binary.right)) - + def visit_now_func(self, fn, **kw): return "CURRENT_TIMESTAMP" - + def visit_char_length_func(self, fn, **kw): return "LENGTH" + self.function_argspec(fn, **kw) - + def visit_match_op(self, binary, **kw): return "CONTAINS (%s, %s)" % (self.process(binary.left), self.process(binary.right)) - + def get_select_hint_text(self, byfroms): return " ".join( "/*+ %s */" % text for table, text in byfroms.items() ) - + def function_argspec(self, fn, **kw): if len(fn.clauses) > 0: return compiler.SQLCompiler.function_argspec(self, fn, **kw) else: return "" - + def default_from(self): """Called when a ``SELECT`` statement has no froms, and no ``FROM`` clause is to be appended. @@ -418,15 +418,15 @@ class OracleCompiler(compiler.SQLCompiler): {'binary':visit_binary})) else: clauses.append(join.onclause) - + for j in join.left, join.right: if isinstance(j, expression.Join): visit_join(j) - + for f in froms: if isinstance(f, expression.Join): visit_join(f) - + if not clauses: return None else: @@ -440,11 +440,11 @@ class OracleCompiler(compiler.SQLCompiler): def visit_alias(self, alias, asfrom=False, ashint=False, **kwargs): """Oracle doesn't like ``FROM table AS alias``. Is the AS standard SQL??""" - + if asfrom or ashint: alias_name = isinstance(alias.name, expression._generated_label) and \ self._truncated_identifier("alias", alias.name) or alias.name - + if ashint: return alias_name elif asfrom: @@ -454,19 +454,19 @@ class OracleCompiler(compiler.SQLCompiler): return self.process(alias.original, **kwargs) def returning_clause(self, stmt, returning_cols): - + def create_out_param(col, i): bindparam = sql.outparam("ret_%d" % i, type_=col.type) self.binds[bindparam.key] = bindparam return self.bindparam_string(self._truncate_bindparam(bindparam)) - + columnlist = list(expression._select_iterables(returning_cols)) - + # within_columns_clause =False so that labels (foo AS bar) don't render columns = [self.process(c, within_columns_clause=False, result_map=self.result_map) for c in columnlist] - + binds = [create_out_param(c, i) for i, c in enumerate(columnlist)] - + return 'RETURNING ' + ', '.join(columns) + " INTO " + ", ".join(binds) def _TODO_visit_compound_select(self, select): @@ -484,7 +484,7 @@ class OracleCompiler(compiler.SQLCompiler): existingfroms = self.stack[-1]['from'] else: existingfroms = None - + froms = select._get_display_froms(existingfroms) whereclause = self._get_nonansi_join_whereclause(froms) if whereclause is not None: @@ -513,7 +513,7 @@ class OracleCompiler(compiler.SQLCompiler): limitselect._oracle_visit = True limitselect._is_wrapper = True - + # If needed, add the limiting clause if select._limit is not None: max_row = select._limit @@ -563,7 +563,7 @@ class OracleDDLCompiler(compiler.DDLCompiler): text = "" if constraint.ondelete is not None: text += " ON DELETE %s" % constraint.ondelete - + # oracle has no ON UPDATE CASCADE - # its only available via triggers http://asktom.oracle.com/tkyte/update_cascade/index.html if constraint.onupdate is not None: @@ -571,11 +571,11 @@ class OracleDDLCompiler(compiler.DDLCompiler): "Oracle does not contain native UPDATE CASCADE " "functionality - onupdates will not be rendered for foreign keys. " "Consider using deferrable=True, initially='deferred' or triggers.") - + return text class OracleIdentifierPreparer(compiler.IdentifierPreparer): - + reserved_words = set([x.lower() for x in RESERVED_WORDS]) illegal_initial_characters = set(xrange(0, 10)).union(["_", "$"]) @@ -586,18 +586,18 @@ class OracleIdentifierPreparer(compiler.IdentifierPreparer): or value[0] in self.illegal_initial_characters or not self.legal_characters.match(unicode(value)) ) - + def format_savepoint(self, savepoint): name = re.sub(r'^_+', '', savepoint.ident) return super(OracleIdentifierPreparer, self).format_savepoint(savepoint, name) - - + + class OracleExecutionContext(default.DefaultExecutionContext): def fire_sequence(self, seq): return int(self._execute_scalar("SELECT " + self.dialect.identifier_preparer.format_sequence(seq) + ".nextval FROM DUAL")) - + class OracleDialect(default.DefaultDialect): name = 'oracle' supports_alter = True @@ -610,21 +610,21 @@ class OracleDialect(default.DefaultDialect): supports_sequences = True sequences_optional = False postfetch_lastrowid = False - + default_paramstyle = 'named' colspecs = colspecs ischema_names = ischema_names requires_name_normalize = True - + supports_default_values = False supports_empty_insert = False - + statement_compiler = OracleCompiler ddl_compiler = OracleDDLCompiler type_compiler = OracleTypeCompiler preparer = OracleIdentifierPreparer execution_ctx_cls = OracleExecutionContext - + reflection_options = ('oracle_resolve_synonyms', ) def __init__(self, @@ -641,7 +641,7 @@ class OracleDialect(default.DefaultDialect): 'implicit_returning', self.server_version_info > (10, ) ) - + if self._is_oracle_8: self.colspecs = self.colspecs.copy() self.colspecs.pop(sqltypes.Interval) @@ -651,7 +651,7 @@ class OracleDialect(default.DefaultDialect): def _is_oracle_8(self): return self.server_version_info and \ self.server_version_info < (9, ) - + @property def _supports_char_length(self): return not self._is_oracle_8 @@ -659,7 +659,7 @@ class OracleDialect(default.DefaultDialect): @property def _supports_nchar(self): return not self._is_oracle_8 - + def do_release_savepoint(self, connection, name): # Oracle does not support RELEASE SAVEPOINT pass @@ -868,7 +868,7 @@ class OracleDialect(default.DefaultDialect): def get_indexes(self, connection, table_name, schema=None, resolve_synonyms=False, dblink='', **kw): - + info_cache = kw.get('info_cache') (table_name, schema, dblink, synonym) = \ self._prepare_reflection_args(connection, table_name, schema, @@ -883,7 +883,7 @@ class OracleDialect(default.DefaultDialect): a.index_name = b.index_name AND a.table_owner = b.table_owner AND a.table_name = b.table_name - + AND a.table_name = :table_name AND a.table_owner = :schema ORDER BY a.index_name, a.column_position""" % {'dblink': dblink}) @@ -896,7 +896,7 @@ class OracleDialect(default.DefaultDialect): dblink=dblink, info_cache=kw.get('info_cache')) uniqueness = dict(NONUNIQUE=False, UNIQUE=True) - + oracle_sys_col = re.compile(r'SYS_NC\d+\$', re.IGNORECASE) def upper_name_set(names): @@ -983,7 +983,7 @@ class OracleDialect(default.DefaultDialect): constraint_data = self._get_constraint_data(connection, table_name, schema, dblink, info_cache=kw.get('info_cache')) - + for row in constraint_data: #print "ROW:" , row (cons_name, cons_type, local_column, remote_table, remote_column, remote_owner) = \ @@ -1038,7 +1038,7 @@ class OracleDialect(default.DefaultDialect): } fkeys = util.defaultdict(fkey_rec) - + for row in constraint_data: (cons_name, cons_type, local_column, remote_table, remote_column, remote_owner) = \ row[0:2] + tuple([self.normalize_name(x) for x in row[2:6]]) @@ -1067,12 +1067,12 @@ class OracleDialect(default.DefaultDialect): if ref_synonym: remote_table = self.normalize_name(ref_synonym) remote_owner = self.normalize_name(ref_remote_owner) - + rec['referred_table'] = remote_table - + if requested_schema is not None or self.denormalize_name(remote_owner) != schema: rec['referred_schema'] = remote_owner - + local_cols.append(local_column) remote_cols.append(remote_column) @@ -1102,7 +1102,7 @@ class OracleDialect(default.DefaultDialect): class _OuterJoinColumn(sql.ClauseElement): __visit_name__ = 'outer_join_column' - + def __init__(self, column): self.column = column diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index f4f4912ef..04f3aab95 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -31,7 +31,7 @@ URL, or as keyword arguments to :func:`~sqlalchemy.create_engine()` are: * *arraysize* - set the cx_oracle.arraysize value on cursors, in SQLAlchemy it defaults to 50. See the section on "LOB Objects" below. - + * *auto_convert_lobs* - defaults to True, see the section on LOB objects. * *auto_setinputsizes* - the cx_oracle.setinputsizes() call is issued for all bind parameters. @@ -62,7 +62,7 @@ these to strings so that the interface of the Binary type is consistent with tha other backends, and so that the linkage to a live cursor is not needed in scenarios like result.fetchmany() and result.fetchall(). This means that by default, LOB objects are fully fetched unconditionally by SQLAlchemy, and the linkage to a live -cursor is broken. +cursor is broken. To disable this processing, pass ``auto_convert_lobs=False`` to :func:`create_engine()`. @@ -144,7 +144,7 @@ class _OracleNumeric(sqltypes.Numeric): # regardless of the scale given for the originating type. # So we still need an old school isinstance() handler # here for decimals. - + if dialect.supports_native_decimal: if self.asdecimal: if self.scale is None: @@ -190,7 +190,7 @@ class _LOBMixin(object): if not dialect.auto_convert_lobs: # return the cx_oracle.LOB directly. return None - + def process(value): if value is not None: return value.read() @@ -213,11 +213,11 @@ class _NativeUnicodeMixin(object): else: return super(_NativeUnicodeMixin, self).bind_processor(dialect) # end Py2K - + # we apply a connection output handler that returns # unicode in all cases, so the "native_unicode" flag # will be set for the default String.result_processor. - + class _OracleChar(_NativeUnicodeMixin, sqltypes.CHAR): def get_dbapi_type(self, dbapi): return dbapi.FIXED_CHAR @@ -225,7 +225,7 @@ class _OracleChar(_NativeUnicodeMixin, sqltypes.CHAR): class _OracleNVarChar(_NativeUnicodeMixin, sqltypes.NVARCHAR): def get_dbapi_type(self, dbapi): return getattr(dbapi, 'UNICODE', dbapi.STRING) - + class _OracleText(_LOBMixin, sqltypes.Text): def get_dbapi_type(self, dbapi): return dbapi.CLOB @@ -258,7 +258,7 @@ class _OracleInteger(sqltypes.Integer): val = int(val) return val return to_int - + class _OracleBinary(_LOBMixin, sqltypes.LargeBinary): def get_dbapi_type(self, dbapi): return dbapi.BLOB @@ -269,14 +269,14 @@ class _OracleBinary(_LOBMixin, sqltypes.LargeBinary): class _OracleInterval(oracle.INTERVAL): def get_dbapi_type(self, dbapi): return dbapi.INTERVAL - + class _OracleRaw(oracle.RAW): pass class _OracleRowid(oracle.ROWID): def get_dbapi_type(self, dbapi): return dbapi.ROWID - + class OracleCompiler_cx_oracle(OracleCompiler): def bindparam_string(self, name): if self.preparer._bindparam_requires_quotes(name): @@ -286,9 +286,9 @@ class OracleCompiler_cx_oracle(OracleCompiler): else: return OracleCompiler.bindparam_string(self, name) - + class OracleExecutionContext_cx_oracle(OracleExecutionContext): - + def pre_exec(self): quoted_bind_names = \ getattr(self.compiled, '_quoted_bind_names', None) @@ -331,7 +331,7 @@ class OracleExecutionContext_cx_oracle(OracleExecutionContext): self.out_parameters[name] = self.cursor.var(dbtype) self.parameters[0][quoted_bind_names.get(name, name)] = \ self.out_parameters[name] - + def create_cursor(self): c = self._dbapi_connection.cursor() if self.dialect.arraysize: @@ -353,15 +353,15 @@ class OracleExecutionContext_cx_oracle(OracleExecutionContext): type_code = column[1] if type_code in self.dialect._cx_oracle_binary_types: result = base.BufferedColumnResultProxy(self) - + if result is None: result = base.ResultProxy(self) - + if hasattr(self, 'out_parameters'): if self.compiled_parameters is not None and \ len(self.compiled_parameters) == 1: result.out_parameters = out_parameters = {} - + for bind, name in self.compiled.bind_names.items(): if name in self.out_parameters: type = bind.type @@ -385,16 +385,16 @@ class OracleExecutionContext_cx_oracle(OracleExecutionContext): class OracleExecutionContext_cx_oracle_with_unicode(OracleExecutionContext_cx_oracle): """Support WITH_UNICODE in Python 2.xx. - + WITH_UNICODE allows cx_Oracle's Python 3 unicode handling behavior under Python 2.x. This mode in some cases disallows and in other cases silently passes corrupted data when non-Python-unicode strings (a.k.a. plain old Python strings) are passed as arguments to connect(), the statement sent to execute(), - or any of the bind parameter keys or values sent to execute(). + or any of the bind parameter keys or values sent to execute(). This optional context therefore ensures that all statements are passed as Python unicode objects. - + """ def __init__(self, *arg, **kw): OracleExecutionContext_cx_oracle.__init__(self, *arg, **kw) @@ -403,17 +403,17 @@ class OracleExecutionContext_cx_oracle_with_unicode(OracleExecutionContext_cx_or def _execute_scalar(self, stmt): return super(OracleExecutionContext_cx_oracle_with_unicode, self).\ _execute_scalar(unicode(stmt)) - + class ReturningResultProxy(base.FullyBufferedResultProxy): """Result proxy which stuffs the _returning clause + outparams into the fetch.""" - + def __init__(self, context, returning_params): self._returning_params = returning_params super(ReturningResultProxy, self).__init__(context) - + def _cursor_description(self): returning = self.context.compiled.returning - + ret = [] for c in returning: if hasattr(c, 'name'): @@ -421,7 +421,7 @@ class ReturningResultProxy(base.FullyBufferedResultProxy): else: ret.append((c.anon_label, c.type)) return ret - + def _buffer_rows(self): return [tuple(self._returning_params["ret_%d" % i] for i, c in enumerate(self._returning_params))] @@ -431,7 +431,7 @@ class OracleDialect_cx_oracle(OracleDialect): statement_compiler = OracleCompiler_cx_oracle driver = "cx_oracle" - + colspecs = colspecs = { sqltypes.Numeric: _OracleNumeric, sqltypes.Date : _OracleDate, # generic type, assume datetime.date is desired @@ -452,9 +452,9 @@ class OracleDialect_cx_oracle(OracleDialect): oracle.ROWID: _OracleRowid, } - + execute_sequence_format = list - + def __init__(self, auto_setinputsizes=True, auto_convert_lobs=True, @@ -468,12 +468,12 @@ class OracleDialect_cx_oracle(OracleDialect): self.supports_timestamp = self.dbapi is None or hasattr(self.dbapi, 'TIMESTAMP' ) self.auto_setinputsizes = auto_setinputsizes self.auto_convert_lobs = auto_convert_lobs - + if hasattr(self.dbapi, 'version'): self.cx_oracle_ver = tuple([int(x) for x in self.dbapi.version.split('.')]) - else: + else: self.cx_oracle_ver = (0, 0, 0) - + def types(*names): return set([ getattr(self.dbapi, name, None) for name in names @@ -536,28 +536,28 @@ class OracleDialect_cx_oracle(OracleDialect): if self._is_oracle_8: self.supports_unicode_binds = False self._detect_decimal_char(connection) - + def _detect_decimal_char(self, connection): """detect if the decimal separator character is not '.', as is the case with european locale settings for NLS_LANG. - + cx_oracle itself uses similar logic when it formats Python Decimal objects to strings on the bind side (as of 5.0.3), as Oracle sends/receives string numerics only in the current locale. - + """ if self.cx_oracle_ver < (5,): # no output type handlers before version 5 return - + cx_Oracle = self.dbapi conn = connection.connection - + # override the output_type_handler that's # on the cx_oracle connection with a plain # one on the cursor - + def output_type_handler(cursor, name, defaultType, size, precision, scale): return cursor.var( @@ -576,20 +576,20 @@ class OracleDialect_cx_oracle(OracleDialect): lambda value: _detect_decimal(value.replace(char, '.')) self._to_decimal = \ lambda value: decimal.Decimal(value.replace(char, '.')) - + def _detect_decimal(self, value): if "." in value: return decimal.Decimal(value) else: return int(value) - + _to_decimal = decimal.Decimal - + def on_connect(self): if self.cx_oracle_ver < (5,): # no output type handlers before version 5 return - + cx_Oracle = self.dbapi def output_type_handler(cursor, name, defaultType, size, precision, scale): @@ -616,12 +616,12 @@ class OracleDialect_cx_oracle(OracleDialect): # allow all strings to come back natively as Unicode elif defaultType in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR): return cursor.var(unicode, size, cursor.arraysize) - + def on_connect(conn): conn.outputtypehandler = output_type_handler - + return on_connect - + def create_connect_args(self, url): dialect_opts = dict(url.query) for opt in ('use_ansi', 'auto_setinputsizes', 'auto_convert_lobs', diff --git a/lib/sqlalchemy/dialects/postgres.py b/lib/sqlalchemy/dialects/postgres.py index fdf818a99..48d1a8c3b 100644 --- a/lib/sqlalchemy/dialects/postgres.py +++ b/lib/sqlalchemy/dialects/postgres.py @@ -11,6 +11,6 @@ warn_deprecated( "The SQLAlchemy PostgreSQL dialect has been renamed from 'postgres' to 'postgresql'. " "The new URL format is postgresql[+driver]://<user>:<pass>@<host>/<dbname>" ) - + from sqlalchemy.dialects.postgresql import * from sqlalchemy.dialects.postgresql import base diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 009f8fd94..31f699d2b 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -4,7 +4,7 @@ # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -"""Support for the PostgreSQL database. +"""Support for the PostgreSQL database. For information on connecting using specific drivers, see the documentation section regarding that driver. @@ -64,7 +64,7 @@ use the :meth:`._UpdateBase.returning` method on a per-statement basis:: result = table.insert().returning(table.c.col1, table.c.col2).\\ values(name='foo') print result.fetchall() - + # UPDATE..RETURNING result = table.update().returning(table.c.col1, table.c.col2).\\ where(table.c.name=='foo').values(name='bar') @@ -113,7 +113,7 @@ class BYTEA(sqltypes.LargeBinary): class DOUBLE_PRECISION(sqltypes.Float): __visit_name__ = 'DOUBLE_PRECISION' - + class INET(sqltypes.TypeEngine): __visit_name__ = "INET" PGInet = INET @@ -131,7 +131,7 @@ class TIMESTAMP(sqltypes.TIMESTAMP): super(TIMESTAMP, self).__init__(timezone=timezone) self.precision = precision - + class TIME(sqltypes.TIME): def __init__(self, timezone=False, precision=None): super(TIME, self).__init__(timezone=timezone) @@ -139,15 +139,15 @@ class TIME(sqltypes.TIME): class INTERVAL(sqltypes.TypeEngine): """Postgresql INTERVAL type. - + The INTERVAL type may not be supported on all DBAPIs. It is known to work on psycopg2 and not pg8000 or zxjdbc. - + """ __visit_name__ = 'INTERVAL' def __init__(self, precision=None): self.precision = precision - + @classmethod def _adapt_from_generic_interval(cls, interval): return INTERVAL(precision=interval.second_precision) @@ -155,44 +155,44 @@ class INTERVAL(sqltypes.TypeEngine): @property def _type_affinity(self): return sqltypes.Interval - + PGInterval = INTERVAL class BIT(sqltypes.TypeEngine): __visit_name__ = 'BIT' def __init__(self, length=1): self.length= length - + PGBit = BIT class UUID(sqltypes.TypeEngine): """Postgresql UUID type. - + Represents the UUID column type, interpreting data either as natively returned by the DBAPI or as Python uuid objects. The UUID type may not be supported on all DBAPIs. It is known to work on psycopg2 and not pg8000. - + """ __visit_name__ = 'UUID' - + def __init__(self, as_uuid=False): """Construct a UUID type. - - + + :param as_uuid=False: if True, values will be interpreted as Python uuid objects, converting to/from string via the DBAPI. - + """ if as_uuid and _python_UUID is None: raise NotImplementedError( "This version of Python does not support the native UUID type." ) self.as_uuid = as_uuid - + def bind_processor(self, dialect): if self.as_uuid: def process(value): @@ -202,7 +202,7 @@ class UUID(sqltypes.TypeEngine): return process else: return None - + def result_processor(self, dialect, coltype): if self.as_uuid: def process(value): @@ -212,21 +212,21 @@ class UUID(sqltypes.TypeEngine): return process else: return None - + PGUuid = UUID class ARRAY(sqltypes.MutableType, sqltypes.Concatenable, sqltypes.TypeEngine): """Postgresql ARRAY type. - + Represents values as Python lists. The ARRAY type may not be supported on all DBAPIs. It is known to work on psycopg2 and not pg8000. - - + + """ __visit_name__ = 'ARRAY' - + def __init__(self, item_type, mutable=False, as_tuple=False): """Construct an ARRAY. @@ -248,18 +248,18 @@ class ARRAY(sqltypes.MutableType, sqltypes.Concatenable, sqltypes.TypeEngine): notes for :class:`.MutableType` regarding ORM performance implications (default changed from ``True`` in 0.7.0). - + .. note:: This functionality is now superceded by the ``sqlalchemy.ext.mutable`` extension described in :ref:`mutable_toplevel`. - + :param as_tuple=False: Specify whether return results should be converted to tuples from lists. DBAPIs such as psycopg2 return lists by default. When tuples are returned, the results are hashable. This flag can only be set to ``True`` when ``mutable`` is set to ``False``. (new in 0.6.5) - + """ if isinstance(item_type, ARRAY): raise ValueError("Do not nest ARRAY types; ARRAY(basetype) " @@ -273,7 +273,7 @@ class ARRAY(sqltypes.MutableType, sqltypes.Concatenable, sqltypes.TypeEngine): "mutable must be set to False if as_tuple is True." ) self.as_tuple = as_tuple - + def copy_value(self, value): if value is None: return None @@ -343,7 +343,7 @@ class ENUM(sqltypes.Enum): def create(self, bind=None, checkfirst=True): if not bind.dialect.supports_native_enum: return - + if not checkfirst or \ not bind.dialect.has_type(bind, self.name, schema=self.schema): bind.execute(CreateEnumType(self)) @@ -355,7 +355,7 @@ class ENUM(sqltypes.Enum): if not checkfirst or \ bind.dialect.has_type(bind, self.name, schema=self.schema): bind.execute(DropEnumType(self)) - + def _on_table_create(self, event, target, bind, **kw): self.create(bind=bind, checkfirst=True) @@ -406,7 +406,7 @@ ischema_names = { class PGCompiler(compiler.SQLCompiler): - + def visit_match_op(self, binary, **kw): return "%s @@ to_tsquery(%s)" % ( self.process(binary.left), @@ -472,7 +472,7 @@ class PGCompiler(compiler.SQLCompiler): return super(PGCompiler, self).for_update_clause(select) def returning_clause(self, stmt, returning_cols): - + columns = [ self.process( self.label_select_column(None, c, asfrom=False), @@ -480,7 +480,7 @@ class PGCompiler(compiler.SQLCompiler): result_map=self.result_map) for c in expression._select_iterables(returning_cols) ] - + return 'RETURNING ' + ', '.join(columns) def visit_extract(self, extract, **kwargs): @@ -489,7 +489,7 @@ class PGCompiler(compiler.SQLCompiler): affinity = extract.expr.type._type_affinity else: affinity = None - + casts = { sqltypes.Date:'date', sqltypes.DateTime:'timestamp', @@ -530,7 +530,7 @@ class PGDDLCompiler(compiler.DDLCompiler): def visit_create_enum_type(self, create): type_ = create.element - + return "CREATE TYPE %s AS ENUM (%s)" % ( self.preparer.format_type(type_), ",".join("'%s'" % e for e in type_.enums) @@ -542,7 +542,7 @@ class PGDDLCompiler(compiler.DDLCompiler): return "DROP TYPE %s" % ( self.preparer.format_type(type_) ) - + def visit_create_index(self, create): preparer = self.preparer index = create.element @@ -555,7 +555,7 @@ class PGDDLCompiler(compiler.DDLCompiler): preparer.format_table(index.table), ', '.join([preparer.format_column(c) for c in index.columns])) - + if "postgres_where" in index.kwargs: whereclause = index.kwargs['postgres_where'] util.warn_deprecated( @@ -565,7 +565,7 @@ class PGDDLCompiler(compiler.DDLCompiler): whereclause = index.kwargs['postgresql_where'] else: whereclause = None - + if whereclause is not None: whereclause = sql_util.expression_as_ddl(whereclause) where_compiled = self.sql_compiler.process(whereclause) @@ -588,25 +588,25 @@ class PGTypeCompiler(compiler.GenericTypeCompiler): return "FLOAT" else: return "FLOAT(%(precision)s)" % {'precision': type_.precision} - + def visit_DOUBLE_PRECISION(self, type_): return "DOUBLE PRECISION" - + def visit_BIGINT(self, type_): return "BIGINT" def visit_datetime(self, type_): return self.visit_TIMESTAMP(type_) - + def visit_enum(self, type_): if not type_.native_enum or not self.dialect.supports_native_enum: return super(PGTypeCompiler, self).visit_enum(type_) else: return self.visit_ENUM(type_) - + def visit_ENUM(self, type_): return self.dialect.identifier_preparer.format_type(type_) - + def visit_TIMESTAMP(self, type_): return "TIMESTAMP%s %s" % ( getattr(type_, 'precision', None) and "(%d)" % @@ -635,7 +635,7 @@ class PGTypeCompiler(compiler.GenericTypeCompiler): def visit_large_binary(self, type_): return self.visit_BYTEA(type_) - + def visit_BYTEA(self, type_): return "BYTEA" @@ -656,12 +656,12 @@ class PGIdentifierPreparer(compiler.IdentifierPreparer): def format_type(self, type_, use_schema=True): if not type_.name: raise exc.ArgumentError("Postgresql ENUM type requires a name.") - + name = self.quote(type_.name, type_.quote) if not self.omit_schema and use_schema and type_.schema is not None: name = self.quote_schema(type_.schema, type_.quote) + "." + name return name - + class PGInspector(reflection.Inspector): def __init__(self, conn): @@ -716,27 +716,27 @@ class PGExecutionContext(default.DefaultExecutionContext): return self._execute_scalar(exc) return super(PGExecutionContext, self).get_insert_default(column) - + class PGDialect(default.DefaultDialect): name = 'postgresql' supports_alter = True max_identifier_length = 63 supports_sane_rowcount = True - + supports_native_enum = True supports_native_boolean = True - + supports_sequences = True sequences_optional = True preexecute_autoincrement_sequences = True postfetch_lastrowid = False - + supports_default_values = True supports_empty_insert = False default_paramstyle = 'pyformat' ischema_names = ischema_names colspecs = colspecs - + statement_compiler = PGCompiler ddl_compiler = PGDDLCompiler type_compiler = PGTypeCompiler @@ -776,7 +776,7 @@ class PGDialect(default.DefaultDialect): return connect else: return None - + def do_begin_twophase(self, connection, xid): self.do_begin(connection.connection) @@ -1056,24 +1056,24 @@ class PGDialect(default.DefaultDialect): rows = c.fetchall() domains = self._load_domains(connection) enums = self._load_enums(connection) - + # format columns columns = [] for name, format_type, default, notnull, attnum, table_oid in rows: ## strip (5) from character varying(5), timestamp(5) # with time zone, etc attype = re.sub(r'\([\d,]+\)', '', format_type) - + # strip '[]' from integer[], etc. attype = re.sub(r'\[\]', '', attype) - + nullable = not notnull is_array = format_type.endswith('[]') charlen = re.search('\(([\d,]+)\)', format_type) if charlen: charlen = charlen.group(1) kwargs = {} - + if attype == 'numeric': if charlen: prec, scale = charlen.split(',') @@ -1105,7 +1105,7 @@ class PGDialect(default.DefaultDialect): args = (int(charlen),) else: args = () - + while True: if attype in self.ischema_names: coltype = self.ischema_names[attype] @@ -1132,7 +1132,7 @@ class PGDialect(default.DefaultDialect): else: coltype = None break - + if coltype: coltype = coltype(*args, **kwargs) if is_array: @@ -1183,7 +1183,7 @@ class PGDialect(default.DefaultDialect): def get_pk_constraint(self, connection, table_name, schema=None, **kw): cols = self.get_primary_keys(connection, table_name, schema=schema, **kw) - + table_oid = self.get_table_oid(connection, table_name, schema, info_cache=kw.get('info_cache')) diff --git a/lib/sqlalchemy/dialects/postgresql/pg8000.py b/lib/sqlalchemy/dialects/postgresql/pg8000.py index 2187092e5..d3c2f1d50 100644 --- a/lib/sqlalchemy/dialects/postgresql/pg8000.py +++ b/lib/sqlalchemy/dialects/postgresql/pg8000.py @@ -76,27 +76,27 @@ class PGIdentifierPreparer_pg8000(PGIdentifierPreparer): value = value.replace(self.escape_quote, self.escape_to_quote) return value.replace('%', '%%') - + class PGDialect_pg8000(PGDialect): driver = 'pg8000' supports_unicode_statements = True - + supports_unicode_binds = True - + default_paramstyle = 'format' supports_sane_multi_rowcount = False execution_ctx_cls = PGExecutionContext_pg8000 statement_compiler = PGCompiler_pg8000 preparer = PGIdentifierPreparer_pg8000 - + colspecs = util.update_copy( PGDialect.colspecs, { sqltypes.Numeric : _PGNumeric, } ) - + @classmethod def dbapi(cls): return __import__('pg8000').dbapi diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index 75cf53fda..411bd42bd 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -157,7 +157,7 @@ SERVER_SIDE_CURSOR_RE = re.compile( class PGExecutionContext_psycopg2(PGExecutionContext): def create_cursor(self): # TODO: coverage for server side cursors + select.for_update() - + if self.dialect.server_side_cursors: is_server_side = \ self.execution_options.get('stream_results', True) and ( @@ -185,7 +185,7 @@ class PGExecutionContext_psycopg2(PGExecutionContext): # TODO: ouch if logger.isEnabledFor(logging.INFO): self._log_notices(self.cursor) - + if self.__is_server_side: return base.BufferedRowResultProxy(self) else: @@ -203,7 +203,7 @@ class PGExecutionContext_psycopg2(PGExecutionContext): class PGCompiler_psycopg2(PGCompiler): def visit_mod(self, binary, **kw): return self.process(binary.left) + " %% " + self.process(binary.right) - + def post_process_text(self, text): return text.replace('%', '%%') @@ -237,12 +237,12 @@ class PGDialect_psycopg2(PGDialect): self.server_side_cursors = server_side_cursors self.use_native_unicode = use_native_unicode self.supports_unicode_binds = use_native_unicode - + @classmethod def dbapi(cls): psycopg = __import__('psycopg2') return psycopg - + def on_connect(self): if self.isolation_level is not None: extensions = __import__('psycopg2.extensions').extensions @@ -251,7 +251,7 @@ class PGDialect_psycopg2(PGDialect): 'READ_UNCOMMITTED':extensions.ISOLATION_LEVEL_READ_UNCOMMITTED, 'REPEATABLE_READ':extensions.ISOLATION_LEVEL_REPEATABLE_READ, 'SERIALIZABLE':extensions.ISOLATION_LEVEL_SERIALIZABLE - + } def base_on_connect(conn): try: @@ -262,7 +262,7 @@ class PGDialect_psycopg2(PGDialect): self.isolation_level) else: base_on_connect = None - + if self.dbapi and self.use_native_unicode: extensions = __import__('psycopg2.extensions').extensions def connect(conn): @@ -292,4 +292,4 @@ class PGDialect_psycopg2(PGDialect): return False dialect = PGDialect_psycopg2 - + diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 6e050304d..c52668762 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -65,22 +65,22 @@ from sqlalchemy import processors from sqlalchemy.types import BLOB, BOOLEAN, CHAR, DATE, DATETIME, DECIMAL,\ FLOAT, INTEGER, NUMERIC, SMALLINT, TEXT, TIME,\ TIMESTAMP, VARCHAR - + class _DateTimeMixin(object): _reg = None _storage_format = None - + def __init__(self, storage_format=None, regexp=None, **kw): super(_DateTimeMixin, self).__init__(**kw) if regexp is not None: self._reg = re.compile(regexp) if storage_format is not None: self._storage_format = storage_format - + class DATETIME(_DateTimeMixin, sqltypes.DateTime): _storage_format = "%04d-%02d-%02d %02d:%02d:%02d.%06d" - + def bind_processor(self, dialect): datetime_datetime = datetime.datetime datetime_date = datetime.date @@ -122,7 +122,7 @@ class DATE(_DateTimeMixin, sqltypes.Date): raise TypeError("SQLite Date type only accepts Python " "date objects as input.") return process - + def result_processor(self, dialect, coltype): if self._reg: return processors.str_to_datetime_processor_factory( @@ -146,7 +146,7 @@ class TIME(_DateTimeMixin, sqltypes.Time): raise TypeError("SQLite Time type only accepts Python " "time objects as input.") return process - + def result_processor(self, dialect, coltype): if self._reg: return processors.str_to_datetime_processor_factory( @@ -200,10 +200,10 @@ class SQLiteCompiler(compiler.SQLCompiler): def visit_now_func(self, fn, **kw): return "CURRENT_TIMESTAMP" - + def visit_char_length_func(self, fn, **kw): return "length%s" % self.function_argspec(fn) - + def visit_cast(self, cast, **kwargs): if self.dialect.supports_cast: return super(SQLiteCompiler, self).visit_cast(cast) @@ -252,7 +252,7 @@ class SQLiteDDLCompiler(compiler.DDLCompiler): isinstance(column.type, sqltypes.Integer) and \ not column.foreign_keys: colspec += " PRIMARY KEY AUTOINCREMENT" - + return colspec def visit_primary_key_constraint(self, constraint): @@ -269,12 +269,12 @@ class SQLiteDDLCompiler(compiler.DDLCompiler): return super(SQLiteDDLCompiler, self).\ visit_primary_key_constraint(constraint) - + def visit_foreign_key_constraint(self, constraint): - + local_table = constraint._elements.values()[0].parent.table remote_table = list(constraint._elements.values())[0].column.table - + if local_table.schema != remote_table.schema: return None else: @@ -282,7 +282,7 @@ class SQLiteDDLCompiler(compiler.DDLCompiler): def define_constraint_remote_table(self, constraint, table, preparer): """Format the remote table clause of a CREATE CONSTRAINT clause.""" - + return preparer.format_table(table, use_schema=False) def visit_create_index(self, create): @@ -347,7 +347,7 @@ class SQLiteExecutionContext(default.DefaultExecutionContext): trunc_col = colname.split(".")[1] rp._metadata._set_keymap_synonym(trunc_col, colname) return rp - + class SQLiteDialect(default.DefaultDialect): name = 'sqlite' supports_alter = False @@ -356,7 +356,7 @@ class SQLiteDialect(default.DefaultDialect): supports_default_values = True supports_empty_insert = False supports_cast = True - + default_paramstyle = 'qmark' statement_compiler = SQLiteCompiler ddl_compiler = SQLiteDDLCompiler @@ -366,7 +366,7 @@ class SQLiteDialect(default.DefaultDialect): colspecs = colspecs isolation_level = None execution_ctx_cls = SQLiteExecutionContext - + supports_cast = True supports_default_values = True @@ -378,7 +378,7 @@ class SQLiteDialect(default.DefaultDialect): "Valid isolation levels for sqlite are 'SERIALIZABLE' and " "'READ UNCOMMITTED'.") self.isolation_level = isolation_level - + # this flag used by pysqlite dialect, and perhaps others in the # future, to indicate the driver is handling date/timestamp # conversions (and perhaps datetime/time as well on some @@ -391,14 +391,14 @@ class SQLiteDialect(default.DefaultDialect): self.supports_cast = \ self.dbapi.sqlite_version_info >= (3, 2, 3) - + def on_connect(self): if self.isolation_level is not None: if self.isolation_level == 'READ UNCOMMITTED': isolation_level = 1 else: isolation_level = 0 - + def connect(conn): cursor = conn.cursor() cursor.execute("PRAGMA read_uncommitted = %d" % isolation_level) @@ -439,7 +439,7 @@ class SQLiteDialect(default.DefaultDialect): qtable = quote(table_name) cursor = _pragma_cursor(connection.execute("%stable_info(%s)" % (pragma, qtable))) row = cursor.fetchone() - + # consume remaining rows, to work around # http://www.sqlite.org/cvstrac/tktview?tn=1884 while not cursor.closed and cursor.fetchone() is not None: @@ -626,7 +626,7 @@ class SQLiteDialect(default.DefaultDialect): def _pragma_cursor(cursor): """work around SQLite issue whereby cursor.description is blank when PRAGMA returns no rows.""" - + if cursor.closed: cursor.fetchone = lambda: None return cursor diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlite.py b/lib/sqlalchemy/dialects/sqlite/pysqlite.py index 261ddffe2..14cfa93d9 100644 --- a/lib/sqlalchemy/dialects/sqlite/pysqlite.py +++ b/lib/sqlalchemy/dialects/sqlite/pysqlite.py @@ -36,20 +36,20 @@ The file specification for the SQLite database is taken as the "database" portio the URL. Note that the format of a url is:: driver://user:pass@host/database - + This means that the actual filename to be used starts with the characters to the **right** of the third slash. So connecting to a relative filepath looks like:: # relative path e = create_engine('sqlite:///path/to/database.db') - + An absolute path, which is denoted by starting with a slash, means you need **four** slashes:: # absolute path e = create_engine('sqlite:////path/to/database.db') -To use a Windows path, regular drive specifications and backslashes can be used. +To use a Windows path, regular drive specifications and backslashes can be used. Double backslashes are probably needed:: # absolute path on Windows @@ -117,7 +117,7 @@ implementation suitable: SQLite file-based connections have extermely low overhead, so pooling is not necessary. The scheme also prevents a connection from being used again in a different thread and works best with SQLite's coarse-grained file locking. - + .. note:: The default selection of :class:`.NullPool` for SQLite file-based databases is new in SQLAlchemy 0.7. Previous versions select :class:`.SingletonThreadPool` by @@ -150,7 +150,7 @@ class _SQLite_pysqliteTimeStamp(DATETIME): return None else: return DATETIME.bind_processor(self, dialect) - + def result_processor(self, dialect, coltype): if dialect.native_datetime: return None @@ -163,7 +163,7 @@ class _SQLite_pysqliteDate(DATE): return None else: return DATE.bind_processor(self, dialect) - + def result_processor(self, dialect, coltype): if dialect.native_datetime: return None @@ -180,12 +180,12 @@ class SQLiteDialect_pysqlite(SQLiteDialect): sqltypes.TIMESTAMP:_SQLite_pysqliteTimeStamp, } ) - + # Py3K #description_encoding = None - + driver = 'pysqlite' - + def __init__(self, **kwargs): SQLiteDialect.__init__(self, **kwargs) diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py index 0668dcc56..3c4706043 100644 --- a/lib/sqlalchemy/dialects/sybase/base.py +++ b/lib/sqlalchemy/dialects/sybase/base.py @@ -88,10 +88,10 @@ RESERVED_WORDS = set([ "within", "work", "writetext", ]) - + class _SybaseUnitypeMixin(object): """these types appear to return a buffer object.""" - + def result_processor(self, dialect, coltype): def process(value): if value is not None: @@ -99,7 +99,7 @@ class _SybaseUnitypeMixin(object): else: return None return process - + class UNICHAR(_SybaseUnitypeMixin, sqltypes.Unicode): __visit_name__ = 'UNICHAR' @@ -114,7 +114,7 @@ class TINYINT(sqltypes.Integer): class BIT(sqltypes.TypeEngine): __visit_name__ = 'BIT' - + class MONEY(sqltypes.TypeEngine): __visit_name__ = "MONEY" @@ -123,7 +123,7 @@ class SMALLMONEY(sqltypes.TypeEngine): class UNIQUEIDENTIFIER(sqltypes.TypeEngine): __visit_name__ = "UNIQUEIDENTIFIER" - + class IMAGE(sqltypes.LargeBinary): __visit_name__ = 'IMAGE' @@ -131,7 +131,7 @@ class IMAGE(sqltypes.LargeBinary): class SybaseTypeCompiler(compiler.GenericTypeCompiler): def visit_large_binary(self, type_): return self.visit_IMAGE(type_) - + def visit_boolean(self, type_): return self.visit_BIT(type_) @@ -149,7 +149,7 @@ class SybaseTypeCompiler(compiler.GenericTypeCompiler): def visit_TINYINT(self, type_): return "TINYINT" - + def visit_IMAGE(self, type_): return "IMAGE" @@ -158,13 +158,13 @@ class SybaseTypeCompiler(compiler.GenericTypeCompiler): def visit_MONEY(self, type_): return "MONEY" - + def visit_SMALLMONEY(self, type_): return "SMALLMONEY" - + def visit_UNIQUEIDENTIFIER(self, type_): return "UNIQUEIDENTIFIER" - + ischema_names = { 'integer' : INTEGER, 'unsigned int' : INTEGER, # TODO: unsigned flags @@ -194,31 +194,31 @@ ischema_names = { class SybaseExecutionContext(default.DefaultExecutionContext): _enable_identity_insert = False - + def set_ddl_autocommit(self, connection, value): """Must be implemented by subclasses to accommodate DDL executions. - + "connection" is the raw unwrapped DBAPI connection. "value" is True or False. when True, the connection should be configured such that a DDL can take place subsequently. when False, a DDL has taken place and the connection should be resumed into non-autocommit mode. - + """ raise NotImplementedError() - + def pre_exec(self): if self.isinsert: tbl = self.compiled.statement.table seq_column = tbl._autoincrement_column insert_has_sequence = seq_column is not None - + if insert_has_sequence: self._enable_identity_insert = \ seq_column.key in self.compiled_parameters[0] else: self._enable_identity_insert = False - + if self._enable_identity_insert: self.cursor.execute("SET IDENTITY_INSERT %s ON" % self.dialect.identifier_preparer.format_table(tbl)) @@ -238,15 +238,15 @@ class SybaseExecutionContext(default.DefaultExecutionContext): self.set_ddl_autocommit( self.root_connection.connection.connection, True) - + def post_exec(self): if self.isddl: self.set_ddl_autocommit(self.root_connection, False) - + if self._enable_identity_insert: self.cursor.execute( - "SET IDENTITY_INSERT %s OFF" % + "SET IDENTITY_INSERT %s OFF" % self.dialect.identifier_preparer. format_table(self.compiled.statement.table) ) @@ -395,7 +395,7 @@ class SybaseDialect(default.DefaultDialect): self.max_identifier_length = 30 else: self.max_identifier_length = 255 - + @reflection.cache def get_table_names(self, connection, schema=None, **kw): if schema is None: diff --git a/lib/sqlalchemy/dialects/sybase/pyodbc.py b/lib/sqlalchemy/dialects/sybase/pyodbc.py index 025b33743..c8480cb43 100644 --- a/lib/sqlalchemy/dialects/sybase/pyodbc.py +++ b/lib/sqlalchemy/dialects/sybase/pyodbc.py @@ -31,7 +31,7 @@ Currently *not* supported are:: UNICHAR UNITEXT UNIVARCHAR - + """ from sqlalchemy.dialects.sybase.base import SybaseDialect,\ @@ -42,11 +42,11 @@ from sqlalchemy.util.compat import decimal class _SybNumeric_pyodbc(sqltypes.Numeric): """Turns Decimals with adjusted() < -6 into floats. - + It's not yet known how to get decimals with many significant digits or very large adjusted() into Sybase via pyodbc. - + """ def bind_processor(self, dialect): diff --git a/lib/sqlalchemy/dialects/sybase/pysybase.py b/lib/sqlalchemy/dialects/sybase/pysybase.py index d6f5c3b6b..fed792817 100644 --- a/lib/sqlalchemy/dialects/sybase/pysybase.py +++ b/lib/sqlalchemy/dialects/sybase/pysybase.py @@ -54,7 +54,7 @@ class SybaseExecutionContext_pysybase(SybaseExecutionContext): class SybaseSQLCompiler_pysybase(SybaseSQLCompiler): def bindparam_string(self, name): return "@" + name - + class SybaseDialect_pysybase(SybaseDialect): driver = 'pysybase' execution_ctx_cls = SybaseExecutionContext_pysybase diff --git a/lib/sqlalchemy/dialects/type_migration_guidelines.txt b/lib/sqlalchemy/dialects/type_migration_guidelines.txt index c26b65e08..1ca15f7fb 100644 --- a/lib/sqlalchemy/dialects/type_migration_guidelines.txt +++ b/lib/sqlalchemy/dialects/type_migration_guidelines.txt @@ -5,20 +5,20 @@ Rules for Migrating TypeEngine classes to 0.6 a. Specifying behavior which needs to occur for bind parameters or result row columns. - + b. Specifying types that are entirely specific to the database in use and have no analogue in the sqlalchemy.types package. - + c. Specifying types where there is an analogue in sqlalchemy.types, but the database in use takes vendor-specific flags for those types. d. If a TypeEngine class doesn't provide any of this, it should be *removed* from the dialect. - + 2. the TypeEngine classes are *no longer* used for generating DDL. Dialects now have a TypeCompiler subclass which uses the same visit_XXX model as -other compilers. +other compilers. 3. the "ischema_names" and "colspecs" dictionaries are now required members on the Dialect class. @@ -29,7 +29,7 @@ the current mixed case naming can remain, i.e. _PGNumeric for Numeric - in this end users would never need to use _PGNumeric directly. However, if a dialect-specific type is specifying a type *or* arguments that are not present generically, it should match the real name of the type on that backend, in uppercase. E.g. postgresql.INET, -mysql.ENUM, postgresql.ARRAY. +mysql.ENUM, postgresql.ARRAY. Or follow this handy flowchart: @@ -61,8 +61,8 @@ Or follow this handy flowchart: | v the type should - subclass the - UPPERCASE + subclass the + UPPERCASE type in types.py (i.e. class BLOB(types.BLOB)) @@ -86,14 +86,14 @@ MySQL names it SET in the dialect's base.py, and it subclasses types.String, sin it ultimately deals with strings. Example 5. Postgresql has a DATETIME type. The DBAPIs handle dates correctly, -and no special arguments are used in PG's DDL beyond what types.py provides. +and no special arguments are used in PG's DDL beyond what types.py provides. Postgresql dialect therefore imports types.DATETIME into its base.py. Ideally one should be able to specify a schema using names imported completely from a dialect, all matching the real name on that backend: from sqlalchemy.dialects.postgresql import base as pg - + t = Table('mytable', metadata, Column('id', pg.INTEGER, primary_key=True), Column('name', pg.VARCHAR(300)), @@ -110,7 +110,7 @@ indicate a special type only available in this database, it must be *removed* fr module and from this dictionary. 6. "ischema_names" indicates string descriptions of types as returned from the database -linked to TypeEngine classes. +linked to TypeEngine classes. a. The string name should be matched to the most specific type possible within sqlalchemy.types, unless there is no matching type within sqlalchemy.types in which @@ -118,28 +118,28 @@ linked to TypeEngine classes. own subclass of that type with special bind/result behavior - reflect to the types.py UPPERCASE type as much as possible. With very few exceptions, all types should reflect to an UPPERCASE type. - + b. If the dialect contains a matching dialect-specific type that takes extra arguments which the generic one does not, then point to the dialect-specific type. E.g. mssql.VARCHAR takes a "collation" parameter which should be preserved. - + 5. DDL, or what was formerly issued by "get_col_spec()", is now handled exclusively by a subclass of compiler.GenericTypeCompiler. a. your TypeCompiler class will receive generic and uppercase types from sqlalchemy.types. Do not assume the presence of dialect-specific attributes on these types. - + b. the visit_UPPERCASE methods on GenericTypeCompiler should *not* be overridden with methods that produce a different DDL name. Uppercase types don't do any kind of "guessing" - if visit_TIMESTAMP is called, the DDL should render as TIMESTAMP in all cases, regardless of whether or not that type is legal on the backend database. - + c. the visit_UPPERCASE methods *should* be overridden with methods that add additional - arguments and flags to those types. - + arguments and flags to those types. + d. the visit_lowercase methods are overridden to provide an interpretation of a generic type. E.g. visit_large_binary() might be overridden to say "return self.visit_BIT(type_)". - + e. visit_lowercase methods should *never* render strings directly - it should always be via calling a visit_UPPERCASE() method. |