@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.cjs CHANGED
@@ -860,6 +860,10 @@ var _PgIdentifier = class _PgIdentifier {
860
860
  this.value = value;
861
861
  this.quoted = quoted;
862
862
  }
863
+ /**
864
+ * Constructs an identifier from a single part (column or table name).
865
+ * When quoting identifiers like `select table.col` use {@link fromParts} instead
866
+ */
863
867
  static fromString(identifier) {
864
868
  const identifierRegex = /^[a-z_][a-zA-Z0-9_]*$/;
865
869
  const match = identifier.match(/^"(.+)"$/);
@@ -869,6 +873,18 @@ var _PgIdentifier = class _PgIdentifier {
869
873
  const quoted = !identifierRegex.test(identifier) || this.reservedKeywords.has(identifier.toLowerCase());
870
874
  return new _PgIdentifier(identifier, quoted);
871
875
  }
876
+ /**
877
+ * Quotes parts of an identifier like `select schema.table.col`.
878
+ * A separate function is necessary because postgres will treat
879
+ * `select "HELLO.WORLD"` as a column name. It has to be like
880
+ * `select "HELLO"."WORLD"` instead.
881
+ */
882
+ static fromParts(...identifiers) {
883
+ return new _PgIdentifier(
884
+ identifiers.map((identifier) => _PgIdentifier.fromString(identifier)).join("."),
885
+ false
886
+ );
887
+ }
872
888
  toString() {
873
889
  if (this.quoted) {
874
890
  return `"${this.value.replace(/"/g, '""')}"`;
@@ -876,36 +892,24 @@ var _PgIdentifier = class _PgIdentifier {
876
892
  return this.value;
877
893
  }
878
894
  };
895
+ // Every keyword that's not explicitly marked as
896
+ // unreserved in src/include/parser/kwlist.h
879
897
  __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
898
  "all",
899
+ "analyse",
900
+ "analyze",
901
+ "and",
905
902
  "any",
903
+ "array",
904
+ "as",
906
905
  "asc",
906
+ "asymmetric",
907
+ "authorization",
907
908
  "between",
909
+ "bigint",
910
+ "binary",
908
911
  "bit",
912
+ "boolean",
909
913
  "both",
910
914
  "case",
911
915
  "cast",
@@ -914,76 +918,147 @@ __publicField(_PgIdentifier, "reservedKeywords", /* @__PURE__ */ new Set([
914
918
  "check",
915
919
  "coalesce",
916
920
  "collate",
921
+ "collation",
917
922
  "column",
923
+ "concurrently",
918
924
  "constraint",
925
+ "create",
919
926
  "cross",
920
- "current",
927
+ "current_catalog",
921
928
  "current_date",
929
+ "current_role",
930
+ "current_schema",
922
931
  "current_time",
923
932
  "current_timestamp",
924
933
  "current_user",
925
934
  "dec",
926
935
  "decimal",
927
936
  "default",
937
+ "deferrable",
928
938
  "desc",
929
939
  "distinct",
940
+ "do",
930
941
  "else",
931
942
  "end",
932
943
  "except",
933
944
  "exists",
934
945
  "extract",
935
946
  "false",
947
+ "fetch",
936
948
  "float",
937
949
  "for",
938
950
  "foreign",
951
+ "freeze",
939
952
  "from",
940
953
  "full",
941
- "global",
954
+ "grant",
955
+ "greatest",
942
956
  "group",
957
+ "grouping",
943
958
  "having",
959
+ "ilike",
944
960
  "in",
961
+ "initially",
945
962
  "inner",
963
+ "inout",
964
+ "int",
965
+ "integer",
946
966
  "intersect",
967
+ "interval",
947
968
  "into",
948
969
  "is",
970
+ "isnull",
949
971
  "join",
972
+ "json",
973
+ "json_array",
974
+ "json_arrayagg",
975
+ "json_exists",
976
+ "json_object",
977
+ "json_objectagg",
978
+ "json_query",
979
+ "json_scalar",
980
+ "json_serialize",
981
+ "json_table",
982
+ "json_value",
983
+ "lateral",
950
984
  "leading",
985
+ "least",
951
986
  "left",
952
987
  "like",
953
- "local",
988
+ "limit",
989
+ "localtime",
990
+ "localtimestamp",
991
+ "merge_action",
992
+ "national",
954
993
  "natural",
955
994
  "nchar",
995
+ "none",
996
+ "normalize",
956
997
  "not",
998
+ "notnull",
957
999
  "null",
958
1000
  "nullif",
959
1001
  "numeric",
1002
+ "offset",
960
1003
  "on",
1004
+ "only",
961
1005
  "or",
962
1006
  "order",
1007
+ "out",
963
1008
  "outer",
964
1009
  "overlaps",
1010
+ "overlay",
1011
+ "placing",
965
1012
  "position",
966
1013
  "precision",
967
1014
  "primary",
968
- "public",
1015
+ "real",
969
1016
  "references",
1017
+ "returning",
970
1018
  "right",
1019
+ "row",
971
1020
  "select",
972
1021
  "session_user",
1022
+ "setof",
1023
+ "similar",
1024
+ "smallint",
973
1025
  "some",
974
1026
  "substring",
1027
+ "symmetric",
1028
+ "system_user",
975
1029
  "table",
1030
+ "tablesample",
976
1031
  "then",
1032
+ "time",
1033
+ "timestamp",
977
1034
  "to",
978
- "transaction",
1035
+ "trailing",
1036
+ "treat",
979
1037
  "trim",
980
1038
  "true",
981
1039
  "union",
982
1040
  "unique",
983
1041
  "user",
1042
+ "using",
1043
+ "values",
984
1044
  "varchar",
1045
+ "variadic",
1046
+ "verbose",
985
1047
  "when",
986
- "where"
1048
+ "where",
1049
+ "window",
1050
+ "with",
1051
+ "xmlattributes",
1052
+ "xmlconcat",
1053
+ "xmlelement",
1054
+ "xmlexists",
1055
+ "xmlforest",
1056
+ "xmlnamespaces",
1057
+ "xmlparse",
1058
+ "xmlpi",
1059
+ "xmlroot",
1060
+ "xmlserialize",
1061
+ "xmltable"
987
1062
  ]));
988
1063
  var PgIdentifier = _PgIdentifier;
989
1064
 
@@ -1130,7 +1205,10 @@ var _IndexOptimizer = class _IndexOptimizer {
1130
1205
  if (!isIndexProbablyDroppable(index)) {
1131
1206
  continue;
1132
1207
  }
1133
- const indexName = `${index.schema_name}.${index.index_name}`;
1208
+ const indexName = PgIdentifier.fromParts(
1209
+ index.schema_name,
1210
+ index.index_name
1211
+ );
1134
1212
  await dropIndex(tx, indexName);
1135
1213
  }
1136
1214
  }
@@ -1181,9 +1259,12 @@ var _IndexOptimizer = class _IndexOptimizer {
1181
1259
  await this.db.transaction(async (tx) => {
1182
1260
  await f?.(tx);
1183
1261
  await this.statistics.restoreStats(tx);
1184
- const flags = ["format json", "trace"];
1262
+ const flags = ["format json"];
1185
1263
  if (options && !options.genericPlan) {
1186
1264
  flags.push("analyze");
1265
+ if (this.config.trace) {
1266
+ flags.push("trace");
1267
+ }
1187
1268
  } else {
1188
1269
  flags.push("generic_plan");
1189
1270
  }