1+ import { expressionToWhereRaw } from './expressionHelper' ;
12import * as kustoHelper from './kustoHelper' ;
23import { Syntax , SyntaxKind } from './kustoHelper' ;
34import { parsePatternsToRe2 , PrimitiveTypeLong , PrimitiveTypeString , unescapeRegexPlaceholders } from './parseExpressionHelper' ;
45import { DebugSQLOptions , getQueryBuilder , QueryContext , QueryInterface , raw , SQLResult } from "./QueryBuilder" ;
56
6- function visitBinaryExpression (
7- qc : QueryContext ,
8- qb : QueryInterface ,
9- v : Syntax . BinaryExpression ,
10- ) {
11- // TODO: recursive visit
12- const left = kustoHelper . kqlToString ( v . Left ! ) ;
13- const right = kustoHelper . kqlToString ( v . Right ! ) ;
14- const op = kustoHelper . kqlToString ( v . Operator ! ) ;
15-
16- const raw = `${ left } ${ op } ${ right } ` ;
17- qb . whereRaw ( raw ) ;
18- }
19-
20- function visitContainsExpression (
21- qc : QueryContext ,
22- qb : QueryInterface ,
23- v : Syntax . BinaryExpression ,
24- ) {
25- const left = kustoHelper . kqlToString ( v . Left ! ) ;
26- // use getTokenValue to unquote string
27- const right = kustoHelper . getTokenValue ( v . Right ! ) ;
28- const op = kustoHelper . kqlToString ( v . Operator ! ) . toLowerCase ( ) ;
29-
30- switch ( op ) {
31- case 'contains' :
32- qb . whereLike ( left , `%${ right } %` ) ;
33- break ;
34- case '!contains' :
35- qb . not . whereLike ( left , `%${ right } %` ) ;
36- break
37- case 'contains_cs' :
38- throw new Error ( `contains_cs not implemented` ) ;
39- case '!contains_cs' :
40- throw new Error ( `!contains_cs not implemented` ) ;
41- }
42- }
43-
447function visitFilterOperator (
458 qc : QueryContext ,
469 qb : QueryInterface ,
@@ -50,26 +13,8 @@ function visitFilterOperator(
5013 throw new Error ( `missing condition` ) ;
5114 }
5215
53- switch ( v . Condition . Kind ) {
54- case SyntaxKind . AndExpression :
55- case SyntaxKind . OrExpression :
56- case SyntaxKind . GreaterThanExpression :
57- case SyntaxKind . GreaterThanOrEqualExpression :
58- case SyntaxKind . LessThanExpression :
59- case SyntaxKind . LessThanOrEqualExpression :
60- case SyntaxKind . NotEqualExpression :
61- case SyntaxKind . EqualExpression :
62- visitBinaryExpression ( qc , qb , v . Condition as Syntax . BinaryExpression ) ;
63- break ;
64- case SyntaxKind . ContainsExpression :
65- case SyntaxKind . ContainsCsExpression :
66- case SyntaxKind . NotContainsExpression :
67- case SyntaxKind . NotContainsCsExpression :
68- visitContainsExpression ( qc , qb , v . Condition as Syntax . BinaryExpression ) ;
69- break
70- default :
71- throw new Error ( `unsupported condition type ${ kustoHelper . getSyntaxKindName ( v . Condition . Kind ) } ` ) ;
72- }
16+ const whereRaw = expressionToWhereRaw ( v . Condition ) ;
17+ qb . whereRaw ( whereRaw . sql , whereRaw . bindings ) ;
7318}
7419
7520function visitProjectOperator_SeparatedElement (
@@ -91,17 +36,17 @@ function visitProjectOperator_SeparatedElement(
9136 // case: project a = foo
9237 {
9338 const projectAsExpr = ( exprChild as Syntax . SimpleNamedExpression ) ;
39+ const projectSource = expressionToWhereRaw ( projectAsExpr . Expression ) ;
9440 const projectAsName = kustoHelper . kqlToString ( projectAsExpr . Name ) ;
95- const projectSource = kustoHelper . kqlToString ( projectAsExpr . Expression ) ;
96- qb . select ( raw ( `${ projectSource } as ${ projectAsName } ` ) ) ;
41+ qb . select ( raw ( `${ projectSource . sql } as ${ projectAsName } ` , projectSource . bindings ) ) ;
9742 }
9843 break ;
9944 default :
10045 // case: project foo + 10
10146 {
102- const projectSource = kustoHelper . kqlToString ( exprChild ) ;
47+ const projectSource = expressionToWhereRaw ( exprChild as Syntax . Expression ) ;
10348 const projectAsName = qc . acquireAutoProjectAsName ( ) ;
104- qb . select ( raw ( `${ projectSource } as ${ projectAsName } ` ) ) ;
49+ qb . select ( raw ( `${ projectSource . sql } as ${ projectAsName } ` , projectSource . bindings ) ) ;
10550 }
10651 }
10752
@@ -244,6 +189,38 @@ function visitDistinctOperator(
244189 return qc . wrapAsCTE ( qb ) ;
245190}
246191
192+ function visitExtendOperator (
193+ qc : QueryContext ,
194+ qb : QueryInterface ,
195+ v : Syntax . ExtendOperator ,
196+ ) : QueryInterface {
197+ if ( ! v . Expressions ) {
198+ return qb ;
199+ }
200+
201+ kustoHelper . visitChild (
202+ v . Expressions ,
203+ ( child ) => {
204+ if ( child . Kind !== SyntaxKind . SeparatedElement ) {
205+ // unexpected
206+ return ;
207+ }
208+
209+ visitProjectOperator_SeparatedElement (
210+ qc ,
211+ qb ,
212+ child as Syntax . SeparatedElement ,
213+ ) ;
214+ }
215+ ) ;
216+
217+ // select all fields from CTE, but after extended columns as extended columns
218+ // take higher precedence.
219+ qb . select ( '*' ) ;
220+
221+ return qc . wrapAsCTE ( qb ) ;
222+ }
223+
247224function visitQueryBlock (
248225 qc : QueryContext ,
249226 qb : QueryInterface ,
@@ -312,6 +289,8 @@ function visit(
312289 return visitCountOperator ( qc , qb , v as Syntax . CountOperator ) ;
313290 case SyntaxKind . DistinctOperator :
314291 return visitDistinctOperator ( qc , qb , v as Syntax . DistinctOperator ) ;
292+ case SyntaxKind . ExtendOperator :
293+ return visitExtendOperator ( qc , qb , v as Syntax . ExtendOperator ) ;
315294 default :
316295 qc . logUnknown ( `unhandled kind: ${ kustoHelper . getSyntaxKindName ( v . Kind ) } ` ) ;
317296 return qb ;
0 commit comments