@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.js
CHANGED
|
@@ -269,11 +269,15 @@ var Walker = class _Walker {
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
if (is2(node, "RangeVar") && node.RangeVar.relname) {
|
|
272
|
-
|
|
272
|
+
const columnReference = {
|
|
273
273
|
text: node.RangeVar.relname,
|
|
274
274
|
start: node.RangeVar.location,
|
|
275
275
|
quoted: false
|
|
276
|
-
}
|
|
276
|
+
};
|
|
277
|
+
if (node.RangeVar.schemaname) {
|
|
278
|
+
columnReference.schema = node.RangeVar.schemaname;
|
|
279
|
+
}
|
|
280
|
+
this.tableMappings.set(node.RangeVar.relname, columnReference);
|
|
277
281
|
if (node.RangeVar.alias?.aliasname) {
|
|
278
282
|
const aliasName = node.RangeVar.alias.aliasname;
|
|
279
283
|
const existingMapping = this.tableMappings.get(aliasName);
|
|
@@ -286,9 +290,12 @@ var Walker = class _Walker {
|
|
|
286
290
|
quoted: true,
|
|
287
291
|
alias: aliasName
|
|
288
292
|
};
|
|
293
|
+
if (node.RangeVar.schemaname) {
|
|
294
|
+
part.schema = node.RangeVar.schemaname;
|
|
295
|
+
}
|
|
289
296
|
if (existingMapping) {
|
|
290
297
|
console.warn(
|
|
291
|
-
`Ignoring alias ${aliasName} as it shadows an existing mapping. We currently do not support alias shadowing.`
|
|
298
|
+
`Ignoring alias ${aliasName} as it shadows an existing mapping for ${existingMapping.text}. We currently do not support alias shadowing.`
|
|
292
299
|
);
|
|
293
300
|
this.shadowedAliases.push(part);
|
|
294
301
|
return;
|
|
@@ -524,7 +531,10 @@ var Analyzer = class {
|
|
|
524
531
|
const referencedTables = [];
|
|
525
532
|
for (const value of tableMappings.values()) {
|
|
526
533
|
if (!value.alias) {
|
|
527
|
-
referencedTables.push(
|
|
534
|
+
referencedTables.push({
|
|
535
|
+
schema: value.schema,
|
|
536
|
+
table: value.text
|
|
537
|
+
});
|
|
528
538
|
}
|
|
529
539
|
}
|
|
530
540
|
const { tags, queryWithoutTags } = this.extractSqlcommenter(query);
|
|
@@ -580,13 +590,14 @@ var Analyzer = class {
|
|
|
580
590
|
}
|
|
581
591
|
} else if (tableReference) {
|
|
582
592
|
const [table, column] = colReference.parts;
|
|
593
|
+
const referencedSchema = table.schema;
|
|
583
594
|
const referencedTable = this.normalize(table);
|
|
584
595
|
const referencedColumn = this.normalize(column);
|
|
585
596
|
const matchingTable = tables.find((table2) => {
|
|
586
597
|
const hasMatchingColumn = table2.columns?.some((column2) => {
|
|
587
598
|
return column2.columnName === referencedColumn;
|
|
588
599
|
}) ?? false;
|
|
589
|
-
return table2.tableName === referencedTable && hasMatchingColumn;
|
|
600
|
+
return table2.schemaName === referencedSchema && table2.tableName === referencedTable && hasMatchingColumn;
|
|
590
601
|
});
|
|
591
602
|
if (matchingTable) {
|
|
592
603
|
const index = {
|
|
@@ -811,6 +822,10 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
811
822
|
this.value = value;
|
|
812
823
|
this.quoted = quoted;
|
|
813
824
|
}
|
|
825
|
+
/**
|
|
826
|
+
* Constructs an identifier from a single part (column or table name).
|
|
827
|
+
* When quoting identifiers like `select table.col` use {@link fromParts} instead
|
|
828
|
+
*/
|
|
814
829
|
static fromString(identifier) {
|
|
815
830
|
const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
|
|
816
831
|
const match = identifier.match(/^"(.+)"$/);
|
|
@@ -820,6 +835,18 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
820
835
|
const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
|
|
821
836
|
return new _PgIdentifier(identifier, quoted);
|
|
822
837
|
}
|
|
838
|
+
/**
|
|
839
|
+
* Quotes parts of an identifier like `select schema.table.col`.
|
|
840
|
+
* A separate function is necessary because postgres will treat
|
|
841
|
+
* `select "HELLO.WORLD"` as a column name. It has to be like
|
|
842
|
+
* `select "HELLO"."WORLD"` instead.
|
|
843
|
+
*/
|
|
844
|
+
static fromParts(...identifiers) {
|
|
845
|
+
return new _PgIdentifier(
|
|
846
|
+
identifiers.map((identifier) => _PgIdentifier.fromString(identifier)).join("."),
|
|
847
|
+
false
|
|
848
|
+
);
|
|
849
|
+
}
|
|
823
850
|
toString() {
|
|
824
851
|
if (this.quoted) {
|
|
825
852
|
return `"${this.value.replace(/"/g, '""')}"`;
|
|
@@ -827,36 +854,24 @@ var _PgIdentifier = class _PgIdentifier {
|
|
|
827
854
|
return this.value;
|
|
828
855
|
}
|
|
829
856
|
};
|
|
857
|
+
// Every keyword that's not explicitly marked as
|
|
858
|
+
// unreserved in src/include/parser/kwlist.h
|
|
830
859
|
__publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
|
|
831
|
-
"abort",
|
|
832
|
-
"analyze",
|
|
833
|
-
"binary",
|
|
834
|
-
"cluster",
|
|
835
|
-
"constraint",
|
|
836
|
-
"copy",
|
|
837
|
-
"do",
|
|
838
|
-
"explain",
|
|
839
|
-
"extend",
|
|
840
|
-
"listen",
|
|
841
|
-
"load",
|
|
842
|
-
"lock",
|
|
843
|
-
"move",
|
|
844
|
-
"new",
|
|
845
|
-
"none",
|
|
846
|
-
"notify",
|
|
847
|
-
"offset",
|
|
848
|
-
"reset",
|
|
849
|
-
"setof",
|
|
850
|
-
"show",
|
|
851
|
-
"unlisten",
|
|
852
|
-
"until",
|
|
853
|
-
"vacuum",
|
|
854
|
-
"verbose",
|
|
855
860
|
"all",
|
|
861
|
+
"analyse",
|
|
862
|
+
"analyze",
|
|
863
|
+
"and",
|
|
856
864
|
"any",
|
|
865
|
+
"array",
|
|
866
|
+
"as",
|
|
857
867
|
"asc",
|
|
868
|
+
"asymmetric",
|
|
869
|
+
"authorization",
|
|
858
870
|
"between",
|
|
871
|
+
"bigint",
|
|
872
|
+
"binary",
|
|
859
873
|
"bit",
|
|
874
|
+
"boolean",
|
|
860
875
|
"both",
|
|
861
876
|
"case",
|
|
862
877
|
"cast",
|
|
@@ -865,76 +880,147 @@ __publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
|
|
|
865
880
|
"check",
|
|
866
881
|
"coalesce",
|
|
867
882
|
"collate",
|
|
883
|
+
"collation",
|
|
868
884
|
"column",
|
|
885
|
+
"concurrently",
|
|
869
886
|
"constraint",
|
|
887
|
+
"create",
|
|
870
888
|
"cross",
|
|
871
|
-
"
|
|
889
|
+
"current_catalog",
|
|
872
890
|
"current_date",
|
|
891
|
+
"current_role",
|
|
892
|
+
"current_schema",
|
|
873
893
|
"current_time",
|
|
874
894
|
"current_timestamp",
|
|
875
895
|
"current_user",
|
|
876
896
|
"dec",
|
|
877
897
|
"decimal",
|
|
878
898
|
"default",
|
|
899
|
+
"deferrable",
|
|
879
900
|
"desc",
|
|
880
901
|
"distinct",
|
|
902
|
+
"do",
|
|
881
903
|
"else",
|
|
882
904
|
"end",
|
|
883
905
|
"except",
|
|
884
906
|
"exists",
|
|
885
907
|
"extract",
|
|
886
908
|
"false",
|
|
909
|
+
"fetch",
|
|
887
910
|
"float",
|
|
888
911
|
"for",
|
|
889
912
|
"foreign",
|
|
913
|
+
"freeze",
|
|
890
914
|
"from",
|
|
891
915
|
"full",
|
|
892
|
-
"
|
|
916
|
+
"grant",
|
|
917
|
+
"greatest",
|
|
893
918
|
"group",
|
|
919
|
+
"grouping",
|
|
894
920
|
"having",
|
|
921
|
+
"ilike",
|
|
895
922
|
"in",
|
|
923
|
+
"initially",
|
|
896
924
|
"inner",
|
|
925
|
+
"inout",
|
|
926
|
+
"int",
|
|
927
|
+
"integer",
|
|
897
928
|
"intersect",
|
|
929
|
+
"interval",
|
|
898
930
|
"into",
|
|
899
931
|
"is",
|
|
932
|
+
"isnull",
|
|
900
933
|
"join",
|
|
934
|
+
"json",
|
|
935
|
+
"json_array",
|
|
936
|
+
"json_arrayagg",
|
|
937
|
+
"json_exists",
|
|
938
|
+
"json_object",
|
|
939
|
+
"json_objectagg",
|
|
940
|
+
"json_query",
|
|
941
|
+
"json_scalar",
|
|
942
|
+
"json_serialize",
|
|
943
|
+
"json_table",
|
|
944
|
+
"json_value",
|
|
945
|
+
"lateral",
|
|
901
946
|
"leading",
|
|
947
|
+
"least",
|
|
902
948
|
"left",
|
|
903
949
|
"like",
|
|
904
|
-
"
|
|
950
|
+
"limit",
|
|
951
|
+
"localtime",
|
|
952
|
+
"localtimestamp",
|
|
953
|
+
"merge_action",
|
|
954
|
+
"national",
|
|
905
955
|
"natural",
|
|
906
956
|
"nchar",
|
|
957
|
+
"none",
|
|
958
|
+
"normalize",
|
|
907
959
|
"not",
|
|
960
|
+
"notnull",
|
|
908
961
|
"null",
|
|
909
962
|
"nullif",
|
|
910
963
|
"numeric",
|
|
964
|
+
"offset",
|
|
911
965
|
"on",
|
|
966
|
+
"only",
|
|
912
967
|
"or",
|
|
913
968
|
"order",
|
|
969
|
+
"out",
|
|
914
970
|
"outer",
|
|
915
971
|
"overlaps",
|
|
972
|
+
"overlay",
|
|
973
|
+
"placing",
|
|
916
974
|
"position",
|
|
917
975
|
"precision",
|
|
918
976
|
"primary",
|
|
919
|
-
"
|
|
977
|
+
"real",
|
|
920
978
|
"references",
|
|
979
|
+
"returning",
|
|
921
980
|
"right",
|
|
981
|
+
"row",
|
|
922
982
|
"select",
|
|
923
983
|
"session_user",
|
|
984
|
+
"setof",
|
|
985
|
+
"similar",
|
|
986
|
+
"smallint",
|
|
924
987
|
"some",
|
|
925
988
|
"substring",
|
|
989
|
+
"symmetric",
|
|
990
|
+
"system_user",
|
|
926
991
|
"table",
|
|
992
|
+
"tablesample",
|
|
927
993
|
"then",
|
|
994
|
+
"time",
|
|
995
|
+
"timestamp",
|
|
928
996
|
"to",
|
|
929
|
-
"
|
|
997
|
+
"trailing",
|
|
998
|
+
"treat",
|
|
930
999
|
"trim",
|
|
931
1000
|
"true",
|
|
932
1001
|
"union",
|
|
933
1002
|
"unique",
|
|
934
1003
|
"user",
|
|
1004
|
+
"using",
|
|
1005
|
+
"values",
|
|
935
1006
|
"varchar",
|
|
1007
|
+
"variadic",
|
|
1008
|
+
"verbose",
|
|
936
1009
|
"when",
|
|
937
|
-
"where"
|
|
1010
|
+
"where",
|
|
1011
|
+
"window",
|
|
1012
|
+
"with",
|
|
1013
|
+
"xmlattributes",
|
|
1014
|
+
"xmlconcat",
|
|
1015
|
+
"xmlelement",
|
|
1016
|
+
"xmlexists",
|
|
1017
|
+
"xmlforest",
|
|
1018
|
+
"xmlnamespaces",
|
|
1019
|
+
"xmlparse",
|
|
1020
|
+
"xmlpi",
|
|
1021
|
+
"xmlroot",
|
|
1022
|
+
"xmlserialize",
|
|
1023
|
+
"xmltable"
|
|
938
1024
|
]));
|
|
939
1025
|
var PgIdentifier = _PgIdentifier;
|
|
940
1026
|
|
|
@@ -1081,7 +1167,10 @@ var _IndexOptimizer = class _IndexOptimizer {
|
|
|
1081
1167
|
if (!isIndexProbablyDroppable(index)) {
|
|
1082
1168
|
continue;
|
|
1083
1169
|
}
|
|
1084
|
-
const indexName =
|
|
1170
|
+
const indexName = PgIdentifier.fromParts(
|
|
1171
|
+
index.schema_name,
|
|
1172
|
+
index.index_name
|
|
1173
|
+
);
|
|
1085
1174
|
await dropIndex(tx, indexName);
|
|
1086
1175
|
}
|
|
1087
1176
|
}
|