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
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() ]
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
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)
def indexes_on_model(model): return [ pw.IndexMetadata('', '', [_column_name(f)], f.unique, _table_name(model)) for f in model._fields_to_index() ]