Implement ToString function

This commit is contained in:
Pijus Kamandulis 2024-02-23 00:11:14 +02:00
parent 59632ec966
commit 16f41a5479
7 changed files with 277 additions and 139 deletions

View File

@ -87,6 +87,7 @@ const (
FunctionCallEndsWith FunctionCallType = "EndsWith" FunctionCallEndsWith FunctionCallType = "EndsWith"
FunctionCallStartsWith FunctionCallType = "StartsWith" FunctionCallStartsWith FunctionCallType = "StartsWith"
FunctionCallIndexOf FunctionCallType = "IndexOf" FunctionCallIndexOf FunctionCallType = "IndexOf"
FunctionCallToString FunctionCallType = "ToString"
) )
type FunctionCall struct { type FunctionCall struct {

View File

@ -1608,10 +1608,14 @@ var g = &grammar{
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 312, col: 7, offset: 9001}, pos: position{line: 312, col: 7, offset: 9001},
name: "ToStringExpression",
},
&ruleRefExpr{
pos: position{line: 313, col: 7, offset: 9026},
name: "ConcatExpression", name: "ConcatExpression",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 313, col: 7, offset: 9024}, pos: position{line: 314, col: 7, offset: 9049},
name: "ThreeArgumentStringFunctionExpression", name: "ThreeArgumentStringFunctionExpression",
}, },
}, },
@ -1619,91 +1623,91 @@ var g = &grammar{
}, },
{ {
name: "StringEqualsExpression", name: "StringEqualsExpression",
pos: position{line: 315, col: 1, offset: 9063}, pos: position{line: 316, col: 1, offset: 9088},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 315, col: 27, offset: 9089}, pos: position{line: 316, col: 27, offset: 9114},
run: (*parser).callonStringEqualsExpression1, run: (*parser).callonStringEqualsExpression1,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 315, col: 27, offset: 9089}, pos: position{line: 316, col: 27, offset: 9114},
exprs: []any{ exprs: []any{
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 27, offset: 9089}, pos: position{line: 316, col: 27, offset: 9114},
name: "StringEquals", name: "StringEquals",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 40, offset: 9102}, pos: position{line: 316, col: 40, offset: 9127},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 315, col: 43, offset: 9105}, pos: position{line: 316, col: 43, offset: 9130},
val: "(", val: "(",
ignoreCase: false, ignoreCase: false,
want: "\"(\"", want: "\"(\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 47, offset: 9109}, pos: position{line: 316, col: 47, offset: 9134},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 315, col: 50, offset: 9112}, pos: position{line: 316, col: 50, offset: 9137},
label: "ex1", label: "ex1",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 315, col: 54, offset: 9116}, pos: position{line: 316, col: 54, offset: 9141},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 65, offset: 9127}, pos: position{line: 316, col: 65, offset: 9152},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 315, col: 68, offset: 9130}, pos: position{line: 316, col: 68, offset: 9155},
val: ",", val: ",",
ignoreCase: false, ignoreCase: false,
want: "\",\"", want: "\",\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 72, offset: 9134}, pos: position{line: 316, col: 72, offset: 9159},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 315, col: 75, offset: 9137}, pos: position{line: 316, col: 75, offset: 9162},
label: "ex2", label: "ex2",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 315, col: 79, offset: 9141}, pos: position{line: 316, col: 79, offset: 9166},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 90, offset: 9152}, pos: position{line: 316, col: 90, offset: 9177},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 315, col: 93, offset: 9155}, pos: position{line: 316, col: 93, offset: 9180},
label: "ignoreCase", label: "ignoreCase",
expr: &zeroOrOneExpr{ expr: &zeroOrOneExpr{
pos: position{line: 315, col: 104, offset: 9166}, pos: position{line: 316, col: 104, offset: 9191},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 315, col: 105, offset: 9167}, pos: position{line: 316, col: 105, offset: 9192},
run: (*parser).callonStringEqualsExpression17, run: (*parser).callonStringEqualsExpression17,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 315, col: 105, offset: 9167}, pos: position{line: 316, col: 105, offset: 9192},
exprs: []any{ exprs: []any{
&litMatcher{ &litMatcher{
pos: position{line: 315, col: 105, offset: 9167}, pos: position{line: 316, col: 105, offset: 9192},
val: ",", val: ",",
ignoreCase: false, ignoreCase: false,
want: "\",\"", want: "\",\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 315, col: 109, offset: 9171}, pos: position{line: 316, col: 109, offset: 9196},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 315, col: 112, offset: 9174}, pos: position{line: 316, col: 112, offset: 9199},
label: "boolean", label: "boolean",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 315, col: 120, offset: 9182}, pos: position{line: 316, col: 120, offset: 9207},
name: "SelectItem", name: "SelectItem",
}, },
}, },
@ -1713,7 +1717,58 @@ var g = &grammar{
}, },
}, },
&litMatcher{ &litMatcher{
pos: position{line: 315, col: 157, offset: 9219}, pos: position{line: 316, col: 157, offset: 9244},
val: ")",
ignoreCase: false,
want: "\")\"",
},
},
},
},
},
{
name: "ToStringExpression",
pos: position{line: 320, col: 1, offset: 9378},
expr: &actionExpr{
pos: position{line: 320, col: 23, offset: 9400},
run: (*parser).callonToStringExpression1,
expr: &seqExpr{
pos: position{line: 320, col: 23, offset: 9400},
exprs: []any{
&litMatcher{
pos: position{line: 320, col: 23, offset: 9400},
val: "tostring",
ignoreCase: true,
want: "\"TOSTRING\"i",
},
&ruleRefExpr{
pos: position{line: 320, col: 35, offset: 9412},
name: "ws",
},
&litMatcher{
pos: position{line: 320, col: 38, offset: 9415},
val: "(",
ignoreCase: false,
want: "\"(\"",
},
&ruleRefExpr{
pos: position{line: 320, col: 42, offset: 9419},
name: "ws",
},
&labeledExpr{
pos: position{line: 320, col: 45, offset: 9422},
label: "ex",
expr: &ruleRefExpr{
pos: position{line: 320, col: 48, offset: 9425},
name: "SelectItem",
},
},
&ruleRefExpr{
pos: position{line: 320, col: 59, offset: 9436},
name: "ws",
},
&litMatcher{
pos: position{line: 320, col: 62, offset: 9439},
val: ")", val: ")",
ignoreCase: false, ignoreCase: false,
want: "\")\"", want: "\")\"",
@ -1724,71 +1779,71 @@ var g = &grammar{
}, },
{ {
name: "ConcatExpression", name: "ConcatExpression",
pos: position{line: 319, col: 1, offset: 9353}, pos: position{line: 324, col: 1, offset: 9551},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 319, col: 21, offset: 9373}, pos: position{line: 324, col: 21, offset: 9571},
run: (*parser).callonConcatExpression1, run: (*parser).callonConcatExpression1,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 319, col: 21, offset: 9373}, pos: position{line: 324, col: 21, offset: 9571},
exprs: []any{ exprs: []any{
&litMatcher{ &litMatcher{
pos: position{line: 319, col: 21, offset: 9373}, pos: position{line: 324, col: 21, offset: 9571},
val: "concat", val: "concat",
ignoreCase: true, ignoreCase: true,
want: "\"CONCAT\"i", want: "\"CONCAT\"i",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 319, col: 31, offset: 9383}, pos: position{line: 324, col: 31, offset: 9581},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 319, col: 34, offset: 9386}, pos: position{line: 324, col: 34, offset: 9584},
val: "(", val: "(",
ignoreCase: false, ignoreCase: false,
want: "\"(\"", want: "\"(\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 319, col: 38, offset: 9390}, pos: position{line: 324, col: 38, offset: 9588},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 319, col: 41, offset: 9393}, pos: position{line: 324, col: 41, offset: 9591},
label: "ex1", label: "ex1",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 319, col: 45, offset: 9397}, pos: position{line: 324, col: 45, offset: 9595},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 319, col: 56, offset: 9408}, pos: position{line: 324, col: 56, offset: 9606},
label: "others", label: "others",
expr: &oneOrMoreExpr{ expr: &oneOrMoreExpr{
pos: position{line: 319, col: 63, offset: 9415}, pos: position{line: 324, col: 63, offset: 9613},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 319, col: 64, offset: 9416}, pos: position{line: 324, col: 64, offset: 9614},
run: (*parser).callonConcatExpression11, run: (*parser).callonConcatExpression11,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 319, col: 64, offset: 9416}, pos: position{line: 324, col: 64, offset: 9614},
exprs: []any{ exprs: []any{
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 319, col: 64, offset: 9416}, pos: position{line: 324, col: 64, offset: 9614},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 319, col: 67, offset: 9419}, pos: position{line: 324, col: 67, offset: 9617},
val: ",", val: ",",
ignoreCase: false, ignoreCase: false,
want: "\",\"", want: "\",\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 319, col: 71, offset: 9423}, pos: position{line: 324, col: 71, offset: 9621},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 319, col: 74, offset: 9426}, pos: position{line: 324, col: 74, offset: 9624},
label: "ex", label: "ex",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 319, col: 77, offset: 9429}, pos: position{line: 324, col: 77, offset: 9627},
name: "SelectItem", name: "SelectItem",
}, },
}, },
@ -1798,11 +1853,11 @@ var g = &grammar{
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 319, col: 109, offset: 9461}, pos: position{line: 324, col: 109, offset: 9659},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 319, col: 112, offset: 9464}, pos: position{line: 324, col: 112, offset: 9662},
val: ")", val: ")",
ignoreCase: false, ignoreCase: false,
want: "\")\"", want: "\")\"",
@ -1813,95 +1868,95 @@ var g = &grammar{
}, },
{ {
name: "ThreeArgumentStringFunctionExpression", name: "ThreeArgumentStringFunctionExpression",
pos: position{line: 324, col: 1, offset: 9637}, pos: position{line: 329, col: 1, offset: 9835},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 324, col: 42, offset: 9678}, pos: position{line: 329, col: 42, offset: 9876},
run: (*parser).callonThreeArgumentStringFunctionExpression1, run: (*parser).callonThreeArgumentStringFunctionExpression1,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 324, col: 42, offset: 9678}, pos: position{line: 329, col: 42, offset: 9876},
exprs: []any{ exprs: []any{
&labeledExpr{ &labeledExpr{
pos: position{line: 324, col: 42, offset: 9678}, pos: position{line: 329, col: 42, offset: 9876},
label: "function", label: "function",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 324, col: 51, offset: 9687}, pos: position{line: 329, col: 51, offset: 9885},
name: "ThreeArgumentStringFunction", name: "ThreeArgumentStringFunction",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 79, offset: 9715}, pos: position{line: 329, col: 79, offset: 9913},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 324, col: 82, offset: 9718}, pos: position{line: 329, col: 82, offset: 9916},
val: "(", val: "(",
ignoreCase: false, ignoreCase: false,
want: "\"(\"", want: "\"(\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 86, offset: 9722}, pos: position{line: 329, col: 86, offset: 9920},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 324, col: 89, offset: 9725}, pos: position{line: 329, col: 89, offset: 9923},
label: "ex1", label: "ex1",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 324, col: 93, offset: 9729}, pos: position{line: 329, col: 93, offset: 9927},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 104, offset: 9740}, pos: position{line: 329, col: 104, offset: 9938},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 324, col: 107, offset: 9743}, pos: position{line: 329, col: 107, offset: 9941},
val: ",", val: ",",
ignoreCase: false, ignoreCase: false,
want: "\",\"", want: "\",\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 111, offset: 9747}, pos: position{line: 329, col: 111, offset: 9945},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 324, col: 114, offset: 9750}, pos: position{line: 329, col: 114, offset: 9948},
label: "ex2", label: "ex2",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 324, col: 118, offset: 9754}, pos: position{line: 329, col: 118, offset: 9952},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 129, offset: 9765}, pos: position{line: 329, col: 129, offset: 9963},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 324, col: 132, offset: 9768}, pos: position{line: 329, col: 132, offset: 9966},
label: "ignoreCase", label: "ignoreCase",
expr: &zeroOrOneExpr{ expr: &zeroOrOneExpr{
pos: position{line: 324, col: 143, offset: 9779}, pos: position{line: 329, col: 143, offset: 9977},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 324, col: 144, offset: 9780}, pos: position{line: 329, col: 144, offset: 9978},
run: (*parser).callonThreeArgumentStringFunctionExpression18, run: (*parser).callonThreeArgumentStringFunctionExpression18,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 324, col: 144, offset: 9780}, pos: position{line: 329, col: 144, offset: 9978},
exprs: []any{ exprs: []any{
&litMatcher{ &litMatcher{
pos: position{line: 324, col: 144, offset: 9780}, pos: position{line: 329, col: 144, offset: 9978},
val: ",", val: ",",
ignoreCase: false, ignoreCase: false,
want: "\",\"", want: "\",\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 324, col: 148, offset: 9784}, pos: position{line: 329, col: 148, offset: 9982},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 324, col: 151, offset: 9787}, pos: position{line: 329, col: 151, offset: 9985},
label: "boolean", label: "boolean",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 324, col: 159, offset: 9795}, pos: position{line: 329, col: 159, offset: 9993},
name: "SelectItem", name: "SelectItem",
}, },
}, },
@ -1911,7 +1966,7 @@ var g = &grammar{
}, },
}, },
&litMatcher{ &litMatcher{
pos: position{line: 324, col: 196, offset: 9832}, pos: position{line: 329, col: 196, offset: 10030},
val: ")", val: ")",
ignoreCase: false, ignoreCase: false,
want: "\")\"", want: "\")\"",
@ -1922,33 +1977,33 @@ var g = &grammar{
}, },
{ {
name: "ThreeArgumentStringFunction", name: "ThreeArgumentStringFunction",
pos: position{line: 342, col: 1, offset: 10378}, pos: position{line: 347, col: 1, offset: 10576},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 342, col: 32, offset: 10409}, pos: position{line: 347, col: 32, offset: 10607},
run: (*parser).callonThreeArgumentStringFunction1, run: (*parser).callonThreeArgumentStringFunction1,
expr: &choiceExpr{ expr: &choiceExpr{
pos: position{line: 342, col: 33, offset: 10410}, pos: position{line: 347, col: 33, offset: 10608},
alternatives: []any{ alternatives: []any{
&litMatcher{ &litMatcher{
pos: position{line: 342, col: 33, offset: 10410}, pos: position{line: 347, col: 33, offset: 10608},
val: "contains", val: "contains",
ignoreCase: true, ignoreCase: true,
want: "\"CONTAINS\"i", want: "\"CONTAINS\"i",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 342, col: 47, offset: 10424}, pos: position{line: 347, col: 47, offset: 10622},
val: "endswith", val: "endswith",
ignoreCase: true, ignoreCase: true,
want: "\"ENDSWITH\"i", want: "\"ENDSWITH\"i",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 342, col: 61, offset: 10438}, pos: position{line: 347, col: 61, offset: 10636},
val: "startswith", val: "startswith",
ignoreCase: true, ignoreCase: true,
want: "\"STARTSWITH\"i", want: "\"STARTSWITH\"i",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 342, col: 77, offset: 10454}, pos: position{line: 347, col: 77, offset: 10652},
val: "index_of", val: "index_of",
ignoreCase: true, ignoreCase: true,
want: "\"INDEX_OF\"i", want: "\"INDEX_OF\"i",
@ -1959,47 +2014,47 @@ var g = &grammar{
}, },
{ {
name: "IsDefined", name: "IsDefined",
pos: position{line: 346, col: 1, offset: 10503}, pos: position{line: 351, col: 1, offset: 10701},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 346, col: 14, offset: 10516}, pos: position{line: 351, col: 14, offset: 10714},
run: (*parser).callonIsDefined1, run: (*parser).callonIsDefined1,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 346, col: 14, offset: 10516}, pos: position{line: 351, col: 14, offset: 10714},
exprs: []any{ exprs: []any{
&litMatcher{ &litMatcher{
pos: position{line: 346, col: 14, offset: 10516}, pos: position{line: 351, col: 14, offset: 10714},
val: "is_defined", val: "is_defined",
ignoreCase: true, ignoreCase: true,
want: "\"IS_DEFINED\"i", want: "\"IS_DEFINED\"i",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 346, col: 28, offset: 10530}, pos: position{line: 351, col: 28, offset: 10728},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 346, col: 31, offset: 10533}, pos: position{line: 351, col: 31, offset: 10731},
val: "(", val: "(",
ignoreCase: false, ignoreCase: false,
want: "\"(\"", want: "\"(\"",
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 346, col: 35, offset: 10537}, pos: position{line: 351, col: 35, offset: 10735},
name: "ws", name: "ws",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 346, col: 38, offset: 10540}, pos: position{line: 351, col: 38, offset: 10738},
label: "ex", label: "ex",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 346, col: 41, offset: 10543}, pos: position{line: 351, col: 41, offset: 10741},
name: "SelectItem", name: "SelectItem",
}, },
}, },
&ruleRefExpr{ &ruleRefExpr{
pos: position{line: 346, col: 52, offset: 10554}, pos: position{line: 351, col: 52, offset: 10752},
name: "ws", name: "ws",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 346, col: 55, offset: 10557}, pos: position{line: 351, col: 55, offset: 10755},
val: ")", val: ")",
ignoreCase: false, ignoreCase: false,
want: "\")\"", want: "\")\"",
@ -2010,14 +2065,14 @@ var g = &grammar{
}, },
{ {
name: "Integer", name: "Integer",
pos: position{line: 350, col: 1, offset: 10670}, pos: position{line: 355, col: 1, offset: 10868},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 350, col: 12, offset: 10681}, pos: position{line: 355, col: 12, offset: 10879},
run: (*parser).callonInteger1, run: (*parser).callonInteger1,
expr: &oneOrMoreExpr{ expr: &oneOrMoreExpr{
pos: position{line: 350, col: 12, offset: 10681}, pos: position{line: 355, col: 12, offset: 10879},
expr: &charClassMatcher{ expr: &charClassMatcher{
pos: position{line: 350, col: 12, offset: 10681}, pos: position{line: 355, col: 12, offset: 10879},
val: "[0-9]", val: "[0-9]",
ranges: []rune{'0', '9'}, ranges: []rune{'0', '9'},
ignoreCase: false, ignoreCase: false,
@ -2028,29 +2083,29 @@ var g = &grammar{
}, },
{ {
name: "StringCharacter", name: "StringCharacter",
pos: position{line: 354, col: 1, offset: 10733}, pos: position{line: 359, col: 1, offset: 10931},
expr: &choiceExpr{ expr: &choiceExpr{
pos: position{line: 354, col: 20, offset: 10752}, pos: position{line: 359, col: 20, offset: 10950},
alternatives: []any{ alternatives: []any{
&actionExpr{ &actionExpr{
pos: position{line: 354, col: 20, offset: 10752}, pos: position{line: 359, col: 20, offset: 10950},
run: (*parser).callonStringCharacter2, run: (*parser).callonStringCharacter2,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 354, col: 20, offset: 10752}, pos: position{line: 359, col: 20, offset: 10950},
exprs: []any{ exprs: []any{
&notExpr{ &notExpr{
pos: position{line: 354, col: 20, offset: 10752}, pos: position{line: 359, col: 20, offset: 10950},
expr: &choiceExpr{ expr: &choiceExpr{
pos: position{line: 354, col: 22, offset: 10754}, pos: position{line: 359, col: 22, offset: 10952},
alternatives: []any{ alternatives: []any{
&litMatcher{ &litMatcher{
pos: position{line: 354, col: 22, offset: 10754}, pos: position{line: 359, col: 22, offset: 10952},
val: "\"", val: "\"",
ignoreCase: false, ignoreCase: false,
want: "\"\\\"\"", want: "\"\\\"\"",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 354, col: 28, offset: 10760}, pos: position{line: 359, col: 28, offset: 10958},
val: "\\", val: "\\",
ignoreCase: false, ignoreCase: false,
want: "\"\\\\\"", want: "\"\\\\\"",
@ -2059,28 +2114,28 @@ var g = &grammar{
}, },
}, },
&anyMatcher{ &anyMatcher{
line: 354, col: 34, offset: 10766, line: 359, col: 34, offset: 10964,
}, },
}, },
}, },
}, },
&actionExpr{ &actionExpr{
pos: position{line: 355, col: 5, offset: 10803}, pos: position{line: 360, col: 5, offset: 11001},
run: (*parser).callonStringCharacter9, run: (*parser).callonStringCharacter9,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 355, col: 5, offset: 10803}, pos: position{line: 360, col: 5, offset: 11001},
exprs: []any{ exprs: []any{
&litMatcher{ &litMatcher{
pos: position{line: 355, col: 5, offset: 10803}, pos: position{line: 360, col: 5, offset: 11001},
val: "\\", val: "\\",
ignoreCase: false, ignoreCase: false,
want: "\"\\\\\"", want: "\"\\\\\"",
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 355, col: 10, offset: 10808}, pos: position{line: 360, col: 10, offset: 11006},
label: "seq", label: "seq",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 355, col: 14, offset: 10812}, pos: position{line: 360, col: 14, offset: 11010},
name: "EscapeSequenceCharacter", name: "EscapeSequenceCharacter",
}, },
}, },
@ -2092,85 +2147,85 @@ var g = &grammar{
}, },
{ {
name: "EscapeSequenceCharacter", name: "EscapeSequenceCharacter",
pos: position{line: 357, col: 1, offset: 10857}, pos: position{line: 362, col: 1, offset: 11055},
expr: &labeledExpr{ expr: &labeledExpr{
pos: position{line: 357, col: 28, offset: 10884}, pos: position{line: 362, col: 28, offset: 11082},
label: "char", label: "char",
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 357, col: 33, offset: 10889}, pos: position{line: 362, col: 33, offset: 11087},
name: "EscapeCharacter", name: "EscapeCharacter",
}, },
}, },
}, },
{ {
name: "EscapeCharacter", name: "EscapeCharacter",
pos: position{line: 359, col: 1, offset: 10906}, pos: position{line: 364, col: 1, offset: 11104},
expr: &choiceExpr{ expr: &choiceExpr{
pos: position{line: 359, col: 20, offset: 10925}, pos: position{line: 364, col: 20, offset: 11123},
alternatives: []any{ alternatives: []any{
&litMatcher{ &litMatcher{
pos: position{line: 359, col: 20, offset: 10925}, pos: position{line: 364, col: 20, offset: 11123},
val: "'", val: "'",
ignoreCase: false, ignoreCase: false,
want: "\"'\"", want: "\"'\"",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 360, col: 5, offset: 10933}, pos: position{line: 365, col: 5, offset: 11131},
val: "\"", val: "\"",
ignoreCase: false, ignoreCase: false,
want: "\"\\\"\"", want: "\"\\\"\"",
}, },
&litMatcher{ &litMatcher{
pos: position{line: 361, col: 5, offset: 10941}, pos: position{line: 366, col: 5, offset: 11139},
val: "\\", val: "\\",
ignoreCase: false, ignoreCase: false,
want: "\"\\\\\"", want: "\"\\\\\"",
}, },
&actionExpr{ &actionExpr{
pos: position{line: 362, col: 5, offset: 10950}, pos: position{line: 367, col: 5, offset: 11148},
run: (*parser).callonEscapeCharacter5, run: (*parser).callonEscapeCharacter5,
expr: &litMatcher{ expr: &litMatcher{
pos: position{line: 362, col: 5, offset: 10950}, pos: position{line: 367, col: 5, offset: 11148},
val: "b", val: "b",
ignoreCase: false, ignoreCase: false,
want: "\"b\"", want: "\"b\"",
}, },
}, },
&actionExpr{ &actionExpr{
pos: position{line: 363, col: 5, offset: 10979}, pos: position{line: 368, col: 5, offset: 11177},
run: (*parser).callonEscapeCharacter7, run: (*parser).callonEscapeCharacter7,
expr: &litMatcher{ expr: &litMatcher{
pos: position{line: 363, col: 5, offset: 10979}, pos: position{line: 368, col: 5, offset: 11177},
val: "f", val: "f",
ignoreCase: false, ignoreCase: false,
want: "\"f\"", want: "\"f\"",
}, },
}, },
&actionExpr{ &actionExpr{
pos: position{line: 364, col: 5, offset: 11008}, pos: position{line: 369, col: 5, offset: 11206},
run: (*parser).callonEscapeCharacter9, run: (*parser).callonEscapeCharacter9,
expr: &litMatcher{ expr: &litMatcher{
pos: position{line: 364, col: 5, offset: 11008}, pos: position{line: 369, col: 5, offset: 11206},
val: "n", val: "n",
ignoreCase: false, ignoreCase: false,
want: "\"n\"", want: "\"n\"",
}, },
}, },
&actionExpr{ &actionExpr{
pos: position{line: 365, col: 5, offset: 11037}, pos: position{line: 370, col: 5, offset: 11235},
run: (*parser).callonEscapeCharacter11, run: (*parser).callonEscapeCharacter11,
expr: &litMatcher{ expr: &litMatcher{
pos: position{line: 365, col: 5, offset: 11037}, pos: position{line: 370, col: 5, offset: 11235},
val: "r", val: "r",
ignoreCase: false, ignoreCase: false,
want: "\"r\"", want: "\"r\"",
}, },
}, },
&actionExpr{ &actionExpr{
pos: position{line: 366, col: 5, offset: 11066}, pos: position{line: 371, col: 5, offset: 11264},
run: (*parser).callonEscapeCharacter13, run: (*parser).callonEscapeCharacter13,
expr: &litMatcher{ expr: &litMatcher{
pos: position{line: 366, col: 5, offset: 11066}, pos: position{line: 371, col: 5, offset: 11264},
val: "t", val: "t",
ignoreCase: false, ignoreCase: false,
want: "\"t\"", want: "\"t\"",
@ -2181,25 +2236,25 @@ var g = &grammar{
}, },
{ {
name: "non_escape_character", name: "non_escape_character",
pos: position{line: 368, col: 1, offset: 11092}, pos: position{line: 373, col: 1, offset: 11290},
expr: &actionExpr{ expr: &actionExpr{
pos: position{line: 368, col: 25, offset: 11116}, pos: position{line: 373, col: 25, offset: 11314},
run: (*parser).callonnon_escape_character1, run: (*parser).callonnon_escape_character1,
expr: &seqExpr{ expr: &seqExpr{
pos: position{line: 368, col: 25, offset: 11116}, pos: position{line: 373, col: 25, offset: 11314},
exprs: []any{ exprs: []any{
&notExpr{ &notExpr{
pos: position{line: 368, col: 25, offset: 11116}, pos: position{line: 373, col: 25, offset: 11314},
expr: &ruleRefExpr{ expr: &ruleRefExpr{
pos: position{line: 368, col: 27, offset: 11118}, pos: position{line: 373, col: 27, offset: 11316},
name: "escape_character", name: "escape_character",
}, },
}, },
&labeledExpr{ &labeledExpr{
pos: position{line: 368, col: 45, offset: 11136}, pos: position{line: 373, col: 45, offset: 11334},
label: "char", label: "char",
expr: &anyMatcher{ expr: &anyMatcher{
line: 368, col: 50, offset: 11141, line: 373, col: 50, offset: 11339,
}, },
}, },
}, },
@ -2208,11 +2263,11 @@ var g = &grammar{
}, },
{ {
name: "ws", name: "ws",
pos: position{line: 371, col: 1, offset: 11180}, pos: position{line: 376, col: 1, offset: 11378},
expr: &zeroOrMoreExpr{ expr: &zeroOrMoreExpr{
pos: position{line: 371, col: 7, offset: 11186}, pos: position{line: 376, col: 7, offset: 11384},
expr: &charClassMatcher{ expr: &charClassMatcher{
pos: position{line: 371, col: 7, offset: 11186}, pos: position{line: 376, col: 7, offset: 11384},
val: "[ \\t\\n\\r]", val: "[ \\t\\n\\r]",
chars: []rune{' ', '\t', '\n', '\r'}, chars: []rune{' ', '\t', '\n', '\r'},
ignoreCase: false, ignoreCase: false,
@ -2222,11 +2277,11 @@ var g = &grammar{
}, },
{ {
name: "EOF", name: "EOF",
pos: position{line: 373, col: 1, offset: 11198}, pos: position{line: 378, col: 1, offset: 11396},
expr: &notExpr{ expr: &notExpr{
pos: position{line: 373, col: 8, offset: 11205}, pos: position{line: 378, col: 8, offset: 11403},
expr: &anyMatcher{ expr: &anyMatcher{
line: 373, col: 9, offset: 11206, line: 378, col: 9, offset: 11404,
}, },
}, },
}, },
@ -2685,6 +2740,16 @@ func (p *parser) callonStringEqualsExpression1() (any, error) {
return p.cur.onStringEqualsExpression1(stack["ex1"], stack["ex2"], stack["ignoreCase"]) return p.cur.onStringEqualsExpression1(stack["ex1"], stack["ex2"], stack["ignoreCase"])
} }
func (c *current) onToStringExpression1(ex any) (any, error) {
return parsers.FunctionCall{Type: parsers.FunctionCallToString, Arguments: []interface{}{ex}}, nil
}
func (p *parser) callonToStringExpression1() (any, error) {
stack := p.vstack[len(p.vstack)-1]
_ = stack
return p.cur.onToStringExpression1(stack["ex"])
}
func (c *current) onConcatExpression11(ex any) (any, error) { func (c *current) onConcatExpression11(ex any) (any, error) {
return ex, nil return ex, nil
} }

View File

@ -309,6 +309,7 @@ BooleanLiteral <- ("true"i / "false"i) {
FunctionCall <- StringFunctions / IsDefined FunctionCall <- StringFunctions / IsDefined
StringFunctions <- StringEqualsExpression StringFunctions <- StringEqualsExpression
/ ToStringExpression
/ ConcatExpression / ConcatExpression
/ ThreeArgumentStringFunctionExpression / ThreeArgumentStringFunctionExpression
@ -316,6 +317,10 @@ StringEqualsExpression <- StringEquals ws "(" ws ex1:SelectItem ws "," ws ex2:Se
return parsers.FunctionCall{Type: parsers.FunctionCallStringEquals, Arguments: []interface{}{ex1, ex2, ignoreCase}}, nil return parsers.FunctionCall{Type: parsers.FunctionCallStringEquals, Arguments: []interface{}{ex1, ex2, ignoreCase}}, nil
} }
ToStringExpression <- "TOSTRING"i ws "(" ws ex:SelectItem ws ")" {
return parsers.FunctionCall{Type: parsers.FunctionCallToString, Arguments: []interface{}{ex}}, nil
}
ConcatExpression <- "CONCAT"i ws "(" ws ex1:SelectItem others:(ws "," ws ex:SelectItem { return ex, nil })+ ws ")" { ConcatExpression <- "CONCAT"i ws "(" ws ex1:SelectItem others:(ws "," ws ex:SelectItem { return ex, nil })+ ws ")" {
arguments := append([]interface{}{ex1}, others.([]interface{})...) arguments := append([]interface{}{ex1}, others.([]interface{})...)
return parsers.FunctionCall{Type: parsers.FunctionCallConcat, Arguments: arguments}, nil return parsers.FunctionCall{Type: parsers.FunctionCallConcat, Arguments: arguments}, nil

View File

@ -264,4 +264,28 @@ func Test_Execute_StringFunctions(t *testing.T) {
}, },
) )
}) })
t.Run("Should parse function ToString()", func(t *testing.T) {
testQueryParse(
t,
`SELECT ToString(c.id) FROM c`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallToString,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "id"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
)
})
} }

View File

@ -188,6 +188,8 @@ func getFieldValue(field parsers.SelectItem, queryParameters map[string]interfac
return strings_Concat(typedValue.Arguments, queryParameters, row) return strings_Concat(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIndexOf: case parsers.FunctionCallIndexOf:
return strings_IndexOf(typedValue.Arguments, queryParameters, row) return strings_IndexOf(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallToString:
return strings_ToString(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsDefined: case parsers.FunctionCallIsDefined:
return typeChecking_IsDefined(typedValue.Arguments, queryParameters, row) return typeChecking_IsDefined(typedValue.Arguments, queryParameters, row)
} }

View File

@ -9,8 +9,8 @@ import (
func Test_Execute_StringFunctions(t *testing.T) { func Test_Execute_StringFunctions(t *testing.T) {
mockData := []memoryexecutor.RowType{ mockData := []memoryexecutor.RowType{
map[string]interface{}{"id": "123", "pk": "aaa", "str": "hello"}, map[string]interface{}{"id": "123", "pk": "aaa", "str": "hello", "rng_type": true},
map[string]interface{}{"id": "456", "pk": "bbb", "str": "world"}, map[string]interface{}{"id": "456", "pk": "bbb", "str": "world", "rng_type": 159},
map[string]interface{}{"id": "789", "pk": "AAA", "str": "cool world"}, map[string]interface{}{"id": "789", "pk": "AAA", "str": "cool world"},
} }
@ -343,4 +343,38 @@ func Test_Execute_StringFunctions(t *testing.T) {
}, },
) )
}) })
t.Run("Should execute function ToString()", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Path: []string{"c", "id"},
Type: parsers.SelectItemTypeField,
},
{
Alias: "str",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallToString,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "rng_type"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "123", "str": "true"},
map[string]interface{}{"id": "456", "str": "159"},
map[string]interface{}{"id": "789", "str": ""},
},
)
})
} }

View File

@ -96,6 +96,11 @@ func strings_IndexOf(arguments []interface{}, queryParameters map[string]interfa
} }
} }
func strings_ToString(arguments []interface{}, queryParameters map[string]interface{}, row RowType) string {
value := getFieldValue(arguments[0].(parsers.SelectItem), queryParameters, row)
return convertToString(value)
}
func getBoolFlag(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool { func getBoolFlag(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
ignoreCase := false ignoreCase := false
if len(arguments) > 2 && arguments[2] != nil { if len(arguments) > 2 && arguments[2] != nil {
@ -127,6 +132,8 @@ func convertToString(value interface{}) string {
return fmt.Sprintf("%d", v) return fmt.Sprintf("%d", v)
case float32, float64: case float32, float64:
return fmt.Sprintf("%f", v) return fmt.Sprintf("%f", v)
case bool:
return fmt.Sprintf("%t", v)
} }
return "" return ""
} }