@query-doctor/core 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/defineProperty.cjs +13 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/defineProperty.mjs +13 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/toPrimitive.cjs +15 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/toPrimitive.mjs +15 -0
  5. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/toPropertyKey.cjs +10 -0
  6. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/toPropertyKey.mjs +10 -0
  7. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/typeof.cjs +17 -0
  8. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/typeof.mjs +12 -0
  9. package/dist/index.cjs +6 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +3 -2
  12. package/dist/index.d.cts.map +1 -0
  13. package/dist/index.d.mts +3 -2
  14. package/dist/index.d.mts.map +1 -0
  15. package/dist/index.mjs +3 -2
  16. package/dist/index.mjs.map +1 -0
  17. package/dist/optimizer/dump.cjs +74 -0
  18. package/dist/optimizer/dump.cjs.map +1 -0
  19. package/dist/optimizer/dump.d.cts +101 -0
  20. package/dist/optimizer/dump.d.cts.map +1 -0
  21. package/dist/optimizer/dump.d.mts +101 -0
  22. package/dist/optimizer/dump.d.mts.map +1 -0
  23. package/dist/optimizer/dump.mjs +69 -0
  24. package/dist/optimizer/dump.mjs.map +1 -0
  25. package/dist/optimizer/statistics.cjs +110 -109
  26. package/dist/optimizer/statistics.cjs.map +1 -1
  27. package/dist/optimizer/statistics.d.cts +3 -2
  28. package/dist/optimizer/statistics.d.cts.map +1 -1
  29. package/dist/optimizer/statistics.d.mts +3 -2
  30. package/dist/optimizer/statistics.d.mts.map +1 -1
  31. package/dist/optimizer/statistics.mjs +110 -110
  32. package/dist/optimizer/statistics.mjs.map +1 -1
  33. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
