Show More
@@ -2,7 +2,7 b'' | |||
|
2 | 2 | Firebird database specific implementations of changeset classes. |
|
3 | 3 | """ |
|
4 | 4 | from sqlalchemy.databases import firebird as sa_base |
|
5 | ||
|
5 | from sqlalchemy.schema import PrimaryKeyConstraint | |
|
6 | 6 | from rhodecode.lib.dbmigrate.migrate import exceptions |
|
7 | 7 | from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06 |
|
8 | 8 | |
@@ -27,13 +27,32 b' class FBColumnDropper(ansisql.ANSIColumn' | |||
|
27 | 27 | if column.table.primary_key.columns.contains_column(column): |
|
28 | 28 | column.table.primary_key.drop() |
|
29 | 29 | # TODO: recreate primary key if it references more than this column |
|
30 | if column.unique or getattr(column, 'unique_name', None): | |
|
30 | ||
|
31 | for index in column.table.indexes: | |
|
32 | # "column in index.columns" causes problems as all | |
|
33 | # column objects compare equal and return a SQL expression | |
|
34 | if column.name in [col.name for col in index.columns]: | |
|
35 | index.drop() | |
|
36 | # TODO: recreate index if it references more than this column | |
|
37 | ||
|
31 | 38 |
|
|
32 | if cons.contains_column(column): | |
|
33 | cons.drop() | |
|
39 | if isinstance(cons,PrimaryKeyConstraint): | |
|
40 | # will be deleted only when the column its on | |
|
41 | # is deleted! | |
|
42 | continue | |
|
43 | ||
|
44 | if SQLA_06: | |
|
45 | should_drop = column.name in cons.columns | |
|
46 | else: | |
|
47 | should_drop = cons.contains_column(column) and cons.name | |
|
48 | if should_drop: | |
|
49 | self.start_alter_table(column) | |
|
50 | self.append("DROP CONSTRAINT ") | |
|
51 | self.append(self.preparer.format_constraint(cons)) | |
|
52 | self.execute() | |
|
34 | 53 |
|
|
35 | 54 | |
|
36 |
|
|
|
55 | self.start_alter_table(column) | |
|
37 | 56 | self.append('DROP %s' % self.preparer.format_column(column)) |
|
38 | 57 | self.execute() |
|
39 | 58 |
@@ -80,10 +80,17 b' class SQLiteColumnDropper(SQLiteHelper, ' | |||
|
80 | 80 | """SQLite ColumnDropper""" |
|
81 | 81 | |
|
82 | 82 | def _modify_table(self, table, column, delta): |
|
83 | ||
|
83 | 84 | columns = ' ,'.join(map(self.preparer.format_column, table.columns)) |
|
84 | 85 | return 'INSERT INTO %(table_name)s SELECT ' + columns + \ |
|
85 | 86 | ' from migration_tmp' |
|
86 | 87 | |
|
88 | def visit_column(self,column): | |
|
89 | # For SQLite, we *have* to remove the column here so the table | |
|
90 | # is re-created properly. | |
|
91 | column.remove_from_table(column.table,unset_table=False) | |
|
92 | super(SQLiteColumnDropper,self).visit_column(column) | |
|
93 | ||
|
87 | 94 | |
|
88 | 95 | class SQLiteSchemaChanger(SQLiteHelper, ansisql.ANSISchemaChanger): |
|
89 | 96 | """SQLite SchemaChanger""" |
@@ -29,9 +29,6 b' from rhodecode.lib.dbmigrate.migrate.cha' | |||
|
29 | 29 | 'ColumnDelta', |
|
30 | 30 | ] |
|
31 | 31 | |
|
32 | DEFAULT_ALTER_METADATA = True | |
|
33 | ||
|
34 | ||
|
35 | 32 | def create_column(column, table=None, *p, **kw): |
|
36 | 33 | """Create a column, given the table. |
|
37 | 34 | |
@@ -109,19 +106,11 b' def alter_column(*p, **k):' | |||
|
109 | 106 | The :class:`~sqlalchemy.engine.base.Engine` to use for table |
|
110 | 107 | reflection and schema alterations. |
|
111 | 108 | |
|
112 | :param alter_metadata: | |
|
113 | If `True`, which is the default, the | |
|
114 | :class:`~sqlalchemy.schema.Column` will also modified. | |
|
115 | If `False`, the :class:`~sqlalchemy.schema.Column` will be left | |
|
116 | as it was. | |
|
117 | ||
|
118 | 109 | :returns: A :class:`ColumnDelta` instance representing the change. |
|
119 | 110 | |
|
120 | 111 | |
|
121 | 112 | """ |
|
122 | 113 | |
|
123 | k.setdefault('alter_metadata', DEFAULT_ALTER_METADATA) | |
|
124 | ||
|
125 | 114 | if 'table' not in k and isinstance(p[0], sqlalchemy.Column): |
|
126 | 115 | k['table'] = p[0].table |
|
127 | 116 | if 'engine' not in k: |
@@ -135,6 +124,12 b' def alter_column(*p, **k):' | |||
|
135 | 124 | MigrateDeprecationWarning |
|
136 | 125 | ) |
|
137 | 126 | engine = k['engine'] |
|
127 | ||
|
128 | # enough tests seem to break when metadata is always altered | |
|
129 | # that this crutch has to be left in until they can be sorted | |
|
130 | # out | |
|
131 | k['alter_metadata']=True | |
|
132 | ||
|
138 | 133 | delta = ColumnDelta(*p, **k) |
|
139 | 134 | |
|
140 | 135 | visitorcallable = get_engine_visitor(engine, 'schemachanger') |
@@ -188,11 +183,10 b' class ColumnDelta(DictMixin, sqlalchemy.' | |||
|
188 | 183 | :param table: Table at which current Column should be bound to.\ |
|
189 | 184 | If table name is given, reflection will be used. |
|
190 | 185 | :type table: string or Table instance |
|
191 | :param alter_metadata: If True, it will apply changes to metadata. | |
|
192 | :type alter_metadata: bool | |
|
193 | :param metadata: If `alter_metadata` is true, \ | |
|
194 | metadata is used to reflect table names into | |
|
195 | :type metadata: :class:`MetaData` instance | |
|
186 | ||
|
187 | :param metadata: A :class:`MetaData` instance to store | |
|
188 | reflected table names | |
|
189 | ||
|
196 | 190 | :param engine: When reflecting tables, either engine or metadata must \ |
|
197 | 191 | be specified to acquire engine object. |
|
198 | 192 | :type engine: :class:`Engine` instance |
@@ -213,7 +207,11 b' class ColumnDelta(DictMixin, sqlalchemy.' | |||
|
213 | 207 | __visit_name__ = 'column' |
|
214 | 208 | |
|
215 | 209 | def __init__(self, *p, **kw): |
|
210 | # 'alter_metadata' is not a public api. It exists purely | |
|
211 | # as a crutch until the tests that fail when 'alter_metadata' | |
|
212 | # behaviour always happens can be sorted out | |
|
216 | 213 | self.alter_metadata = kw.pop("alter_metadata", False) |
|
214 | ||
|
217 | 215 | self.meta = kw.pop("metadata", None) |
|
218 | 216 | self.engine = kw.pop("engine", None) |
|
219 | 217 | |
@@ -237,8 +235,10 b' class ColumnDelta(DictMixin, sqlalchemy.' | |||
|
237 | 235 | self.apply_diffs(diffs) |
|
238 | 236 | |
|
239 | 237 | def __repr__(self): |
|
240 |
return '<ColumnDelta altermetadata=%r, %s>' % ( |
|
|
241 | super(ColumnDelta, self).__repr__()) | |
|
238 | return '<ColumnDelta altermetadata=%r, %s>' % ( | |
|
239 | self.alter_metadata, | |
|
240 | super(ColumnDelta, self).__repr__() | |
|
241 | ) | |
|
242 | 242 | |
|
243 | 243 | def __getitem__(self, key): |
|
244 | 244 | if key not in self.keys(): |
@@ -395,7 +395,6 b' class ColumnDelta(DictMixin, sqlalchemy.' | |||
|
395 | 395 | self._table = table |
|
396 | 396 | if not self.alter_metadata: |
|
397 | 397 | self._table.meta = sqlalchemy.MetaData(bind=self._table.bind) |
|
398 | ||
|
399 | 398 | def _get_result_column(self): |
|
400 | 399 | return getattr(self, '_result_column', None) |
|
401 | 400 | |
@@ -456,19 +455,15 b' class ChangesetTable(object):' | |||
|
456 | 455 | |
|
457 | 456 | :param name: New name of the table. |
|
458 | 457 | :type name: string |
|
459 | :param alter_metadata: If True, table will be removed from metadata | |
|
460 | :type alter_metadata: bool | |
|
461 | 458 | :param connection: reuse connection istead of creating new one. |
|
462 | 459 | :type connection: :class:`sqlalchemy.engine.base.Connection` instance |
|
463 | 460 | """ |
|
464 | self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA) | |
|
465 | 461 | engine = self.bind |
|
466 | 462 | self.new_name = name |
|
467 | 463 | visitorcallable = get_engine_visitor(engine, 'schemachanger') |
|
468 | 464 | run_single_visitor(engine, visitorcallable, self, connection, **kwargs) |
|
469 | 465 | |
|
470 | 466 | # Fix metadata registration |
|
471 | if self.alter_metadata: | |
|
472 | 467 |
|
|
473 | 468 |
|
|
474 | 469 |
|
@@ -510,7 +505,6 b' class ChangesetColumn(object):' | |||
|
510 | 505 | `~migrate.changeset.constraint.UniqueConstraint` on this column. |
|
511 | 506 | :param primary_key_name: Creates :class:\ |
|
512 | 507 | `~migrate.changeset.constraint.PrimaryKeyConstraint` on this column. |
|
513 | :param alter_metadata: If True, column will be added to table object. | |
|
514 | 508 | :param populate_default: If True, created column will be \ |
|
515 | 509 | populated with defaults |
|
516 | 510 | :param connection: reuse connection istead of creating new one. |
@@ -518,21 +512,18 b' populated with defaults' | |||
|
518 | 512 | :type index_name: string |
|
519 | 513 | :type unique_name: string |
|
520 | 514 | :type primary_key_name: string |
|
521 | :type alter_metadata: bool | |
|
522 | 515 | :type populate_default: bool |
|
523 | 516 | :type connection: :class:`sqlalchemy.engine.base.Connection` instance |
|
524 | 517 | |
|
525 | 518 | :returns: self |
|
526 | 519 | """ |
|
527 | 520 | self.populate_default = populate_default |
|
528 | self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA) | |
|
529 | 521 | self.index_name = index_name |
|
530 | 522 | self.unique_name = unique_name |
|
531 | 523 | self.primary_key_name = primary_key_name |
|
532 | 524 | for cons in ('index_name', 'unique_name', 'primary_key_name'): |
|
533 | 525 | self._check_sanity_constraints(cons) |
|
534 | 526 | |
|
535 | if self.alter_metadata: | |
|
536 | 527 |
|
|
537 | 528 | engine = self.table.bind |
|
538 | 529 | visitorcallable = get_engine_visitor(engine, 'columngenerator') |
@@ -550,20 +541,15 b' populated with defaults' | |||
|
550 | 541 | |
|
551 | 542 | ``ALTER TABLE DROP COLUMN``, for most databases. |
|
552 | 543 | |
|
553 | :param alter_metadata: If True, column will be removed from table object. | |
|
554 | :type alter_metadata: bool | |
|
555 | 544 | :param connection: reuse connection istead of creating new one. |
|
556 | 545 | :type connection: :class:`sqlalchemy.engine.base.Connection` instance |
|
557 | 546 | """ |
|
558 | self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA) | |
|
559 | 547 | if table is not None: |
|
560 | 548 | self.table = table |
|
561 | 549 | engine = self.table.bind |
|
562 | if self.alter_metadata: | |
|
563 | self.remove_from_table(self.table, unset_table=False) | |
|
564 | 550 | visitorcallable = get_engine_visitor(engine, 'columndropper') |
|
565 | 551 | engine._run_visitor(visitorcallable, self, connection, **kwargs) |
|
566 | if self.alter_metadata: | |
|
552 | self.remove_from_table(self.table, unset_table=False) | |
|
567 | 553 |
|
|
568 | 554 | return self |
|
569 | 555 | |
@@ -643,17 +629,13 b' class ChangesetIndex(object):' | |||
|
643 | 629 | |
|
644 | 630 | :param name: New name of the Index. |
|
645 | 631 | :type name: string |
|
646 | :param alter_metadata: If True, Index object will be altered. | |
|
647 | :type alter_metadata: bool | |
|
648 | 632 | :param connection: reuse connection istead of creating new one. |
|
649 | 633 | :type connection: :class:`sqlalchemy.engine.base.Connection` instance |
|
650 | 634 | """ |
|
651 | self.alter_metadata = kwargs.pop('alter_metadata', DEFAULT_ALTER_METADATA) | |
|
652 | 635 | engine = self.table.bind |
|
653 | 636 | self.new_name = name |
|
654 | 637 | visitorcallable = get_engine_visitor(engine, 'schemachanger') |
|
655 | 638 | engine._run_visitor(visitorcallable, self, connection, **kwargs) |
|
656 | if self.alter_metadata: | |
|
657 | 639 |
|
|
658 | 640 | |
|
659 | 641 |
@@ -169,11 +169,11 b' class ModelGenerator(object):' | |||
|
169 | 169 | modelTable, col.name)) |
|
170 | 170 | for modelCol, databaseCol, modelDecl, databaseDecl in diffDecl: |
|
171 | 171 | upgradeCommands.append( |
|
172 |
'assert False, "Can\'t alter columns: %s:%s=>%s"' |
|
|
173 | modelTable, modelCol.name, databaseCol.name) | |
|
172 | 'assert False, "Can\'t alter columns: %s:%s=>%s"' % ( | |
|
173 | modelTable, modelCol.name, databaseCol.name)) | |
|
174 | 174 | downgradeCommands.append( |
|
175 |
'assert False, "Can\'t alter columns: %s:%s=>%s"' |
|
|
176 | modelTable, modelCol.name, databaseCol.name) | |
|
175 | 'assert False, "Can\'t alter columns: %s:%s=>%s"' % ( | |
|
176 | modelTable, modelCol.name, databaseCol.name)) | |
|
177 | 177 | pre_command = ' meta.bind = migrate_engine' |
|
178 | 178 | |
|
179 | 179 | return ( |
@@ -4,6 +4,7 b'' | |||
|
4 | 4 | import shutil |
|
5 | 5 | import warnings |
|
6 | 6 | import logging |
|
7 | import inspect | |
|
7 | 8 | from StringIO import StringIO |
|
8 | 9 | |
|
9 | 10 | from rhodecode.lib.dbmigrate import migrate |
@@ -136,12 +137,12 b' class PythonScript(base.BaseScript):' | |||
|
136 | 137 | funcname = base.operations[op] |
|
137 | 138 | script_func = self._func(funcname) |
|
138 | 139 | |
|
139 | try: | |
|
140 | # check for old way of using engine | |
|
141 | if not inspect.getargspec(script_func)[0]: | |
|
142 | raise TypeError("upgrade/downgrade functions must accept engine" | |
|
143 | " parameter (since version 0.5.4)") | |
|
144 | ||
|
140 | 145 |
|
|
141 | except TypeError: | |
|
142 | warnings.warn("upgrade/downgrade functions must accept engine" | |
|
143 | " parameter (since version > 0.5.4)", MigrateDeprecationWarning) | |
|
144 | raise | |
|
145 | 146 | |
|
146 | 147 | @property |
|
147 | 148 | def module(self): |
@@ -18,6 +18,7 b' class SqlScript(base.BaseScript):' | |||
|
18 | 18 | |
|
19 | 19 | :returns: :class:`SqlScript instance <migrate.versioning.script.sql.SqlScript>`""" |
|
20 | 20 | cls.require_notfound(path) |
|
21 | ||
|
21 | 22 | src = Template(opts.pop('templates_path', None)).get_sql_script(theme=opts.pop('templates_theme', None)) |
|
22 | 23 | shutil.copy(src, path) |
|
23 | 24 | return cls(path) |
@@ -77,8 +77,7 b' def main(argv=None, **kwargs):' | |||
|
77 | 77 | %s |
|
78 | 78 | |
|
79 | 79 | Enter "%%prog help COMMAND" for information on a particular command. |
|
80 | """ % '\n\t'.join(["%s - %s" % (command.ljust(28), | |
|
81 | api.command_desc.get(command)) for command in commands]) | |
|
80 | """ % '\n\t'.join(["%s - %s" % (command.ljust(28), api.command_desc.get(command)) for command in commands]) | |
|
82 | 81 | |
|
83 | 82 | parser = PassiveOptionParser(usage=usage) |
|
84 | 83 | parser.add_option("-d", "--debug", |
General Comments 0
You need to be logged in to leave comments.
Login now