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

« back to all changes in this revision

Viewing changes to lib/sqlalchemy/engine/base.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/base.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
6
6
 
7
7
 
8
 
"""Basic components for SQL execution and interfacing with DB-API.
 
8
"""Defines :class:`.Connection` and :class:`.Engine`.
9
9
 
10
 
Defines the basic components used to interface DB-API modules with
11
 
higher-level statement-construction, connection-management, execution
12
 
and result contexts.
13
10
"""
14
11
 
15
 
__all__ = [
16
 
    'BufferedColumnResultProxy', 'BufferedColumnRow',
17
 
    'BufferedRowResultProxy','Compiled', 'Connectable', 'Connection',
18
 
    'Dialect', 'Engine','ExecutionContext', 'NestedTransaction',
19
 
    'ResultProxy', 'RootTransaction','RowProxy', 'SchemaIterator',
20
 
    'StringIO', 'Transaction', 'TwoPhaseTransaction',
21
 
    'connection_memoize']
22
 
 
23
 
import inspect, StringIO, sys, operator
24
 
from itertools import izip
25
 
from sqlalchemy import exc, schema, util, types, log, interfaces, \
26
 
    event, events
27
 
from sqlalchemy.sql import expression, util as sql_util
28
 
from sqlalchemy import processors
29
 
import collections
30
 
 
31
 
class Dialect(object):
32
 
    """Define the behavior of a specific database and DB-API combination.
33
 
 
34
 
    Any aspect of metadata definition, SQL query generation,
35
 
    execution, result-set handling, or anything else which varies
36
 
    between databases is defined under the general category of the
37
 
    Dialect.  The Dialect acts as a factory for other
38
 
    database-specific object implementations including
39
 
    ExecutionContext, Compiled, DefaultGenerator, and TypeEngine.
40
 
 
41
 
    All Dialects implement the following attributes:
42
 
 
43
 
    name
44
 
      identifying name for the dialect from a DBAPI-neutral point of view
45
 
      (i.e. 'sqlite')
46
 
 
47
 
    driver
48
 
      identifying name for the dialect's DBAPI
49
 
 
50
 
    positional
51
 
      True if the paramstyle for this Dialect is positional.
52
 
 
53
 
    paramstyle
54
 
      the paramstyle to be used (some DB-APIs support multiple
55
 
      paramstyles).
56
 
 
57
 
    convert_unicode
58
 
      True if Unicode conversion should be applied to all ``str``
59
 
      types.
60
 
 
61
 
    encoding
62
 
      type of encoding to use for unicode, usually defaults to
63
 
      'utf-8'.
64
 
 
65
 
    statement_compiler
66
 
      a :class:`~Compiled` class used to compile SQL statements
67
 
 
68
 
    ddl_compiler
69
 
      a :class:`~Compiled` class used to compile DDL statements
70
 
 
71
 
    server_version_info
72
 
      a tuple containing a version number for the DB backend in use.
73
 
      This value is only available for supporting dialects, and is
74
 
      typically populated during the initial connection to the database.
75
 
 
76
 
    default_schema_name
77
 
     the name of the default schema.  This value is only available for
78
 
     supporting dialects, and is typically populated during the
79
 
     initial connection to the database.
80
 
 
81
 
    execution_ctx_cls
82
 
      a :class:`.ExecutionContext` class used to handle statement execution
83
 
 
84
 
    execute_sequence_format
85
 
      either the 'tuple' or 'list' type, depending on what cursor.execute()
86
 
      accepts for the second argument (they vary).
87
 
 
88
 
    preparer
89
 
      a :class:`~sqlalchemy.sql.compiler.IdentifierPreparer` class used to
90
 
      quote identifiers.
91
 
 
92
 
    supports_alter
93
 
      ``True`` if the database supports ``ALTER TABLE``.
94
 
 
95
 
    max_identifier_length
96
 
      The maximum length of identifier names.
97
 
 
98
 
    supports_unicode_statements
99
 
      Indicate whether the DB-API can receive SQL statements as Python
100
 
      unicode strings
101
 
 
102
 
    supports_unicode_binds
103
 
      Indicate whether the DB-API can receive string bind parameters
104
 
      as Python unicode strings
105
 
 
106
 
    supports_sane_rowcount
107
 
      Indicate whether the dialect properly implements rowcount for
108
 
      ``UPDATE`` and ``DELETE`` statements.
109
 
 
110
 
    supports_sane_multi_rowcount
111
 
      Indicate whether the dialect properly implements rowcount for
112
 
      ``UPDATE`` and ``DELETE`` statements when executed via
113
 
      executemany.
114
 
 
115
 
    preexecute_autoincrement_sequences
116
 
      True if 'implicit' primary key functions must be executed separately
117
 
      in order to get their value.   This is currently oriented towards
118
 
      Postgresql.
119
 
 
120
 
    implicit_returning
121
 
      use RETURNING or equivalent during INSERT execution in order to load
122
 
      newly generated primary keys and other column defaults in one execution,
123
 
      which are then available via inserted_primary_key.
124
 
      If an insert statement has returning() specified explicitly,
125
 
      the "implicit" functionality is not used and inserted_primary_key
126
 
      will not be available.
127
 
 
128
 
    dbapi_type_map
129
 
      A mapping of DB-API type objects present in this Dialect's
130
 
      DB-API implementation mapped to TypeEngine implementations used
131
 
      by the dialect.
132
 
 
133
 
      This is used to apply types to result sets based on the DB-API
134
 
      types present in cursor.description; it only takes effect for
135
 
      result sets against textual statements where no explicit
136
 
      typemap was present.
137
 
 
138
 
    colspecs
139
 
      A dictionary of TypeEngine classes from sqlalchemy.types mapped
140
 
      to subclasses that are specific to the dialect class.  This
141
 
      dictionary is class-level only and is not accessed from the
142
 
      dialect instance itself.
143
 
 
144
 
    supports_default_values
145
 
      Indicates if the construct ``INSERT INTO tablename DEFAULT
146
 
      VALUES`` is supported
147
 
 
148
 
    supports_sequences
149
 
      Indicates if the dialect supports CREATE SEQUENCE or similar.
150
 
 
151
 
    sequences_optional
152
 
      If True, indicates if the "optional" flag on the Sequence() construct
153
 
      should signal to not generate a CREATE SEQUENCE. Applies only to
154
 
      dialects that support sequences. Currently used only to allow Postgresql
155
 
      SERIAL to be used on a column that specifies Sequence() for usage on
156
 
      other backends.
157
 
 
158
 
    supports_native_enum
159
 
      Indicates if the dialect supports a native ENUM construct.
160
 
      This will prevent types.Enum from generating a CHECK
161
 
      constraint when that type is used.
162
 
 
163
 
    supports_native_boolean
164
 
      Indicates if the dialect supports a native boolean construct.
165
 
      This will prevent types.Boolean from generating a CHECK
166
 
      constraint when that type is used.
167
 
 
168
 
    """
169
 
 
170
 
    def create_connect_args(self, url):
171
 
        """Build DB-API compatible connection arguments.
172
 
 
173
 
        Given a :class:`~sqlalchemy.engine.url.URL` object, returns a tuple
174
 
        consisting of a `*args`/`**kwargs` suitable to send directly
175
 
        to the dbapi's connect function.
176
 
 
177
 
        """
178
 
 
179
 
        raise NotImplementedError()
180
 
 
181
 
    @classmethod
182
 
    def type_descriptor(cls, typeobj):
183
 
        """Transform a generic type to a dialect-specific type.
184
 
 
185
 
        Dialect classes will usually use the
186
 
        :func:`~sqlalchemy.types.adapt_type` function in the types module to
187
 
        make this job easy.
188
 
 
189
 
        The returned result is cached *per dialect class* so can
190
 
        contain no dialect-instance state.
191
 
 
192
 
        """
193
 
 
194
 
        raise NotImplementedError()
195
 
 
196
 
    def initialize(self, connection):
197
 
        """Called during strategized creation of the dialect with a
198
 
        connection.
199
 
 
200
 
        Allows dialects to configure options based on server version info or
201
 
        other properties.
202
 
 
203
 
        The connection passed here is a SQLAlchemy Connection object,
204
 
        with full capabilities.
205
 
 
206
 
        The initalize() method of the base dialect should be called via
207
 
        super().
208
 
 
209
 
        """
210
 
 
211
 
        pass
212
 
 
213
 
    def reflecttable(self, connection, table, include_columns=None):
214
 
        """Load table description from the database.
215
 
 
216
 
        Given a :class:`.Connection` and a
217
 
        :class:`~sqlalchemy.schema.Table` object, reflect its columns and
218
 
        properties from the database.  If include_columns (a list or
219
 
        set) is specified, limit the autoload to the given column
220
 
        names.
221
 
 
222
 
        The default implementation uses the
223
 
        :class:`~sqlalchemy.engine.reflection.Inspector` interface to
224
 
        provide the output, building upon the granular table/column/
225
 
        constraint etc. methods of :class:`.Dialect`.
226
 
 
227
 
        """
228
 
 
229
 
        raise NotImplementedError()
230
 
 
231
 
    def get_columns(self, connection, table_name, schema=None, **kw):
232
 
        """Return information about columns in `table_name`.
233
 
 
234
 
        Given a :class:`.Connection`, a string
235
 
        `table_name`, and an optional string `schema`, return column
236
 
        information as a list of dictionaries with these keys:
237
 
 
238
 
        name
239
 
          the column's name
240
 
 
241
 
        type
