]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
illustrate the basic idea of add_xxx(strings), whereby Table/Column/Constraint objects
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 26 Apr 2010 04:20:57 +0000 (00:20 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 26 Apr 2010 04:20:57 +0000 (00:20 -0400)
are just generated in order to produce the DDL.   I'm not entirely
thrilled with this - would be nicer if we could get sqlalchemy.schema constructs
to generate with strings alone - but this would change their signatures.  so we're sort
of doing that here anyway.

alembic/command.py
alembic/context.py
alembic/op.py
alembic/util.py
tests/test_schema.py [new file with mode: 0644]

index 5110db26e2ba840620567d51f560b1350dcbd7db..9e79c0709307c2dd11cd25bd8cb34f195059cfc4 100644 (file)
@@ -14,7 +14,7 @@ def list_templates(opts):
                         tempname, 
                         'README')
         synopsis = open(readme).next()
-        print options.format_opt(tempname, synopsis)
+        print util.format_opt(tempname, synopsis)
     
     print "\nTemplates are used via the 'init' command, e.g.:"
     print "\n  alembic init --template pylons ./scripts"
index 27771daae1a6d8f149ed3eb866b51a9fbe89bcbd..a919c07baf8407cc089fa27d451a2871d8976b8b 100644 (file)
@@ -1,4 +1,5 @@
 from alembic.ddl import base
+from alembic import util
 
 class ContextMeta(type):
     def __init__(cls, classname, bases, dict_):
@@ -15,17 +16,25 @@ class DefaultContext(object):
     def __init__(self, options, connection):
         self.options = options
         self.connection = connection
+    
+    def _exec(self, construct):
+        pass
         
     def alter_column(self, table_name, column_name, 
-                        nullable=NO_VALUE,
-                        server_default=NO_VALUE,
-                        name=NO_VALUE,
-                        type=NO_VALUE
+                        nullable=util.NO_VALUE,
+                        server_default=util.NO_VALUE,
+                        name=util.NO_VALUE,
+                        type=util.NO_VALUE
     ):
     
-        if nullable is not NO_VALUE:
-            base.ColumnNullable(table_name, column_name, nullable)
-        if server_default is not NO_VALUE:
-            base.ColumnDefault(table_name, column_name, server_default)
+        if nullable is not util.NO_VALUE:
+            self._exec(base.ColumnNullable(table_name, column_name, nullable))
+        if server_default is not util.NO_VALUE:
+            self._exec(base.ColumnDefault(table_name, column_name, server_default))
     
-        # ... etc
\ No newline at end of file
+        # ... etc
+        
+    def add_constraint(self, const):
+        self._exec(schema.AddConstraint(const))
+
+        
\ No newline at end of file
index 6a31c4f079872933b4e5c08e33ad8fc97724ebf6..16fc1ab71b0c7648144503416f6e2427d33a3492 100644 (file)
@@ -1,12 +1,14 @@
-from sqlalchemy import util
+from alembic import util
+from sqlalchemy.types import NULLTYPE
+from sqlalchemy import schema
 
-NO_VALUE = util.symbol("NO_VALUE")
+__all__ = ['alter_column', 'add_foreign_key']
 
 def alter_column(table_name, column_name, 
-                    nullable=NO_VALUE,
-                    server_default=NO_VALUE,
-                    name=NO_VALUE,
-                    type_=NO_VALUE
+                    nullable=util.NO_VALUE,
+                    server_default=util.NO_VALUE,
+                    name=util.NO_VALUE,
+                    type_=util.NO_VALUE
 ):
     """Issue ALTER COLUMN using the current change context."""
     
@@ -16,3 +18,34 @@ def alter_column(table_name, column_name,
         name=name,
         type_=type_
     )
+
+
+def _foreign_key_constraint(name, source, referent, local_cols, remote_cols):
+    m = schema.MetaData()
+    t1 = schema.Table(source, m, 
+            *[schema.Column(n, NULLTYPE) for n in local_cols])
+    t2 = schema.Table(referent, m, 
+            *[schema.Column(n, NULLTYPE) for n in remote_cols])
+
+    f = schema.ForeignKeyConstraint(local_cols, 
+                                        ["%s.%s" % (referent, name) 
+                                        for name in remote_cols],
+                                        name=name
+                                        )
+    t1.append_constraint(f)
+    return f
+
+def _unique_constraint(name, source, local_cols):
+    t = schema.Table(source, schema.MetaData(), 
+                *[schema.Column(n, NULLTYPE) for n in local_cols])
+    return schema.UniqueConstraint(*t.c, name=name)
+    
+def create_foreign_key(name, source, referent, local_cols, remote_cols):
+    context.add_constraint(
+                _foreign_key_constraint(source, referent, local_cols, remote_cols)
+            )
+
+def create_unique_constraint(name, source, local_cols):
+    context.add_constraint(
+                _unique_constraint(name, source, local_cols)
+            )
index a7ae885219c587dc9f1fd5cf40d5655112d8a2bb..54004bdbe7f84d98483785b7f162cd9bfe7bd5e6 100644 (file)
@@ -2,6 +2,10 @@ from mako.template import Template
 import sys
 import os
 import textwrap
+from sqlalchemy import util
+
+NO_VALUE = util.symbol("NO_VALUE")
+
 
 def template_to_file(template_file, dest, **kw):
     f = open(dest, 'w')
diff --git a/tests/test_schema.py b/tests/test_schema.py
new file mode 100644 (file)
index 0000000..5ba4fc9
--- /dev/null
@@ -0,0 +1,18 @@
+from tests import assert_compiled
+from alembic import op
+from sqlalchemy.schema import AddConstraint, ForeignKeyConstraint
+
+def test_foreign_key():
+    fk = op._foreign_key_constraint('fk_test', 't1', 't2', ['foo', 'bar'], ['bat', 'hoho'])
+    assert_compiled(
+        AddConstraint(fk),
+        "ALTER TABLE t1 ADD CONSTRAINT hoho FOREIGN KEY(foo, bar) REFERENCES t2 (bat, hoho)"
+    )
+    
+def test_unique_constraint():
+    uc = op._unique_constraint('uk_test', 't1', ['foo', 'bar'])
+    assert_compiled(
+        AddConstraint(uc),
+        "ALTER TABLE t1 ADD CONSTRAINT uk_test UNIQUE (foo, bar)"
+    )
+    
\ No newline at end of file