@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.cjs
CHANGED
|
@@ -53,8 +53,7 @@ __export(index_exports, {
|
|
|
53
53
|
ignoredIdentifier: () => ignoredIdentifier,
|
|
54
54
|
isIndexProbablyDroppable: () => isIndexProbablyDroppable,
|
|
55
55
|
isIndexSupported: () => isIndexSupported,
|
|
56
|
-
parseNudges: () => parseNudges
|
|
57
|
-
permuteWithFeedback: () => permuteWithFeedback
|
|
56
|
+
parseNudges: () => parseNudges
|
|
58
57
|
});
|
|
59
58
|
module.exports = __toCommonJS(index_exports);
|
|
60
59
|
|
|
@@ -916,7 +915,9 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
916
915
|
const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
|
|
917
916
|
const match = identifier.match(/^"(.+)"$/);
|
|
918
917
|
if (match) {
|
|
919
|
-
|
|
918
|
+
const value = match[1];
|
|
919
|
+
const quoted2 = !identifierRegex.test(value) || this.reservedKeywords.has(value.toLowerCase());
|
|
920
|
+
return new _PgIdentifier(value, quoted2);
|
|
920
921
|
}
|
|
921
922
|
const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
|
|
922
923
|
return new _PgIdentifier(identifier, quoted);
|
|
@@ -1121,6 +1122,24 @@ var PgIdentifier = _PgIdentifier;
|
|
|
1121
1122
|
|
|
1122
1123
|
// src/optimizer/genalgo.ts
|
|
1123
1124
|
var import_colorette2 = require("colorette");
|
|
1125
|
+
|
|
1126
|
+
// src/sql/permutations.ts
|
|
1127
|
+
function permutationsWithDescendingLength(arr) {
|
|
1128
|
+
const collected = [];
|
|
1129
|
+
function collect(path, rest) {
|
|
1130
|
+
for (let i = 0; i < rest.length; i++) {
|
|
1131
|
+
const nextRest = [...rest.slice(0, i), ...rest.slice(i + 1)];
|
|
1132
|
+
const nextPath = [...path, rest[i]];
|
|
1133
|
+
collected.push(nextPath);
|
|
1134
|
+
collect(nextPath, nextRest);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
collect([], arr);
|
|
1138
|
+
collected.sort((a, b) => b.length - a.length);
|
|
1139
|
+
return collected;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// src/optimizer/genalgo.ts
|
|
1124
1143
|
var _IndexOptimizer = class _IndexOptimizer {
|
|
1125
1144
|
constructor(db, statistics, existingIndexes, config = {}) {
|
|
1126
1145
|
this.db = db;
|
|
@@ -1222,21 +1241,43 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1222
1241
|
// TODO: this doesn't belong in the optimizer
|
|
1223
1242
|
indexAlreadyExists(table, columns) {
|
|
1224
1243
|
return this.existingIndexes.find(
|
|
1225
|
-
(index) => index.index_type === "btree" && index.table_name === table && index.index_columns.length === columns.length && index.index_columns.every((c, i) =>
|
|
1244
|
+
(index) => index.index_type === "btree" && index.table_name === table && index.index_columns.length === columns.length && index.index_columns.every((c, i) => {
|
|
1245
|
+
if (columns[i].column !== c.name) {
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
if (columns[i].where) {
|
|
1249
|
+
return false;
|
|
1250
|
+
}
|
|
1251
|
+
if (columns[i].sort) {
|
|
1252
|
+
switch (columns[i].sort.dir) {
|
|
1253
|
+
// Sorting is ASC by default in postgres
|
|
1254
|
+
case "SORTBY_DEFAULT":
|
|
1255
|
+
case "SORTBY_ASC":
|
|
1256
|
+
if (c.order !== "ASC") {
|
|
1257
|
+
return false;
|
|
1258
|
+
}
|
|
1259
|
+
break;
|
|
1260
|
+
case "SORTBY_DESC":
|
|
1261
|
+
if (c.order !== "DESC") {
|
|
1262
|
+
return false;
|
|
1263
|
+
}
|
|
1264
|
+
break;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
return true;
|
|
1268
|
+
})
|
|
1226
1269
|
);
|
|
1227
1270
|
}
|
|
1228
1271
|
/**
|
|
1229
1272
|
* Derive the list of indexes [tableA(X, Y, Z), tableB(H, I, J)]
|
|
1230
1273
|
**/
|
|
1231
1274
|
indexesToCreate(rootCandidates) {
|
|
1232
|
-
const permutedIndexes = this.
|
|
1275
|
+
const permutedIndexes = this.groupPotentialIndexColumnsByTable(rootCandidates);
|
|
1233
1276
|
const nextStage = [];
|
|
1234
1277
|
for (const permutation of permutedIndexes.values()) {
|
|
1235
1278
|
const { table: rawTable, schema: rawSchema, columns } = permutation;
|
|
1236
|
-
const permutations =
|
|
1237
|
-
|
|
1238
|
-
while (!iter.done) {
|
|
1239
|
-
const columns2 = iter.value;
|
|
1279
|
+
const permutations = permutationsWithDescendingLength(columns);
|
|
1280
|
+
for (const columns2 of permutations) {
|
|
1240
1281
|
const schema = PgIdentifier.fromString(rawSchema);
|
|
1241
1282
|
const table = PgIdentifier.fromString(rawTable);
|
|
1242
1283
|
const existingIndex = this.indexAlreadyExists(
|
|
@@ -1244,12 +1285,10 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1244
1285
|
columns2
|
|
1245
1286
|
);
|
|
1246
1287
|
if (existingIndex) {
|
|
1247
|
-
iter = permutations.next(PROCEED);
|
|
1248
1288
|
continue;
|
|
1249
1289
|
}
|
|
1250
1290
|
const indexName = this.indexName();
|
|
1251
1291
|
const definition = this.toDefinition({ table, schema, columns: columns2 }).raw;
|
|
1252
|
-
iter = permutations.next(PROCEED);
|
|
1253
1292
|
nextStage.push({
|
|
1254
1293
|
name: indexName,
|
|
1255
1294
|
schema: schema.toString(),
|
|
@@ -1381,7 +1420,7 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1381
1420
|
}
|
|
1382
1421
|
throw new Error("Unreachable");
|
|
1383
1422
|
}
|
|
1384
|
-
|
|
1423
|
+
groupPotentialIndexColumnsByTable(indexes) {
|
|
1385
1424
|
const tableColumns = /* @__PURE__ */ new Map();
|
|
1386
1425
|
for (const index of indexes) {
|
|
1387
1426
|
const existing = tableColumns.get(`${index.schema}.${index.table}`);
|
|
@@ -1451,21 +1490,6 @@ var RollbackError = class {
|
|
|
1451
1490
|
};
|
|
1452
1491
|
var PROCEED = Symbol("PROCEED");
|
|
1453
1492
|
var SKIP = Symbol("SKIP");
|
|
1454
|
-
function* permuteWithFeedback(arr) {
|
|
1455
|
-
function* helper(path, rest) {
|
|
1456
|
-
let i = 0;
|
|
1457
|
-
while (i < rest.length) {
|
|
1458
|
-
const nextPath = [...path, rest[i]];
|
|
1459
|
-
const nextRest = [...rest.slice(0, i), ...rest.slice(i + 1)];
|
|
1460
|
-
const input = yield nextPath;
|
|
1461
|
-
if (input === PROCEED) {
|
|
1462
|
-
yield* helper(nextPath, nextRest);
|
|
1463
|
-
}
|
|
1464
|
-
i++;
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
yield* helper([], arr);
|
|
1468
|
-
}
|
|
1469
1493
|
|
|
1470
1494
|
// src/optimizer/statistics.ts
|
|
1471
1495
|
var import_colorette3 = require("colorette");
|
|
@@ -2182,7 +2206,6 @@ var PssRewriter = class {
|
|
|
2182
2206
|
ignoredIdentifier,
|
|
2183
2207
|
isIndexProbablyDroppable,
|
|
2184
2208
|
isIndexSupported,
|
|
2185
|
-
parseNudges
|
|
2186
|
-
permuteWithFeedback
|
|
2209
|
+
parseNudges
|
|
2187
2210
|
});
|
|
2188
2211
|
//# sourceMappingURL=index.cjs.map
|