root/galaxy-central/eggs/SQLAlchemy-0.5.6_dev_r6498-py2.6.egg/sqlalchemy/engine/default.py @ 3

リビジョン 3, 14.4 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# engine/default.py
2# Copyright (C) 2005, 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
3#
4# This module is part of SQLAlchemy and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7"""Default implementations of per-dialect sqlalchemy.engine classes.
8
9These are semi-private implementation classes which are only of importance
10to database dialect authors; dialects will usually use the classes here
11as the base class for their own corresponding classes.
12
13"""
14
15import re, random
16from sqlalchemy.engine import base
17from sqlalchemy.sql import compiler, expression
18from sqlalchemy import exc
19
20AUTOCOMMIT_REGEXP = re.compile(r'\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)',
21                               re.I | re.UNICODE)
22
23class DefaultDialect(base.Dialect):
24    """Default implementation of Dialect"""
25
26    name = 'default'
27    schemagenerator = compiler.SchemaGenerator
28    schemadropper = compiler.SchemaDropper
29    statement_compiler = compiler.DefaultCompiler
30    preparer = compiler.IdentifierPreparer
31    defaultrunner = base.DefaultRunner
32    supports_alter = True
33    supports_unicode_statements = False
34    max_identifier_length = 9999
35    supports_sane_rowcount = True
36    supports_sane_multi_rowcount = True
37    preexecute_pk_sequences = False
38    supports_pk_autoincrement = True
39    dbapi_type_map = {}
40    default_paramstyle = 'named'
41    supports_default_values = False
42    supports_empty_insert = True
43
44    def __init__(self, convert_unicode=False, assert_unicode=False,
45                 encoding='utf-8', paramstyle=None, dbapi=None,
46                 label_length=None, **kwargs):
47        self.convert_unicode = convert_unicode
48        self.assert_unicode = assert_unicode
49        self.encoding = encoding
50        self.positional = False
51        self._ischema = None
52        self.dbapi = dbapi
53        if paramstyle is not None:
54            self.paramstyle = paramstyle
55        elif self.dbapi is not None:
56            self.paramstyle = self.dbapi.paramstyle
57        else:
58            self.paramstyle = self.default_paramstyle
59        self.positional = self.paramstyle in ('qmark', 'format', 'numeric')
60        self.identifier_preparer = self.preparer(self)
61        if label_length and label_length > self.max_identifier_length:
62            raise exc.ArgumentError("Label length of %d is greater than this dialect's maximum identifier length of %d" % (label_length, self.max_identifier_length))
63        self.label_length = label_length
64        self.description_encoding = getattr(self, 'description_encoding', encoding)
65
66    def type_descriptor(self, typeobj):
67        """Provide a database-specific ``TypeEngine`` object, given
68        the generic object which comes from the types module.
69
70        Subclasses will usually use the ``adapt_type()`` method in the
71        types module to make this job easy."""
72
73        if type(typeobj) is type:
74            typeobj = typeobj()
75        return typeobj
76
77    def validate_identifier(self, ident):
78        if len(ident) > self.max_identifier_length:
79            raise exc.IdentifierError("Identifier '%s' exceeds maximum length of %d characters" % (ident, self.max_identifier_length))
80       
81    def do_begin(self, connection):
82        """Implementations might want to put logic here for turning
83        autocommit on/off, etc.
84        """
85
86        pass
87
88    def do_rollback(self, connection):
89        """Implementations might want to put logic here for turning
90        autocommit on/off, etc.
91        """
92
93        connection.rollback()
94
95    def do_commit(self, connection):
96        """Implementations might want to put logic here for turning
97        autocommit on/off, etc.
98        """
99
100        connection.commit()
101
102    def create_xid(self):
103        """Create a random two-phase transaction ID.
104
105        This id will be passed to do_begin_twophase(), do_rollback_twophase(),
106        do_commit_twophase().  Its format is unspecified."""
107
108        return "_sa_%032x" % random.randint(0, 2 ** 128)
109
110    def do_savepoint(self, connection, name):
111        connection.execute(expression.SavepointClause(name))
112
113    def do_rollback_to_savepoint(self, connection, name):
114        connection.execute(expression.RollbackToSavepointClause(name))
115
116    def do_release_savepoint(self, connection, name):
117        connection.execute(expression.ReleaseSavepointClause(name))
118
119    def do_executemany(self, cursor, statement, parameters, context=None):
120        cursor.executemany(statement, parameters)
121
122    def do_execute(self, cursor, statement, parameters, context=None):
123        cursor.execute(statement, parameters)
124
125    def is_disconnect(self, e):
126        return False
127
128
129class DefaultExecutionContext(base.ExecutionContext):
130    def __init__(self, dialect, connection, compiled=None, statement=None, parameters=None):
131        self.dialect = dialect
132        self._connection = self.root_connection = connection
133        self.compiled = compiled
134        self.engine = connection.engine
135
136        if compiled is not None:
137            # compiled clauseelement.  process bind params, process table defaults,
138            # track collections used by ResultProxy to target and process results
139
140            if not compiled.can_execute:
141                raise exc.ArgumentError("Not an executable clause: %s" % compiled)
142
143            self.processors = dict(
144                (key, value) for key, value in
145                ( (compiled.bind_names[bindparam],
146                   bindparam.bind_processor(self.dialect))
147                  for bindparam in compiled.bind_names )
148                if value is not None)
149
150            self.result_map = compiled.result_map
151
152            if not dialect.supports_unicode_statements:
153                self.statement = unicode(compiled).encode(self.dialect.encoding)
154            else:
155                self.statement = unicode(compiled)
156
157            self.isinsert = compiled.isinsert
158            self.isupdate = compiled.isupdate
159            self.should_autocommit = compiled.statement._autocommit
160            if isinstance(compiled.statement, expression._TextClause):
161                self.should_autocommit = self.should_autocommit or self.should_autocommit_text(self.statement)
162
163            if not parameters:
164                self.compiled_parameters = [compiled.construct_params()]
165                self.executemany = False
166            else:
167                self.compiled_parameters = [compiled.construct_params(m) for m in parameters]
168                self.executemany = len(parameters) > 1
169
170            self.cursor = self.create_cursor()
171            if self.isinsert or self.isupdate:
172                self.__process_defaults()
173            self.parameters = self.__convert_compiled_params(self.compiled_parameters)
174
175        elif statement is not None:
176            # plain text statement.
177            self.result_map = None
178            self.parameters = self.__encode_param_keys(parameters)
179            self.executemany = len(parameters) > 1
180            if isinstance(statement, unicode) and not dialect.supports_unicode_statements:
181                self.statement = statement.encode(self.dialect.encoding)
182            else:
183                self.statement = statement
184            self.isinsert = self.isupdate = False
185            self.cursor = self.create_cursor()
186            self.should_autocommit = self.should_autocommit_text(statement)
187        else:
188            # no statement. used for standalone ColumnDefault execution.
189            self.statement = None
190            self.isinsert = self.isupdate = self.executemany = self.should_autocommit = False
191            self.cursor = self.create_cursor()
192
193    @property
194    def connection(self):
195        return self._connection._branch()
196
197    def __encode_param_keys(self, params):
198        """apply string encoding to the keys of dictionary-based bind parameters.
199
200        This is only used executing textual, non-compiled SQL expressions."""
201
202        if self.dialect.positional or self.dialect.supports_unicode_statements:
203            if params:
204                return params
205            elif self.dialect.positional:
206                return [()]
207            else:
208                return [{}]
209        else:
210            def proc(d):
211                # sigh, sometimes we get positional arguments with a dialect
212                # that doesnt specify positional (because of execute_text())
213                if not isinstance(d, dict):
214                    return d
215                return dict((k.encode(self.dialect.encoding), d[k]) for k in d)
216            return [proc(d) for d in params] or [{}]
217
218    def __convert_compiled_params(self, compiled_parameters):
219        """convert the dictionary of bind parameter values into a dict or list
220        to be sent to the DBAPI's execute() or executemany() method.
221        """
222
223        processors = self.processors
224        parameters = []
225        if self.dialect.positional:
226            for compiled_params in compiled_parameters:
227                param = []
228                for key in self.compiled.positiontup:
229                    if key in processors:
230                        param.append(processors[key](compiled_params[key]))
231                    else:
232                        param.append(compiled_params[key])
233                parameters.append(param)
234        else:
235            encode = not self.dialect.supports_unicode_statements
236            for compiled_params in compiled_parameters:
237                param = {}
238                if encode:
239                    encoding = self.dialect.encoding
240                    for key in compiled_params:
241                        if key in processors:
242                            param[key.encode(encoding)] = processors[key](compiled_params[key])
243                        else:
244                            param[key.encode(encoding)] = compiled_params[key]
245                else:
246                    for key in compiled_params:
247                        if key in processors:
248                            param[key] = processors[key](compiled_params[key])
249                        else:
250                            param[key] = compiled_params[key]
251                parameters.append(param)
252        return parameters
253
254    def should_autocommit_text(self, statement):
255        return AUTOCOMMIT_REGEXP.match(statement)
256
257    def create_cursor(self):
258        return self._connection.connection.cursor()
259
260    def pre_exec(self):
261        pass
262
263    def post_exec(self):
264        pass
265   
266    def handle_dbapi_exception(self, e):
267        pass
268
269    def get_result_proxy(self):
270        return base.ResultProxy(self)
271
272    def get_rowcount(self):
273        if hasattr(self, '_rowcount'):
274            return self._rowcount
275        else:
276            return self.cursor.rowcount
277       
278    def supports_sane_rowcount(self):
279        return self.dialect.supports_sane_rowcount
280
281    def supports_sane_multi_rowcount(self):
282        return self.dialect.supports_sane_multi_rowcount
283
284    def last_inserted_ids(self):
285        return self._last_inserted_ids
286
287    def last_inserted_params(self):
288        return self._last_inserted_params
289
290    def last_updated_params(self):
291        return self._last_updated_params
292
293    def lastrow_has_defaults(self):
294        return hasattr(self, 'postfetch_cols') and len(self.postfetch_cols)
295
296    def set_input_sizes(self):
297        """Given a cursor and ClauseParameters, call the appropriate
298        style of ``setinputsizes()`` on the cursor, using DB-API types
299        from the bind parameter's ``TypeEngine`` objects.
300        """
301
302        types = dict(
303                (self.compiled.bind_names[bindparam], bindparam.type)
304                 for bindparam in self.compiled.bind_names)
305
306        if self.dialect.positional:
307            inputsizes = []
308            for key in self.compiled.positiontup:
309                typeengine = types[key]
310                dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
311                if dbtype is not None:
312                    inputsizes.append(dbtype)
313            try:
314                self.cursor.setinputsizes(*inputsizes)
315            except Exception, e:
316                self._connection._handle_dbapi_exception(e, None, None, None, self)
317                raise
318        else:
319            inputsizes = {}
320            for key in self.compiled.bind_names.values():
321                typeengine = types[key]
322                dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
323                if dbtype is not None:
324                    inputsizes[key.encode(self.dialect.encoding)] = dbtype
325            try:
326                self.cursor.setinputsizes(**inputsizes)
327            except Exception, e:
328                self._connection._handle_dbapi_exception(e, None, None, None, self)
329                raise
330
331    def __process_defaults(self):
332        """generate default values for compiled insert/update statements,
333        and generate last_inserted_ids() collection."""
334
335        if self.executemany:
336            if len(self.compiled.prefetch):
337                drunner = self.dialect.defaultrunner(self)
338                params = self.compiled_parameters
339                for param in params:
340                    # assign each dict of params to self.compiled_parameters;
341                    # this allows user-defined default generators to access the full
342                    # set of bind params for the row
343                    self.compiled_parameters = param
344                    for c in self.compiled.prefetch:
345                        if self.isinsert:
346                            val = drunner.get_column_default(c)
347                        else:
348                            val = drunner.get_column_onupdate(c)
349                        if val is not None:
350                            param[c.key] = val
351                self.compiled_parameters = params
352
353        else:
354            compiled_parameters = self.compiled_parameters[0]
355            drunner = self.dialect.defaultrunner(self)
356
357            for c in self.compiled.prefetch:
358                if self.isinsert:
359                    val = drunner.get_column_default(c)
360                else:
361                    val = drunner.get_column_onupdate(c)
362
363                if val is not None:
364                    compiled_parameters[c.key] = val
365
366            if self.isinsert:
367                self._last_inserted_ids = [compiled_parameters.get(c.key, None) for c in self.compiled.statement.table.primary_key]
368                self._last_inserted_params = compiled_parameters
369            else:
370                self._last_updated_params = compiled_parameters
371
372            self.postfetch_cols = self.compiled.postfetch
373            self.prefetch_cols = self.compiled.prefetch
374
375DefaultDialect.execution_ctx_cls = DefaultExecutionContext
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。