indexes.test.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import { afterAll, beforeAll, expect, test } from 'vitest'
  2. import pgMeta from '../src/index'
  3. import { cleanupRoot, createTestDatabase } from './db/utils'
  4. beforeAll(async () => {
  5. // Any global setup if needed
  6. })
  7. afterAll(async () => {
  8. await cleanupRoot()
  9. })
  10. const withTestDatabase = (
  11. name: string,
  12. fn: (db: Awaited<ReturnType<typeof createTestDatabase>>) => Promise<void>
  13. ) => {
  14. test(name, async () => {
  15. const db = await createTestDatabase()
  16. try {
  17. await fn(db)
  18. } finally {
  19. await db.cleanup()
  20. }
  21. })
  22. }
  23. withTestDatabase('list indexes', async ({ executeQuery }) => {
  24. // List indexes
  25. const { sql: listSql, zod: listZod } = await pgMeta.indexes.list()
  26. const indexes = listZod.parse(await executeQuery(listSql))
  27. const usersPkeyIndex = indexes.find(
  28. ({ index_definition }) =>
  29. index_definition === 'CREATE UNIQUE INDEX users_pkey ON public.users USING btree (id)'
  30. )!
  31. expect(usersPkeyIndex).toMatchInlineSnapshot(
  32. `
  33. {
  34. "access_method": "btree",
  35. "check_xmin": false,
  36. "class": [
  37. 3124,
  38. ],
  39. "collation": [
  40. 0,
  41. ],
  42. "comment": null,
  43. "id": 16399,
  44. "index_attributes": [
  45. {
  46. "attribute_name": "id",
  47. "attribute_number": 1,
  48. "data_type": "bigint",
  49. },
  50. ],
  51. "index_definition": "CREATE UNIQUE INDEX users_pkey ON public.users USING btree (id)",
  52. "index_predicate": null,
  53. "is_clustered": false,
  54. "is_exclusion": false,
  55. "is_immediate": true,
  56. "is_live": true,
  57. "is_primary": true,
  58. "is_ready": true,
  59. "is_replica_identity": false,
  60. "is_unique": true,
  61. "is_valid": true,
  62. "key_attributes": [
  63. 1,
  64. ],
  65. "number_of_attributes": 1,
  66. "number_of_key_attributes": 1,
  67. "options": [
  68. 0,
  69. ],
  70. "schema": "public",
  71. "table_id": 16393,
  72. }
  73. `
  74. )
  75. })
  76. withTestDatabase('retrieve index', async ({ executeQuery }) => {
  77. // Retrieve specific index
  78. const { sql: retrieveSql, zod: retrieveZod } = await pgMeta.indexes.retrieve({
  79. id: 16399,
  80. })
  81. const index = retrieveZod.parse((await executeQuery(retrieveSql))[0])
  82. expect(index).toMatchInlineSnapshot(
  83. `
  84. {
  85. "access_method": "btree",
  86. "check_xmin": false,
  87. "class": [
  88. 3124,
  89. ],
  90. "collation": [
  91. 0,
  92. ],
  93. "comment": null,
  94. "id": 16399,
  95. "index_attributes": [
  96. {
  97. "attribute_name": "id",
  98. "attribute_number": 1,
  99. "data_type": "bigint",
  100. },
  101. ],
  102. "index_definition": "CREATE UNIQUE INDEX users_pkey ON public.users USING btree (id)",
  103. "index_predicate": null,
  104. "is_clustered": false,
  105. "is_exclusion": false,
  106. "is_immediate": true,
  107. "is_live": true,
  108. "is_primary": true,
  109. "is_ready": true,
  110. "is_replica_identity": false,
  111. "is_unique": true,
  112. "is_valid": true,
  113. "key_attributes": [
  114. 1,
  115. ],
  116. "number_of_attributes": 1,
  117. "number_of_key_attributes": 1,
  118. "options": [
  119. 0,
  120. ],
  121. "schema": "public",
  122. "table_id": 16393,
  123. }
  124. `
  125. )
  126. })
  127. withTestDatabase('list with filters', async ({ executeQuery }) => {
  128. // Test includeSystemSchemas
  129. const { sql: withSystemSql, zod } = await pgMeta.indexes.list({ includeSystemSchemas: true })
  130. const withSystem = zod.parse(await executeQuery(withSystemSql))
  131. expect(withSystem.some((idx) => idx.schema === 'pg_catalog')).toBe(true)
  132. // Test without system schemas (default)
  133. const { sql: withoutSystemSql, zod: withoutSystemZod } = await pgMeta.indexes.list()
  134. const withoutSystem = withoutSystemZod.parse(await executeQuery(withoutSystemSql))
  135. expect(withoutSystem.some((idx) => idx.schema === 'pg_catalog')).toBe(false)
  136. // Test includedSchemas
  137. const { sql: includedSchemasSql, zod: includedSchemasZod } = await pgMeta.indexes.list({
  138. includedSchemas: ['public'],
  139. })
  140. const includedSchemas = includedSchemasZod.parse(await executeQuery(includedSchemasSql))
  141. expect(includedSchemas.every((idx) => idx.schema === 'public')).toBe(true)
  142. // Test excludedSchemas
  143. const { sql: excludedSchemasSql, zod: excludedSchemasZod } = await pgMeta.indexes.list({
  144. excludedSchemas: ['public'],
  145. })
  146. const excludedSchemas = excludedSchemasZod.parse(await executeQuery(excludedSchemasSql))
  147. expect(excludedSchemas.some((idx) => idx.schema === 'public')).toBe(false)
  148. // Test limit and offset
  149. const { sql: limitSql, zod: limitZod } = await pgMeta.indexes.list({ limit: 1 })
  150. const limited = limitZod.parse(await executeQuery(limitSql))
  151. expect(limited).toHaveLength(1)
  152. const { sql: offsetSql, zod: offsetZod } = await pgMeta.indexes.list({ offset: 1 })
  153. const offset = offsetZod.parse(await executeQuery(offsetSql))
  154. expect(offset).toHaveLength(withoutSystem.length - 1)
  155. })
  156. withTestDatabase('handles same index name across schemas correctly', async ({ executeQuery }) => {
  157. // Create two schemas
  158. await executeQuery(`CREATE SCHEMA schema_a;`)
  159. await executeQuery(`CREATE SCHEMA schema_b;`)
  160. // Create tables
  161. await executeQuery(`CREATE TABLE schema_a.test (id int);`)
  162. await executeQuery(`CREATE TABLE schema_b.test (id int);`)
  163. // Create SAME index name in both schemas
  164. await executeQuery(`CREATE INDEX idx_test ON schema_a.test (id);`)
  165. await executeQuery(`CREATE INDEX idx_test ON schema_b.test (id);`)
  166. // Fetch indexes
  167. const { sql, zod } = await pgMeta.indexes.list({ includeSystemSchemas: true })
  168. const indexes = zod.parse(await executeQuery(sql))
  169. const schemaAIndex = indexes.find(
  170. (i) => i.schema === 'schema_a' && i.index_definition.includes('schema_a.test')
  171. )
  172. const schemaBIndex = indexes.find(
  173. (i) => i.schema === 'schema_b' && i.index_definition.includes('schema_b.test')
  174. )
  175. expect(schemaAIndex).toBeDefined()
  176. expect(schemaBIndex).toBeDefined()
  177. expect(schemaAIndex!.index_definition).toContain('schema_a.test')
  178. expect(schemaBIndex!.index_definition).toContain('schema_b.test')
  179. })