~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/engine/default.py

  • Committer: Package Import Robot
  • Author(s): Piotr Ożarowski, Jakub Wilk, Piotr Ożarowski
  • Date: 2013-07-06 20:53:52 UTC
  • mfrom: (1.4.23) (16.1.17 experimental)
  • Revision ID: package-import@ubuntu.com-20130706205352-ryppl1eto3illd79
Tags: 0.8.2-1
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Piotr Ożarowski ]
* New upstream release
* Upload to unstable
* Build depend on python3-all instead of -dev, extensions are not built for
  Python 3.X 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# engine/default.py
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>
3
3
#
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
12
12
 
13
13
"""
14
14
 
15
 
import re, random
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
 
15
import re
 
16
import random
 
17
from . import reflection, interfaces, result
 
18
from ..sql import compiler, expression
 
19
from .. import exc, types as sqltypes, util, pool, processors
19
20
import codecs
20
21
import weakref
21
22
 
24
25
            re.I | re.UNICODE)
25
26
 
26
27
 
27
 
class DefaultDialect(base.Dialect):
 
28
class DefaultDialect(interfaces.Dialect):
28
29
    """Default implementation of Dialect"""
29
30
 
30
31
    statement_compiler = compiler.SQLCompiler
33
34
    preparer = compiler.IdentifierPreparer
34
35
    supports_alter = True
35
36
 
 
37
    # the first value we'd get for an autoincrement
 
38
    # column.
 
39
    default_sequence_base = 1
 
40
 
36
41
    # most DBAPIs happy with this for execute().
37
42
    # not cx_oracle.
38
43
    execute_sequence_format = tuple
44
49
    postfetch_lastrowid = True
45
50
    implicit_returning = False
46
51
 
47
 
 
48
52
    supports_native_enum = False
49
53
    supports_native_boolean = False
50
54
 
65
69
    description_encoding = 'use_encoding'
66
70
    # end Py2K
67
71
 
68
 
 
69
72
    name = 'default'
70
73
 
71
74
    # length at which to truncate
86
89
    default_paramstyle = 'named'
87
90
    supports_default_values = False
88
91
    supports_empty_insert = True
 
92
    supports_multivalues_insert = False
89
93
 
90
94
    server_version_info = None
91
95
 
98
102
 
99
103
    reflection_options = ()
100
104
 
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,
 
108
                 case_sensitive=True,
104
109
                 label_length=None, **kwargs):
105
110
 
106
111
        if not getattr(self, 'ported_sqla_06', True):
107
112
            util.warn(
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" %
109
114
                self.name)
110
115
 
111
116
        self.convert_unicode = convert_unicode
112
 
        if assert_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 "
118
 
                "received. "
119
 
                "This does *not* apply to DBAPIs that coerce Unicode "
120
 
                "natively.")
121
 
 
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)
137
132
 
 
133
        self.case_sensitive = case_sensitive
 
134
 
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
144
141
 
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(
147
145
                                            encoding
148
146
                                    )
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
152
151
                                    )
153
152
        self._encoder = codecs.getencoder(self.encoding)
210
209
        # end Py2K
211
210
        # Py3K
212
211
        #cast_to = str
 
212
 
213
213
        def check_unicode(formatstr, type_):
214
214
            cursor = connection.connection.cursor()
215
215
            try:
219
219
                            expression.select(
220
220
                            [expression.cast(
221
221
                                expression.literal_column(
222
 
                                        "'test %s returns'" % formatstr), type_)
 
222
                                        "'test %s returns'" % formatstr),
 
223
                                        type_)
223
224
                            ]).compile(dialect=self)
224
225
                        )
225
226
                    )
245
246
            return unicode_for_varchar
246
247
 
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.
250
251
 
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`.
254
255
 
255
256
        """
256
257
        return sqltypes.adapt_type(typeobj, self.colspecs)
257
258
 
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)
261
263
 
285
287
        opts.update(url.query)
286
288
        return [[], opts]
287
289
 
288
 
    def do_begin(self, connection):
289
 
        """Implementations might want to put logic here for turning
290
 
        autocommit on/off, etc.
291
 
        """
292
 
 
 
290
    def do_begin(self, dbapi_connection):
293
291
        pass
294
292
 
295
 
    def do_rollback(self, connection):
296
 
        """Implementations might want to put logic here for turning
297
 
        autocommit on/off, etc.
298
 
        """
299
 
 
300
 
        connection.rollback()
301
 
 
302
 
    def do_commit(self, connection):
303
 
        """Implementations might want to put logic here for turning
304
 
        autocommit on/off, etc.
305
 
        """