3
+ const require_pg_identifier = require("../sql/pg-identifier.cjs");
4
+ const require_statistics = require("./statistics.cjs");
5
+ let zod = require("zod");
6
+ let dedent = require("dedent");
7
+ dedent = require_runtime.__toESM(dedent, 1);
8
+ //#region src/optimizer/dump.ts
9
+ const ExportedQuery = zod.z.object({
10
+ username: zod.z.string(),
11
+ query: zod.z.string(),
12
+ meanTime: zod.z.number(),
13
+ calls: zod.z.coerce.string(),
14
+ rows: zod.z.coerce.string(),
15
+ topLevel: zod.z.boolean()
16
+ });
17
+ const CombinedExport = zod.z.object({
18
+ queries: zod.z.array(ExportedQuery).nullable().transform((v) => v ?? []),
19
+ stats: zod.z.array(require_statistics.ExportedStats)
20
+ });
21
+ function indent(sql, spaces) {
22
+ const pad = " ".repeat(spaces);
23
+ return sql.trim().split("\n").map((line) => pad + line).join("\n");
24
+ }
25
+ function dumpQueriesSql(schema, source = "pg_stat_statements") {
26
+ const quotedSchema = require_pg_identifier.PgIdentifier.fromString(schema).toString();
27
+ if (source === "pg_stat_monitor") return dedent.default`
28
+ SELECT
29
+ COALESCE(username, 'unknown_user') as "username",
30
+ query,
31
+ mean_exec_time as "meanTime",
32
+ calls,
33
+ rows,
34
+ toplevel as "topLevel"
35
+ FROM ${quotedSchema}.pg_stat_monitor
36
+ WHERE query NOT LIKE '%pg_stat_monitor%'
37
+ AND query NOT LIKE '%@qd_introspection%'
38
+ AND query NOT ILIKE 'explain%'
39
+ `;
40
+ return dedent.default`
41
+ SELECT
42
+ 'unknown_user' as "username",
43
+ query,
44
+ mean_exec_time as "meanTime",
45
+ calls,
46
+ rows,
47
+ toplevel as "topLevel"
48
+ FROM ${quotedSchema}.pg_stat_statements
49
+ WHERE query NOT LIKE '%pg_stat_statements%'
50
+ AND query NOT LIKE '%@qd_introspection%'
51
+ AND query != '<insufficient privilege>'
52
+ AND query NOT ILIKE 'explain%'
53
+ `;
54
+ }
55
+ function combinedDumpSql(schema, source = "pg_stat_statements") {
56
+ const statsSql = indent(require_statistics.DUMP_STATS_SQL, 6);
57
+ return [
58
+ "SELECT json_build_object(",
59
+ ` 'queries', (SELECT json_agg(q) FROM (`,
60
+ indent(dumpQueriesSql(schema, source), 8),
61
+ ` ) q),`,
62
+ ` 'stats', (`,
63
+ statsSql,
64
+ ` )`,
65
+ `);`
66
+ ].join("\n");
67
+ }
68
+ //#endregion
69
+ exports.CombinedExport = CombinedExport;
70
+ exports.ExportedQuery = ExportedQuery;
71
+ exports.combinedDumpSql = combinedDumpSql;
72
+ exports.dumpQueriesSql = dumpQueriesSql;
73
+
74
+ //# sourceMappingURL=dump.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump.cjs","names":["z","ExportedStats","PgIdentifier","DUMP_STATS_SQL"],"sources":["../../src/optimizer/dump.ts"],"sourcesContent":["import dedent from \"dedent\";\nimport { z } from \"zod\";\nimport { PgIdentifier } from \"../sql/pg-identifier.js\";\nimport { DUMP_STATS_SQL, ExportedStats } from \"./statistics.js\";\n\nexport const ExportedQuery = z.object({\n username: z.string(),\n query: z.string(),\n meanTime: z.number(),\n calls: z.coerce.string(),\n rows: z.coerce.string(),\n topLevel: z.boolean(),\n});\n\nexport type ExportedQuery = z.infer<typeof ExportedQuery>;\n\nexport const CombinedExport = z.object({\n queries: z.array(ExportedQuery).nullable().transform((v) => v ?? []),\n stats: z.array(ExportedStats),\n});\n\nexport type CombinedExport = z.infer<typeof CombinedExport>;\n\nexport type QuerySource = \"pg_stat_statements\" | \"pg_stat_monitor\";\n\nfunction indent(sql: string, spaces: number): string {\n const pad = \" \".repeat(spaces);\n return sql\n .trim()\n .split(\"\\n\")\n .map((line) => pad + line)\n .join(\"\\n\");\n}\n\nexport function dumpQueriesSql(\n schema: string,\n source: QuerySource = \"pg_stat_statements\",\n): string {\n const quotedSchema = PgIdentifier.fromString(schema).toString();\n if (source === \"pg_stat_monitor\") {\n return dedent`\n SELECT\n COALESCE(username, 'unknown_user') as \"username\",\n query,\n mean_exec_time as \"meanTime\",\n calls,\n rows,\n toplevel as \"topLevel\"\n FROM ${quotedSchema}.pg_stat_monitor\n WHERE query NOT LIKE '%pg_stat_monitor%'\n AND query NOT LIKE '%@qd_introspection%'\n AND query NOT ILIKE 'explain%'\n `;\n }\n return dedent`\n SELECT\n 'unknown_user' as \"username\",\n query,\n mean_exec_time as \"meanTime\",\n calls,\n rows,\n toplevel as \"topLevel\"\n FROM ${quotedSchema}.pg_stat_statements\n WHERE query NOT LIKE '%pg_stat_statements%'\n AND query NOT LIKE '%@qd_introspection%'\n AND query != '<insufficient privilege>'\n AND query NOT ILIKE 'explain%'\n `;\n}\n\nexport function combinedDumpSql(\n schema: string,\n source: QuerySource = \"pg_stat_statements\",\n): string {\n const statsSql = indent(DUMP_STATS_SQL, 6);\n const queriesSql = indent(dumpQueriesSql(schema, source), 8);\n return [\n \"SELECT json_build_object(\",\n ` 'queries', (SELECT json_agg(q) FROM (`,\n queriesSql,\n ` ) q),`,\n ` 'stats', (`,\n statsSql,\n ` )`,\n `);`,\n ].join(\"\\n\");\n}\n"],"mappings":";;;;;;;;AAKA,MAAa,gBAAgBA,IAAAA,EAAE,OAAO;CACpC,UAAUA,IAAAA,EAAE,QAAQ;CACpB,OAAOA,IAAAA,EAAE,QAAQ;CACjB,UAAUA,IAAAA,EAAE,QAAQ;CACpB,OAAOA,IAAAA,EAAE,OAAO,QAAQ;CACxB,MAAMA,IAAAA,EAAE,OAAO,QAAQ;CACvB,UAAUA,IAAAA,EAAE,SAAS;CACtB,CAAC;AAIF,MAAa,iBAAiBA,IAAAA,EAAE,OAAO;CACrC,SAASA,IAAAA,EAAE,MAAM,cAAc,CAAC,UAAU,CAAC,WAAW,MAAM,KAAK,EAAE,CAAC;CACpE,OAAOA,IAAAA,EAAE,MAAMC,mBAAAA,cAAc;CAC9B,CAAC;AAMF,SAAS,OAAO,KAAa,QAAwB;CACnD,MAAM,MAAM,IAAI,OAAO,OAAO;AAC9B,QAAO,IACJ,MAAM,CACN,MAAM,KAAK,CACX,KAAK,SAAS,MAAM,KAAK,CACzB,KAAK,KAAK;;AAGf,SAAgB,eACd,QACA,SAAsB,sBACd;CACR,MAAM,eAAeC,sBAAAA,aAAa,WAAW,OAAO,CAAC,UAAU;AAC/D,KAAI,WAAW,kBACb,QAAO,OAAA,OAAM;;;;;;;;aAQJ,aAAa;;;;;AAMxB,QAAO,OAAA,OAAM;;;;;;;;WAQJ,aAAa;;;;;;;AAQxB,SAAgB,gBACd,QACA,SAAsB,sBACd;CACR,MAAM,WAAW,OAAOC,mBAAAA,gBAAgB,EAAE;AAE1C,QAAO;EACL;EACA;EAHiB,OAAO,eAAe,QAAQ,OAAO,EAAE,EAAE;EAK1D;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK"}
@@ -0,0 +1,101 @@
1
+ 'use client';
2
+
3
+ import { z } from "zod";
4
+
5
+ //#region src/optimizer/dump.d.ts
6
+ declare const ExportedQuery: z.ZodObject<{
7
+ username: z.ZodString;
8
+ query: z.ZodString;
9
+ meanTime: z.ZodNumber;
10
+ calls: z.ZodCoercedString<unknown>;
11
+ rows: z.ZodCoercedString<unknown>;
12
+ topLevel: z.ZodBoolean;
13
+ }, z.core.$strip>;
14
+ type ExportedQuery = z.infer<typeof ExportedQuery>;
15
+ declare const CombinedExport: z.ZodObject<{
16
+ queries: z.ZodPipe<z.ZodNullable<z.ZodArray<z.ZodObject<{
17
+ username: z.ZodString;
18
+ query: z.ZodString;
19
+ meanTime: z.ZodNumber;
20
+ calls: z.ZodCoercedString<unknown>;
21
+ rows: z.ZodCoercedString<unknown>;
22
+ topLevel: z.ZodBoolean;
23
+ }, z.core.$strip>>>, z.ZodTransform<{
24
+ username: string;
25
+ query: string;
26
+ meanTime: number;
27
+ calls: string;
28
+ rows: string;
29
+ topLevel: boolean;
30
+ }[], {
31
+ username: string;
32
+ query: string;
33
+ meanTime: number;
34
+ calls: string;
35
+ rows: string;
36
+ topLevel: boolean;
37
+ }[] | null>>;
38
+ stats: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
39
+ tableName: z.ZodString;
40
+ schemaName: z.ZodString;
41
+ relpages: z.ZodNumber;
42
+ reltuples: z.ZodNumber;
43
+ relallvisible: z.ZodNumber;
44
+ relallfrozen: z.ZodOptional<z.ZodNumber>;
45
+ columns: z.ZodDefault<z.ZodArray<z.ZodObject<{
46
+ columnName: z.ZodString;
47
+ attlen: z.ZodNullable<z.ZodNumber>;
48
+ dataType: z.ZodOptional<z.ZodString>;
49
+ stats: z.ZodNullable<z.ZodObject<{
50
+ stawidth: z.ZodNumber;
51
+ stainherit: z.ZodDefault<z.ZodBoolean>;
52
+ stadistinct: z.ZodNumber;
53
+ stanullfrac: z.ZodNumber;
54
+ stakind1: z.ZodNumber;
55
+ stakind2: z.ZodNumber;
56
+ stakind3: z.ZodNumber;
57
+ stakind4: z.ZodNumber;
58
+ stakind5: z.ZodNumber;
59
+ staop1: z.ZodString;
60
+ staop2: z.ZodString;
61
+ staop3: z.ZodString;
62
+ staop4: z.ZodString;
63
+ staop5: z.ZodString;
64
+ stacoll1: z.ZodString;
65
+ stacoll2: z.ZodString;
66
+ stacoll3: z.ZodString;
67
+ stacoll4: z.ZodString;
68
+ stacoll5: z.ZodString;
69
+ stanumbers1: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
70
+ stanumbers2: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
71
+ stanumbers3: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
72
+ stanumbers4: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
73
+ stanumbers5: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
74
+ stavalues1: z.ZodNullable<z.ZodArray<z.ZodAny>>;
75
+ stavalues2: z.ZodNullable<z.ZodArray<z.ZodAny>>;
76
+ stavalues3: z.ZodNullable<z.ZodArray<z.ZodAny>>;
77
+ stavalues4: z.ZodNullable<z.ZodArray<z.ZodAny>>;
78
+ stavalues5: z.ZodNullable<z.ZodArray<z.ZodAny>>;
79
+ }, z.core.$strip>>;
80
+ }, z.core.$strip>>>;
81
+ indexes: z.ZodArray<z.ZodObject<{
82
+ indexName: z.ZodString;
83
+ amname: z.ZodDefault<z.ZodString>;
84
+ relpages: z.ZodNumber;
85
+ reltuples: z.ZodNumber;
86
+ relallvisible: z.ZodNumber;
87
+ relallfrozen: z.ZodOptional<z.ZodNumber>;
88
+ fillfactor: z.ZodDefault<z.ZodNumber>;
89
+ columns: z.ZodDefault<z.ZodArray<z.ZodObject<{
90
+ attlen: z.ZodNullable<z.ZodNumber>;
91
+ }, z.core.$strip>>>;
92
+ }, z.core.$strip>>;
93
+ }, z.core.$strip>]>>;
94
+ }, z.core.$strip>;
95
+ type CombinedExport = z.infer<typeof CombinedExport>;
96
+ type QuerySource = "pg_stat_statements" | "pg_stat_monitor";
97
+ declare function dumpQueriesSql(schema: string, source?: QuerySource): string;
98
+ declare function combinedDumpSql(schema: string, source?: QuerySource): string;
99
+ //#endregion
100
+ export { CombinedExport, ExportedQuery, QuerySource, combinedDumpSql, dumpQueriesSql };
101
+ //# sourceMappingURL=dump.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump.d.cts","names":[],"sources":["../../src/optimizer/dump.ts"],"mappings":";;;;;cAKa,aAAA,EAAa,CAAA,CAAA,SAAA;;;;;;;;KASd,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,aAAA;AAAA,cAE9B,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKf,cAAA,GAAiB,CAAA,CAAE,KAAA,QAAa,cAAA;AAAA,KAEhC,WAAA;AAAA,iBAWI,cAAA,CACd,MAAA,UACA,MAAA,GAAQ,WAAA;AAAA,iBAkCM,eAAA,CACd,MAAA,UACA,MAAA,GAAQ,WAAA"}
@@ -0,0 +1,101 @@
1
+ 'use client';
2
+
3
+ import { z } from "zod";
4
+
5
+ //#region src/optimizer/dump.d.ts
6
+ declare const ExportedQuery: z.ZodObject<{
7
+ username: z.ZodString;
8
+ query: z.ZodString;
9
+ meanTime: z.ZodNumber;
10
+ calls: z.ZodCoercedString<unknown>;
11
+ rows: z.ZodCoercedString<unknown>;
12
+ topLevel: z.ZodBoolean;
13
+ }, z.core.$strip>;
14
+ type ExportedQuery = z.infer<typeof ExportedQuery>;
15
+ declare const CombinedExport: z.ZodObject<{
16
+ queries: z.ZodPipe<z.ZodNullable<z.ZodArray<z.ZodObject<{
17
+ username: z.ZodString;
18
+ query: z.ZodString;
19
+ meanTime: z.ZodNumber;
20
+ calls: z.ZodCoercedString<unknown>;
21
+ rows: z.ZodCoercedString<unknown>;
22
+ topLevel: z.ZodBoolean;
23
+ }, z.core.$strip>>>, z.ZodTransform<{
24
+ username: string;
25
+ query: string;
26
+ meanTime: number;
27
+ calls: string;
28
+ rows: string;
29
+ topLevel: boolean;
30
+ }[], {
31
+ username: string;
32
+ query: string;
33
+ meanTime: number;
34
+ calls: string;
35
+ rows: string;
36
+ topLevel: boolean;
37
+ }[] | null>>;
38
+ stats: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
39
+ tableName: z.ZodString;
40
+ schemaName: z.ZodString;
41
+ relpages: z.ZodNumber;
42
+ reltuples: z.ZodNumber;
43
+ relallvisible: z.ZodNumber;
44
+ relallfrozen: z.ZodOptional<z.ZodNumber>;
45
+ columns: z.ZodDefault<z.ZodArray<z.ZodObject<{
46
+ columnName: z.ZodString;
47
+ attlen: z.ZodNullable<z.ZodNumber>;
48
+ dataType: z.ZodOptional<z.ZodString>;
49
+ stats: z.ZodNullable<z.ZodObject<{
50
+ stawidth: z.ZodNumber;
51
+ stainherit: z.ZodDefault<z.ZodBoolean>;
52
+ stadistinct: z.ZodNumber;
53
+ stanullfrac: z.ZodNumber;
54
+ stakind1: z.ZodNumber;
55
+ stakind2: z.ZodNumber;
56
+ stakind3: z.ZodNumber;
57
+ stakind4: z.ZodNumber;
58
+ stakind5: z.ZodNumber;
59
+ staop1: z.ZodString;
60
+ staop2: z.ZodString;
61
+ staop3: z.ZodString;
62
+ staop4: z.ZodString;
63
+ staop5: z.ZodString;
64
+ stacoll1: z.ZodString;
65
+ stacoll2: z.ZodString;
66
+ stacoll3: z.ZodString;
67
+ stacoll4: z.ZodString;
68
+ stacoll5: z.ZodString;
69
+ stanumbers1: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
70
+ stanumbers2: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
71
+ stanumbers3: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
72
+ stanumbers4: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
73
+ stanumbers5: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
74
+ stavalues1: z.ZodNullable<z.ZodArray<z.ZodAny>>;
75
+ stavalues2: z.ZodNullable<z.ZodArray<z.ZodAny>>;
76
+ stavalues3: z.ZodNullable<z.ZodArray<z.ZodAny>>;
77
+ stavalues4: z.ZodNullable<z.ZodArray<z.ZodAny>>;
78
+ stavalues5: z.ZodNullable<z.ZodArray<z.ZodAny>>;
79
+ }, z.core.$strip>>;
80
+ }, z.core.$strip>>>;
81
+ indexes: z.ZodArray<z.ZodObject<{
82
+ indexName: z.ZodString;
83
+ amname: z.ZodDefault<z.ZodString>;
84
+ relpages: z.ZodNumber;
85
+ reltuples: z.ZodNumber;
86
+ relallvisible: z.ZodNumber;
87
+ relallfrozen: z.ZodOptional<z.ZodNumber>;
88
+ fillfactor: z.ZodDefault<z.ZodNumber>;
89
+ columns: z.ZodDefault<z.ZodArray<z.ZodObject<{
90
+ attlen: z.ZodNullable<z.ZodNumber>;
91
+ }, z.core.$strip>>>;
92
+ }, z.core.$strip>>;
93
+ }, z.core.$strip>]>>;
94
+ }, z.core.$strip>;
95
+ type CombinedExport = z.infer<typeof CombinedExport>;
96
+ type QuerySource = "pg_stat_statements" | "pg_stat_monitor";
97
+ declare function dumpQueriesSql(schema: string, source?: QuerySource): string;
98
+ declare function combinedDumpSql(schema: string, source?: QuerySource): string;
99
+ //#endregion
100
+ export { CombinedExport, ExportedQuery, QuerySource, combinedDumpSql, dumpQueriesSql };
101
+ //# sourceMappingURL=dump.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump.d.mts","names":[],"sources":["../../src/optimizer/dump.ts"],"mappings":";;;;;cAKa,aAAA,EAAa,CAAA,CAAA,SAAA;;;;;;;;KASd,aAAA,GAAgB,CAAA,CAAE,KAAA,QAAa,aAAA;AAAA,cAE9B,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKf,cAAA,GAAiB,CAAA,CAAE,KAAA,QAAa,cAAA;AAAA,KAEhC,WAAA;AAAA,iBAWI,cAAA,CACd,MAAA,UACA,MAAA,GAAQ,WAAA;AAAA,iBAkCM,eAAA,CACd,MAAA,UACA,MAAA,GAAQ,WAAA"}
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { PgIdentifier } from "../sql/pg-identifier.mjs";
3
+ import { DUMP_STATS_SQL, ExportedStats } from "./statistics.mjs";
4
+ import { z } from "zod";
5
+ import dedent from "dedent";
6
+ //#region src/optimizer/dump.ts
7
+ const ExportedQuery = z.object({
8
+ username: z.string(),
9
+ query: z.string(),
10
+ meanTime: z.number(),
11
+ calls: z.coerce.string(),
12
+ rows: z.coerce.string(),
13
+ topLevel: z.boolean()
14
+ });
15
+ const CombinedExport = z.object({
16
+ queries: z.array(ExportedQuery).nullable().transform((v) => v ?? []),
17
+ stats: z.array(ExportedStats)
18
+ });
19
+ function indent(sql, spaces) {
20
+ const pad = " ".repeat(spaces);
21
+ return sql.trim().split("\n").map((line) => pad + line).join("\n");
22
+ }
23
+ function dumpQueriesSql(schema, source = "pg_stat_statements") {
24
+ const quotedSchema = PgIdentifier.fromString(schema).toString();
25
+ if (source === "pg_stat_monitor") return dedent`
26
+ SELECT
27
+ COALESCE(username, 'unknown_user') as "username",
28
+ query,
29
+ mean_exec_time as "meanTime",
30
+ calls,
31
+ rows,
32
+ toplevel as "topLevel"
33
+ FROM ${quotedSchema}.pg_stat_monitor
34
+ WHERE query NOT LIKE '%pg_stat_monitor%'
35
+ AND query NOT LIKE '%@qd_introspection%'
36
+ AND query NOT ILIKE 'explain%'
37
+ `;
38
+ return dedent`
39
+ SELECT
40
+ 'unknown_user' as "username",
41
+ query,
42
+ mean_exec_time as "meanTime",
43
+ calls,
44
+ rows,
45
+ toplevel as "topLevel"
46
+ FROM ${quotedSchema}.pg_stat_statements
47
+ WHERE query NOT LIKE '%pg_stat_statements%'
48
+ AND query NOT LIKE '%@qd_introspection%'
49
+ AND query != '<insufficient privilege>'
50
+ AND query NOT ILIKE 'explain%'
51
+ `;
52
+ }
53
+ function combinedDumpSql(schema, source = "pg_stat_statements") {
54
+ const statsSql = indent(DUMP_STATS_SQL, 6);
55
+ return [
56
+ "SELECT json_build_object(",
57
+ ` 'queries', (SELECT json_agg(q) FROM (`,
58
+ indent(dumpQueriesSql(schema, source), 8),
59
+ ` ) q),`,
60
+ ` 'stats', (`,
61
+ statsSql,
62
+ ` )`,
63
+ `);`
64
+ ].join("\n");
65
+ }
66
+ //#endregion
67
+ export { CombinedExport, ExportedQuery, combinedDumpSql, dumpQueriesSql };
68
+
69
+ //# sourceMappingURL=dump.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dump.mjs","names":[],"sources":["../../src/optimizer/dump.ts"],"sourcesContent":["import dedent from \"dedent\";\nimport { z } from \"zod\";\nimport { PgIdentifier } from \"../sql/pg-identifier.js\";\nimport { DUMP_STATS_SQL, ExportedStats } from \"./statistics.js\";\n\nexport const ExportedQuery = z.object({\n username: z.string(),\n query: z.string(),\n meanTime: z.number(),\n calls: z.coerce.string(),\n rows: z.coerce.string(),\n topLevel: z.boolean(),\n});\n\nexport type ExportedQuery = z.infer<typeof ExportedQuery>;\n\nexport const CombinedExport = z.object({\n queries: z.array(ExportedQuery).nullable().transform((v) => v ?? []),\n stats: z.array(ExportedStats),\n});\n\nexport type CombinedExport = z.infer<typeof CombinedExport>;\n\nexport type QuerySource = \"pg_stat_statements\" | \"pg_stat_monitor\";\n\nfunction indent(sql: string, spaces: number): string {\n const pad = \" \".repeat(spaces);\n return sql\n .trim()\n .split(\"\\n\")\n .map((line) => pad + line)\n .join(\"\\n\");\n}\n\nexport function dumpQueriesSql(\n schema: string,\n source: QuerySource = \"pg_stat_statements\",\n): string {\n const quotedSchema = PgIdentifier.fromString(schema).toString();\n if (source === \"pg_stat_monitor\") {\n return dedent`\n SELECT\n COALESCE(username, 'unknown_user') as \"username\",\n query,\n mean_exec_time as \"meanTime\",\n calls,\n rows,\n toplevel as \"topLevel\"\n FROM ${quotedSchema}.pg_stat_monitor\n WHERE query NOT LIKE '%pg_stat_monitor%'\n AND query NOT LIKE '%@qd_introspection%'\n AND query NOT ILIKE 'explain%'\n `;\n }\n return dedent`\n SELECT\n 'unknown_user' as \"username\",\n query,\n mean_exec_time as \"meanTime\",\n calls,\n rows,\n toplevel as \"topLevel\"\n FROM ${quotedSchema}.pg_stat_statements\n WHERE query NOT LIKE '%pg_stat_statements%'\n AND query NOT LIKE '%@qd_introspection%'\n AND query != '<insufficient privilege>'\n AND query NOT ILIKE 'explain%'\n `;\n}\n\nexport function combinedDumpSql(\n schema: string,\n source: QuerySource = \"pg_stat_statements\",\n): string {\n const statsSql = indent(DUMP_STATS_SQL, 6);\n const queriesSql = indent(dumpQueriesSql(schema, source), 8);\n return [\n \"SELECT json_build_object(\",\n ` 'queries', (SELECT json_agg(q) FROM (`,\n queriesSql,\n ` ) q),`,\n ` 'stats', (`,\n statsSql,\n ` )`,\n `);`,\n ].join(\"\\n\");\n}\n"],"mappings":";;;;;;AAKA,MAAa,gBAAgB,EAAE,OAAO;CACpC,UAAU,EAAE,QAAQ;CACpB,OAAO,EAAE,QAAQ;CACjB,UAAU,EAAE,QAAQ;CACpB,OAAO,EAAE,OAAO,QAAQ;CACxB,MAAM,EAAE,OAAO,QAAQ;CACvB,UAAU,EAAE,SAAS;CACtB,CAAC;AAIF,MAAa,iBAAiB,EAAE,OAAO;CACrC,SAAS,EAAE,MAAM,cAAc,CAAC,UAAU,CAAC,WAAW,MAAM,KAAK,EAAE,CAAC;CACpE,OAAO,EAAE,MAAM,cAAc;CAC9B,CAAC;AAMF,SAAS,OAAO,KAAa,QAAwB;CACnD,MAAM,MAAM,IAAI,OAAO,OAAO;AAC9B,QAAO,IACJ,MAAM,CACN,MAAM,KAAK,CACX,KAAK,SAAS,MAAM,KAAK,CACzB,KAAK,KAAK;;AAGf,SAAgB,eACd,QACA,SAAsB,sBACd;CACR,MAAM,eAAe,aAAa,WAAW,OAAO,CAAC,UAAU;AAC/D,KAAI,WAAW,kBACb,QAAO,MAAM;;;;;;;;aAQJ,aAAa;;;;;AAMxB,QAAO,MAAM;;;;;;;;WAQJ,aAAa;;;;;;;AAQxB,SAAgB,gBACd,QACA,SAAsB,sBACd;CACR,MAAM,WAAW,OAAO,gBAAgB,EAAE;AAE1C,QAAO;EACL;EACA;EAHiB,OAAO,eAAe,QAAQ,OAAO,EAAE,EAAE;EAK1D;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK"}
@@ -143,6 +143,112 @@ function estimateIndexRelpages(reltuples, columns, fillfactor, amname, tableRelp
143
143
  const keyWidth = columns.reduce((sum, col) => sum + estimateStawidth(col) + 16, 0);
144
144
  return Math.ceil(reltuples * keyWidth / DEFAULT_PAGE_SIZE / fillfactor);
145
145
  }
