2
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
2
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
4
4
# This module is part of SQLAlchemy and is released under
5
5
# the MIT License: http://www.opensource.org/licenses/mit-license.php
16
from sqlalchemy.engine import base, reflection
17
from sqlalchemy.sql import compiler, expression
18
from sqlalchemy import exc, types as sqltypes, util, pool, processors
17
from . import reflection, interfaces, result
18
from ..sql import compiler, expression
19
from .. import exc, types as sqltypes, util, pool, processors
33
34
preparer = compiler.IdentifierPreparer
34
35
supports_alter = True
37
# the first value we'd get for an autoincrement
39
default_sequence_base = 1
36
41
# most DBAPIs happy with this for execute().
38
43
execute_sequence_format = tuple
86
89
default_paramstyle = 'named'
87
90
supports_default_values = False
88
91
supports_empty_insert = True
92
supports_multivalues_insert = False
90
94
server_version_info = None
99
103
reflection_options = ()
101
def __init__(self, convert_unicode=False, assert_unicode=False,
105
def __init__(self, convert_unicode=False,
102
106
encoding='utf-8', paramstyle=None, dbapi=None,
103
107
implicit_returning=None,
104
109
label_length=None, **kwargs):
106
111
if not getattr(self, 'ported_sqla_06', True):
108
"The %s dialect is not yet ported to SQLAlchemy 0.6/0.7" %
113
"The %s dialect is not yet ported to the 0.6 format" %
111
116
self.convert_unicode = convert_unicode
113
util.warn_deprecated(
114
"assert_unicode is deprecated. "
115
"SQLAlchemy emits a warning in all cases where it "
116
"would otherwise like to encode a Python unicode object "
117
"into a specific encoding but a plain bytestring is "
119
"This does *not* apply to DBAPIs that coerce Unicode "
122
117
self.encoding = encoding
123
118
self.positional = False
124
119
self._ischema = None
135
130
self.identifier_preparer = self.preparer(self)
136
131
self.type_compiler = self.type_compiler(self)
133
self.case_sensitive = case_sensitive
138
135
if label_length and label_length > self.max_identifier_length:
139
136
raise exc.ArgumentError(
140
137
"Label length of %d is greater than this dialect's"
143
140
self.label_length = label_length
145
142
if self.description_encoding == 'use_encoding':
146
self._description_decoder = processors.to_unicode_processor_factory(
143
self._description_decoder = \
144
processors.to_unicode_processor_factory(
149
147
elif self.description_encoding is not None:
150
self._description_decoder = processors.to_unicode_processor_factory(
148
self._description_decoder = \
149
processors.to_unicode_processor_factory(
151
150
self.description_encoding
153
152
self._encoder = codecs.getencoder(self.encoding)
245
246
return unicode_for_varchar
247
248
def type_descriptor(self, typeobj):
248
"""Provide a database-specific ``TypeEngine`` object, given
249
"""Provide a database-specific :class:`.TypeEngine` object, given
249
250
the generic object which comes from the types module.
251
252
This method looks for a dictionary called
252
253
``colspecs`` as a class or instance-level variable,
253
and passes on to ``types.adapt_type()``.
254
and passes on to :func:`.types.adapt_type`.
256
257
return sqltypes.adapt_type(typeobj, self.colspecs)
258
def reflecttable(self, connection, table, include_columns, exclude_columns=None):
259
def reflecttable(self, connection, table, include_columns,
260
exclude_columns=None):
259
261
insp = reflection.Inspector.from_engine(connection)
260
262
return insp.reflecttable(table, include_columns, exclude_columns)
285
287
opts.update(url.query)
286
288
return [[], opts]
288
def do_begin(self, connection):
289
"""Implementations might want to put logic here for turning
290
autocommit on/off, etc.
290
def do_begin(self, dbapi_connection):
295
def do_rollback(self, connection):
296
"""Implementations might want to put logic here for turning
297
autocommit on/off, etc.
300
connection.rollback()
302
def do_commit(self, connection):
303
"""Implementations might want to put logic here for turning
304
autocommit on/off, etc.
293
def do_rollback(self, dbapi_connection):
294
dbapi_connection.rollback()
296
def do_commit(self, dbapi_connection):
297
dbapi_connection.commit()
299
def do_close(self, dbapi_connection):
300
dbapi_connection.close()
309
302
def create_xid(self):
310
303
"""Create a random two-phase transaction ID.
342
335
# the configured default of this dialect.
343
336
self.set_isolation_level(dbapi_conn, self.default_isolation_level)
345
class DefaultExecutionContext(base.ExecutionContext):
339
class DefaultExecutionContext(interfaces.ExecutionContext):
398
def _init_compiled(cls, dialect, connection, dbapi_connection, compiled, parameters):
392
def _init_compiled(cls, dialect, connection, dbapi_connection,
393
compiled, parameters):
399
394
"""Initialize execution context for a Compiled construct."""
401
396
self = cls.__new__(cls)
422
417
self.unicode_statement = unicode(compiled)
423
418
if not dialect.supports_unicode_statements:
424
self.statement = self.unicode_statement.encode(self.dialect.encoding)
419
self.statement = self.unicode_statement.encode(
420
self.dialect.encoding)
426
422
self.statement = self.unicode_statement
430
426
self.isdelete = compiled.isdelete
432
428
if self.isinsert or self.isupdate or self.isdelete:
433
self._is_explicit_returning = compiled.statement._returning
434
self._is_implicit_returning = compiled.returning and \
435
not compiled.statement._returning
429
self._is_explicit_returning = bool(compiled.statement._returning)
430
self._is_implicit_returning = bool(compiled.returning and \
431
not compiled.statement._returning)
437
433
if not parameters:
438
434
self.compiled_parameters = [compiled.construct_params()]
440
436
self.compiled_parameters = \
441
437
[compiled.construct_params(m, _group_number=grp) for
442
grp,m in enumerate(parameters)]
438
grp, m in enumerate(parameters)]
444
440
self.executemany = len(parameters) > 1
474
470
param[dialect._encoder(key)[0]] = \
475
471
processors[key](compiled_params[key])
477
param[dialect._encoder(key)[0]] = compiled_params[key]
473
param[dialect._encoder(key)[0]] = \
479
476
for key in compiled_params:
480
477
if key in processors:
490
def _init_statement(cls, dialect, connection, dbapi_connection, statement, parameters):
487
def _init_statement(cls, dialect, connection, dbapi_connection,
488
statement, parameters):
491
489
"""Initialize execution context for a string SQL statement."""
493
491
self = cls.__new__(cls)
521
519
self.executemany = len(parameters) > 1
523
if not dialect.supports_unicode_statements and isinstance(statement, unicode):
521
if not dialect.supports_unicode_statements and \
522
isinstance(statement, unicode):
524
523
self.unicode_statement = statement
525
524
self.statement = dialect._encoder(statement)[0]
584
583
default_params = {}
586
conn._cursor_execute(self.cursor, stmt, default_params)
585
conn._cursor_execute(self.cursor, stmt, default_params, context=self)
587
586
r = self.cursor.fetchone()[0]
588
587
if type_ is not None:
589
588
# apply type post processors to the result
611
610
def post_exec(self):
613
def get_result_processor(self, type_, colname, coltype):
614
"""Return a 'result processor' for a given type as present in
617
This has a default implementation that dialects can override
618
for context-sensitive result type handling.
621
return type_._cached_result_processor(self.dialect, coltype)
614
623
def get_lastrowid(self):
615
624
"""return self.cursor.lastrowid, or equivalent, after an INSERT.
658
667
def post_insert(self):
659
668
if not self._is_implicit_returning and \
669
not self._is_explicit_returning and \
670
not self.compiled.inline and \
660
671
self.dialect.postfetch_lastrowid and \
661
672
(not self.inserted_primary_key or \
662
673
None in self.inserted_primary_key):
664
675
table = self.compiled.statement.table
665
676
lastrowid = self.get_lastrowid()
667
677
autoinc_col = table._autoincrement_column
668
678
if autoinc_col is not None:
669
679
# apply type post processors to the lastrowid
670
proc = autoinc_col.type._cached_result_processor(self.dialect, None)
680
proc = autoinc_col.type._cached_result_processor(
671
682
if proc is not None:
672
683
lastrowid = proc(lastrowid)
674
685
self.inserted_primary_key = [
675
c is autoinc_col and lastrowid or v
686
lastrowid if c is autoinc_col else v
677
688
table.primary_key,
678
689
self.inserted_primary_key)
717
728
for key in self.compiled.positiontup:
718
729
typeengine = types[key]
719
dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
720
if dbtype is not None and (not exclude_types or dbtype not in exclude_types):
730
dbtype = typeengine.dialect_impl(self.dialect).\
731
get_dbapi_type(self.dialect.dbapi)
732
if dbtype is not None and \
733
(not exclude_types or dbtype not in exclude_types):
721
734
inputsizes.append(dbtype)
723
736
self.cursor.setinputsizes(*inputsizes)
724
737
except Exception, e:
725
self.root_connection._handle_dbapi_exception(e, None, None, None, self)
738
self.root_connection._handle_dbapi_exception(
739
e, None, None, None, self)
729
742
for key in self.compiled.bind_names.values():
730
743
typeengine = types[key]
731
dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
732
if dbtype is not None and (not exclude_types or dbtype not in exclude_types):
744
dbtype = typeengine.dialect_impl(self.dialect).\
745
get_dbapi_type(self.dialect.dbapi)
746
if dbtype is not None and \
747
(not exclude_types or dbtype not in exclude_types):
734
749
key = translate.get(key, key)
735
inputsizes[self.dialect._encoder(key)[0]] = dbtype
750
if not self.dialect.supports_unicode_binds:
751
key = self.dialect._encoder(key)[0]
752
inputsizes[key] = dbtype
737
754
self.cursor.setinputsizes(**inputsizes)
738
755
except Exception, e:
739
self.root_connection._handle_dbapi_exception(e, None, None, None, self)
756
self.root_connection._handle_dbapi_exception(
757
e, None, None, None, self)
742
759
def _exec_default(self, default, type_):
743
760
if default.is_sequence: