@sqg/sqg 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sqg.mjs
CHANGED
|
@@ -67,14 +67,16 @@ SQL Annotation Syntax:
|
|
|
67
67
|
-- EXEC <name> Execute statement (INSERT/UPDATE/DELETE)
|
|
68
68
|
-- MIGRATE <number> Schema migration (run in order)
|
|
69
69
|
-- TESTDATA <name> Test data setup (not generated)
|
|
70
|
+
-- TABLE <name> :appender Table for bulk insert appender (DuckDB only)
|
|
70
71
|
|
|
71
72
|
@set <varName> = <value> Define a variable
|
|
72
73
|
\${varName} Reference a variable in SQL
|
|
73
74
|
|
|
74
75
|
Modifiers:
|
|
75
|
-
:one
|
|
76
|
-
:pluck
|
|
77
|
-
:all
|
|
76
|
+
:one Return single row (or null) instead of array
|
|
77
|
+
:pluck Return single column value (requires exactly 1 column)
|
|
78
|
+
:all Return all rows (default)
|
|
79
|
+
:appender Generate bulk insert appender for TABLE annotation
|
|
78
80
|
|
|
79
81
|
Example:
|
|
80
82
|
-- MIGRATE 1
|
|
@@ -83,6 +85,8 @@ Example:
|
|
|
83
85
|
-- QUERY get_user :one
|
|
84
86
|
@set id = 1
|
|
85
87
|
SELECT * FROM users WHERE id = \${id};
|
|
88
|
+
|
|
89
|
+
-- TABLE users :appender
|
|
86
90
|
`.trim();
|
|
87
91
|
/**
|
|
88
92
|
* Find similar generator names for typo suggestions
|
|
@@ -280,21 +284,21 @@ function formatErrorForOutput(err) {
|
|
|
280
284
|
//#region src/parser/sql-parser.ts
|
|
281
285
|
const parser = LRParser.deserialize({
|
|
282
286
|
version: 14,
|
|
283
|
-
states: "&SOVQPOOO_QPO'#CwOdQPO'#CzOiQPO'#
|
|
284
|
-
stateData: "
|
|
287
|
+
states: "&SOVQPOOO_QPO'#CwOdQPO'#CzOiQPO'#CvO!SQQO'#C^OOQO'#Cn'#CnQVQPOOO!aQSO,59cO!lQPO,59fOOQO'#Cp'#CpO!tQQO,59bOOQO'#C}'#C}O#iQQO'#CiOOQO,58x,58xOOQO-E6l-E6lOOQO'#Co'#CoO!aQSO1G.}O!dQSO1G.}OOQO'#Cb'#CbOOQO1G.}1G.}O#yQPO1G/QOOQO-E6n-E6nO$RQPO'#CdOOQO'#Cq'#CqO$WQQO1G.|OOQO'#Cm'#CmOOQO'#Cr'#CrO$xQQO,59TOOQO-E6m-E6mO!dQSO7+$iOOQO7+$i7+$iO%YQPO,59OOOQO-E6o-E6oOOQO-E6p-E6pOOQO<<HT<<HTO%_QQO1G.jOOQO'#Ce'#CeOiQPO7+$UO%jQQO<<Gp",
|
|
288
|
+
stateData: "&l~OiOS~ORPOVQO~OSVO~OSWO~OlXO~OYZOZZO[ZO^ZO_ZO`ZO~OR]PV]Pg]P~PnOT_OlXOmbO~OT_Olna~OlXOofORjaVjaYjaZja[ja^ja_ja`jagja~OliOR]XV]Xg]X~PnOT_Olni~OSoO~OofORjiVjiYjiZji[ji^ji_ji`jigji~OliOR]aV]ag]a~PnOpsO~OYtOZtO[tO~OlXORWyVWyYWyZWy[Wy^Wy_Wy`WygWyoWy~OR`o^iZTmYV_[~",
|
|
285
289
|
goto: "#prPPsPPPwP!R!VPPP!YPPP!]!a!g!q#T#ZPPP#a#ePP#ePP#iTTOUQcVSn`aRrmTgYhRusR]STj[kQUOR^UQ`VQdWTl`dQYRQaVWeYamvQm`RvuQhYRphQk[RqkTSOUTROUQ[STj[k",
|
|
286
290
|
nodeNames: "⚠ File QueryBlock BlockCommentStartSpecial Name Modifiers Config LineCommentStartSpecial SetVarLine Value StringLiteral StringLiteralSingle SQLText SQLBlock BlockComment LineComment VarRef BR",
|
|
287
291
|
maxTerm: 33,
|
|
288
292
|
skippedNodes: [0],
|
|
289
293
|
repeatNodeCount: 5,
|
|
290
|
-
tokenData: "$+x~RqOX#YXY'wYZ(iZ]#Y]^$W^p#Ypq'wqr#Yrs(}st#Ytu6^uw#Ywx9[xz#Yz{%_{}#Y}!OKi!O!P#Y!P!Q# n!Q![$!S![!]$#l!]!_#Y!_!`$&l!`!b#Y!b!c$'l!c!}$!S!}#R#Y#R#S$!S#S#T#Y#T#o$!S#o;'S#Y;'S;=`'q<%lO#YU#_][QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YS$ZTOz$Wz{$j{;'S$W;'S;=`%X<%lO$WS$mVOz$Wz{$j{!P$W!P!Q%S!Q;'S$W;'S;=`%X<%lO$WS%XOmSS%[P;=`<%l$WU%d_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!P#Y!P!Q&c!Q;'S#Y;'S;=`'q<%lO#YU&jVmS[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ'UV[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ'nP;=`<%l'PU'tP;=`<%l#Y~'|Xi~OX$WXY'wYp$Wpq'wqz$Wz{$j{;'S$W;'S;=`%X<%lO$W~(nTl~Oz$Wz{$j{;'S$W;'S;=`%X<%lO$WU)Sb[QOX(}XY*[YZ$WZ](}]^*[^p(}pq*[qr(}rs.yst(}tu*[uz(}z{/y{#O(}#O#P5V#P;'S(};'S;=`6W<%lO(}U*_ZOY*[YZ$WZr*[rs+Qsz*[z{+f{#O*[#O#P.Z#P;'S*[;'S;=`.s<%lO*[U+VTYQOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU+i]OY*[YZ$WZr*[rs+Qsz*[z{+f{!P*[!P!Q,b!Q#O*[#O#P.Z#P;'S*[;'S;=`.s<%lO*[U,gWmSOY-PZr-Prs-ls#O-P#O#P-q#P;'S-P;'S;=`.T<%lO-PQ-SWOY-PZr-Prs-ls#O-P#O#P-q#P;'S-P;'S;=`.T<%lO-PQ-qOYQQ-tTOY-PYZ-PZ;'S-P;'S;=`.T<%lO-PQ.WP;=`<%l-PU.^VOY*[YZ*[Zz*[z{+f{;'S*[;'S;=`.s<%lO*[U.vP;=`<%l*[U/Q]YQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YU0Od[QOX(}XY*[YZ$WZ](}]^*[^p(}pq*[qr(}rs.yst(}tu*[uz(}z{/y{!P(}!P!Q1^!Q#O(}#O#P5V#P;'S(};'S;=`6W<%lO(}U1e_mS[QOX2dXY-PZ]2d]^-P^p2dpq-Pqr2drs3hst2dtu-Pu#O2d#O#P4U#P;'S2d;'S;=`5P<%lO2dQ2i_[QOX2dXY-PZ]2d]^-P^p2dpq-Pqr2drs3hst2dtu-Pu#O2d#O#P4U#P;'S2d;'S;=`5P<%lO2dQ3oVYQ[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ4Z[[QOX2dXY-PYZ-PZ]2d]^-P^p2dpq-Pqt2dtu-Pu;'S2d;'S;=`5P<%lO2dQ5SP;=`<%l2dU5[^[QOX(}XY*[YZ*[Z](}]^*[^p(}pq*[qt(}tu*[uz(}z{/y{;'S(};'S;=`6W<%lO(}U6ZP;=`<%l(}U6cV[QOz$Wz{$j{#o$W#o#p6x#p;'S$W;'S;=`%X<%lO$WU6{]Oz$Wz{$j{!Q$W!Q![7t![!c$W!c!}7t!}#R$W#R#S7t#S#T$W#T#o7t#o;'S$W;'S;=`%X<%lO$WU7w_Oz$Wz{$j{!Q$W!Q![7t![!c$W!c!}7t!}#R$W#R#S7t#S#T$W#T#o7t#o#q$W#q#r8v#r;'S$W;'S;=`%X<%lO$WU8{T`QOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU9ab[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[U:lZOY:iYZ$WZw:iwx;_xz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU;dTZQOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU;v]OY:iYZ$WZw:iwx;_xz:iz{;s{!P:i!P!Q<o!Q#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU<tWmSOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q=aWOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q>OOZQQ>RXOY=^YZ=^Zw=^wx>nx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q>sWZQOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q?`P;=`<%l=^U?fZOY:iYZ:iZw:iwx@Xxz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU@^ZZQOY:iYZ$WZw:iwx;_xz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iUASP;=`<%l:iUA^]ZQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YUB[d[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{!P9[!P!QCj!Q#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UCq_mS[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQDu_[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQE{VZQ[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQFg`[QOXDpXY=^YZ=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxGix#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQGp_ZQ[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQHrP;=`<%lDpUHzb[QOX9[XY:iYZ:iZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxJSxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UJZbZQ[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UKfP;=`<%l9[VKn_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{}#Y}!OLm!O;'S#Y;'S;=`'q<%lO#YVLtf_Q[QOXNYXY!&vYZ$WZ]NY]^! ]^pNYpq!&vqtNYtu! ]uzNYz{!#k{!gNY!g!h!6m!h!oNY!o!p!;_!p!sNY!s!t!Bg!t!vNY!v!w!G]!w;'SNY;'S;=`!&p<%lONYUNa^_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{;'SNY;'S;=`!&p<%lONYU! bV_QOY! ]YZ$WZz! ]z{! w{;'S! ];'S;=`!#e<%lO! ]U! |X_QOY! ]YZ$WZz! ]z{! w{!P! ]!P!Q!!i!Q;'S! ];'S;=`!#e<%lO! ]U!!pSmS_QOY!!|Z;'S!!|;'S;=`!#_<%lO!!|Q!#RS_QOY!!|Z;'S!!|;'S;=`!#_<%lO!!|Q!#bP;=`<%l!!|U!#hP;=`<%l! ]U!#r`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!PNY!P!Q!$t!Q;'SNY;'S;=`!&p<%lONYU!$}ZmS_Q[QOX!%pXY!!|Z]!%p]^!!|^p!%ppq!!|qt!%ptu!!|u;'S!%p;'S;=`!&j<%lO!%pQ!%wZ_Q[QOX!%pXY!!|Z]!%p]^!!|^p!%ppq!!|qt!%ptu!!|u;'S!%p;'S;=`!&j<%lO!%pQ!&mP;=`<%l!%pU!&sP;=`<%lNYV!&{b_QOX! ]XY!&vYZ$WZp! ]pq!&vqz! ]z{! w{!g! ]!g!h!(T!h!o! ]!o!p!*u!p!s! ]!s!t!.}!t!v! ]!v!w!1s!w;'S! ];'S;=`!#e<%lO! ]V!(YX_QOY! ]YZ$WZz! ]z{! w{!z! ]!z!{!(u!{;'S! ];'S;=`!#e<%lO! ]V!(zX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!)g!h;'S! ];'S;=`!#e<%lO! ]V!)lX_QOY! ]YZ$WZz! ]z{! w{!e! ]!e!f!*X!f;'S! ];'S;=`!#e<%lO! ]V!*`VVR_QOY! ]YZ$WZz! ]z{! w{;'S! ];'S;=`!#e<%lO! ]V!*zX_QOY! ]YZ$WZz! ]z{! w{!k! ]!k!l!+g!l;'S! ];'S;=`!#e<%lO! ]V!+lX_QOY! ]YZ$WZz! ]z{! w{!i! ]!i!j!,X!j;'S! ];'S;=`!#e<%lO! ]V!,^X_QOY! ]YZ$WZz! ]z{! w{!t! ]!t!u!,y!u;'S! ];'S;=`!#e<%lO! ]V!-OX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!-k!d;'S! ];'S;=`!#e<%lO! ]V!-pX_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!.]!w;'S! ];'S;=`!#e<%lO! ]V!.bX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!*X!h;'S! ];'S;=`!#e<%lO! ]V!/SX_QOY! ]YZ$WZz! ]z{! w{!w! ]!w!x!/o!x;'S! ];'S;=`!#e<%lO! ]V!/tX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!0a!h;'S! ];'S;=`!#e<%lO! ]V!0fX_QOY! ]YZ$WZz! ]z{! w{!t! ]!t!u!1R!u;'S! ];'S;=`!#e<%lO! ]V!1WX_QOY! ]YZ$WZz! ]z{! w{!{! ]!{!|!*X!|;'S! ];'S;=`!#e<%lO! ]V!1xX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!2e!h;'S! ];'S;=`!#e<%lO! ]V!2jX_QOY! ]YZ$WZz! ]z{! w{!u! ]!u!v!3V!v;'S! ];'S;=`!#e<%lO! ]V!3[X_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!3w!w;'S! ];'S;=`!#e<%lO! ]V!3|X_QOY! ]YZ$WZz! ]z{! w{!f! ]!f!g!4i!g;'S! ];'S;=`!#e<%lO! ]V!4nX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!5Z!d;'S! ];'S;=`!#e<%lO! ]V!5`X_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!5{!w;'S! ];'S;=`!#e<%lO! ]V!6QX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!*X!d;'S! ];'S;=`!#e<%lO! ]V!6t`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!zNY!z!{!7v!{;'SNY;'S;=`!&p<%lONYV!7}`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!9P!h;'SNY;'S;=`!&p<%lONYV!9W`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!eNY!e!f!:Y!f;'SNY;'S;=`!&p<%lONYV!:c^VR_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{;'SNY;'S;=`!&p<%lONYV!;f`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!kNY!k!l!<h!l;'SNY;'S;=`!&p<%lONYV!<o`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!iNY!i!j!=q!j;'SNY;'S;=`!&p<%lONYV!=x`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!tNY!t!u!>z!u;'SNY;'S;=`!&p<%lONYV!?R`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!@T!d;'SNY;'S;=`!&p<%lONYV!@[`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w!A^!w;'SNY;'S;=`!&p<%lONYV!Ae`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!:Y!h;'SNY;'S;=`!&p<%lONYV!Bn`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!wNY!w!x!Cp!x;'SNY;'S;=`!&p<%lONYV!Cw`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!Dy!h;'SNY;'S;=`!&p<%lONYV!EQ`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!tNY!t!u!FS!u;'SNY;'S;=`!&p<%lONYV!FZ`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!{NY!{!|!:Y!|;'SNY;'S;=`!&p<%lONYV!Gd`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!Hf!h;'SNY;'S;=`!&p<%lONYV!Hm`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!uNY!u!v!Io!v;'SNY;'S;=`!&p<%lONYV!Iv`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w!Jx!w;'SNY;'S;=`!&p<%lONYV!KP`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!fNY!f!g!LR!g;'SNY;'S;=`!&p<%lONYV!LY`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!M[!d;'SNY;'S;=`!&p<%lONYV!Mc`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w!Ne!w;'SNY;'S;=`!&p<%lONYV!Nl`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!:Y!d;'SNY;'S;=`!&p<%lONYV# s][QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{#!l{;'S#Y;'S;=`'q<%lO#YV#!qh[QOX#$]XY#(^YZ#(^Z]#$]]^#%Z^p#$]pq#(^qt#$]tu#%Zuz#$]z{#&d{!P#$]!P!Q#4c!Q!g#$]!g!h#9`!h!o#$]!o!p#=l!p!s#$]!s!t#DU!t!v#$]!v!w#Hf!w;'S#$];'S;=`#(W<%lO#$]U#$b][QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{;'S#$];'S;=`#(W<%lO#$]U#%^TOz#%Zz{#%m{;'S#%Z;'S;=`#&^<%lO#%ZU#%pVOz#%Zz{#%m{!P#%Z!P!Q#&V!Q;'S#%Z;'S;=`#&^<%lO#%ZU#&^O^QmSU#&aP;=`<%l#%ZU#&i_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!P#$]!P!Q#'h!Q;'S#$];'S;=`#(W<%lO#$]U#'qV^QmS[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PU#(ZP;=`<%l#$]V#(abOX#%ZXY#(^YZ#(^Zp#%Zpq#(^qz#%Zz{#%m{!g#%Z!g!h#)i!h!o#%Z!o!p#+i!p!s#%Z!s!t#.o!t!v#%Z!v!w#0s!w;'S#%Z;'S;=`#&^<%lO#%ZV#)lVOz#%Zz{#%m{!z#%Z!z!{#*R!{;'S#%Z;'S;=`#&^<%lO#%ZV#*UVOz#%Zz{#%m{!g#%Z!g!h#*k!h;'S#%Z;'S;=`#&^<%lO#%ZV#*nVOz#%Zz{#%m{!e#%Z!e!f#+T!f;'S#%Z;'S;=`#&^<%lO#%ZV#+YTRROz#%Zz{#%m{;'S#%Z;'S;=`#&^<%lO#%ZV#+lVOz#%Zz{#%m{!k#%Z!k!l#,R!l;'S#%Z;'S;=`#&^<%lO#%ZV#,UVOz#%Zz{#%m{!i#%Z!i!j#,k!j;'S#%Z;'S;=`#&^<%lO#%ZV#,nVOz#%Zz{#%m{!t#%Z!t!u#-T!u;'S#%Z;'S;=`#&^<%lO#%ZV#-WVOz#%Zz{#%m{!c#%Z!c!d#-m!d;'S#%Z;'S;=`#&^<%lO#%ZV#-pVOz#%Zz{#%m{!v#%Z!v!w#.V!w;'S#%Z;'S;=`#&^<%lO#%ZV#.YVOz#%Zz{#%m{!g#%Z!g!h#+T!h;'S#%Z;'S;=`#&^<%lO#%ZV#.rVOz#%Zz{#%m{!w#%Z!w!x#/X!x;'S#%Z;'S;=`#&^<%lO#%ZV#/[VOz#%Zz{#%m{!g#%Z!g!h#/q!h;'S#%Z;'S;=`#&^<%lO#%ZV#/tVOz#%Zz{#%m{!t#%Z!t!u#0Z!u;'S#%Z;'S;=`#&^<%lO#%ZV#0^VOz#%Zz{#%m{!{#%Z!{!|#+T!|;'S#%Z;'S;=`#&^<%lO#%ZV#0vVOz#%Zz{#%m{!g#%Z!g!h#1]!h;'S#%Z;'S;=`#&^<%lO#%ZV#1`VOz#%Zz{#%m{!u#%Z!u!v#1u!v;'S#%Z;'S;=`#&^<%lO#%ZV#1xVOz#%Zz{#%m{!v#%Z!v!w#2_!w;'S#%Z;'S;=`#&^<%lO#%ZV#2bVOz#%Zz{#%m{!f#%Z!f!g#2w!g;'S#%Z;'S;=`#&^<%lO#%ZV#2zVOz#%Zz{#%m{!c#%Z!c!d#3a!d;'S#%Z;'S;=`#&^<%lO#%ZV#3dVOz#%Zz{#%m{!v#%Z!v!w#3y!w;'S#%Z;'S;=`#&^<%lO#%ZV#3|VOz#%Zz{#%m{!c#%Z!c!d#+T!d;'S#%Z;'S;=`#&^<%lO#%ZU#4j]mS[QOX#5cXZ#6aZ]#5c]^#6a^p#5cpq#6aqt#5ctu#6auz#5cz{#7h{;'S#5c;'S;=`#9Y<%lO#5cQ#5h][QOX#5cXZ#6aZ]#5c]^#6a^p#5cpq#6aqt#5ctu#6auz#5cz{#7h{;'S#5c;'S;=`#9Y<%lO#5cQ#6dTOz#6az{#6s{;'S#6a;'S;=`#7b<%lO#6aQ#6vVOz#6az{#6s{!P#6a!P!Q#7]!Q;'S#6a;'S;=`#7b<%lO#6aQ#7bO^QQ#7eP;=`<%l#6aQ#7m_[QOX#5cXZ#6aZ]#5c]^#6a^p#5cpq#6aqt#5ctu#6auz#5cz{#7h{!P#5c!P!Q#8l!Q;'S#5c;'S;=`#9Y<%lO#5cQ#8sV^Q[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ#9]P;=`<%l#5cV#9e_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!z#$]!z!{#:d!{;'S#$];'S;=`#(W<%lO#$]V#:i_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!g#$]!g!h#;h!h;'S#$];'S;=`#(W<%lO#$]V#;m_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!e#$]!e!f#<l!f;'S#$];'S;=`#(W<%lO#$]V#<s]RR[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{;'S#$];'S;=`#(W<%lO#$]V#=q_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!k#$]!k!l#>p!l;'S#$];'S;=`#(W<%lO#$]V#>u_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!i#$]!i!j#?t!j;'S#$];'S;=`#(W<%lO#$]V#?y_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!t#$]!t!u#@x!u;'S#$];'S;=`#(W<%lO#$]V#@}_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!c#$]!c!d#A|!d;'S#$];'S;=`#(W<%lO#$]V#BR_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!v#$]!v!w#CQ!w;'S#$];'S;=`#(W<%lO#$]V#CV_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!g#$]!g!h#<l!h;'S#$];'S;=`#(W<%lO#$]V#DZ_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!w#$]!w!x#EY!x;'S#$];'S;=`#(W<%lO#$]V#E__[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!g#$]!g!h#F^!h;'S#$];'S;=`#(W<%lO#$]V#Fc_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!t#$]!t!u#Gb!u;'S#$];'S;=`#(W<%lO#$]V#Gg_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!{#$]!{!|#<l!|;'S#$];'S;=`#(W<%lO#$]V#Hk_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!g#$]!g!h#Ij!h;'S#$];'S;=`#(W<%lO#$]V#Io_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!u#$]!u!v#Jn!v;'S#$];'S;=`#(W<%lO#$]V#Js_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!v#$]!v!w#Kr!w;'S#$];'S;=`#(W<%lO#$]V#Kw_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!f#$]!f!g#Lv!g;'S#$];'S;=`#(W<%lO#$]V#L{_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!c#$]!c!d#Mz!d;'S#$];'S;=`#(W<%lO#$]V#NP_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!v#$]!v!w$ O!w;'S#$];'S;=`#(W<%lO#$]V$ T_[QOX#$]XZ#%ZZ]#$]]^#%Z^p#$]pq#%Zqt#$]tu#%Zuz#$]z{#&d{!c#$]!c!d#<l!d;'S#$];'S;=`#(W<%lO#$]V$!ZeSP[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$!S![!c#Y!c!}$!S!}#R#Y#R#S$!S#S#T#Y#T#o$!S#o;'S#Y;'S;=`'q<%lO#Y~$#qe[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$%S![!c#Y!c!}$%S!}#R#Y#R#S$%S#S#T#Y#T#o$%S#o;'S#Y;'S;=`'q<%lO#Y~$%ZeT~[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$%S![!c#Y!c!}$%S!}#R#Y#R#S$%S#S#T#Y#T#o$%S#o;'S#Y;'S;=`'q<%lO#YV$&s]pP[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YU$'q_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#g#Y#g#h$(p#h;'S#Y;'S;=`'q<%lO#YU$(u_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#X#Y#X#Y$)t#Y;'S#Y;'S;=`'q<%lO#YU$)y_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#h#Y#h#i$*x#i;'S#Y;'S;=`'q<%lO#YU$+P]oQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#Y",
|
|
294
|
+
tokenData: "$3b~RqOX#YXY'wYZ(iZ]#Y]^$W^p#Ypq'wqr#Yrs(}st#Ytu6^uw#Ywx9[xz#Yz{%_{}#Y}!OKi!O!P#Y!P!Q#%p!Q![$)l![!]$+U!]!_#Y!_!`$.U!`!b#Y!b!c$/U!c!}$)l!}#R#Y#R#S$)l#S#T#Y#T#o$)l#o;'S#Y;'S;=`'q<%lO#YU#_][QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YS$ZTOz$Wz{$j{;'S$W;'S;=`%X<%lO$WS$mVOz$Wz{$j{!P$W!P!Q%S!Q;'S$W;'S;=`%X<%lO$WS%XOmSS%[P;=`<%l$WU%d_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!P#Y!P!Q&c!Q;'S#Y;'S;=`'q<%lO#YU&jVmS[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ'UV[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ'nP;=`<%l'PU'tP;=`<%l#Y~'|Xi~OX$WXY'wYp$Wpq'wqz$Wz{$j{;'S$W;'S;=`%X<%lO$W~(nTl~Oz$Wz{$j{;'S$W;'S;=`%X<%lO$WU)Sb[QOX(}XY*[YZ$WZ](}]^*[^p(}pq*[qr(}rs.yst(}tu*[uz(}z{/y{#O(}#O#P5V#P;'S(};'S;=`6W<%lO(}U*_ZOY*[YZ$WZr*[rs+Qsz*[z{+f{#O*[#O#P.Z#P;'S*[;'S;=`.s<%lO*[U+VTYQOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU+i]OY*[YZ$WZr*[rs+Qsz*[z{+f{!P*[!P!Q,b!Q#O*[#O#P.Z#P;'S*[;'S;=`.s<%lO*[U,gWmSOY-PZr-Prs-ls#O-P#O#P-q#P;'S-P;'S;=`.T<%lO-PQ-SWOY-PZr-Prs-ls#O-P#O#P-q#P;'S-P;'S;=`.T<%lO-PQ-qOYQQ-tTOY-PYZ-PZ;'S-P;'S;=`.T<%lO-PQ.WP;=`<%l-PU.^VOY*[YZ*[Zz*[z{+f{;'S*[;'S;=`.s<%lO*[U.vP;=`<%l*[U/Q]YQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YU0Od[QOX(}XY*[YZ$WZ](}]^*[^p(}pq*[qr(}rs.yst(}tu*[uz(}z{/y{!P(}!P!Q1^!Q#O(}#O#P5V#P;'S(};'S;=`6W<%lO(}U1e_mS[QOX2dXY-PZ]2d]^-P^p2dpq-Pqr2drs3hst2dtu-Pu#O2d#O#P4U#P;'S2d;'S;=`5P<%lO2dQ2i_[QOX2dXY-PZ]2d]^-P^p2dpq-Pqr2drs3hst2dtu-Pu#O2d#O#P4U#P;'S2d;'S;=`5P<%lO2dQ3oVYQ[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ4Z[[QOX2dXY-PYZ-PZ]2d]^-P^p2dpq-Pqt2dtu-Pu;'S2d;'S;=`5P<%lO2dQ5SP;=`<%l2dU5[^[QOX(}XY*[YZ*[Z](}]^*[^p(}pq*[qt(}tu*[uz(}z{/y{;'S(};'S;=`6W<%lO(}U6ZP;=`<%l(}U6cV[QOz$Wz{$j{#o$W#o#p6x#p;'S$W;'S;=`%X<%lO$WU6{]Oz$Wz{$j{!Q$W!Q![7t![!c$W!c!}7t!}#R$W#R#S7t#S#T$W#T#o7t#o;'S$W;'S;=`%X<%lO$WU7w_Oz$Wz{$j{!Q$W!Q![7t![!c$W!c!}7t!}#R$W#R#S7t#S#T$W#T#o7t#o#q$W#q#r8v#r;'S$W;'S;=`%X<%lO$WU8{T`QOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU9ab[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[U:lZOY:iYZ$WZw:iwx;_xz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU;dTZQOz$Wz{$j{;'S$W;'S;=`%X<%lO$WU;v]OY:iYZ$WZw:iwx;_xz:iz{;s{!P:i!P!Q<o!Q#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU<tWmSOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q=aWOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q>OOZQQ>RXOY=^YZ=^Zw=^wx>nx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q>sWZQOY=^Zw=^wx=yx#O=^#O#P>O#P;'S=^;'S;=`?]<%lO=^Q?`P;=`<%l=^U?fZOY:iYZ:iZw:iwx@Xxz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iU@^ZZQOY:iYZ$WZw:iwx;_xz:iz{;s{#O:i#O#P?c#P;'S:i;'S;=`AP<%lO:iUASP;=`<%l:iUA^]ZQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YUB[d[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{!P9[!P!QCj!Q#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UCq_mS[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQDu_[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQE{VZQ[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQFg`[QOXDpXY=^YZ=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxGix#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQGp_ZQ[QOXDpXY=^Z]Dp]^=^^pDppq=^qtDptu=^uwDpwxEtx#ODp#O#PFb#P;'SDp;'S;=`Ho<%lODpQHrP;=`<%lDpUHzb[QOX9[XY:iYZ:iZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxJSxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UJZbZQ[QOX9[XY:iYZ$WZ]9[]^:i^p9[pq:iqt9[tu:iuw9[wxAVxz9[z{BV{#O9[#O#PHu#P;'S9[;'S;=`Kc<%lO9[UKfP;=`<%l9[VKn_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{}#Y}!OLm!O;'S#Y;'S;=`'q<%lO#YVLtf_Q[QOXNYXY!&vYZ$WZ]NY]^! ]^pNYpq!&vqtNYtu! ]uzNYz{!#k{!gNY!g!h!8V!h!oNY!o!p!<w!p!sNY!s!t!DP!t!vNY!v!w!Hu!w;'SNY;'S;=`!&p<%lONYUNa^_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{;'SNY;'S;=`!&p<%lONYU! bV_QOY! ]YZ$WZz! ]z{! w{;'S! ];'S;=`!#e<%lO! ]U! |X_QOY! ]YZ$WZz! ]z{! w{!P! ]!P!Q!!i!Q;'S! ];'S;=`!#e<%lO! ]U!!pSmS_QOY!!|Z;'S!!|;'S;=`!#_<%lO!!|Q!#RS_QOY!!|Z;'S!!|;'S;=`!#_<%lO!!|Q!#bP;=`<%l!!|U!#hP;=`<%l! ]U!#r`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!PNY!P!Q!$t!Q;'SNY;'S;=`!&p<%lONYU!$}ZmS_Q[QOX!%pXY!!|Z]!%p]^!!|^p!%ppq!!|qt!%ptu!!|u;'S!%p;'S;=`!&j<%lO!%pQ!%wZ_Q[QOX!%pXY!!|Z]!%p]^!!|^p!%ppq!!|qt!%ptu!!|u;'S!%p;'S;=`!&j<%lO!%pQ!&mP;=`<%l!%pU!&sP;=`<%lNYV!&{b_QOX! ]XY!&vYZ$WZp! ]pq!&vqz! ]z{! w{!g! ]!g!h!(T!h!o! ]!o!p!*u!p!s! ]!s!t!.}!t!v! ]!v!w!1s!w;'S! ];'S;=`!#e<%lO! ]V!(YX_QOY! ]YZ$WZz! ]z{! w{!z! ]!z!{!(u!{;'S! ];'S;=`!#e<%lO! ]V!(zX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!)g!h;'S! ];'S;=`!#e<%lO! ]V!)lX_QOY! ]YZ$WZz! ]z{! w{!e! ]!e!f!*X!f;'S! ];'S;=`!#e<%lO! ]V!*`VVR_QOY! ]YZ$WZz! ]z{! w{;'S! ];'S;=`!#e<%lO! ]V!*zX_QOY! ]YZ$WZz! ]z{! w{!k! ]!k!l!+g!l;'S! ];'S;=`!#e<%lO! ]V!+lX_QOY! ]YZ$WZz! ]z{! w{!i! ]!i!j!,X!j;'S! ];'S;=`!#e<%lO! ]V!,^X_QOY! ]YZ$WZz! ]z{! w{!t! ]!t!u!,y!u;'S! ];'S;=`!#e<%lO! ]V!-OX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!-k!d;'S! ];'S;=`!#e<%lO! ]V!-pX_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!.]!w;'S! ];'S;=`!#e<%lO! ]V!.bX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!*X!h;'S! ];'S;=`!#e<%lO! ]V!/SX_QOY! ]YZ$WZz! ]z{! w{!w! ]!w!x!/o!x;'S! ];'S;=`!#e<%lO! ]V!/tX_QOY! ]YZ$WZz! ]z{! w{!g! ]!g!h!0a!h;'S! ];'S;=`!#e<%lO! ]V!0fX_QOY! ]YZ$WZz! ]z{! w{!t! ]!t!u!1R!u;'S! ];'S;=`!#e<%lO! ]V!1WX_QOY! ]YZ$WZz! ]z{! w{!{! ]!{!|!*X!|;'S! ];'S;=`!#e<%lO! ]V!1xZ_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!2k!d!g! ]!g!h!3}!h;'S! ];'S;=`!#e<%lO! ]V!2pX_QOY! ]YZ$WZz! ]z{! w{!d! ]!d!e!3]!e;'S! ];'S;=`!#e<%lO! ]V!3bX_QOY! ]YZ$WZz! ]z{! w{!n! ]!n!o!.]!o;'S! ];'S;=`!#e<%lO! ]V!4SX_QOY! ]YZ$WZz! ]z{! w{!u! ]!u!v!4o!v;'S! ];'S;=`!#e<%lO! ]V!4tX_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!5a!w;'S! ];'S;=`!#e<%lO! ]V!5fX_QOY! ]YZ$WZz! ]z{! w{!f! ]!f!g!6R!g;'S! ];'S;=`!#e<%lO! ]V!6WX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!6s!d;'S! ];'S;=`!#e<%lO! ]V!6xX_QOY! ]YZ$WZz! ]z{! w{!v! ]!v!w!7e!w;'S! ];'S;=`!#e<%lO! ]V!7jX_QOY! ]YZ$WZz! ]z{! w{!c! ]!c!d!*X!d;'S! ];'S;=`!#e<%lO! ]V!8^`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!zNY!z!{!9`!{;'SNY;'S;=`!&p<%lONYV!9g`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!:i!h;'SNY;'S;=`!&p<%lONYV!:p`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!eNY!e!f!;r!f;'SNY;'S;=`!&p<%lONYV!;{^VR_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{;'SNY;'S;=`!&p<%lONYV!=O`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!kNY!k!l!>Q!l;'SNY;'S;=`!&p<%lONYV!>X`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!iNY!i!j!?Z!j;'SNY;'S;=`!&p<%lONYV!?b`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!tNY!t!u!@d!u;'SNY;'S;=`!&p<%lONYV!@k`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!Am!d;'SNY;'S;=`!&p<%lONYV!At`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w!Bv!w;'SNY;'S;=`!&p<%lONYV!B}`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!;r!h;'SNY;'S;=`!&p<%lONYV!DW`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!wNY!w!x!EY!x;'SNY;'S;=`!&p<%lONYV!Ea`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!gNY!g!h!Fc!h;'SNY;'S;=`!&p<%lONYV!Fj`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!tNY!t!u!Gl!u;'SNY;'S;=`!&p<%lONYV!Gs`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!{NY!{!|!;r!|;'SNY;'S;=`!&p<%lONYV!H|b_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!JU!d!gNY!g!h!Lh!h;'SNY;'S;=`!&p<%lONYV!J]`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!dNY!d!e!K_!e;'SNY;'S;=`!&p<%lONYV!Kf`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!nNY!n!o!Bv!o;'SNY;'S;=`!&p<%lONYV!Lo`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!uNY!u!v!Mq!v;'SNY;'S;=`!&p<%lONYV!Mx`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w!Nz!w;'SNY;'S;=`!&p<%lONYV# R`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!fNY!f!g#!T!g;'SNY;'S;=`!&p<%lONYV#![`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d##^!d;'SNY;'S;=`!&p<%lONYV##e`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!vNY!v!w#$g!w;'SNY;'S;=`!&p<%lONYV#$n`_Q[QOXNYXY! ]YZ$WZ]NY]^! ]^pNYpq! ]qtNYtu! ]uzNYz{!#k{!cNY!c!d!;r!d;'SNY;'S;=`!&p<%lONYV#%u][QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{#&n{;'S#Y;'S;=`'q<%lO#YV#&sh[QOX#(_XY#,`YZ#,`Z]#(_]^#)]^p#(_pq#,`qt#(_tu#)]uz#(_z{#*f{!P#(_!P!Q#9m!Q!g#(_!g!h#>j!h!o#(_!o!p#Bv!p!s#(_!s!t#I`!t!v#(_!v!w#Mp!w;'S#(_;'S;=`#,Y<%lO#(_U#(d][QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{;'S#(_;'S;=`#,Y<%lO#(_U#)`TOz#)]z{#)o{;'S#)];'S;=`#*`<%lO#)]U#)rVOz#)]z{#)o{!P#)]!P!Q#*X!Q;'S#)];'S;=`#*`<%lO#)]U#*`O^QmSU#*cP;=`<%l#)]U#*k_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!P#(_!P!Q#+j!Q;'S#(_;'S;=`#,Y<%lO#(_U#+sV^QmS[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PU#,]P;=`<%l#(_V#,cbOX#)]XY#,`YZ#,`Zp#)]pq#,`qz#)]z{#)o{!g#)]!g!h#-k!h!o#)]!o!p#/k!p!s#)]!s!t#2q!t!v#)]!v!w#4u!w;'S#)];'S;=`#*`<%lO#)]V#-nVOz#)]z{#)o{!z#)]!z!{#.T!{;'S#)];'S;=`#*`<%lO#)]V#.WVOz#)]z{#)o{!g#)]!g!h#.m!h;'S#)];'S;=`#*`<%lO#)]V#.pVOz#)]z{#)o{!e#)]!e!f#/V!f;'S#)];'S;=`#*`<%lO#)]V#/[TRROz#)]z{#)o{;'S#)];'S;=`#*`<%lO#)]V#/nVOz#)]z{#)o{!k#)]!k!l#0T!l;'S#)];'S;=`#*`<%lO#)]V#0WVOz#)]z{#)o{!i#)]!i!j#0m!j;'S#)];'S;=`#*`<%lO#)]V#0pVOz#)]z{#)o{!t#)]!t!u#1V!u;'S#)];'S;=`#*`<%lO#)]V#1YVOz#)]z{#)o{!c#)]!c!d#1o!d;'S#)];'S;=`#*`<%lO#)]V#1rVOz#)]z{#)o{!v#)]!v!w#2X!w;'S#)];'S;=`#*`<%lO#)]V#2[VOz#)]z{#)o{!g#)]!g!h#/V!h;'S#)];'S;=`#*`<%lO#)]V#2tVOz#)]z{#)o{!w#)]!w!x#3Z!x;'S#)];'S;=`#*`<%lO#)]V#3^VOz#)]z{#)o{!g#)]!g!h#3s!h;'S#)];'S;=`#*`<%lO#)]V#3vVOz#)]z{#)o{!t#)]!t!u#4]!u;'S#)];'S;=`#*`<%lO#)]V#4`VOz#)]z{#)o{!{#)]!{!|#/V!|;'S#)];'S;=`#*`<%lO#)]V#4xXOz#)]z{#)o{!c#)]!c!d#5e!d!g#)]!g!h#6g!h;'S#)];'S;=`#*`<%lO#)]V#5hVOz#)]z{#)o{!d#)]!d!e#5}!e;'S#)];'S;=`#*`<%lO#)]V#6QVOz#)]z{#)o{!n#)]!n!o#2X!o;'S#)];'S;=`#*`<%lO#)]V#6jVOz#)]z{#)o{!u#)]!u!v#7P!v;'S#)];'S;=`#*`<%lO#)]V#7SVOz#)]z{#)o{!v#)]!v!w#7i!w;'S#)];'S;=`#*`<%lO#)]V#7lVOz#)]z{#)o{!f#)]!f!g#8R!g;'S#)];'S;=`#*`<%lO#)]V#8UVOz#)]z{#)o{!c#)]!c!d#8k!d;'S#)];'S;=`#*`<%lO#)]V#8nVOz#)]z{#)o{!v#)]!v!w#9T!w;'S#)];'S;=`#*`<%lO#)]V#9WVOz#)]z{#)o{!c#)]!c!d#/V!d;'S#)];'S;=`#*`<%lO#)]U#9t]mS[QOX#:mXZ#;kZ]#:m]^#;k^p#:mpq#;kqt#:mtu#;kuz#:mz{#<r{;'S#:m;'S;=`#>d<%lO#:mQ#:r][QOX#:mXZ#;kZ]#:m]^#;k^p#:mpq#;kqt#:mtu#;kuz#:mz{#<r{;'S#:m;'S;=`#>d<%lO#:mQ#;nTOz#;kz{#;}{;'S#;k;'S;=`#<l<%lO#;kQ#<QVOz#;kz{#;}{!P#;k!P!Q#<g!Q;'S#;k;'S;=`#<l<%lO#;kQ#<lO^QQ#<oP;=`<%l#;kQ#<w_[QOX#:mXZ#;kZ]#:m]^#;k^p#:mpq#;kqt#:mtu#;kuz#:mz{#<r{!P#:m!P!Q#=v!Q;'S#:m;'S;=`#>d<%lO#:mQ#=}V^Q[QOX'PZ]'P^p'Pqt'Pu;'S'P;'S;=`'k<%lO'PQ#>gP;=`<%l#:mV#>o_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!z#(_!z!{#?n!{;'S#(_;'S;=`#,Y<%lO#(_V#?s_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!g#(_!g!h#@r!h;'S#(_;'S;=`#,Y<%lO#(_V#@w_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!e#(_!e!f#Av!f;'S#(_;'S;=`#,Y<%lO#(_V#A}]RR[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{;'S#(_;'S;=`#,Y<%lO#(_V#B{_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!k#(_!k!l#Cz!l;'S#(_;'S;=`#,Y<%lO#(_V#DP_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!i#(_!i!j#EO!j;'S#(_;'S;=`#,Y<%lO#(_V#ET_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!t#(_!t!u#FS!u;'S#(_;'S;=`#,Y<%lO#(_V#FX_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!c#(_!c!d#GW!d;'S#(_;'S;=`#,Y<%lO#(_V#G]_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!v#(_!v!w#H[!w;'S#(_;'S;=`#,Y<%lO#(_V#Ha_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!g#(_!g!h#Av!h;'S#(_;'S;=`#,Y<%lO#(_V#Ie_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!w#(_!w!x#Jd!x;'S#(_;'S;=`#,Y<%lO#(_V#Ji_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!g#(_!g!h#Kh!h;'S#(_;'S;=`#,Y<%lO#(_V#Km_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!t#(_!t!u#Ll!u;'S#(_;'S;=`#,Y<%lO#(_V#Lq_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!{#(_!{!|#Av!|;'S#(_;'S;=`#,Y<%lO#(_V#Mua[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!c#(_!c!d#Nz!d!g#(_!g!h$#S!h;'S#(_;'S;=`#,Y<%lO#(_V$ P_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!d#(_!d!e$!O!e;'S#(_;'S;=`#,Y<%lO#(_V$!T_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!n#(_!n!o#H[!o;'S#(_;'S;=`#,Y<%lO#(_V$#X_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!u#(_!u!v$$W!v;'S#(_;'S;=`#,Y<%lO#(_V$$]_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!v#(_!v!w$%[!w;'S#(_;'S;=`#,Y<%lO#(_V$%a_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!f#(_!f!g$&`!g;'S#(_;'S;=`#,Y<%lO#(_V$&e_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!c#(_!c!d$'d!d;'S#(_;'S;=`#,Y<%lO#(_V$'i_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!v#(_!v!w$(h!w;'S#(_;'S;=`#,Y<%lO#(_V$(m_[QOX#(_XZ#)]Z]#(_]^#)]^p#(_pq#)]qt#(_tu#)]uz#(_z{#*f{!c#(_!c!d#Av!d;'S#(_;'S;=`#,Y<%lO#(_V$)seSP[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$)l![!c#Y!c!}$)l!}#R#Y#R#S$)l#S#T#Y#T#o$)l#o;'S#Y;'S;=`'q<%lO#Y~$+Ze[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$,l![!c#Y!c!}$,l!}#R#Y#R#S$,l#S#T#Y#T#o$,l#o;'S#Y;'S;=`'q<%lO#Y~$,seT~[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{!Q#Y!Q![$,l![!c#Y!c!}$,l!}#R#Y#R#S$,l#S#T#Y#T#o$,l#o;'S#Y;'S;=`'q<%lO#YV$.]]pP[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#YU$/Z_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#g#Y#g#h$0Y#h;'S#Y;'S;=`'q<%lO#YU$0__[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#X#Y#X#Y$1^#Y;'S#Y;'S;=`'q<%lO#YU$1c_[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{#h#Y#h#i$2b#i;'S#Y;'S;=`'q<%lO#YU$2i]oQ[QOX#YXZ$WZ]#Y]^$W^p#Ypq$Wqt#Ytu$Wuz#Yz{%_{;'S#Y;'S;=`'q<%lO#Y",
|
|
291
295
|
tokenizers: [
|
|
292
296
|
0,
|
|
293
297
|
1,
|
|
294
298
|
2
|
|
295
299
|
],
|
|
296
300
|
topRules: { "File": [0, 1] },
|
|
297
|
-
tokenPrec:
|
|
301
|
+
tokenPrec: 245
|
|
298
302
|
});
|
|
299
303
|
|
|
300
304
|
//#endregion
|
|
@@ -377,11 +381,30 @@ var SQLQuery = class {
|
|
|
377
381
|
return missingVars;
|
|
378
382
|
}
|
|
379
383
|
};
|
|
384
|
+
/**
|
|
385
|
+
* Represents a TABLE annotation for generating appenders.
|
|
386
|
+
* TABLE annotations specify a table name for which to generate bulk insert appenders.
|
|
387
|
+
*/
|
|
388
|
+
var TableInfo = class {
|
|
389
|
+
/** Columns introspected from the database table schema */
|
|
390
|
+
columns = [];
|
|
391
|
+
constructor(filename, id, tableName, includeColumns, hasAppender) {
|
|
392
|
+
this.filename = filename;
|
|
393
|
+
this.id = id;
|
|
394
|
+
this.tableName = tableName;
|
|
395
|
+
this.includeColumns = includeColumns;
|
|
396
|
+
this.hasAppender = hasAppender;
|
|
397
|
+
}
|
|
398
|
+
get skipGenerateFunction() {
|
|
399
|
+
return !this.hasAppender;
|
|
400
|
+
}
|
|
401
|
+
};
|
|
380
402
|
function parseSQLQueries(filePath, extraVariables) {
|
|
381
403
|
const content = readFileSync(filePath, "utf-8");
|
|
382
404
|
consola.info(`Parsing SQL file: ${filePath}`);
|
|
383
405
|
consola.debug(`File start: ${content.slice(0, 200)}`);
|
|
384
406
|
const queries = [];
|
|
407
|
+
const tables = [];
|
|
385
408
|
const cursor = parser.parse(content).cursor();
|
|
386
409
|
function getStr(nodeName, optional = false) {
|
|
387
410
|
const node = cursor.node.getChild(nodeName);
|
|
@@ -532,6 +555,21 @@ function parseSQLQueries(filePath, extraVariables) {
|
|
|
532
555
|
if (to > from) sql.appendSql(content.slice(from, to));
|
|
533
556
|
sql.trim();
|
|
534
557
|
}
|
|
558
|
+
if (queryType === "TABLE") {
|
|
559
|
+
const hasAppender = modifiers.includes(":appender");
|
|
560
|
+
const tableName = sqlContentStr.trim() || name;
|
|
561
|
+
const includeColumns = [];
|
|
562
|
+
for (const mod of modifiers) {
|
|
563
|
+
const match = mod.match(/:appender\(([^)]+)\)/);
|
|
564
|
+
if (match) includeColumns.push(...match[1].split(",").map((c) => c.trim()));
|
|
565
|
+
}
|
|
566
|
+
const table = new TableInfo(filePath, name, tableName, includeColumns, hasAppender);
|
|
567
|
+
if (queryNames.has(name)) throw SqgError.inFile(`Duplicate name '${name}'`, "DUPLICATE_QUERY", filePath, { suggestion: `Rename one of the tables/queries to have a unique name` });
|
|
568
|
+
queryNames.add(name);
|
|
569
|
+
tables.push(table);
|
|
570
|
+
consola.debug(`Added table: ${name} -> ${tableName} (appender: ${hasAppender})`);
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
535
573
|
consola.debug("Parsed query:", {
|
|
536
574
|
type: queryType,
|
|
537
575
|
name,
|
|
@@ -548,9 +586,13 @@ function parseSQLQueries(filePath, extraVariables) {
|
|
|
548
586
|
consola.debug(`Added query: ${name} (${queryType})`);
|
|
549
587
|
}
|
|
550
588
|
while (cursor.next());
|
|
551
|
-
consola.info(`Total queries parsed: ${queries.length}`);
|
|
589
|
+
consola.info(`Total queries parsed: ${queries.length}, tables: ${tables.length}`);
|
|
552
590
|
consola.info(`Query names: ${queries.map((q) => q.id).join(", ")}`);
|
|
553
|
-
|
|
591
|
+
if (tables.length > 0) consola.info(`Table names: ${tables.map((t) => t.id).join(", ")}`);
|
|
592
|
+
return {
|
|
593
|
+
queries,
|
|
594
|
+
tables
|
|
595
|
+
};
|
|
554
596
|
}
|
|
555
597
|
|
|
556
598
|
//#endregion
|
|
@@ -658,6 +700,47 @@ const duckdb = new class {
|
|
|
658
700
|
throw error;
|
|
659
701
|
}
|
|
660
702
|
}
|
|
703
|
+
async introspectTables(tables) {
|
|
704
|
+
const connection = this.connection;
|
|
705
|
+
if (!connection) throw new DatabaseError("DuckDB connection not initialized", "duckdb", "This is an internal error. Check that migrations completed successfully.");
|
|
706
|
+
for (const table of tables) {
|
|
707
|
+
consola.info(`Introspecting table schema: ${table.tableName}`);
|
|
708
|
+
try {
|
|
709
|
+
const rows = (await connection.runAndReadAll(`DESCRIBE ${table.tableName}`)).getRows();
|
|
710
|
+
function convertType(type) {
|
|
711
|
+
if (type instanceof DuckDBListType) return new ListType(convertType(type.valueType));
|
|
712
|
+
if (type instanceof DuckDBStructType) return new StructType(type.entryTypes.map((t, index) => ({
|
|
713
|
+
name: type.entryNames[index],
|
|
714
|
+
type: convertType(t),
|
|
715
|
+
nullable: true
|
|
716
|
+
})));
|
|
717
|
+
if (type instanceof DuckDBMapType) return new MapType({
|
|
718
|
+
name: "key",
|
|
719
|
+
type: convertType(type.keyType),
|
|
720
|
+
nullable: true
|
|
721
|
+
}, {
|
|
722
|
+
name: "value",
|
|
723
|
+
type: convertType(type.valueType),
|
|
724
|
+
nullable: true
|
|
725
|
+
});
|
|
726
|
+
if (type instanceof DuckDBEnumType) return new EnumType(type.values);
|
|
727
|
+
return type.toString();
|
|
728
|
+
}
|
|
729
|
+
table.columns = rows.map((row) => {
|
|
730
|
+
return {
|
|
731
|
+
name: row[0],
|
|
732
|
+
type: row[1],
|
|
733
|
+
nullable: row[2] !== "NO"
|
|
734
|
+
};
|
|
735
|
+
});
|
|
736
|
+
consola.debug(`Table ${table.tableName} columns:`, table.columns);
|
|
737
|
+
consola.success(`Introspected table: ${table.tableName} (${table.columns.length} columns)`);
|
|
738
|
+
} catch (error) {
|
|
739
|
+
consola.error(`Failed to introspect table '${table.tableName}':`, error);
|
|
740
|
+
throw error;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
661
744
|
close() {
|
|
662
745
|
this.connection.closeSync();
|
|
663
746
|
}
|
|
@@ -752,6 +835,27 @@ const postgres = new class {
|
|
|
752
835
|
throw error;
|
|
753
836
|
}
|
|
754
837
|
}
|
|
838
|
+
async introspectTables(tables) {
|
|
839
|
+
const db = this.db;
|
|
840
|
+
if (!db) throw new DatabaseError("PostgreSQL database not initialized", "postgres", "This is an internal error. Check that migrations completed successfully.");
|
|
841
|
+
for (const table of tables) {
|
|
842
|
+
consola.info(`Introspecting table schema: ${table.tableName}`);
|
|
843
|
+
try {
|
|
844
|
+
table.columns = (await db.query(`SELECT column_name, data_type, is_nullable
|
|
845
|
+
FROM information_schema.columns
|
|
846
|
+
WHERE table_name = $1
|
|
847
|
+
ORDER BY ordinal_position`, [table.tableName])).rows.map((row) => ({
|
|
848
|
+
name: row.column_name,
|
|
849
|
+
type: row.data_type.toUpperCase(),
|
|
850
|
+
nullable: row.is_nullable === "YES"
|
|
851
|
+
}));
|
|
852
|
+
consola.success(`Introspected table: ${table.tableName} (${table.columns.length} columns)`);
|
|
853
|
+
} catch (error) {
|
|
854
|
+
consola.error(`Failed to introspect table '${table.tableName}':`, error);
|
|
855
|
+
throw error;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
755
859
|
async close() {
|
|
756
860
|
await this.db.end();
|
|
757
861
|
await this.dbInitial.query(`DROP DATABASE "${databaseName}"`);
|
|
@@ -791,6 +895,20 @@ const sqlite = new class {
|
|
|
791
895
|
throw error;
|
|
792
896
|
}
|
|
793
897
|
}
|
|
898
|
+
introspectTables(tables) {
|
|
899
|
+
const db = this.db;
|
|
900
|
+
if (!db) throw new DatabaseError("SQLite database not initialized", "sqlite", "This is an internal error. Migrations may have failed silently.");
|
|
901
|
+
for (const table of tables) {
|
|
902
|
+
consola.info(`Introspecting table schema: ${table.tableName}`);
|
|
903
|
+
const info = this.getTableInfo(db, table.tableName);
|
|
904
|
+
table.columns = Array.from(info.values()).map((col) => ({
|
|
905
|
+
name: col.name,
|
|
906
|
+
type: col.type || "TEXT",
|
|
907
|
+
nullable: col.notnull === 0 && col.pk === 0
|
|
908
|
+
}));
|
|
909
|
+
consola.success(`Introspected table: ${table.tableName} (${table.columns.length} columns)`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
794
912
|
close() {
|
|
795
913
|
this.db.close();
|
|
796
914
|
}
|
|
@@ -1206,7 +1324,7 @@ var BaseGenerator = class {
|
|
|
1206
1324
|
listType(column) {
|
|
1207
1325
|
return this.typeMapper.listType(column);
|
|
1208
1326
|
}
|
|
1209
|
-
async beforeGenerate(_projectDir, _gen, _queries) {}
|
|
1327
|
+
async beforeGenerate(_projectDir, _gen, _queries, _tables) {}
|
|
1210
1328
|
isCompatibleWith(_engine) {
|
|
1211
1329
|
return true;
|
|
1212
1330
|
}
|
|
@@ -1272,7 +1390,7 @@ var JavaGenerator = class extends BaseGenerator {
|
|
|
1272
1390
|
readColumn(column, index, path) {
|
|
1273
1391
|
return this.typeMapper.parseValue(column, `rs.getObject(${index + 1})`, path);
|
|
1274
1392
|
}
|
|
1275
|
-
async beforeGenerate(_projectDir, _gen, _queries) {
|
|
1393
|
+
async beforeGenerate(_projectDir, _gen, _queries, _tables) {
|
|
1276
1394
|
Handlebars.registerHelper("partsToString", (parts) => this.partsToString(parts));
|
|
1277
1395
|
Handlebars.registerHelper("declareTypes", (queryHelper) => {
|
|
1278
1396
|
const query = queryHelper.query;
|
|
@@ -1324,7 +1442,7 @@ var JavaDuckDBArrowGenerator = class extends BaseGenerator {
|
|
|
1324
1442
|
getFunctionName(id) {
|
|
1325
1443
|
return this.javaGenerator.getFunctionName(id);
|
|
1326
1444
|
}
|
|
1327
|
-
async beforeGenerate(projectDir, gen, queries) {
|
|
1445
|
+
async beforeGenerate(projectDir, gen, queries, tables) {
|
|
1328
1446
|
const q = queries.filter((q$1) => q$1.isQuery && q$1.isOne || q$1.isMigrate);
|
|
1329
1447
|
const name = `${gen.name}-jdbc`;
|
|
1330
1448
|
writeGeneratedFile(projectDir, {
|
|
@@ -1332,7 +1450,7 @@ var JavaDuckDBArrowGenerator = class extends BaseGenerator {
|
|
|
1332
1450
|
generator: "java/jdbc",
|
|
1333
1451
|
output: gen.output,
|
|
1334
1452
|
config: gen.config
|
|
1335
|
-
}, this.javaGenerator, name, q);
|
|
1453
|
+
}, this.javaGenerator, name, q, tables);
|
|
1336
1454
|
}
|
|
1337
1455
|
isCompatibleWith(engine) {
|
|
1338
1456
|
return engine === "duckdb";
|
|
@@ -1410,8 +1528,45 @@ var TsGenerator = class extends BaseGenerator {
|
|
|
1410
1528
|
getClassName(name) {
|
|
1411
1529
|
return pascalCase$1(name);
|
|
1412
1530
|
}
|
|
1413
|
-
async beforeGenerate(_projectDir, _gen, _queries) {
|
|
1531
|
+
async beforeGenerate(_projectDir, _gen, _queries, _tables) {
|
|
1414
1532
|
Handlebars.registerHelper("quote", (value) => this.quote(value));
|
|
1533
|
+
Handlebars.registerHelper("appendMethod", (column) => {
|
|
1534
|
+
const typeStr = column.type?.toString().toUpperCase() || "";
|
|
1535
|
+
if (typeStr === "INTEGER" || typeStr === "INT" || typeStr === "INT4" || typeStr === "SIGNED") return "Integer";
|
|
1536
|
+
if (typeStr === "SMALLINT" || typeStr === "INT2" || typeStr === "SHORT") return "SmallInt";
|
|
1537
|
+
if (typeStr === "TINYINT" || typeStr === "INT1") return "TinyInt";
|
|
1538
|
+
if (typeStr === "BIGINT" || typeStr === "INT8" || typeStr === "LONG") return "BigInt";
|
|
1539
|
+
if (typeStr === "HUGEINT" || typeStr === "INT128") return "HugeInt";
|
|
1540
|
+
if (typeStr === "UINTEGER" || typeStr === "UINT4") return "UInteger";
|
|
1541
|
+
if (typeStr === "USMALLINT" || typeStr === "UINT2") return "USmallInt";
|
|
1542
|
+
if (typeStr === "UTINYINT" || typeStr === "UINT1") return "UTinyInt";
|
|
1543
|
+
if (typeStr === "UBIGINT" || typeStr === "UINT8") return "UBigInt";
|
|
1544
|
+
if (typeStr === "DOUBLE" || typeStr === "FLOAT8" || typeStr === "NUMERIC" || typeStr === "DECIMAL") return "Double";
|
|
1545
|
+
if (typeStr === "FLOAT" || typeStr === "FLOAT4" || typeStr === "REAL") return "Float";
|
|
1546
|
+
if (typeStr === "BOOLEAN" || typeStr === "BOOL" || typeStr === "LOGICAL") return "Boolean";
|
|
1547
|
+
if (typeStr === "DATE") return "Date";
|
|
1548
|
+
if (typeStr === "TIMESTAMP" || typeStr.includes("TIMESTAMP")) return "Timestamp";
|
|
1549
|
+
if (typeStr === "TIME" || typeStr.includes("TIME")) return "Time";
|
|
1550
|
+
if (typeStr === "BLOB" || typeStr === "BYTEA" || typeStr === "BINARY" || typeStr === "VARBINARY") return "Blob";
|
|
1551
|
+
if (typeStr === "UUID") return "Uuid";
|
|
1552
|
+
if (typeStr === "INTERVAL") return "Interval";
|
|
1553
|
+
return "Varchar";
|
|
1554
|
+
});
|
|
1555
|
+
Handlebars.registerHelper("tsTypeForAppender", (column) => {
|
|
1556
|
+
const typeStr = column.type?.toString().toUpperCase() || "";
|
|
1557
|
+
let baseType;
|
|
1558
|
+
if (typeStr === "INTEGER" || typeStr === "INT" || typeStr === "INT4" || typeStr === "SMALLINT" || typeStr === "INT2" || typeStr === "TINYINT" || typeStr === "INT1" || typeStr === "UINTEGER" || typeStr === "UINT4" || typeStr === "USMALLINT" || typeStr === "UINT2" || typeStr === "UTINYINT" || typeStr === "UINT1" || typeStr === "DOUBLE" || typeStr === "FLOAT8" || typeStr === "FLOAT" || typeStr === "FLOAT4" || typeStr === "REAL") baseType = "number";
|
|
1559
|
+
else if (typeStr === "BIGINT" || typeStr === "INT8" || typeStr === "HUGEINT" || typeStr === "INT128" || typeStr === "UBIGINT" || typeStr === "UINT8") baseType = "bigint";
|
|
1560
|
+
else if (typeStr === "BOOLEAN" || typeStr === "BOOL") baseType = "boolean";
|
|
1561
|
+
else if (typeStr === "DATE") baseType = "DuckDBDateValue";
|
|
1562
|
+
else if (typeStr === "TIMESTAMP" || typeStr.includes("TIMESTAMP")) baseType = "DuckDBTimestampValue";
|
|
1563
|
+
else if (typeStr === "TIME" || typeStr.includes("TIME")) baseType = "DuckDBTimeValue";
|
|
1564
|
+
else if (typeStr === "BLOB" || typeStr === "BYTEA") baseType = "DuckDBBlobValue";
|
|
1565
|
+
else if (typeStr === "UUID") baseType = "string";
|
|
1566
|
+
else baseType = "string";
|
|
1567
|
+
if (column.nullable) return `${baseType} | null`;
|
|
1568
|
+
return baseType;
|
|
1569
|
+
});
|
|
1415
1570
|
Handlebars.registerHelper("tsType", (column) => {
|
|
1416
1571
|
const inlineType = (col) => {
|
|
1417
1572
|
const t = col.type;
|
|
@@ -1533,8 +1688,8 @@ var TsDuckDBGenerator = class extends TsGenerator {
|
|
|
1533
1688
|
constructor(template) {
|
|
1534
1689
|
super(template);
|
|
1535
1690
|
}
|
|
1536
|
-
async beforeGenerate(projectDir, gen, queries) {
|
|
1537
|
-
await super.beforeGenerate(projectDir, gen, queries);
|
|
1691
|
+
async beforeGenerate(projectDir, gen, queries, tables) {
|
|
1692
|
+
await super.beforeGenerate(projectDir, gen, queries, tables);
|
|
1538
1693
|
Handlebars.registerHelper("tsType", (column) => {
|
|
1539
1694
|
const inlineType = (col) => {
|
|
1540
1695
|
const t = col.type;
|
|
@@ -1707,15 +1862,50 @@ var SqlQueryHelper = class {
|
|
|
1707
1862
|
return this.generator.typeMapper;
|
|
1708
1863
|
}
|
|
1709
1864
|
};
|
|
1710
|
-
|
|
1865
|
+
/** Util class to help generating appenders for tables */
|
|
1866
|
+
var TableHelper = class {
|
|
1867
|
+
constructor(table, generator) {
|
|
1868
|
+
this.table = table;
|
|
1869
|
+
this.generator = generator;
|
|
1870
|
+
}
|
|
1871
|
+
get id() {
|
|
1872
|
+
return this.table.id;
|
|
1873
|
+
}
|
|
1874
|
+
get tableName() {
|
|
1875
|
+
return this.table.tableName;
|
|
1876
|
+
}
|
|
1877
|
+
get columns() {
|
|
1878
|
+
if (this.table.includeColumns.length > 0) return this.table.columns.filter((c) => this.table.includeColumns.includes(c.name));
|
|
1879
|
+
return this.table.columns;
|
|
1880
|
+
}
|
|
1881
|
+
get skipGenerateFunction() {
|
|
1882
|
+
return this.table.skipGenerateFunction;
|
|
1883
|
+
}
|
|
1884
|
+
get functionName() {
|
|
1885
|
+
return this.generator.getFunctionName(`create_${this.table.id}_appender`);
|
|
1886
|
+
}
|
|
1887
|
+
get className() {
|
|
1888
|
+
return this.generator.getClassName(`${this.table.id}_appender`);
|
|
1889
|
+
}
|
|
1890
|
+
get rowTypeName() {
|
|
1891
|
+
return this.generator.getClassName(`${this.table.id}_row`);
|
|
1892
|
+
}
|
|
1893
|
+
get typeMapper() {
|
|
1894
|
+
return this.generator.typeMapper;
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
function generateSourceFile(name, queries, tables, templatePath, generator, config) {
|
|
1711
1898
|
const templateSrc = readFileSync(templatePath, "utf-8");
|
|
1712
1899
|
const template = Handlebars.compile(templateSrc);
|
|
1713
1900
|
Handlebars.registerHelper("mapType", (column) => generator.mapType(column));
|
|
1714
1901
|
Handlebars.registerHelper("plusOne", (value) => value + 1);
|
|
1902
|
+
const migrations = queries.filter((q) => q.isMigrate).map((q) => new SqlQueryHelper(q, generator, generator.getStatement(q)));
|
|
1903
|
+
const tableHelpers = tables.filter((t) => !t.skipGenerateFunction).map((t) => new TableHelper(t, generator));
|
|
1715
1904
|
return template({
|
|
1716
1905
|
generatedComment: GENERATED_FILE_COMMENT,
|
|
1717
|
-
migrations
|
|
1906
|
+
migrations,
|
|
1718
1907
|
queries: queries.map((q) => new SqlQueryHelper(q, generator, generator.getStatement(q))),
|
|
1908
|
+
tables: tableHelpers,
|
|
1719
1909
|
className: generator.getClassName(name),
|
|
1720
1910
|
config
|
|
1721
1911
|
}, {
|
|
@@ -1830,11 +2020,11 @@ function validateQueries(queries) {
|
|
|
1830
2020
|
};
|
|
1831
2021
|
}
|
|
1832
2022
|
}
|
|
1833
|
-
async function writeGeneratedFile(projectDir, gen, generator, file, queries) {
|
|
1834
|
-
await generator.beforeGenerate(projectDir, gen, queries);
|
|
2023
|
+
async function writeGeneratedFile(projectDir, gen, generator, file, queries, tables = []) {
|
|
2024
|
+
await generator.beforeGenerate(projectDir, gen, queries, tables);
|
|
1835
2025
|
const templatePath = join(dirname(new URL(import.meta.url).pathname), gen.template ?? generator.template);
|
|
1836
2026
|
const name = gen.name ?? basename(file, extname(file));
|
|
1837
|
-
const sourceFile = generateSourceFile(name, queries, templatePath, generator, gen.config);
|
|
2027
|
+
const sourceFile = generateSourceFile(name, queries, tables, templatePath, generator, gen.config);
|
|
1838
2028
|
const outputPath = getOutputPath(projectDir, name, gen, generator);
|
|
1839
2029
|
writeFileSync(outputPath, sourceFile);
|
|
1840
2030
|
consola.success(`Generated ${outputPath}`);
|
|
@@ -1922,8 +2112,11 @@ async function processProject(projectPath) {
|
|
|
1922
2112
|
const fullPath = join(projectDir, sqlFile);
|
|
1923
2113
|
if (!existsSync(fullPath)) throw new FileNotFoundError(fullPath, projectDir);
|
|
1924
2114
|
let queries;
|
|
2115
|
+
let tables;
|
|
1925
2116
|
try {
|
|
1926
|
-
|
|
2117
|
+
const parseResult = parseSQLQueries(fullPath, extraVariables);
|
|
2118
|
+
queries = parseResult.queries;
|
|
2119
|
+
tables = parseResult.tables;
|
|
1927
2120
|
} catch (e) {
|
|
1928
2121
|
if (e instanceof SqgError) throw e;
|
|
1929
2122
|
throw SqgError.inFile(`Failed to parse SQL file: ${e.message}`, "SQL_PARSE_ERROR", sqlFile, { suggestion: "Check SQL syntax and annotation format" });
|
|
@@ -1932,6 +2125,7 @@ async function processProject(projectPath) {
|
|
|
1932
2125
|
const dbEngine = getDatabaseEngine(sql.engine);
|
|
1933
2126
|
await dbEngine.initializeDatabase(queries);
|
|
1934
2127
|
await dbEngine.executeQueries(queries);
|
|
2128
|
+
if (tables.length > 0) await dbEngine.introspectTables(tables);
|
|
1935
2129
|
validateQueries(queries);
|
|
1936
2130
|
await dbEngine.close();
|
|
1937
2131
|
} catch (e) {
|
|
@@ -1942,7 +2136,7 @@ async function processProject(projectPath) {
|
|
|
1942
2136
|
});
|
|
1943
2137
|
}
|
|
1944
2138
|
for (const gen of sql.gen) {
|
|
1945
|
-
const outputPath = await writeGeneratedFile(projectDir, gen, getGenerator(gen.generator), sqlFile, queries);
|
|
2139
|
+
const outputPath = await writeGeneratedFile(projectDir, gen, getGenerator(gen.generator), sqlFile, queries, tables);
|
|
1946
2140
|
files.push(outputPath);
|
|
1947
2141
|
}
|
|
1948
2142
|
}
|
|
@@ -2242,7 +2436,7 @@ Documentation: https://sqg.dev
|
|
|
2242
2436
|
|
|
2243
2437
|
//#endregion
|
|
2244
2438
|
//#region src/sqg.ts
|
|
2245
|
-
const version = process.env.npm_package_version ?? "0.
|
|
2439
|
+
const version = process.env.npm_package_version ?? "0.3.0";
|
|
2246
2440
|
const description = process.env.npm_package_description ?? "SQG - SQL Query Generator - Type-safe code generation from SQL (https://sqg.dev)";
|
|
2247
2441
|
consola.level = LogLevels.info;
|
|
2248
2442
|
const program = new Command().name("sqg").description(`${description}
|
|
@@ -14,6 +14,9 @@ import org.apache.arrow.vector.complex.ListVector;
|
|
|
14
14
|
import org.apache.arrow.vector.ipc.ArrowReader;
|
|
15
15
|
import org.duckdb.DuckDBConnection;
|
|
16
16
|
import org.duckdb.DuckDBResultSet;
|
|
17
|
+
{{#if tables.length}}
|
|
18
|
+
import org.duckdb.DuckDBAppender;
|
|
19
|
+
{{/if}}
|
|
17
20
|
import {{config.package}}.{{className}}Jdbc.*;
|
|
18
21
|
|
|
19
22
|
public class {{className}} {
|
|
@@ -46,9 +49,18 @@ public class {{className}} {
|
|
|
46
49
|
{{/if}}
|
|
47
50
|
{{/unless}}
|
|
48
51
|
{{/each}}
|
|
49
|
-
}
|
|
50
52
|
|
|
53
|
+
{{#if tables.length}}
|
|
54
|
+
// ==================== Appenders ====================
|
|
55
|
+
{{#each tables}}
|
|
51
56
|
|
|
57
|
+
/** Create an appender for bulk inserts into {{tableName}} */
|
|
58
|
+
public {{className}} {{functionName}}() throws SQLException {
|
|
59
|
+
return jdbc.{{functionName}}();
|
|
60
|
+
}
|
|
61
|
+
{{/each}}
|
|
62
|
+
{{/if}}
|
|
63
|
+
}
|
|
52
64
|
|
|
53
65
|
|
|
54
66
|
{{#*inline "columnTypesRecord"}}
|
|
@@ -21,6 +21,10 @@ import java.util.HashMap;
|
|
|
21
21
|
import java.util.Collections;
|
|
22
22
|
import java.util.UUID;
|
|
23
23
|
import java.util.function.Function;
|
|
24
|
+
{{#if tables.length}}
|
|
25
|
+
import org.duckdb.DuckDBAppender;
|
|
26
|
+
import org.duckdb.DuckDBConnection;
|
|
27
|
+
{{/if}}
|
|
24
28
|
|
|
25
29
|
public class {{className}} {
|
|
26
30
|
private final Connection connection;
|
|
@@ -139,8 +143,72 @@ public class {{className}} {
|
|
|
139
143
|
}
|
|
140
144
|
{{/unless}}
|
|
141
145
|
{{/each}}
|
|
142
|
-
}
|
|
143
146
|
|
|
147
|
+
{{#if tables.length}}
|
|
148
|
+
// ==================== Appenders ====================
|
|
149
|
+
{{#each tables}}
|
|
150
|
+
|
|
151
|
+
/** Create an appender for bulk inserts into {{tableName}} */
|
|
152
|
+
public {{className}} {{functionName}}() throws SQLException {
|
|
153
|
+
return new {{className}}(((DuckDBConnection) connection).createAppender(DuckDBConnection.DEFAULT_SCHEMA, "{{tableName}}"));
|
|
154
|
+
}
|
|
155
|
+
{{/each}}
|
|
156
|
+
{{/if}}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
{{#each tables}}
|
|
160
|
+
/** Row type for {{tableName}} appender */
|
|
161
|
+
public record {{rowTypeName}}({{#each columns}}{{mapType this}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) {}
|
|
162
|
+
|
|
163
|
+
/** Appender for bulk inserts into {{tableName}} */
|
|
164
|
+
public static class {{className}} implements AutoCloseable {
|
|
165
|
+
private final DuckDBAppender appender;
|
|
166
|
+
|
|
167
|
+
{{className}}(DuckDBAppender appender) {
|
|
168
|
+
this.appender = appender;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Get the underlying DuckDB appender for advanced operations */
|
|
172
|
+
public DuckDBAppender getAppender() {
|
|
173
|
+
return appender;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Append a single row */
|
|
177
|
+
public {{className}} append({{rowTypeName}} row) throws SQLException {
|
|
178
|
+
appender.beginRow();
|
|
179
|
+
{{#each columns}}
|
|
180
|
+
appender.append(row.{{name}}());
|
|
181
|
+
{{/each}}
|
|
182
|
+
appender.endRow();
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Append a single row with individual values */
|
|
187
|
+
public {{className}} append({{#each columns}}{{mapType this}} {{name}}{{#unless @last}}, {{/unless}}{{/each}}) throws SQLException {
|
|
188
|
+
appender.beginRow();
|
|
189
|
+
{{#each columns}}
|
|
190
|
+
appender.append({{name}});
|
|
191
|
+
{{/each}}
|
|
192
|
+
appender.endRow();
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Append multiple rows */
|
|
197
|
+
public {{className}} appendMany(Iterable<{{rowTypeName}}> rows) throws SQLException {
|
|
198
|
+
for (var row : rows) {
|
|
199
|
+
append(row);
|
|
200
|
+
}
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Flush and close the appender */
|
|
205
|
+
@Override
|
|
206
|
+
public void close() throws SQLException {
|
|
207
|
+
appender.close();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
{{/each}}
|
|
211
|
+
}
|
|
144
212
|
|
|
145
213
|
{{#*inline "columnTypesRecord"}}
|
|
146
214
|
{{#if isQuery}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// {{generatedComment}}
|
|
2
|
-
import type { DuckDBConnection, DuckDBMaterializedResult } from "@duckdb/node-api";
|
|
2
|
+
import type { DuckDBConnection, DuckDBMaterializedResult, DuckDBAppender, DuckDBDateValue, DuckDBTimeValue, DuckDBTimestampValue, DuckDBBlobValue } from "@duckdb/node-api";
|
|
3
3
|
|
|
4
4
|
export class {{className}} {
|
|
5
5
|
|
|
@@ -46,7 +46,67 @@ export class {{className}} {
|
|
|
46
46
|
{{/unless}}
|
|
47
47
|
|
|
48
48
|
{{/each}}
|
|
49
|
+
|
|
50
|
+
{{#if tables.length}}
|
|
51
|
+
// ==================== Appenders ====================
|
|
52
|
+
{{#each tables}}
|
|
53
|
+
|
|
54
|
+
async {{functionName}}(): Promise<{{className}}> {
|
|
55
|
+
return new {{className}}(await this.conn.createAppender('{{tableName}}'));
|
|
56
|
+
}
|
|
57
|
+
{{/each}}
|
|
58
|
+
{{/if}}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
{{#each tables}}
|
|
62
|
+
/** Row type for {{tableName}} appender */
|
|
63
|
+
export interface {{rowTypeName}} {
|
|
64
|
+
{{#each columns}}
|
|
65
|
+
{{name}}: {{{tsTypeForAppender this}}};
|
|
66
|
+
{{/each}}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Appender for bulk inserts into {{tableName}} */
|
|
70
|
+
export class {{className}} {
|
|
71
|
+
constructor(public readonly appender: DuckDBAppender) {}
|
|
72
|
+
|
|
73
|
+
/** Append a single row */
|
|
74
|
+
append(row: {{rowTypeName}}): this {
|
|
75
|
+
{{#each columns}}
|
|
76
|
+
{{#if nullable}}
|
|
77
|
+
if (row.{{name}} === null || row.{{name}} === undefined) {
|
|
78
|
+
this.appender.appendNull();
|
|
79
|
+
} else {
|
|
80
|
+
this.appender.append{{appendMethod this}}(row.{{name}});
|
|
81
|
+
}
|
|
82
|
+
{{else}}
|
|
83
|
+
this.appender.append{{appendMethod this}}(row.{{name}});
|
|
84
|
+
{{/if}}
|
|
85
|
+
{{/each}}
|
|
86
|
+
this.appender.endRow();
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Append multiple rows */
|
|
91
|
+
appendMany(rows: {{rowTypeName}}[]): this {
|
|
92
|
+
for (const row of rows) {
|
|
93
|
+
this.append(row);
|
|
94
|
+
}
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Flush buffered data to the table */
|
|
99
|
+
flush(): this {
|
|
100
|
+
this.appender.flushSync();
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Flush and close the appender */
|
|
105
|
+
close(): void {
|
|
106
|
+
this.appender.closeSync();
|
|
107
|
+
}
|
|
49
108
|
}
|
|
109
|
+
{{/each}}
|
|
50
110
|
|
|
51
111
|
{{#*inline "params"}}{{#each parameterNames}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}{{/inline}}
|
|
52
112
|
|