def _alter_column(self, table, column): return [ SQL('ALTER TABLE'), Entity(table), SQL('ALTER COLUMN'), Entity(column) ]
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]))
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)
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))
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)
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)
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
def drop_index(self, table, index_name): return Clause(SQL('DROP INDEX'), Entity(index_name), SQL('ON'), Entity(table))
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))
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))
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))
def rename_table(self, old_name, new_name): return Clause(SQL('ALTER TABLE'), Entity(old_name), SQL('RENAME TO'), Entity(new_name))
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))