5757import static com .facebook .presto .common .type .IntegerType .INTEGER ;
5858import static com .facebook .presto .common .type .RealType .REAL ;
5959import static com .facebook .presto .common .type .SmallintType .SMALLINT ;
60+ import static com .facebook .presto .common .type .TimestampType .TIMESTAMP ;
61+ import static com .facebook .presto .common .type .TimestampType .TIMESTAMP_MICROSECONDS ;
6062import static com .facebook .presto .common .type .TinyintType .TINYINT ;
6163import static com .facebook .presto .plugin .clp .ClpErrorCode .CLP_PUSHDOWN_UNSUPPORTED_EXPRESSION ;
6264import static com .facebook .presto .spi .relation .SpecialFormExpression .Form .AND ;
@@ -486,7 +488,7 @@ private Optional<ClpExpression> tryInterpretSubstringEquality(
486488 RowExpression possibleSubstring ,
487489 RowExpression possibleLiteral )
488490 {
489- if (!operator .equals (EQUAL )) {
491+ if (!operator .equals (EQUAL ) && ! operator . equals ( NOT_EQUAL ) ) {
490492 return Optional .empty ();
491493 }
492494
@@ -501,7 +503,7 @@ private Optional<ClpExpression> tryInterpretSubstringEquality(
501503 }
502504
503505 String targetString = getLiteralString ((ConstantExpression ) possibleLiteral );
504- return interpretSubstringEquality (maybeSubstringCall .get (), targetString );
506+ return interpretSubstringEquality (maybeSubstringCall .get (), targetString , operator . equals ( EQUAL ) );
505507 }
506508
507509 /**
@@ -552,10 +554,15 @@ private Optional<SubstrInfo> parseSubstringCall(CallExpression callExpression)
552554 *
553555 * @param info parsed SUBSTR call info
554556 * @param targetString the literal string being compared to
557+ * @param isEqual whether the operator is EQUAL or not
555558 * @return an Optional containing either a ClpExpression with the equivalent KQL query
556559 */
557- private Optional <ClpExpression > interpretSubstringEquality (SubstrInfo info , String targetString )
560+ private Optional <ClpExpression > interpretSubstringEquality (SubstrInfo info , String targetString , boolean isEqual )
558561 {
562+ StringBuilder result = new StringBuilder ();
563+ if (!isEqual ) {
564+ result .append ("NOT " );
565+ }
559566 if (info .lengthExpression != null ) {
560567 Optional <Integer > maybeStart = parseIntValue (info .startExpression );
561568 Optional <Integer > maybeLen = parseLengthLiteral (info .lengthExpression , targetString );
@@ -564,7 +571,6 @@ private Optional<ClpExpression> interpretSubstringEquality(SubstrInfo info, Stri
564571 int start = maybeStart .get ();
565572 int len = maybeLen .get ();
566573 if (start > 0 && len == targetString .length ()) {
567- StringBuilder result = new StringBuilder ();
568574 result .append (info .variableName ).append (": \" " );
569575 for (int i = 1 ; i < start ; i ++) {
570576 result .append ("?" );
@@ -579,7 +585,6 @@ private Optional<ClpExpression> interpretSubstringEquality(SubstrInfo info, Stri
579585 if (maybeStart .isPresent ()) {
580586 int start = maybeStart .get ();
581587 if (start > 0 ) {
582- StringBuilder result = new StringBuilder ();
583588 result .append (info .variableName ).append (": \" " );
584589 for (int i = 1 ; i < start ; i ++) {
585590 result .append ("?" );
@@ -588,7 +593,8 @@ private Optional<ClpExpression> interpretSubstringEquality(SubstrInfo info, Stri
588593 return Optional .of (new ClpExpression (result .toString ()));
589594 }
590595 if (start == -targetString .length ()) {
591- return Optional .of (new ClpExpression (format ("%s: \" *%s\" " , info .variableName , targetString )));
596+ result .append (format ("%s: \" *%s\" " , info .variableName , targetString ));
597+ return Optional .of (new ClpExpression (result .toString ()));
592598 }
593599 }
594600 }
@@ -914,6 +920,8 @@ public static boolean isClpCompatibleNumericType(Type type)
914920 || type .equals (TINYINT )
915921 || type .equals (DOUBLE )
916922 || type .equals (REAL )
923+ || type .equals (TIMESTAMP )
924+ || type .equals (TIMESTAMP_MICROSECONDS )
917925 || type instanceof DecimalType ;
918926 }
919927
0 commit comments