@query-doctor/core 0.1.7 → 0.1.10
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.
- package/dist/index.cjs +47 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +47 -5
- package/dist/index.js.map +1 -1
- package/dist/optimizer/genalgo.d.ts +14 -0
- package/dist/optimizer/genalgo.d.ts.map +1 -1
- package/dist/optimizer/statistics.d.ts.map +1 -1
- package/dist/sql/analyzer.d.ts.map +1 -1
- package/dist/sql/nudges.d.ts +1 -1
- package/dist/sql/nudges.d.ts.map +1 -1
- package/dist/sql/walker.d.ts.map +1 -1
- package/dist/sql/walker.test.d.ts +2 -0
- package/dist/sql/walker.test.d.ts.map +1 -0
- package/package.json +2 -3
- package/.eslintrc.cjs +0 -4
package/dist/index.js
CHANGED
|
@@ -139,6 +139,23 @@ function parseNudges(node, stack) {
|
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
if (is(node, "A_Expr")) {
|
|
143
|
+
if (node.A_Expr.kind === "AEXPR_IN") {
|
|
144
|
+
let list;
|
|
145
|
+
if (node.A_Expr.lexpr && is(node.A_Expr.lexpr, "List")) {
|
|
146
|
+
list = node.A_Expr.lexpr.List;
|
|
147
|
+
} else if (node.A_Expr.rexpr && is(node.A_Expr.rexpr, "List")) {
|
|
148
|
+
list = node.A_Expr.rexpr.List;
|
|
149
|
+
}
|
|
150
|
+
if (list?.items && list.items.length >= 10) {
|
|
151
|
+
nudges.push({
|
|
152
|
+
kind: "REPLACE_LARGE_IN_TUPLE_WITH_ANY_ARRAY",
|
|
153
|
+
message: "`in (...)` queries with large tuples can often be replaced with `= ANY($1)` using a single parameter",
|
|
154
|
+
severity: "INFO"
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
142
159
|
return nudges;
|
|
143
160
|
}
|
|
144
161
|
function containsColumnRef(args) {
|
|
@@ -294,9 +311,12 @@ var Walker = class _Walker {
|
|
|
294
311
|
part.schema = node.RangeVar.schemaname;
|
|
295
312
|
}
|
|
296
313
|
if (existingMapping) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
314
|
+
const isSystemCatalog = node.RangeVar.relname?.startsWith("pg_") ?? false;
|
|
315
|
+
if (!isSystemCatalog) {
|
|
316
|
+
console.warn(
|
|
317
|
+
`Ignoring alias ${aliasName} as it shadows an existing mapping for ${existingMapping.text}. We currently do not support alias shadowing.`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
300
320
|
this.shadowedAliases.push(part);
|
|
301
321
|
return;
|
|
302
322
|
}
|
|
@@ -694,7 +714,7 @@ var Analyzer = class {
|
|
|
694
714
|
return { tags: [], queryWithoutTags: trimmedQuery };
|
|
695
715
|
}
|
|
696
716
|
const queryWithoutTags = trimmedQuery.slice(0, startPosition);
|
|
697
|
-
const tagString = trimmedQuery.slice(startPosition + 2, endPosition);
|
|
717
|
+
const tagString = trimmedQuery.slice(startPosition + 2, endPosition).trim();
|
|
698
718
|
if (!tagString || typeof tagString !== "string") {
|
|
699
719
|
return { tags: [], queryWithoutTags };
|
|
700
720
|
}
|
|
@@ -702,7 +722,11 @@ var Analyzer = class {
|
|
|
702
722
|
for (const match of tagString.split(",")) {
|
|
703
723
|
const [key, value] = match.split("=");
|
|
704
724
|
if (!key || !value) {
|
|
705
|
-
|
|
725
|
+
if (tags.length > 0) {
|
|
726
|
+
console.warn(
|
|
727
|
+
`Invalid sqlcommenter tag: ${match} in comment: ${tagString}. Ignoring`
|
|
728
|
+
);
|
|
729
|
+
}
|
|
706
730
|
continue;
|
|
707
731
|
}
|
|
708
732
|
try {
|
|
@@ -1108,6 +1132,24 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1108
1132
|
await this.dropExistingIndexes(tx);
|
|
1109
1133
|
});
|
|
1110
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Given the current indexes in the optimizer, transform them in some
|
|
1137
|
+
* way to change which indexes will be assumed to exist when optimizing
|
|
1138
|
+
*
|
|
1139
|
+
* @example
|
|
1140
|
+
* ```
|
|
1141
|
+
* // resets indexes
|
|
1142
|
+
* optimizer.transformIndexes(() => [])
|
|
1143
|
+
*
|
|
1144
|
+
* // adds new index
|
|
1145
|
+
* optimizer.transformIndexes(indexes => [...indexes, newIndex])
|
|
1146
|
+
* ```
|
|
1147
|
+
*/
|
|
1148
|
+
transformIndexes(f) {
|
|
1149
|
+
const newIndexes = f(this.existingIndexes);
|
|
1150
|
+
this.existingIndexes = newIndexes;
|
|
1151
|
+
return this;
|
|
1152
|
+
}
|
|
1111
1153
|
/**
|
|
1112
1154
|
* Postgres has a limit of 63 characters for index names.
|
|
1113
1155
|
* So we use this to make sure we don't derive it from a list of columns that can
|