@rex0220/kintone-sql-tools 3.36.0 → 3.37.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-cli/ksql.js CHANGED
@@ -23813,8 +23813,256 @@ function buildBatchEnvelope(batch, options = {}) {
23813
23813
  };
23814
23814
  }
23815
23815
 
23816
+ // src/core/logicalApps.ts
23817
+ var LOGICAL_APP_NAME_MAX_UTF16_UNITS = 64;
23818
+ var LOGICAL_APP_ASCII_LETTERS = "A-Za-z";
23819
+ var LOGICAL_APP_JAPANESE_RANGES = "\\u3040-\\u30FF\\u3400-\\u9FFF\\uF900-\\uFAFF\\uFF01-\\uFF60";
23820
+ var LOGICAL_APP_START_CLASS = `${LOGICAL_APP_ASCII_LETTERS}${LOGICAL_APP_JAPANESE_RANGES}`;
23821
+ var LOGICAL_APP_CONTINUE_CLASS = `${LOGICAL_APP_START_CLASS}0-9_`;
23822
+ var LOGICAL_APP_NAME_START_RE = new RegExp(`^[${LOGICAL_APP_START_CLASS}]$`, "u");
23823
+ var LOGICAL_APP_NAME_CONTINUE_RE = new RegExp(`^[${LOGICAL_APP_CONTINUE_CLASS}]$`, "u");
23824
+ var LOGICAL_APP_NAME_RE = new RegExp(
23825
+ `^[${LOGICAL_APP_START_CLASS}][${LOGICAL_APP_CONTINUE_CLASS}]{0,63}$`,
23826
+ "u"
23827
+ );
23828
+ function isLogicalAppNameStart(ch) {
23829
+ return LOGICAL_APP_NAME_START_RE.test(ch);
23830
+ }
23831
+ function isLogicalAppNameContinue(ch) {
23832
+ return LOGICAL_APP_NAME_CONTINUE_RE.test(ch);
23833
+ }
23834
+ function canonicalizeLogicalAppName(name) {
23835
+ const canonical = name.normalize("NFC").toUpperCase();
23836
+ if (!LOGICAL_APP_NAME_RE.test(canonical)) {
23837
+ throw new Error(
23838
+ `ArgumentError: logical app name "${name}" is invalid; expected 1-${LOGICAL_APP_NAME_MAX_UTF16_UNITS} UTF-16 units starting with an ASCII letter or supported Japanese character.`
23839
+ );
23840
+ }
23841
+ return canonical;
23842
+ }
23843
+ function isSqlIdentContinue(ch) {
23844
+ if (!ch) return false;
23845
+ const cp = ch.codePointAt(0);
23846
+ return cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp >= 48 && cp <= 57 || cp === 95 || cp === 36 || cp >= 12352 && cp <= 12543 || cp >= 13312 && cp <= 40959 || cp >= 63744 && cp <= 64255 || cp >= 65281 && cp <= 65376;
23847
+ }
23848
+ function isProfileNameChar(ch) {
23849
+ if (!ch) return false;
23850
+ const cp = ch.codePointAt(0);
23851
+ return cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp >= 48 && cp <= 57 || ch === "_" || ch === "-" || ch === "." || ch === "$";
23852
+ }
23853
+ function tryParseAppProfileToken(sql, start) {
23854
+ const prev = start > 0 ? sql[start - 1] : "";
23855
+ if (isSqlIdentContinue(prev)) return null;
23856
+ let source;
23857
+ let appId;
23858
+ let logicalName;
23859
+ let referenceValueStart;
23860
+ let referenceValueEnd;
23861
+ let i;
23862
+ if (sql.slice(start, start + 5).toUpperCase() === "LAPP_") {
23863
+ source = "logical";
23864
+ i = start + 5;
23865
+ referenceValueStart = i;
23866
+ if (!isLogicalAppNameStart(sql[i] ?? "")) return null;
23867
+ i++;
23868
+ while (i < sql.length && isLogicalAppNameContinue(sql[i])) i++;
23869
+ referenceValueEnd = i;
23870
+ try {
23871
+ logicalName = canonicalizeLogicalAppName(sql.slice(referenceValueStart, referenceValueEnd));
23872
+ } catch {
23873
+ return null;
23874
+ }
23875
+ } else if (sql.slice(start, start + 3).toUpperCase() === "APP") {
23876
+ source = "physical";
23877
+ i = start + 3;
23878
+ referenceValueStart = i;
23879
+ while (i < sql.length && /[0-9]/.test(sql[i])) i++;
23880
+ referenceValueEnd = i;
23881
+ if (referenceValueEnd === referenceValueStart) return null;
23882
+ appId = Number(sql.slice(referenceValueStart, referenceValueEnd));
23883
+ } else {
23884
+ return null;
23885
+ }
23886
+ if (sql[i] === "$") {
23887
+ i++;
23888
+ const subStart = i;
23889
+ while (i < sql.length && isSqlIdentContinue(sql[i])) i++;
23890
+ if (i === subStart) return null;
23891
+ }
23892
+ const appEnd = i;
23893
+ let profile = null;
23894
+ if (sql[i] === "@") {
23895
+ i++;
23896
+ const pStart = i;
23897
+ while (i < sql.length && isProfileNameChar(sql[i])) i++;
23898
+ if (i === pStart) return null;
23899
+ profile = sql.slice(pStart, i);
23900
+ }
23901
+ const next = i < sql.length ? sql[i] : "";
23902
+ if (isSqlIdentContinue(next)) return null;
23903
+ const common = {
23904
+ profile,
23905
+ start,
23906
+ referenceValueStart,
23907
+ referenceValueEnd,
23908
+ appEnd,
23909
+ fullEnd: i
23910
+ };
23911
+ return source === "physical" ? { ...common, source, appId } : { ...common, source, logicalName };
23912
+ }
23913
+ function collectAppProfileTokens(sql) {
23914
+ const tokens = [];
23915
+ let i = 0;
23916
+ while (i < sql.length) {
23917
+ const ch = sql[i];
23918
+ if (ch === "'") {
23919
+ i++;
23920
+ while (i < sql.length) {
23921
+ if (sql[i] === "'") {
23922
+ i++;
23923
+ if (i < sql.length && sql[i] === "'") {
23924
+ i++;
23925
+ continue;
23926
+ }
23927
+ break;
23928
+ }
23929
+ i++;
23930
+ }
23931
+ continue;
23932
+ }
23933
+ if (ch === "`") {
23934
+ i++;
23935
+ while (i < sql.length && sql[i] !== "`") i++;
23936
+ if (i < sql.length) i++;
23937
+ continue;
23938
+ }
23939
+ if (ch === "-" && sql[i + 1] === "-") {
23940
+ i += 2;
23941
+ while (i < sql.length && sql[i] !== "\n") i++;
23942
+ continue;
23943
+ }
23944
+ if (ch === "/" && sql[i + 1] === "*") {
23945
+ i += 2;
23946
+ while (i < sql.length) {
23947
+ if (sql[i] === "*" && sql[i + 1] === "/") {
23948
+ i += 2;
23949
+ break;
23950
+ }
23951
+ i++;
23952
+ }
23953
+ continue;
23954
+ }
23955
+ const parsed = tryParseAppProfileToken(sql, i);
23956
+ if (!parsed) {
23957
+ i++;
23958
+ continue;
23959
+ }
23960
+ tokens.push(parsed);
23961
+ i = parsed.fullEnd;
23962
+ }
23963
+ return tokens;
23964
+ }
23965
+ function nextVirtualAppId(used) {
23966
+ let id = 9e8;
23967
+ while (used.has(id)) id++;
23968
+ used.add(id);
23969
+ return id;
23970
+ }
23971
+ function normalizeSqlAppProfiles(sql, defaultProfile = "dev", resolutionContext) {
23972
+ const tokens = collectAppProfileTokens(sql);
23973
+ const hasProfileSyntax = tokens.some((t) => t.profile !== null);
23974
+ const profilesByApp = /* @__PURE__ */ new Map();
23975
+ const normalizedProfile = (profile) => profile ?? defaultProfile;
23976
+ for (const t of tokens) {
23977
+ if (t.source !== "physical") continue;
23978
+ const p = normalizedProfile(t.profile);
23979
+ let set = profilesByApp.get(t.appId);
23980
+ if (!set) {
23981
+ set = /* @__PURE__ */ new Set();
23982
+ profilesByApp.set(t.appId, set);
23983
+ }
23984
+ set.add(p.toLowerCase());
23985
+ }
23986
+ const usedAppIds = new Set(tokens.filter((t) => t.source === "physical").map((t) => t.appId));
23987
+ const resolvedLogicalApps = /* @__PURE__ */ new Map();
23988
+ for (const t of tokens) {
23989
+ if (t.source !== "logical") continue;
23990
+ const pLower = normalizedProfile(t.profile).toLowerCase();
23991
+ const logicalKey = `logical:${t.logicalName}@${pLower}`;
23992
+ if (resolvedLogicalApps.has(logicalKey)) continue;
23993
+ if (!resolutionContext) {
23994
+ throw new Error(`ArgumentError: logical app LAPP_${t.logicalName}@${pLower} requires logicalApps configuration.`);
23995
+ }
23996
+ const resolvedAppId = resolutionContext.resolveLogicalApp(t.logicalName, pLower);
23997
+ resolvedLogicalApps.set(logicalKey, resolvedAppId);
23998
+ usedAppIds.add(resolvedAppId);
23999
+ }
24000
+ const pairToMapped = /* @__PURE__ */ new Map();
24001
+ const appBindingByMappedApp = /* @__PURE__ */ new Map();
24002
+ for (const [appId, pSet] of profilesByApp.entries()) {
24003
+ const profiles = [...pSet].sort();
24004
+ if (profiles.length <= 1) continue;
24005
+ for (const pLower of profiles) {
24006
+ const mapped = nextVirtualAppId(usedAppIds);
24007
+ pairToMapped.set(`physical:${appId}@${pLower}`, mapped);
24008
+ appBindingByMappedApp.set(mapped, {
24009
+ source: "physical",
24010
+ mappedAppId: mapped,
24011
+ appId,
24012
+ profile: pLower
24013
+ });
24014
+ }
24015
+ }
24016
+ const out = [];
24017
+ const rewriteSegments = [];
24018
+ let normalizedLength = 0;
24019
+ let cursor = 0;
24020
+ const appendSegment = (text, sourceStart, sourceEnd, bindingMappedAppId) => {
24021
+ if (!text && sourceStart === sourceEnd) return;
24022
+ const normalizedStart = normalizedLength;
24023
+ out.push(text);
24024
+ normalizedLength += text.length;
24025
+ rewriteSegments.push({
24026
+ normalizedStart,
24027
+ normalizedEnd: normalizedLength,
24028
+ sourceStart,
24029
+ sourceEnd,
24030
+ ...bindingMappedAppId === void 0 ? {} : { bindingMappedAppId }
24031
+ });
24032
+ };
24033
+ for (const t of tokens) {
24034
+ const pLower = normalizedProfile(t.profile).toLowerCase();
24035
+ let binding;
24036
+ if (t.source === "physical") {
24037
+ const mapped = pairToMapped.get(`physical:${t.appId}@${pLower}`) ?? t.appId;
24038
+ binding = { source: "physical", mappedAppId: mapped, appId: t.appId, profile: pLower };
24039
+ } else {
24040
+ const logicalKey = `logical:${t.logicalName}@${pLower}`;
24041
+ let mapped = pairToMapped.get(logicalKey);
24042
+ if (mapped === void 0) {
24043
+ mapped = nextVirtualAppId(usedAppIds);
24044
+ pairToMapped.set(logicalKey, mapped);
24045
+ }
24046
+ binding = {
24047
+ source: "logical",
24048
+ logicalName: t.logicalName,
24049
+ mappedAppId: mapped,
24050
+ appId: resolvedLogicalApps.get(logicalKey),
24051
+ profile: pLower
24052
+ };
24053
+ }
24054
+ appBindingByMappedApp.set(binding.mappedAppId, binding);
24055
+ appendSegment(sql.slice(cursor, t.start), cursor, t.start);
24056
+ const subtableSuffix = sql.slice(t.referenceValueEnd, t.appEnd);
24057
+ const normalizedReference = t.source === "physical" ? `${sql.slice(t.start, t.referenceValueStart)}${binding.mappedAppId}${subtableSuffix}` : `APP${binding.mappedAppId}${subtableSuffix}`;
24058
+ appendSegment(normalizedReference, t.start, t.fullEnd, binding.mappedAppId);
24059
+ cursor = t.fullEnd;
24060
+ }
24061
+ appendSegment(sql.slice(cursor), cursor, sql.length);
24062
+ return { normalizedSql: out.join(""), hasProfileSyntax, appBindingByMappedApp, rewriteSegments };
24063
+ }
24064
+
23816
24065
  // src/node/config.ts
