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

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

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

行番号 
1# schema.py
2# Copyright (C) 2005, 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
3#
4# This module is part of SQLAlchemy and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7"""The schema module provides the building blocks for database metadata.
8
9Each element within this module describes a database entity which can be
10created and dropped, or is otherwise part of such an entity.  Examples include
11tables, columns, sequences, and indexes.
12
13All entities are subclasses of :class:`~sqlalchemy.schema.SchemaItem`, and as defined
14in this module they are intended to be agnostic of any vendor-specific
15constructs.
16
17A collection of entities are grouped into a unit called
18:class:`~sqlalchemy.schema.MetaData`.  MetaData serves as a logical grouping of schema
19elements, and can also be associated with an actual database connection such
20that operations involving the contained elements can contact the database as
21needed.
22
23Two of the elements here also build upon their "syntactic" counterparts, which
24are defined in :class:`~sqlalchemy.sql.expression.`, specifically
25:class:`~sqlalchemy.schema.Table` and :class:`~sqlalchemy.schema.Column`.  Since these objects
26are part of the SQL expression language, they are usable as components in SQL
27expressions.
28
29"""
30import re, inspect
31from sqlalchemy import types, exc, util, databases
32from sqlalchemy.sql import expression, visitors
33
34URL = None
35
36__all__ = ['SchemaItem', 'Table', 'Column', 'ForeignKey', 'Sequence', 'Index',
37           'ForeignKeyConstraint', 'PrimaryKeyConstraint', 'CheckConstraint',
38           'UniqueConstraint', 'DefaultGenerator', 'Constraint', 'MetaData',
39           'ThreadLocalMetaData', 'SchemaVisitor', 'PassiveDefault',
40           'DefaultClause', 'FetchedValue', 'ColumnDefault', 'DDL']
41__all__.sort()
42
43class SchemaItem(visitors.Visitable):
44    """Base class for items that define a database schema."""
45
46    __visit_name__ = 'schema_item'
47    quote = None
48
49    def _init_items(self, *args):
50        """Initialize the list of child items for this SchemaItem."""
51
52        for item in args:
53            if item is not None:
54                item._set_parent(self)
55
56    def _set_parent(self, parent):
57        """Associate with this SchemaItem's parent object."""
58
59        raise NotImplementedError()
60
61    def get_children(self, **kwargs):
62        """used to allow SchemaVisitor access"""
63        return []
64
65    def __repr__(self):
66        return "%s()" % self.__class__.__name__
67
68    @property
69    def bind(self):
70        """Return the connectable associated with this SchemaItem."""
71
72        m = self.metadata
73        return m and m.bind or None
74
75    @util.memoized_property
76    def info(self):
77        return {}
78
79def _get_table_key(name, schema):
80    if schema is None:
81        return name
82    else:
83        return schema + "." + name
84
85class _TableSingleton(visitors.VisitableType):
86    """A metaclass used by the ``Table`` object to provide singleton behavior."""
87
88    def __call__(self, name, metadata, *args, **kwargs):
89        schema = kwargs.get('schema', kwargs.get('owner', None))
90        useexisting = kwargs.pop('useexisting', False)
91        mustexist = kwargs.pop('mustexist', False)
92        key = _get_table_key(name, schema)
93        try:
94            table = metadata.tables[key]
95            if not useexisting and table._cant_override(*args, **kwargs):
96                raise exc.InvalidRequestError(
97                    "Table '%s' is already defined for this MetaData instance.  "
98                    "Specify 'useexisting=True' to redefine options and "
99                    "columns on an existing Table object." % key)
100            else:
101                table._init_existing(*args, **kwargs)
102            return table
103        except KeyError:
104            if mustexist:
105                raise exc.InvalidRequestError(
106                    "Table '%s' not defined" % (key))
107            try:
108                return type.__call__(self, name, metadata, *args, **kwargs)
109            except:
110                if key in metadata.tables:
111                    del metadata.tables[key]
112                raise
113
114
115class Table(SchemaItem, expression.TableClause):
116    """Represent a table in a database."""
117
118    __metaclass__ = _TableSingleton
119
120    __visit_name__ = 'table'
121
122    ddl_events = ('before-create', 'after-create', 'before-drop', 'after-drop')
123
124    def __init__(self, name, metadata, *args, **kwargs):
125        """
126        Construct a Table.
127
128        :param name: The name of this table as represented in the database.
129
130            This property, along with the *schema*, indicates the *singleton
131            identity* of this table in relation to its parent :class:`MetaData`.
132            Additional calls to :class:`Table` with the same name, metadata,
133            and schema name will return the same :class:`Table` object.
134
135            Names which contain no upper case characters
136            will be treated as case insensitive names, and will not be quoted
137            unless they are a reserved word.  Names with any number of upper
138            case characters will be quoted and sent exactly.  Note that this
139            behavior applies even for databases which standardize upper
140            case names as case insensitive such as Oracle.
141
142        :param metadata: a :class:`MetaData` object which will contain this
143            table.  The metadata is used as a point of association of this table
144            with other tables which are referenced via foreign key.  It also
145            may be used to associate this table with a particular
146            :class:`~sqlalchemy.engine.base.Connectable`.
147
148        :param \*args: Additional positional arguments are used primarily
149            to add the list of :class:`Column` objects contained within this table.
150            Similar to the style of a CREATE TABLE statement, other :class:`SchemaItem`
151            constructs may be added here, including :class:`PrimaryKeyConstraint`,
152            and :class:`ForeignKeyConstraint`.
153           
154        :param autoload: Defaults to False: the Columns for this table should be reflected
155            from the database.  Usually there will be no Column objects in the
156            constructor if this property is set.
157
158        :param autoload_with: If autoload==True, this is an optional Engine or Connection
159            instance to be used for the table reflection.  If ``None``, the
160            underlying MetaData's bound connectable will be used.
161
162        :param include_columns: A list of strings indicating a subset of columns to be loaded via
163            the ``autoload`` operation; table columns who aren't present in
164            this list will not be represented on the resulting ``Table``
165            object.  Defaults to ``None`` which indicates all columns should
166            be reflected.
167
168        :param info: A dictionary which defaults to ``{}``.  A space to store application
169            specific data. This must be a dictionary.
170
171        :param mustexist: When ``True``, indicates that this Table must already
172            be present in the given :class:`MetaData`` collection.
173
174        :param prefixes:
175            A list of strings to insert after CREATE in the CREATE TABLE
176            statement.  They will be separated by spaces.
177
178        :param quote: Force quoting of this table's name on or off, corresponding
179            to ``True`` or ``False``.  When left at its default of ``None``,
180            the column identifier will be quoted according to whether the name is
181            case sensitive (identifiers with at least one upper case character are
182            treated as case sensitive), or if it's a reserved word.  This flag
183            is only needed to force quoting of a reserved word which is not known
184            by the SQLAlchemy dialect.
185
186        :param quote_schema: same as 'quote' but applies to the schema identifier.
187
188        :param schema: The *schema name* for this table, which is required if the table
189            resides in a schema other than the default selected schema for the
190            engine's database connection.  Defaults to ``None``.
191
192        :param useexisting: When ``True``, indicates that if this Table is already
193            present in the given :class:`MetaData`, apply further arguments within
194            the constructor to the existing :class:`Table`.  If this flag is not
195            set, an error is raised when the parameters of an existing :class:`Table`
196            are overwritten.
197
198        """
199        super(Table, self).__init__(name)
200        self.metadata = metadata
201        self.schema = kwargs.pop('schema', kwargs.pop('owner', None))
202        self.indexes = set()
203        self.constraints = set()
204        self._columns = expression.ColumnCollection()
205        self.primary_key = PrimaryKeyConstraint()
206        self._foreign_keys = util.OrderedSet()
207        self.ddl_listeners = util.defaultdict(list)
208        self.kwargs = {}
209        if self.schema is not None:
210            self.fullname = "%s.%s" % (self.schema, self.name)
211        else:
212            self.fullname = self.name
213
214        autoload = kwargs.pop('autoload', False)
215        autoload_with = kwargs.pop('autoload_with', None)
216        include_columns = kwargs.pop('include_columns', None)
217
218        self._set_parent(metadata)
219
220        self.quote = kwargs.pop('quote', None)
221        self.quote_schema = kwargs.pop('quote_schema', None)
222        if 'info' in kwargs:
223            self.info = kwargs.pop('info')
224
225        self._prefixes = kwargs.pop('prefixes', [])
226
227        self.__extra_kwargs(**kwargs)
228
229        # load column definitions from the database if 'autoload' is defined
230        # we do it after the table is in the singleton dictionary to support
231        # circular foreign keys
232        if autoload:
233            if autoload_with:
234                autoload_with.reflecttable(self, include_columns=include_columns)
235            else:
236                _bind_or_error(metadata).reflecttable(self, include_columns=include_columns)
237
238        # initialize all the column, etc. objects.  done after reflection to
239        # allow user-overrides
240        self.__post_init(*args, **kwargs)
241
242    def _init_existing(self, *args, **kwargs):
243        autoload = kwargs.pop('autoload', False)
244        autoload_with = kwargs.pop('autoload_with', None)
245        schema = kwargs.pop('schema', None)
246        if schema and schema != self.schema:
247            raise exc.ArgumentError(
248                "Can't change schema of existing table from '%s' to '%s'",
249                (self.schema, schema))
250
251        include_columns = kwargs.pop('include_columns', None)
252        if include_columns:
253            for c in self.c:
254                if c.name not in include_columns:
255                    self.c.remove(c)
256
257        for key in ('quote', 'quote_schema'):
258            if key in kwargs:
259                setattr(self, key, kwargs.pop(key))
260
261        if 'info' in kwargs:
262            self.info = kwargs.pop('info')
263
264        self.__extra_kwargs(**kwargs)
265        self.__post_init(*args, **kwargs)
266
267    def _cant_override(self, *args, **kwargs):
268        """Return True if any argument is not supported as an override.
269
270        Takes arguments that would be sent to Table.__init__, and returns
271        True if any of them would be disallowed if sent to an existing
272        Table singleton.
273        """
274        return bool(args) or bool(set(kwargs).difference(
275            ['autoload', 'autoload_with', 'schema', 'owner']))
276
277    def __extra_kwargs(self, **kwargs):
278        # validate remaining kwargs that they all specify DB prefixes
279        if len([k for k in kwargs
280                if not re.match(r'^(?:%s)_' % '|'.join(databases.__all__), k)]):
281            raise TypeError(
282                "Invalid argument(s) for Table: %s" % repr(kwargs.keys()))
283        self.kwargs.update(kwargs)
284
285    def __post_init(self, *args, **kwargs):
286        self._init_items(*args)
287
288    @property
289    def key(self):
290        return _get_table_key(self.name, self.schema)
291
292    def _set_primary_key(self, pk):
293        if getattr(self, '_primary_key', None) in self.constraints:
294            self.constraints.remove(self._primary_key)
295        self._primary_key = pk
296        self.constraints.add(pk)
297
298    def primary_key(self):
299        return self._primary_key
300    primary_key = property(primary_key, _set_primary_key)
301
302    def __repr__(self):
303        return "Table(%s)" % ', '.join(
304            [repr(self.name)] + [repr(self.metadata)] +
305            [repr(x) for x in self.columns] +
306            ["%s=%s" % (k, repr(getattr(self, k))) for k in ['schema']])
307
308    def __str__(self):
309        return _get_table_key(self.description, self.schema)
310
311    def append_column(self, column):
312        """Append a ``Column`` to this ``Table``."""
313
314        column._set_parent(self)
315
316    def append_constraint(self, constraint):
317        """Append a ``Constraint`` to this ``Table``."""
318
319        constraint._set_parent(self)
320
321    def append_ddl_listener(self, event, listener):
322        """Append a DDL event listener to this ``Table``.
323
324        The ``listener`` callable will be triggered when this ``Table`` is
325        created or dropped, either directly before or after the DDL is issued
326        to the database.  The listener may modify the Table, but may not abort
327        the event itself.
328
329        Arguments are:
330
331        event
332          One of ``Table.ddl_events``; e.g. 'before-create', 'after-create',
333          'before-drop' or 'after-drop'.
334
335        listener
336          A callable, invoked with three positional arguments:
337
338          event
339            The event currently being handled
340          schema_item
341            The ``Table`` object being created or dropped
342          bind
343            The ``Connection`` bueing used for DDL execution.
344
345        Listeners are added to the Table's ``ddl_listeners`` attribute.
346        """
347
348        if event not in self.ddl_events:
349            raise LookupError(event)
350        self.ddl_listeners[event].append(listener)
351
352    def _set_parent(self, metadata):
353        metadata.tables[_get_table_key(self.name, self.schema)] = self
354        self.metadata = metadata
355
356    def get_children(self, column_collections=True, schema_visitor=False, **kwargs):
357        if not schema_visitor:
358            return expression.TableClause.get_children(
359                self, column_collections=column_collections, **kwargs)
360        else:
361            if column_collections:
362                return [c for c in self.columns]
363            else:
364                return []
365
366    def exists(self, bind=None):
367        """Return True if this table exists."""
368
369        if bind is None:
370            bind = _bind_or_error(self)
371
372        def do(conn):
373            return conn.dialect.has_table(conn, self.name, schema=self.schema)
374        return bind.run_callable(do)
375
376    def create(self, bind=None, checkfirst=False):
377        """Issue a ``CREATE`` statement for this table.
378
379        See also ``metadata.create_all()``.
380        """
381        self.metadata.create_all(bind=bind, checkfirst=checkfirst, tables=[self])
382
383    def drop(self, bind=None, checkfirst=False):
384        """Issue a ``DROP`` statement for this table.
385
386        See also ``metadata.drop_all()``.
387        """
388        self.metadata.drop_all(bind=bind, checkfirst=checkfirst, tables=[self])
389
390    def tometadata(self, metadata, schema=None):
391        """Return a copy of this ``Table`` associated with a different ``MetaData``."""
392
393        try:
394            if not schema:
395                schema = self.schema
396            key = _get_table_key(self.name, schema)
397            return metadata.tables[key]
398        except KeyError:
399            args = []
400            for c in self.columns:
401                args.append(c.copy(schema=schema))
402            for c in self.constraints:
403                args.append(c.copy(schema=schema))
404            return Table(self.name, metadata, schema=schema, *args)
405
406class Column(SchemaItem, expression.ColumnClause):
407    """Represents a column in a database table."""
408
409    __visit_name__ = 'column'
410
411    def __init__(self, *args, **kwargs):
412        """
413        Construct a new ``Column`` object.
414       
415        :param name: The name of this column as represented in the database.
416          This argument may be the first positional argument, or specified
417          via keyword.
418         
419          Names which contain no upper case characters
420          will be treated as case insensitive names, and will not be quoted
421          unless they are a reserved word.  Names with any number of upper
422          case characters will be quoted and sent exactly.  Note that this
423          behavior applies even for databases which standardize upper
424          case names as case insensitive such as Oracle.
425         
426          The name field may be omitted at construction time and applied
427          later, at any time before the Column is associated with a
428          :class:`Table`.  This is to support convenient
429          usage within the :mod:`~sqlalchemy.ext.declarative` extension.
430         
431        :param type\_: The column's type, indicated using an instance which
432          subclasses :class:`~sqlalchemy.types.AbstractType`.  If no arguments
433          are required for the type, the class of the type can be sent
434          as well, e.g.::
435         
436            # use a type with arguments
437            Column('data', String(50))
438           
439            # use no arguments
440            Column('level', Integer)
441           
442          The ``type`` argument may be the second positional argument
443          or specified by keyword.
444
445          If this column also contains a :class:`ForeignKey`,
446          the type argument may be left as ``None`` in which case the
447          type assigned will be that of the referenced column.
448
449        :param \*args: Additional positional arguments include various
450          :class:`SchemaItem` derived constructs which will be applied
451          as options to the column.  These include instances of
452          :class:`Constraint`, :class:`ForeignKey`, :class:`ColumnDefault`,
453          and :class:`Sequence`.  In some cases an equivalent keyword
454          argument is available such as ``server_default``, ``default``
455          and ``unique``.
456
457        :param autoincrement: This flag may be set to ``False`` to disable
458          SQLAlchemy indicating at the DDL level that an integer primary
459          key column should have autoincrementing behavior.  This
460          is an oft misunderstood flag and has no effect whatsoever unless
461          all of the following conditions are met:
462           
463          * The column is of the :class:`~sqlalchemy.types.Integer` datatype.
464          * The column has the ``primary_key`` flag set, or is otherwise
465            a member of a :class:`PrimaryKeyConstraint` on this table.
466          * a CREATE TABLE statement is being issued via :meth:`create()`
467            or :meth:`create_all()`.  The flag has no relevance at any
468            other time.
469          * The database supports autoincrementing behavior, such as
470            PostgreSQL or MySQL, and this behavior can be disabled (which does
471            not include SQLite).
472
473        :param default: A scalar, Python callable, or :class:`~sqlalchemy.sql.expression.ClauseElement`
474          representing the *default value* for this column, which will be
475          invoked upon insert if this column is otherwise not specified
476          in the VALUES clause of the insert.  This is a shortcut
477          to using :class:`ColumnDefault` as a positional argument.
478         
479          Contrast this argument to ``server_default`` which creates a
480          default generator on the database side.
481
482        :param key: An optional string identifier which will identify this ``Column``
483            object on the :class:`Table`.  When a key is provided, this is the
484            only identifier referencing the ``Column`` within the application,
485            including ORM attribute mapping; the ``name`` field is used only
486            when rendering SQL.
487
488        :param index: When ``True``, indicates that the column is indexed.
489          This is a shortcut for using a :class:`Index` construct on the table.
490          To specify indexes with explicit names or indexes that contain multiple
491          columns, use the :class:`Index` construct instead.
492
493        :param info: A dictionary which defaults to ``{}``.  A space to store application
494          specific data. This must be a dictionary.
495
496        :param nullable: If set to the default of ``True``, indicates the column
497            will be rendered as allowing NULL, else it's rendered as NOT NULL.
498            This parameter is only used when issuing CREATE TABLE statements.
499
500        :param onupdate: A scalar, Python callable, or :class:`~sqlalchemy.sql.expression.ClauseElement`
501            representing a default value to be applied to the column within UPDATE
502            statements, which wil be invoked upon update if this column is not present
503            in the SET clause of the update.  This is a shortcut to using
504            :class:`ColumnDefault` as a positional argument with ``for_update=True``.
505           
506        :param primary_key: If ``True``, marks this column as a primary key
507            column.  Multiple columns can have this flag set to specify composite
508            primary keys.  As an alternative, the primary key of a :class:`Table` can
509            be specified via an explicit :class:`PrimaryKeyConstraint` object.
510
511        :param server_default: A :class:`FetchedValue` instance, str, Unicode or
512          :func:`~sqlalchemy.sql.expression.text` construct representing
513          the DDL DEFAULT value for the column.
514
515          String types will be emitted as-is, surrounded by single quotes::
516
517              Column('x', Text, server_default="val")
518
519              x TEXT DEFAULT 'val'
520
521          A :func:`~sqlalchemy.sql.expression.text` expression will be
522          rendered as-is, without quotes::
523
524              Column('y', DateTime, server_default=text('NOW()'))0
525
526              y DATETIME DEFAULT NOW()
527
528          Strings and text() will be converted into a :class:`DefaultClause`
529          object upon initialization.
530         
531          Use :class:`FetchedValue` to indicate that an already-existing column will generate
532          a default value on the database side which will be available to SQLAlchemy
533          for post-fetch after inserts. 
534          This construct does not specify any DDL and the implementation is
535          left to the database, such as via a trigger.
536
537        :param server_onupdate:   A :class:`FetchedValue` instance representing
538            a database-side default generation function.  This indicates to
539            SQLAlchemy that a newly generated value will be available after updates.
540            This construct does not specify any DDL and the implementation is
541            left to the database, such as via a trigger.
542
543        :param quote: Force quoting of this column's name on or off, corresponding
544           to ``True`` or ``False``.  When left at its default of ``None``,
545           the column identifier will be quoted according to whether the name is
546           case sensitive (identifiers with at least one upper case character are
547           treated as case sensitive), or if it's a reserved word.  This flag
548           is only needed to force quoting of a reserved word which is not known
549           by the SQLAlchemy dialect.
550
551        :param unique: When ``True``, indicates that this column contains a unique
552            constraint, or if ``index`` is ``True`` as well, indicates that the
553            :class:`Index` should be created with the unique flag.  To specify multiple
554            columns in the constraint/index or to specify an explicit name,
555            use the :class:`UniqueConstraint` or :class:`Index` constructs explicitly.
556
557        """
558
559        name = kwargs.pop('name', None)
560        type_ = kwargs.pop('type_', None)
561        if args:
562            args = list(args)
563            if isinstance(args[0], basestring):
564                if name is not None:
565                    raise exc.ArgumentError(
566                        "May not pass name positionally and as a keyword.")
567                name = args.pop(0)
568        if args:
569            coltype = args[0]
570           
571            # adjust for partials
572            if util.callable(coltype):
573                coltype = args[0]()
574
575            if (isinstance(coltype, types.AbstractType) or
576                (isinstance(coltype, type) and
577                 issubclass(coltype, types.AbstractType))):
578                if type_ is not None:
579                    raise exc.ArgumentError(
580                        "May not pass type_ positionally and as a keyword.")
581                type_ = args.pop(0)
582
583        super(Column, self).__init__(name, None, type_)
584        self.args = args
585        self.key = kwargs.pop('key', name)
586        self.primary_key = kwargs.pop('primary_key', False)
587        self.nullable = kwargs.pop('nullable', not self.primary_key)
588        self.default = kwargs.pop('default', None)
589        self.server_default = kwargs.pop('server_default', None)
590        self.server_onupdate = kwargs.pop('server_onupdate', None)
591        self.index = kwargs.pop('index', None)
592        self.unique = kwargs.pop('unique', None)
593        self.quote = kwargs.pop('quote', None)
594        self.onupdate = kwargs.pop('onupdate', None)
595        self.autoincrement = kwargs.pop('autoincrement', True)
596        self.constraints = set()
597        self.foreign_keys = util.OrderedSet()
598        util.set_creation_order(self)
599
600        if 'info' in kwargs:
601            self.info = kwargs.pop('info')
602           
603        if kwargs:
604            raise exc.ArgumentError(
605                "Unknown arguments passed to Column: " + repr(kwargs.keys()))
606
607    def __str__(self):
608        if self.name is None:
609            return "(no name)"
610        elif self.table is not None:
611            if self.table.named_with_column:
612                return (self.table.description + "." + self.description)
613            else:
614                return self.description
615        else:
616            return self.description
617
618    @property
619    def bind(self):
620        return self.table.bind
621
622    def references(self, column):
623        """Return True if this Column references the given column via foreign key."""
624        for fk in self.foreign_keys:
625            if fk.references(column.table):
626                return True
627        else:
628            return False
629
630    def append_foreign_key(self, fk):
631        fk._set_parent(self)
632
633    def __repr__(self):
634        kwarg = []
635        if self.key != self.name:
636            kwarg.append('key')
637        if self.primary_key:
638            kwarg.append('primary_key')
639        if not self.nullable:
640            kwarg.append('nullable')
641        if self.onupdate:
642            kwarg.append('onupdate')
643        if self.default:
644            kwarg.append('default')
645        if self.server_default:
646            kwarg.append('server_default')
647        return "Column(%s)" % ', '.join(
648            [repr(self.name)] + [repr(self.type)] +
649            [repr(x) for x in self.foreign_keys if x is not None] +
650            [repr(x) for x in self.constraints] +
651            [(self.table and "table=<%s>" % self.table.description or "")] +
652            ["%s=%s" % (k, repr(getattr(self, k))) for k in kwarg])
653
654    def _set_parent(self, table):
655        if self.name is None:
656            raise exc.ArgumentError(
657                "Column must be constructed with a name or assign .name "
658                "before adding to a Table.")
659        if self.key is None:
660            self.key = self.name
661        self.metadata = table.metadata
662        if getattr(self, 'table', None) is not None:
663            raise exc.ArgumentError("this Column already has a table!")
664
665        if self.key in table._columns:
666            # note the column being replaced, if any
667            self._pre_existing_column = table._columns.get(self.key)
668        table._columns.replace(self)
669
670        if self.primary_key:
671            table.primary_key.replace(self)
672        elif self.key in table.primary_key:
673            raise exc.ArgumentError(
674                "Trying to redefine primary-key column '%s' as a "
675                "non-primary-key column on table '%s'" % (
676                self.key, table.fullname))
677            # if we think this should not raise an error, we'd instead do this:
678            #table.primary_key.remove(self)
679        self.table = table
680
681        if self.index:
682            if isinstance(self.index, basestring):
683                raise exc.ArgumentError(
684                    "The 'index' keyword argument on Column is boolean only. "
685                    "To create indexes with a specific name, create an "
686                    "explicit Index object external to the Table.")
687            Index('ix_%s' % self._label, self, unique=self.unique)
688        elif self.unique:
689            if isinstance(self.unique, basestring):
690                raise exc.ArgumentError(
691                    "The 'unique' keyword argument on Column is boolean only. "
692                    "To create unique constraints or indexes with a specific "
693                    "name, append an explicit UniqueConstraint to the Table's "
694                    "list of elements, or create an explicit Index object "
695                    "external to the Table.")
696            table.append_constraint(UniqueConstraint(self.key))
697
698        toinit = list(self.args)
699        if self.default is not None:
700            if isinstance(self.default, ColumnDefault):
701                toinit.append(self.default)
702            else:
703                toinit.append(ColumnDefault(self.default))
704        if self.server_default is not None:
705            if isinstance(self.server_default, FetchedValue):
706                toinit.append(self.server_default)
707            else:
708                toinit.append(DefaultClause(self.server_default))
709        if self.onupdate is not None:
710            toinit.append(ColumnDefault(self.onupdate, for_update=True))
711        if self.server_onupdate is not None:
712            if isinstance(self.server_onupdate, FetchedValue):
713                toinit.append(self.server_default)
714            else:
715                toinit.append(DefaultClause(self.server_onupdate,
716                                            for_update=True))
717        self._init_items(*toinit)
718        self.args = None
719
720    def copy(self, **kw):
721        """Create a copy of this ``Column``, unitialized.
722
723        This is used in ``Table.tometadata``.
724
725        """
726        return Column(
727                self.name,
728                self.type,
729                self.default,
730                key = self.key,
731                primary_key = self.primary_key,
732                nullable = self.nullable,
733                quote=self.quote,
734                index=self.index,
735                autoincrement=self.autoincrement,
736                default=self.default,
737                server_default=self.server_default,
738                onupdate=self.onupdate,
739                server_onupdate=self.server_onupdate,
740                *[c.copy(**kw) for c in self.constraints])
741
742    def _make_proxy(self, selectable, name=None):
743        """Create a *proxy* for this column.
744
745        This is a copy of this ``Column`` referenced by a different parent
746        (such as an alias or select statement).
747
748        """
749        fk = [ForeignKey(f.column) for f in self.foreign_keys]
750        c = Column(
751            name or self.name,
752            self.type,
753            self.default,
754            key = name or self.key,
755            primary_key = self.primary_key,
756            nullable = self.nullable,
757            quote=self.quote, *fk)
758        c.table = selectable
759        c.proxies = [self]
760        selectable.columns.add(c)
761        if self.primary_key:
762            selectable.primary_key.add(c)
763        [c._init_items(f) for f in fk]
764        return c
765
766    def get_children(self, schema_visitor=False, **kwargs):
767        if schema_visitor:
768            return [x for x in (self.default, self.onupdate) if x is not None] + \
769                list(self.foreign_keys) + list(self.constraints)
770        else:
771            return expression.ColumnClause.get_children(self, **kwargs)
772
773
774class ForeignKey(SchemaItem):
775    """Defines a column-level FOREIGN KEY constraint between two columns.
776
777    ``ForeignKey`` is specified as an argument to a :class:`Column` object, e.g.::
778   
779        t = Table("remote_table", metadata,
780            Column("remote_id", ForeignKey("main_table.id"))
781        )
782
783    For a composite (multiple column) FOREIGN KEY, use a :class:`ForeignKeyConstraint`
784    object specified at the level of the :class:`Table`.
785   
786    Further examples of foreign key configuration are in :ref:`metadata_foreignkeys`.
787
788    """
789
790    __visit_name__ = 'foreign_key'
791
792    def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None, link_to_name=False):
793        """
794        Construct a column-level FOREIGN KEY.
795
796        :param column: A single target column for the key relationship.  A :class:`Column`
797          object or a column name as a string: ``tablename.columnkey`` or
798          ``schema.tablename.columnkey``.  ``columnkey`` is the ``key`` which has been assigned
799          to the column (defaults to the column name itself), unless ``link_to_name`` is ``True``
800          in which case the rendered name of the column is used.
801
802        :param constraint: Optional.  A parent :class:`ForeignKeyConstraint` object.  If not
803          supplied, a :class:`ForeignKeyConstraint` will be automatically created
804          and added to the parent table.
805
806        :param name: Optional string.  An in-database name for the key if `constraint` is
807          not provided.
808
809        :param onupdate: Optional string.  If set, emit ON UPDATE <value> when issuing DDL
810          for this constraint.  Typical values include CASCADE, DELETE and
811          RESTRICT.
812
813        :param ondelete: Optional string.  If set, emit ON DELETE <value> when issuing DDL
814          for this constraint.  Typical values include CASCADE, DELETE and
815          RESTRICT.
816
817        :param deferrable: Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
818          issuing DDL for this constraint.
819
820        :param initially: Optional string.  If set, emit INITIALLY <value> when issuing DDL
821          for this constraint.
822       
823        :param link_to_name: if True, the string name given in ``column`` is the rendered
824          name of the referenced column, not its locally assigned ``key``.
825         
826        :param use_alter: If True, do not emit this key as part of the CREATE TABLE
827          definition.  Instead, use ALTER TABLE after table creation to add
828          the key.  Useful for circular dependencies.
829         
830        """
831
832        self._colspec = column
833        self.constraint = constraint
834        self.use_alter = use_alter
835        self.name = name
836        self.onupdate = onupdate
837        self.ondelete = ondelete
838        self.deferrable = deferrable
839        self.initially = initially
840        self.link_to_name = link_to_name
841
842    def __repr__(self):
843        return "ForeignKey(%r)" % self._get_colspec()
844
845    def copy(self, schema=None):
846        """Produce a copy of this ForeignKey object."""
847
848        return ForeignKey(self._get_colspec(schema=schema))
849
850    def _get_colspec(self, schema=None):
851        if schema:
852            return schema + "." + self.column.table.name + "." + self.column.key
853        elif isinstance(self._colspec, basestring):
854            return self._colspec
855        elif hasattr(self._colspec, '__clause_element__'):
856            _column = self._colspec.__clause_element__()
857        else:
858            _column = self._colspec
859           
860        return "%s.%s" % (_column.table.fullname, _column.key)
861
862    target_fullname = property(_get_colspec)
863
864    def references(self, table):
865        """Return True if the given table is referenced by this ForeignKey."""
866        return table.corresponding_column(self.column) is not None
867
868    def get_referent(self, table):
869        """Return the column in the given table referenced by this ForeignKey.
870
871        Returns None if this ``ForeignKey`` does not reference the given table.
872
873        """
874
875        return table.corresponding_column(self.column)
876
877    @util.memoized_property
878    def column(self):
879        # ForeignKey inits its remote column as late as possible, so tables
880        # can be defined without dependencies
881        if isinstance(self._colspec, basestring):
882            # locate the parent table this foreign key is attached to.  we
883            # use the "original" column which our parent column represents
884            # (its a list of columns/other ColumnElements if the parent
885            # table is a UNION)
886            for c in self.parent.base_columns:
887                if isinstance(c, Column):
888                    parenttable = c.table
889                    break
890            else:
891                raise exc.ArgumentError(
892                    "Parent column '%s' does not descend from a "
893                    "table-attached Column" % str(self.parent))
894
895            m = self._colspec.split('.')
896
897            if m is None:
898                raise exc.ArgumentError(
899                    "Invalid foreign key column specification: %s" %
900                    self._colspec)
901
902            # A FK between column 'bar' and table 'foo' can be
903            # specified as 'foo', 'foo.bar', 'dbo.foo.bar',
904            # 'otherdb.dbo.foo.bar'. Once we have the column name and
905            # the table name, treat everything else as the schema
906            # name. Some databases (e.g. Sybase) support
907            # inter-database foreign keys. See tickets#1341 and --
908            # indirectly related -- Ticket #594. This assumes that '.'
909            # will never appear *within* any component of the FK.
910
911            (schema, tname, colname) = (None, None, None)
912            if (len(m) == 1):
913                tname   = m.pop()
914            else:
915                colname = m.pop()
916                tname   = m.pop()
917
918            if (len(m) > 0):
919                schema = '.'.join(m)
920
921            if _get_table_key(tname, schema) not in parenttable.metadata:
922                raise exc.NoReferencedTableError(
923                    "Could not find table '%s' with which to generate a "
924                    "foreign key" % tname)
925            table = Table(tname, parenttable.metadata,
926                          mustexist=True, schema=schema)
927                         
928            _column = None
929            if colname is None:
930                # colname is None in the case that ForeignKey argument
931                # was specified as table name only, in which case we
932                # match the column name to the same column on the
933                # parent.
934                key = self.parent
935                _column = table.c.get(self.parent.key, None)
936            elif self.link_to_name:
937                key = colname
938                for c in table.c:
939                    if c.name == colname:
940                        _column = c
941            else:
942                key = colname
943                _column = table.c.get(colname, None)
944
945            if not _column:
946                raise exc.NoReferencedColumnError(
947                    "Could not create ForeignKey '%s' on table '%s': "
948                    "table '%s' has no column named '%s'" % (
949                    self._colspec, parenttable.name, table.name, key))
950
951        elif hasattr(self._colspec, '__clause_element__'):
952            _column = self._colspec.__clause_element__()
953        else:
954            _column = self._colspec
955
956        # propagate TypeEngine to parent if it didn't have one
957        if isinstance(self.parent.type, types.NullType):
958            self.parent.type = _column.type
959        return _column
960
961    def _set_parent(self, column):
962        if hasattr(self, 'parent'):
963            raise exc.InvalidRequestError("This ForeignKey already has a parent !")
964        self.parent = column
965
966        if hasattr(self.parent, '_pre_existing_column'):
967            # remove existing FK which matches us
968            for fk in self.parent._pre_existing_column.foreign_keys:
969                if fk.target_fullname == self.target_fullname:
970                    self.parent.table.foreign_keys.remove(fk)
971                    self.parent.table.constraints.remove(fk.constraint)
972
973        if self.constraint is None and isinstance(self.parent.table, Table):
974            self.constraint = ForeignKeyConstraint(
975                [], [], use_alter=self.use_alter, name=self.name,
976                onupdate=self.onupdate, ondelete=self.ondelete,
977                deferrable=self.deferrable, initially=self.initially)
978            self.parent.table.append_constraint(self.constraint)
979            self.constraint._append_fk(self)
980
981        self.parent.foreign_keys.add(self)
982        self.parent.table.foreign_keys.add(self)
983
984class DefaultGenerator(SchemaItem):
985    """Base class for column *default* values."""
986
987    __visit_name__ = 'default_generator'
988
989    def __init__(self, for_update=False, metadata=None):
990        self.for_update = for_update
991        self.metadata = util.assert_arg_type(metadata, (MetaData, type(None)), 'metadata')
992
993    def _set_parent(self, column):
994        self.column = column
995        self.metadata = self.column.table.metadata
996        if self.for_update:
997            self.column.onupdate = self
998        else:
999            self.column.default = self
1000
1001    def execute(self, bind=None, **kwargs):
1002        if bind is None:
1003            bind = _bind_or_error(self)
1004        return bind._execute_default(self, **kwargs)
1005
1006    def __repr__(self):
1007        return "DefaultGenerator()"
1008
1009
1010class ColumnDefault(DefaultGenerator):
1011    """A plain default value on a column.
1012
1013    This could correspond to a constant, a callable function, or a SQL clause.
1014    """
1015
1016    def __init__(self, arg, **kwargs):
1017        super(ColumnDefault, self).__init__(**kwargs)
1018        if isinstance(arg, FetchedValue):
1019            raise exc.ArgumentError(
1020                "ColumnDefault may not be a server-side default type.")
1021        if util.callable(arg):
1022            arg = self._maybe_wrap_callable(arg)
1023        self.arg = arg
1024
1025    def _maybe_wrap_callable(self, fn):
1026        """Backward compat: Wrap callables that don't accept a context."""
1027
1028        if inspect.isfunction(fn):
1029            inspectable = fn
1030        elif inspect.isclass(fn):
1031            inspectable = fn.__init__
1032        elif hasattr(fn, '__call__'):
1033            inspectable = fn.__call__
1034        else:
1035            # probably not inspectable, try anyways.
1036            inspectable = fn
1037        try:
1038            argspec = inspect.getargspec(inspectable)
1039        except TypeError:
1040            return lambda ctx: fn()
1041
1042        positionals = len(argspec[0])
1043        if inspect.ismethod(inspectable):
1044            positionals -= 1
1045
1046        if positionals == 0:
1047            return lambda ctx: fn()
1048
1049        defaulted = argspec[3] is not None and len(argspec[3]) or 0
1050        if positionals - defaulted > 1:
1051            raise exc.ArgumentError(
1052                "ColumnDefault Python function takes zero or one "
1053                "positional arguments")
1054        return fn
1055
1056    def _visit_name(self):
1057        if self.for_update:
1058            return "column_onupdate"
1059        else:
1060            return "column_default"
1061    __visit_name__ = property(_visit_name)
1062
1063    def __repr__(self):
1064        return "ColumnDefault(%s)" % repr(self.arg)
1065
1066class Sequence(DefaultGenerator):
1067    """Represents a named database sequence."""
1068
1069    __visit_name__ = 'sequence'
1070
1071    def __init__(self, name, start=None, increment=None, schema=None,
1072                 optional=False, quote=None, **kwargs):
1073        super(Sequence, self).__init__(**kwargs)
1074        self.name = name
1075        self.start = start
1076        self.increment = increment
1077        self.optional = optional
1078        self.quote = quote
1079        self.schema = schema
1080        self.kwargs = kwargs
1081
1082    def __repr__(self):
1083        return "Sequence(%s)" % ', '.join(
1084            [repr(self.name)] +
1085            ["%s=%s" % (k, repr(getattr(self, k)))
1086             for k in ['start', 'increment', 'optional']])
1087
1088    def _set_parent(self, column):
1089        super(Sequence, self)._set_parent(column)
1090        column.sequence = self
1091
1092    def create(self, bind=None, checkfirst=True):
1093        """Creates this sequence in the database."""
1094
1095        if bind is None:
1096            bind = _bind_or_error(self)
1097        bind.create(self, checkfirst=checkfirst)
1098
1099    def drop(self, bind=None, checkfirst=True):
1100        """Drops this sequence from the database."""
1101
1102        if bind is None:
1103            bind = _bind_or_error(self)
1104        bind.drop(self, checkfirst=checkfirst)
1105
1106
1107class FetchedValue(object):
1108    """A default that takes effect on the database side."""
1109
1110    def __init__(self, for_update=False):
1111        self.for_update = for_update
1112
1113    def _set_parent(self, column):
1114        self.column = column
1115        if self.for_update:
1116            self.column.server_onupdate = self
1117        else:
1118            self.column.server_default = self
1119
1120    def __repr__(self):
1121        return 'FetchedValue(for_update=%r)' % self.for_update
1122
1123
1124class DefaultClause(FetchedValue):
1125    """A DDL-specified DEFAULT column value."""
1126
1127    def __init__(self, arg, for_update=False):
1128        util.assert_arg_type(arg, (basestring,
1129                                   expression.ClauseElement,
1130                                   expression._TextClause), 'arg')
1131        super(DefaultClause, self).__init__(for_update)
1132        self.arg = arg
1133
1134    def __repr__(self):
1135        return "DefaultClause(%r, for_update=%r)" % (self.arg, self.for_update)
1136
1137# alias; deprecated starting 0.5.0
1138PassiveDefault = DefaultClause
1139
1140
1141class Constraint(SchemaItem):
1142    """A table-level SQL constraint, such as a KEY.
1143
1144    Implements a hybrid of dict/setlike behavior with regards to the list of
1145    underying columns.
1146    """
1147
1148    __visit_name__ = 'constraint'
1149
1150    def __init__(self, name=None, deferrable=None, initially=None):
1151        """Create a SQL constraint.
1152
1153        name
1154          Optional, the in-database name of this ``Constraint``.
1155
1156        deferrable
1157          Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
1158          issuing DDL for this constraint.
1159
1160        initially
1161          Optional string.  If set, emit INITIALLY <value> when issuing DDL
1162          for this constraint.
1163        """
1164
1165        self.name = name
1166        self.columns = expression.ColumnCollection()
1167        self.deferrable = deferrable
1168        self.initially = initially
1169
1170    def __contains__(self, x):
1171        return x in self.columns
1172
1173    def contains_column(self, col):
1174        return self.columns.contains_column(col)
1175
1176    def keys(self):
1177        return self.columns.keys()
1178
1179    def __add__(self, other):
1180        return self.columns + other
1181
1182    def __iter__(self):
1183        return iter(self.columns)
1184
1185    def __len__(self):
1186        return len(self.columns)
1187
1188    def copy(self, **kw):
1189        raise NotImplementedError()
1190
1191class CheckConstraint(Constraint):
1192    """A table- or column-level CHECK constraint.
1193
1194    Can be included in the definition of a Table or Column.
1195    """
1196
1197    def __init__(self, sqltext, name=None, deferrable=None, initially=None):
1198        """Construct a CHECK constraint.
1199
1200        sqltext
1201          A string containing the constraint definition.  Will be used
1202          verbatim.
1203
1204        name
1205          Optional, the in-database name of the constraint.
1206
1207        deferrable
1208          Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
1209          issuing DDL for this constraint.
1210
1211        initially
1212          Optional string.  If set, emit INITIALLY <value> when issuing DDL
1213          for this constraint.
1214        """
1215
1216        super(CheckConstraint, self).__init__(name, deferrable, initially)
1217        if not isinstance(sqltext, basestring):
1218            raise exc.ArgumentError(
1219                "sqltext must be a string and will be used verbatim.")
1220        self.sqltext = sqltext
1221
1222    def __visit_name__(self):
1223        if isinstance(self.parent, Table):
1224            return "check_constraint"
1225        else:
1226            return "column_check_constraint"
1227    __visit_name__ = property(__visit_name__)
1228
1229    def _set_parent(self, parent):
1230        self.parent = parent
1231        parent.constraints.add(self)
1232
1233    def copy(self, **kw):
1234        return CheckConstraint(self.sqltext, name=self.name)
1235
1236class ForeignKeyConstraint(Constraint):
1237    """A table-level FOREIGN KEY constraint.
1238
1239    Defines a single column or composite FOREIGN KEY ... REFERENCES
1240    constraint. For a no-frills, single column foreign key, adding a
1241    :class:`ForeignKey` to the definition of a :class:`Column` is a shorthand equivalent
1242    for an unnamed, single column :class:`ForeignKeyConstraint`.
1243   
1244    Examples of foreign key configuration are in :ref:`metadata_foreignkeys`.
1245   
1246    """
1247    __visit_name__ = 'foreign_key_constraint'
1248
1249    def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None, link_to_name=False):
1250        """Construct a composite-capable FOREIGN KEY.
1251
1252        :param columns: A sequence of local column names.  The named columns must be defined
1253          and present in the parent Table.  The names should match the ``key`` given
1254          to each column (defaults to the name) unless ``link_to_name`` is True.
1255
1256        :param refcolumns: A sequence of foreign column names or Column objects.  The columns
1257          must all be located within the same Table.
1258
1259        :param name: Optional, the in-database name of the key.
1260
1261        :param onupdate: Optional string.  If set, emit ON UPDATE <value> when issuing DDL
1262          for this constraint.  Typical values include CASCADE, DELETE and
1263          RESTRICT.
1264
1265        :param ondelete: Optional string.  If set, emit ON DELETE <value> when issuing DDL
1266          for this constraint.  Typical values include CASCADE, DELETE and
1267          RESTRICT.
1268
1269        :param deferrable: Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
1270          issuing DDL for this constraint.
1271
1272        :param initially: Optional string.  If set, emit INITIALLY <value> when issuing DDL
1273          for this constraint.
1274
1275        :param link_to_name: if True, the string name given in ``column`` is the rendered
1276          name of the referenced column, not its locally assigned ``key``.
1277
1278        :param use_alter: If True, do not emit this key as part of the CREATE TABLE
1279          definition.  Instead, use ALTER TABLE after table creation to add
1280          the key.  Useful for circular dependencies.
1281         
1282        """
1283        super(ForeignKeyConstraint, self).__init__(name, deferrable, initially)
1284        self.__colnames = columns
1285        self.__refcolnames = refcolumns
1286        self.elements = util.OrderedSet()
1287        self.onupdate = onupdate
1288        self.ondelete = ondelete
1289        self.link_to_name = link_to_name
1290        if self.name is None and use_alter:
1291            raise exc.ArgumentError("Alterable ForeignKey/ForeignKeyConstraint requires a name")
1292        self.use_alter = use_alter
1293
1294    def _set_parent(self, table):
1295        self.table = table
1296        if self not in table.constraints:
1297            table.constraints.add(self)
1298            for (c, r) in zip(self.__colnames, self.__refcolnames):
1299                self.append_element(c, r)
1300
1301    def append_element(self, col, refcol):
1302        fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter, link_to_name=self.link_to_name)
1303        fk._set_parent(self.table.c[col])
1304        self._append_fk(fk)
1305
1306    def _append_fk(self, fk):
1307        self.columns.add(self.table.c[fk.parent.key])
1308        self.elements.add(fk)
1309
1310    def copy(self, **kw):
1311        return ForeignKeyConstraint([x.parent.name for x in self.elements], [x._get_colspec(**kw) for x in self.elements], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter)
1312
1313class PrimaryKeyConstraint(Constraint):
1314    """A table-level PRIMARY KEY constraint.
1315
1316    Defines a single column or composite PRIMARY KEY constraint. For a
1317    no-frills primary key, adding ``primary_key=True`` to one or more
1318    ``Column`` definitions is a shorthand equivalent for an unnamed single- or
1319    multiple-column PrimaryKeyConstraint.
1320    """
1321
1322    __visit_name__ = 'primary_key_constraint'
1323
1324    def __init__(self, *columns, **kwargs):
1325        """Construct a composite-capable PRIMARY KEY.
1326
1327        \*columns
1328          A sequence of column names.  All columns named must be defined and
1329          present within the parent Table.
1330
1331        name
1332          Optional, the in-database name of the key.
1333
1334        deferrable
1335          Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
1336          issuing DDL for this constraint.
1337
1338        initially
1339          Optional string.  If set, emit INITIALLY <value> when issuing DDL
1340          for this constraint.
1341        """
1342
1343        constraint_args = dict(name=kwargs.pop('name', None),
1344                               deferrable=kwargs.pop('deferrable', None),
1345                               initially=kwargs.pop('initially', None))
1346        if kwargs:
1347            raise exc.ArgumentError(
1348                'Unknown PrimaryKeyConstraint argument(s): %s' %
1349                ', '.join(repr(x) for x in kwargs.keys()))
1350
1351        super(PrimaryKeyConstraint, self).__init__(**constraint_args)
1352        self.__colnames = list(columns)
1353
1354    def _set_parent(self, table):
1355        self.table = table
1356        table.primary_key = self
1357        for name in self.__colnames:
1358            self.add(table.c[name])
1359
1360    def add(self, col):
1361        self.columns.add(col)
1362        col.primary_key = True
1363    append_column = add
1364
1365    def replace(self, col):
1366        self.columns.replace(col)
1367
1368    def remove(self, col):
1369        col.primary_key = False
1370        del self.columns[col.key]
1371
1372    def copy(self, **kw):
1373        return PrimaryKeyConstraint(name=self.name, *[c.key for c in self])
1374
1375    __hash__ = Constraint.__hash__
1376   
1377    def __eq__(self, other):
1378        return self.columns == other
1379
1380class UniqueConstraint(Constraint):
1381    """A table-level UNIQUE constraint.
1382
1383    Defines a single column or composite UNIQUE constraint. For a no-frills,
1384    single column constraint, adding ``unique=True`` to the ``Column``
1385    definition is a shorthand equivalent for an unnamed, single column
1386    UniqueConstraint.
1387    """
1388
1389    __visit_name__ = 'unique_constraint'
1390
1391    def __init__(self, *columns, **kwargs):
1392        """Construct a UNIQUE constraint.
1393
1394        \*columns
1395          A sequence of column names.  All columns named must be defined and
1396          present within the parent Table.
1397
1398        name
1399          Optional, the in-database name of the key.
1400
1401        deferrable
1402          Optional bool.  If set, emit DEFERRABLE or NOT DEFERRABLE when
1403          issuing DDL for this constraint.
1404
1405        initially
1406          Optional string.  If set, emit INITIALLY <value> when issuing DDL
1407          for this constraint.
1408        """
1409
1410        constraint_args = dict(name=kwargs.pop('name', None),
1411                               deferrable=kwargs.pop('deferrable', None),
1412                               initially=kwargs.pop('initially', None))
1413        if kwargs:
1414            raise exc.ArgumentError(
1415                'Unknown UniqueConstraint argument(s): %s' %
1416                ', '.join(repr(x) for x in kwargs.keys()))
1417
1418        super(UniqueConstraint, self).__init__(**constraint_args)
1419        self.__colnames = list(columns)
1420
1421    def _set_parent(self, table):
1422        self.table = table
1423        table.constraints.add(self)
1424        for c in self.__colnames:
1425            self.append_column(table.c[c])
1426
1427    def append_column(self, col):
1428        self.columns.add(col)
1429
1430    def copy(self, **kw):
1431        return UniqueConstraint(name=self.name, *self.__colnames)
1432
1433class Index(SchemaItem):
1434    """A table-level INDEX.
1435
1436    Defines a composite (one or more column) INDEX. For a no-frills, single
1437    column index, adding ``index=True`` to the ``Column`` definition is
1438    a shorthand equivalent for an unnamed, single column Index.
1439    """
1440
1441    __visit_name__ = 'index'
1442
1443    def __init__(self, name, *columns, **kwargs):
1444        """Construct an index object.
1445
1446        Arguments are:
1447
1448        name
1449          The name of the index
1450
1451        \*columns
1452          Columns to include in the index. All columns must belong to the same
1453          table, and no column may appear more than once.
1454
1455        \**kwargs
1456          Keyword arguments include:
1457
1458          unique
1459            Defaults to False: create a unique index.
1460
1461          postgres_where
1462            Defaults to None: create a partial index when using PostgreSQL
1463        """
1464
1465        self.name = name
1466        self.columns = []
1467        self.table = None
1468        self.unique = kwargs.pop('unique', False)
1469        self.kwargs = kwargs
1470
1471        self._init_items(*columns)
1472
1473    def _init_items(self, *args):
1474        for column in args:
1475            self.append_column(_to_schema_column(column))
1476
1477    def _set_parent(self, table):
1478        self.table = table
1479        self.metadata = table.metadata
1480        table.indexes.add(self)
1481
1482    def append_column(self, column):
1483        # make sure all columns are from the same table
1484        # and no column is repeated
1485        if self.table is None:
1486            self._set_parent(column.table)
1487        elif column.table != self.table:
1488            # all columns muse be from same table
1489            raise exc.ArgumentError(
1490                "All index columns must be from same table. "
1491                "%s is from %s not %s" % (column, column.table, self.table))
1492        elif column.name in [ c.name for c in self.columns ]:
1493            raise exc.ArgumentError(
1494                "A column may not appear twice in the "
1495                "same index (%s already has column %s)" % (self.name, column))
1496        self.columns.append(column)
1497
1498    def create(self, bind=None):
1499        if bind is None:
1500            bind = _bind_or_error(self)
1501        bind.create(self)
1502        return self
1503
1504    def drop(self, bind=None):
1505        if bind is None:
1506            bind = _bind_or_error(self)
1507        bind.drop(self)
1508
1509    def __str__(self):
1510        return repr(self)
1511
1512    def __repr__(self):
1513        return 'Index("%s", %s%s)' % (self.name,
1514                                      ', '.join(repr(c) for c in self.columns),
1515                                      (self.unique and ', unique=True') or '')
1516
1517class MetaData(SchemaItem):
1518    """A collection of Tables and their associated schema constructs.
1519
1520    Holds a collection of Tables and an optional binding to an ``Engine`` or
1521    ``Connection``.  If bound, the :class:`~sqlalchemy.schema.Table` objects
1522    in the collection and their columns may participate in implicit SQL
1523    execution.
1524
1525    The `Table` objects themselves are stored in the `metadata.tables`
1526    dictionary.
1527
1528    The ``bind`` property may be assigned to dynamically.  A common pattern is
1529    to start unbound and then bind later when an engine is available::
1530
1531      metadata = MetaData()
1532      # define tables
1533      Table('mytable', metadata, ...)
1534      # connect to an engine later, perhaps after loading a URL from a
1535      # configuration file
1536      metadata.bind = an_engine
1537
1538    MetaData is a thread-safe object after tables have been explicitly defined
1539    or loaded via reflection.
1540
1541    .. index::
1542      single: thread safety; MetaData
1543
1544    """
1545
1546    __visit_name__ = 'metadata'
1547
1548    ddl_events = ('before-create', 'after-create', 'before-drop', 'after-drop')
1549
1550    def __init__(self, bind=None, reflect=False):
1551        """Create a new MetaData object.
1552
1553        bind
1554          An Engine or Connection to bind to.  May also be a string or URL
1555          instance, these are passed to create_engine() and this MetaData will
1556          be bound to the resulting engine.
1557
1558        reflect
1559          Optional, automatically load all tables from the bound database.
1560          Defaults to False. ``bind`` is required when this option is set.
1561          For finer control over loaded tables, use the ``reflect`` method of
1562          ``MetaData``.
1563
1564        """
1565        self.tables = {}
1566        self.bind = bind
1567        self.metadata = self
1568        self.ddl_listeners = util.defaultdict(list)
1569        if reflect:
1570            if not bind:
1571                raise exc.ArgumentError(
1572                    "A bind must be supplied in conjunction with reflect=True")
1573            self.reflect()
1574
1575    def __repr__(self):
1576        return 'MetaData(%r)' % self.bind
1577
1578    def __contains__(self, key):
1579        return key in self.tables
1580
1581    def __getstate__(self):
1582        return {'tables': self.tables}
1583
1584    def __setstate__(self, state):
1585        self.tables = state['tables']
1586        self._bind = None
1587
1588    def is_bound(self):
1589        """True if this MetaData is bound to an Engine or Connection."""
1590
1591        return self._bind is not None
1592
1593    @util.deprecated('Deprecated. Use ``metadata.bind = <engine>`` or '
1594                     '``metadata.bind = <url>``.')
1595    def connect(self, bind, **kwargs):
1596        """Bind this MetaData to an Engine.
1597
1598        bind
1599          A string, ``URL``, ``Engine`` or ``Connection`` instance.  If a
1600          string or ``URL``, will be passed to ``create_engine()`` along with
1601          ``\**kwargs`` to produce the engine which to connect to.  Otherwise
1602          connects directly to the given ``Engine``.
1603         
1604        """
1605        global URL
1606        if URL is None:
1607            from sqlalchemy.engine.url import URL
1608        if isinstance(bind, (basestring, URL)):
1609            from sqlalchemy import create_engine
1610            self._bind = create_engine(bind, **kwargs)
1611        else:
1612            self._bind = bind
1613
1614    def bind(self):
1615        """An Engine or Connection to which this MetaData is bound.
1616
1617        This property may be assigned an ``Engine`` or ``Connection``, or
1618        assigned a string or URL to automatically create a basic ``Engine``
1619        for this bind with ``create_engine()``.
1620       
1621        """
1622        return self._bind
1623
1624    def _bind_to(self, bind):
1625        """Bind this MetaData to an Engine, Connection, string or URL."""
1626
1627        global URL
1628        if URL is None:
1629            from sqlalchemy.engine.url import URL
1630
1631        if isinstance(bind, (basestring, URL)):
1632            from sqlalchemy import create_engine
1633            self._bind = create_engine(bind)
1634        else:
1635            self._bind = bind
1636    bind = property(bind, _bind_to)
1637
1638    def clear(self):
1639        """Clear all Table objects from this MetaData."""
1640        # TODO: why have clear()/remove() but not all
1641        # other accesors/mutators for the tables dict ?
1642        self.tables.clear()
1643
1644    def remove(self, table):
1645        """Remove the given Table object from this MetaData."""
1646       
1647        # TODO: scan all other tables and remove FK _column
1648        del self.tables[table.key]
1649
1650    @util.deprecated('Deprecated. Use ``metadata.sorted_tables``')
1651    def table_iterator(self, reverse=True, tables=None):
1652        """Deprecated - use metadata.sorted_tables()."""
1653       
1654        from sqlalchemy.sql.util import sort_tables
1655        if tables is None:
1656            tables = self.tables.values()
1657        else:
1658            tables = set(tables).intersection(self.tables.values())
1659        ret = sort_tables(tables)
1660        if reverse:
1661            ret = reversed(ret)
1662        return iter(ret)
1663   
1664    @property
1665    def sorted_tables(self):
1666        """Returns a list of ``Table`` objects sorted in order of
1667        dependency.
1668        """
1669        from sqlalchemy.sql.util import sort_tables
1670        return sort_tables(self.tables.values())
1671       
1672    def reflect(self, bind=None, schema=None, only=None):
1673        """Load all available table definitions from the database.
1674
1675        Automatically creates ``Table`` entries in this ``MetaData`` for any
1676        table available in the database but not yet present in the
1677        ``MetaData``.  May be called multiple times to pick up tables recently
1678        added to the database, however no special action is taken if a table
1679        in this ``MetaData`` no longer exists in the database.
1680
1681        bind
1682          A :class:`~sqlalchemy.engine.base.Connectable` used to access the database; if None, uses the
1683          existing bind on this ``MetaData``, if any.
1684
1685        schema
1686          Optional, query and reflect tables from an alterate schema.
1687
1688        only
1689          Optional.  Load only a sub-set of available named tables.  May be
1690          specified as a sequence of names or a callable.
1691
1692          If a sequence of names is provided, only those tables will be
1693          reflected.  An error is raised if a table is requested but not
1694          available.  Named tables already present in this ``MetaData`` are
1695          ignored.
1696
1697          If a callable is provided, it will be used as a boolean predicate to
1698          filter the list of potential table names.  The callable is called
1699          with a table name and this ``MetaData`` instance as positional
1700          arguments and should return a true value for any table to reflect.
1701
1702        """
1703        reflect_opts = {'autoload': True}
1704        if bind is None:
1705            bind = _bind_or_error(self)
1706            conn = None
1707        else:
1708            reflect_opts['autoload_with'] = bind
1709            conn = bind.contextual_connect()
1710
1711        if schema is not None:
1712            reflect_opts['schema'] = schema
1713
1714        available = util.OrderedSet(bind.engine.table_names(schema,
1715                                                            connection=conn))
1716        current = set(self.tables.keys())
1717
1718        if only is None:
1719            load = [name for name in available if name not in current]
1720        elif util.callable(only):
1721            load = [name for name in available
1722                    if name not in current and only(name, self)]
1723        else:
1724            missing = [name for name in only if name not in available]
1725            if missing:
1726                s = schema and (" schema '%s'" % schema) or ''
1727                raise exc.InvalidRequestError(
1728                    'Could not reflect: requested table(s) not available '
1729                    'in %s%s: (%s)' % (bind.engine.url, s, ', '.join(missing)))
1730            load = [name for name in only if name not in current]
1731
1732        for name in load:
1733            Table(name, self, **reflect_opts)
1734
1735    def append_ddl_listener(self, event, listener):
1736        """Append a DDL event listener to this ``MetaData``.
1737
1738        The ``listener`` callable will be triggered when this ``MetaData`` is
1739        involved in DDL creates or drops, and will be invoked either before
1740        all Table-related actions or after.
1741
1742        Arguments are:
1743
1744        event
1745          One of ``MetaData.ddl_events``; 'before-create', 'after-create',
1746          'before-drop' or 'after-drop'.
1747        listener
1748          A callable, invoked with three positional arguments:
1749
1750          event
1751            The event currently being handled
1752          schema_item
1753            The ``MetaData`` object being operated upon
1754          bind
1755            The ``Connection`` bueing used for DDL execution.
1756
1757        Listeners are added to the MetaData's ``ddl_listeners`` attribute.
1758
1759        Note: MetaData listeners are invoked even when ``Tables`` are created
1760        in isolation.  This may change in a future release. I.e.::
1761
1762          # triggers all MetaData and Table listeners:
1763          metadata.create_all()
1764
1765          # triggers MetaData listeners too:
1766          some.table.create()
1767
1768        """
1769        if event not in self.ddl_events:
1770            raise LookupError(event)
1771        self.ddl_listeners[event].append(listener)
1772
1773    def create_all(self, bind=None, tables=None, checkfirst=True):
1774        """Create all tables stored in this metadata.
1775
1776        Conditional by default, will not attempt to recreate tables already
1777        present in the target database.
1778
1779        bind
1780          A :class:`~sqlalchemy.engine.base.Connectable` used to access the database; if None, uses the
1781          existing bind on this ``MetaData``, if any.
1782
1783        tables
1784          Optional list of ``Table`` objects, which is a subset of the total
1785          tables in the ``MetaData`` (others are ignored).
1786
1787        checkfirst
1788          Defaults to True, don't issue CREATEs for tables already present
1789          in the target database.
1790         
1791        """
1792        if bind is None:
1793            bind = _bind_or_error(self)
1794        for listener in self.ddl_listeners['before-create']:
1795            listener('before-create', self, bind)
1796        bind.create(self, checkfirst=checkfirst, tables=tables)
1797        for listener in self.ddl_listeners['after-create']:
1798            listener('after-create', self, bind)
1799
1800    def drop_all(self, bind=None, tables=None, checkfirst=True):
1801        """Drop all tables stored in this metadata.
1802
1803        Conditional by default, will not attempt to drop tables not present in
1804        the target database.
1805
1806        bind
1807          A :class:`~sqlalchemy.engine.base.Connectable` used to access the database; if None, uses
1808          the existing bind on this ``MetaData``, if any.
1809
1810        tables
1811          Optional list of ``Table`` objects, which is a subset of the
1812          total tables in the ``MetaData`` (others are ignored).
1813
1814        checkfirst
1815          Defaults to True, only issue DROPs for tables confirmed to be present
1816          in the target database.
1817
1818        """
1819        if bind is None:
1820            bind = _bind_or_error(self)
1821        for listener in self.ddl_listeners['before-drop']:
1822            listener('before-drop', self, bind)
1823        bind.drop(self, checkfirst=checkfirst, tables=tables)
1824        for listener in self.ddl_listeners['after-drop']:
1825            listener('after-drop', self, bind)
1826
1827class ThreadLocalMetaData(MetaData):
1828    """A MetaData variant that presents a different ``bind`` in every thread.
1829
1830    Makes the ``bind`` property of the MetaData a thread-local value, allowing
1831    this collection of tables to be bound to different ``Engine``
1832    implementations or connections in each thread.
1833
1834    The ThreadLocalMetaData starts off bound to None in each thread.  Binds
1835    must be made explicitly by assigning to the ``bind`` property or using
1836    ``connect()``.  You can also re-bind dynamically multiple times per
1837    thread, just like a regular ``MetaData``.
1838
1839    """
1840
1841    __visit_name__ = 'metadata'
1842
1843    def __init__(self):
1844        """Construct a ThreadLocalMetaData."""
1845
1846        self.context = util.threading.local()
1847        self.__engines = {}
1848        super(ThreadLocalMetaData, self).__init__()
1849
1850    @util.deprecated('Deprecated. Use ``metadata.bind = <engine>`` or '
1851                     '``metadata.bind = <url>``.')
1852    def connect(self, bind, **kwargs):
1853        """Bind to an Engine in the caller's thread.
1854
1855        bind
1856          A string, ``URL``, ``Engine`` or ``Connection`` instance.  If a
1857          string or ``URL``, will be passed to ``create_engine()`` along with
1858          ``\**kwargs`` to produce the engine which to connect to.  Otherwise
1859          connects directly to the given ``Engine``.
1860        """
1861
1862        global URL
1863        if URL is None:
1864            from sqlalchemy.engine.url import URL
1865
1866        if isinstance(bind, (basestring, URL)):
1867            try:
1868                engine = self.__engines[bind]
1869            except KeyError:
1870                from sqlalchemy import create_engine
1871                engine = create_engine(bind, **kwargs)
1872            bind = engine
1873        self._bind_to(bind)
1874
1875    def bind(self):
1876        """The bound Engine or Connection for this thread.
1877
1878        This property may be assigned an Engine or Connection, or assigned a
1879        string or URL to automatically create a basic Engine for this bind
1880        with ``create_engine()``."""
1881
1882        return getattr(self.context, '_engine', None)
1883
1884    def _bind_to(self, bind):
1885        """Bind to a Connectable in the caller's thread."""
1886
1887        global URL
1888        if URL is None:
1889            from sqlalchemy.engine.url import URL
1890
1891        if isinstance(bind, (basestring, URL)):
1892            try:
1893                self.context._engine = self.__engines[bind]
1894            except KeyError:
1895                from sqlalchemy import create_engine
1896                e = create_engine(bind)
1897                self.__engines[bind] = e
1898                self.context._engine = e
1899        else:
1900            # TODO: this is squirrely.  we shouldnt have to hold onto engines
1901            # in a case like this
1902            if bind not in self.__engines:
1903                self.__engines[bind] = bind
1904            self.context._engine = bind
1905
1906    bind = property(bind, _bind_to)
1907
1908    def is_bound(self):
1909        """True if there is a bind for this thread."""
1910        return (hasattr(self.context, '_engine') and
1911                self.context._engine is not None)
1912
1913    def dispose(self):
1914        """Dispose all bound engines, in all thread contexts."""
1915
1916        for e in self.__engines.values():
1917            if hasattr(e, 'dispose'):
1918                e.dispose()
1919
1920class SchemaVisitor(visitors.ClauseVisitor):
1921    """Define the visiting for ``SchemaItem`` objects."""
1922
1923    __traverse_options__ = {'schema_visitor':True}
1924
1925
1926class DDL(object):
1927    """A literal DDL statement.
1928
1929    Specifies literal SQL DDL to be executed by the database.  DDL objects can
1930    be attached to ``Tables`` or ``MetaData`` instances, conditionally
1931    executing SQL as part of the DDL lifecycle of those schema items.  Basic
1932    templating support allows a single DDL instance to handle repetitive tasks
1933    for multiple tables.
1934
1935    Examples::
1936
1937      tbl = Table('users', metadata, Column('uid', Integer)) # ...
1938      DDL('DROP TRIGGER users_trigger').execute_at('before-create', tbl)
1939
1940      spow = DDL('ALTER TABLE %(table)s SET secretpowers TRUE', on='somedb')
1941      spow.execute_at('after-create', tbl)
1942
1943      drop_spow = DDL('ALTER TABLE users SET secretpowers FALSE')
1944      connection.execute(drop_spow)
1945    """
1946
1947    def __init__(self, statement, on=None, context=None, bind=None):
1948        """Create a DDL statement.
1949
1950        statement
1951          A string or unicode string to be executed.  Statements will be
1952          processed with Python's string formatting operator.  See the
1953          ``context`` argument and the ``execute_at`` method.
1954
1955          A literal '%' in a statement must be escaped as '%%'.
1956
1957          SQL bind parameters are not available in DDL statements.
1958
1959        on
1960          Optional filtering criteria.  May be a string or a callable
1961          predicate.  If a string, it will be compared to the name of the
1962          executing database dialect::
1963
1964            DDL('something', on='postgres')
1965
1966          If a callable, it will be invoked with three positional arguments:
1967
1968            event
1969              The name of the event that has triggered this DDL, such as
1970              'after-create' Will be None if the DDL is executed explicitly.
1971
1972            schema_item
1973              A SchemaItem instance, such as ``Table`` or ``MetaData``. May be
1974              None if the DDL is executed explicitly.
1975
1976            connection
1977              The ``Connection`` being used for DDL execution
1978
1979          If the callable returns a true value, the DDL statement will be
1980          executed.
1981
1982        context
1983          Optional dictionary, defaults to None.  These values will be
1984          available for use in string substitutions on the DDL statement.
1985
1986        bind
1987          Optional. A :class:`~sqlalchemy.engine.base.Connectable`, used by default when ``execute()``
1988          is invoked without a bind argument.
1989         
1990        """
1991
1992        if not isinstance(statement, basestring):
1993            raise exc.ArgumentError(
1994                "Expected a string or unicode SQL statement, got '%r'" %
1995                statement)
1996        if (on is not None and
1997            (not isinstance(on, basestring) and not util.callable(on))):
1998            raise exc.ArgumentError(
1999                "Expected the name of a database dialect or a callable for "
2000                "'on' criteria, got type '%s'." % type(on).__name__)
2001
2002        self.statement = statement
2003        self.on = on
2004        self.context = context or {}
2005        self._bind = bind
2006
2007    def execute(self, bind=None, schema_item=None):
2008        """Execute this DDL immediately.
2009
2010        Executes the DDL statement in isolation using the supplied
2011        :class:`~sqlalchemy.engine.base.Connectable` or :class:`~sqlalchemy.engine.base.Connectable` assigned to the ``.bind`` property,
2012        if not supplied.  If the DDL has a conditional ``on`` criteria, it
2013        will be invoked with None as the event.
2014
2015        bind
2016          Optional, an ``Engine`` or ``Connection``.  If not supplied, a
2017          valid :class:`~sqlalchemy.engine.base.Connectable` must be present in the ``.bind`` property.
2018
2019        schema_item
2020          Optional, defaults to None.  Will be passed to the ``on`` callable
2021          criteria, if any, and may provide string expansion data for the
2022          statement. See ``execute_at`` for more information.
2023        """
2024
2025        if bind is None:
2026            bind = _bind_or_error(self)
2027        # no SQL bind params are supported
2028        if self._should_execute(None, schema_item, bind):
2029            executable = expression.text(self._expand(schema_item, bind))
2030            return bind.execute(executable)
2031        else:
2032            bind.engine.logger.info("DDL execution skipped, criteria not met.")
2033
2034    def execute_at(self, event, schema_item):
2035        """Link execution of this DDL to the DDL lifecycle of a SchemaItem.
2036
2037        Links this ``DDL`` to a ``Table`` or ``MetaData`` instance, executing
2038        it when that schema item is created or dropped.  The DDL statement
2039        will be executed using the same Connection and transactional context
2040        as the Table create/drop itself.  The ``.bind`` property of this
2041        statement is ignored.
2042
2043        event
2044          One of the events defined in the schema item's ``.ddl_events``;
2045          e.g. 'before-create', 'after-create', 'before-drop' or 'after-drop'
2046
2047        schema_item
2048          A Table or MetaData instance
2049
2050        When operating on Table events, the following additional ``statement``
2051        string substitions are available::
2052
2053            %(table)s  - the Table name, with any required quoting applied
2054            %(schema)s - the schema name, with any required quoting applied
2055            %(fullname)s - the Table name including schema, quoted if needed
2056
2057        The DDL's ``context``, if any, will be combined with the standard
2058        substutions noted above.  Keys present in the context will override
2059        the standard substitutions.
2060
2061        A DDL instance can be linked to any number of schema items. The
2062        statement subsitution support allows for DDL instances to be used in a
2063        template fashion.
2064
2065        ``execute_at`` builds on the ``append_ddl_listener`` interface of
2066        MetaDta and Table objects.
2067
2068        Caveat: Creating or dropping a Table in isolation will also trigger
2069        any DDL set to ``execute_at`` that Table's MetaData.  This may change
2070        in a future release.
2071        """
2072
2073        if not hasattr(schema_item, 'ddl_listeners'):
2074            raise exc.ArgumentError(
2075                "%s does not support DDL events" % type(schema_item).__name__)
2076        if event not in schema_item.ddl_events:
2077            raise exc.ArgumentError(
2078                "Unknown event, expected one of (%s), got '%r'" %
2079                (', '.join(schema_item.ddl_events), event))
2080        schema_item.ddl_listeners[event].append(self)
2081        return self
2082
2083    def bind(self):
2084        """An Engine or Connection to which this DDL is bound.
2085
2086        This property may be assigned an ``Engine`` or ``Connection``, or
2087        assigned a string or URL to automatically create a basic ``Engine``
2088        for this bind with ``create_engine()``.
2089        """
2090        return self._bind
2091
2092    def _bind_to(self, bind):
2093        """Bind this MetaData to an Engine, Connection, string or URL."""
2094
2095        global URL
2096        if URL is None:
2097            from sqlalchemy.engine.url import URL
2098
2099        if isinstance(bind, (basestring, URL)):
2100            from sqlalchemy import create_engine
2101            self._bind = create_engine(bind)
2102        else:
2103            self._bind = bind
2104    bind = property(bind, _bind_to)
2105
2106    def __call__(self, event, schema_item, bind):
2107        """Execute the DDL as a ddl_listener."""
2108
2109        if self._should_execute(event, schema_item, bind):
2110            statement = expression.text(self._expand(schema_item, bind))
2111            return bind.execute(statement)
2112
2113    def _expand(self, schema_item, bind):
2114        return self.statement % self._prepare_context(schema_item, bind)
2115
2116    def _should_execute(self, event, schema_item, bind):
2117        if self.on is None:
2118            return True
2119        elif isinstance(self.on, basestring):
2120            return self.on == bind.engine.name
2121        else:
2122            return self.on(event, schema_item, bind)
2123
2124    def _prepare_context(self, schema_item, bind):
2125        # table events can substitute table and schema name
2126        if isinstance(schema_item, Table):
2127            context = self.context.copy()
2128
2129            preparer = bind.dialect.identifier_preparer
2130            path = preparer.format_table_seq(schema_item)
2131            if len(path) == 1:
2132                table, schema = path[0], ''
2133            else:
2134                table, schema = path[-1], path[0]
2135
2136            context.setdefault('table', table)
2137            context.setdefault('schema', schema)
2138            context.setdefault('fullname', preparer.format_table(schema_item))
2139            return context
2140        else:
2141            return self.context
2142
2143    def __repr__(self):
2144        return '<%s@%s; %s>' % (
2145            type(self).__name__, id(self),
2146            ', '.join([repr(self.statement)] +
2147                      ['%s=%r' % (key, getattr(self, key))
2148                       for key in ('on', 'context')
2149                       if getattr(self, key)]))
2150
2151def _to_schema_column(element):
2152    if hasattr(element, '__clause_element__'):
2153        element = element.__clause_element__()
2154    if not isinstance(element, Column):
2155        raise exc.ArgumentError("schema.Column object expected")
2156    return element
2157   
2158def _bind_or_error(schemaitem):
2159    bind = schemaitem.bind
2160    if not bind:
2161        name = schemaitem.__class__.__name__
2162        label = getattr(schemaitem, 'fullname',
2163                        getattr(schemaitem, 'name', None))
2164        if label:
2165            item = '%s %r' % (name, label)
2166        else:
2167            item = name
2168        if isinstance(schemaitem, (MetaData, DDL)):
2169            bindable = "the %s's .bind" % name
2170        else:
2171            bindable = "this %s's .metadata.bind" % name
2172
2173        msg = ('The %s is not bound to an Engine or Connection.  '
2174               'Execution can not proceed without a database to execute '
2175               'against.  Either execute with an explicit connection or '
2176               'assign %s to enable implicit execution.') % (item, bindable)
2177        raise exc.UnboundExecutionError(msg)
2178    return bind
2179
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。