146
+ const DUMP_STATS_SQL = dedent.default`
147
+ WITH table_columns AS (
148
+ SELECT
149
+ cl.relname,
150
+ n.nspname,
151
+ cl.reltuples,
152
+ cl.relpages,
153
+ cl.relallvisible,
154
+ -- cl.relallfrozen,
155
+ json_agg(
156
+ json_build_object(
157
+ 'columnName', a.attname,
158
+ 'attlen', CASE WHEN a.attlen > 0 THEN a.attlen ELSE NULL END,
159
+ 'dataType', t.typname,
160
+ 'stats', (
161
+ SELECT json_build_object(
162
+ 'starelid', s.starelid,
163
+ 'staattnum', s.staattnum,
164
+ 'stanullfrac', s.stanullfrac,
165
+ 'stawidth', s.stawidth,
166
+ 'stadistinct', s.stadistinct,
167
+ 'stakind1', s.stakind1, 'staop1', s.staop1, 'stacoll1', s.stacoll1, 'stanumbers1', s.stanumbers1,
168
+ 'stakind2', s.stakind2, 'staop2', s.staop2, 'stacoll2', s.stacoll2, 'stanumbers2', s.stanumbers2,
169
+ 'stakind3', s.stakind3, 'staop3', s.staop3, 'stacoll3', s.stacoll3, 'stanumbers3', s.stanumbers3,
170
+ 'stakind4', s.stakind4, 'staop4', s.staop4, 'stacoll4', s.stacoll4, 'stanumbers4', s.stanumbers4,
171
+ 'stakind5', s.stakind5, 'staop5', s.staop5, 'stacoll5', s.stacoll5, 'stanumbers5', s.stanumbers5,
172
+ 'stavalues1', s.stavalues1,
173
+ 'stavalues2', s.stavalues2,
174
+ 'stavalues3', s.stavalues3,
175
+ 'stavalues4', s.stavalues4,
176
+ 'stavalues5', s.stavalues5
177
+ )
178
+ FROM pg_statistic s
179
+ WHERE s.starelid = a.attrelid AND s.staattnum = a.attnum
180
+ )
181
+ )
182
+ ORDER BY a.attnum
183
+ ) AS columns
184
+ FROM pg_class cl
185
+ JOIN pg_namespace n ON n.oid = cl.relnamespace
186
+ JOIN pg_attribute a ON a.attrelid = cl.oid AND a.attnum > 0 AND NOT a.attisdropped
187
+ JOIN pg_type t ON t.oid = a.atttypid
188
+ WHERE cl.relkind = 'r'
189
+ AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'tiger', 'tiger_data', 'topology')
190
+ AND cl.relname NOT IN ('pg_stat_statements', 'pg_stat_statements_info')
191
+ GROUP BY cl.relname, n.nspname, cl.reltuples, cl.relpages, cl.relallvisible
192
+ ),
193
+ table_indexes AS (
194
+ SELECT
195
+ t.relname AS table_name,
196
+ json_agg(
197
+ json_build_object(
198
+ 'indexName', i.relname,
199
+ 'amname', am.amname,
200
+ 'reltuples', i.reltuples,
201
+ 'relpages', i.relpages,
202
+ 'relallvisible', i.relallvisible,
203
+ -- 'relallfrozen', i.relallfrozen,
204
+ 'fillfactor', COALESCE(
205
+ (
206
+ SELECT (regexp_match(opt, 'fillfactor=(\\d+)'))[1]::integer
207
+ FROM unnest(i.reloptions) AS opt
208
+ WHERE opt LIKE 'fillfactor=%'
209
+ LIMIT 1
210
+ ),
211
+ 90
212
+ ),
213
+ 'columns', COALESCE(
214
+ (
215
+ SELECT json_agg(json_build_object(
216
+ 'attlen', CASE WHEN a.attlen > 0 THEN a.attlen ELSE NULL END
217
+ ) ORDER BY col_pos.ord)
218
+ FROM unnest(ix.indkey) WITH ORDINALITY AS col_pos(attnum, ord)
219
+ JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = col_pos.attnum
220
+ WHERE col_pos.attnum > 0
221
+ ),
222
+ '[]'::json
223
+ )
224
+ )
225
+ ) AS indexes
226
+ FROM pg_class t
227
+ JOIN pg_index ix ON ix.indrelid = t.oid
228
+ JOIN pg_class i ON i.oid = ix.indexrelid
229
+ JOIN pg_am am ON am.oid = i.relam
230
+ JOIN pg_namespace n ON n.oid = t.relnamespace
231
+ WHERE t.relname NOT LIKE 'pg_%'
232
+ AND n.nspname <> 'information_schema'
233
+ AND n.nspname NOT IN ('tiger', 'tiger_data', 'topology')
234
+ GROUP BY t.relname
235
+ )
236
+ SELECT json_agg(
237
+ json_build_object(
238
+ 'tableName', tc.relname,
239
+ 'schemaName', tc.nspname,
240
+ 'reltuples', tc.reltuples,
241
+ 'relpages', tc.relpages,
242
+ 'relallvisible', tc.relallvisible,
243
+ -- 'relallfrozen', tc.relallfrozen,
244
+ 'columns', COALESCE(tc.columns, '[]'::json),
245
+ 'indexes', COALESCE(ti.indexes, '[]'::json)
246
+ )
247
+ )
248
+ FROM table_columns tc
249
+ LEFT JOIN table_indexes ti
250
+ ON ti.table_name = tc.relname
251
+ `;
146
252
  var Statistics = class Statistics {
147
253
  constructor(db, postgresVersion, ownMetadata, statsMode) {
148
254
  this.db = db;
@@ -315,7 +421,7 @@ var Statistics = class Statistics {
315
421
  }
316
422
  static async fromPostgres(db, statsMode) {
317
423
  const version = await db.serverNum();
318
- return new Statistics(db, version, await Statistics.dumpStats(db, version, "full"), statsMode);
424
+ return new Statistics(db, version, await Statistics.dumpStats(db, version), statsMode);
319
425
  }
320
426
  restoreStats(tx) {
321
427
  return this.restoreStats17(tx);
@@ -421,115 +527,9 @@ var Statistics = class Statistics {
421
527
  if (reltuplesUpdates.length !== this.computedStats.reltuples.length) console.error(`Did not update expected reltuples/relpages`);
422
528
  return warnings;
423
529
  }
424
- static async dumpStats(db, postgresVersion, kind) {
425
- const fullDump = kind === "full";
530
+ static async dumpStats(db, postgresVersion) {
426
531
  console.log(`dumping stats for postgres ${(0, colorette.gray)(postgresVersion)}`);
427
- const stats = await db.exec(`
428
- WITH table_columns AS (
429
- SELECT
430
- cl.relname,
431
- n.nspname,
432
- cl.reltuples,
433
- cl.relpages,
434
- cl.relallvisible,
435
- -- cl.relallfrozen,
436
- json_agg(
437
- json_build_object(
438
- 'columnName', a.attname,
439
- 'attlen', CASE WHEN a.attlen > 0 THEN a.attlen ELSE NULL END,
440
- 'dataType', t.typname,
441
- 'stats', (
442
- SELECT json_build_object(
443
- 'starelid', s.starelid,
444
- 'staattnum', s.staattnum,
445
- 'stanullfrac', s.stanullfrac,
446
- 'stawidth', s.stawidth,
447
- 'stadistinct', s.stadistinct,
448
- 'stakind1', s.stakind1, 'staop1', s.staop1, 'stacoll1', s.stacoll1, 'stanumbers1', s.stanumbers1,
449
- 'stakind2', s.stakind2, 'staop2', s.staop2, 'stacoll2', s.stacoll2, 'stanumbers2', s.stanumbers2,
450
- 'stakind3', s.stakind3, 'staop3', s.staop3, 'stacoll3', s.stacoll3, 'stanumbers3', s.stanumbers3,
451
- 'stakind4', s.stakind4, 'staop4', s.staop4, 'stacoll4', s.stacoll4, 'stanumbers4', s.stanumbers4,
452
- 'stakind5', s.stakind5, 'staop5', s.staop5, 'stacoll5', s.stacoll5, 'stanumbers5', s.stanumbers5,
453
- 'stavalues1', CASE WHEN $1 THEN s.stavalues1 ELSE NULL END,
454
- 'stavalues2', CASE WHEN $1 THEN s.stavalues2 ELSE NULL END,
455
- 'stavalues3', CASE WHEN $1 THEN s.stavalues3 ELSE NULL END,
456
- 'stavalues4', CASE WHEN $1 THEN s.stavalues4 ELSE NULL END,
457
- 'stavalues5', CASE WHEN $1 THEN s.stavalues5 ELSE NULL END
458
- )
459
- FROM pg_statistic s
460
- WHERE s.starelid = a.attrelid AND s.staattnum = a.attnum
461
- )
462
- )
463
- ORDER BY a.attnum
464
- ) AS columns
465
- FROM pg_class cl
466
- JOIN pg_namespace n ON n.oid = cl.relnamespace
467
- JOIN pg_attribute a ON a.attrelid = cl.oid AND a.attnum > 0 AND NOT a.attisdropped
468
- JOIN pg_type t ON t.oid = a.atttypid
469
- WHERE cl.relkind = 'r'
470
- AND n.nspname NOT IN ('pg_catalog', 'information_schema', 'tiger', 'tiger_data', 'topology')
471
- AND cl.relname NOT IN ('pg_stat_statements', 'pg_stat_statements_info')
472
- GROUP BY cl.relname, n.nspname, cl.reltuples, cl.relpages, cl.relallvisible
473
- ),
474
- table_indexes AS (
475
- SELECT
476
- t.relname AS table_name,
477
- json_agg(
478
- json_build_object(
479
- 'indexName', i.relname,
480
- 'amname', am.amname,
481
- 'reltuples', i.reltuples,
482
- 'relpages', i.relpages,
483
- 'relallvisible', i.relallvisible,
484
- -- 'relallfrozen', i.relallfrozen,
485
- 'fillfactor', COALESCE(
486
- (
487
- SELECT (regexp_match(opt, 'fillfactor=(\\d+)'))[1]::integer
488
- FROM unnest(i.reloptions) AS opt
489
- WHERE opt LIKE 'fillfactor=%'
490
- LIMIT 1
491
- ),
492
- 90
493
- ),
494
- 'columns', COALESCE(
495
- (
496
- SELECT json_agg(json_build_object(
497
- 'attlen', CASE WHEN a.attlen > 0 THEN a.attlen ELSE NULL END
498
- ) ORDER BY col_pos.ord)
499
- FROM unnest(ix.indkey) WITH ORDINALITY AS col_pos(attnum, ord)
500
- JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = col_pos.attnum
501
- WHERE col_pos.attnum > 0
502
- ),
503
- '[]'::json
504
- )
505
- )
506
- ) AS indexes
507
- FROM pg_class t
508
- JOIN pg_index ix ON ix.indrelid = t.oid
509
- JOIN pg_class i ON i.oid = ix.indexrelid
510
- JOIN pg_am am ON am.oid = i.relam
511
- JOIN pg_namespace n ON n.oid = t.relnamespace
512
- WHERE t.relname NOT LIKE 'pg_%'
513
- AND n.nspname <> 'information_schema'
514
- AND n.nspname NOT IN ('tiger', 'tiger_data', 'topology')
515
- GROUP BY t.relname
516
- )
517
- SELECT json_agg(
518
- json_build_object(
519
- 'tableName', tc.relname,
520
- 'schemaName', tc.nspname,
521
- 'reltuples', tc.reltuples,
522
- 'relpages', tc.relpages,
523
- 'relallvisible', tc.relallvisible,
524
- -- 'relallfrozen', tc.relallfrozen,
525
- 'columns', COALESCE(tc.columns, '[]'::json),
526
- 'indexes', COALESCE(ti.indexes, '[]'::json)
527
- )
528
- )
529
- FROM table_columns tc
530
- LEFT JOIN table_indexes ti
531
- ON ti.table_name = tc.relname;
532
- `, [fullDump]);
532
+ const stats = await db.exec(DUMP_STATS_SQL);
533
533
  return zod.z.array(ExportedStats).parse(stats[0].json_agg);
534
534
  }
535
535
  /**
@@ -784,6 +784,7 @@ require_defineProperty._defineProperty(Statistics, "columnStatsSQL", dedent.defa
784
784
  exports.ComputedColumnStats = ComputedColumnStats;
785
785
  exports.ComputedReltuples = ComputedReltuples;
786
786
  exports.ComputedStats = ComputedStats;
787
+ exports.DUMP_STATS_SQL = DUMP_STATS_SQL;
787
788
  exports.ExportedStats = ExportedStats;
788
789
  exports.ExportedStatsColumns = ExportedStatsColumns;
789
790
  exports.ExportedStatsIndex = ExportedStatsIndex;