@query-doctor/core 0.2.3 → 0.2.5
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 +52 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +51 -27
- package/dist/index.js.map +1 -1
- package/dist/optimizer/genalgo.d.ts +1 -6
- package/dist/optimizer/genalgo.d.ts.map +1 -1
- package/dist/sql/permutations.d.ts +10 -0
- package/dist/sql/permutations.d.ts.map +1 -0
- package/dist/sql/pg-identifier.d.ts.map +1 -1
- package/package.json +5 -4
- package/dist/optimizer/pss-rewriter.test.d.ts +0 -2
- package/dist/optimizer/pss-rewriter.test.d.ts.map +0 -1
- package/dist/sql/analyzer.test.d.ts +0 -2
- package/dist/sql/analyzer.test.d.ts.map +0 -1
- package/dist/sql/permutations.test.d.ts +0 -2
- package/dist/sql/permutations.test.d.ts.map +0 -1
- package/dist/sql/pg-identifier.test.d.ts +0 -2
- package/dist/sql/pg-identifier.test.d.ts.map +0 -1
- package/dist/sql/walker.test.d.ts +0 -2
- package/dist/sql/walker.test.d.ts.map +0 -1
- package/tsconfig.json +0 -12
package/dist/index.js
CHANGED
|
@@ -866,7 +866,9 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
866
866
|
const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
|
|
867
867
|
const match = identifier.match(/^"(.+)"$/);
|
|
868
868
|
if (match) {
|
|
869
|
-
|
|
869
|
+
const value = match[1];
|
|
870
|
+
const quoted2 = !identifierRegex.test(value) || this.reservedKeywords.has(value.toLowerCase());
|
|
871
|
+
return new _PgIdentifier(value, quoted2);
|
|
870
872
|
}
|
|
871
873
|
const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
|
|
872
874
|
return new _PgIdentifier(identifier, quoted);
|
|
@@ -1071,6 +1073,24 @@ var PgIdentifier = _PgIdentifier;
|
|
|
1071
1073
|
|
|
1072
1074
|
// src/optimizer/genalgo.ts
|
|
1073
1075
|
import { blue as blue2, gray, green, magenta, red, yellow } from "colorette";
|
|
1076
|
+
|
|
1077
|
+
// src/sql/permutations.ts
|
|
1078
|
+
function permutationsWithDescendingLength(arr) {
|
|
1079
|
+
const collected = [];
|
|
1080
|
+
function collect(path, rest) {
|
|
1081
|
+
for (let i = 0; i < rest.length; i++) {
|
|
1082
|
+
const nextRest = [...rest.slice(0, i), ...rest.slice(i + 1)];
|
|
1083
|
+
const nextPath = [...path, rest[i]];
|
|
1084
|
+
collected.push(nextPath);
|
|
1085
|
+
collect(nextPath, nextRest);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
collect([], arr);
|
|
1089
|
+
collected.sort((a, b) => b.length - a.length);
|
|
1090
|
+
return collected;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// src/optimizer/genalgo.ts
|
|
1074
1094
|
var _IndexOptimizer = class _IndexOptimizer {
|
|
1075
1095
|
constructor(db, statistics, existingIndexes, config = {}) {
|
|
1076
1096
|
this.db = db;
|
|
@@ -1172,21 +1192,43 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1172
1192
|
// TODO: this doesn't belong in the optimizer
|
|
1173
1193
|
indexAlreadyExists(table, columns) {
|
|
1174
1194
|
return this.existingIndexes.find(
|
|
1175
|
-
(index) => index.index_type === "btree" && index.table_name === table && index.index_columns.length === columns.length && index.index_columns.every((c, i) =>
|
|
1195
|
+
(index) => index.index_type === "btree" && index.table_name === table && index.index_columns.length === columns.length && index.index_columns.every((c, i) => {
|
|
1196
|
+
if (columns[i].column !== c.name) {
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
if (columns[i].where) {
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
if (columns[i].sort) {
|
|
1203
|
+
switch (columns[i].sort.dir) {
|
|
1204
|
+
// Sorting is ASC by default in postgres
|
|
1205
|
+
case "SORTBY_DEFAULT":
|
|
1206
|
+
case "SORTBY_ASC":
|
|
1207
|
+
if (c.order !== "ASC") {
|
|
1208
|
+
return false;
|
|
1209
|
+
}
|
|
1210
|
+
break;
|
|
1211
|
+
case "SORTBY_DESC":
|
|
1212
|
+
if (c.order !== "DESC") {
|
|
1213
|
+
return false;
|
|
1214
|
+
}
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return true;
|
|
1219
|
+
})
|
|
1176
1220
|
);
|
|
1177
1221
|
}
|
|
1178
1222
|
/**
|
|
1179
1223
|
* Derive the list of indexes [tableA(X, Y, Z), tableB(H, I, J)]
|
|
1180
1224
|
**/
|
|
1181
1225
|
indexesToCreate(rootCandidates) {
|
|
1182
|
-
const permutedIndexes = this.
|
|
1226
|
+
const permutedIndexes = this.groupPotentialIndexColumnsByTable(rootCandidates);
|
|
1183
1227
|
const nextStage = [];
|
|
1184
1228
|
for (const permutation of permutedIndexes.values()) {
|
|
1185
1229
|
const { table: rawTable, schema: rawSchema, columns } = permutation;
|
|
1186
|
-
const permutations =
|
|
1187
|
-
|
|
1188
|
-
while (!iter.done) {
|
|
1189
|
-
const columns2 = iter.value;
|
|
1230
|
+
const permutations = permutationsWithDescendingLength(columns);
|
|
1231
|
+
for (const columns2 of permutations) {
|
|
1190
1232
|
const schema = PgIdentifier.fromString(rawSchema);
|
|
1191
1233
|
const table = PgIdentifier.fromString(rawTable);
|
|
1192
1234
|
const existingIndex = this.indexAlreadyExists(
|
|
@@ -1194,12 +1236,10 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1194
1236
|
columns2
|
|
1195
1237
|
);
|
|
1196
1238
|
if (existingIndex) {
|
|
1197
|
-
iter = permutations.next(PROCEED);
|
|
1198
1239
|
continue;
|
|
1199
1240
|
}
|
|
1200
1241
|
const indexName = this.indexName();
|
|
1201
1242
|
const definition = this.toDefinition({ table, schema, columns: columns2 }).raw;
|
|
1202
|
-
iter = permutations.next(PROCEED);
|
|
1203
1243
|
nextStage.push({
|
|
1204
1244
|
name: indexName,
|
|
1205
1245
|
schema: schema.toString(),
|
|
@@ -1331,7 +1371,7 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1331
1371
|
}
|
|
1332
1372
|
throw new Error("Unreachable");
|
|
1333
1373
|
}
|
|
1334
|
-
|
|
1374
|
+
groupPotentialIndexColumnsByTable(indexes) {
|
|
1335
1375
|
const tableColumns = /* @__PURE__ */ new Map();
|
|
1336
1376
|
for (const index of indexes) {
|
|
1337
1377
|
const existing = tableColumns.get(`${index.schema}.${index.table}`);
|
|
@@ -1401,21 +1441,6 @@ var RollbackError = class {
|
|
|
1401
1441
|
};
|
|
1402
1442
|
var PROCEED = Symbol("PROCEED");
|
|
1403
1443
|
var SKIP = Symbol("SKIP");
|
|
1404
|
-
function* permuteWithFeedback(arr) {
|
|
1405
|
-
function* helper(path, rest) {
|
|
1406
|
-
let i = 0;
|
|
1407
|
-
while (i < rest.length) {
|
|
1408
|
-
const nextPath = [...path, rest[i]];
|
|
1409
|
-
const nextRest = [...rest.slice(0, i), ...rest.slice(i + 1)];
|
|
1410
|
-
const input = yield nextPath;
|
|
1411
|
-
if (input === PROCEED) {
|
|
1412
|
-
yield* helper(nextPath, nextRest);
|
|
1413
|
-
}
|
|
1414
|
-
i++;
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
yield* helper([], arr);
|
|
1418
|
-
}
|
|
1419
1444
|
|
|
1420
1445
|
// src/optimizer/statistics.ts
|
|
1421
1446
|
import { gray as gray2 } from "colorette";
|
|
@@ -2131,7 +2156,6 @@ export {
|
|
|
2131
2156
|
ignoredIdentifier,
|
|
2132
2157
|
isIndexProbablyDroppable,
|
|
2133
2158
|
isIndexSupported,
|
|
2134
|
-
parseNudges
|
|
2135
|
-
permuteWithFeedback
|
|
2159
|
+
parseNudges
|
|
2136
2160
|
};
|
|
2137
2161
|
//# sourceMappingURL=index.js.map
|