@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 CHANGED
@@ -318,11 +318,15 @@ var Walker = class _Walker {
318
318
  }
319
319
  }
320
320
  if (is2(node, "RangeVar") && node.RangeVar.relname) {
321
- this.tableMappings.set(node.RangeVar.relname, {
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(value.text);
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
- "current",
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
- "global",
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
- "local",
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
- "public",
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
- "transaction",
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 = `${index.schema_name}.${index.index_name}`;
1219
+ const indexName = PgIdentifier.fromParts(
1220
+ index.schema_name,
1221
+ index.index_name
1222
+ );
1134
1223
  await dropIndex(tx, indexName);
1135
1224
  }
1136
1225
  }