@rex0220/kintone-sql-tools 3.36.0 → 3.37.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-cli/ksql.js +290 -260
- package/dist-engine/index.cjs +10 -9
- package/dist-engine/index.mjs +10 -9
- package/dist-engine/ksql-engine.umd.js +10 -9
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +58 -7
- package/dist-engine/meta/esm.json +58 -7
- package/dist-engine/meta/umd.json +58 -7
- package/dist-engine/publicTypes.d.ts +2 -0
- package/dist-mcp/ksql-mcp.js +303 -263
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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
|
-
|
|
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}`);
|
|
@@ -25324,35 +25332,41 @@ function tryParseStatements(sql) {
|
|
|
25324
25332
|
}
|
|
25325
25333
|
}
|
|
25326
25334
|
|
|
25327
|
-
// src/
|
|
25328
|
-
function restoreSqlDiagnosticValue(value, bindings) {
|
|
25335
|
+
// src/core/sqlDiagnostics.ts
|
|
25336
|
+
function restoreSqlDiagnosticValue(value, bindings, options = {}) {
|
|
25337
|
+
const displayMode = options.logicalAppDisplay ?? "profile";
|
|
25329
25338
|
if (typeof value === "string") {
|
|
25330
25339
|
const dmlTarget = value.match(/^(\s*target:\s*)APP(\d+) \((\d+)\)\s*$/);
|
|
25331
25340
|
if (dmlTarget && dmlTarget[2] === dmlTarget[3]) {
|
|
25332
25341
|
const binding = bindings.get(Number(dmlTarget[2]));
|
|
25333
25342
|
if (binding) {
|
|
25334
|
-
const target = binding.source === "logical" ? `LAPP_${binding.logicalName} -> APP${binding.appId}@${binding.profile}` : `APP${binding.appId}@${binding.profile}`;
|
|
25343
|
+
const target = binding.source === "logical" ? displayMode === "physical" ? `LAPP_${binding.logicalName} -> APP${binding.appId}` : `LAPP_${binding.logicalName} -> APP${binding.appId}@${binding.profile}` : displayMode === "physical" ? `APP${binding.appId}` : `APP${binding.appId}@${binding.profile}`;
|
|
25335
25344
|
return `${dmlTarget[1]}${target}`;
|
|
25336
25345
|
}
|
|
25337
25346
|
}
|
|
25338
25347
|
let restored = value;
|
|
25339
25348
|
for (const binding of bindings.values()) {
|
|
25340
25349
|
const internal = `APP${binding.mappedAppId}`;
|
|
25341
|
-
const display = binding.source === "logical" ? `LAPP_${binding.logicalName}@${binding.profile}` : `APP${binding.appId}@${binding.profile}`;
|
|
25350
|
+
const display = binding.source === "logical" ? displayMode === "physical" ? `LAPP_${binding.logicalName} -> APP${binding.appId}` : `LAPP_${binding.logicalName}@${binding.profile}` : displayMode === "physical" ? `APP${binding.appId}` : `APP${binding.appId}@${binding.profile}`;
|
|
25342
25351
|
restored = restored.split(`${internal} (${binding.mappedAppId})`).join(display).split(internal).join(display);
|
|
25343
25352
|
}
|
|
25344
25353
|
return restored;
|
|
25345
25354
|
}
|
|
25346
25355
|
if (Array.isArray(value)) {
|
|
25347
|
-
return value.map((item) => restoreSqlDiagnosticValue(item, bindings));
|
|
25356
|
+
return value.map((item) => restoreSqlDiagnosticValue(item, bindings, options));
|
|
25348
25357
|
}
|
|
25349
25358
|
if (value !== null && typeof value === "object") {
|
|
25350
25359
|
return Object.fromEntries(
|
|
25351
|
-
Object.entries(value).map(([key, item]) => [
|
|
25360
|
+
Object.entries(value).map(([key, item]) => [
|
|
25361
|
+
key,
|
|
25362
|
+
restoreSqlDiagnosticValue(item, bindings, options)
|
|
25363
|
+
])
|
|
25352
25364
|
);
|
|
25353
25365
|
}
|
|
25354
25366
|
return value;
|
|
25355
25367
|
}
|
|
25368
|
+
|
|
25369
|
+
// src/node/sqlDiagnostics.ts
|
|
25356
25370
|
function restoreSqlContextError(err, sourceSql, context) {
|
|
25357
25371
|
if (!(err instanceof Error)) return err;
|
|
25358
25372
|
let message = err.message;
|
|
@@ -26857,6 +26871,7 @@ async function run() {
|
|
|
26857
26871
|
let containsApplyStatement = false;
|
|
26858
26872
|
let containsApplyMutation = false;
|
|
26859
26873
|
let dryRunNeedsMetadata = false;
|
|
26874
|
+
let parsedStatements = [];
|
|
26860
26875
|
if (args.diagRecordId === null) {
|
|
26861
26876
|
sql = args.executeSql;
|
|
26862
26877
|
if (!sql && args.filePath) sql = (0, import_fs2.readFileSync)(args.filePath, "utf-8");
|
|
@@ -26884,6 +26899,7 @@ async function run() {
|
|
|
26884
26899
|
const importEnabled = Object.keys(args.importCsv).length > 0 || Object.keys(args.importJson).length > 0;
|
|
26885
26900
|
try {
|
|
26886
26901
|
const statements = parseSqlStatements(sql, { import: importEnabled });
|
|
26902
|
+
parsedStatements = statements;
|
|
26887
26903
|
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
26904
|
containsApplyStatement = statements.some(hasApply);
|
|
26889
26905
|
containsApplyMutation = statements.some((statement) => {
|
|
@@ -27360,7 +27376,7 @@ query=${label}`);
|
|
|
27360
27376
|
return 2;
|
|
27361
27377
|
}
|
|
27362
27378
|
}
|
|
27363
|
-
|
|
27379
|
+
let batchResult = await executeBatch(sql, client, {
|
|
27364
27380
|
maxRecords,
|
|
27365
27381
|
fetchParallel,
|
|
27366
27382
|
onLimitReached: effectiveOnLimit,
|
|
@@ -27396,6 +27412,20 @@ query=${label}`);
|
|
|
27396
27412
|
return true;
|
|
27397
27413
|
} : void 0
|
|
27398
27414
|
});
|
|
27415
|
+
if (sqlDiagnosticContext) {
|
|
27416
|
+
batchResult = {
|
|
27417
|
+
...batchResult,
|
|
27418
|
+
statements: batchResult.statements.map(
|
|
27419
|
+
(statementResult, index) => parsedStatements[index]?.type === "EXPLAIN" && statementResult.result ? {
|
|
27420
|
+
...statementResult,
|
|
27421
|
+
result: restoreSqlDiagnosticValue(
|
|
27422
|
+
statementResult.result,
|
|
27423
|
+
sqlDiagnosticContext.appBindingByMappedApp
|
|
27424
|
+
)
|
|
27425
|
+
} : statementResult
|
|
27426
|
+
)
|
|
27427
|
+
};
|
|
27428
|
+
}
|
|
27399
27429
|
return writeBatchOutput(batchResult, { format, noHeader, pretty, displayOptions, outputPath, quiet });
|
|
27400
27430
|
}
|
|
27401
27431
|
let result = args.dryRun ? await execute(`EXPLAIN ${sql}`, client, {
|
|
@@ -27423,7 +27453,7 @@ query=${label}`);
|
|
|
27423
27453
|
} : {},
|
|
27424
27454
|
...containsApplyMutation ? { allowApplyMutation: true } : {}
|
|
27425
27455
|
});
|
|
27426
|
-
if (args.dryRun && sqlDiagnosticContext) {
|
|
27456
|
+
if ((args.dryRun || parsedStatements[0]?.type === "EXPLAIN") && sqlDiagnosticContext) {
|
|
27427
27457
|
result = restoreSqlDiagnosticValue(result, sqlDiagnosticContext.appBindingByMappedApp);
|
|
27428
27458
|
}
|
|
27429
27459
|
if (result.type === "ASSERT") {
|