-
-
Notifications
You must be signed in to change notification settings - Fork 107
Expand file tree
/
Copy pathindexes.ts
More file actions
132 lines (121 loc) · 4.31 KB
/
Copy pathindexes.ts
File metadata and controls
132 lines (121 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import type { Kysely } from 'kysely'
import type { Columns as ClickHouseColumns } from '../dialects/clickhouse/schema/system'
import type { SysColumns, SysIndexColumns, SysIndexes, SysSchemas, SysTables } from '../dialects/mssql/schema/indexes'
import type { MysqlStatistics } from '../dialects/mysql/schema/indexes'
import type { PgAttribute, PgClass, PgIndex, PgNamespace } from '../dialects/postgres/schema/indexes'
import { type } from 'arktype'
import { sql } from 'kysely'
import { createQuery } from '../query'
export const indexesType = type({
schema: 'string',
table: 'string',
name: 'string',
column: 'string',
isUnique: 'boolean | 1 | 0',
isPrimary: 'boolean | 1 | 0',
}).pipe(data => ({
...data,
isUnique: !!data.isUnique,
isPrimary: !!data.isPrimary,
}))
export const indexesQuery = createQuery({
type: indexesType.array(),
query: () => ({
postgres: (db) => {
const sysDb = db as unknown as Kysely<{
pg_class: PgClass
pg_index: PgIndex
pg_attribute: PgAttribute
pg_namespace: PgNamespace
}>
return sysDb
.selectFrom('pg_class as t')
.innerJoin('pg_index as ix', 't.oid', 'ix.indrelid')
.innerJoin('pg_class as i', 'i.oid', 'ix.indexrelid')
.innerJoin('pg_attribute as a', join => join
.onRef('a.attrelid', '=', 't.oid')
.on(sql<boolean>`a.attnum = ANY(ix.indkey)`))
.innerJoin('pg_namespace as n', 'n.oid', 't.relnamespace')
.select([
'n.nspname as schema',
't.relname as table',
'i.relname as name',
'a.attname as column',
'ix.indisunique as isUnique',
'ix.indisprimary as isPrimary',
])
.where('n.nspname', 'not in', ['pg_catalog', 'information_schema'])
.where('t.relkind', '=', 'r')
.execute()
},
mysql: (db) => {
const sysDb = db as unknown as Kysely<{
'information_schema.STATISTICS': MysqlStatistics
}>
return sysDb
.selectFrom('information_schema.STATISTICS')
.select([
'TABLE_SCHEMA as schema',
'TABLE_NAME as table',
'INDEX_NAME as name',
'COLUMN_NAME as column',
eb => eb('NON_UNIQUE', '=', 0).as('isUnique'),
eb => eb('INDEX_NAME', '=', 'PRIMARY').as('isPrimary'),
])
.where('TABLE_SCHEMA', 'not in', ['mysql', 'information_schema', 'performance_schema', 'sys'])
.execute()
},
mssql: (db) => {
const sysDb = db as unknown as Kysely<{
'sys.indexes': SysIndexes
'sys.tables': SysTables
'sys.schemas': SysSchemas
'sys.index_columns': SysIndexColumns
'sys.columns': SysColumns
}>
return sysDb
.selectFrom('sys.indexes as i')
.innerJoin('sys.tables as t', 't.object_id', 'i.object_id')
.innerJoin('sys.schemas as s', 's.schema_id', 't.schema_id')
.innerJoin('sys.index_columns as ic', join => join
.onRef('ic.object_id', '=', 'i.object_id')
.onRef('ic.index_id', '=', 'i.index_id'))
.innerJoin('sys.columns as c', join => join
.onRef('c.object_id', '=', 'ic.object_id')
.onRef('c.column_id', '=', 'ic.column_id'))
.select([
's.name as schema',
't.name as table',
'i.name as name',
'c.name as column',
'i.is_unique as isUnique',
'i.is_primary_key as isPrimary',
])
.execute()
},
clickhouse: async (db) => {
/* ClickHouse uses ORDER BY as its primary key/sorting key (similar to clustered index).
It doesn't enforce constraints like traditional RDBMS (no foreign keys, unique constraints, etc.).
We show ORDER BY columns as primary key indexes since that's how ClickHouse optimizes queries. */
const sysDb = db as unknown as Kysely<{
'system.columns': ClickHouseColumns
}>
const query = await sysDb
.selectFrom('system.columns')
.select([
'database as schema',
'table',
'name as column',
])
.where('is_in_primary_key', '=', 1)
.where('database', 'not in', ['system', 'information_schema'])
.execute()
return query.map(row => ({
...row,
name: 'primary_key',
isUnique: true,
isPrimary: true,
}))
},
}),
})