@graphenedata/cli 0.0.10 → 0.0.12
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/bin.js +15 -0
- package/cli.ts +6 -1
- package/dist/cli/cli.js +126 -113
- package/dist/docs/agent-instructions.md +18 -0
- package/dist/docs/graphene.md +308 -182
- package/dist/ui/app.css +8 -10
- package/dist/ui/components/_Table.svelte +16 -13
- package/dist/ui/internal/NavSidebar.svelte +24 -8
- package/dist/ui/internal/NavSidebarHMR.svelte +8 -0
- package/dist/ui/internal/queryEngine.ts +1 -1
- package/dist/ui/web.js +1 -1
- package/package.json +3 -2
package/dist/cli/cli.js
CHANGED
|
@@ -58,12 +58,12 @@ function walkExpression(root, fn, parent = null) {
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
async function pollFor(fn, timeoutMs,
|
|
61
|
+
async function pollFor(fn, timeoutMs, interval2) {
|
|
62
62
|
let end = Date.now() + timeoutMs;
|
|
63
63
|
while (Date.now() < end) {
|
|
64
64
|
let res = fn();
|
|
65
65
|
if (res) return res;
|
|
66
|
-
await new Promise((r) => setTimeout(r,
|
|
66
|
+
await new Promise((r) => setTimeout(r, interval2));
|
|
67
67
|
}
|
|
68
68
|
return null;
|
|
69
69
|
}
|
|
@@ -240,7 +240,11 @@ var init_functionDefs = __esm({
|
|
|
240
240
|
}
|
|
241
241
|
});
|
|
242
242
|
BIGQUERY_DIALECT_FUNCTIONS = {
|
|
243
|
-
"
|
|
243
|
+
"countif": {
|
|
244
|
+
takes: { "value": "boolean" },
|
|
245
|
+
returns: { measure: "number" },
|
|
246
|
+
impl: { function: "COUNTIF" }
|
|
247
|
+
},
|
|
244
248
|
"if": { ...DUCKDB_DIALECT_FUNCTIONS["if"] },
|
|
245
249
|
"safe_divide": {
|
|
246
250
|
takes: { "numerator": "number", "denominator": "number" },
|
|
@@ -478,29 +482,6 @@ function parseTemporalLiteral(value, expected) {
|
|
|
478
482
|
}
|
|
479
483
|
return null;
|
|
480
484
|
}
|
|
481
|
-
function parseTemporal(node) {
|
|
482
|
-
if (node.node !== "stringLiteral") return null;
|
|
483
|
-
let rawValue = typeof node.literal === "string" ? node.literal.trim() : "";
|
|
484
|
-
if (!rawValue) return null;
|
|
485
|
-
let parsedDate = parseTemporalLiteral(rawValue, "date");
|
|
486
|
-
if (parsedDate) {
|
|
487
|
-
let typeDef = { type: parsedDate.type, timeframe: parsedDate.timeframe };
|
|
488
|
-
Object.assign(node, { node: "timeLiteral", literal: parsedDate.literal, type: parsedDate.type, typeDef });
|
|
489
|
-
return parsedDate.timeframe;
|
|
490
|
-
}
|
|
491
|
-
let parsedTimestamp = parseTemporalLiteral(rawValue, "timestamp");
|
|
492
|
-
if (parsedTimestamp) {
|
|
493
|
-
let typeDef = { type: parsedTimestamp.type, timeframe: parsedTimestamp.timeframe };
|
|
494
|
-
Object.assign(node, { node: "timeLiteral", literal: parsedTimestamp.literal, type: parsedTimestamp.type, typeDef });
|
|
495
|
-
return parsedTimestamp.timeframe;
|
|
496
|
-
}
|
|
497
|
-
let interval = parseIntervalLiteral(rawValue);
|
|
498
|
-
if (interval) {
|
|
499
|
-
Object.assign(node, { node: "numberLiteral", literal: interval.quantity.toString(), type: "interval", intervalUnit: interval.unit });
|
|
500
|
-
return interval.unit;
|
|
501
|
-
}
|
|
502
|
-
return null;
|
|
503
|
-
}
|
|
504
485
|
function parseIntervalLiteral(value) {
|
|
505
486
|
let raw = (value ?? "").trim().toLowerCase().replace(/\s+/g, " ");
|
|
506
487
|
if (!raw) return null;
|
|
@@ -512,6 +493,9 @@ function parseIntervalLiteral(value) {
|
|
|
512
493
|
if (!unit) return null;
|
|
513
494
|
return { quantity, unit };
|
|
514
495
|
}
|
|
496
|
+
function parseIntervalUnit(value) {
|
|
497
|
+
return INTERVAL_UNITS[value.toLowerCase()] || null;
|
|
498
|
+
}
|
|
515
499
|
function buildResult(year, month, day, hour, minute, second, timeframe, expected) {
|
|
516
500
|
if (expected === "date") {
|
|
517
501
|
return { literal: `${pad(year)}-${pad(month)}-${pad(day)}`, timeframe, type: "date" };
|
|
@@ -528,8 +512,8 @@ function inRange(value, min, max) {
|
|
|
528
512
|
function isValidDate(year, month, day) {
|
|
529
513
|
if (!inRange(month, 1, 12)) return false;
|
|
530
514
|
if (!inRange(day, 1, 31)) return false;
|
|
531
|
-
let
|
|
532
|
-
return
|
|
515
|
+
let date2 = new Date(Date.UTC(year, month - 1, day));
|
|
516
|
+
return date2.getUTCFullYear() === year && date2.getUTCMonth() === month - 1 && date2.getUTCDate() === day;
|
|
533
517
|
}
|
|
534
518
|
function pad(value) {
|
|
535
519
|
return value.toString().padStart(2, "0");
|
|
@@ -717,9 +701,11 @@ function findTables(fi) {
|
|
|
717
701
|
let nodes = tn.getChildren("TableStatement").concat(tn.getChildren("ViewStatement"));
|
|
718
702
|
for (let syntaxNode of nodes) {
|
|
719
703
|
let name = txt(syntaxNode.getChild("Ref"));
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
704
|
+
let existing = Object.values(FILE_MAP).find((f) => {
|
|
705
|
+
if (f.path.endsWith(".md") && f.path != fi.path) return;
|
|
706
|
+
return f.tables.find((t) => t.name == name);
|
|
707
|
+
});
|
|
708
|
+
if (existing) diag(syntaxNode.getChild("Ref"), `Table "${name}" is already defined`);
|
|
723
709
|
let table2 = makeTable(name, syntaxNode.getChild("QueryStatement") ? "query_source" : "table");
|
|
724
710
|
table2.metadata = extractLeadingMetadata(syntaxNode);
|
|
725
711
|
syntaxNode.getChildren("ColumnDef").forEach((cn) => addColumnField(table2, cn));
|
|
@@ -734,7 +720,7 @@ function makeTable(name, type) {
|
|
|
734
720
|
return { name, type, fields: [], connection: config.dialect, dialect: config.dialect, tableName: name, tablePath, metadata: {} };
|
|
735
721
|
}
|
|
736
722
|
function addColumnField(table2, node) {
|
|
737
|
-
let name = txt(node.getChild("
|
|
723
|
+
let name = txt(node.getChild("ColumnName"));
|
|
738
724
|
if (node.getChild("PrimaryKey")) {
|
|
739
725
|
if (table2.primaryKey) diag(node, `Table ${table2.name} has multiple primary keys`);
|
|
740
726
|
table2.primaryKey = name;
|
|
@@ -957,6 +943,31 @@ function analyzeExpression(expr, scope) {
|
|
|
957
943
|
if (!type) return diag(expr.getChild("CastType"), `Unsupported cast type: ${targetTypeStr}`, errExpr2);
|
|
958
944
|
return { node: "cast", safe: false, e, dstSQLType: targetTypeStr.toUpperCase(), type, isAgg: e.isAgg };
|
|
959
945
|
}
|
|
946
|
+
case "IntervalExpression": {
|
|
947
|
+
let stringNode = expr.getChild("String");
|
|
948
|
+
if (stringNode) {
|
|
949
|
+
let parsed = parseIntervalLiteral(txt(stringNode).slice(1, -1));
|
|
950
|
+
if (!parsed) return diag(stringNode, "Could not parse interval literal", errExpr2);
|
|
951
|
+
return { node: "numberLiteral", literal: parsed.quantity.toString(), type: "interval", intervalUnit: parsed.unit, isAgg: false };
|
|
952
|
+
} else {
|
|
953
|
+
let numNode = expr.getChild("Number");
|
|
954
|
+
let unitNode = expr.getChild("IntervalUnit");
|
|
955
|
+
let quantity = Number(txt(numNode));
|
|
956
|
+
let unitStr = txt(unitNode).toLowerCase();
|
|
957
|
+
let unit = parseIntervalUnit(unitStr);
|
|
958
|
+
if (!unit) return diag(unitNode, `Invalid interval unit: "${unitStr}"`, errExpr2);
|
|
959
|
+
return { node: "numberLiteral", literal: quantity.toString(), type: "interval", intervalUnit: unit, isAgg: false };
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
case "DateExpression":
|
|
963
|
+
case "TimestampExpression": {
|
|
964
|
+
let expectedType = expr.name === "DateExpression" ? "date" : "timestamp";
|
|
965
|
+
let stringNode = expr.getChild("String");
|
|
966
|
+
let parsed = parseTemporalLiteral(txt(stringNode).slice(1, -1), expectedType);
|
|
967
|
+
if (!parsed) return diag(stringNode, `Could not parse ${expectedType}`, errExpr2);
|
|
968
|
+
let typeDef = { type: parsed.type, timeframe: parsed.timeframe };
|
|
969
|
+
return { node: "timeLiteral", literal: parsed.literal, type: parsed.type, typeDef, isAgg: false };
|
|
970
|
+
}
|
|
960
971
|
case "FunctionCall":
|
|
961
972
|
return analyzeFunctionCall(expr, scope);
|
|
962
973
|
case "Parenthetical":
|
|
@@ -1049,29 +1060,25 @@ function analyzeExpression(expr, scope) {
|
|
|
1049
1060
|
}
|
|
1050
1061
|
function analyzeTimeExpression(op, left2, right2, node) {
|
|
1051
1062
|
if (left2.type !== "date" && left2.type !== "timestamp") return diag(node, "Expected left side to be a date or timestamp", errExpr2);
|
|
1052
|
-
let units = left2.type === "timestamp" ? "second" : "day";
|
|
1053
|
-
if (right2.node == "stringLiteral") {
|
|
1054
|
-
units = parseTemporal(right2);
|
|
1055
|
-
if (right2.node == "stringLiteral") {
|
|
1056
|
-
return diag(node, "Could not parse interval", errExpr2);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
1063
|
if (right2.type == "date" || right2.type == "timestamp") {
|
|
1060
1064
|
if (op !== "-") return diag(node, "Only subtraction between dates is supported", errExpr2);
|
|
1061
1065
|
if (right2.type !== left2.type) return diag(node, `Expected right side to be a ${left2.type}`, errExpr2);
|
|
1066
|
+
let units = left2.type === "timestamp" ? "second" : "day";
|
|
1062
1067
|
return { node: "timeDiff", kids: { left: left2, right: right2 }, units, type: "interval", isAgg: false };
|
|
1063
1068
|
}
|
|
1064
1069
|
if (right2.type == "interval") {
|
|
1065
1070
|
let typeDef = { type: left2.type };
|
|
1071
|
+
let units = right2.intervalUnit;
|
|
1072
|
+
if (!units) return diag(node, "Interval must have a unit", errExpr2);
|
|
1066
1073
|
return { node: "delta", kids: { base: left2, delta: right2 }, op, units, type: left2.type, typeDef, isAgg: false };
|
|
1067
1074
|
}
|
|
1068
|
-
return diag(node, "Expected right side to be a date or interval", errExpr2);
|
|
1075
|
+
return diag(node, "Expected right side to be a date, timestamp, or interval", errExpr2);
|
|
1069
1076
|
}
|
|
1070
1077
|
function ensureSameType(left2, leftNode, right2, rightNode) {
|
|
1071
1078
|
if (left2.type === "error" || right2.type === "error") return;
|
|
1072
1079
|
if (left2.node === "parameter" || right2.node === "parameter") return;
|
|
1073
|
-
if (
|
|
1074
|
-
if (
|
|
1080
|
+
if (left2.type === "date" || left2.type === "timestamp") checkTypes(right2, [left2.type], rightNode);
|
|
1081
|
+
if (right2.type === "date" || right2.type === "timestamp") checkTypes(left2, [right2.type], leftNode);
|
|
1075
1082
|
if (left2.type !== right2.type) diag(rightNode, `Expected ${left2.type}, got ${right2.type}`);
|
|
1076
1083
|
}
|
|
1077
1084
|
function checkTypes(expr, expected, node) {
|
|
@@ -1085,11 +1092,9 @@ function checkTypes(expr, expected, node) {
|
|
|
1085
1092
|
if (!parsed) return diag(node, `Could not parse ${dt} literal: "${expr.literal}"`, void 0);
|
|
1086
1093
|
let typeDef = { type: parsed.type, timeframe: parsed.timeframe };
|
|
1087
1094
|
Object.assign(expr, { node: "timeLiteral", literal: parsed?.literal, type: parsed?.type, typeDef });
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
return Object.assign(expr, { node: "numberLiteral", literal: parsed.quantity.toString(), type: "interval", intervalUnit: parsed.unit });
|
|
1092
|
-
} else diag(node, `Expected types: ${expected.join(", ")}`);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
diag(node, `Expected types: ${expected.join(", ")}`);
|
|
1093
1098
|
}
|
|
1094
1099
|
function lookupField(expr, scope) {
|
|
1095
1100
|
let pathNodes = expr.getChildren("Identifier");
|
|
@@ -1247,40 +1252,43 @@ var init_analyze = __esm({
|
|
|
1247
1252
|
});
|
|
1248
1253
|
|
|
1249
1254
|
// ../lang/parser.terms.js
|
|
1250
|
-
var table, primary_key, join, as, on, or, and, like, not, _in, from, inner, left, right, full, cross, select, where, group, by, order, asc, desc, limit, offset, is, _null, exists, _true, _false;
|
|
1255
|
+
var table, date, timestamp, interval, primary_key, join, as, on, or, and, like, not, _in, from, inner, left, right, full, cross, select, where, group, by, order, asc, desc, limit, offset, is, _null, exists, _true, _false;
|
|
1251
1256
|
var init_parser_terms = __esm({
|
|
1252
1257
|
"../lang/parser.terms.js"() {
|
|
1253
1258
|
"use strict";
|
|
1254
1259
|
table = 5;
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1260
|
+
date = 10;
|
|
1261
|
+
timestamp = 12;
|
|
1262
|
+
interval = 14;
|
|
1263
|
+
primary_key = 18;
|
|
1264
|
+
join = 22;
|
|
1265
|
+
as = 28;
|
|
1266
|
+
on = 31;
|
|
1267
|
+
or = 40;
|
|
1268
|
+
and = 44;
|
|
1269
|
+
like = 53;
|
|
1270
|
+
not = 55;
|
|
1271
|
+
_in = 65;
|
|
1272
|
+
from = 70;
|
|
1273
|
+
inner = 76;
|
|
1274
|
+
left = 78;
|
|
1275
|
+
right = 80;
|
|
1276
|
+
full = 82;
|
|
1277
|
+
cross = 84;
|
|
1278
|
+
select = 87;
|
|
1279
|
+
where = 94;
|
|
1280
|
+
group = 97;
|
|
1281
|
+
by = 99;
|
|
1282
|
+
order = 105;
|
|
1283
|
+
asc = 109;
|
|
1284
|
+
desc = 111;
|
|
1285
|
+
limit = 114;
|
|
1286
|
+
offset = 116;
|
|
1287
|
+
is = 119;
|
|
1288
|
+
_null = 121;
|
|
1289
|
+
exists = 139;
|
|
1290
|
+
_true = 143;
|
|
1291
|
+
_false = 145;
|
|
1284
1292
|
}
|
|
1285
1293
|
});
|
|
1286
1294
|
|
|
@@ -1324,7 +1332,10 @@ var init_tokens = __esm({
|
|
|
1324
1332
|
offset,
|
|
1325
1333
|
table,
|
|
1326
1334
|
exists,
|
|
1327
|
-
primary_key
|
|
1335
|
+
primary_key,
|
|
1336
|
+
interval,
|
|
1337
|
+
date,
|
|
1338
|
+
timestamp
|
|
1328
1339
|
};
|
|
1329
1340
|
}
|
|
1330
1341
|
});
|
|
@@ -1336,24 +1347,24 @@ var init_parser = __esm({
|
|
|
1336
1347
|
"../lang/parser.js"() {
|
|
1337
1348
|
"use strict";
|
|
1338
1349
|
init_tokens();
|
|
1339
|
-
spec_Identifier = { __proto__: null, table: 10, primary_key:
|
|
1350
|
+
spec_Identifier = { __proto__: null, table: 10, date: 20, timestamp: 24, interval: 28, primary_key: 36, join: 44, one: 48, many: 52, as: 56, on: 62, or: 80, and: 88, like: 106, not: 110, in: 130, from: 140, inner: 152, left: 156, right: 160, full: 164, cross: 168, select: 174, distinct: 178, where: 188, group: 194, by: 198, having: 204, order: 210, asc: 218, desc: 222, limit: 228, offset: 232, is: 238, null: 242, case: 252, when: 258, then: 262, else: 268, end: 272, exists: 278, true: 286, false: 290, count: 300, extract: 306, cast: 314, extend: 340 };
|
|
1340
1351
|
parser = LRParser.deserialize({
|
|
1341
1352
|
version: 14,
|
|
1342
|
-
states: "
|
|
1343
|
-
stateData: "
|
|
1344
|
-
goto: "
|
|
1345
|
-
nodeNames: "\u26A0 Program TableStatement Kw Identifier table Ref ColumnDef DataType PrimaryKey Kw primary_key JoinDef JoinType Kw join Kw one Kw many Kw as Alias Kw on BinaryExpression = ComputedDef TypeCastExpression :: CastType BinaryExpression Kw or TypeCastExpression BinaryExpression Kw and ComparisonOp != <> < > <= >= Kw like Kw not AddOp + - MulOp * / % InExpression Kw in InValueList QueryStatement FromClause Kw from TableName Subquery SubqueryExpression JoinClause Kw inner Kw left Kw right Kw full Kw cross SelectClause Kw select Kw distinct SelectItem Wildcard WhereClause Kw where GroupByClause Kw group Kw by HavingClause Kw having OrderByClause Kw order OrderItem Number Kw asc Kw desc LimitClause Kw limit Kw offset NullTestExpression Kw is Kw null UnaryExpression UnaryOperator CaseExpression Kw case WhenClause Kw when Kw then ElseClause Kw else Kw end ExistsExpression Kw exists String Boolean Kw true Kw false Null FunctionCall Count Kw count ExtractExpression Kw extract ExtractUnit CastExpression Kw cast Param Parenthetical InExpression NullTestExpression : ViewStatement ExtendStatement Kw extend",
|
|
1346
|
-
maxTerm:
|
|
1353
|
+
states: "KOQYQPOOOOQO'#C_'#C_OOQO'#Ds'#DsOwQPO'#DrOOQO'#EU'#EUO#aQPO'#ETOOQO'#E]'#E]OOQO'#E`'#E`O#hQPO'#E_OOQO'#Ee'#EeOOQO'#Eh'#EhO#hQPO'#EgOOQO'#Eq'#EqO#mQPO'#EpOOQO'#GR'#GRO$ZQPO'#DqO$hQPO'#C^OOQO'#F{'#F{O$hQPO'#FzO$mQPO'#F}QYQPOOQ%bQPO'#F}O%gQPO'#E[O%gQPO'#EdO)^QPO'#CbO)hQPO'#CbO)mQPO'#DuO#rQPO'#DwO*zQPO'#DvOOQO'#Gc'#GcO,mQPO,5:^O-aQPO'#CbO.sQPO'#CbOOQO'#Ce'#CeOOQO'#Cg'#CgOOQO'#Ci'#CiO0]QPO'#EYOOQO'#Dd'#DdO1VQPO'#DwOOQO'#EW'#EWOOQO'#EZ'#EZOOQO'#EY'#EYO1pQPO,5:oO!PQPO,5:oOOQO'#Ex'#ExOOQO'#E{'#E{OOQO'#E}'#E}O2eQPO'#E|OOQO'#F['#F[O2lQPO'#FZOOQO'#F`'#F`OOQO'#Fb'#FbOOQO'#F_'#F_OOQO'#Fd'#FdOOQO'#Gg'#GgOOQO'#Fg'#FgO2qQPO'#FfOOQO'#Gf'#GfOOQO'#Fj'#FjOOQO'#Fn'#FnO2vQPO'#FpO3OQPO'#FrO3TQPO'#FsOOQO'#Ge'#GeOOQO'#Gh'#GhOOQO'#Ga'#GaO%gQPO'#EzO3YQPO'#FiO3_QPO'#FmOOQO'#Eb'#EbO!PQPO,5:yO3dQPO,5;RO3lQPO,5;[OOQO-E:P-E:PO4aQPO,58xO4iQPO,5<fOOQO,5<i,5<iOOQO-E9{-E9{O4nQPO,5:vO5bQPO,5;OOOQO,5<j,5<jO6UQPO,58|OOQO-E9|-E9|OOQO'#Cw'#CwOOQO'#Cy'#CyOOQO,5:a,5:aO:PQPO,5:aO:UQPO,5:cOOQO,5:b,5:bO:PQPO,5:bOOQO'#Cq'#CqOOQO'#Dy'#DyOOQO'#D{'#D{OOQO'#D}'#D}OOQO'#EP'#EPOOQO'#ER'#EROwQPO'#DxO:ZQPO'#DxOOQO'#GS'#GSO:`QPO1G/xO;SQPO,5<POOQO,5:u,5:uOOQO'#DT'#DTO;ZQPO,59qOOQO'#DX'#DXOOQO'#Db'#DbOOQO'#DZ'#DZO;iQPO,5:XOOQO'#Df'#DfOOQO'#Di'#DiOOQO'#Dn'#DnO;qQPO,5:XOOQO'#Ev'#EvO;vQPO,5;aO%gQPO,59rO%gQPO,59rO%gQPO,59rO%gQPO,59rO%gQPO,59rOOQO,5:t,5:tO:PQPO,5:tO<OQPO,5<aO<VQPO1G0ZO<yQPO1G0ZO<yQPO1G0ZO=nQPO,5;hOOQO'#FQ'#FQOOQO'#GV'#GVO=uQPO,5;hO%gQPO'#FPO#rQPO,5;uO>QQPO,5<QOOQO,5<[,5<[O>_QPO,5<[OOQO,5<^,5<^OOQO,5<_,5<_O>dQPO,5;fOBUQPO,5<TO%gQPO,5<XOB^QPO1G0eOCRQPO'#EjOC|QPO1G0mOOQO'#Es'#EsODqQPO1G0vODvQPO1G.dOFTQPO1G2POFYQPO1G2QPGgQPO'#GOOOQO1G/{1G/{OOQO1G/}1G/}OOQO1G/|1G/|OGlQPO,5:dOwQPO,5:dOOQO-E:Q-E:QOHsQPO1G1kOOQO1G1k1G1kOOQO'#DR'#DROOQO1G/]1G/]OOQO,59u,59uOH}QPO1G/sO1VQPO1G/sOOQO1G0{1G0{O;yQPO1G0{OLqQPO1G/^OLxQPO1G/^O!!kQPO1G/^O!!uQPO1G/^O!#PQPO1G/^OOQO1G0`1G0`OOQO1G1{1G1{OOQO,5<o,5<oO!&qQPO7+%uOOQO-E:R-E:RO!'eQPO7+%uO=uQPO1G1SOOQO-E:T-E:TOOQO'#FV'#FVOOQO'#FX'#FXOOQO1G1S1G1SO={QPO1G1SO%gQPO'#FUO!(YQPO,5;kO!(aQPO1G1aO!(fQPO1G1lOOQO1G1l1G1lO!(mQPO1G1lO%gQPO1G1lOOQO'#Fq'#FqOOQO1G1v1G1vOOQO'#Fl'#FlO!(rQPO1G1oO.{QPO1G1sO!(wQPO7+&PO!)kQPO7+&POOQO'#El'#ElOOQO'#En'#EnOOQO,5;U,5;UO!+QQPO7+&XO!+[QPO7+&XOOQO7+&b7+&bO!,|QPO'#CbO!-^QPO'#CdO!-oQPO'#CdO!.QQPO'#CdO!.fQPO'#CcO!.tQPO'#CpO$hQPO'#CoO!0WQPO'#DOOOQO'#G`'#G`OOQO'#G_'#G_O!0bQPO'#GPO!1uQPO7+$OO!1|QPO'#DOO#rQPO7+'kO!+cQPO'#CbOOQO'#Gj'#GjO!2RQPO'#GWO!3fQPO7+'lOOQO'#Cz'#CzO%gQPO1G0OO!3mQPO1G0OO!4tQPO7+'VO!4|QPO7+'VOOQO7+'V7+'VO1VQPO7+%_O!5TQPO'#DpO!5_QPO7+%_OOQO7+&g7+&gP!PQPO'#GTO!5dQPO<<IaOOQO7+&n7+&nO={QPO7+&nO!6WQPO,5;pOOQO'#FS'#FSO%gQPO1G1VOOQO7+&{7+&{OOQO7+'W7+'WO!6_QPO7+'WO%gQPO7+'ZO;ZQPO7+'_O!6fQPO<<IkOOQO,5<p,5<pO!7YQPO<<IsOOQO-E:S-E:SOOQO'#Ck'#CkO!8QQPO,58}OOQO'#Cs'#CsOOQO'#Cu'#CuOOQO,59[,59[O!9hQPO,59ZO;ZQPO,59kO;iQPO,5<bO!9pQPO,5<bO;vQPO,5<cO%gQPO,59nO%gQPO,59nO%gQPO,59nO%gQPO,59nO%gQPO,59nO:PQPO,59jOOQO,5<k,5<kOOQO-E9}-E9}OOQO<<Gj<<GjO%gQPO,59jO!9uQPO<<KVOOQO,5<r,5<rOOQO-E:U-E:UOOQO<<KW<<KWO!9zQPO7+%jO%gQPO7+%jOOQO-E:O-E:OO!;QQPO<<JqOOQO<<Jq<<JqO!;XQPO,5<lO!;cQPO<<HyO!;hQPO,5:[O!;pQPO,5:[OOQO<<Hy<<HyOOQO<<JY<<JYO!;wQPO7+&qOOQO<<Jr<<JrO!<UQPO<<JuO!<]QPO<<JyP3dQPO'#GUOOQO'#Cm'#CmOOQO'#Cl'#ClOOQO1G.i1G.iO$hQPO1G.uO:PQPO1G.uOOQO1G/V1G/VO!<bQPO1G1|O1VQPO1G1|OOQO1G1}1G1}O;yQPO1G1}O!=tQPO1G/YO!={QPO1G/YO!?^QPO1G/YO!?hQPO1G/YO!?rQPO1G/YOOQO1G/U1G/UO!ASQPO1G/UOOQOAN@qAN@qO!B`QPO<<IUP%gQPO'#GQOOQOAN@]AN@]OOQOAN>eAN>eO!CfQPO1G/vOOQOAN@aAN@aOOQOAN@eAN@eO!CmQPO'#C|OOQO7+$a7+$aO!9kQPO7+$aO1VQPO7+'hO!CrQPO7+'hOOQO7+'i7+'iO$hQPO,59hO$hQPO<<G{O!CwQPO<<KSOOQO<<KS<<KSOOQO1G/S1G/SOOQOAN=gAN=gOOQOAN@nAN@n",
|
|
1354
|
+
stateData: "!DT~O$}OS%OOS~OTPO!hQO!ySO#QUO#TVO#YXO#]YO#f[O$paO~OShO%QkO~OSoOYqO[rO^sO!XuO!Z}O![}O!^xO#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO%QvO~O!{wO~P!PO#V!gO~O#_!jO~O!hQO!ySO#QUO#TVO#YXO#]YO#f[O~O${!eX%]!eX%W!eX~P#rOShO~O%]!nOT$qX!h$qX!y$qX#Q$qX#T$qX#Y$qX#]$qX#f$qX$p$qX${$qX~O%]!nO~OSoOYqO[rO^sO!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO%QvO~O%P!rOSUXfUXlUX!hUX!nUX!pUX!rUX!tUX!vUX!yUX#QUX#TUX#YUX#]UX#fUX${UX%]UX%WUXqUXYUX[UX^UX!XUX!ZUX![UX#_UX#mUX#rUX$PUX$QUX$TUX$VUX$[UX$_UX$cUX$hUX%UUX~O%QUXoUX~P&tOS!sO~OS!vOl!uOf!iX!h!iX!n!iX!p!iX!r!iX!t!iX!v!iX!y!iX#Q!iX#T!iX#Y!iX#]!iX#f!iX${!iX%]!iX%W!iXo!iX~OS!vOl!uOf!jX!h!jX!n!jX!p!jX!r!jX!t!jX!v!jX!y!jX#Q!jX#T!jX#Y!jX#]!jX#f!jX${!jX%]!jX%W!jXo!jX~Of!|O!n!}O!p#OO!r#PO!t#QO!v#RO~O!h!fa!y!fa#Q!fa#T!fa#Y!fa#]!fa#f!fa${!fa%]!fa%W!fa~P,XO%Q#WOtUXxUX|UX!OUX!PUX!QUX!RUX!SUX!TUX!VUX!^UX!_UX!`UX!cUX#kUX#uUX#wUX#|UX#zUX~P&tOS!sO!^#XO~Ol!uOq#^Ot#ZOx#YO|#[O!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dO~OS!vO!h!|X!y!|X#Q!|X#T!|X#Y!|X#]!|X#f!|X${!|X%U!|X%]!|X%W!|X~P.{O!hQO!ySO#QUO#TVO#YXO#]YO#f[O~P%gO%U#nO!h!wa!y!wa#Q!wa#T!wa#Y!wa#]!wa#f!wa${!wa%]!wa%W!wa~O#u#rO~P%gO%Q#vO~O%Q#wO~O#_#yO$Q#xO~O$Q#zO~O$Q#{O~O%Q#}O~O%Q$OO~OS$QO#_$QO~O#h$SO!h#da!y#da#Q#da#T#da#Y#da#]#da#f#da${#da%]#da%W#da~Ol!uO%Q$UO~O%Q$WO~O!h#Oa!y#Oa#Q#Oa#T#Oa#Y#Oa#]#Oa#f#Oa${#Oa%]#Oa%W#Oa~P/OO!h#Wa!y#Wa#Q#Wa#T#Wa#Y#Wa#]#Wa#f#Wa${#Wa%]#Wa%W#Wa~P/OO%P!rOSUafUalUa!hUa!nUa!pUa!rUa!tUa!vUa!yUa#QUa#TUa#YUa#]Ua#fUa${Ua%]UaqUatUaxUa|Ua!OUa!PUa!QUa!RUa!SUa!TUa!VUa!XUa!ZUa![Ua!^Ua!_Ua!`Ua!cUa#kUa%UUa%QUa%WUa#uUaoUa#wUa#|Ua#zUaYUa[Ua^Ua#_Ua#mUa#rUa$PUa$QUa$TUa$VUa$[Ua$_Ua$cUa$hUa~OS!vO~O%W$ZO~Of!|O~O!h!fi!y!fi#Q!fi#T!fi#Y!fi#]!fi#f!fi${!fi%]!fi%W!fi~P,XO%W$aO~P%gOS$bOYqO[rO^sO~O!V#]O!c#bO~O%Q$fO~O!XuO#m|O~O%W$oO~P/OO!h!wi!y!wi#Q!wi#T!wi#Y!wi#]!wi#f!wi${!wi%]!wi%W!wi~P!PO%U$qO!h!wi!y!wi#Q!wi#T!wi#Y!wi#]!wi#f!wi${!wi%]!wi%W!wi~O#u#rO~P/OO#u#rO#z$vO#|$wO~O!^%PO!{wO%W%OO~P%gOS%RO~Ot#ZOS#nal#naq#nax#na|#na!O#na!P#na!Q#na!R#na!S#na!T#na!V#na!X#na!Z#na![#na!^#na!_#na!`#na!c#na!h#na!y#na#Q#na#T#na#Y#na#]#na#f#na#k#na${#na%U#na%]#na%W#na#u#na#w#na#|#naf#na!n#na!p#na!r#na!t#na!v#na#z#naY#na[#na^#na#_#na#m#na#r#na$P#na$Q#na$T#na$V#na$[#na$_#na$c#na$h#na~OS%TO$Q%TO~O%U%WO!h#Ri!y#Ri#Q#Ri#T#Ri#Y#Ri#]#Ri#f#Ri${#Ri%]#Ri%W#Ri~O#a%YO#c%ZO!h#^X!y#^X#Q#^X#T#^X#Y#^X#]#^X#f#^X${#^X%U#^X%]#^X%W#^X~O%U%]O!h#Zi!y#Zi#Q#Zi#T#Zi#Y#Zi#]#Zi#f#Zi${#Zi%]#Zi%W#Zi~O#_%_O~OS%`OYqO[rO^sOf!|O!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO~O%Q%mO~OS%nOYqO[rO^sOf!|O!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO~O%P!rO~Oo%rOf!la!h!la!n!la!p!la!r!la!t!la!v!la!y!la#Q!la#T!la#Y!la#]!la#f!la${!la%]!la%W!la~O%U%vO%W%wO~P/OO%Q%xO~Oq#^Ot#ZO!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dOSzilzixzi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O|#[O~PISO|zi~PISOt#ZO!^#aO!_#aO!`#aOSzilziqzixzi|zi!Ozi!Pzi!Qzi!Rzi!Szi!Tzi!Vzi!Xzi!czi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi#kzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O!Z#`O![#`O~PMPO!Zzi![zi~PMPOt#ZOSzilziqzixzi|zi!Ozi!Pzi!Qzi!Rzi!Szi!Tzi!Vzi!Xzi!Zzi![zi!^zi!_zi!`zi!czi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi#kzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O!h!wq!y!wq#Q!wq#T!wq#Y!wq#]!wq#f!wq${!wq%]!wq%W!wq~P!PO%U%}O!h!wq!y!wq#Q!wq#T!wq#Y!wq#]!wq#f!wq${!wq%]!wq%W!wq~O#w&RO~P/OO%W&TO~O%W&UO~P/OO%W&UO~O!hQO~O!h#Rq!y#Rq#Q#Rq#T#Rq#Y#Rq#]#Rq#f#Rq${#Rq%]#Rq%W#Rq~P!PO%U&YO!h#Rq!y#Rq#Q#Rq#T#Rq#Y#Rq#]#Rq#f#Rq${#Rq%]#Rq%W#Rq~O!h#Zq!y#Zq#Q#Zq#T#Zq#Y#Zq#]#Zq#f#Zq${#Zq%]#Zq%W#Zq~OS$QO#_$QO~P!*`O%U&[O~P!*`O%P!rO%Q#WOlUXqUXtUXxUX|UX!OUX!PUX!QUX!RUX!SUX!TUX!VUX!XUX!ZUX![UX!^UX!_UX!`UX!cUX#kUX$lmX~OSWXYWX[WX^WX~P!+cO$Q#zOSWXYWX[WX^WX~O$Q#{OSWXYWX[WX^WX~O#_#yO$Q#xOSWXYWX[WX^WX~OS&^OYqO[rO^sO~Oh&`Oj&aO~Oq#^Ox#YO|#[O!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dO~Ol!uOt&dO~P!.|O%U&nOS$sXY$sX[$sX^$sXf$sX!X$sX!Z$sX![$sX#_$sX#m$sX#r$sX$P$sX$Q$sX$T$sX$V$sX$[$sX$_$sX$c$sX$h$sX%W$sX~O%W&pO~PDvO$l&qO~O%U&sOS$zXY$zX[$zX^$zXf$zX!X$zX!Z$zX![$zX#_$zX#m$zX#r$zX$P$zX$Q$zX$T$zX$V$zX$[$zX$_$zX$c$zX$h$zX%W$zX~O%W&uO~PFYOo%rOf!li!h!li!n!li!p!li!r!li!t!li!v!li!y!li#Q!li#T!li#Y!li#]!li#f!li${!li%]!li%W!li~O%U&yO%W&zO~O%W&zO~P%gO%U'OO%W!dX~P/OO%W'PO~O!h!wy!y!wy#Q!wy#T!wy#Y!wy#]!wy#f!wy${!wy%]!wy%W!wy~P!PO#|#xa~P/OO%W'SO~P/OO!h#Ry!y#Ry#Q#Ry#T#Ry#Y#Ry#]#Ry#f#Ry${#Ry%]#Ry%W#Ry~P!POS$QO#_$QO!h#Zy!y#Zy#Q#Zy#T#Zy#Y#Zy#]#Zy#f#Zy${#Zy%]#Zy%W#Zy~Ob'WOSVaYVa[Va^VafVa!XVa!ZVa![Va#_Va#mVa#rVa$PVa$QVa$TVa$VVa$[Va$_Va$cVa$hVa%UVa%WVa~Ol!uOo%rO~O%Q'_O~O%W'iO~Of!lq!h!lq!n!lq!p!lq!r!lq!t!lq!v!lq!y!lq#Q!lq#T!lq#Y!lq#]!lq#f!lq${!lq%]!lq%W!lq~P/OO%W'lO~P%gO%U$ta%W$ta~P/OO%W'mO~O%U'nO%W!da~O%W!da~P%gO#u#sq#z#sq#|#sq~P/OO%W'oO~P/OO%W'pO~O%Q'tO~Oq#^Ot#ZO!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dOlvixvi~O|#[O~P!<gO|vi~P!<gOt#ZO!^#aO!_#aO!`#aOlviqvixvi|vi!Ovi!Pvi!Qvi!Rvi!Svi!Tvi!Vvi!Xvi!cvi#kvi~O!Z#`O![#`O~P!>SO!Zvi![vi~P!>SOt#ZOlviqvixvi|vi!Ovi!Pvi!Qvi!Rvi!Svi!Tvi!Vvi!Xvi!Zvi![vi!^vi!_vi!`vi!cvi#kvi~OSriYri[ri^rifri#_ri#mri#rri$Pri$Qri$Tri$Vri$[ri$_ri$cri$hri%Uri%Wri~P/OOf!ly!h!ly!n!ly!p!ly!r!ly!t!ly!v!ly!y!ly#Q!ly#T!ly#Y!ly#]!ly#f!ly${!ly%]!ly%W!ly~P/OO%W!di~P%gOq'wO~O%W'zO~O%W'}O~O%O![t$l!^!_~",
|
|
1355
|
+
goto: "! b%_PP%`%dPP%h'R'V'ZP(iP)wP+V+Y+]P+`+h+nP+{P+{P,OP,e-TP-aP+`-gP-m-g-vP._._/_P/xPPPPPP0eP1SP2yPP3hPPP._4XP4z5W5r6PP6a6a6f7k7oP7oP7oP7oP7oP5r7sP8QP8W8i5r8tP5r9RP9`P5r9fP5r9sP:QP:YP:YP5r:]P:jP._:mP;YP<j=n<j>rP?v?|P@SP@V@]P@aP<j@kPPAoBsPBsPAoCwCwD{P<jFPPGT<jGWP<jH[<j<jP6k-g-gP%`%`H_PHcHiI|JSJ^JmJsKRKXKcPPPPPPKiKmKsPM}PNW<jCw._P! ^TcOdT`OdUjR#S$^#S!ZTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tQ!l`Q!mbQ&c%fS'q'Z'xR'{'wT%i$U%kT%d$U%k#O!_Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%a$U%kR&^%d#O!`Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%b$U%kR&^%d#O!^Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%c$U%kR&^%dR&_%dR'Y&_R'X&_S%i$U%kT%o$W%qX%f$U$W%k%qS#Sn#VQ$^#TX%e$U$W%k%qR&b%eQ!xjQ!{lQ#ltQ$V!lQ&X%VQ&m%gR'[&cQ!wjQ!zlQ#ktQ$Y!xQ$[!{Q$n#lW%l$U$W%k%qQ'g&mR's'[Q%s$]Q&w%tQ'Z&cR'x'sQ'r'ZR'|'xX%h$U$W%k%qQ$c#ZQ'U&XR']&dt#ft!p!q#m#q$`${$}%V%y&Q&V&v&{'R'T'h'jR&h%g!{!cTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tx#gt!p!q#m#q$`$i${$}%V%y&Q&V&v&{'R'T'b'h'jR&i%g|#ht!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jR&j%g!O#^t!p!q#m#q$`$i$j${$}%V%g%y&Q&V&v&{'R'T'b'c'h'jT$d#_&e#S}Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't|#_t!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jQ$h#eQ&e%gR'a&g!Q#it!p!q#m#q$`$i$j$k${$}%V%y&Q&V&v&{'R'T'b'c'd'h'jR&k%g!U#jt!p!q#m#q$`$i$j$k$l${$}%V%y&Q&V&v&{'R'T'b'c'd'e'h'jR&l%g|#ct!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jQ$e#_Q&f%gR'^&eQ%z$fQ&|%xQ'u'_R'y'tSeOdS!ykvQ$|#vQ%z$fQ&r%mQ&|%xQ'u'_R'y'tg^O_dkv#v$f%m%x'_'tfRO_dkv#v$f%m%x'_'tR&W%UVmR#S$^UlR#S$^!{!bTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tT#Un#VT#Tn#VgTO_dkv#v$f%m%x'_'tQ{TR%Q#wQzTQ#p{Q$P!h]$p#n$q%W%|%}&YcyT{!h#n$q%W%|%}&YgfO_dkv#v$f%m%x'_'tgWO_dkv#v$f%m%x'_'tQ!hWR!iZggO_dkv#v$f%m%x'_'tgZO_dkv#v$f%m%x'_'tQ$R!iV&Z%]&['VR%[$Qg]O_dkv#v$f%m%x'_'tR$T!j|#et!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jR&g%g#S!VTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tQ$g#eQ%{$hQ'`&gR'v'a#T!aTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!dTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!PTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tX#s!P#q#t$tX#u!P#q#t$tR&S${Q$y#tR&P$tT$z#t$tQ$x#tS&O$t$yR'Q&P#T!RTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!WTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!UTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!ZTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!YTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!eTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tR%U#}#T!fTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tR%S#yTbOdQdOR!od#SiR`bfgv!P!d#S#W#f#g#h#i#j#u#w$O$U$W$^$f$z%Q%f%k%q%s%v%x&S&W&h&i&j&k&l&q&w&y'O'Z'_'k'n't'w'xbpT{!h#n$q%W%|%}&YT!tipQ%k$UR&o%kQ%u$`S&x%u&}R&}%yd_Odkv#v$f%m%x'_'tR!k_Q#VnR$_#VQ#ozU$r#o$s%XQ$s#pR%X$PQ%^$RR&]%^Q#t!PQ$t#qT$u#t$tQ%q$WR&t%qT%j$U%kX%g$U$W%k%qbtT{!h#n$q%W%|%}&YQ!pfQ!qgQ#mvQ#q!PQ#|!dQ$`#WQ$i#fQ$j#gQ$k#hQ$l#iQ$m#jQ${#uQ$}#wQ%V$OW%y$f%x'_'tQ&Q$zQ&V%QQ&v%sY&{%v&y'O'k'nQ'R&SQ'T&WQ'b&hQ'c&iQ'd&jQ'e&kQ'f&lQ'h&qR'j&wQnRQ$]#SR%t$^!z!cTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tX%h$U$W%k%qT%p$W%q",
|
|
1356
|
+
nodeNames: "\u26A0 Program TableStatement Kw Identifier table Ref ColumnDef ColumnName Kw date Kw timestamp Kw interval DataType PrimaryKey Kw primary_key JoinDef JoinType Kw join Kw one Kw many Kw as Alias Kw on BinaryExpression = ComputedDef TypeCastExpression :: CastType BinaryExpression Kw or TypeCastExpression BinaryExpression Kw and ComparisonOp != <> < > <= >= Kw like Kw not AddOp + - MulOp * / % InExpression Kw in InValueList QueryStatement FromClause Kw from TableName Subquery SubqueryExpression JoinClause Kw inner Kw left Kw right Kw full Kw cross SelectClause Kw select Kw distinct SelectItem Wildcard WhereClause Kw where GroupByClause Kw group Kw by HavingClause Kw having OrderByClause Kw order OrderItem Number Kw asc Kw desc LimitClause Kw limit Kw offset NullTestExpression Kw is Kw null UnaryExpression UnaryOperator CaseExpression Kw case WhenClause Kw when Kw then ElseClause Kw else Kw end ExistsExpression Kw exists String Boolean Kw true Kw false Null FunctionCall Count Kw count ExtractExpression Kw extract ExtractUnit CastExpression Kw cast IntervalExpression IntervalUnit DateExpression TimestampExpression Param Parenthetical InExpression NullTestExpression : ViewStatement ExtendStatement Kw extend",
|
|
1357
|
+
maxTerm: 198,
|
|
1347
1358
|
nodeProps: [
|
|
1348
|
-
["group", -
|
|
1359
|
+
["group", -16, 6, 107, 122, 124, 137, 140, 141, 146, 147, 148, 151, 155, 158, 160, 161, 162, "Expression Expression", -11, 32, 35, 38, 41, 42, 63, 73, 117, 163, 164, 165, "Expression", -2, 71, 72, "TablePrimary"]
|
|
1349
1360
|
],
|
|
1350
1361
|
skippedNodes: [0],
|
|
1351
1362
|
repeatNodeCount: 10,
|
|
1352
|
-
tokenData: "*w~RoX^#Spq#Sqr#wrs$Stu$quv%cwx%hxy&Qyz&Vz{&[{|&a|}&f}!O&k!O!P'[!P!Q'a!Q![(p![!])Z!]!^)h!^!_)m!_!`*S!`!a*X!c!}*f#T#o*f#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#XY$
|
|
1363
|
+
tokenData: "*w~RoX^#Spq#Sqr#wrs$Stu$quv%cwx%hxy&Qyz&Vz{&[{|&a|}&f}!O&k!O!P'[!P!Q'a!Q![(p![!])Z!]!^)h!^!_)m!_!`*S!`!a*X!c!}*f#T#o*f#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#XY$}~X^#Spq#S#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#zP!_!`#}~$SO!O~~$VTOr$Srs$fs;'S$S;'S;=`$k<%lO$S~$kO$Q~~$nP;=`<%l$S~$tS!Q![%Q!c!}%Q#R#S%Q#T#o%Q~%VS$h~!Q![%Q!c!}%Q#R#S%Q#T#o%Q~%hO!`~~%kTOw%hwx$fx;'S%h;'S;=`%z<%lO%h~%}P;=`<%l%h~&VO%Q~~&[O%W~~&aO!^~~&fO!Z~~&kO%U~~&pP![~}!O&s~&xS%O~OY&sZ;'S&s;'S;=`'U<%lO&s~'XP;=`<%l&s~'aO%P~~'fP!_~z{'i~'lTOz'iz{'{{;'S'i;'S;=`(j<%lO'i~(OVOz'iz{'{{!P'i!P!Q(e!Q;'S'i;'S;=`(j<%lO'i~(jO%O~~(mP;=`<%l'i~(uQ#_~!O!P({!Q![(p~)OP!Q![)R~)WP#_~!Q![)R~)`P$l~![!])c~)hOt~~)mO%]~~)rQ!Q~!_!`)x!`!a)}~)}O!S~~*SO!P~~*XOq~~*^P!R~!_!`*a~*fO!T~~*kSS~!Q![*f!c!}*f#R#S*f#T#o*f",
|
|
1353
1364
|
tokenizers: [0],
|
|
1354
1365
|
topRules: { "Program": [0, 1] },
|
|
1355
1366
|
specialized: [{ term: 4, get: (value, stack) => specializeIdentifier(value, stack) << 1, external: specializeIdentifier }, { term: 4, get: (value) => spec_Identifier[value] || -1 }],
|
|
1356
|
-
tokenPrec:
|
|
1367
|
+
tokenPrec: 3724
|
|
1357
1368
|
});
|
|
1358
1369
|
}
|
|
1359
1370
|
});
|
|
@@ -2206,8 +2217,8 @@ __export(bigQuery_exports, {
|
|
|
2206
2217
|
});
|
|
2207
2218
|
import { BigQuery, BigQueryDate, BigQueryTimestamp } from "@google-cloud/bigquery";
|
|
2208
2219
|
import { readFileSync as readFileSync3 } from "fs";
|
|
2209
|
-
function
|
|
2210
|
-
|
|
2220
|
+
function validateBigQueryIdent(ident) {
|
|
2221
|
+
if (!/^[\w.-]+$/.test(ident)) throw new Error(`Invalid BigQuery identifier: ${ident}`);
|
|
2211
2222
|
}
|
|
2212
2223
|
var BigQueryConnection;
|
|
2213
2224
|
var init_bigQuery = __esm({
|
|
@@ -2234,8 +2245,8 @@ var init_bigQuery = __esm({
|
|
|
2234
2245
|
this.client = new BigQuery({ ...options, userAgent: "Graphene" });
|
|
2235
2246
|
this.defaultNamespace = config.namespace;
|
|
2236
2247
|
}
|
|
2237
|
-
async runQuery(sql) {
|
|
2238
|
-
let [job] = await this.client.createQueryJob({ query: sql, useLegacySql: false });
|
|
2248
|
+
async runQuery(sql, params) {
|
|
2249
|
+
let [job] = await this.client.createQueryJob({ query: sql, useLegacySql: false, params });
|
|
2239
2250
|
let [rows] = await job.getQueryResults({ maxResults: 1e4 });
|
|
2240
2251
|
let metadata = job.metadata || (await job.getMetadata())[0];
|
|
2241
2252
|
let totalRows = Number(metadata?.statistics?.query?.totalRows ?? rows.length);
|
|
@@ -2253,6 +2264,7 @@ var init_bigQuery = __esm({
|
|
|
2253
2264
|
}
|
|
2254
2265
|
async listTables(dataset) {
|
|
2255
2266
|
if (!dataset) throw new Error("BigQuery requires a dataset");
|
|
2267
|
+
validateBigQueryIdent(dataset);
|
|
2256
2268
|
let res = await this.runQuery(`select table_schema as table_schema, table_name as table_name
|
|
2257
2269
|
from \`${dataset}.INFORMATION_SCHEMA.TABLES\`
|
|
2258
2270
|
where table_type in ('BASE TABLE', 'VIEW') order by table_name`);
|
|
@@ -2262,13 +2274,14 @@ var init_bigQuery = __esm({
|
|
|
2262
2274
|
let parts = target.split(".");
|
|
2263
2275
|
let table2 = parts.pop() || "";
|
|
2264
2276
|
let dataset = parts.join(".");
|
|
2277
|
+
validateBigQueryIdent(dataset);
|
|
2265
2278
|
let sql = `
|
|
2266
2279
|
select column_name as column_name, data_type as data_type, ordinal_position as ordinal_position
|
|
2267
2280
|
from \`${dataset}.INFORMATION_SCHEMA.COLUMNS\`
|
|
2268
|
-
where lower(table_name) = lower(
|
|
2281
|
+
where lower(table_name) = lower(@table)
|
|
2269
2282
|
order by ordinal_position
|
|
2270
2283
|
`.trim();
|
|
2271
|
-
let res = await this.runQuery(sql);
|
|
2284
|
+
let res = await this.runQuery(sql, { table: table2 });
|
|
2272
2285
|
return res.rows.map((row) => {
|
|
2273
2286
|
return { name: String(row["column_name"]), dataType: String(row["data_type"]) };
|
|
2274
2287
|
});
|
|
@@ -2285,9 +2298,6 @@ __export(duckdb_exports, {
|
|
|
2285
2298
|
import { promises as fs5 } from "fs";
|
|
2286
2299
|
import path6 from "path";
|
|
2287
2300
|
import { DuckDBTimestampValue, DuckDBInstance, DuckDBDateValue } from "@duckdb/node-api";
|
|
2288
|
-
function sqlStringLiteral2(value) {
|
|
2289
|
-
return `'${value.replace(/'/g, "''")}'`;
|
|
2290
|
-
}
|
|
2291
2301
|
var DuckDBConnection;
|
|
2292
2302
|
var init_duckdb = __esm({
|
|
2293
2303
|
"connections/duckdb.ts"() {
|
|
@@ -2315,9 +2325,9 @@ var init_duckdb = __esm({
|
|
|
2315
2325
|
await this.connection.run(`attach '${escapedPath}' as graphene_cli (READ_ONLY);`);
|
|
2316
2326
|
await this.connection.run("use graphene_cli;");
|
|
2317
2327
|
}
|
|
2318
|
-
async runQuery(sql) {
|
|
2328
|
+
async runQuery(sql, params) {
|
|
2319
2329
|
await this.ready;
|
|
2320
|
-
let reader = await this.connection.runAndReadAll(sql);
|
|
2330
|
+
let reader = params ? await this.connection.runAndReadAll(sql, params) : await this.connection.runAndReadAll(sql);
|
|
2321
2331
|
let rows = reader.getRowObjects().map((record) => {
|
|
2322
2332
|
let out = {};
|
|
2323
2333
|
for (let [k, v] of Object.entries(record)) {
|
|
@@ -2349,14 +2359,15 @@ var init_duckdb = __esm({
|
|
|
2349
2359
|
let parts = target.split(".");
|
|
2350
2360
|
let table2 = parts.pop() || "";
|
|
2351
2361
|
let schema = parts[0];
|
|
2352
|
-
let schemaFilter = schema ?
|
|
2362
|
+
let schemaFilter = schema ? "lower(table_schema) = lower($2)" : "table_schema not in ('information_schema', 'pg_catalog')";
|
|
2353
2363
|
let sql = `
|
|
2354
2364
|
select column_name as column_name, data_type as data_type, ordinal_position as ordinal_position
|
|
2355
2365
|
from information_schema.columns
|
|
2356
|
-
where lower(table_name) = lower($
|
|
2366
|
+
where lower(table_name) = lower($1) and ${schemaFilter}
|
|
2357
2367
|
order by ordinal_position
|
|
2358
2368
|
`.trim();
|
|
2359
|
-
let
|
|
2369
|
+
let params = schema ? [table2, schema] : [table2];
|
|
2370
|
+
let res = await this.runQuery(sql, params);
|
|
2360
2371
|
return res.rows.map((row) => {
|
|
2361
2372
|
return { name: String(row["column_name"]), dataType: String(row["data_type"]) };
|
|
2362
2373
|
});
|
|
@@ -2376,9 +2387,6 @@ function snowflakeIdent(value) {
|
|
|
2376
2387
|
if (!value) throw new Error("Snowflake identifiers cannot be empty");
|
|
2377
2388
|
return `"${value.replace(/"/g, '""')}"`;
|
|
2378
2389
|
}
|
|
2379
|
-
function sqlStringLiteral3(value) {
|
|
2380
|
-
return `'${value.replace(/'/g, "''")}'`;
|
|
2381
|
-
}
|
|
2382
2390
|
var SnowflakeConnection;
|
|
2383
2391
|
var init_snowflake2 = __esm({
|
|
2384
2392
|
"connections/snowflake.ts"() {
|
|
@@ -2412,12 +2420,13 @@ var init_snowflake2 = __esm({
|
|
|
2412
2420
|
this.connection.connect((err, conn) => err ? reject(err) : resolve(conn));
|
|
2413
2421
|
});
|
|
2414
2422
|
}
|
|
2415
|
-
async runQuery(sql) {
|
|
2423
|
+
async runQuery(sql, params) {
|
|
2416
2424
|
await this.ready;
|
|
2417
2425
|
return await new Promise((resolve, reject) => {
|
|
2418
2426
|
let rows = [];
|
|
2419
2427
|
this.connection.execute({
|
|
2420
2428
|
sqlText: sql,
|
|
2429
|
+
binds: params,
|
|
2421
2430
|
streamResult: true,
|
|
2422
2431
|
complete: (error, statement) => {
|
|
2423
2432
|
if (error) {
|
|
@@ -2450,9 +2459,9 @@ var init_snowflake2 = __esm({
|
|
|
2450
2459
|
let res = await this.runQuery(`
|
|
2451
2460
|
select table_schema as "table_schema", table_name as "table_name"
|
|
2452
2461
|
from ${snowflakeIdent(database)}.INFORMATION_SCHEMA.TABLES
|
|
2453
|
-
where table_type in ('BASE TABLE', 'VIEW') and table_schema =
|
|
2462
|
+
where table_type in ('BASE TABLE', 'VIEW') and table_schema = ?
|
|
2454
2463
|
order by table_name
|
|
2455
|
-
|
|
2464
|
+
`, [schema]);
|
|
2456
2465
|
return res.rows.map((row) => `${row["table_schema"]}.${row["table_name"]}`);
|
|
2457
2466
|
}
|
|
2458
2467
|
async describeTable(target) {
|
|
@@ -2463,9 +2472,9 @@ var init_snowflake2 = __esm({
|
|
|
2463
2472
|
let res = await this.runQuery(`
|
|
2464
2473
|
select column_name as "column_name", data_type as "data_type", ordinal_position as ordinal_position
|
|
2465
2474
|
from ${snowflakeIdent(database)}.INFORMATION_SCHEMA.COLUMNS
|
|
2466
|
-
where upper(table_schema) = upper(
|
|
2475
|
+
where upper(table_schema) = upper(?) and upper(table_name) = upper(?)
|
|
2467
2476
|
order by ordinal_position
|
|
2468
|
-
|
|
2477
|
+
`, [schema, table2]);
|
|
2469
2478
|
return res.rows.map((row) => {
|
|
2470
2479
|
return { name: String(row["column_name"]).toLowerCase(), dataType: String(row["data_type"]) };
|
|
2471
2480
|
});
|
|
@@ -2489,17 +2498,17 @@ async function getConnection() {
|
|
|
2489
2498
|
throw new Error(`Unsupported dialect: ${config.dialect}`);
|
|
2490
2499
|
}
|
|
2491
2500
|
}
|
|
2492
|
-
async function runQuery(sql) {
|
|
2501
|
+
async function runQuery(sql, params) {
|
|
2493
2502
|
if (config.host) {
|
|
2494
2503
|
let resp = await authenticatedFetch("/_api/query", {
|
|
2495
2504
|
method: "POST",
|
|
2496
2505
|
headers: { "Content-Type": "application/json" },
|
|
2497
|
-
body: JSON.stringify({ sql })
|
|
2506
|
+
body: JSON.stringify({ sql, params })
|
|
2498
2507
|
});
|
|
2499
2508
|
return await resp.json();
|
|
2500
2509
|
}
|
|
2501
2510
|
let conn = await getConnection();
|
|
2502
|
-
return await conn.runQuery(sql);
|
|
2511
|
+
return await conn.runQuery(sql, params);
|
|
2503
2512
|
}
|
|
2504
2513
|
var init_connections = __esm({
|
|
2505
2514
|
"connections/index.ts"() {
|
|
@@ -2838,10 +2847,14 @@ init_auth();
|
|
|
2838
2847
|
import { Command } from "commander";
|
|
2839
2848
|
import fs8 from "fs-extra";
|
|
2840
2849
|
import path9 from "path";
|
|
2850
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2841
2851
|
import dotenv from "dotenv";
|
|
2842
2852
|
dotenv.config({ quiet: true });
|
|
2843
2853
|
var program = new Command();
|
|
2844
|
-
|
|
2854
|
+
var __dirname = path9.dirname(fileURLToPath3(import.meta.url));
|
|
2855
|
+
var pkgPath = fs8.existsSync(path9.join(__dirname, "package.json")) ? path9.join(__dirname, "package.json") : path9.join(__dirname, "../../package.json");
|
|
2856
|
+
var pkg = fs8.readJsonSync(pkgPath);
|
|
2857
|
+
program.name("graphene").description("Graphene CLI").version(pkg.version, "-v, --version");
|
|
2845
2858
|
program.hook("preAction", async () => {
|
|
2846
2859
|
if (process.env.CLI_DELAY) {
|
|
2847
2860
|
await new Promise((r) => setTimeout(r, 1e3));
|