306
 
 
307
 
        connection.commit()
 
293
    def do_rollback(self, dbapi_connection):
 
294
        dbapi_connection.rollback()
 
295
 
 
296
    def do_commit(self, dbapi_connection):
 
297
        dbapi_connection.commit()
 
298
 
 
299
    def do_close(self, dbapi_connection):
 
300
        dbapi_connection.close()
308
301
 
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)
344
337
 
345
 
class DefaultExecutionContext(base.ExecutionContext):
 
338
 
 
339
class DefaultExecutionContext(interfaces.ExecutionContext):
346
340
    isinsert = False
347
341
    isupdate = False
348
342
    isdelete = False
395
389
        return self
396
390
 
397
391
    @classmethod
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."""
400
395
 
401
396
        self = cls.__new__(cls)
421
416
 
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)
425
421
        else:
426
422
            self.statement = self.unicode_statement
427
423
 
430
426
        self.isdelete = compiled.isdelete
431
427
 
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)
436
432
 
437
433
        if not parameters:
438
434
            self.compiled_parameters = [compiled.construct_params()]
439
435
        else:
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)]
443
439
 
444
440
            self.executemany = len(parameters) > 1
445
441
 
474
470
                            param[dialect._encoder(key)[0]] = \
475
471
                                        processors[key](compiled_params[key])
476
472
                        else:
477
 
                            param[dialect._encoder(key)[0]] = compiled_params[key]
 
473
                            param[dialect._encoder(key)[0]] = \
 
474
                                    compiled_params[key]
478
475
                else:
479
476
                    for key in compiled_params:
480
477
                        if key in processors:
487
484
        return self
488
485
 
489
486
    @classmethod
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."""
492
490
 
493
491
        self = cls.__new__(cls)
510
508
            if dialect.supports_unicode_statements:
511
509
                self.parameters = parameters
512
510
            else:
513
 
                self.parameters= [
 
511
                self.parameters = [
514
512
                            dict((dialect._encoder(k)[0], d[k]) for k in d)
515
513
                            for d in parameters
516
514
                        ] or [{}]
520
518
 
521
519
        self.executemany = len(parameters) > 1
522
520
 
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]
526
525
        else:
583
582
        else:
584
583
            default_params = {}
585
584
 
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):
612
611
        pass
613
612
 
 
613
    def get_result_processor(self, type_, colname, coltype):
 
614
        """Return a 'result processor' for a given type as present in
 
615
        cursor.description.
 
616
 
 
617
        This has a default implementation that dialects can override
 
618
        for context-sensitive result type handling.
 
619
 
 
620
        """
 
621
        return type_._cached_result_processor(self.dialect, coltype)
 
622
 
614
623
    def get_lastrowid(self):
615
624
        """return self.cursor.lastrowid, or equivalent, after an INSERT.
616
625
 
643
652
        pass
644
653
 
645
654
    def get_result_proxy(self):
646
 
        return base.ResultProxy(self)
 
655
        return result.ResultProxy(self)
647
656
 
648
657
    @property
649
658
    def rowcount(self):
657
666
 
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):
663
674
 
664
675
            table = self.compiled.statement.table
665
676
            lastrowid = self.get_lastrowid()
666
 
 
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(
 
681
                                        self.dialect, None)
671
682
                if proc is not None:
672
683
                    lastrowid = proc(lastrowid)
673
684
 
674
685
            self.inserted_primary_key = [
675
 
                c is autoinc_col and lastrowid or v
 
686
                lastrowid if c is autoinc_col else v
676
687
                for c, v in zip(
677
688
                                    table.primary_key,
678
689
                                    self.inserted_primary_key)
716
727
            inputsizes = []
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)
722
735
            try:
723
736
                self.cursor.setinputsizes(*inputsizes)
724
737
            except Exception, e:
725
 
                self.root_connection._handle_dbapi_exception(e, None, None, None, self)
726
 
                raise
 
738
                self.root_connection._handle_dbapi_exception(
 
739
                                e, None, None, None, self)
727
740
        else:
728
741
            inputsizes = {}
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):
733
748
                    if translate:
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
736
753
            try:
737
754
                self.cursor.setinputsizes(**inputsizes)
738
755
            except Exception, e:
739
 
                self.root_connection._handle_dbapi_exception(e, None, None, None, self)
740
 
                raise
 
756
                self.root_connection._handle_dbapi_exception(
 
757
                                e, None, None, None, self)
741
758
 
742
759
    def _exec_default(self, default, type_):
743
760
        if default.is_sequence: