예제 #1
0
def calc_index_changes(db, migrator, existing_indexes, model, renamed_cols):
    to_run = []
    fields = list(model._meta.sorted_fields)
    fields_by_column_name = {_column_name(f): f for f in fields}
    pk_cols = set([unicode(_column_name(f)) for f in fields if f.primary_key])
    existing_indexes = [
        i for i in existing_indexes
        if not all([(unicode(c) in pk_cols) for c in i.columns])
    ]
    normalized_existing_indexes = normalize_indexes(existing_indexes)
    existing_indexes_by_normalized_existing_indexes = dict(
        zip(normalized_existing_indexes, existing_indexes))
    normalized_existing_indexes = set(normalized_existing_indexes)
    defined_indexes = indexes_on_model(model)
    for fields, unique in model._meta.indexes:
        try:
            columns = [
                _column_name(model._meta.fields[fname]) for fname in fields
            ]
        except KeyError as e:
            raise Exception(
                "Index %s on %s references field %s in a multi-column index, but that field doesn't exist. (Be sure to use the field name, not the db_column name, when specifying a multi-column index.)"
                % ((fields, unique), model.__name__, repr(e.message)))
        defined_indexes.append(
            pw.IndexMetadata('', '', columns, unique, _table_name(model)))
    normalized_defined_indexes = set(normalize_indexes(defined_indexes))
    to_add = normalized_defined_indexes - normalized_existing_indexes
    to_del = normalized_existing_indexes - normalized_defined_indexes
    for index in to_del:
        index = existing_indexes_by_normalized_existing_indexes[index]
        to_run += drop_index(migrator, model, index)
    for index in to_add:
        to_run += create_index(
            model, [fields_by_column_name[col] for col in index[1]], index[2])
    return to_run
예제 #2
0
 def indexes_on_model(model):
     return [
         pw.IndexMetadata('', '',
                          [_column_name(f)
                           for f in idx._expressions], idx._unique,
                          _table_name(model))
         for idx in model._meta.fields_to_index()
     ]
예제 #3
0
def calc_index_changes(db, migrator, existing_indexes, model, renamed_cols):
    qc = db.compiler()
    to_run = []
    fields = list(model._meta.sorted_fields)
    fields_by_column_name = {f.db_column: f for f in fields}
    pk_cols = set([unicode(f.db_column) for f in fields if f.primary_key])
    existing_indexes = [
        i for i in existing_indexes
        if not all([(unicode(c) in pk_cols) for c in i.columns])
    ]
    normalized_existing_indexes = normalize_indexes(existing_indexes)
    existing_indexes_by_normalized_existing_indexes = dict(
        zip(normalized_existing_indexes, existing_indexes))
    normalized_existing_indexes = set(normalized_existing_indexes)
    defined_indexes = [
        pw.IndexMetadata('', '', [f.db_column], f.unique, model._meta.db_table)
        for f in model._fields_to_index()
    ]
    for fields, unique in model._meta.indexes:
        try:
            columns = [model._meta.fields[fname].db_column for fname in fields]
        except KeyError as e:
            raise Exception(
                "Index %s on %s references field %s in a multi-column index, but that field doesn't exist. (Be sure to use the field name, not the db_column name, when specifying a multi-column index.)"
                % ((fields, unique), model.__name__, repr(e.message)))
        defined_indexes.append(
            pw.IndexMetadata('', '', columns, unique, model._meta.db_table))
    normalized_defined_indexes = set(normalize_indexes(defined_indexes))
    to_add = normalized_defined_indexes - normalized_existing_indexes
    to_del = normalized_existing_indexes - normalized_defined_indexes
    for index in to_add:
        to_run.append(
            qc.create_index(model,
                            [fields_by_column_name[col] for col in index[1]],
                            index[2]))
    for index in to_del:
        index = existing_indexes_by_normalized_existing_indexes[index]
        op = migrator.drop_index(model._meta.db_table,
                                 index.name,
                                 generate=True)
        to_run.append(qc.parse_node(op))
    return to_run
예제 #4
0
def get_indexes_by_table(db, table, schema='public'):
    # peewee's get_indexes returns the columns in an index in arbitrary order
    if is_postgres(db):
        query = '''
      select index_class.relname,
        idxs.indexdef,
        array_agg(table_attribute.attname order by array_position(index.indkey, table_attribute.attnum)),
        index.indisunique,
        table_class.relname
      from pg_catalog.pg_class index_class
      join pg_catalog.pg_index index on index_class.oid = index.indexrelid
      join pg_catalog.pg_class table_class on table_class.oid = index.indrelid
      join pg_catalog.pg_attribute table_attribute on table_class.oid = table_attribute.attrelid and table_attribute.attnum = any(index.indkey)
      join pg_catalog.pg_indexes idxs on idxs.tablename = table_class.relname and idxs.indexname = index_class.relname
      where table_class.relname = %s and table_class.relkind = %s and idxs.schemaname = %s
      group by index_class.relname, idxs.indexdef, index.indisunique, table_class.relname;
    '''
        cursor = db.execute_sql(query, (table, 'r', schema))
        return [pw.IndexMetadata(*row) for row in cursor.fetchall()]
    else:
        return db.get_indexes(table, schema=schema)
예제 #5
0
 def indexes_on_model(model):
     return [
         pw.IndexMetadata('', '', [_column_name(f)], f.unique,
                          _table_name(model))
         for f in model._fields_to_index()
     ]