1 | """ |
---|
2 | Oracle database specific implementations of changeset classes. |
---|
3 | """ |
---|
4 | |
---|
5 | from migrate.changeset import ansisql, exceptions |
---|
6 | from sqlalchemy.databases import oracle as sa_base |
---|
7 | import sqlalchemy as sa |
---|
8 | |
---|
9 | OracleSchemaGenerator = sa_base.OracleSchemaGenerator |
---|
10 | |
---|
11 | |
---|
12 | class OracleColumnGenerator(OracleSchemaGenerator, |
---|
13 | ansisql.ANSIColumnGenerator): |
---|
14 | pass |
---|
15 | |
---|
16 | |
---|
17 | class OracleColumnDropper(ansisql.ANSIColumnDropper): |
---|
18 | pass |
---|
19 | |
---|
20 | |
---|
21 | class OracleSchemaChanger(OracleSchemaGenerator, ansisql.ANSISchemaChanger): |
---|
22 | |
---|
23 | def get_column_specification(self, column, **kwargs): |
---|
24 | # Ignore the NOT NULL generated |
---|
25 | override_nullable = kwargs.pop('override_nullable', None) |
---|
26 | if override_nullable: |
---|
27 | orig = column.nullable |
---|
28 | column.nullable = True |
---|
29 | ret = super(OracleSchemaChanger, self).get_column_specification( |
---|
30 | column, **kwargs) |
---|
31 | if override_nullable: |
---|
32 | column.nullable = orig |
---|
33 | return ret |
---|
34 | |
---|
35 | def visit_column(self, delta): |
---|
36 | keys = delta.keys() |
---|
37 | if 'type' in keys or 'nullable' in keys or 'default' in keys \ |
---|
38 | or 'server_default' in keys: |
---|
39 | self._run_subvisit(delta, self._visit_column_change) |
---|
40 | if 'name' in keys: |
---|
41 | self._run_subvisit(delta, self._visit_column_name) |
---|
42 | |
---|
43 | def _visit_column_change(self, table_name, col_name, delta): |
---|
44 | if not hasattr(delta, 'result_column'): |
---|
45 | # Oracle needs the whole column definition, not just a |
---|
46 | # lone name/type |
---|
47 | raise exceptions.NotSupportedError( |
---|
48 | "A column object is required to do this") |
---|
49 | |
---|
50 | column = delta.result_column |
---|
51 | # Oracle cannot drop a default once created, but it can set it |
---|
52 | # to null. We'll do that if default=None |
---|
53 | # http://forums.oracle.com/forums/message.jspa?\ |
---|
54 | # messageID=1273234#1273234 |
---|
55 | dropdefault_hack = (column.server_default is None \ |
---|
56 | and 'server_default' in delta.keys()) |
---|
57 | # Oracle apparently doesn't like it when we say "not null" if |
---|
58 | # the column's already not null. Fudge it, so we don't need a |
---|
59 | # new function |
---|
60 | notnull_hack = ((not column.nullable) \ |
---|
61 | and ('nullable' not in delta.keys())) |
---|
62 | # We need to specify NULL if we're removing a NOT NULL |
---|
63 | # constraint |
---|
64 | null_hack = (column.nullable and ('nullable' in delta.keys())) |
---|
65 | |
---|
66 | if dropdefault_hack: |
---|
67 | column.server_default = sa.PassiveDefault(sa.sql.null()) |
---|
68 | if notnull_hack: |
---|
69 | column.nullable = True |
---|
70 | colspec=self.get_column_specification(column, |
---|
71 | override_nullable=null_hack) |
---|
72 | if null_hack: |
---|
73 | colspec += ' NULL' |
---|
74 | if notnull_hack: |
---|
75 | column.nullable = False |
---|
76 | if dropdefault_hack: |
---|
77 | column.server_default = None |
---|
78 | |
---|
79 | self.start_alter_table(table_name) |
---|
80 | self.append("MODIFY ") |
---|
81 | self.append(colspec) |
---|
82 | |
---|
83 | |
---|
84 | class OracleConstraintCommon(object): |
---|
85 | |
---|
86 | def get_constraint_name(self, cons): |
---|
87 | # Oracle constraints can't guess their name like other DBs |
---|
88 | if not cons.name: |
---|
89 | raise exceptions.NotSupportedError( |
---|
90 | "Oracle constraint names must be explicitly stated") |
---|
91 | return cons.name |
---|
92 | |
---|
93 | |
---|
94 | class OracleConstraintGenerator(OracleConstraintCommon, |
---|
95 | ansisql.ANSIConstraintGenerator): |
---|
96 | pass |
---|
97 | |
---|
98 | |
---|
99 | class OracleConstraintDropper(OracleConstraintCommon, |
---|
100 | ansisql.ANSIConstraintDropper): |
---|
101 | pass |
---|
102 | |
---|
103 | |
---|
104 | class OracleDialect(ansisql.ANSIDialect): |
---|
105 | columngenerator = OracleColumnGenerator |
---|
106 | columndropper = OracleColumnDropper |
---|
107 | schemachanger = OracleSchemaChanger |
---|
108 | constraintgenerator = OracleConstraintGenerator |
---|
109 | constraintdropper = OracleConstraintDropper |
---|