jsql-neo 6.4.0-beta.3 → 6.4.0-beta.4
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 +1 -1
- package/index.js +1 -1
- package/lib/sql.js +56 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **One engine to rule them all** — a Rust-powered embedded database that speaks your language:
|
|
4
4
|
> MySQL, PostgreSQL, MongoDB, Redis, SQL, TypeScript, **and the browser**.
|
|
5
5
|
|
|
6
|
-
> **v6.4.0-beta.
|
|
6
|
+
> **v6.4.0-beta.4** — official release build · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|

|
package/index.js
CHANGED
package/lib/sql.js
CHANGED
|
@@ -136,8 +136,22 @@ function tokenize(sql) {
|
|
|
136
136
|
let i = 0;
|
|
137
137
|
const n = sql.length;
|
|
138
138
|
|
|
139
|
+
// 获取位置 i 处的完整 Unicode 字符(处理代理对,如 emoji)
|
|
140
|
+
// 返回 { char, length },char 是完整字符,length 是 UTF-16 码元数
|
|
141
|
+
function charAt(pos) {
|
|
142
|
+
const c = sql[pos];
|
|
143
|
+
const code = sql.charCodeAt(pos);
|
|
144
|
+
if (code >= 0xD800 && code <= 0xDBFF && pos + 1 < n) {
|
|
145
|
+
const next = sql.charCodeAt(pos + 1);
|
|
146
|
+
if (next >= 0xDC00 && next <= 0xDFFF) {
|
|
147
|
+
return { char: sql.slice(pos, pos + 2), length: 2 };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { char: c, length: 1 };
|
|
151
|
+
}
|
|
152
|
+
|
|
139
153
|
while (i < n) {
|
|
140
|
-
const c =
|
|
154
|
+
const { char: c, length: cLen } = charAt(i);
|
|
141
155
|
|
|
142
156
|
if (c === ' ' || c === '\t' || c === '\n' || c === '\r') { i++; continue; }
|
|
143
157
|
|
|
@@ -188,6 +202,37 @@ function tokenize(sql) {
|
|
|
188
202
|
continue;
|
|
189
203
|
}
|
|
190
204
|
|
|
205
|
+
// 16 进制字面量:0x1F / 0XFF / X'1F' / x'FF'
|
|
206
|
+
// 标准 SQL:0x 前缀或 X'' 包裹,解析成十进制整数
|
|
207
|
+
if ((c === '0' && (sql[i + 1] === 'x' || sql[i + 1] === 'X')) ||
|
|
208
|
+
((c === 'X' || c === 'x') && sql[i + 1] === "'")) {
|
|
209
|
+
if (c === '0') {
|
|
210
|
+
// 0x 前缀形式:0x1F, 0XFF
|
|
211
|
+
let j = i + 2;
|
|
212
|
+
while (j < n && /[0-9A-Fa-f]/.test(sql[j])) j++;
|
|
213
|
+
if (j === i + 2) throw new Error(`Invalid hexadecimal literal at position ${i}`);
|
|
214
|
+
const hexStr = sql.slice(i + 2, j);
|
|
215
|
+
const numVal = parseInt(hexStr, 16);
|
|
216
|
+
tokens.push(new SQLToken('number', numVal, i));
|
|
217
|
+
i = j;
|
|
218
|
+
continue;
|
|
219
|
+
} else {
|
|
220
|
+
// X'...' 形式:X'1F', x'FF'
|
|
221
|
+
let j = i + 2;
|
|
222
|
+
let hexStr = '';
|
|
223
|
+
while (j < n && sql[j] !== "'") {
|
|
224
|
+
if (!/[0-9A-Fa-f]/.test(sql[j])) throw new Error(`Invalid hexadecimal literal at position ${j}`);
|
|
225
|
+
hexStr += sql[j];
|
|
226
|
+
j++;
|
|
227
|
+
}
|
|
228
|
+
if (j >= n) throw new Error(`Unterminated hexadecimal literal at position ${i}`);
|
|
229
|
+
const numVal = parseInt(hexStr, 16);
|
|
230
|
+
tokens.push(new SQLToken('number', numVal, i));
|
|
231
|
+
i = j + 1;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
191
236
|
if (/[0-9]/.test(c) || (c === '.' && /[0-9]/.test(sql[i + 1] || ''))) {
|
|
192
237
|
let j = i;
|
|
193
238
|
let isFloat = false;
|
|
@@ -219,9 +264,16 @@ function tokenize(sql) {
|
|
|
219
264
|
continue;
|
|
220
265
|
}
|
|
221
266
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
267
|
+
// Unicode 标识符:标准 SQL 允许非 ASCII 字母做列名/表名(中文、emoji 等)
|
|
268
|
+
// \p{L} = Unicode 字母,\p{So} = Unicode 其他符号(含 emoji),\p{M} = 组合标记
|
|
269
|
+
// 注意:不包含 \p{Sm}(数学符号如 + = < >)和 \p{P}(标点如 ( ) , ;)
|
|
270
|
+
if (/[\p{L}\p{So}\p{Sc}\p{M}_$]/u.test(c)) {
|
|
271
|
+
let j = i + cLen;
|
|
272
|
+
while (j < n) {
|
|
273
|
+
const { char: jc, length: jLen } = charAt(j);
|
|
274
|
+
if (!/[\p{L}\p{N}\p{So}\p{Sc}\p{M}_$]/u.test(jc)) break;
|
|
275
|
+
j += jLen;
|
|
276
|
+
}
|
|
225
277
|
const word = sql.slice(i, j);
|
|
226
278
|
const upper = word.toUpperCase();
|
|
227
279
|
const tok = new SQLToken(KEYWORDS.has(upper) ? 'keyword' : 'ident', word, i);
|
package/package.json
CHANGED