From: Mike Bayer Date: Tue, 29 Nov 2011 03:28:28 +0000 (-0500) Subject: - [feature] Added create_type constructor argument X-Git-Tag: rel_0_7_4~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b854074c6dd93cfeb4c5335a4469c700c4d47f04;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [feature] Added create_type constructor argument to pg.ENUM. When False, no CREATE/DROP or checking for the type will be performed as part of a table create/drop event; only the create()/drop)() methods called directly will do this. Helps with Alembic "offline" scripts. --- diff --git a/CHANGES b/CHANGES index f3793cfc33..04e45d97d5 100644 --- a/CHANGES +++ b/CHANGES @@ -138,6 +138,14 @@ CHANGES "checkfirst" turned on it only needs to check for the ENUM once. [ticket:2311] + - [feature] Added create_type constructor argument + to pg.ENUM. When False, no CREATE/DROP or + checking for the type will be performed as part + of a table create/drop event; only the + create()/drop)() methods called directly + will do this. Helps with Alembic "offline" + scripts. + - mysql - [bug] Unicode adjustments allow latest pymysql (post 0.4) to pass 100% on Python 2. diff --git a/doc/build/core/types.rst b/doc/build/core/types.rst index 4e55b25d73..b7b4e3488c 100644 --- a/doc/build/core/types.rst +++ b/doc/build/core/types.rst @@ -58,7 +58,7 @@ Standard Types`_ and the other sections of this chapter. .. autoclass:: Enum :show-inheritance: - :members: + :members: __init__, create, drop .. autoclass:: Float :show-inheritance: diff --git a/doc/build/dialects/postgresql.rst b/doc/build/dialects/postgresql.rst index 6e45992eb7..b34c076848 100644 --- a/doc/build/dialects/postgresql.rst +++ b/doc/build/dialects/postgresql.rst @@ -44,7 +44,7 @@ construction arguments, are as follows: :show-inheritance: .. autoclass:: ENUM - :members: __init__ + :members: __init__, create, drop :show-inheritance: .. autoclass:: INET diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index e3beeab79c..673b86add2 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -432,8 +432,74 @@ class ARRAY(sqltypes.MutableType, sqltypes.Concatenable, sqltypes.TypeEngine): PGArray = ARRAY class ENUM(sqltypes.Enum): + """Postgresql ENUM type. + + This is a subclass of :class:`.types.Enum` which includes + support for PG's ``CREATE TYPE``. + + :class:`~.postgresql.ENUM` is used automatically when + using the :class:`.types.Enum` type on PG assuming + the ``native_enum`` is left as ``True``. However, the + :class:`~.postgresql.ENUM` class can also be instantiated + directly in order to access some additional Postgresql-specific + options, namely finer control over whether or not + ``CREATE TYPE`` should be emitted. + + Note that both :class:`.types.Enum` as well as + :class:`~.postgresql.ENUM` feature create/drop + methods; the base :class:`.types.Enum` type ultimately + delegates to the :meth:`~.postgresql.ENUM.create` and + :meth:`~.postgresql.ENUM.drop` methods present here. + + """ + + def __init__(self, *enums, **kw): + """Construct an :class:`~.postgresql.ENUM`. + + Arguments are the same as that of + :class:`.types.Enum`, but also including + the following parameters. + + :param create_type: Defaults to True. + Indicates that ``CREATE TYPE`` should be + emitted, after optionally checking for the + presence of the type, when the parent + table is being created; and additionally + that ``DROP TYPE`` is called when the table + is dropped. When ``False``, no check + will be performed and no ``CREATE TYPE`` + or ``DROP TYPE`` is emitted, unless + :meth:`~.postgresql.ENUM.create` + or :meth:`~.postgresql.ENUM.drop` + are called directly. + Setting to ``False`` is helpful + when invoking a creation scheme to a SQL file + without access to the actual database - + the :meth:`~.postgresql.ENUM.create` and + :meth:`~.postgresql.ENUM.drop` methods can + be used to emit SQL to a target bind. + (new in 0.7.4) + + """ + self.create_type = kw.pop("create_type", True) + super(ENUM, self).__init__(*enums, **kw) def create(self, bind=None, checkfirst=True): + """Emit ``CREATE TYPE`` for this + :class:`~.postgresql.ENUM`. + + If the underlying dialect does not support + Postgresql CREATE TYPE, no action is taken. + + :param bind: a connectable :class:`.Engine`, + :class:`.Connection`, or similar object to emit + SQL. + :param checkfirst: if ``True``, a query against + the PG catalog will be first performed to see + if the type does not exist already before + creating. + + """ if not bind.dialect.supports_native_enum: return @@ -442,6 +508,20 @@ class ENUM(sqltypes.Enum): bind.execute(CreateEnumType(self)) def drop(self, bind=None, checkfirst=True): + """Emit ``DROP TYPE`` for this + :class:`~.postgresql.ENUM`. + + If the underlying dialect does not support + Postgresql DROP TYPE, no action is taken. + + :param bind: a connectable :class:`.Engine`, + :class:`.Connection`, or similar object to emit + SQL. + :param checkfirst: if ``True``, a query against + the PG catalog will be first performed to see + if the type actually exists before dropping. + + """ if not bind.dialect.supports_native_enum: return @@ -458,7 +538,8 @@ class ENUM(sqltypes.Enum): sequence without relying upon "checkfirst". """ - + if not self.create_type: + return True if '_ddl_runner' in kw: ddl_runner = kw['_ddl_runner'] if '_pg_enums' in ddl_runner.memo: diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 79799da8f3..136de147ee 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -1784,6 +1784,12 @@ class Enum(String, SchemaType): By default, uses the backend's native ENUM type if available, else uses VARCHAR + a CHECK constraint. + + See also: + + :class:`~.postgresql.ENUM` - PostgreSQL-specific type, + which has additional functionality. + """ __visit_name__ = 'enum' diff --git a/test/dialect/test_postgresql.py b/test/dialect/test_postgresql.py index b4b7e818cd..7279508ba9 100644 --- a/test/dialect/test_postgresql.py +++ b/test/dialect/test_postgresql.py @@ -450,6 +450,24 @@ class EnumTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiledSQL): finally: metadata.drop_all(testing.db) + @testing.provide_metadata + def test_disable_create(self): + metadata = self.metadata + + e1 = postgresql.ENUM('one', 'two', 'three', + name="myenum", + create_type=False) + + t1 = Table('e1', metadata, + Column('c1', e1) + ) + # table can be created separately + # without conflict + e1.create(bind=testing.db) + t1.create(testing.db) + t1.drop(testing.db) + e1.drop(bind=testing.db) + @testing.provide_metadata def test_generate_multiple(self): """Test that the same enum twice only generates once