@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 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
- return new _PgIdentifier(match[1], true);
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) => columns[i].column === c.name)
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.tableColumnIndexCandidates(rootCandidates);
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 = permuteWithFeedback(columns);
1237
- let iter = permutations.next(PROCEED);
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
- tableColumnIndexCandidates(indexes) {
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