242
 
          [sqlalchemy.types#TypeEngine]
243
 
 
244
 
        nullable
245
 
          boolean
246
 
 
247
 
        default
248
 
          the column's default value
249
 
 
250
 
        autoincrement
251
 
          boolean
252
 
 
253
 
        sequence
254
 
          a dictionary of the form
255
 
              {'name' : str, 'start' :int, 'increment': int}
256
 
 
257
 
        Additional column attributes may be present.
258
 
        """
259
 
 
260
 
        raise NotImplementedError()
261
 
 
262
 
    def get_primary_keys(self, connection, table_name, schema=None, **kw):
263
 
        """Return information about primary keys in `table_name`.
264
 
 
265
 
        Given a :class:`.Connection`, a string
266
 
        `table_name`, and an optional string `schema`, return primary
267
 
        key information as a list of column names.
268
 
 
269
 
        """
270
 
        raise NotImplementedError()
271
 
 
272
 
    def get_pk_constraint(self, table_name, schema=None, **kw):
273
 
        """Return information about the primary key constraint on
274
 
        table_name`.
275
 
 
276
 
        Given a string `table_name`, and an optional string `schema`, return
277
 
        primary key information as a dictionary with these keys:
278
 
 
279
 
        constrained_columns
280
 
          a list of column names that make up the primary key
281
 
 
282
 
        name
283
 
          optional name of the primary key constraint.
284
 
 
285
 
        """
286
 
        raise NotImplementedError()
287
 
 
288
 
    def get_foreign_keys(self, connection, table_name, schema=None, **kw):
289
 
        """Return information about foreign_keys in `table_name`.
290
 
 
291
 
        Given a :class:`.Connection`, a string
292
 
        `table_name`, and an optional string `schema`, return foreign
293
 
        key information as a list of dicts with these keys:
294
 
 
295
 
        name
296
 
          the constraint's name
297
 
 
298
 
        constrained_columns
299
 
          a list of column names that make up the foreign key
300
 
 
301
 
        referred_schema
302
 
          the name of the referred schema
303
 
 
304
 
        referred_table
305
 
          the name of the referred table
306
 
 
307
 
        referred_columns
308
 
          a list of column names in the referred table that correspond to
309
 
          constrained_columns
310
 
        """
311
 
 
312
 
        raise NotImplementedError()
313
 
 
314
 
    def get_table_names(self, connection, schema=None, **kw):
315
 
        """Return a list of table names for `schema`."""
316
 
 
317
 
        raise NotImplementedError
318
 
 
319
 
    def get_view_names(self, connection, schema=None, **kw):
320
 
        """Return a list of all view names available in the database.
321
 
 
322
 
        schema:
323
 
          Optional, retrieve names from a non-default schema.
324
 
        """
325
 
 
326
 
        raise NotImplementedError()
327
 
 
328
 
    def get_view_definition(self, connection, view_name, schema=None, **kw):
329
 
        """Return view definition.
330
 
 
331
 
        Given a :class:`.Connection`, a string
332
 
        `view_name`, and an optional string `schema`, return the view
333
 
        definition.
334
 
        """
335
 
 
336
 
        raise NotImplementedError()
337
 
 
338
 
    def get_indexes(self, connection, table_name, schema=None, **kw):
339
 
        """Return information about indexes in `table_name`.
340
 
 
341
 
        Given a :class:`.Connection`, a string
342
 
        `table_name` and an optional string `schema`, return index
343
 
        information as a list of dictionaries with these keys:
344
 
 
345
 
        name
346
 
          the index's name
347
 
 
348
 
        column_names
349
 
          list of column names in order
350
 
 
351
 
        unique
352
 
          boolean
353
 
        """
354
 
 
355
 
        raise NotImplementedError()
356
 
 
357
 
    def normalize_name(self, name):
358
 
        """convert the given name to lowercase if it is detected as
359
 
        case insensitive.
360
 
 
361
 
        this method is only used if the dialect defines
362
 
        requires_name_normalize=True.
363
 
 
364
 
        """
365
 
        raise NotImplementedError()
366
 
 
367
 
    def denormalize_name(self, name):
368
 
        """convert the given name to a case insensitive identifier
369
 
        for the backend if it is an all-lowercase name.
370
 
 
371
 
        this method is only used if the dialect defines
372
 
        requires_name_normalize=True.
373
 
 
374
 
        """
375
 
        raise NotImplementedError()
376
 
 
377
 
    def has_table(self, connection, table_name, schema=None):
378
 
        """Check the existence of a particular table in the database.
379
 
 
380
 
        Given a :class:`.Connection` object and a string
381
 
        `table_name`, return True if the given table (possibly within
382
 
        the specified `schema`) exists in the database, False
383
 
        otherwise.
384
 
        """
385
 
 
386
 
        raise NotImplementedError()
387
 
 
388
 
    def has_sequence(self, connection, sequence_name, schema=None):
389
 
        """Check the existence of a particular sequence in the database.
390
 
 
391
 
        Given a :class:`.Connection` object and a string
392
 
        `sequence_name`, return True if the given sequence exists in
393
 
        the database, False otherwise.
394
 
        """
395
 
 
396
 
        raise NotImplementedError()
397
 
 
398
 
    def _get_server_version_info(self, connection):
399
 
        """Retrieve the server version info from the given connection.
400
 
 
401
 
        This is used by the default implementation to populate the
402
 
        "server_version_info" attribute and is called exactly
403
 
        once upon first connect.
404
 
 
405
 
        """
406
 
 
407
 
        raise NotImplementedError()
408
 
 
409
 
    def _get_default_schema_name(self, connection):
410
 
        """Return the string name of the currently selected schema from
411
 
        the given connection.
412
 
 
413
 
        This is used by the default implementation to populate the
414
 
        "default_schema_name" attribute and is called exactly
415
 
        once upon first connect.
416
 
 
417
 
        """
418
 
 
419
 
        raise NotImplementedError()
420
 
 
421
 
    def do_begin(self, connection):
422
 
        """Provide an implementation of *connection.begin()*, given a
423
 
        DB-API connection."""
424
 
 
425
 
        raise NotImplementedError()
426
 
 
427
 
    def do_rollback(self, connection):
428
 
        """Provide an implementation of *connection.rollback()*, given
429
 
        a DB-API connection."""
430
 
 
431
 
        raise NotImplementedError()
432
 
 
433
 
    def create_xid(self):
434
 
        """Create a two-phase transaction ID.
435
 
 
436
 
        This id will be passed to do_begin_twophase(),
437
 
        do_rollback_twophase(), do_commit_twophase().  Its format is
438
 
        unspecified.
439
 
        """
440
 
 
441
 
        raise NotImplementedError()
442
 
 
443
 
    def do_commit(self, connection):
444
 
        """Provide an implementation of *connection.commit()*, given a
445
 
        DB-API connection."""
446
 
 
447
 
        raise NotImplementedError()
448
 
 
449
 
    def do_savepoint(self, connection, name):
450
 
        """Create a savepoint with the given name on a SQLAlchemy
451
 
        connection."""
452
 
 
453
 
        raise NotImplementedError()
454
 
 
455
 
    def do_rollback_to_savepoint(self, connection, name):
456
 
        """Rollback a SQL Alchemy connection to the named savepoint."""
457
 
 
458
 
        raise NotImplementedError()
459
 
 
460
 
    def do_release_savepoint(self, connection, name):
461
 
        """Release the named savepoint on a SQL Alchemy connection."""
462
 
 
463
 
        raise NotImplementedError()
464
 
 
465
 
    def do_begin_twophase(self, connection, xid):
466
 
        """Begin a two phase transaction on the given connection."""
467
 
 
468
 
        raise NotImplementedError()
469
 
 
470
 
    def do_prepare_twophase(self, connection, xid):
471
 
        """Prepare a two phase transaction on the given connection."""
472
 
 
473
 
        raise NotImplementedError()
474
 
 
475
 
    def do_rollback_twophase(self, connection, xid, is_prepared=True,
476
 
                            recover=False):
477
 
        """Rollback a two phase transaction on the given connection."""
478
 
 
479
 
        raise NotImplementedError()
480
 
 
481
 
    def do_commit_twophase(self, connection, xid, is_prepared=True,
482
 
                            recover=False):
483
 
        """Commit a two phase transaction on the given connection."""
484
 
 
485
 
        raise NotImplementedError()
486
 
 
487
 
    def do_recover_twophase(self, connection):
488
 
        """Recover list of uncommited prepared two phase transaction
489
 
        identifiers on the given connection."""
490
 
 
491
 
        raise NotImplementedError()
492
 
 
493
 
    def do_executemany(self, cursor, statement, parameters, context=None):
494
 
        """Provide an implementation of ``cursor.executemany(statement,
495
 
        parameters)``."""
496
 
 
497
 
        raise NotImplementedError()
498
 
 
499
 
    def do_execute(self, cursor, statement, parameters, context=None):
500
 
        """Provide an implementation of ``cursor.execute(statement,
501
 
        parameters)``."""
502
 
 
503
 
        raise NotImplementedError()
504
 
 
505
 
    def do_execute_no_params(self, cursor, statement, parameters, context=None):
506
 
        """Provide an implementation of ``cursor.execute(statement)``.
507
 
 
508
 
        The parameter collection should not be sent.
509
 
 
510
 
        """
511
 
 
512
 
        raise NotImplementedError()
513
 
 
514
 
    def is_disconnect(self, e, connection, cursor):
515
 
        """Return True if the given DB-API error indicates an invalid
516
 
        connection"""
517
 
 
518
 
        raise NotImplementedError()
519
 
 
520
 
    def connect(self):
521
 
        """return a callable which sets up a newly created DBAPI connection.
522
 
 
523
 
        The callable accepts a single argument "conn" which is the
524
 
        DBAPI connection itself.  It has no return value.
525
 
 
526
 
        This is used to set dialect-wide per-connection options such as
527
 
        isolation modes, unicode modes, etc.
528
 
 
529
 
        If a callable is returned, it will be assembled into a pool listener
530
 
        that receives the direct DBAPI connection, with all wrappers removed.
531
 
 
532
 
        If None is returned, no listener will be generated.
533
 
 
534
 
        """
535
 
        return None
536
 
 
537
 
    def reset_isolation_level(self, dbapi_conn):
538
 
        """Given a DBAPI connection, revert its isolation to the default."""
539
 
 
540
 
        raise NotImplementedError()
541
 
 
542
 
    def set_isolation_level(self, dbapi_conn, level):
543
 
        """Given a DBAPI connection, set its isolation level."""
544
 
 
545
 
        raise NotImplementedError()
546
 
 
547
 
    def get_isolation_level(self, dbapi_conn):
548
 
        """Given a DBAPI connection, return its isolation level."""
549
 
 
550
 
        raise NotImplementedError()
551
 
 
552
 
 
553
 
class ExecutionContext(object):
554
 
    """A messenger object for a Dialect that corresponds to a single
555
 
    execution.
556
 
 
557
 
    ExecutionContext should have these data members:
558
 
 
559
 
    connection
560
 
      Connection object which can be freely used by default value
561
 
      generators to execute SQL.  This Connection should reference the
562
 
      same underlying connection/transactional resources of
563
 
      root_connection.
564
 
 
565
 
    root_connection
566
 
      Connection object which is the source of this ExecutionContext.  This
567
 
      Connection may have close_with_result=True set, in which case it can
568
 
      only be used once.
569
 
 
570
 
    dialect
571
 
      dialect which created this ExecutionContext.
572
 
 
573
 
    cursor
574
 
      DB-API cursor procured from the connection,
575
 
 
576
 
    compiled
577
 
      if passed to constructor, sqlalchemy.engine.base.Compiled object
578
 
      being executed,
579
 
 
580
 
    statement
581
 
      string version of the statement to be executed.  Is either
582
 
      passed to the constructor, or must be created from the
583
 
      sql.Compiled object by the time pre_exec() has completed.
584
 
 
585
 
    parameters
586
 
      bind parameters passed to the execute() method.  For compiled
587
 
      statements, this is a dictionary or list of dictionaries.  For
588
 
      textual statements, it should be in a format suitable for the
589
 
      dialect's paramstyle (i.e. dict or list of dicts for non
590
 
      positional, list or list of lists/tuples for positional).
591
 
 
592
 
    isinsert
593
 
      True if the statement is an INSERT.
594
 
 
595
 
    isupdate
596
 
      True if the statement is an UPDATE.
597
 
 
598
 
    should_autocommit
599
 
      True if the statement is a "committable" statement.
600
 
 
601
 
    postfetch_cols
602
 
      a list of Column objects for which a server-side default or
603
 
      inline SQL expression value was fired off.  Applies to inserts
604
 
      and updates.
605
 
    """
606
 
 
607
 
    def create_cursor(self):
608
 
        """Return a new cursor generated from this ExecutionContext's
609
 
        connection.
610
 
 
611
 
        Some dialects may wish to change the behavior of
612
 
        connection.cursor(), such as postgresql which may return a PG
613
 
        "server side" cursor.
614
 
        """
615
 
 
616
 
        raise NotImplementedError()
617
 
 
618
 
    def pre_exec(self):
619
 
        """Called before an execution of a compiled statement.
620
 
 
621
 
        If a compiled statement was passed to this ExecutionContext,
622
 
        the `statement` and `parameters` datamembers must be
623
 
        initialized after this statement is complete.
624
 
        """
625
 
 
626
 
        raise NotImplementedError()
627
 
 
628
 
    def post_exec(self):
629
 
        """Called after the execution of a compiled statement.
630
 
 
631
 
        If a compiled statement was passed to this ExecutionContext,
632
 
        the `last_insert_ids`, `last_inserted_params`, etc.
633
 
        datamembers should be available after this method completes.
634
 
        """
635
 
 
636
 
        raise NotImplementedError()
637
 
 
638
 
    def result(self):
639
 
        """Return a result object corresponding to this ExecutionContext.
640
 
 
641
 
        Returns a ResultProxy.
642
 
        """
643
 
 
644
 
        raise NotImplementedError()
645
 
 
646
 
    def handle_dbapi_exception(self, e):
647
 
        """Receive a DBAPI exception which occurred upon execute, result
648
 
        fetch, etc."""
649
 
 
650
 
        raise NotImplementedError()
651
 
 
652
 
    def should_autocommit_text(self, statement):
653
 
        """Parse the given textual statement and return True if it refers to
654
 
        a "committable" statement"""
655
 
 
656
 
        raise NotImplementedError()
657
 
 
658
 
    def lastrow_has_defaults(self):
659
 
        """Return True if the last INSERT or UPDATE row contained
660
 
        inlined or database-side defaults.
661
 
        """
662
 
 
663
 
        raise NotImplementedError()
664
 
 
665
 
    def get_rowcount(self):
666
 
        """Return the DBAPI ``cursor.rowcount`` value, or in some
667
 
        cases an interpreted value.
668
 
 
669
 
        See :attr:`.ResultProxy.rowcount` for details on this.
670
 
 
671
 
        """
672
 
 
673
 
        raise NotImplementedError()
674
 
 
675
 
 
676
 
class Compiled(object):
677
 
    """Represent a compiled SQL or DDL expression.
678
 
 
679
 
    The ``__str__`` method of the ``Compiled`` object should produce
680
 
    the actual text of the statement.  ``Compiled`` objects are
681
 
    specific to their underlying database dialect, and also may
682
 
    or may not be specific to the columns referenced within a
683
 
    particular set of bind parameters.  In no case should the
684
 
    ``Compiled`` object be dependent on the actual values of those
685
 
    bind parameters, even though it may reference those values as
686
 
    defaults.
687
 
    """
688
 
 
689
 
    def __init__(self, dialect, statement, bind=None):
690
 
        """Construct a new ``Compiled`` object.
691
 
 
692
 
        :param dialect: ``Dialect`` to compile against.
693
 
 
694
 
        :param statement: ``ClauseElement`` to be compiled.
695
 
 
696
 
        :param bind: Optional Engine or Connection to compile this
697
 
          statement against.
698
 
        """
699
 
 
700
 
        self.dialect = dialect
701
 
        self.bind = bind
702
 
        if statement is not None:
703
 
            self.statement = statement
704
 
            self.can_execute = statement.supports_execution
705
 
            self.string = self.process(self.statement)
706
 
 
707
 
    @util.deprecated("0.7", ":class:`.Compiled` objects now compile "
708
 
                        "within the constructor.")
709
 
    def compile(self):
710
 
        """Produce the internal string representation of this element."""
711
 
        pass
712
 
 
713
 
    @property
714
 
    def sql_compiler(self):
715
 
        """Return a Compiled that is capable of processing SQL expressions.
716
 
 
717
 
        If this compiler is one, it would likely just return 'self'.
718
 
 
719
 
        """
720
 
 
721
 
        raise NotImplementedError()
722
 
 
723
 
    def process(self, obj, **kwargs):
724
 
        return obj._compiler_dispatch(self, **kwargs)
725
 
 
726
 
    def __str__(self):
727
 
        """Return the string text of the generated SQL or DDL."""
728
 
 
729
 
        return self.string or ''
730
 
 
731
 
    def construct_params(self, params=None):
732
 
        """Return the bind params for this compiled object.
733
 
 
734
 
        :param params: a dict of string/object pairs whose values will
735
 
                       override bind values compiled in to the
736
 
                       statement.
737
 
        """
738
 
 
739
 
        raise NotImplementedError()
740
 
 
741
 
    @property
742
 
    def params(self):
743
 
        """Return the bind params for this compiled object."""
744
 
        return self.construct_params()
745
 
 
746
 
    def execute(self, *multiparams, **params):
747
 
        """Execute this compiled object."""
748
 
 
749
 
        e = self.bind
750
 
        if e is None:
751
 
            raise exc.UnboundExecutionError(
752
 
                        "This Compiled object is not bound to any Engine "
753
 
                        "or Connection.")
754
 
        return e._execute_compiled(self, multiparams, params)
755
 
 
756
 
    def scalar(self, *multiparams, **params):
757
 
        """Execute this compiled object and return the result's
758
 
        scalar value."""
759
 
 
760
 
        return self.execute(*multiparams, **params).scalar()
761
 
 
762
 
 
763
 
class TypeCompiler(object):
764
 
    """Produces DDL specification for TypeEngine objects."""
765
 
 
766
 
    def __init__(self, dialect):
767
 
        self.dialect = dialect
768
 
 
769
 
    def process(self, type_):
770
 
        return type_._compiler_dispatch(self)
771
 
 
772
 
 
773
 
class Connectable(object):
774
 
    """Interface for an object which supports execution of SQL constructs.
775
 
 
776
 
    The two implementations of :class:`.Connectable` are :class:`.Connection` and
777
 
    :class:`.Engine`.
778
 
 
779
 
    Connectable must also implement the 'dialect' member which references a
780
 
    :class:`.Dialect` instance.
781
 
 
782
 
    """
783
 
 
784
 
    def connect(self, **kwargs):
785
 
        """Return a :class:`.Connection` object.
786
 
 
787
 
        Depending on context, this may be ``self`` if this object
788
 
        is already an instance of :class:`.Connection`, or a newly
789
 
        procured :class:`.Connection` if this object is an instance
790
 
        of :class:`.Engine`.
791
 
 
792
 
        """
793
 
 
794
 
    def contextual_connect(self):
795
 
        """Return a :class:`.Connection` object which may be part of an ongoing
796
 
        context.
797
 
 
798
 
        Depending on context, this may be ``self`` if this object
799
 
        is already an instance of :class:`.Connection`, or a newly
800
 
        procured :class:`.Connection` if this object is an instance
801
 
        of :class:`.Engine`.
802
 
 
803
 
        """
804
 
 
805
 
        raise NotImplementedError()
806
 
 
807
 
    @util.deprecated("0.7", "Use the create() method on the given schema "
808
 
                            "object directly, i.e. :meth:`.Table.create`, "
809
 
                            ":meth:`.Index.create`, :meth:`.MetaData.create_all`")
810
 
    def create(self, entity, **kwargs):
811
 
        """Emit CREATE statements for the given schema entity."""
812
 
 
813
 
        raise NotImplementedError()
814
 
 
815
 
    @util.deprecated("0.7", "Use the drop() method on the given schema "
816
 
                            "object directly, i.e. :meth:`.Table.drop`, "
817
 
                            ":meth:`.Index.drop`, :meth:`.MetaData.drop_all`")
818
 
    def drop(self, entity, **kwargs):
819
 
        """Emit DROP statements for the given schema entity."""
820
 
 
821
 
        raise NotImplementedError()
822
 
 
823
 
    def execute(self, object, *multiparams, **params):
824
 
        """Executes the given construct and returns a :class:`.ResultProxy`."""
825
 
        raise NotImplementedError()
826
 
 
827
 
    def scalar(self, object, *multiparams, **params):
828
 
        """Executes and returns the first column of the first row.
829
 
 
830
 
        The underlying cursor is closed after execution.
831
 
        """
832
 
        raise NotImplementedError()
833
 
 
834
 
    def _run_visitor(self, visitorcallable, element,
835
 
                                    **kwargs):
836
 
        raise NotImplementedError()
837
 
 
838
 
    def _execute_clauseelement(self, elem, multiparams=None, params=None):
839
 
        raise NotImplementedError()
 
12
from __future__ import with_statement
 
13
import sys
 
14
from .. import exc, schema, util, log, interfaces
 
15
from ..sql import expression, util as sql_util
 
16
from .interfaces import Connectable, Compiled
 
17
from .util import _distill_params
 
18
import contextlib
840
19
 
841
20
 
842
21
class Connection(Connectable):
865
44
    """
866
45
 
867
46
    def __init__(self, engine, connection=None, close_with_result=False,
868
 
                 _branch=False, _execution_options=None):
 
47
                 _branch=False, _execution_options=None,
 
48
                 _dispatch=None,
 
49
                 _has_events=False):
869
50
        """Construct a new Connection.
870
51
 
871
52
        The constructor here is not public and is only called only by an
881
62
        self.__savepoint_seq = 0
882
63
        self.__branch = _branch
883
64
        self.__invalid = False
884
 
        self._has_events = engine._has_events
 
65
        self.__can_reconnect = True
 
66
        if _dispatch:
 
67
            self.dispatch = _dispatch
 
68
        elif engine._has_events:
 
69
            self.dispatch = self.dispatch._join(engine.dispatch)
 
70
        self._has_events = _has_events or engine._has_events
 
71
 
885
72
        self._echo = self.engine._should_log_info()
886
73
        if _execution_options:
887
74
            self._execution_options =\
900
87
 
901
88
        return self.engine._connection_cls(
902
89
                                self.engine,
903
 
                                self.__connection, _branch=True)
 
90
                                self.__connection,
 
91
                                _branch=True,
 
92
                                _has_events=self._has_events,
 
93
                                _dispatch=self.dispatch)
904
94
 
905
95
    def _clone(self):
906
96
        """Create a shallow copy of this Connection.
924
114
        the same underlying DBAPI connection, but also defines the given
925
115
        execution options which will take effect for a call to
926
116
        :meth:`execute`. As the new :class:`.Connection` references the same
927
 
        underlying resource, it is probably best to ensure that the copies
 
117
        underlying resource, it's usually a good idea to ensure that the copies
928
118
        would be discarded immediately, which is implicit if used as in::
929
119
 
930
120
            result = connection.execution_options(stream_results=True).\\
931
121
                                execute(stmt)
932
122
 
933
 
        :meth:`.Connection.execution_options` accepts all options as those
934
 
        accepted by :meth:`.Executable.execution_options`.  Additionally,
935
 
        it includes options that are applicable only to
936
 
        :class:`.Connection`.
 
123
        Note that any key/value can be passed to
 
124
        :meth:`.Connection.execution_options`, and it will be stored in the
 
125
        ``_execution_options`` dictionary of the :class:`.Connection`.   It
 
126
        is suitable for usage by end-user schemes to communicate with
 
127
        event listeners, for example.
 
128
 
 
129
        The keywords that are currently recognized by SQLAlchemy itself
 
130
        include all those listed under :meth:`.Executable.execution_options`,
 
131
        as well as others that are specific to :class:`.Connection`.
937
132
 
938
133
        :param autocommit: Available on: Connection, statement.
939
134
          When True, a COMMIT will be invoked after execution
1019
214
    def closed(self):
1020
215
        """Return True if this connection is closed."""
1021
216
 
1022
 
        return not self.__invalid and '_Connection__connection' \
1023
 
                        not in self.__dict__
 
217
        return '_Connection__connection' not in self.__dict__ \
 
218
            and not self.__can_reconnect
1024
219
 
1025
220
    @property
1026
221
    def invalidated(self):
1038
233
            return self._revalidate_connection()
1039
234
 
1040
235
    def _revalidate_connection(self):
1041
 
        if self.__invalid:
 
236
        if self.__can_reconnect and self.__invalid:
1042
237
            if self.__transaction is not None:
1043
238
                raise exc.InvalidRequestError(
1044
239
                                "Can't reconnect until invalid "
1065
260
 
1066
261
    @property
1067
262
    def info(self):
1068
 
        """A collection of per-DB-API connection instance properties."""
 
263
        """Info dictionary associated with the underlying DBAPI connection
 
264
        referred to by this :class:`.Connection`, allowing user-defined
 
265
        data to be associated with the connection.
 
266
 
 
267
        The data here will follow along with the DBAPI connection including
 
268
        after it is returned to the connection pool and used again
 
269
        in subsequent instances of :class:`.Connection`.
 
270
 
 
271
        """
1069
272
 
1070
273
        return self.connection.info
1071
274
 
1072
275
    def connect(self):
1073
 
        """Returns self.
1074
 
 
1075
 
        This ``Connectable`` interface method returns self, allowing
1076
 
        Connections to be used interchangeably with Engines in most
1077
 
        situations that require a bind.
 
276
        """Returns a branched version of this :class:`.Connection`.
 
277
 
 
278
        The :meth:`.Connection.close` method on the returned
 
279
        :class:`.Connection` can be called and this
 
280
        :class:`.Connection` will remain open.
 
281
 
 
282
        This method provides usage symmetry with
 
283
        :meth:`.Engine.connect`, including for usage
 
284
        with context managers.
 
285
 
1078
286
        """
1079
287
 
1080
 
        return self
 
288
        return self._branch()
1081
289
 
1082
290
    def contextual_connect(self, **kwargs):
1083
 
        """Returns self.
1084
 
 
1085
 
        This ``Connectable`` interface method returns self, allowing
1086
 
        Connections to be used interchangeably with Engines in most
1087
 
        situations that require a bind.
 
291
        """Returns a branched version of this :class:`.Connection`.
 
292
 
 
293
        The :meth:`.Connection.close` method on the returned
 
294
        :class:`.Connection` can be called and this
 
295
        :class:`.Connection` will remain open.
 
296
 
 
297
        This method provides usage symmetry with
 
298
        :meth:`.Engine.contextual_connect`, including for usage
 
299
        with context managers.
 
300
 
1088
301
        """
1089
302
 
1090
 
        return self
 
303
        return self._branch()
1091
304
 
1092
305
    def invalidate(self, exception=None):
1093
306
        """Invalidate the underlying DBAPI connection associated with
1118
331
        del self.__connection
1119
332
        self.__invalid = True
1120
333
 
1121
 
 
1122
334
    def detach(self):
1123
335
        """Detach the underlying DB-API connection from its connection pool.
1124
336
 
1167
379
 
1168
380
        :meth:`.Connection.begin_twophase` - use a two phase /XID transaction
1169
381
 
1170
 
        :meth:`.Engine.begin` - context manager available from :class:`.Engine`.
 
382
        :meth:`.Engine.begin` - context manager available from
 
383
        :class:`.Engine`.
1171
384
 
1172
385
        """
1173
386
 
1204
417
 
1205
418
        The returned object is an instance of :class:`.TwoPhaseTransaction`,
1206
419
        which in addition to the methods provided by
1207
 
        :class:`.Transaction`, also provides a :meth:`~.TwoPhaseTransaction.prepare`
1208
 
        method.
 
420
        :class:`.Transaction`, also provides a
 
421
        :meth:`~.TwoPhaseTransaction.prepare` method.
1209
422
 
1210
423
        :param xid: the two phase transaction id.  If not supplied, a
1211
424
          random id will be generated.
1220
433
                "Cannot start a two phase transaction when a transaction "
1221
434
                "is already in progress.")
1222
435
        if xid is None:
1223
 
            xid = self.engine.dialect.create_xid();
 
436
            xid = self.engine.dialect.create_xid()
1224
437
        self.__transaction = TwoPhaseTransaction(self, xid)
1225
438
        return self.__transaction
1226
439
 
1243
456
            self.engine.logger.info("BEGIN (implicit)")
1244
457
 
1245
458
        if self._has_events:
1246
 
            self.engine.dispatch.begin(self)
 
459
            self.dispatch.begin(self)
1247
460
 
1248
461
        try:
1249
462
            self.engine.dialect.do_begin(self.connection)
1250
463
        except Exception, e:
1251
464
            self._handle_dbapi_exception(e, None, None, None, None)
1252
 
            raise
1253
465
 
1254
466
    def _rollback_impl(self):
1255
467
        if self._has_events:
1256
 
            self.engine.dispatch.rollback(self)
 
468
            self.dispatch.rollback(self)
1257
469
 
1258
470
        if self._still_open_and_connection_is_valid:
1259
471
            if self._echo:
1263
475
                self.__transaction = None
1264
476
            except Exception, e:
1265
477
                self._handle_dbapi_exception(e, None, None, None, None)
1266
 
                raise
1267
478
        else:
1268
479
            self.__transaction = None
1269
480
 
1270
 
    def _commit_impl(self):
 
481
    def _commit_impl(self, autocommit=False):
1271
482
        if self._has_events:
1272
 
            self.engine.dispatch.commit(self)
 
483
            self.dispatch.commit(self)
1273
484
 
1274
485
        if self._echo:
1275
486
            self.engine.logger.info("COMMIT")
1278
489
            self.__transaction = None
1279
490
        except Exception, e:
1280
491
            self._handle_dbapi_exception(e, None, None, None, None)
1281
 
            raise
1282
492
 
1283
493
    def _savepoint_impl(self, name=None):
1284
494
        if self._has_events:
1285
 
            self.engine.dispatch.savepoint(self, name)
 
495
            self.dispatch.savepoint(self, name)
1286
496
 
1287
497
        if name is None:
1288
498
            self.__savepoint_seq += 1
1293
503
 
1294
504
    def _rollback_to_savepoint_impl(self, name, context):
1295
505
        if self._has_events:
1296
 
            self.engine.dispatch.rollback_savepoint(self, name, context)
 
506
            self.dispatch.rollback_savepoint(self, name, context)
1297
507
 
1298
508
        if self._still_open_and_connection_is_valid:
1299
509
            self.engine.dialect.do_rollback_to_savepoint(self, name)
1301
511
 
1302
512
    def _release_savepoint_impl(self, name, context):
1303
513
        if self._has_events:
1304
 
            self.engine.dispatch.release_savepoint(self, name, context)
 
514
            self.dispatch.release_savepoint(self, name, context)
1305
515
 
1306
516
        if self._still_open_and_connection_is_valid:
1307
517
            self.engine.dialect.do_release_savepoint(self, name)
1308
518
        self.__transaction = context
1309
519
 
1310
520
    def _begin_twophase_impl(self, xid):
 
521
        if self._echo:
 
522
            self.engine.logger.info("BEGIN TWOPHASE (implicit)")
1311
523
        if self._has_events:
1312
 
            self.engine.dispatch.begin_twophase(self, xid)
 
524
            self.dispatch.begin_twophase(self, xid)
1313
525
 
1314
526
        if self._still_open_and_connection_is_valid:
1315
527
            self.engine.dialect.do_begin_twophase(self, xid)
1316
528
 
1317
529
    def _prepare_twophase_impl(self, xid):
1318
530
        if self._has_events:
1319
 
            self.engine.dispatch.prepare_twophase(self, xid)
 
531
            self.dispatch.prepare_twophase(self, xid)
1320
532
 
1321
533
        if self._still_open_and_connection_is_valid:
1322
534
            assert isinstance(self.__transaction, TwoPhaseTransaction)
1324
536
 
1325
537
    def _rollback_twophase_impl(self, xid, is_prepared):
1326
538
        if self._has_events:
1327
 
            self.engine.dispatch.rollback_twophase(self, xid, is_prepared)
 
539
            self.dispatch.rollback_twophase(self, xid, is_prepared)
1328
540
 
1329
541
        if self._still_open_and_connection_is_valid:
1330
542
            assert isinstance(self.__transaction, TwoPhaseTransaction)
1333
545
 
1334
546
    def _commit_twophase_impl(self, xid, is_prepared):
1335
547
        if self._has_events:
1336
 
            self.engine.dispatch.commit_twophase(self, xid, is_prepared)
 
548
            self.dispatch.commit_twophase(self, xid, is_prepared)
1337
549
 
1338
550
        if self._still_open_and_connection_is_valid:
1339
551
            assert isinstance(self.__transaction, TwoPhaseTransaction)
1363
575
        and will allow no further operations.
1364
576
 
1365
577
        """
1366
 
 
1367
578
        try:
1368
579
            conn = self.__connection
1369
580
        except AttributeError:
1370
 
            return
1371
 
        if not self.__branch:
1372
 
            conn.close()
1373
 
        self.__invalid = False
1374
 
        del self.__connection
 
581
            pass
 
582
        else:
 
583
            if not self.__branch:
 
584
                conn.close()
 
585
            del self.__connection
 
586
        self.__can_reconnect = False
1375
587
        self.__transaction = None
1376
588
 
1377
589
    def scalar(self, object, *multiparams, **params):
1383
595
        return self.execute(object, *multiparams, **params).scalar()
1384
596
 
1385
597
    def execute(self, object, *multiparams, **params):
1386
 
        """Executes the a SQL statement construct and returns a :class:`.ResultProxy`.
 
598
        """Executes the a SQL statement construct and returns a
 
599
        :class:`.ResultProxy`.
1387
600
 
1388
601
        :param object: The statement to be executed.  May be
1389
602
         one of:
1452
665
                                "Unexecutable object type: %s" %
1453
666
                                type(object))
1454
667
 
1455
 
    def __distill_params(self, multiparams, params):
1456
 
        """Given arguments from the calling form *multiparams, **params,
1457
 
        return a list of bind parameter structures, usually a list of
1458
 
        dictionaries.
1459
 
 
1460
 
        In the case of 'raw' execution which accepts positional parameters,
1461
 
        it may be a list of tuples or lists.
1462
 
 
1463
 
        """
1464
 
 
1465
 
        if not multiparams:
1466
 
            if params:
1467
 
                return [params]
1468
 
            else:
1469
 
                return []
1470
 
        elif len(multiparams) == 1:
1471
 
            zero = multiparams[0]
1472
 
            if isinstance(zero, (list, tuple)):
1473
 
                if not zero or hasattr(zero[0], '__iter__') and \
1474
 
                        not hasattr(zero[0], 'strip'):
1475
 
                    return zero
1476
 
                else:
1477
 
                    return [zero]
1478
 
            elif hasattr(zero, 'keys'):
1479
 
                return [zero]
1480
 
            else:
1481
 
                return [[zero]]
1482
 
        else:
1483
 
            if hasattr(multiparams[0], '__iter__') and \
1484
 
                not hasattr(multiparams[0], 'strip'):
1485
 
                return multiparams
1486
 
            else:
1487
 
                return [multiparams]
1488
 
 
1489
668
    def _execute_function(self, func, multiparams, params):
1490
669
        """Execute a sql.FunctionElement object."""
1491
670
 
1496
675
        """Execute a schema.ColumnDefault object."""
1497
676
 
1498
677
        if self._has_events:
1499
 
            for fn in self.engine.dispatch.before_execute:
 
678
            for fn in self.dispatch.before_execute:
1500
679
                default, multiparams, params = \
1501
680
                    fn(self, default, multiparams, params)
1502
681
 
1511
690
                                dialect, self, conn)
1512
691
        except Exception, e:
1513
692
            self._handle_dbapi_exception(e, None, None, None, None)
1514
 
            raise
1515
693
 
1516
694
        ret = ctx._exec_default(default, None)
1517
695
        if self.should_close_with_result:
1518
696
            self.close()
1519
697
 
1520
698
        if self._has_events:
1521
 
            self.engine.dispatch.after_execute(self,
 
699
            self.dispatch.after_execute(self,
1522
700
                default, multiparams, params, ret)
1523
701
 
1524
702
        return ret
1527
705
        """Execute a schema.DDL object."""
1528
706
 
1529
707
        if self._has_events:
1530
 
            for fn in self.engine.dispatch.before_execute:
 
708
            for fn in self.dispatch.before_execute:
1531
709
                ddl, multiparams, params = \
1532
710
                    fn(self, ddl, multiparams, params)
1533
711
 
1542
720
            compiled
1543
721
        )
1544
722
        if self._has_events:
1545
 
            self.engine.dispatch.after_execute(self,
 
723
            self.dispatch.after_execute(self,
1546
724
                ddl, multiparams, params, ret)
1547
725
        return ret
1548
726
 
1550
728
        """Execute a sql.ClauseElement object."""
1551
729
 
1552
730
        if self._has_events:
1553
 
            for fn in self.engine.dispatch.before_execute:
 
731
            for fn in self.dispatch.before_execute:
1554
732
                elem, multiparams, params = \
1555
733
                    fn(self, elem, multiparams, params)
1556
734
 
1557
 
        distilled_params = self.__distill_params(multiparams, params)
 
735
        distilled_params = _distill_params(multiparams, params)
1558
736
        if distilled_params:
1559
737
            keys = distilled_params[0].keys()
1560
738
        else:
1575
753
                            dialect=dialect, column_keys=keys,
1576
754
                            inline=len(distilled_params) > 1)
1577
755
 
1578
 
 
1579
756
        ret = self._execute_context(
1580
757
            dialect,
1581
758
            dialect.execution_ctx_cls._init_compiled,
1584
761
            compiled_sql, distilled_params
1585
762
        )
1586
763
        if self._has_events:
1587
 
            self.engine.dispatch.after_execute(self,
 
764
            self.dispatch.after_execute(self,
1588
765
                elem, multiparams, params, ret)
1589
766
        return ret
1590
767
 
1592
769
        """Execute a sql.Compiled object."""
1593
770
 
1594
771
        if self._has_events:
1595
 
            for fn in self.engine.dispatch.before_execute:
 
772
            for fn in self.dispatch.before_execute:
1596
773
                compiled, multiparams, params = \
1597
774
                    fn(self, compiled, multiparams, params)
1598
775
 
1599
776
        dialect = self.dialect
1600
 
        parameters=self.__distill_params(multiparams, params)
 
777
        parameters = _distill_params(multiparams, params)
1601
778
        ret = self._execute_context(
1602
779
            dialect,
1603
780
            dialect.execution_ctx_cls._init_compiled,
1606
783
            compiled, parameters
1607
784
        )
1608
785
        if self._has_events:
1609
 
            self.engine.dispatch.after_execute(self,
 
786
            self.dispatch.after_execute(self,
1610
787
                compiled, multiparams, params, ret)
1611
788
        return ret
1612
789
 
1614
791
        """Execute a string SQL statement."""
1615
792
 
1616
793
        if self._has_events:
1617
 
            for fn in self.engine.dispatch.before_execute:
 
794
            for fn in self.dispatch.before_execute:
1618
795
                statement, multiparams, params = \
1619
796
                    fn(self, statement, multiparams, params)
1620
797
 
1621
798
        dialect = self.dialect
1622
 
        parameters = self.__distill_params(multiparams, params)
 
799
        parameters = _distill_params(multiparams, params)
1623
800
        ret = self._execute_context(
1624
801
            dialect,
1625
802
            dialect.execution_ctx_cls._init_statement,
1628
805
            statement, parameters
1629
806
        )
1630
807
        if self._has_events:
1631
 
            self.engine.dispatch.after_execute(self,
 
808
            self.dispatch.after_execute(self,
1632
809
                statement, multiparams, params, ret)
1633
810
        return ret
1634
811
 
1649
826
            self._handle_dbapi_exception(e,
1650
827
                        str(statement), parameters,
1651
828
                        None, None)
1652
 
            raise
1653
829
 
1654
830
        if context.compiled:
1655
831
            context.pre_exec()
1662
838
            parameters = parameters[0]
1663
839
 
1664
840
        if self._has_events:
1665
 
            for fn in self.engine.dispatch.before_cursor_execute:
 
841
            for fn in self.dispatch.before_cursor_execute:
1666
842
                statement, parameters = \
1667
843
                            fn(self, cursor, statement, parameters,
1668
844
                                        context, context.executemany)
1696
872
                                parameters,
1697
873
                                cursor,
1698
874
                                context)
1699
 
            raise
1700
 
 
1701
875
 
1702
876
        if self._has_events:
1703
 
            self.engine.dispatch.after_cursor_execute(self, cursor,
 
877
            self.dispatch.after_cursor_execute(self, cursor,
1704
878
                                                statement,
1705
879
                                                parameters,
1706
880
                                                context,
1719
893
            if context._is_implicit_returning:
1720
894
                context._fetch_implicit_returning(result)
1721
895
                result.close(_autoclose_connection=False)
 
896
                result._metadata = None
1722
897
            elif not context._is_explicit_returning:
1723
898
                result.close(_autoclose_connection=False)
 
899
                result._metadata = None
1724
900
        elif result._metadata is None:
1725
901
            # no results, get rowcount
1726
902
            # (which requires open cursor on some drivers
1729
905
            result.close(_autoclose_connection=False)
1730
906
 
1731
907
        if self.__transaction is None and context.should_autocommit:
1732
 
            self._commit_impl()
 
908
            self._commit_impl(autocommit=True)
1733
909
 
1734
910
        if result.closed and self.should_close_with_result:
1735
911
            self.close()
1736
912
 
1737
913
        return result
1738
914
 
1739
 
    def _cursor_execute(self, cursor, statement, parameters):
 
915
    def _cursor_execute(self, cursor, statement, parameters, context=None):
1740
916
        """Execute a statement + params on the given cursor.
1741
917
 
1742
918
        Adds appropriate logging and exception handling.
1747
923
        terminates at _execute_context().
1748
924
 
1749
925
        """
 
926
        if self._has_events:
 
927
            for fn in self.dispatch.before_cursor_execute:
 
928
                statement, parameters = \
 
929
                            fn(self, cursor, statement, parameters,
 
930
                                        context,
 
931
                                        context.executemany
 
932
                                           if context is not None else False)
 
933
 
1750
934
        if self._echo:
1751
935
            self.engine.logger.info(statement)
1752
936
            self.engine.logger.info("%r", parameters)
1762
946
                                parameters,
1763
947
                                cursor,
1764
948
                                None)
1765
 
            raise
1766
949
 
1767
950
    def _safe_close_cursor(self, cursor):
1768
951
        """Close the given cursor, catching exceptions
1776
959
                ex_text = str(e)
1777
960
            except TypeError:
1778
961
                ex_text = repr(e)
1779
 
            self.connection._logger.warn("Error closing cursor: %s", ex_text)
 
962
            if not self.closed:
 
963
                self.connection._logger.warn(
 
964
                            "Error closing cursor: %s", ex_text)
1780
965
 
1781
966
            if isinstance(e, (SystemExit, KeyboardInterrupt)):
1782
967
                raise
1783
968
 
 
969
    _reentrant_error = False
 
970
    _is_disconnect = False
 
971
 
1784
972
    def _handle_dbapi_exception(self,
1785
973
                                    e,
1786
974
                                    statement,
1787
975
                                    parameters,
1788
976
                                    cursor,
1789
977
                                    context):
1790
 
        if getattr(self, '_reentrant_error', False):
1791
 
            # Py3K
1792
 
            #raise exc.DBAPIError.instance(statement, parameters, e,
1793
 
            #                               self.dialect.dbapi.Error) from e
1794
 
            # Py2K
1795
 
            raise exc.DBAPIError.instance(statement,
 
978
 
 
979
        exc_info = sys.exc_info()
 
980
 
 
981
        if not self._is_disconnect:
 
982
            self._is_disconnect = isinstance(e, self.dialect.dbapi.Error) and \
 
983
                not self.closed and \
 
984
                self.dialect.is_disconnect(e, self.__connection, cursor)
 
985
 
 
986
        if self._reentrant_error:
 
987
            util.raise_from_cause(
 
988
                        exc.DBAPIError.instance(statement,
1796
989
                                            parameters,
1797
990
                                            e,
1798
 
                                            self.dialect.dbapi.Error), \
1799
 
                                            None, sys.exc_info()[2]
1800
 
            # end Py2K
 
991
                                            self.dialect.dbapi.Error),
 
992
                        exc_info
 
993
                        )
1801
994
        self._reentrant_error = True
1802
995
        try:
1803
996
            # non-DBAPI error - if we already got a context,
1807
1000
 
1808
1001
            if should_wrap and context:
1809
1002
                if self._has_events:
1810
 
                    self.engine.dispatch.dbapi_error(self,
 
1003
                    self.dispatch.dbapi_error(self,
1811
1004
                                                    cursor,
1812
1005
                                                    statement,
1813
1006
                                                    parameters,
1815
1008
                                                    e)
1816
1009
                context.handle_dbapi_exception(e)
1817
1010
 
1818
 
            is_disconnect = isinstance(e, self.dialect.dbapi.Error) and \
1819
 
                                self.dialect.is_disconnect(e, self.__connection, cursor)
1820
 
 
1821
 
 
1822
 
            if is_disconnect:
1823
 
                self.invalidate(e)
1824
 
                self.engine.dispose()
1825
 
            else:
 
1011
            if not self._is_disconnect:
1826
1012
                if cursor:
1827
1013
                    self._safe_close_cursor(cursor)
1828
1014
                self._autorollback()
1829
 
                if self.should_close_with_result:
1830
 
                    self.close()
1831
 
 
1832
 
            if not should_wrap:
1833
 
                return
1834
 
 
1835
 
            # Py3K
1836
 
            #raise exc.DBAPIError.instance(
1837
 
            #                        statement,
1838
 
            #                        parameters,
1839
 
            #                        e,
1840
 
            #                        self.dialect.dbapi.Error,
1841
 
            #                        connection_invalidated=is_disconnect) \
1842
 
            #                        from e
1843
 
            # Py2K
1844
 
            raise exc.DBAPIError.instance(
1845
 
                                    statement,
1846
 
                                    parameters,
1847
 
                                    e,
1848
 
                                    self.dialect.dbapi.Error,
1849
 
                                    connection_invalidated=is_disconnect), \
1850
 
                                    None, sys.exc_info()[2]
1851
 
            # end Py2K
 
1015
 
 
1016
            if should_wrap:
 
1017
                util.raise_from_cause(
 
1018
                                    exc.DBAPIError.instance(
 
1019
                                        statement,
 
1020
                                        parameters,
 
1021
                                        e,
 
1022
                                        self.dialect.dbapi.Error,
 
1023
                                        connection_invalidated=self._is_disconnect),
 
1024
                                    exc_info
 
1025
                                )
 
1026
 
 
1027
            util.reraise(*exc_info)
1852
1028
 
1853
1029
        finally:
1854
1030
            del self._reentrant_error
 
1031
            if self._is_disconnect:
 
1032
                del self._is_disconnect
 
1033
                dbapi_conn_wrapper = self.connection
 
1034
                self.invalidate(e)
 
1035
                if not hasattr(dbapi_conn_wrapper, '_pool') or \
 
1036
                        dbapi_conn_wrapper._pool is self.engine.pool:
 
1037
                    self.engine.dispose()
 
1038
            if self.should_close_with_result:
 
1039
                self.close()
1855
1040
 
1856
1041
    # poor man's multimethod/generic function thingy
1857
1042
    executors = {
1863
1048
        basestring: _execute_text
1864
1049
    }
1865
1050
 
1866
 
    @util.deprecated("0.7", "Use the create() method on the given schema "
1867
 
                            "object directly, i.e. :meth:`.Table.create`, "
1868
 
                            ":meth:`.Index.create`, :meth:`.MetaData.create_all`")
1869
 
    def create(self, entity, **kwargs):
1870
 
        """Emit CREATE statements for the given schema entity."""
1871
 
 
1872
 
        return self.engine.create(entity, connection=self, **kwargs)
1873
 
 
1874
 
    @util.deprecated("0.7", "Use the drop() method on the given schema "
1875
 
                            "object directly, i.e. :meth:`.Table.drop`, "
1876
 
                            ":meth:`.Index.drop`, :meth:`.MetaData.drop_all`")
1877
 
    def drop(self, entity, **kwargs):
1878
 
        """Emit DROP statements for the given schema entity."""
1879
 
 
1880
 
        return self.engine.drop(entity, connection=self, **kwargs)
1881
 
 
1882
 
    @util.deprecated("0.7", "Use autoload=True with :class:`.Table`, "
1883
 
                        "or use the :class:`.Inspector` object.")
1884
 
    def reflecttable(self, table, include_columns=None):
1885
 
        """Load table description from the database.
1886
 
 
1887
 
        Given a :class:`.Table` object, reflect its columns and
1888
 
        properties from the database, populating the given :class:`.Table`
1889
 
        object with attributes..  If include_columns (a list or
1890
 
        set) is specified, limit the autoload to the given column
1891
 
        names.
1892
 
 
1893
 
        The default implementation uses the
1894
 
        :class:`.Inspector` interface to
1895
 
        provide the output, building upon the granular table/column/
1896
 
        constraint etc. methods of :class:`.Dialect`.
1897
 
 
1898
 
        """
1899
 
        return self.engine.reflecttable(table, self, include_columns)
1900
 
 
1901
1051
    def default_schema_name(self):
1902
1052
        return self.engine.dialect.get_default_schema_name(self)
1903
1053
 
1949
1099
            trans.commit()
1950
1100
            return ret
1951
1101
        except:
1952
 
            trans.rollback()
1953
 
            raise
 
1102
            with util.safe_reraise():
 
1103
                trans.rollback()
1954
1104
 
1955
1105
    def run_callable(self, callable_, *args, **kwargs):
1956
1106
        """Given a callable object or function, execute it, passing
2056
1206
            try:
2057
1207
                self.commit()
2058
1208
            except:
2059
 
                self.rollback()
2060
 
                raise
 
1209
                with util.safe_reraise():
 
1210
                    self.rollback()
2061
1211
        else:
2062
1212
            self.rollback()
2063
1213
 
 
1214
 
2064
1215
class RootTransaction(Transaction):
2065
1216
    def __init__(self, connection):
2066
1217
        super(RootTransaction, self).__init__(connection, None)
2136
1287
class Engine(Connectable, log.Identified):
2137
1288
    """
2138
1289
    Connects a :class:`~sqlalchemy.pool.Pool` and
2139
 
    :class:`~sqlalchemy.engine.base.Dialect` together to provide a source
2140
 
    of database connectivity and behavior.
 
1290
    :class:`~sqlalchemy.engine.interfaces.Dialect` together to provide a
 
1291
    source of database connectivity and behavior.
2141
1292
 
2142
1293
    An :class:`.Engine` object is instantiated publicly using the
2143
1294
    :func:`~sqlalchemy.create_engine` function.
2144
1295
 
2145
1296
    See also:
2146
1297
 
2147
 
    :ref:`engines_toplevel`
 
1298
    :doc:`/core/engines`
2148
1299
 
2149
1300
    :ref:`connections_toplevel`
2150
1301
 
2161
1312
        self.pool = pool
2162
1313
        self.url = url
2163
1314
        self.dialect = dialect
 
1315
        self.pool._dialect = dialect
2164
1316
        if logging_name:
2165
1317
            self.logging_name = logging_name
2166
1318
        self.echo = echo
2169
1321
        if proxy:
2170
1322
            interfaces.ConnectionProxy._adapt_listener(self, proxy)
2171
1323
        if execution_options:
2172
 
            if 'isolation_level' in execution_options:
2173
 
                raise exc.ArgumentError(
2174
 
                    "'isolation_level' execution option may "
2175
 
                    "only be specified on Connection.execution_options(). "
2176
 
                    "To set engine-wide isolation level, "
2177
 
                    "use the isolation_level argument to create_engine()."
2178
 
                )
2179
1324
            self.update_execution_options(**execution_options)
2180
1325
 
2181
 
    dispatch = event.dispatcher(events.ConnectionEvents)
2182
 
 
2183
1326
    def update_execution_options(self, **opt):
2184
1327
        """Update the default execution_options dictionary
2185
1328
        of this :class:`.Engine`.
2190
1333
        can be sent via the ``execution_options`` parameter
2191
1334
        to :func:`.create_engine`.
2192
1335
 
2193
 
        See :meth:`.Connection.execution_options` for more
2194
 
        details on execution options.
 
1336
        .. seealso::
 
1337
 
 
1338
            :meth:`.Connection.execution_options`
 
1339
 
 
1340
            :meth:`.Engine.execution_options`
2195
1341
 
2196
1342
        """
 
1343
        if 'isolation_level' in opt:
 
1344
            raise exc.ArgumentError(
 
1345
                "'isolation_level' execution option may "
 
1346
                "only be specified on Connection.execution_options(). "
 
1347
                "To set engine-wide isolation level, "
 
1348
                "use the isolation_level argument to create_engine()."
 
1349
            )
2197
1350
        self._execution_options = \
2198
1351
                self._execution_options.union(opt)
2199
1352
 
 
1353
    def execution_options(self, **opt):
 
1354
        """Return a new :class:`.Engine` that will provide
 
1355
        :class:`.Connection` objects with the given execution options.
 
1356
 
 
1357
        The returned :class:`.Engine` remains related to the original
 
1358
        :class:`.Engine` in that it shares the same connection pool and
 
1359
        other state:
 
1360
 
 
1361
        * The :class:`.Pool` used by the new :class:`.Engine` is the
 
1362
          same instance.  The :meth:`.Engine.dispose` method will replace
 
1363
          the connection pool instance for the parent engine as well
 
1364
          as this one.
 
1365
        * Event listeners are "cascaded" - meaning, the new :class:`.Engine`
 
1366
          inherits the events of the parent, and new events can be associated
 
1367
          with the new :class:`.Engine` individually.
 
1368
        * The logging configuration and logging_name is copied from the parent
 
1369
          :class:`.Engine`.
 
1370
 
 
1371
        The intent of the :meth:`.Engine.execution_options` method is
 
1372
        to implement "sharding" schemes where multiple :class:`.Engine`
 
1373
        objects refer to the same connection pool, but are differentiated
 
1374
        by options that would be consumed by a custom event::
 
1375
 
 
1376
            primary_engine = create_engine("mysql://")
 
1377
            shard1 = primary_engine.execution_options(shard_id="shard1")
 
1378
            shard2 = primary_engine.execution_options(shard_id="shard2")
 
1379
 
 
1380
        Above, the ``shard1`` engine serves as a factory for
 
1381
        :class:`.Connection` objects that will contain the execution option
 
1382
        ``shard_id=shard1``, and ``shard2`` will produce :class:`.Connection`
 
1383
        objects that contain the execution option ``shard_id=shard2``.
 
1384
 
 
1385
        An event handler can consume the above execution option to perform
 
1386
        a schema switch or other operation, given a connection.  Below
 
1387
        we emit a MySQL ``use`` statement to switch databases, at the same
 
1388
        time keeping track of which database we've established using the
 
1389
        :attr:`.Connection.info` dictionary, which gives us a persistent
 
1390
        storage space that follows the DBAPI connection::
 
1391
 
 
1392
            from sqlalchemy import event
 
1393
            from sqlalchemy.engine import Engine
 
1394
 
 
1395
            shards = {"default": "base", shard_1: "db1", "shard_2": "db2"}
 
1396
 
 
1397
            @event.listens_for(Engine, "before_cursor_execute")
 
1398
            def _switch_shard(conn, cursor, stmt, params, context, executemany):
 
1399
                shard_id = conn._execution_options.get('shard_id', "default")
 
1400
                current_shard = conn.info.get("current_shard", None)
 
1401
 
 
1402
                if current_shard != shard_id:
 
1403
                    cursor.execute("use %s" % shards[shard_id])
 
1404
                    conn.info["current_shard"] = shard_id
 
1405
 
 
1406
        .. versionadded:: 0.8
 
1407
 
 
1408
        .. seealso::
 
1409
 
 
1410
            :meth:`.Connection.execution_options` - update execution options
 
1411
            on a :class:`.Connection` object.
 
1412
 
 
1413
            :meth:`.Engine.update_execution_options` - update the execution
 
1414
            options for a given :class:`.Engine` in place.
 
1415
 
 
1416
        """
 
1417
        return OptionEngine(self, opt)
 
1418
 
2200
1419
    @property
2201
1420
    def name(self):
2202
 
        """String name of the :class:`~sqlalchemy.engine.Dialect` in use by
2203
 
        this ``Engine``."""
 
1421
        """String name of the :class:`~sqlalchemy.engine.interfaces.Dialect`
 
1422
        in use by this :class:`Engine`."""
2204
1423
 
2205
1424
        return self.dialect.name
2206
1425
 
2207
1426
    @property
2208
1427
    def driver(self):
2209
 
        """Driver name of the :class:`~sqlalchemy.engine.Dialect` in use by
2210
 
        this ``Engine``."""
 
1428
        """Driver name of the :class:`~sqlalchemy.engine.interfaces.Dialect`
 
1429
        in use by this :class:`Engine`."""
2211
1430
 
2212
1431
        return self.dialect.driver
2213
1432
 
2240
1459
        the engine are not affected.
2241
1460
 
2242
1461
        """
2243
 
        self.pool.dispose()
2244
1462
        self.pool = self.pool._replace()
2245
1463
 
2246
 
    @util.deprecated("0.7", "Use the create() method on the given schema "
2247
 
                            "object directly, i.e. :meth:`.Table.create`, "
2248
 
                            ":meth:`.Index.create`, :meth:`.MetaData.create_all`")
2249
 
    def create(self, entity, connection=None, **kwargs):
2250
 
        """Emit CREATE statements for the given schema entity."""
2251
 
 
2252
 
        from sqlalchemy.engine import ddl
2253
 
 
2254
 
        self._run_visitor(ddl.SchemaGenerator, entity,
2255
 
                                connection=connection, **kwargs)
2256
 
 
2257
 
    @util.deprecated("0.7", "Use the drop() method on the given schema "
2258
 
                            "object directly, i.e. :meth:`.Table.drop`, "
2259
 
                            ":meth:`.Index.drop`, :meth:`.MetaData.drop_all`")
2260
 
    def drop(self, entity, connection=None, **kwargs):
2261
 
        """Emit DROP statements for the given schema entity."""
2262
 
 
2263
 
        from sqlalchemy.engine import ddl
2264
 
 
2265
 
        self._run_visitor(ddl.SchemaDropper, entity,
2266
 
                                connection=connection, **kwargs)
2267
 
 
2268
1464
    def _execute_default(self, default):
2269
 
        connection = self.contextual_connect()
2270
 
        try:
2271
 
            return connection._execute_default(default, (), {})
2272
 
        finally:
2273
 
            connection.close()
2274
 
 
2275
 
    @property
2276
 
    @util.deprecated("0.7",
2277
 
                "Use :attr:`~sqlalchemy.sql.expression.func` to create function constructs.")
2278
 
    def func(self):
2279
 
        return expression._FunctionGenerator(bind=self)
2280
 
 
2281
 
    @util.deprecated("0.7",
2282
 
                "Use :func:`.expression.text` to create text constructs.")
2283
 
    def text(self, text, *args, **kwargs):
2284
 
        """Return a :func:`~sqlalchemy.sql.expression.text` construct,
2285
 
        bound to this engine.
2286
 
 
2287
 
        This is equivalent to::
2288
 
 
2289
 
            text("SELECT * FROM table", bind=engine)
2290
 
 
2291
 
        """
2292
 
 
2293
 
        return expression.text(text, bind=self, *args, **kwargs)
 
1465
        with self.contextual_connect() as conn:
 
1466
            return conn._execute_default(default, (), {})
 
1467
 
 
1468
    @contextlib.contextmanager
 
1469
    def _optional_conn_ctx_manager(self, connection=None):
 
1470
        if connection is None:
 
1471
            with self.contextual_connect() as conn:
 
1472
                yield conn
 
1473
        else:
 
1474
            yield connection
2294
1475
 
2295
1476
    def _run_visitor(self, visitorcallable, element,
2296
1477
                                    connection=None, **kwargs):
2297
 
        if connection is None:
2298
 
            conn = self.contextual_connect(close_with_result=False)
2299
 
        else:
2300
 
            conn = connection
2301
 
        try:
 
1478
        with self._optional_conn_ctx_manager(connection) as conn:
2302
1479
            conn._run_visitor(visitorcallable, element, **kwargs)
2303
 
        finally:
2304
 
            if connection is None:
2305
 
                conn.close()
2306
1480
 
2307
1481
    class _trans_ctx(object):
2308
1482
        def __init__(self, conn, transaction, close_with_result):
2337
1511
 
2338
1512
        The ``close_with_result`` flag is normally ``False``, and indicates
2339
1513
        that the :class:`.Connection` will be closed when the operation
2340
 
        is complete.   When set to ``True``, it indicates the :class:`.Connection`
2341
 
        is in "single use" mode, where the :class:`.ResultProxy`
2342
 
        returned by the first call to :meth:`.Connection.execute` will
2343
 
        close the :class:`.Connection` when that :class:`.ResultProxy`
2344
 
        has exhausted all result rows.
 
1514
        is complete.   When set to ``True``, it indicates the
 
1515
        :class:`.Connection` is in "single use" mode, where the
 
1516
        :class:`.ResultProxy` returned by the first call to
 
1517
        :meth:`.Connection.execute` will close the :class:`.Connection` when
 
1518
        that :class:`.ResultProxy` has exhausted all result rows.
2345
1519
 
2346
1520
        .. versionadded:: 0.7.6
2347
1521
 
2358
1532
        try:
2359
1533
            trans = conn.begin()
2360
1534
        except:
2361
 
            conn.close()
2362
 
            raise
 
1535
            with util.safe_reraise():
 
1536
                conn.close()
2363
1537
        return Engine._trans_ctx(conn, trans, close_with_result)
2364
1538
 
2365
1539
    def transaction(self, callable_, *args, **kwargs):
2401
1575
 
2402
1576
        """
2403
1577
 
2404
 
        conn = self.contextual_connect()
2405
 
        try:
 
1578
        with self.contextual_connect() as conn:
2406
1579
            return conn.transaction(callable_, *args, **kwargs)
2407
 
        finally:
2408
 
            conn.close()
2409
1580
 
2410
1581
    def run_callable(self, callable_, *args, **kwargs):
2411
1582
        """Given a callable object or function, execute it, passing
2420
1591
        which one is being dealt with.
2421
1592
 
2422
1593
        """
2423
 
        conn = self.contextual_connect()
2424
 
        try:
 
1594
        with self.contextual_connect() as conn:
2425
1595
            return conn.run_callable(callable_, *args, **kwargs)
2426
 
        finally:
2427
 
            conn.close()
2428
1596
 
2429
1597
    def execute(self, statement, *multiparams, **params):
2430
1598
        """Executes the given construct and returns a :class:`.ResultProxy`.
2459
1627
    def connect(self, **kwargs):
2460
1628
        """Return a new :class:`.Connection` object.
2461
1629
 
2462
 
        The :class:`.Connection` object is a facade that uses a DBAPI connection internally
2463
 
        in order to communicate with the database.  This connection is procured
2464
 
        from the connection-holding :class:`.Pool` referenced by this :class:`.Engine`.
2465
 
        When the :meth:`~.Connection.close` method of the :class:`.Connection` object is called,
2466
 
        the underlying DBAPI connection is then returned to the connection pool,
2467
 
        where it may be used again in a subsequent call to :meth:`~.Engine.connect`.
 
1630
        The :class:`.Connection` object is a facade that uses a DBAPI
 
1631
        connection internally in order to communicate with the database.  This
 
1632
        connection is procured from the connection-holding :class:`.Pool`
 
1633
        referenced by this :class:`.Engine`. When the
 
1634
        :meth:`~.Connection.close` method of the :class:`.Connection` object
 
1635
        is called, the underlying DBAPI connection is then returned to the
 
1636
        connection pool, where it may be used again in a subsequent call to
 
1637
        :meth:`~.Engine.connect`.
2468
1638
 
2469
1639
        """
2470
1640
 
2471
1641
        return self._connection_cls(self, **kwargs)
2472
1642
 
2473
1643
    def contextual_connect(self, close_with_result=False, **kwargs):
2474
 
        """Return a :class:`.Connection` object which may be part of some ongoing context.
 
1644
        """Return a :class:`.Connection` object which may be part of some
 
1645
        ongoing context.
2475
1646
 
2476
1647
        By default, this method does the same thing as :meth:`.Engine.connect`.
2477
1648
        Subclasses of :class:`.Engine` may override this method
2478
1649
        to provide contextual behavior.
2479
1650
 
2480
 
        :param close_with_result: When True, the first :class:`.ResultProxy` created
2481
 
          by the :class:`.Connection` will call the :meth:`.Connection.close` method
2482
 
          of that connection as soon as any pending result rows are exhausted.
2483
 
          This is used to supply the "connectionless execution" behavior provided
2484
 
          by the :meth:`.Engine.execute` method.
 
1651
        :param close_with_result: When True, the first :class:`.ResultProxy`
 
1652
          created by the :class:`.Connection` will call the
 
1653
          :meth:`.Connection.close` method of that connection as soon as any
 
1654
          pending result rows are exhausted. This is used to supply the
 
1655
          "connectionless execution" behavior provided by the
 
1656
          :meth:`.Engine.execute` method.
2485
1657
 
2486
1658
        """
2487
1659
 
2499
1671
          the ``contextual_connect`` for this ``Engine``.
2500
1672
        """
2501
1673
 
2502
 
        if connection is None:
2503
 
            conn = self.contextual_connect()
2504
 
        else:
2505
 
            conn = connection
2506
 
        if not schema:
2507
 
            schema =  self.dialect.default_schema_name
2508
 
        try:
 
1674
        with self._optional_conn_ctx_manager(connection) as conn:
 
1675
            if not schema:
 
1676
                schema = self.dialect.default_schema_name
2509
1677
            return self.dialect.get_table_names(conn, schema)
2510
 
        finally:
2511
 
            if connection is None:
2512
 
                conn.close()
2513
 
 
2514
 
    @util.deprecated("0.7", "Use autoload=True with :class:`.Table`, "
2515
 
                        "or use the :class:`.Inspector` object.")
2516
 
    def reflecttable(self, table, connection=None, include_columns=None):
2517
 
        """Load table description from the database.
2518
 
 
2519
 
        Uses the given :class:`.Connection`, or if None produces
2520
 
        its own :class:`.Connection`, and passes the ``table``
2521
 
        and ``include_columns`` arguments onto that
2522
 
        :class:`.Connection` object's :meth:`.Connection.reflecttable`
2523
 
        method.  The :class:`.Table` object is then populated
2524
 
        with new attributes.
2525
 
 
2526
 
        """
2527
 
        if connection is None:
2528
 
            conn = self.contextual_connect()
2529
 
        else:
2530
 
            conn = connection
2531
 
        try:
2532
 
            self.dialect.reflecttable(conn, table, include_columns)
2533
 
        finally:
2534
 
            if connection is None:
2535
 
                conn.close()
2536
1678
 
2537
1679
    def has_table(self, table_name, schema=None):
2538
1680
        return self.run_callable(self.dialect.has_table, table_name, schema)
2557
1699
        return self.pool.unique_connection()
2558
1700
 
2559
1701
 
2560
 
# This reconstructor is necessary so that pickles with the C extension or
2561
 
# without use the same Binary format.
2562
 
try:
2563
 
    # We need a different reconstructor on the C extension so that we can
2564
 
    # add extra checks that fields have correctly been initialized by
2565
 
    # __setstate__.
2566
 
    from sqlalchemy.cresultproxy import safe_rowproxy_reconstructor
2567
 
 
2568
 
    # The extra function embedding is needed so that the
2569
 
    # reconstructor function has the same signature whether or not
2570
 
    # the extension is present.
2571
 
    def rowproxy_reconstructor(cls, state):
2572
 
        return safe_rowproxy_reconstructor(cls, state)
2573
 
except ImportError:
2574
 
    def rowproxy_reconstructor(cls, state):
2575
 
        obj = cls.__new__(cls)
2576
 
        obj.__setstate__(state)
2577
 
        return obj
2578
 
 
2579
 
try:
2580
 
    from sqlalchemy.cresultproxy import BaseRowProxy
2581
 
except ImportError:
2582
 
    class BaseRowProxy(object):
2583
 
        __slots__ = ('_parent', '_row', '_processors', '_keymap')
2584
 
 
2585
 
        def __init__(self, parent, row, processors, keymap):
2586
 
            """RowProxy objects are constructed by ResultProxy objects."""
2587
 
 
2588
 
            self._parent = parent
2589
 
            self._row = row
2590
 
            self._processors = processors
2591
 
            self._keymap = keymap
2592
 
 
2593
 
        def __reduce__(self):
2594
 
            return (rowproxy_reconstructor,
2595
 
                    (self.__class__, self.__getstate__()))
2596
 
 
2597
 
        def values(self):
2598
 
            """Return the values represented by this RowProxy as a list."""
2599
 
            return list(self)
2600
 
 
2601
 
        def __iter__(self):
2602
 
            for processor, value in izip(self._processors, self._row):
2603
 
                if processor is None:
2604
 
                    yield value
2605
 
                else:
2606
 
                    yield processor(value)
2607
 
 
2608
 
        def __len__(self):
2609
 
            return len(self._row)
2610
 
 
2611
 
        def __getitem__(self, key):
2612
 
            try:
2613
 
                processor, obj, index = self._keymap[key]
2614
 
            except KeyError:
2615
 
                processor, obj, index = self._parent._key_fallback(key)
2616
 
            except TypeError:
2617
 
                if isinstance(key, slice):
2618
 
                    l = []
2619
 
                    for processor, value in izip(self._processors[key],
2620
 
                                                 self._row[key]):
2621
 
                        if processor is None:
2622
 
                            l.append(value)
2623
 
                        else:
2624
 
                            l.append(processor(value))
2625
 
                    return tuple(l)
2626
 
                else:
2627
 
                    raise
2628
 
            if index is None:
2629
 
                raise exc.InvalidRequestError(
2630
 
                        "Ambiguous column name '%s' in result set! "
2631
 
                        "try 'use_labels' option on select statement." % key)
2632
 
            if processor is not None:
2633
 
                return processor(self._row[index])
2634
 
            else:
2635
 
                return self._row[index]
2636
 
 
2637
 
        def __getattr__(self, name):
2638
 
            try:
2639
 
                return self[name]
2640
 
            except KeyError, e:
2641
 
                raise AttributeError(e.args[0])
2642
 
 
2643
 
 
2644
 
class RowProxy(BaseRowProxy):
2645
 
    """Proxy values from a single cursor row.
2646
 
 
2647
 
    Mostly follows "ordered dictionary" behavior, mapping result
2648
 
    values to the string-based column name, the integer position of
2649
 
    the result in the row, as well as Column instances which can be
2650
 
    mapped to the original Columns that produced this result set (for
2651
 
    results that correspond to constructed SQL expressions).
2652
 
    """
2653
 
    __slots__ = ()
2654
 
 
2655
 
    def __contains__(self, key):
2656
 
        return self._parent._has_key(self._row, key)
2657
 
 
2658
 
    def __getstate__(self):
2659
 
        return {
2660
 
            '_parent': self._parent,
2661
 
            '_row': tuple(self)
2662
 
        }
2663
 
 
2664
 
    def __setstate__(self, state):
2665
 
        self._parent = parent = state['_parent']
2666
 
        self._row = state['_row']
2667
 
        self._processors = parent._processors
2668
 
        self._keymap = parent._keymap
2669
 
 
2670
 
    __hash__ = None
2671
 
 
2672
 
    def __eq__(self, other):
2673
 
        return other is self or other == tuple(self)
2674
 
 
2675
 
    def __ne__(self, other):
2676
 
        return not self.__eq__(other)
2677
 
 
2678
 
    def __repr__(self):
2679
 
        return repr(tuple(self))
2680
 
 
2681
 
    def has_key(self, key):
2682
 
        """Return True if this RowProxy contains the given key."""
2683
 
 
2684
 
        return self._parent._has_key(self._row, key)
2685
 
 
2686
 
    def items(self):
2687
 
        """Return a list of tuples, each tuple containing a key/value pair."""
2688
 
        # TODO: no coverage here
2689
 
        return [(key, self[key]) for key in self.iterkeys()]
2690
 
 
2691
 
    def keys(self):
2692
 
        """Return the list of keys as strings represented by this RowProxy."""
2693
 
 
2694
 
        return self._parent.keys
2695
 
 
2696
 
    def iterkeys(self):
2697
 
        return iter(self._parent.keys)
2698
 
 
2699
 
    def itervalues(self):
2700
 
        return iter(self)
2701
 
 
2702
 
try:
2703
 
    # Register RowProxy with Sequence,
2704
 
    # so sequence protocol is implemented
2705
 
    from collections import Sequence
2706
 
    Sequence.register(RowProxy)
2707
 
except ImportError:
2708
 
    pass
2709
 
 
2710
 
 
2711
 
class ResultMetaData(object):
2712
 
    """Handle cursor.description, applying additional info from an execution
2713
 
    context."""
2714
 
 
2715
 
    def __init__(self, parent, metadata):
2716
 
        self._processors = processors = []
2717
 
 
2718
 
        # We do not strictly need to store the processor in the key mapping,
2719
 
        # though it is faster in the Python version (probably because of the
2720
 
        # saved attribute lookup self._processors)
2721
 
        self._keymap = keymap = {}
2722
 
        self.keys = []
2723
 
        context = parent.context
2724
 
        dialect = context.dialect
2725
 
        typemap = dialect.dbapi_type_map
2726
 
        translate_colname = context._translate_colname
2727
 
 
2728
 
        # high precedence key values.
2729
 
        primary_keymap = {}
2730
 
 
2731
 
        for i, rec in enumerate(metadata):
2732
 
            colname = rec[0]
2733
 
            coltype = rec[1]
2734
 
 
2735
 
            if dialect.description_encoding:
2736
 
                colname = dialect._description_decoder(colname)
2737
 
 
2738
 
            if translate_colname:
2739
 
                colname, untranslated = translate_colname(colname)
2740
 
 
2741
 
            if context.result_map:
2742
 
                try:
2743
 
                    name, obj, type_ = context.result_map[colname.lower()]
2744
 
                except KeyError:
2745
 
                    name, obj, type_ = \
2746
 
                        colname, None, typemap.get(coltype, types.NULLTYPE)
2747
 
            else:
2748
 
                name, obj, type_ = \
2749
 
                        colname, None, typemap.get(coltype, types.NULLTYPE)
2750
 
 
2751
 
            processor = type_._cached_result_processor(dialect, coltype)
2752
 
 
2753
 
            processors.append(processor)
2754
 
            rec = (processor, obj, i)
2755
 
 
2756
 
            # indexes as keys. This is only needed for the Python version of
2757
 
            # RowProxy (the C version uses a faster path for integer indexes).
2758
 
            primary_keymap[i] = rec
2759
 
 
2760
 
            # populate primary keymap, looking for conflicts.
2761
 
            if primary_keymap.setdefault(name.lower(), rec) is not rec:
2762
 
                # place a record that doesn't have the "index" - this
2763
 
                # is interpreted later as an AmbiguousColumnError,
2764
 
                # but only when actually accessed.   Columns
2765
 
                # colliding by name is not a problem if those names
2766
 
                # aren't used; integer and ColumnElement access is always
2767
 
                # unambiguous.
2768
 
                primary_keymap[name.lower()] = (processor, obj, None)
2769
 
 
2770
 
            if dialect.requires_name_normalize:
2771
 
                colname = dialect.normalize_name(colname)
2772
 
 
2773
 
            self.keys.append(colname)
2774
 
            if obj:
2775
 
                for o in obj:
2776
 
                    keymap[o] = rec
2777
 
 
2778
 
            if translate_colname and \
2779
 
                untranslated:
2780
 
                keymap[untranslated] = rec
2781
 
 
2782
 
        # overwrite keymap values with those of the
2783
 
        # high precedence keymap.
2784
 
        keymap.update(primary_keymap)
2785
 
 
2786
 
        if parent._echo:
2787
 
            context.engine.logger.debug(
2788
 
                "Col %r", tuple(x[0] for x in metadata))
2789
 
 
2790
 
    @util.pending_deprecation("0.8", "sqlite dialect uses "
2791
 
                    "_translate_colname() now")
2792
 
    def _set_keymap_synonym(self, name, origname):
2793
 
        """Set a synonym for the given name.
2794
 
 
2795
 
        Some dialects (SQLite at the moment) may use this to
2796
 
        adjust the column names that are significant within a
2797
 
        row.
2798
 
 
2799
 
        """
2800
 
        rec = (processor, obj, i) = self._keymap[origname.lower()]
2801
 
        if self._keymap.setdefault(name, rec) is not rec:
2802
 
            self._keymap[name] = (processor, obj, None)
2803
 
 
2804
 
    def _key_fallback(self, key, raiseerr=True):
2805
 
        map = self._keymap
2806
 
        result = None
2807
 
        if isinstance(key, basestring):
2808
 
            result = map.get(key.lower())
2809
 
        # fallback for targeting a ColumnElement to a textual expression
2810
 
        # this is a rare use case which only occurs when matching text()
2811
 
        # or colummn('name') constructs to ColumnElements, or after a
2812
 
        # pickle/unpickle roundtrip
2813
 
        elif isinstance(key, expression.ColumnElement):
2814
 
            if key._label and key._label.lower() in map:
2815
 
                result = map[key._label.lower()]
2816
 
            elif hasattr(key, 'name') and key.name.lower() in map:
2817
 
                # match is only on name.
2818
 
                result = map[key.name.lower()]
2819
 
            # search extra hard to make sure this
2820
 
            # isn't a column/label name overlap.
2821
 
            # this check isn't currently available if the row
2822
 
            # was unpickled.
2823
 
            if result is not None and \
2824
 
                result[1] is not None:
2825
 
                for obj in result[1]:
2826
 
                    if key._compare_name_for_result(obj):
2827
 
                        break
2828
 
                else:
2829
 
                    result = None
2830
 
        if result is None:
2831
 
            if raiseerr:
2832
 
                raise exc.NoSuchColumnError(
2833
 
                    "Could not locate column in row for column '%s'" %
2834
 
                        expression._string_or_unprintable(key))
2835
 
            else:
2836
 
                return None
2837
 
        else:
2838
 
            map[key] = result
2839
 
        return result
2840
 
 
2841
 
    def _has_key(self, row, key):
2842
 
        if key in self._keymap:
2843
 
            return True
2844
 
        else:
2845
 
            return self._key_fallback(key, False) is not None
2846
 
 
2847
 
    def __getstate__(self):
2848
 
        return {
2849
 
            '_pickled_keymap': dict(
2850
 
                (key, index)
2851
 
                for key, (processor, obj, index) in self._keymap.iteritems()
2852
 
                if isinstance(key, (basestring, int))
2853
 
            ),
2854
 
            'keys': self.keys
2855
 
        }
2856
 
 
2857
 
    def __setstate__(self, state):
2858
 
        # the row has been processed at pickling time so we don't need any
2859
 
        # processor anymore
2860
 
        self._processors = [None for _ in xrange(len(state['keys']))]
2861
 
        self._keymap = keymap = {}
2862
 
        for key, index in state['_pickled_keymap'].iteritems():
2863
 
            # not preserving "obj" here, unfortunately our
2864
 
            # proxy comparison fails with the unpickle
2865
 
            keymap[key] = (None, None, index)
2866
 
        self.keys = state['keys']
2867
 
        self._echo = False
2868
 
 
2869
 
 
2870
 
class ResultProxy(object):
2871
 
    """Wraps a DB-API cursor object to provide easier access to row columns.
2872
 
 
2873
 
    Individual columns may be accessed by their integer position,
2874
 
    case-insensitive column name, or by ``schema.Column``
2875
 
    object. e.g.::
2876
 
 
2877
 
      row = fetchone()
2878
 
 
2879
 
      col1 = row[0]    # access via integer position
2880
 
 
2881
 
      col2 = row['col2']   # access via name
2882
 
 
2883
 
      col3 = row[mytable.c.mycol] # access via Column object.
2884
 
 
2885
 
    ``ResultProxy`` also handles post-processing of result column
2886
 
    data using ``TypeEngine`` objects, which are referenced from
2887
 
    the originating SQL statement that produced this result set.
2888
 
 
2889
 
    """
2890
 
 
2891
 
    _process_row = RowProxy
2892
 
    out_parameters = None
2893
 
    _can_close_connection = False
2894
 
 
2895
 
    def __init__(self, context):
2896
 
        self.context = context
2897
 
        self.dialect = context.dialect
2898
 
        self.closed = False
2899
 
        self.cursor = self._saved_cursor = context.cursor
2900
 
        self.connection = context.root_connection
2901
 
        self._echo = self.connection._echo and \
2902
 
                        context.engine._should_log_debug()
2903
 
        self._init_metadata()
2904
 
 
2905
 
    def _init_metadata(self):
2906
 
        metadata = self._cursor_description()
2907
 
        if metadata is None:
2908
 
            self._metadata = None
2909
 
        else:
2910
 
            self._metadata = ResultMetaData(self, metadata)
2911
 
 
2912
 
    def keys(self):
2913
 
        """Return the current set of string keys for rows."""
2914
 
        if self._metadata:
2915
 
            return self._metadata.keys
2916
 
        else:
2917
 
            return []
2918
 
 
2919
 
    @util.memoized_property
2920
 
    def rowcount(self):
2921
 
        """Return the 'rowcount' for this result.
2922
 
 
2923
 
        The 'rowcount' reports the number of rows *matched*
2924
 
        by the WHERE criterion of an UPDATE or DELETE statement.
2925
 
 
2926
 
        .. note::
2927
 
 
2928
 
           Notes regarding :attr:`.ResultProxy.rowcount`:
2929
 
 
2930
 
 
2931
 
           * This attribute returns the number of rows *matched*,
2932
 
             which is not necessarily the same as the number of rows
2933
 
             that were actually *modified* - an UPDATE statement, for example,
2934
 
             may have no net change on a given row if the SET values
2935
 
             given are the same as those present in the row already.
2936
 
             Such a row would be matched but not modified.
2937
 
             On backends that feature both styles, such as MySQL,
2938
 
             rowcount is configured by default to return the match
2939
 
             count in all cases.
2940
 
 
2941
 
           * :attr:`.ResultProxy.rowcount` is *only* useful in conjunction
2942
 
             with an UPDATE or DELETE statement.  Contrary to what the Python
2943
 
             DBAPI says, it does *not* return the
2944
 
             number of rows available from the results of a SELECT statement
2945
 
             as DBAPIs cannot support this functionality when rows are
2946
 
             unbuffered.
2947
 
 
2948
 
           * :attr:`.ResultProxy.rowcount` may not be fully implemented by
2949
 
             all dialects.  In particular, most DBAPIs do not support an
2950
 
             aggregate rowcount result from an executemany call.
2951
 
             The :meth:`.ResultProxy.supports_sane_rowcount` and
2952
 
             :meth:`.ResultProxy.supports_sane_multi_rowcount` methods
2953
 
             will report from the dialect if each usage is known to be
2954
 
             supported.
2955
 
 
2956
 
           * Statements that use RETURNING may not return a correct
2957
 
             rowcount.
2958
 
 
2959
 
        """
2960
 
        try:
2961
 
            return self.context.rowcount
2962
 
        except Exception, e:
2963
 
            self.connection._handle_dbapi_exception(
2964
 
                              e, None, None, self.cursor, self.context)
2965
 
            raise
2966
 
 
2967
 
    @property
2968
 
    def lastrowid(self):
2969
 
        """return the 'lastrowid' accessor on the DBAPI cursor.
2970
 
 
2971
 
        This is a DBAPI specific method and is only functional
2972
 
        for those backends which support it, for statements
2973
 
        where it is appropriate.  It's behavior is not
2974
 
        consistent across backends.
2975
 
 
2976
 
        Usage of this method is normally unnecessary; the
2977
 
        :attr:`~ResultProxy.inserted_primary_key` attribute provides a
2978
 
        tuple of primary key values for a newly inserted row,
2979
 
        regardless of database backend.
2980
 
 
2981
 
        """
2982
 
        try:
2983
 
            return self._saved_cursor.lastrowid
2984
 
        except Exception, e:
2985
 
            self.connection._handle_dbapi_exception(
2986
 
                                 e, None, None,
2987
 
                                 self._saved_cursor, self.context)
2988
 
            raise
2989
 
 
2990
 
    @property
2991
 
    def returns_rows(self):
2992
 
        """True if this :class:`.ResultProxy` returns rows.
2993
 
 
2994
 
        I.e. if it is legal to call the methods
2995
 
        :meth:`~.ResultProxy.fetchone`,
2996
 
        :meth:`~.ResultProxy.fetchmany`
2997
 
        :meth:`~.ResultProxy.fetchall`.
2998
 
 
2999
 
        """
3000
 
        return self._metadata is not None
3001
 
 
3002
 
    @property
3003
 
    def is_insert(self):
3004
 
        """True if this :class:`.ResultProxy` is the result
3005
 
        of a executing an expression language compiled
3006
 
        :func:`.expression.insert` construct.
3007
 
 
3008
 
        When True, this implies that the
3009
 
        :attr:`inserted_primary_key` attribute is accessible,
3010
 
        assuming the statement did not include
3011
 
        a user defined "returning" construct.
3012
 
 
3013
 
        """
3014
 
        return self.context.isinsert
3015
 
 
3016
 
    def _cursor_description(self):
3017
 
        """May be overridden by subclasses."""
3018
 
 
3019
 
        return self._saved_cursor.description
3020
 
 
3021
 
    def close(self, _autoclose_connection=True):
3022
 
        """Close this ResultProxy.
3023
 
 
3024
 
        Closes the underlying DBAPI cursor corresponding to the execution.
3025
 
 
3026
 
        Note that any data cached within this ResultProxy is still available.
3027
 
        For some types of results, this may include buffered rows.
3028
 
 
3029
 
        If this ResultProxy was generated from an implicit execution,
3030
 
        the underlying Connection will also be closed (returns the
3031
 
        underlying DBAPI connection to the connection pool.)
3032
 
 
3033
 
        This method is called automatically when:
3034
 
 
3035
 
        * all result rows are exhausted using the fetchXXX() methods.
3036
 
        * cursor.description is None.
3037
 
 
3038
 
        """
3039
 
 
3040
 
        if not self.closed:
3041
 
            self.closed = True
3042
 
            self.connection._safe_close_cursor(self.cursor)
3043
 
            if _autoclose_connection and \
3044
 
                self.connection.should_close_with_result:
3045
 
                self.connection.close()
3046
 
            # allow consistent errors
3047
 
            self.cursor = None
3048
 
 
3049
 
    def __iter__(self):
3050
 
        while True:
3051
 
            row = self.fetchone()
3052
 
            if row is None:
3053
 
                raise StopIteration
3054
 
            else:
3055
 
                yield row
3056
 
 
3057
 
    @util.memoized_property
3058
 
    def inserted_primary_key(self):
3059
 
        """Return the primary key for the row just inserted.
3060
 
 
3061
 
        The return value is a list of scalar values
3062
 
        corresponding to the list of primary key columns
3063
 
        in the target table.
3064
 
 
3065
 
        This only applies to single row :func:`.insert`
3066
 
        constructs which did not explicitly specify
3067
 
        :meth:`.Insert.returning`.
3068
 
 
3069
 
        Note that primary key columns which specify a
3070
 
        server_default clause,
3071
 
        or otherwise do not qualify as "autoincrement"
3072
 
        columns (see the notes at :class:`.Column`), and were
3073
 
        generated using the database-side default, will
3074
 
        appear in this list as ``None`` unless the backend
3075
 
        supports "returning" and the insert statement executed
3076
 
        with the "implicit returning" enabled.
3077
 
 
3078
 
        """
3079
 
 
3080
 
        if not self.context.isinsert:
3081
 
            raise exc.InvalidRequestError(
3082
 
                        "Statement is not an insert() expression construct.")
3083
 
        elif self.context._is_explicit_returning:
3084
 
            raise exc.InvalidRequestError(
3085
 
                        "Can't call inserted_primary_key when returning() "
3086
 
                        "is used.")
3087
 
 
3088
 
        return self.context.inserted_primary_key
3089
 
 
3090
 
    @util.deprecated("0.6", "Use :attr:`.ResultProxy.inserted_primary_key`")
3091
 
    def last_inserted_ids(self):
3092
 
        """Return the primary key for the row just inserted."""
3093
 
 
3094
 
        return self.inserted_primary_key
3095
 
 
3096
 
    def last_updated_params(self):
3097
 
        """Return the collection of updated parameters from this
3098
 
        execution.
3099
 
 
3100
 
        """
3101
 
        if self.context.executemany:
3102
 
            return self.context.compiled_parameters
3103
 
        else:
3104
 
            return self.context.compiled_parameters[0]
3105
 
 
3106
 
    def last_inserted_params(self):
3107
 
        """Return the collection of inserted parameters from this
3108
 
        execution.
3109
 
 
3110
 
        """
3111
 
        if self.context.executemany:
3112
 
            return self.context.compiled_parameters
3113
 
        else:
3114
 
            return self.context.compiled_parameters[0]
3115
 
 
3116
 
    def lastrow_has_defaults(self):
3117
 
        """Return ``lastrow_has_defaults()`` from the underlying
3118
 
        ExecutionContext.
3119
 
 
3120
 
        See ExecutionContext for details.
3121
 
        """
3122
 
 
3123
 
        return self.context.lastrow_has_defaults()
3124
 
 
3125
 
    def postfetch_cols(self):
3126
 
        """Return ``postfetch_cols()`` from the underlying ExecutionContext.
3127
 
 
3128
 
        See ExecutionContext for details.
3129
 
        """
3130
 
 
3131
 
        return self.context.postfetch_cols
3132
 
 
3133
 
    def prefetch_cols(self):
3134
 
        return self.context.prefetch_cols
3135
 
 
3136
 
    def supports_sane_rowcount(self):
3137
 
        """Return ``supports_sane_rowcount`` from the dialect.
3138
 
 
3139
 
        See :attr:`.ResultProxy.rowcount` for background.
3140
 
 
3141
 
        """
3142
 
 
3143
 
        return self.dialect.supports_sane_rowcount
3144
 
 
3145
 
    def supports_sane_multi_rowcount(self):
3146
 
        """Return ``supports_sane_multi_rowcount`` from the dialect.
3147
 
 
3148
 
        See :attr:`.ResultProxy.rowcount` for background.
3149
 
 
3150
 
        """
3151
 
 
3152
 
        return self.dialect.supports_sane_multi_rowcount
3153
 
 
3154
 
    def _fetchone_impl(self):
3155
 
        try:
3156
 
            return self.cursor.fetchone()
3157
 
        except AttributeError:
3158
 
            self._non_result()
3159
 
 
3160
 
    def _fetchmany_impl(self, size=None):
3161
 
        try:
3162
 
            if size is None:
3163
 
                return self.cursor.fetchmany()
3164
 
            else:
3165
 
                return self.cursor.fetchmany(size)
3166
 
        except AttributeError:
3167
 
            self._non_result()
3168
 
 
3169
 
    def _fetchall_impl(self):
3170
 
        try:
3171
 
            return self.cursor.fetchall()
3172
 
        except AttributeError:
3173
 
            self._non_result()
3174
 
 
3175
 
    def _non_result(self):
3176
 
        if self._metadata is None:
3177
 
            raise exc.ResourceClosedError(
3178
 
            "This result object does not return rows. "
3179
 
            "It has been closed automatically.",
3180
 
            )
3181
 
        else:
3182
 
            raise exc.ResourceClosedError("This result object is closed.")
3183
 
 
3184
 
    def process_rows(self, rows):
3185
 
        process_row = self._process_row
3186
 
        metadata = self._metadata
3187
 
        keymap = metadata._keymap
3188
 
        processors = metadata._processors
3189
 
        if self._echo:
3190
 
            log = self.context.engine.logger.debug
3191
 
            l = []
3192
 
            for row in rows:
3193
 
                log("Row %r", row)
3194
 
                l.append(process_row(metadata, row, processors, keymap))
3195
 
            return l
3196
 
        else:
3197
 
            return [process_row(metadata, row, processors, keymap)
3198
 
                    for row in rows]
3199
 
 
3200
 
    def fetchall(self):
3201
 
        """Fetch all rows, just like DB-API ``cursor.fetchall()``."""
3202
 
 
3203
 
        try:
3204
 
            l = self.process_rows(self._fetchall_impl())
3205
 
            self.close()
3206
 
            return l
3207
 
        except Exception, e:
3208
 
            self.connection._handle_dbapi_exception(
3209
 
                                    e, None, None,
3210
 
                                    self.cursor, self.context)
3211
 
            raise
3212
 
 
3213
 
    def fetchmany(self, size=None):
3214
 
        """Fetch many rows, just like DB-API
3215
 
        ``cursor.fetchmany(size=cursor.arraysize)``.
3216
 
 
3217
 
        If rows are present, the cursor remains open after this is called.
3218
 
        Else the cursor is automatically closed and an empty list is returned.
3219
 
 
3220
 
        """
3221
 
 
3222
 
        try:
3223
 
            l = self.process_rows(self._fetchmany_impl(size))
3224
 
            if len(l) == 0:
3225
 
                self.close()
3226
 
            return l
3227
 
        except Exception, e:
3228
 
            self.connection._handle_dbapi_exception(
3229
 
                                    e, None, None,
3230
 
                                    self.cursor, self.context)
3231
 
            raise
3232
 
 
3233
 
    def fetchone(self):
3234
 
        """Fetch one row, just like DB-API ``cursor.fetchone()``.
3235
 
 
3236
 
        If a row is present, the cursor remains open after this is called.
3237
 
        Else the cursor is automatically closed and None is returned.
3238
 
 
3239
 
        """
3240
 
        try:
3241
 
            row = self._fetchone_impl()
3242
 
            if row is not None:
3243
 
                return self.process_rows([row])[0]
3244
 
            else:
3245
 
                self.close()
3246
 
                return None
3247
 
        except Exception, e:
3248
 
            self.connection._handle_dbapi_exception(
3249
 
                                    e, None, None,
3250
 
                                    self.cursor, self.context)
3251
 
            raise
3252
 
 
3253
 
    def first(self):
3254
 
        """Fetch the first row and then close the result set unconditionally.
3255
 
 
3256
 
        Returns None if no row is present.
3257
 
 
3258
 
        """
3259
 
        if self._metadata is None:
3260
 
            self._non_result()
3261
 
 
3262
 
        try:
3263
 
            row = self._fetchone_impl()
3264
 
        except Exception, e:
3265
 
            self.connection._handle_dbapi_exception(
3266
 
                                    e, None, None,
3267
 
                                    self.cursor, self.context)
3268
 
            raise
3269
 
 
3270
 
        try:
3271
 
            if row is not None:
3272
 
                return self.process_rows([row])[0]
3273
 
            else:
3274
 
                return None
3275
 
        finally:
3276
 
            self.close()
3277
 
 
3278
 
    def scalar(self):
3279
 
        """Fetch the first column of the first row, and close the result set.
3280
 
 
3281
 
        Returns None if no row is present.
3282
 
 
3283
 
        """
3284
 
        row = self.first()
3285
 
        if row is not None:
3286
 
            return row[0]
3287
 
        else:
3288
 
            return None
3289
 
 
3290
 
class BufferedRowResultProxy(ResultProxy):
3291
 
    """A ResultProxy with row buffering behavior.
3292
 
 
3293
 
    ``ResultProxy`` that buffers the contents of a selection of rows
3294
 
    before ``fetchone()`` is called.  This is to allow the results of
3295
 
    ``cursor.description`` to be available immediately, when
3296
 
    interfacing with a DB-API that requires rows to be consumed before
3297
 
    this information is available (currently psycopg2, when used with
3298
 
    server-side cursors).
3299
 
 
3300
 
    The pre-fetching behavior fetches only one row initially, and then
3301
 
    grows its buffer size by a fixed amount with each successive need
3302
 
    for additional rows up to a size of 100.
3303
 
    """
3304
 
 
3305
 
    def _init_metadata(self):
3306
 
        self.__buffer_rows()
3307
 
        super(BufferedRowResultProxy, self)._init_metadata()
3308
 
 
3309
 
    # this is a "growth chart" for the buffering of rows.
3310
 
    # each successive __buffer_rows call will use the next
3311
 
    # value in the list for the buffer size until the max
3312
 
    # is reached
3313
 
    size_growth = {
3314
 
        1 : 5,
3315
 
        5 : 10,
3316
 
        10 : 20,
3317
 
        20 : 50,
3318
 
        50 : 100,
3319
 
        100 : 250,
3320
 
        250 : 500,
3321
 
        500 : 1000
3322
 
    }
3323
 
 
3324
 
    def __buffer_rows(self):
3325
 
        size = getattr(self, '_bufsize', 1)
3326
 
        self.__rowbuffer = collections.deque(self.cursor.fetchmany(size))
3327
 
        self._bufsize = self.size_growth.get(size, size)
3328
 
 
3329
 
    def _fetchone_impl(self):
3330
 
        if self.closed:
3331
 
            return None
3332
 
        if not self.__rowbuffer:
3333
 
            self.__buffer_rows()
3334
 
            if not self.__rowbuffer:
3335
 
                return None
3336
 
        return self.__rowbuffer.popleft()
3337
 
 
3338
 
    def _fetchmany_impl(self, size=None):
3339
 
        if size is None:
3340
 
            return self._fetchall_impl()
3341
 
        result = []
3342
 
        for x in range(0, size):
3343
 
            row = self._fetchone_impl()
3344
 
            if row is None:
3345
 
                break
3346
 
            result.append(row)
3347
 
        return result
3348
 
 
3349
 
    def _fetchall_impl(self):
3350
 
        self.__rowbuffer.extend(self.cursor.fetchall())
3351
 
        ret = self.__rowbuffer
3352
 
        self.__rowbuffer = collections.deque()
3353
 
        return ret
3354
 
 
3355
 
class FullyBufferedResultProxy(ResultProxy):
3356
 
    """A result proxy that buffers rows fully upon creation.
3357
 
 
3358
 
    Used for operations where a result is to be delivered
3359
 
    after the database conversation can not be continued,
3360
 
    such as MSSQL INSERT...OUTPUT after an autocommit.
3361
 
 
3362
 
    """
3363
 
    def _init_metadata(self):
3364
 
        super(FullyBufferedResultProxy, self)._init_metadata()
3365
 
        self.__rowbuffer = self._buffer_rows()
3366
 
 
3367
 
    def _buffer_rows(self):
3368
 
        return collections.deque(self.cursor.fetchall())
3369
 
 
3370
 
    def _fetchone_impl(self):
3371
 
        if self.__rowbuffer:
3372
 
            return self.__rowbuffer.popleft()
3373
 
        else:
3374
 
            return None
3375
 
 
3376
 
    def _fetchmany_impl(self, size=None):
3377
 
        if size is None:
3378
 
            return self._fetchall_impl()
3379
 
        result = []
3380
 
        for x in range(0, size):
3381
 
            row = self._fetchone_impl()
3382
 
            if row is None:
3383
 
                break
3384
 
            result.append(row)
3385
 
        return result
3386
 
 
3387
 
    def _fetchall_impl(self):
3388
 
        ret = self.__rowbuffer
3389
 
        self.__rowbuffer = collections.deque()
3390
 
        return ret
3391
 
 
3392
 
class BufferedColumnRow(RowProxy):
3393
 
    def __init__(self, parent, row, processors, keymap):
3394
 
        # preprocess row
3395
 
        row = list(row)
3396
 
        # this is a tad faster than using enumerate
3397
 
        index = 0
3398
 
        for processor in parent._orig_processors:
3399
 
            if processor is not None:
3400
 
                row[index] = processor(row[index])
3401
 
            index += 1
3402
 
        row = tuple(row)
3403
 
        super(BufferedColumnRow, self).__init__(parent, row,
3404
 
                                                processors, keymap)
3405
 
 
3406
 
class BufferedColumnResultProxy(ResultProxy):
3407
 
    """A ResultProxy with column buffering behavior.
3408
 
 
3409
 
    ``ResultProxy`` that loads all columns into memory each time
3410
 
    fetchone() is called.  If fetchmany() or fetchall() are called,
3411
 
    the full grid of results is fetched.  This is to operate with
3412
 
    databases where result rows contain "live" results that fall out
3413
 
    of scope unless explicitly fetched.  Currently this includes
3414
 
    cx_Oracle LOB objects.
3415
 
 
3416
 
    """
3417
 
 
3418
 
    _process_row = BufferedColumnRow
3419
 
 
3420
 
    def _init_metadata(self):
3421
 
        super(BufferedColumnResultProxy, self)._init_metadata()
3422
 
        metadata = self._metadata
3423
 
        # orig_processors will be used to preprocess each row when they are
3424
 
        # constructed.
3425
 
        metadata._orig_processors = metadata._processors
3426
 
        # replace the all type processors by None processors.
3427
 
        metadata._processors = [None for _ in xrange(len(metadata.keys))]
3428
 
        keymap = {}
3429
 
        for k, (func, obj, index) in metadata._keymap.iteritems():
3430
 
            keymap[k] = (None, obj, index)
3431
 
        self._metadata._keymap = keymap
3432
 
 
3433
 
    def fetchall(self):
3434
 
        # can't call cursor.fetchall(), since rows must be
3435
 
        # fully processed before requesting more from the DBAPI.
3436
 
        l = []
3437
 
        while True:
3438
 
            row = self.fetchone()
3439
 
            if row is None:
3440
 
                break
3441
 
            l.append(row)
3442
 
        return l
3443
 
 
3444
 
    def fetchmany(self, size=None):
3445
 
        # can't call cursor.fetchmany(), since rows must be
3446
 
        # fully processed before requesting more from the DBAPI.
3447
 
        if size is None:
3448
 
            return self.fetchall()
3449
 
        l = []
3450
 
        for i in xrange(size):
3451
 
            row = self.fetchone()
3452
 
            if row is None:
3453
 
                break
3454
 
            l.append(row)
3455
 
        return l
3456
 
 
3457
 
def connection_memoize(key):
3458
 
    """Decorator, memoize a function in a connection.info stash.
3459
 
 
3460
 
    Only applicable to functions which take no arguments other than a
3461
 
    connection.  The memo will be stored in ``connection.info[key]``.
3462
 
    """
3463
 
 
3464
 
    @util.decorator
3465
 
    def decorated(fn, self, connection):
3466
 
        connection = connection.connect()
3467
 
        try:
3468
 
            return connection.info[key]
3469
 
        except KeyError:
3470
 
            connection.info[key] = val = fn(self, connection)
3471
 
            return val
3472
 
 
3473
 
    return decorated
 
1702
class OptionEngine(Engine):
 
1703
    def __init__(self, proxied, execution_options):
 
1704
        self._proxied = proxied
 
1705
        self.url = proxied.url
 
1706
        self.dialect = proxied.dialect
 
1707
        self.logging_name = proxied.logging_name
 
1708
        self.echo = proxied.echo
 
1709
        log.instance_logger(self, echoflag=self.echo)
 
1710
        self.dispatch = self.dispatch._join(proxied.dispatch)
 
1711
        self._execution_options = proxied._execution_options
 
1712
        self.update_execution_options(**execution_options)
 
1713
 
 
1714
    def _get_pool(self):
 
1715
        return self._proxied.pool
 
1716
 
 
1717
    def _set_pool(self, pool):
 
1718
        self._proxied.pool = pool
 
1719
 
 
1720
    pool = property(_get_pool, _set_pool)
 
1721
 
 
1722
    def _get_has_events(self):
 
1723
        return self._proxied._has_events or \
 
1724
            self.__dict__.get('_has_events', False)
 
1725
 
 
1726
    def _set_has_events(self, value):
 
1727
        self.__dict__['_has_events'] = value
 
1728
 
 
1729
    _has_events = property(_get_has_events, _set_has_events)