@coldsmirk/inkstone-sql 0.34.2 → 0.36.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/README.md +12 -1
- package/dist/{assist-Cr2idunB.d.ts → assist-lygAVE0T.d.ts} +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +381 -16
- package/dist/monaco.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -41,7 +41,18 @@ Everything the intelligence answers goes through one lexical reader taken under
|
|
|
41
41
|
|
|
42
42
|
## The mirror invariant
|
|
43
43
|
|
|
44
|
-
`noise.ts` (which runs of a statement are strings / comments / quoted names, per kind) and the marker grammar mirror [**polyglot's engine scanner**](https://github.com/coldsmirk/polyglot) (`sql/Placeholders`, over its profiles in `kinds/Dialect`) flag for flag, each kind under the two lexicons the sidecar reads it by: the database's own says where a statement ends and what is prose, and the one the kind's driver finds a `?` by says where the markers are — SQL Server nests a block comment, but Microsoft's driver ends one at its first close and binds a `?` past it; ClickHouse's driver reads a `?` as the conditional operator `a ? b : c` where a lone `:` follows it before any other `?`, and binds nothing through that `:` (`conditional.ts`). The scanner decides what actually binds; a reader that diverged would prompt for a parameter the engine refuses, or send a statement short of one it binds. **A scanner change requires a matching release of this package**, and the per-kind cases in `reader.test.ts` are the invariant's guard.
|
|
44
|
+
`noise.ts` (which runs of a statement are strings / comments / quoted names, per kind) and the marker grammar mirror [**polyglot's engine scanner**](https://github.com/coldsmirk/polyglot) (`sql/Placeholders`, over its profiles in `kinds/Dialect`) flag for flag, each kind under the two lexicons the sidecar reads it by: the database's own says where a statement ends and what is prose, and the one the kind's driver finds a `?` by says where the markers are — SQL Server nests a block comment, but Microsoft's driver ends one at its first close and binds a `?` past it; ClickHouse's driver reads a `?` as the conditional operator `a ? b : c` where a lone `:` follows it before any other `?`, and binds nothing through that `:` (`conditional.ts`). The scanner decides what actually binds; a reader that diverged would prompt for a parameter the engine refuses, or send a statement short of one it binds. **A scanner change requires a matching release of this package**, and the per-kind cases in `reader.test.ts` are the invariant's guard. A statement that defines, changes or drops an object, or grants on one (its first word `CREATE`, `ALTER`, `DROP`, `COMMENT`, `RENAME`, `TRUNCATE`, `GRANT` or `REVOKE`), asks for no values: the scanner sends one as written, so a trigger's `:new` is the trigger's row and never a marker (`Placeholders.definesObjects`).
|
|
45
|
+
|
|
46
|
+
## Where a statement ends
|
|
47
|
+
|
|
48
|
+
`runnableStatement` parts a script as the kind's own command-line client parts it (`separators.ts`), since that is the tool a pasted script was written for:
|
|
49
|
+
|
|
50
|
+
- **Oracle and 达梦** (SQL*Plus, DIsql): a line holding only `/` ends whatever stands above it; an anonymous block (`DECLARE` / `BEGIN`) or a stored PL/SQL unit (`CREATE [OR REPLACE] PROCEDURE | FUNCTION | PACKAGE | TRIGGER | TYPE | LIBRARY`, 达梦's `CLASS`) runs past its inner `;`s to the `;` after the `END` that closes it, read by its blocks' nesting, and keeps that `;`, which PL/SQL requires.
|
|
51
|
+
- **MySQL** (`mysql`): `DELIMITER` lines name what ends a statement until the next, and a routine (`CREATE … PROCEDURE | FUNCTION | TRIGGER | EVENT`) runs past the `;`s of its compound statements.
|
|
52
|
+
- **SQL Server** (sqlcmd): a line holding only `GO` ends a batch, and a `PROCEDURE`, `FUNCTION` or `TRIGGER` created or altered runs to its batch's end, as T-SQL reads a routine's body.
|
|
53
|
+
- **PostgreSQL and Kingbase** (psql): a `CREATE [OR REPLACE] FUNCTION | PROCEDURE` runs past the `;`s of a `BEGIN ATOMIC … END` body, counted as psql counts them.
|
|
54
|
+
|
|
55
|
+
Everything else ends at its `;`, which is left off. Completion, hover and signature help read the statement of a routine's body the caret is in; `separators.test.ts` is the guard.
|
|
45
56
|
|
|
46
57
|
## Structured refusals
|
|
47
58
|
|
|
@@ -169,7 +169,9 @@ declare function readStatement(text: string, cursor: number, kind: SqlKind): Sta
|
|
|
169
169
|
type Runnable = {
|
|
170
170
|
kind: "one";
|
|
171
171
|
/**
|
|
172
|
-
* The statement itself, without the whitespace around it or the
|
|
172
|
+
* The statement itself, without the whitespace around it or the separator that ended it:
|
|
173
|
+
* its `;`, a `/` or `GO` line, a `DELIMITER`'s own. A PL/SQL unit keeps its closing `;`,
|
|
174
|
+
* which is PL/SQL's own syntax (`separators.ts`).
|
|
173
175
|
*/
|
|
174
176
|
text: string;
|
|
175
177
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CatalogTable, S as CatalogFunction, _ as readCall, a as createSqlAssist, b as runnableStatement, c as SqlSource, d as CallRead, f as IdentifierRead, g as TableRef, h as StatementRead, i as SqlSignatureHelp, l as createSqlSchema, m as StatementContext, n as SqlCompletionCandidate, o as SqlCatalog, p as Runnable, r as SqlHoverCard, s as SqlSchema, t as SqlAssist, u as qualifiedName, v as readIdentifier, w as SqlKind, x as CatalogColumn, y as readStatement } from "./assist-
|
|
1
|
+
import { C as CatalogTable, S as CatalogFunction, _ as readCall, a as createSqlAssist, b as runnableStatement, c as SqlSource, d as CallRead, f as IdentifierRead, g as TableRef, h as StatementRead, i as SqlSignatureHelp, l as createSqlSchema, m as StatementContext, n as SqlCompletionCandidate, o as SqlCatalog, p as Runnable, r as SqlHoverCard, s as SqlSchema, t as SqlAssist, u as qualifiedName, v as readIdentifier, w as SqlKind, x as CatalogColumn, y as readStatement } from "./assist-lygAVE0T.js";
|
|
2
2
|
//#region src/functions.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* The function vocabulary this bench speaks: the curated floor this project wrote
|
package/dist/index.js
CHANGED
|
@@ -431,18 +431,18 @@ const SPELLINGS = {
|
|
|
431
431
|
reserved: CLICKHOUSE_RESERVED
|
|
432
432
|
}
|
|
433
433
|
};
|
|
434
|
-
function delimited(spelling, name) {
|
|
434
|
+
function delimited$1(spelling, name) {
|
|
435
435
|
const escaped = spelling.backslash === true ? name.replaceAll("\\", () => "\\\\") : name;
|
|
436
436
|
return `${spelling.open}${escaped.replaceAll(spelling.close, () => spelling.close + spelling.close)}${spelling.close}`;
|
|
437
437
|
}
|
|
438
438
|
function spellIdentifier(kind, name) {
|
|
439
439
|
const spelling = SPELLINGS[kind];
|
|
440
440
|
if (spelling.regular.test(name) && !spelling.reserved.has(name.toLowerCase())) return name;
|
|
441
|
-
return delimited(spelling, name);
|
|
441
|
+
return delimited$1(spelling, name);
|
|
442
442
|
}
|
|
443
443
|
function spellCallable(kind, name) {
|
|
444
444
|
const spelling = SPELLINGS[kind];
|
|
445
|
-
return spelling.regular.test(name) ? name : delimited(spelling, name);
|
|
445
|
+
return spelling.regular.test(name) ? name : delimited$1(spelling, name);
|
|
446
446
|
}
|
|
447
447
|
function spellQualifier(kind, source) {
|
|
448
448
|
return source.aliasWritten === "" ? spellIdentifier(kind, source.table.name) : source.aliasWritten;
|
|
@@ -801,17 +801,354 @@ function insideNoise(spans, cursor) {
|
|
|
801
801
|
return spans.some((span) => !span.name && cursor > span.start && (span.sealed ? cursor < span.end : cursor <= span.end));
|
|
802
802
|
}
|
|
803
803
|
//#endregion
|
|
804
|
+
//#region src/separators.ts
|
|
805
|
+
const TOKEN = /(?<word>[a-z_\u{0080}-\u{FFFF}][\w$#\u{0080}-\u{FFFF}]*)|\d[\w.]*|\S/giu;
|
|
806
|
+
const SLASH_LINE = /^\s*\/\s*$/;
|
|
807
|
+
const GO_LINE = /^\s*go(?:\s+\d+)?\s*$/i;
|
|
808
|
+
const DELIMITER_LINE = /^\s*delimiter\s+(?<delimiter>\S+)\s*$/i;
|
|
809
|
+
const PLSQL_MODIFIERS = /* @__PURE__ */ new Set([
|
|
810
|
+
"OR",
|
|
811
|
+
"REPLACE",
|
|
812
|
+
"EDITIONABLE",
|
|
813
|
+
"NONEDITIONABLE"
|
|
814
|
+
]);
|
|
815
|
+
const DECLARES = /* @__PURE__ */ new Set([
|
|
816
|
+
";",
|
|
817
|
+
"IS",
|
|
818
|
+
"AS",
|
|
819
|
+
"DECLARE",
|
|
820
|
+
"CREATE",
|
|
821
|
+
"REPLACE",
|
|
822
|
+
"EDITIONABLE",
|
|
823
|
+
"NONEDITIONABLE",
|
|
824
|
+
"MEMBER",
|
|
825
|
+
"STATIC",
|
|
826
|
+
"CONSTRUCTOR",
|
|
827
|
+
"MAP",
|
|
828
|
+
"ORDER",
|
|
829
|
+
"FINAL",
|
|
830
|
+
"INSTANTIABLE",
|
|
831
|
+
"OVERRIDING"
|
|
832
|
+
]);
|
|
833
|
+
const HEADS = /* @__PURE__ */ new Set([
|
|
834
|
+
"CREATE",
|
|
835
|
+
"REPLACE",
|
|
836
|
+
"EDITIONABLE",
|
|
837
|
+
"NONEDITIONABLE"
|
|
838
|
+
]);
|
|
839
|
+
const CALL_SPECS = /* @__PURE__ */ new Set([
|
|
840
|
+
"LANGUAGE",
|
|
841
|
+
"EXTERNAL",
|
|
842
|
+
"MLE"
|
|
843
|
+
]);
|
|
844
|
+
const MYSQL_ROUTINES = /* @__PURE__ */ new Set([
|
|
845
|
+
"PROCEDURE",
|
|
846
|
+
"FUNCTION",
|
|
847
|
+
"TRIGGER",
|
|
848
|
+
"EVENT"
|
|
849
|
+
]);
|
|
850
|
+
const MYSQL_STATEMENT_STARTS = /* @__PURE__ */ new Set([
|
|
851
|
+
";",
|
|
852
|
+
"BEGIN",
|
|
853
|
+
"THEN",
|
|
854
|
+
"ELSE",
|
|
855
|
+
"DO",
|
|
856
|
+
"LOOP",
|
|
857
|
+
"REPEAT",
|
|
858
|
+
":",
|
|
859
|
+
"ROW"
|
|
860
|
+
]);
|
|
861
|
+
const TSQL_ROUTINES = /* @__PURE__ */ new Set([
|
|
862
|
+
"PROCEDURE",
|
|
863
|
+
"PROC",
|
|
864
|
+
"FUNCTION",
|
|
865
|
+
"TRIGGER"
|
|
866
|
+
]);
|
|
867
|
+
function plsqlUnit(units) {
|
|
868
|
+
return ([first, ...rest]) => {
|
|
869
|
+
if (first === "DECLARE" || first === "BEGIN") return "plsql";
|
|
870
|
+
if (first !== "CREATE") return "plain";
|
|
871
|
+
const made = rest.find((word) => !PLSQL_MODIFIERS.has(word));
|
|
872
|
+
return made === void 0 ? null : units.has(made) ? "plsql" : "plain";
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
const MYSQL_DEFINERS = /* @__PURE__ */ new Set([
|
|
876
|
+
"DEFINER",
|
|
877
|
+
"AGGREGATE",
|
|
878
|
+
"=",
|
|
879
|
+
"@",
|
|
880
|
+
"(",
|
|
881
|
+
")"
|
|
882
|
+
]);
|
|
883
|
+
function mysqlUnit([first, ...rest]) {
|
|
884
|
+
if (first !== "CREATE") return "plain";
|
|
885
|
+
for (const [at, token] of rest.entries()) {
|
|
886
|
+
if (MYSQL_ROUTINES.has(token)) return "compound";
|
|
887
|
+
const before = at === 0 ? first : rest[at - 1];
|
|
888
|
+
if (!(MYSQL_DEFINERS.has(token) || before === "=" || before === "@")) return "plain";
|
|
889
|
+
}
|
|
890
|
+
return null;
|
|
891
|
+
}
|
|
892
|
+
function tsqlUnit([first, ...rest]) {
|
|
893
|
+
if (first !== "CREATE" && first !== "ALTER") return "plain";
|
|
894
|
+
const made = rest.find((word) => word !== "OR" && word !== "ALTER");
|
|
895
|
+
return made === void 0 ? null : TSQL_ROUTINES.has(made) ? "batch" : "plain";
|
|
896
|
+
}
|
|
897
|
+
function psqlUnit([first, ...rest]) {
|
|
898
|
+
if (first !== "CREATE") return "plain";
|
|
899
|
+
if (rest[0] === "OR" && rest.length < 3) return null;
|
|
900
|
+
const made = rest[0] === "OR" ? rest[1] === "REPLACE" ? rest[2] : "" : rest[0];
|
|
901
|
+
return made === void 0 ? null : made === "FUNCTION" || made === "PROCEDURE" ? "atomic" : "plain";
|
|
902
|
+
}
|
|
903
|
+
const UNIT_OF = {
|
|
904
|
+
oracle: plsqlUnit(/* @__PURE__ */ new Set([
|
|
905
|
+
"PROCEDURE",
|
|
906
|
+
"FUNCTION",
|
|
907
|
+
"PACKAGE",
|
|
908
|
+
"TRIGGER",
|
|
909
|
+
"TYPE",
|
|
910
|
+
"LIBRARY"
|
|
911
|
+
])),
|
|
912
|
+
dm: plsqlUnit(/* @__PURE__ */ new Set([
|
|
913
|
+
"PROCEDURE",
|
|
914
|
+
"FUNCTION",
|
|
915
|
+
"PACKAGE",
|
|
916
|
+
"TRIGGER",
|
|
917
|
+
"TYPE",
|
|
918
|
+
"CLASS"
|
|
919
|
+
])),
|
|
920
|
+
mysql: mysqlUnit,
|
|
921
|
+
sqlserver: tsqlUnit,
|
|
922
|
+
postgres: psqlUnit,
|
|
923
|
+
kingbase: psqlUnit,
|
|
924
|
+
doris: () => "plain",
|
|
925
|
+
clickhouse: () => "plain"
|
|
926
|
+
};
|
|
927
|
+
function parenthesized(reading, token) {
|
|
928
|
+
if (token === "(") reading.parens += 1;
|
|
929
|
+
else if (token === ")") reading.parens = Math.max(0, reading.parens - 1);
|
|
930
|
+
return token === "(" || token === ")" || reading.parens > 0;
|
|
931
|
+
}
|
|
932
|
+
function closes(reading, token, closers) {
|
|
933
|
+
const { closing } = reading;
|
|
934
|
+
reading.closing = false;
|
|
935
|
+
return closing && closers.has(token);
|
|
936
|
+
}
|
|
937
|
+
const PLSQL_CLOSERS = /* @__PURE__ */ new Set([
|
|
938
|
+
"IF",
|
|
939
|
+
"LOOP",
|
|
940
|
+
"CASE"
|
|
941
|
+
]);
|
|
942
|
+
function declares(reading) {
|
|
943
|
+
reading.header ||= DECLARES.has(reading.previous);
|
|
944
|
+
}
|
|
945
|
+
function heads(reading) {
|
|
946
|
+
reading.header ||= HEADS.has(reading.previous);
|
|
947
|
+
}
|
|
948
|
+
function opens(reading) {
|
|
949
|
+
if (!reading.header) return;
|
|
950
|
+
reading.header = false;
|
|
951
|
+
reading.opened = true;
|
|
952
|
+
reading.frames.push("declare");
|
|
953
|
+
}
|
|
954
|
+
function times(reading) {
|
|
955
|
+
reading.header ||= reading.frames.at(-1) === "compound";
|
|
956
|
+
}
|
|
957
|
+
function controls({ frames }) {
|
|
958
|
+
frames.push("control");
|
|
959
|
+
}
|
|
960
|
+
const PLSQL_WORDS = /* @__PURE__ */ new Map([
|
|
961
|
+
["DECLARE", ({ frames }) => {
|
|
962
|
+
frames.push("declare");
|
|
963
|
+
}],
|
|
964
|
+
["BEGIN", ({ frames }) => {
|
|
965
|
+
if (frames.at(-1) === "declare") frames[frames.length - 1] = "body";
|
|
966
|
+
else frames.push("body");
|
|
967
|
+
}],
|
|
968
|
+
["IF", controls],
|
|
969
|
+
["LOOP", controls],
|
|
970
|
+
["CASE", controls],
|
|
971
|
+
["END", (reading) => {
|
|
972
|
+
reading.frames.pop();
|
|
973
|
+
reading.closing = true;
|
|
974
|
+
}],
|
|
975
|
+
["IS", opens],
|
|
976
|
+
["AS", opens],
|
|
977
|
+
["PROCEDURE", declares],
|
|
978
|
+
["FUNCTION", declares],
|
|
979
|
+
["PACKAGE", heads],
|
|
980
|
+
["CLASS", heads],
|
|
981
|
+
["BODY", (reading) => {
|
|
982
|
+
reading.header ||= reading.previous === "TYPE";
|
|
983
|
+
}],
|
|
984
|
+
["TRIGGER", (reading) => {
|
|
985
|
+
if (reading.previous === "COMPOUND") reading.frames.push("compound");
|
|
986
|
+
}],
|
|
987
|
+
["BEFORE", times],
|
|
988
|
+
["AFTER", times],
|
|
989
|
+
["INSTEAD", times]
|
|
990
|
+
]);
|
|
991
|
+
function plsql(reading, token) {
|
|
992
|
+
if (parenthesized(reading, token)) return false;
|
|
993
|
+
if (token === ";") {
|
|
994
|
+
reading.header = false;
|
|
995
|
+
reading.closing = false;
|
|
996
|
+
return reading.frames.length === 0;
|
|
997
|
+
}
|
|
998
|
+
if (reading.opened) {
|
|
999
|
+
reading.opened = false;
|
|
1000
|
+
if (CALL_SPECS.has(token)) reading.frames.pop();
|
|
1001
|
+
}
|
|
1002
|
+
if (!closes(reading, token, PLSQL_CLOSERS)) PLSQL_WORDS.get(token)?.(reading);
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
const MYSQL_CLOSERS = /* @__PURE__ */ new Set([
|
|
1006
|
+
"IF",
|
|
1007
|
+
"CASE",
|
|
1008
|
+
"LOOP",
|
|
1009
|
+
"WHILE",
|
|
1010
|
+
"REPEAT"
|
|
1011
|
+
]);
|
|
1012
|
+
function compound(reading, token) {
|
|
1013
|
+
if (parenthesized(reading, token)) return false;
|
|
1014
|
+
if (token === ";") {
|
|
1015
|
+
reading.closing = false;
|
|
1016
|
+
return reading.frames.length === 0;
|
|
1017
|
+
}
|
|
1018
|
+
if (closes(reading, token, MYSQL_CLOSERS)) return false;
|
|
1019
|
+
if (token === "BEGIN" || token === "CASE" || token === "LOOP") reading.frames.push("body");
|
|
1020
|
+
else if ((token === "IF" || token === "WHILE" || token === "REPEAT") && MYSQL_STATEMENT_STARTS.has(reading.previous)) reading.frames.push("control");
|
|
1021
|
+
else if (token === "END") {
|
|
1022
|
+
reading.frames.pop();
|
|
1023
|
+
reading.closing = true;
|
|
1024
|
+
}
|
|
1025
|
+
return false;
|
|
1026
|
+
}
|
|
1027
|
+
function atomic(reading, token) {
|
|
1028
|
+
if (parenthesized(reading, token)) return false;
|
|
1029
|
+
if (token === "BEGIN" || token === "CASE" && reading.depth >= 1) reading.depth += 1;
|
|
1030
|
+
else if (token === "END" && reading.depth > 0) reading.depth -= 1;
|
|
1031
|
+
return token === ";" && reading.depth === 0;
|
|
1032
|
+
}
|
|
1033
|
+
const ENDS = {
|
|
1034
|
+
plain: (_, token) => token === ";",
|
|
1035
|
+
plsql,
|
|
1036
|
+
compound,
|
|
1037
|
+
atomic,
|
|
1038
|
+
batch: () => false
|
|
1039
|
+
};
|
|
1040
|
+
function reading() {
|
|
1041
|
+
return {
|
|
1042
|
+
head: [],
|
|
1043
|
+
unit: null,
|
|
1044
|
+
frames: [],
|
|
1045
|
+
parens: 0,
|
|
1046
|
+
previous: "",
|
|
1047
|
+
closing: false,
|
|
1048
|
+
header: false,
|
|
1049
|
+
opened: false,
|
|
1050
|
+
depth: 0
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
function token(script, value, at) {
|
|
1054
|
+
if (script.current === null && value === ";") {
|
|
1055
|
+
script.separators.push({
|
|
1056
|
+
from: at,
|
|
1057
|
+
to: at + 1
|
|
1058
|
+
});
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
const current = script.current ?? reading();
|
|
1062
|
+
script.current = current;
|
|
1063
|
+
if (current.unit === null && value !== ";") {
|
|
1064
|
+
current.head.push(value);
|
|
1065
|
+
current.unit = UNIT_OF[script.kind](current.head);
|
|
1066
|
+
}
|
|
1067
|
+
const unit = current.unit ?? "plain";
|
|
1068
|
+
const ends = ENDS[unit](current, value);
|
|
1069
|
+
current.previous = value;
|
|
1070
|
+
if (ends) {
|
|
1071
|
+
script.separators.push(unit === "plsql" ? {
|
|
1072
|
+
from: at + 1,
|
|
1073
|
+
to: at + 1
|
|
1074
|
+
} : {
|
|
1075
|
+
from: at,
|
|
1076
|
+
to: at + 1
|
|
1077
|
+
});
|
|
1078
|
+
script.current = null;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
function delimited(script, line, lineStart) {
|
|
1082
|
+
const { delimiter } = script;
|
|
1083
|
+
let after = 0;
|
|
1084
|
+
for (let at = line.indexOf(delimiter); at !== -1; at = line.indexOf(delimiter, after)) {
|
|
1085
|
+
script.separators.push({
|
|
1086
|
+
from: lineStart + at,
|
|
1087
|
+
to: lineStart + at + delimiter.length
|
|
1088
|
+
});
|
|
1089
|
+
script.current = null;
|
|
1090
|
+
after = at + delimiter.length;
|
|
1091
|
+
}
|
|
1092
|
+
if (line.slice(after).trim() !== "") script.current ??= reading();
|
|
1093
|
+
}
|
|
1094
|
+
function statementSeparators(text, blanked, kind) {
|
|
1095
|
+
const script = {
|
|
1096
|
+
kind,
|
|
1097
|
+
separators: [],
|
|
1098
|
+
current: null,
|
|
1099
|
+
delimiter: ";"
|
|
1100
|
+
};
|
|
1101
|
+
const lineEnds = kind === "oracle" || kind === "dm" ? SLASH_LINE : kind === "sqlserver" ? GO_LINE : null;
|
|
1102
|
+
for (let lineStart = 0; lineStart <= blanked.length;) {
|
|
1103
|
+
const newline = blanked.indexOf("\n", lineStart);
|
|
1104
|
+
const lineEnd = newline === -1 ? blanked.length : newline;
|
|
1105
|
+
const line = blanked.slice(lineStart, lineEnd);
|
|
1106
|
+
const directive = kind === "mysql" && script.current === null && DELIMITER_LINE.test(line);
|
|
1107
|
+
if (lineEnds?.test(line) === true) {
|
|
1108
|
+
script.separators.push({
|
|
1109
|
+
from: lineStart,
|
|
1110
|
+
to: lineEnd
|
|
1111
|
+
});
|
|
1112
|
+
script.current = null;
|
|
1113
|
+
} else if (directive) {
|
|
1114
|
+
script.delimiter = DELIMITER_LINE.exec(text.slice(lineStart, lineEnd))?.groups?.delimiter ?? ";";
|
|
1115
|
+
script.separators.push({
|
|
1116
|
+
from: lineStart,
|
|
1117
|
+
to: lineEnd
|
|
1118
|
+
});
|
|
1119
|
+
} else if (script.delimiter === ";") for (const match of line.matchAll(TOKEN)) token(script, (match.groups.word ?? match[0]).toUpperCase(), lineStart + match.index);
|
|
1120
|
+
else delimited(script, line, lineStart);
|
|
1121
|
+
lineStart = lineEnd + 1;
|
|
1122
|
+
}
|
|
1123
|
+
return script.separators;
|
|
1124
|
+
}
|
|
1125
|
+
//#endregion
|
|
804
1126
|
//#region src/reader.ts
|
|
805
1127
|
const TOKENS = /[\w$\u{0080}-\u{FFFF}]+|"(?:[^"]|"")*"|`(?:[^`]|``)*`|\[(?:[^\]]|\]\])*\]|\S/gu;
|
|
806
1128
|
const TOKENS_TSQL = /[\w$#\u{0080}-\u{FFFF}]+|"(?:[^"]|"")*"|`(?:[^`]|``)*`|\[(?:[^\]]|\]\])*\]|\S/gu;
|
|
807
1129
|
const WORD_KIND = /^[\w$"`[\u{0080}-\u{FFFF}]/u;
|
|
808
1130
|
const WORD_KIND_TSQL = /^[\w$#"`[\u{0080}-\u{FFFF}]/u;
|
|
809
|
-
function
|
|
810
|
-
|
|
811
|
-
const
|
|
1131
|
+
function unitBounds(separators, cursor, length) {
|
|
1132
|
+
let start = 0;
|
|
1133
|
+
for (const separator of separators) {
|
|
1134
|
+
if (separator.to > cursor) return {
|
|
1135
|
+
start,
|
|
1136
|
+
end: separator.from
|
|
1137
|
+
};
|
|
1138
|
+
start = separator.to;
|
|
1139
|
+
}
|
|
812
1140
|
return {
|
|
813
1141
|
start,
|
|
814
|
-
end:
|
|
1142
|
+
end: length
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
function statementBounds(blanked, separators, cursor) {
|
|
1146
|
+
const unit = unitBounds(separators, cursor, blanked.length);
|
|
1147
|
+
const before = cursor === 0 ? -1 : blanked.lastIndexOf(";", cursor - 1);
|
|
1148
|
+
const close = blanked.indexOf(";", cursor);
|
|
1149
|
+
return {
|
|
1150
|
+
start: Math.max(unit.start, before + 1),
|
|
1151
|
+
end: close === -1 ? unit.end : Math.min(unit.end, close)
|
|
815
1152
|
};
|
|
816
1153
|
}
|
|
817
1154
|
function tokenize(blanked, bounds, kind) {
|
|
@@ -843,7 +1180,8 @@ function word(token) {
|
|
|
843
1180
|
function scan(text, cursor, kind) {
|
|
844
1181
|
const noise = blankNoise(text, kind);
|
|
845
1182
|
if (insideNoise(noise.spans, cursor)) return null;
|
|
846
|
-
|
|
1183
|
+
const separators = statementSeparators(text, noise.blanked, kind);
|
|
1184
|
+
return tokenize(noise.withNames, statementBounds(noise.blanked, separators, cursor), kind);
|
|
847
1185
|
}
|
|
848
1186
|
const TABLE_ANCHORS = /* @__PURE__ */ new Set([
|
|
849
1187
|
"from",
|
|
@@ -1067,22 +1405,28 @@ function trimmedSpan(text, blanked, from, to) {
|
|
|
1067
1405
|
to: end
|
|
1068
1406
|
};
|
|
1069
1407
|
}
|
|
1070
|
-
function statementSpans(text, blanked, from, to) {
|
|
1408
|
+
function statementSpans(text, blanked, separators, from, to) {
|
|
1071
1409
|
const spans = [];
|
|
1072
1410
|
let start = from;
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
const span = trimmedSpan(text, blanked, start, at);
|
|
1411
|
+
const piece = (end) => {
|
|
1412
|
+
const span = trimmedSpan(text, blanked, start, Math.max(start, end));
|
|
1076
1413
|
if (span !== null) spans.push(span);
|
|
1077
|
-
|
|
1414
|
+
};
|
|
1415
|
+
for (const separator of separators) {
|
|
1416
|
+
if (separator.to <= from) continue;
|
|
1417
|
+
if (separator.from >= to) break;
|
|
1418
|
+
piece(separator.from);
|
|
1419
|
+
start = Math.min(Math.max(start, separator.to), to);
|
|
1078
1420
|
}
|
|
1421
|
+
piece(to);
|
|
1079
1422
|
return spans;
|
|
1080
1423
|
}
|
|
1081
1424
|
function runnableStatement(text, from, to, kind) {
|
|
1082
1425
|
const { blanked } = blankNoise(text, kind);
|
|
1426
|
+
const separators = statementSeparators(text, blanked, kind);
|
|
1083
1427
|
const selected = from < to;
|
|
1084
|
-
const around =
|
|
1085
|
-
const spans = selected ? statementSpans(text, blanked, from, to) : statementSpans(text, blanked, around.start, around.end);
|
|
1428
|
+
const around = unitBounds(separators, from, text.length);
|
|
1429
|
+
const spans = selected ? statementSpans(text, blanked, separators, from, to) : statementSpans(text, blanked, separators, around.start, around.end);
|
|
1086
1430
|
if (spans.length === 0) return { kind: "none" };
|
|
1087
1431
|
if (selected && spans.length > 1) return { kind: "several" };
|
|
1088
1432
|
const span = spans[0];
|
|
@@ -1093,7 +1437,7 @@ function runnableStatement(text, from, to, kind) {
|
|
|
1093
1437
|
blanked: blankNoise(statement, kind, "driver").blanked,
|
|
1094
1438
|
from: span.from,
|
|
1095
1439
|
to: span.to,
|
|
1096
|
-
alone: statementSpans(text, blanked, 0, text.length).length <= 1
|
|
1440
|
+
alone: statementSpans(text, blanked, separators, 0, text.length).length <= 1
|
|
1097
1441
|
};
|
|
1098
1442
|
}
|
|
1099
1443
|
function readIdentifier(text, offset, kind) {
|
|
@@ -1612,7 +1956,28 @@ const NATIVE_GROUP = {
|
|
|
1612
1956
|
kingbase: "dollarDigits",
|
|
1613
1957
|
clickhouse: null
|
|
1614
1958
|
};
|
|
1959
|
+
const DEFINING = /* @__PURE__ */ new Set([
|
|
1960
|
+
"CREATE",
|
|
1961
|
+
"ALTER",
|
|
1962
|
+
"DROP",
|
|
1963
|
+
"COMMENT",
|
|
1964
|
+
"RENAME",
|
|
1965
|
+
"TRUNCATE",
|
|
1966
|
+
"GRANT",
|
|
1967
|
+
"REVOKE"
|
|
1968
|
+
]);
|
|
1969
|
+
const FIRST_WORD = /^\s*(?<word>[a-z_\u{0080}-\u{FFFF}][\w$\u{0080}-\u{FFFF}]*)/iu;
|
|
1970
|
+
function definesObjects(statement) {
|
|
1971
|
+
const word = FIRST_WORD.exec(statement)?.groups?.word;
|
|
1972
|
+
return word !== void 0 && DEFINING.has(word.toUpperCase());
|
|
1973
|
+
}
|
|
1615
1974
|
function statementMarkers(statement, kind) {
|
|
1975
|
+
if (definesObjects(statement)) return {
|
|
1976
|
+
form: "none",
|
|
1977
|
+
names: [],
|
|
1978
|
+
count: 0,
|
|
1979
|
+
refusal: null
|
|
1980
|
+
};
|
|
1616
1981
|
const names = [];
|
|
1617
1982
|
const nativeGroup = NATIVE_GROUP[kind];
|
|
1618
1983
|
let count = 0;
|
package/dist/monaco.d.ts
CHANGED
package/dist/react.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as SqlAssist } from "./assist-
|
|
1
|
+
import { t as SqlAssist } from "./assist-lygAVE0T.js";
|
|
2
2
|
import { ConsoleCaret, ConsoleEditorHandle, ConsoleEditorProps } from "@coldsmirk/inkstone-react/monaco";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
//#region src/react.d.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coldsmirk/inkstone-sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Schema-aware SQL editing intelligence for Monaco: lexical statement reading under per-dialect noise profiles, catalog-driven completion/hover/signature help, unified-placeholder awareness, formatting, and a drop-in React SQL editor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sql",
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"monaco-editor": "^0.57.0",
|
|
50
50
|
"react": "^19.3.0",
|
|
51
|
-
"@coldsmirk/inkstone-react": "^0.
|
|
51
|
+
"@coldsmirk/inkstone-react": "^0.36.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"monaco-editor": "^0.57.0",
|
|
55
55
|
"react": ">=19",
|
|
56
|
-
"@coldsmirk/inkstone-react": "^0.
|
|
56
|
+
"@coldsmirk/inkstone-react": "^0.36.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependenciesMeta": {
|
|
59
59
|
"@coldsmirk/inkstone-react": {
|