@query-doctor/core 0.0.4 → 0.1.0

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.js CHANGED
@@ -811,6 +811,10 @@ var _PgIdentifier = class _PgIdentifier {
811
811
  this.value = value;
812
812
  this.quoted = quoted;
813
813
  }
814
+ /**
815
+ * Constructs an identifier from a single part (column or table name).
816
+ * When quoting identifiers like `select table.col` use {@link fromParts} instead
817
+ */
814
818
  static fromString(identifier) {
815
819
  const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
816
820
  const match = identifier.match(/^"(.+)"$/);
@@ -820,6 +824,18 @@ var _PgIdentifier = class _PgIdentifier {
820
824
  const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
821
825
  return new _PgIdentifier(identifier, quoted);
822
826
  }
827
+ /**
828
+ * Quotes parts of an identifier like `select schema.table.col`.
829
+ * A separate function is necessary because postgres will treat
830
+ * `select "HELLO.WORLD"` as a column name. It has to be like
831
+ * `select "HELLO"."WORLD"` instead.
832
+ */
833
+ static fromParts(...identifiers) {
834
+ return new _PgIdentifier(
835
+ identifiers.map((identifier) => _PgIdentifier.fromString(identifier)).join("."),
836
+ false
837
+ );
838
+ }
823
839
  toString() {
824
840
  if (this.quoted) {
825
841
  return `"${this.value.replace(/"/g, '""')}"`;
@@ -827,36 +843,24 @@ var _PgIdentifier = class _PgIdentifier {
827
843
  return this.value;
828
844
  }
829
845
  };
846
+ // Every keyword that's not explicitly marked as
847
+ // unreserved in src/include/parser/kwlist.h
830
848
  __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
849
  "all",
850
+ "analyse",
851
+ "analyze",
852
+ "and",
856
853
  "any",
854
+ "array",
855
+ "as",
857
856
  "asc",
857
+ "asymmetric",
858
+ "authorization",
858
859
  "between",
860
+ "bigint",
861
+ "binary",
859
862
  "bit",
863
+ "boolean",
860
864
  "both",
861
865
  "case",
862
866
  "cast",
@@ -865,76 +869,147 @@ __publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
865
869
  "check",
866
870
  "coalesce",
867
871
  "collate",
872
+ "collation",
868
873
  "column",
874
+ "concurrently",
869
875
  "constraint",
876
+ "create",
870
877
  "cross",
871
- "current",
878
+ "current_catalog",
872
879
  "current_date",
880
+ "current_role",
881
+ "current_schema",
873
882
  "current_time",
874
883
  "current_timestamp",
875
884
  "current_user",
876
885
  "dec",
877
886
  "decimal",
878
887
  "default",
888
+ "deferrable",
879
889
  "desc",
880
890
  "distinct",
891
+ "do",
881
892
  "else",
882
893
  "end",
883
894
  "except",
884
895
  "exists",
885
896
  "extract",
886
897
  "false",
898
+ "fetch",
887
899
  "float",
888
900
  "for",
889
901
  "foreign",
902
+ "freeze",
890
903
  "from",
891
904
  "full",
892
- "global",
905
+ "grant",
906
+ "greatest",
893
907
  "group",
908
+ "grouping",
894
909
  "having",
910
+ "ilike",
895
911
  "in",
912
+ "initially",
896
913
  "inner",
914
+ "inout",
915
+ "int",
916
+ "integer",
897
917
  "intersect",
918
+ "interval",
898
919
  "into",
899
920
  "is",
921
+ "isnull",
900
922
  "join",
923
+ "json",
924
+ "json_array",
925
+ "json_arrayagg",
926
+ "json_exists",
927
+ "json_object",
928
+ "json_objectagg",
929
+ "json_query",
930
+ "json_scalar",
931
+ "json_serialize",
932
+ "json_table",
933
+ "json_value",
934
+ "lateral",
901
935
  "leading",
936
+ "least",
902
937
  "left",
903
938
  "like",
904
- "local",
939
+ "limit",
940
+ "localtime",
941
+ "localtimestamp",
942
+ "merge_action",
943
+ "national",
905
944
  "natural",
906
945
  "nchar",
946
+ "none",
947
+ "normalize",
907
948
  "not",
949
+ "notnull",
908
950
  "null",
909
951
  "nullif",
910
952
  "numeric",
953
+ "offset",
911
954
  "on",
955
+ "only",
912
956
  "or",
913
957
  "order",
958
+ "out",
914
959
  "outer",
915
960
  "overlaps",
961
+ "overlay",
962
+ "placing",
916
963
  "position",
917
964
  "precision",
918
965
  "primary",
919
- "public",
966
+ "real",
920
967
  "references",
968
+ "returning",
921
969
  "right",
970
+ "row",
922
971
  "select",
923
972
  "session_user",
973
+ "setof",
974
+ "similar",
975
+ "smallint",
924
976
  "some",
925
977
  "substring",
978
+ "symmetric",
979
+ "system_user",
926
980
  "table",
981
+ "tablesample",
927
982
  "then",
983
+ "time",
984
+ "timestamp",
928
985
  "to",
929
- "transaction",
986
+ "trailing",
987
+ "treat",
930
988
  "trim",
931
989
  "true",
932
990
  "union",
933
991
  "unique",
934
992
  "user",
993
+ "using",
994
+ "values",
935
995
  "varchar",
996
+ "variadic",
997
+ "verbose",
936
998
  "when",
937
- "where"
999
+ "where",
1000
+ "window",
1001
+ "with",
1002
+ "xmlattributes",
1003
+ "xmlconcat",
1004
+ "xmlelement",
1005
+ "xmlexists",
1006
+ "xmlforest",
1007
+ "xmlnamespaces",
1008
+ "xmlparse",
1009
+ "xmlpi",
1010
+ "xmlroot",
1011
+ "xmlserialize",
1012
+ "xmltable"
938
1013
  ]));
939
1014
  var PgIdentifier = _PgIdentifier;
940
1015
 
@@ -1081,7 +1156,10 @@ var _IndexOptimizer = class _IndexOptimizer {
1081
1156
  if (!isIndexProbablyDroppable(index)) {
1082
1157
  continue;
1083
1158
  }
1084
- const indexName = `${index.schema_name}.${index.index_name}`;
1159
+ const indexName = PgIdentifier.fromParts(
1160
+ index.schema_name,
1161
+ index.index_name
1162
+ );
1085
1163
  await dropIndex(tx, indexName);
1086
1164
  }
1087
1165
  }
@@ -1132,9 +1210,12 @@ var _IndexOptimizer = class _IndexOptimizer {
1132
1210
  await this.db.transaction(async (tx) => {
1133
1211
  await f?.(tx);
1134
1212
  await this.statistics.restoreStats(tx);
1135
- const flags = ["format json", "trace"];
1213
+ const flags = ["format json"];
1136
1214
  if (options && !options.genericPlan) {
1137
1215
  flags.push("analyze");
1216
+ if (this.config.trace) {
1217
+ flags.push("trace");
1218
+ }
1138
1219
  } else {
1139
1220
  flags.push("generic_plan");
1140
1221
  }