11package com .exasol .adapter .request .parser ;
22
3+ import java .math .BigDecimal ;
4+ import java .util .*;
5+
6+ import javax .json .JsonArray ;
7+ import javax .json .JsonObject ;
8+
39import com .exasol .adapter .metadata .*;
410import com .exasol .adapter .metadata .DataType .ExaCharset ;
511import com .exasol .adapter .metadata .DataType .IntervalType ;
612import com .exasol .adapter .sql .*;
713
8- import javax .json .JsonArray ;
9- import javax .json .JsonObject ;
10- import java .math .BigDecimal ;
11- import java .util .ArrayList ;
12- import java .util .List ;
13-
1414public final class PushdownSqlParser extends AbstractRequestParser {
1515 private static final String ORDER_BY = "orderBy" ;
1616 private static final String EXPRESSION = "expression" ;
@@ -78,6 +78,10 @@ public SqlNode parseExpression(final JsonObject expression) {
7878 return parsePredicateBetween (expression );
7979 case PREDICATE_IN_CONSTLIST :
8080 return parsePredicateInConstlist (expression );
81+ case PREDICATE_IS_JSON :
82+ return parsePredicateIsJson (expression );
83+ case PREDICATE_IS_NOT_JSON :
84+ return parsePredicateIsNotJson (expression );
8185 case PREDICATE_IS_NULL :
8286 return parsePredicateIsNull (expression );
8387 case PREDICATE_IS_NOT_NULL :
@@ -90,6 +94,8 @@ public SqlNode parseExpression(final JsonObject expression) {
9094 return parseFunctionScalarCase (expression );
9195 case FUNCTION_SCALAR_CAST :
9296 return parseFunctionScalarCast (expression );
97+ case FUNCTION_SCALAR_JSON_VALUE :
98+ return parseFunctionScalarJsonValue (expression );
9399 case FUNCTION_AGGREGATE :
94100 return parseFunctionAggregate (expression );
95101 case FUNCTION_AGGREGATE_GROUP_CONCAT :
@@ -277,18 +283,22 @@ private SqlNode parsePredicateNot(final JsonObject exp) {
277283 }
278284
279285 private SqlNode parsePredicateOr (final JsonObject exp ) {
280- final List <SqlNode > orPredicates = new ArrayList <>();
281- for (final JsonObject pred : exp .getJsonArray ("expressions" ).getValuesAs (JsonObject .class )) {
282- orPredicates .add (parseExpression (pred ));
283- }
286+ final List <SqlNode > orPredicates = getListOfSqlNodes (exp , "expressions" );
284287 return new SqlPredicateOr (orPredicates );
285288 }
286289
287- private SqlNode parsePredicateAnd (final JsonObject exp ) {
288- final List <SqlNode > andedPredicates = new ArrayList <>();
289- for (final JsonObject pred : exp .getJsonArray ("expressions" ).getValuesAs (JsonObject .class )) {
290- andedPredicates .add (parseExpression (pred ));
290+ private List <SqlNode > getListOfSqlNodes (final JsonObject jsonExpression , final String key ) {
291+ final List <SqlNode > arguments = new ArrayList <>();
292+ if (jsonExpression .containsKey (key )) {
293+ for (final JsonObject jsonObject : jsonExpression .getJsonArray (key ).getValuesAs (JsonObject .class )) {
294+ arguments .add (parseExpression (jsonObject ));
295+ }
291296 }
297+ return arguments ;
298+ }
299+
300+ private SqlNode parsePredicateAnd (final JsonObject exp ) {
301+ final List <SqlNode > andedPredicates = getListOfSqlNodes (exp , "expressions" );
292302 return new SqlPredicateAnd (andedPredicates );
293303 }
294304
@@ -420,12 +430,27 @@ private SqlNode parsePredicateBetween(final JsonObject exp) {
420430 return new SqlPredicateBetween (betweenExp , betweenLeft , betweenRight );
421431 }
422432
433+ private SqlNode parsePredicateIsJson (final JsonObject jsonExpression ) {
434+ final SqlNode expression = parseExpression (jsonExpression .getJsonObject (EXPRESSION ));
435+ final SqlPredicateIsJson .TypeConstraints typeConstraint = SqlPredicateIsJson .TypeConstraints
436+ .valueOf (jsonExpression .getString ("typeConstraint" ).toUpperCase ());
437+ final SqlPredicateIsJson .KeyUniquenessConstraint keyUniquenessConstraint = SqlPredicateIsJson .KeyUniquenessConstraint
438+ .of (jsonExpression .getString ("keyUniquenessConstraint" ));
439+ return new SqlPredicateIsJson (expression , typeConstraint , keyUniquenessConstraint );
440+ }
441+
442+ private SqlNode parsePredicateIsNotJson (final JsonObject jsonExpression ) {
443+ final SqlNode expression = parseExpression (jsonExpression .getJsonObject (EXPRESSION ));
444+ final SqlPredicateIsJson .TypeConstraints typeConstraint = SqlPredicateIsJson .TypeConstraints
445+ .valueOf (jsonExpression .getString ("typeConstraint" ).toUpperCase ());
446+ final SqlPredicateIsJson .KeyUniquenessConstraint keyUniquenessConstraint = SqlPredicateIsJson .KeyUniquenessConstraint
447+ .of (jsonExpression .getString ("keyUniquenessConstraint" ));
448+ return new SqlPredicateIsNotJson (expression , typeConstraint , keyUniquenessConstraint );
449+ }
450+
423451 private SqlNode parsePredicateInConstlist (final JsonObject exp ) {
424452 final SqlNode inExp = parseExpression (exp .getJsonObject (EXPRESSION ));
425- final List <SqlNode > inArguments = new ArrayList <>();
426- for (final JsonObject pred : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
427- inArguments .add (parseExpression (pred ));
428- }
453+ final List <SqlNode > inArguments = getListOfSqlNodes (exp , ARGUMENTS );
429454 return new SqlPredicateInConstList (inExp , inArguments );
430455 }
431456
@@ -436,10 +461,7 @@ private SqlNode parseFunctionScalar(final JsonObject exp) {
436461 if (exp .containsKey ("variableInputArgs" )) {
437462 hasVariableInputArgs = exp .getBoolean ("variableInputArgs" );
438463 }
439- final List <SqlNode > arguments = new ArrayList <>();
440- for (final JsonObject argument : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
441- arguments .add (parseExpression (argument ));
442- }
464+ final List <SqlNode > arguments = getListOfSqlNodes (exp , ARGUMENTS );
443465 if (!hasVariableInputArgs ) {
444466 numArgs = exp .getInt ("numArgs" );
445467 assert numArgs == arguments .size ();
@@ -457,58 +479,64 @@ private SqlNode parseFunctionScalar(final JsonObject exp) {
457479
458480 private SqlNode parseFunctionScalarExtract (final JsonObject exp ) {
459481 final String toExtract = exp .getString ("toExtract" );
460- final List <SqlNode > extractArguments = new ArrayList <>();
461- if (exp .containsKey (ARGUMENTS )) {
462- for (final JsonObject argument : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
463- extractArguments .add (parseExpression (argument ));
464- }
465- }
482+ final List <SqlNode > extractArguments = getListOfSqlNodes (exp , ARGUMENTS );
466483 return new SqlFunctionScalarExtract (toExtract , extractArguments );
467484 }
468485
469486 private SqlNode parseFunctionScalarCase (final JsonObject exp ) {
470- final List <SqlNode > caseArguments = new ArrayList <>( );
471- final List <SqlNode > caseResults = new ArrayList <>( );
487+ final List <SqlNode > caseArguments = getListOfSqlNodes ( exp , ARGUMENTS );
488+ final List <SqlNode > caseResults = getListOfSqlNodes ( exp , "results" );
472489 SqlNode caseBasis = null ;
473- if (exp .containsKey (ARGUMENTS )) {
474- for (final JsonObject argument : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
475- caseArguments .add (parseExpression (argument ));
476- }
477- }
478- if (exp .containsKey ("results" )) {
479- for (final JsonObject argument : exp .getJsonArray ("results" ).getValuesAs (JsonObject .class )) {
480- caseResults .add (parseExpression (argument ));
481- }
482- }
483490 if (exp .containsKey ("basis" )) {
484491 caseBasis = parseExpression (exp .getJsonObject ("basis" ));
485492 }
486493 return new SqlFunctionScalarCase (caseArguments , caseResults , caseBasis );
487494 }
488495
489- private SqlNode parseFunctionScalarCast (final JsonObject exp ) {
490- final DataType castDataType = getDataType (exp .getJsonObject (DATA_TYPE ));
491- final List <SqlNode > castArguments = new ArrayList <>();
492- if (exp .containsKey (ARGUMENTS )) {
493- for (final JsonObject argument : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
494- castArguments .add (parseExpression (argument ));
495- }
496- }
496+ private SqlNode parseFunctionScalarCast (final JsonObject jsonObject ) {
497+ final DataType castDataType = getDataType (jsonObject .getJsonObject (DATA_TYPE ));
498+ final List <SqlNode > castArguments = getListOfSqlNodes (jsonObject , ARGUMENTS );
497499 return new SqlFunctionScalarCast (castDataType , castArguments );
498500 }
499501
502+ private SqlNode parseFunctionScalarJsonValue (final JsonObject jsonObject ) {
503+ final String functionName = jsonObject .getString ("name" );
504+ final List <SqlNode > arguments = getListOfSqlNodes (jsonObject , ARGUMENTS );
505+ final DataType returningDataType = getDataType (jsonObject .getJsonObject ("returningDataType" ));
506+ final SqlFunctionScalarJsonValue .Behavior emptyBehavior = getScalarJsonValueBehavior (jsonObject ,
507+ "emptyBehavior" );
508+ final SqlFunctionScalarJsonValue .Behavior errorBehavior = getScalarJsonValueBehavior (jsonObject ,
509+ "errorBehavior" );
510+ return new SqlFunctionScalarJsonValue (fromScalarFunctionName (functionName ), arguments , returningDataType ,
511+ emptyBehavior , errorBehavior );
512+ }
513+
514+ private SqlFunctionScalarJsonValue .Behavior getScalarJsonValueBehavior (final JsonObject jsonObject ,
515+ final String key ) {
516+ final JsonObject behaviorJson = jsonObject .getJsonObject (key );
517+ final String behaviorTypeString = behaviorJson .getString ("type" );
518+ final SqlFunctionScalarJsonValue .BehaviorType behaviorType = SqlFunctionScalarJsonValue .BehaviorType
519+ .valueOf (behaviorTypeString );
520+ final Optional <SqlNode > expression = getScalarJsonValueExpression (behaviorJson , behaviorType );
521+ return new SqlFunctionScalarJsonValue .Behavior (behaviorType , expression );
522+ }
523+
524+ private Optional <SqlNode > getScalarJsonValueExpression (final JsonObject jsonObject ,
525+ final SqlFunctionScalarJsonValue .BehaviorType behaviorType ) {
526+ if (behaviorType == SqlFunctionScalarJsonValue .BehaviorType .DEFAULT ) {
527+ return Optional .of (parseExpression (jsonObject .getJsonObject (EXPRESSION )));
528+ } else {
529+ return Optional .empty ();
530+ }
531+ }
532+
500533 private SqlNode parseFunctionAggregate (final JsonObject exp ) {
501534 final String setFunctionName = exp .getString ("name" );
502- final List <SqlNode > setArguments = new ArrayList <>( );
535+ final List <SqlNode > setArguments = getListOfSqlNodes ( exp , ARGUMENTS );
503536 boolean distinct = false ;
504537 if (exp .containsKey (DISTINCT )) {
505538 distinct = exp .getBoolean (DISTINCT );
506539 }
507- if (exp .containsKey (ARGUMENTS )) {
508- for (final JsonObject argument : exp .getJsonArray (ARGUMENTS ).getValuesAs (JsonObject .class )) {
509- setArguments .add (parseExpression (argument ));
510- }
511- }
512540 return new SqlFunctionAggregate (fromAggregationFunctionName (setFunctionName ), setArguments , distinct );
513541 }
514542
0 commit comments