Exemplo n.º 1
0
def print_model(model, indexes=True, inline_indexes=False):
    print(model._meta.name)
    for field in model._meta.sorted_fields:
        parts = ['  %s %s' % (field.name, field.field_type)]
        if field.primary_key:
            parts.append(' PK')
        elif inline_indexes:
            if field.unique:
                parts.append(' UNIQUE')
            elif field.index:
                parts.append(' INDEX')
        if isinstance(field, ForeignKeyField):
            parts.append(' FK: %s.%s' %
                         (field.rel_model.__name__, field.rel_field.name))
        print(''.join(parts))

    if indexes and model._meta.indexes:
        print('\nindex(es)')
        for index in model._meta.fields_to_index():
            parts = ['  ']
            ctx = model._meta.database.get_sql_context()
            with ctx.scope_values(param='%s', quote='""'):
                ctx.sql(CommaNodeList(index._expressions))
                if index._where:
                    ctx.literal(' WHERE ')
                    ctx.sql(index._where)
                sql, params = ctx.query()

            clean = sql % tuple(map(_query_val_transform, params))
            parts.append(clean.replace('"', ''))

            if index._unique:
                parts.append(' UNIQUE')
            print(''.join(parts))
Exemplo n.º 2
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)

        # Make sure the create_table does not contain any newlines or tabs,
        # allowing the regex to work correctly.
        create_table = re.sub(r'\s+', ' ', create_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.
        split_columns = self.column_split_re.findall(raw_columns)
        column_defs = [col.strip() for col in split_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 = [
            NodeList([SQL('DROP TABLE IF EXISTS'),
                      Entity(temp_table)]),
            SQL('%s (%s)' % (create.strip(), columns))
        ]

        # Populate new table.
        populate_table = NodeList(
            (SQL('INSERT INTO'), Entity(temp_table),
             EnclosedNodeList([Entity(col)
                               for col in new_column_names]), SQL('SELECT'),
             CommaNodeList([Entity(col) for col in original_column_names]),
             SQL('FROM'), Entity(table)))
        drop_original = NodeList([SQL('DROP TABLE'), Entity(table)])

        # Drop existing table and rename temp table.
        queries += [
            populate_table, drop_original,
            self.rename_table(temp_table, table)
        ]

        # Re-create user-defined indexes. User-defined indexes will have a
        # non-empty SQL attribute.
        for index in filter(lambda idx: idx.sql, indexes):
            if column_to_update not in index.columns:
                queries.append(SQL(index.sql))
            elif new_column:
                sql = self._fix_index(index.sql, column_to_update, new_column)
                if sql is not None:
                    queries.append(SQL(sql))

        return queries