23817
- var LOGICAL_APP_NAME_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
23818
24066
  var PHYSICAL_APP_KEY_RE = /^APP\d+$/i;
23819
24067
  var NUMERIC_APP_KEY_RE = /^\d+$/;
23820
24068
  var LOGICAL_SQL_KEY_RE = /^LAPP_/i;
@@ -23834,12 +24082,14 @@ function normalizeLogicalApps(profileName, value) {
23834
24082
  `logical app key "${rawName}" in profile "${profileName}" must be a logical name without APP, numeric, or LAPP_ syntax.`
23835
24083
  );
23836
24084
  }
23837
- if (!LOGICAL_APP_NAME_RE.test(rawName)) {
24085
+ let logicalName;
24086
+ try {
24087
+ logicalName = canonicalizeLogicalAppName(rawName);
24088
+ } catch {
23838
24089
  throw argumentError(
23839
- `logical app key "${rawName}" in profile "${profileName}" must match [A-Z][A-Z0-9_]{0,63}.`
24090
+ `logical app key "${rawName}" in profile "${profileName}" must match the logical app name rules.`
23840
24091
  );
23841
24092
  }
23842
- const logicalName = rawName.toUpperCase();
23843
24093
  if (Object.prototype.hasOwnProperty.call(normalized, logicalName)) {
23844
24094
  throw argumentError(
23845
24095
  `logical app name "${logicalName}" is duplicated after case normalization in profile "${profileName}".`
@@ -23912,11 +24162,13 @@ function createAppResolutionContext(config, defaultProfile) {
23912
24162
  }
23913
24163
  return {
23914
24164
  resolveLogicalApp(name, profile) {
23915
- if (!LOGICAL_APP_NAME_RE.test(name)) {
23916
- throw argumentError(`logical app name "${name}" must match [A-Z][A-Z0-9_]{0,63}.`);
23917
- }
23918
24165
  const profileName = profile || defaultProfile;
23919
- const logicalName = name.toUpperCase();
24166
+ let logicalName;
24167
+ try {
24168
+ logicalName = canonicalizeLogicalAppName(name);
24169
+ } catch {
24170
+ throw argumentError(`logical app name "${name}" must match the logical app name rules.`);
24171
+ }
23920
24172
  const appId = requireProfile(profileName).logicalApps?.[logicalName];
23921
24173
  if (appId === void 0) {
23922
24174
  throw argumentError(`logical app LAPP_${logicalName}@${profileName} is not defined.`);
@@ -24973,250 +25225,6 @@ function extractAppIds(sql) {
24973
25225
  }
24974
25226
  return [...out];
24975
25227
  }
24976
- function isSqlIdentContinue(ch) {
24977
- if (!ch) return false;
24978
- const cp = ch.codePointAt(0);
24979
- return cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp >= 48 && cp <= 57 || cp === 95 || cp === 36 || cp >= 12352 && cp <= 12543 || cp >= 13312 && cp <= 40959 || cp >= 63744 && cp <= 64255 || cp >= 65281 && cp <= 65376;
24980
- }
24981
- function isProfileNameChar(ch) {
24982
- if (!ch) return false;
24983
- const cp = ch.codePointAt(0);
24984
- return cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp >= 48 && cp <= 57 || ch === "_" || ch === "-" || ch === "." || ch === "$";
24985
- }
24986
- function isAsciiLogicalNameStart(ch) {
24987
- return /^[A-Za-z]$/.test(ch);
24988
- }
24989
- function isAsciiLogicalNameContinue(ch) {
24990
- return /^[A-Za-z0-9_]$/.test(ch);
24991
- }
24992
- function tryParseAppProfileToken(sql, start) {
24993
- const prev = start > 0 ? sql[start - 1] : "";
24994
- if (isSqlIdentContinue(prev)) return null;
24995
- let source;
24996
- let appId;
24997
- let logicalName;
24998
- let referenceValueStart;
24999
- let referenceValueEnd;
25000
- let i;
25001
- if (sql.slice(start, start + 5).toUpperCase() === "LAPP_") {
25002
- source = "logical";
25003
- i = start + 5;
25004
- referenceValueStart = i;
25005
- if (!isAsciiLogicalNameStart(sql[i] ?? "")) return null;
25006
- i++;
25007
- while (i < sql.length && isAsciiLogicalNameContinue(sql[i])) i++;
25008
- referenceValueEnd = i;
25009
- if (referenceValueEnd - referenceValueStart > 64) return null;
25010
- logicalName = sql.slice(referenceValueStart, referenceValueEnd).toUpperCase();
25011
- } else if (sql.slice(start, start + 3).toUpperCase() === "APP") {
25012
- source = "physical";
25013
- i = start + 3;
25014
- referenceValueStart = i;
25015
- while (i < sql.length && /[0-9]/.test(sql[i])) i++;
25016
- referenceValueEnd = i;
25017
- if (referenceValueEnd === referenceValueStart) return null;
25018
- appId = Number(sql.slice(referenceValueStart, referenceValueEnd));
25019
- } else {
25020
- return null;
25021
- }
25022
- if (sql[i] === "$") {
25023
- i++;
25024
- const subStart = i;
25025
- while (i < sql.length && isSqlIdentContinue(sql[i])) i++;
25026
- if (i === subStart) return null;
25027
- }
25028
- const appEnd = i;
25029
- let profile = null;
25030
- if (sql[i] === "@") {
25031
- i++;
25032
- const pStart = i;
25033
- while (i < sql.length && isProfileNameChar(sql[i])) i++;
25034
- if (i === pStart) return null;
25035
- profile = sql.slice(pStart, i);
25036
- }
25037
- const next = i < sql.length ? sql[i] : "";
25038
- if (isSqlIdentContinue(next)) return null;
25039
- const common = {
25040
- profile,
25041
- start,
25042
- referenceValueStart,
25043
- referenceValueEnd,
25044
- appEnd,
25045
- fullEnd: i
25046
- };
25047
- return source === "physical" ? { ...common, source, appId } : { ...common, source, logicalName };
25048
- }
25049
- function collectAppProfileTokens(sql) {
25050
- const tokens = [];
25051
- let i = 0;
25052
- while (i < sql.length) {
25053
- const ch = sql[i];
25054
- if (ch === "'") {
25055
- i++;
25056
- while (i < sql.length) {
25057
- if (sql[i] === "'") {
25058
- i++;
25059
- if (i < sql.length && sql[i] === "'") {
25060
- i++;
25061
- continue;
25062
- }
25063
- break;
25064
- }
25065
- i++;
25066
- }
25067
- continue;
25068
- }
25069
- if (ch === "`") {
25070
- i++;
25071
- while (i < sql.length && sql[i] !== "`") i++;
25072
- if (i < sql.length) i++;
25073
- continue;
25074
- }
25075
- if (ch === "-" && sql[i + 1] === "-") {
25076
- i += 2;
25077
- while (i < sql.length && sql[i] !== "\n") i++;
25078
- continue;
25079
- }
25080
- if (ch === "/" && sql[i + 1] === "*") {
25081
- i += 2;
25082
- while (i < sql.length) {
25083
- if (sql[i] === "*" && sql[i + 1] === "/") {
25084
- i += 2;
25085
- break;
25086
- }
25087
- i++;
25088
- }
25089
- continue;
25090
- }
25091
- const parsed = tryParseAppProfileToken(sql, i);
25092
- if (!parsed) {
25093
- i++;
25094
- continue;
25095
- }
25096
- tokens.push(parsed);
25097
- i = parsed.fullEnd;
25098
- }
25099
- return tokens;
25100
- }
25101
- function nextVirtualAppId(used) {
25102
- let id = 9e8;
25103
- while (used.has(id)) id++;
25104
- used.add(id);
25105
- return id;
25106
- }
25107
- function normalizeSqlAppProfiles(sql, defaultProfile = "dev", resolutionContext) {
25108
- const tokens = collectAppProfileTokens(sql);
25109
- const hasProfileSyntax = tokens.some((t) => t.profile !== null);
25110
- const profilesByApp = /* @__PURE__ */ new Map();
25111
- const normalizedProfile = (profile) => profile ?? defaultProfile;
25112
- for (const t of tokens) {
25113
- if (t.source !== "physical") continue;
25114
- const p = normalizedProfile(t.profile);
25115
- let set = profilesByApp.get(t.appId);
25116
- if (!set) {
25117
- set = /* @__PURE__ */ new Set();
25118
- profilesByApp.set(t.appId, set);
25119
- }
25120
- set.add(p.toLowerCase());
25121
- }
25122
- const usedAppIds = new Set(
25123
- tokens.filter((t) => t.source === "physical").map((t) => t.appId)
25124
- );
25125
- const resolvedLogicalApps = /* @__PURE__ */ new Map();
25126
- for (const t of tokens) {
25127
- if (t.source !== "logical") continue;
25128
- const pLower = normalizedProfile(t.profile).toLowerCase();
25129
- const logicalKey = `logical:${t.logicalName}@${pLower}`;
25130
- if (resolvedLogicalApps.has(logicalKey)) continue;
25131
- if (!resolutionContext) {
25132
- throw new Error(
25133
- `ArgumentError: logical app LAPP_${t.logicalName}@${pLower} requires logicalApps configuration.`
25134
- );
25135
- }
25136
- const resolvedAppId = resolutionContext.resolveLogicalApp(t.logicalName, pLower);
25137
- resolvedLogicalApps.set(logicalKey, resolvedAppId);
25138
- usedAppIds.add(resolvedAppId);
25139
- }
25140
- const pairToMapped = /* @__PURE__ */ new Map();
25141
- const appBindingByMappedApp = /* @__PURE__ */ new Map();
25142
- for (const [appId, pSet] of profilesByApp.entries()) {
25143
- const profiles = [...pSet].sort();
25144
- if (profiles.length <= 1) continue;
25145
- for (const pLower of profiles) {
25146
- const mapped = nextVirtualAppId(usedAppIds);
25147
- pairToMapped.set(`physical:${appId}@${pLower}`, mapped);
25148
- appBindingByMappedApp.set(mapped, {
25149
- source: "physical",
25150
- mappedAppId: mapped,
25151
- appId,
25152
- profile: pLower
25153
- });
25154
- }
25155
- }
25156
- const out = [];
25157
- const rewriteSegments = [];
25158
- let normalizedLength = 0;
25159
- let cursor = 0;
25160
- const appendSegment = (text, sourceStart, sourceEnd, bindingMappedAppId) => {
25161
- if (!text && sourceStart === sourceEnd) return;
25162
- const normalizedStart = normalizedLength;
25163
- out.push(text);
25164
- normalizedLength += text.length;
25165
- rewriteSegments.push({
25166
- normalizedStart,
25167
- normalizedEnd: normalizedLength,
25168
- sourceStart,
25169
- sourceEnd,
25170
- ...bindingMappedAppId === void 0 ? {} : { bindingMappedAppId }
25171
- });
25172
- };
25173
- for (const t of tokens) {
25174
- const p = normalizedProfile(t.profile);
25175
- const pLower = p.toLowerCase();
25176
- let binding;
25177
- if (t.source === "physical") {
25178
- const mapped = pairToMapped.get(`physical:${t.appId}@${pLower}`) ?? t.appId;
25179
- binding = {
25180
- source: "physical",
25181
- mappedAppId: mapped,
25182
- appId: t.appId,
25183
- profile: pLower
25184
- };
25185
- } else {
25186
- const logicalKey = `logical:${t.logicalName}@${pLower}`;
25187
- let mapped = pairToMapped.get(logicalKey);
25188
- if (mapped === void 0) {
25189
- mapped = nextVirtualAppId(usedAppIds);
25190
- pairToMapped.set(logicalKey, mapped);
25191
- }
25192
- binding = {
25193
- source: "logical",
25194
- logicalName: t.logicalName,
25195
- mappedAppId: mapped,
25196
- appId: resolvedLogicalApps.get(logicalKey),
25197
- profile: pLower
25198
- };
25199
- }
25200
- appBindingByMappedApp.set(binding.mappedAppId, binding);
25201
- appendSegment(sql.slice(cursor, t.start), cursor, t.start);
25202
- const subtableSuffix = sql.slice(t.referenceValueEnd, t.appEnd);
25203
- const normalizedReference = t.source === "physical" ? `${sql.slice(t.start, t.referenceValueStart)}${binding.mappedAppId}${subtableSuffix}` : `APP${binding.mappedAppId}${subtableSuffix}`;
25204
- appendSegment(
25205
- normalizedReference,
25206
- t.start,
25207
- t.fullEnd,
25208
- binding.mappedAppId
25209
- );
25210
- cursor = t.fullEnd;
25211
- }
25212
- appendSegment(sql.slice(cursor), cursor, sql.length);
25213
- return {
25214
- normalizedSql: out.join(""),
25215
- hasProfileSyntax,
25216
- appBindingByMappedApp,
25217
- rewriteSegments
25218
- };
25219
- }
25220
25228
  function buildCacheContext(defaultProfile, appBindingByMappedApp) {
25221
25229
  if (appBindingByMappedApp.size === 0) return `default:${defaultProfile.toLowerCase()}`;
25222
25230
  const pairs = [...appBindingByMappedApp.entries()].sort((a, b) => a[0] - b[0]).map(([mappedAppId, b]) => b.source === "logical" ? `M${mappedAppId}=logical:${b.logicalName}:APP${b.appId}@${b.profile}` : `M${mappedAppId}=physical:APP${b.appId}@${b.profile}`);
@@ -26857,6 +26865,7 @@ async function run() {
26857
26865
  let containsApplyStatement = false;
26858
26866
  let containsApplyMutation = false;
26859
26867
  let dryRunNeedsMetadata = false;
26868
+ let parsedStatements = [];
26860
26869
  if (args.diagRecordId === null) {
26861
26870
  sql = args.executeSql;
26862
26871
  if (!sql && args.filePath) sql = (0, import_fs2.readFileSync)(args.filePath, "utf-8");
@@ -26884,6 +26893,7 @@ async function run() {
26884
26893
  const importEnabled = Object.keys(args.importCsv).length > 0 || Object.keys(args.importJson).length > 0;
26885
26894
  try {
26886
26895
  const statements = parseSqlStatements(sql, { import: importEnabled });
26896
+ parsedStatements = statements;
26887
26897
  const hasApply = (statement) => statement.type === "UPDATE" || statement.type === "INSERT" ? (statement.applyBlocks?.length ?? 0) > 0 : statement.type === "UPSERT" ? (statement.onInsertApplyBlocks?.length ?? 0) > 0 || (statement.onUpdateApplyBlocks?.length ?? 0) > 0 : false;
26888
26898
  containsApplyStatement = statements.some(hasApply);
26889
26899
  containsApplyMutation = statements.some((statement) => {
@@ -27360,7 +27370,7 @@ query=${label}`);
27360
27370
  return 2;
27361
27371
  }
27362
27372
  }
27363
- const batchResult = await executeBatch(sql, client, {
27373
+ let batchResult = await executeBatch(sql, client, {
27364
27374
  maxRecords,
27365
27375
  fetchParallel,
27366
27376
  onLimitReached: effectiveOnLimit,
@@ -27396,6 +27406,20 @@ query=${label}`);
27396
27406
  return true;
27397
27407
  } : void 0
27398
27408
  });
27409
+ if (sqlDiagnosticContext) {
27410
+ batchResult = {
27411
+ ...batchResult,
27412
+ statements: batchResult.statements.map(
27413
+ (statementResult, index) => parsedStatements[index]?.type === "EXPLAIN" && statementResult.result ? {
27414
+ ...statementResult,
27415
+ result: restoreSqlDiagnosticValue(
27416
+ statementResult.result,
27417
+ sqlDiagnosticContext.appBindingByMappedApp
27418
+ )
27419
+ } : statementResult
27420
+ )
27421
+ };
27422
+ }
27399
27423
  return writeBatchOutput(batchResult, { format, noHeader, pretty, displayOptions, outputPath, quiet });
27400
27424
  }
27401
27425
  let result = args.dryRun ? await execute(`EXPLAIN ${sql}`, client, {
@@ -27423,7 +27447,7 @@ query=${label}`);
27423
27447
  } : {},
27424
27448
  ...containsApplyMutation ? { allowApplyMutation: true } : {}
27425
27449
  });
27426
- if (args.dryRun && sqlDiagnosticContext) {
27450
+ if ((args.dryRun || parsedStatements[0]?.type === "EXPLAIN") && sqlDiagnosticContext) {
27427
27451
  result = restoreSqlDiagnosticValue(result, sqlDiagnosticContext.appBindingByMappedApp);
27428
27452
  }
27429
27453
  if (result.type === "ASSERT") {