getIndexes gets all indices of a database.
(txn *sql.Tx)
| 552 | |
| 553 | // getIndexes gets all indices of a database. |
| 554 | func getIndexes(txn *sql.Tx) (map[db.TableKey][]*storepb.IndexMetadata, error) { |
| 555 | indexMap := make(map[db.TableKey][]*storepb.IndexMetadata) |
| 556 | |
| 557 | // Use generate_series to mimic PostgreSQL's generate_subscripts for getting column expressions |
| 558 | // Combined with pg_get_indexdef to get accurate column expressions |
| 559 | query := ` |
| 560 | WITH index_positions AS ( |
| 561 | SELECT generate_series(0, 31) as pos |
| 562 | ) |
| 563 | SELECT |
| 564 | pgidx.schemaname, |
| 565 | pgidx.tablename, |
| 566 | pgidx.indexname, |
| 567 | pgidx.indexdef, |
| 568 | ix.indisunique, |
| 569 | ix.indisprimary, |
| 570 | p.pos + 1 as position, |
| 571 | pg_get_indexdef(pc.oid, p.pos + 1, true) as column_expression, |
| 572 | obj_description(pc.oid) AS comment |
| 573 | FROM |
| 574 | pg_indexes AS pgidx |
| 575 | JOIN pg_namespace AS pns ON pns.nspname = pgidx.schemaname |
| 576 | JOIN pg_class AS pc ON pc.relname = pgidx.indexname AND pns.oid = pc.relnamespace |
| 577 | JOIN pg_index AS ix ON ix.indexrelid = pc.oid |
| 578 | CROSS JOIN index_positions p |
| 579 | WHERE |
| 580 | pgidx.schemaname NOT IN ('pg_catalog', 'information_schema') |
| 581 | AND ix.indkey[p.pos] > 0 -- Only process positions that have actual columns |
| 582 | ORDER BY |
| 583 | pgidx.schemaname, pgidx.tablename, pgidx.indexname, p.pos;` |
| 584 | |
| 585 | rows, err := txn.Query(query) |
| 586 | if err != nil { |
| 587 | return nil, err |
| 588 | } |
| 589 | defer rows.Close() |
| 590 | |
| 591 | // Track index data as we process rows |
| 592 | type indexKey struct { |
| 593 | schema string |
| 594 | table string |
| 595 | index string |
| 596 | } |
| 597 | indexData := make(map[indexKey]*storepb.IndexMetadata) |
| 598 | indexColumns := make(map[indexKey][]string) |
| 599 | |
| 600 | for rows.Next() { |
| 601 | var schemaName, tableName, indexName, indexDef string |
| 602 | var isUnique, isPrimary bool |
| 603 | var position int |
| 604 | var columnExpression sql.NullString |
| 605 | var comment sql.NullString |
| 606 | |
| 607 | if err := rows.Scan(&schemaName, &tableName, &indexName, &indexDef, |
| 608 | &isUnique, &isPrimary, &position, &columnExpression, &comment); err != nil { |
| 609 | return nil, err |
| 610 | } |
| 611 |