Beispiel #1
0
 def _alter_column(self, table, column):
     return [
         SQL('ALTER TABLE'),
         Entity(table),
         SQL('ALTER COLUMN'),
         Entity(column)
     ]
Beispiel #2
0
 def add_index(self, table, columns, unique=False):
     compiler = self.database.compiler()
     statement = 'CREATE UNIQUE INDEX' if unique else 'CREATE INDEX'
     return Clause(SQL(statement),
                   Entity(compiler.index_name(table, columns)), SQL('ON'),
                   Entity(table),
                   EnclosedClause(*[Entity(column) for column in columns]))
Beispiel #3
0
 def drop_column(self, table, column_name, cascade=True):
     nodes = [
         SQL('ALTER TABLE'),
         Entity(table),
         SQL('DROP COLUMN'),
         Entity(column_name)
     ]
     if cascade:
         nodes.append(SQL('CASCADE'))
     return Clause(*nodes)
Beispiel #4
0
    def apply_default(self, table, column_name, field):
        default = field.default
        if callable(default):
            default = default()

        return Clause(
            SQL('UPDATE'), Entity(table), SQL('SET'),
            Expression(Entity(column_name),
                       OP.EQ,
                       Param(field.db_value(default)),
                       flat=True))
Beispiel #5
0
 def alter_add_column(self, table, column_name, field):
     # Make field null at first.
     field_null, field.null = field.null, True
     field.name = field.db_column = column_name
     field_clause = self.database.compiler().field_definition(field)
     field.null = field_null
     parts = [
         SQL('ALTER TABLE'),
         Entity(table),
         SQL('ADD COLUMN'), field_clause
     ]
     if isinstance(field, ForeignKeyField):
         parts.extend([
             SQL('REFERENCES'),
             Entity(field.rel_model._meta.db_table),
             EnclosedClause(Entity(field.to_field.db_column))
         ])
     return Clause(*parts)
Beispiel #6
0
 def sql(self, column_name=None, is_null=None):
     if is_null is None:
         is_null = self.is_null
     if column_name is None:
         column_name = self.name
     parts = [Entity(column_name), SQL(self.definition)]
     if self.is_unique:
         parts.append(SQL('UNIQUE'))
     if not is_null:
         parts.append(SQL('NOT NULL'))
     if self.is_pk:
         parts.append(SQL('PRIMARY KEY'))
     if self.extra:
         parts.append(SQL(self.extra))
     return Clause(*parts)
Beispiel #7
0
    def _update_column(self, table, column_to_update, fn):
        columns = set(column.name.lower()
                      for column in self.database.get_columns(table))
        if column_to_update.lower() not in columns:
            raise ValueError('Column "%s" does not exist on "%s"' %
                             (column_to_update, table))

        # Get the SQL used to create the given table.
        table, create_table = self._get_create_table(table)

        # Get the indexes and SQL to re-create indexes.
        indexes = self.database.get_indexes(table)

        # Find any foreign keys we may need to remove.
        self.database.get_foreign_keys(table)

        # Parse out the `CREATE TABLE` and column list portions of the query.
        raw_create, raw_columns = self.column_re.search(create_table).groups()

        # Clean up the individual column definitions.
        column_defs = [
            col.strip() for col in self.column_split_re.findall(raw_columns)
        ]

        new_column_defs = []
        new_column_names = []
        original_column_names = []

        for column_def in column_defs:
            column_name, = self.column_name_re.match(column_def).groups()

            if column_name == column_to_update:
                new_column_def = fn(column_name, column_def)
                if new_column_def:
                    new_column_defs.append(new_column_def)
                    original_column_names.append(column_name)
                    column_name, = self.column_name_re.match(
                        new_column_def).groups()
                    new_column_names.append(column_name)
            else:
                new_column_defs.append(column_def)
                if not column_name.lower().startswith(('foreign', 'primary')):
                    new_column_names.append(column_name)
                    original_column_names.append(column_name)

        # Create a mapping of original columns to new columns.
        original_to_new = dict(zip(original_column_names, new_column_names))
        new_column = original_to_new.get(column_to_update)

        fk_filter_fn = lambda column_def: column_def
        if not new_column:
            # Remove any foreign keys associated with this column.
            fk_filter_fn = lambda column_def: None
        elif new_column != column_to_update:
            # Update any foreign keys for this column.
            fk_filter_fn = lambda column_def: self.fk_re.sub(
                'FOREIGN KEY ("%s") ' % new_column, column_def)

        cleaned_columns = []
        for column_def in new_column_defs:
            match = self.fk_re.match(column_def)
            if match is not None and match.groups()[0] == column_to_update:
                column_def = fk_filter_fn(column_def)
            if column_def:
                cleaned_columns.append(column_def)

        # Update the name of the new CREATE TABLE query.
        temp_table = table + '__tmp__'
        rgx = re.compile('("?)%s("?)' % table, re.I)
        create = rgx.sub('\\1%s\\2' % temp_table, raw_create)

        # Create the new table.
        columns = ', '.join(cleaned_columns)
        queries = [
            Clause(SQL('DROP TABLE IF EXISTS'), Entity(temp_table)),
            SQL('%s (%s)' % (create.strip(), columns))
        ]

        # Populate new table.
        populate_table = Clause(
            SQL('INSERT INTO'), Entity(temp_table),
            EnclosedClause(*[Entity(col) for col in new_column_names]),
            SQL('SELECT'),
            CommaClause(*[Entity(col) for col in original_column_names]),
            SQL('FROM'), Entity(table))
        queries.append(populate_table)

        # Drop existing table and rename temp table.
        queries.append(Clause(SQL('DROP TABLE'), Entity(table)))
        queries.append(self.rename_table(temp_table, table))

        # Re-create indexes.
        for index in indexes:
            # Auto-generated indexes in SQLite will not have associated SQL,
            # so pass over them.
            if not index.sql:
                continue

            if column_to_update in index.columns:
                if new_column:
                    queries.append(
                        SQL(index.sql.replace(column_to_update, new_column)))
            else:
                queries.append(SQL(index.sql))

        return queries
Beispiel #8
0
 def drop_index(self, table, index_name):
     return Clause(SQL('DROP INDEX'), Entity(index_name), SQL('ON'),
                   Entity(table))
Beispiel #9
0
 def rename_column(self, table, old_name, new_name):
     column = self._get_column_definition(table, old_name)
     return Clause(SQL('ALTER TABLE'), Entity(table), SQL('CHANGE'),
                   Entity(old_name), column.sql(column_name=new_name))
Beispiel #10
0
 def drop_not_null(self, table, column):
     column = self._get_column_definition(table, column)
     if column.is_pk:
         raise ValueError('Primary keys can not be null')
     return Clause(SQL('ALTER TABLE'), Entity(table), SQL('MODIFY'),
                   column.sql(is_null=True))
Beispiel #11
0
 def add_not_null(self, table, column):
     column = self._get_column_definition(table, column)
     return Clause(SQL('ALTER TABLE'), Entity(table), SQL('MODIFY'),
                   column.sql(is_null=False))
Beispiel #12
0
 def rename_table(self, old_name, new_name):
     return Clause(SQL('ALTER TABLE'), Entity(old_name), SQL('RENAME TO'),
                   Entity(new_name))
Beispiel #13
0
 def rename_column(self, table, old_name, new_name):
     return Clause(SQL('ALTER TABLE'), Entity(table), SQL('RENAME COLUMN'),
                   Entity(old_name), SQL('TO'), Entity(new_name))