@query-doctor/core 0.0.5 → 0.1.1
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 +125 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +125 -36
- package/dist/index.js.map +1 -1
- package/dist/optimizer/genalgo.d.ts.map +1 -1
- package/dist/sql/analyzer.d.ts +5 -1
- package/dist/sql/analyzer.d.ts.map +1 -1
- package/dist/sql/database.d.ts +2 -1
- package/dist/sql/database.d.ts.map +1 -1
- package/dist/sql/pg-identifier.d.ts +16 -0
- package/dist/sql/pg-identifier.d.ts.map +1 -1
- package/dist/sql/walker.d.ts +1 -0
- package/dist/sql/walker.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/optimizer/genalgo.js +0 -304
- package/dist/optimizer/statistics.js +0 -700
- package/dist/package.json +0 -25
- package/dist/sql/analyzer.js +0 -270
- package/dist/sql/analyzer_test.d.ts +0 -2
- package/dist/sql/analyzer_test.d.ts.map +0 -1
- package/dist/sql/analyzer_test.js +0 -584
- package/dist/sql/builder.js +0 -77
- package/dist/sql/database.js +0 -20
- package/dist/sql/indexes.js +0 -12
- package/dist/sql/nudges.js +0 -241
- package/dist/sql/permutations_test.d.ts +0 -2
- package/dist/sql/permutations_test.d.ts.map +0 -1
- package/dist/sql/permutations_test.js +0 -53
- package/dist/sql/walker.js +0 -295
package/dist/index.cjs
CHANGED
|
@@ -318,11 +318,15 @@ var Walker = class _Walker {
|
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
if (is2(node, "RangeVar") && node.RangeVar.relname) {
|
|
321
|
-
|
|
321
|
+
const columnReference = {
|
|
322
322
|
text: node.RangeVar.relname,
|
|
323
323
|
start: node.RangeVar.location,
|
|
324
324
|
quoted: false
|
|
325
|
-
}
|
|
325
|
+
};
|
|
326
|
+
if (node.RangeVar.schemaname) {
|
|
327
|
+
columnReference.schema = node.RangeVar.schemaname;
|
|
328
|
+
}
|
|
329
|
+
this.tableMappings.set(node.RangeVar.relname, columnReference);
|
|
326
330
|
if (node.RangeVar.alias?.aliasname) {
|
|
327
331
|
const aliasName = node.RangeVar.alias.aliasname;
|
|
328
332
|
const existingMapping = this.tableMappings.get(aliasName);
|
|
@@ -335,9 +339,12 @@ var Walker = class _Walker {
|
|
|
335
339
|
quoted: true,
|
|
336
340
|
alias: aliasName
|
|
337
341
|
};
|
|
342
|
+
if (node.RangeVar.schemaname) {
|
|
343
|
+
part.schema = node.RangeVar.schemaname;
|
|
344
|
+
}
|
|
338
345
|
if (existingMapping) {
|
|
339
346
|
console.warn(
|
|
340
|
-
`Ignoring alias ${aliasName} as it shadows an existing mapping. We currently do not support alias shadowing.`
|
|
347
|
+
`Ignoring alias ${aliasName} as it shadows an existing mapping for ${existingMapping.text}. We currently do not support alias shadowing.`
|
|
341
348
|
);
|
|
342
349
|
this.shadowedAliases.push(part);
|
|
343
350
|
return;
|
|
@@ -573,7 +580,10 @@ var Analyzer = class {
|
|
|
573
580
|
const referencedTables = [];
|
|
574
581
|
for (const value of tableMappings.values()) {
|
|
575
582
|
if (!value.alias) {
|
|
576
|
-
referencedTables.push(
|
|
583
|
+
referencedTables.push({
|
|
584
|
+
schema: value.schema,
|
|
585
|
+
table: value.text
|
|
586
|
+
});
|
|
577
587
|
}
|
|
578
588
|
}
|
|
579
589
|
const { tags, queryWithoutTags } = this.extractSqlcommenter(query);
|
|
@@ -629,13 +639,14 @@ var Analyzer = class {
|
|
|
629
639
|
}
|
|
630
640
|
} else if (tableReference) {
|
|
631
641
|
const [table, column] = colReference.parts;
|
|
642
|
+
const referencedSchema = table.schema;
|
|
632
643
|
const referencedTable = this.normalize(table);
|
|
633
644
|
const referencedColumn = this.normalize(column);
|
|
634
645
|
const matchingTable = tables.find((table2) => {
|
|
635
646
|
const hasMatchingColumn = table2.columns?.some((column2) => {
|
|
636
647
|
return column2.columnName === referencedColumn;
|
|
637
648
|
}) ?? false;
|
|
638
|
-
return table2.tableName === referencedTable && hasMatchingColumn;
|
|
649
|
+
return table2.schemaName === referencedSchema && table2.tableName === referencedTable && hasMatchingColumn;
|
|
639
650
|
});
|
|
640
651
|
if (matchingTable) {
|
|
641
652
|
const index = {
|
|
@@ -860,6 +871,10 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
860
871
|
this.value = value;
|
|
861
872
|
this.quoted = quoted;
|
|
862
873
|
}
|
|
874
|
+
/**
|
|
875
|
+
* Constructs an identifier from a single part (column or table name).
|
|
876
|
+
* When quoting identifiers like `select table.col` use {@link fromParts} instead
|
|
877
|
+
*/
|
|
863
878
|
static fromString(identifier) {
|
|
864
879
|
const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
|
|
865
880
|
const match = identifier.match(/^"(.+)"$/);
|
|
@@ -869,6 +884,18 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
869
884
|
const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
|
|
870
885
|
return new _PgIdentifier(identifier, quoted);
|
|
871
886
|
}
|
|
887
|
+
/**
|
|
888
|
+
* Quotes parts of an identifier like `select schema.table.col`.
|
|
889
|
+
* A separate function is necessary because postgres will treat
|
|
890
|
+
* `select "HELLO.WORLD"` as a column name. It has to be like
|
|
891
|
+
* `select "HELLO"."WORLD"` instead.
|
|
892
|
+
*/
|
|
893
|
+
static fromParts(...identifiers) {
|
|
894
|
+
return new _PgIdentifier(
|
|
895
|
+
identifiers.map((identifier) => _PgIdentifier.fromString(identifier)).join("."),
|
|
896
|
+
false
|
|
897
|
+
);
|
|
898
|
+
}
|
|
872
899
|
toString() {
|
|
873
900
|
if (this.quoted) {
|
|
874
901
|
return `"${this.value.replace(/"/g, '""')}"`;
|
|
@@ -876,36 +903,24 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
876
903
|
return this.value;
|
|
877
904
|
}
|
|
878
905
|
};
|
|
906
|
+
// Every keyword that's not explicitly marked as
|
|
907
|
+
// unreserved in src/include/parser/kwlist.h
|
|
879
908
|
__publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
|
|
880
|
-
"abort",
|
|
881
|
-
"analyze",
|
|
882
|
-
"binary",
|
|
883
|
-
"cluster",
|
|
884
|
-
"constraint",
|
|
885
|
-
"copy",
|
|
886
|
-
"do",
|
|
887
|
-
"explain",
|
|
888
|
-
"extend",
|
|
889
|
-
"listen",
|
|
890
|
-
"load",
|
|
891
|
-
"lock",
|
|
892
|
-
"move",
|
|
893
|
-
"new",
|
|
894
|
-
"none",
|
|
895
|
-
"notify",
|
|
896
|
-
"offset",
|
|
897
|
-
"reset",
|
|
898
|
-
"setof",
|
|
899
|
-
"show",
|
|
900
|
-
"unlisten",
|
|
901
|
-
"until",
|
|
902
|
-
"vacuum",
|
|
903
|
-
"verbose",
|
|
904
909
|
"all",
|
|
910
|
+
"analyse",
|
|
911
|
+
"analyze",
|
|
912
|
+
"and",
|
|
905
913
|
"any",
|
|
914
|
+
"array",
|
|
915
|
+
"as",
|
|
906
916
|
"asc",
|
|
917
|
+
"asymmetric",
|
|
918
|
+
"authorization",
|
|
907
919
|
"between",
|
|
920
|
+
"bigint",
|
|
921
|
+
"binary",
|
|
908
922
|
"bit",
|
|
923
|
+
"boolean",
|
|
909
924
|
"both",
|
|
910
925
|
"case",
|
|
911
926
|
"cast",
|
|
@@ -914,76 +929,147 @@ __publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
|
|
|
914
929
|
"check",
|
|
915
930
|
"coalesce",
|
|
916
931
|
"collate",
|
|
932
|
+
"collation",
|
|
917
933
|
"column",
|
|
934
|
+
"concurrently",
|
|
918
935
|
"constraint",
|
|
936
|
+
"create",
|
|
919
937
|
"cross",
|
|
920
|
-
"
|
|
938
|
+
"current_catalog",
|
|
921
939
|
"current_date",
|
|
940
|
+
"current_role",
|
|
941
|
+
"current_schema",
|
|
922
942
|
"current_time",
|
|
923
943
|
"current_timestamp",
|
|
924
944
|
"current_user",
|
|
925
945
|
"dec",
|
|
926
946
|
"decimal",
|
|
927
947
|
"default",
|
|
948
|
+
"deferrable",
|
|
928
949
|
"desc",
|
|
929
950
|
"distinct",
|
|
951
|
+
"do",
|
|
930
952
|
"else",
|
|
931
953
|
"end",
|
|
932
954
|
"except",
|
|
933
955
|
"exists",
|
|
934
956
|
"extract",
|
|
935
957
|
"false",
|
|
958
|
+
"fetch",
|
|
936
959
|
"float",
|
|
937
960
|
"for",
|
|
938
961
|
"foreign",
|
|
962
|
+
"freeze",
|
|
939
963
|
"from",
|
|
940
964
|
"full",
|
|
941
|
-
"
|
|
965
|
+
"grant",
|
|
966
|
+
"greatest",
|
|
942
967
|
"group",
|
|
968
|
+
"grouping",
|
|
943
969
|
"having",
|
|
970
|
+
"ilike",
|
|
944
971
|
"in",
|
|
972
|
+
"initially",
|
|
945
973
|
"inner",
|
|
974
|
+
"inout",
|
|
975
|
+
"int",
|
|
976
|
+
"integer",
|
|
946
977
|
"intersect",
|
|
978
|
+
"interval",
|
|
947
979
|
"into",
|
|
948
980
|
"is",
|
|
981
|
+
"isnull",
|
|
949
982
|
"join",
|
|
983
|
+
"json",
|
|
984
|
+
"json_array",
|
|
985
|
+
"json_arrayagg",
|
|
986
|
+
"json_exists",
|
|
987
|
+
"json_object",
|
|
988
|
+
"json_objectagg",
|
|
989
|
+
"json_query",
|
|
990
|
+
"json_scalar",
|
|
991
|
+
"json_serialize",
|
|
992
|
+
"json_table",
|
|
993
|
+
"json_value",
|
|
994
|
+
"lateral",
|
|
950
995
|
"leading",
|
|
996
|
+
"least",
|
|
951
997
|
"left",
|
|
952
998
|
"like",
|
|
953
|
-
"
|
|
999
|
+
"limit",
|
|
1000
|
+
"localtime",
|
|
1001
|
+
"localtimestamp",
|
|
1002
|
+
"merge_action",
|
|
1003
|
+
"national",
|
|
954
1004
|
"natural",
|
|
955
1005
|
"nchar",
|
|
1006
|
+
"none",
|
|
1007
|
+
"normalize",
|
|
956
1008
|
"not",
|
|
1009
|
+
"notnull",
|
|
957
1010
|
"null",
|
|
958
1011
|
"nullif",
|
|
959
1012
|
"numeric",
|
|
1013
|
+
"offset",
|
|
960
1014
|
"on",
|
|
1015
|
+
"only",
|
|
961
1016
|
"or",
|
|
962
1017
|
"order",
|
|
1018
|
+
"out",
|
|
963
1019
|
"outer",
|
|
964
1020
|
"overlaps",
|
|
1021
|
+
"overlay",
|
|
1022
|
+
"placing",
|
|
965
1023
|
"position",
|
|
966
1024
|
"precision",
|
|
967
1025
|
"primary",
|
|
968
|
-
"
|
|
1026
|
+
"real",
|
|
969
1027
|
"references",
|
|
1028
|
+
"returning",
|
|
970
1029
|
"right",
|
|
1030
|
+
"row",
|
|
971
1031
|
"select",
|
|
972
1032
|
"session_user",
|
|
1033
|
+
"setof",
|
|
1034
|
+
"similar",
|
|
1035
|
+
"smallint",
|
|
973
1036
|
"some",
|
|
974
1037
|
"substring",
|
|
1038
|
+
"symmetric",
|
|
1039
|
+
"system_user",
|
|
975
1040
|
"table",
|
|
1041
|
+
"tablesample",
|
|
976
1042
|
"then",
|
|
1043
|
+
"time",
|
|
1044
|
+
"timestamp",
|
|
977
1045
|
"to",
|
|
978
|
-
"
|
|
1046
|
+
"trailing",
|
|
1047
|
+
"treat",
|
|
979
1048
|
"trim",
|
|
980
1049
|
"true",
|
|
981
1050
|
"union",
|
|
982
1051
|
"unique",
|
|
983
1052
|
"user",
|
|
1053
|
+
"using",
|
|
1054
|
+
"values",
|
|
984
1055
|
"varchar",
|
|
1056
|
+
"variadic",
|
|
1057
|
+
"verbose",
|
|
985
1058
|
"when",
|
|
986
|
-
"where"
|
|
1059
|
+
"where",
|
|
1060
|
+
"window",
|
|
1061
|
+
"with",
|
|
1062
|
+
"xmlattributes",
|
|
1063
|
+
"xmlconcat",
|
|
1064
|
+
"xmlelement",
|
|
1065
|
+
"xmlexists",
|
|
1066
|
+
"xmlforest",
|
|
1067
|
+
"xmlnamespaces",
|
|
1068
|
+
"xmlparse",
|
|
1069
|
+
"xmlpi",
|
|
1070
|
+
"xmlroot",
|
|
1071
|
+
"xmlserialize",
|
|
1072
|
+
"xmltable"
|
|
987
1073
|
]));
|
|
988
1074
|
var PgIdentifier = _PgIdentifier;
|
|
989
1075
|
|
|
@@ -1130,7 +1216,10 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1130
1216
|
if (!isIndexProbablyDroppable(index)) {
|
|
1131
1217
|
continue;
|
|
1132
1218
|
}
|
|
1133
|
-
const indexName =
|
|
1219
|
+
const indexName = PgIdentifier.fromParts(
|
|
1220
|
+
index.schema_name,
|
|
1221
|
+
index.index_name
|
|
1222
|
+
);
|
|
1134
1223
|
await dropIndex(tx, indexName);
|
|
1135
1224
|
}
|
|
1136
1225
|
}
|