virajjasani commented on code in PR #1906: URL: https://github.com/apache/phoenix/pull/1906#discussion_r1702236356
########## phoenix-core-client/src/main/java/org/apache/phoenix/expression/util/bson/SQLComparisonExpressionUtils.java: ########## @@ -0,0 +1,290 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.phoenix.expression.util.bson; + +import org.bson.BsonDocument; +import org.bson.BsonValue; +import org.bson.RawBsonDocument; +import org.mvel2.MVEL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.regex.Pattern; + +/** + * SQL style condition expression evaluation support. + */ +public class SQLComparisonExpressionUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(SQLComparisonExpressionUtils.class); + + private static final String FIELD_NOT_EXISTS = "field_not_exists\\(([^)]+)\\)"; + private static final String FIELD_EXISTS = "field_exists\\(([^)]+)\\)"; + private static final String EQUALS1 = "\\b([\\w.\\[\\]]+)\\s*=\\s*([#:$]*\\w+)"; + private static final String EQUALS2 = "\\b([\\w.\\[\\]]+)\\s*==\\s*([#:$]*\\w+)"; + private static final String NOT_EQUALS1 = "\\b([\\w.\\[\\]]+)\\s*!=\\s*([#:$]*\\w+)"; + private static final String NOT_EQUALS2 = "\\b([\\w.\\[\\]]+)\\s*<>\\s*([#:$]*\\w+)"; + private static final String LESS_THAN = "\\b([\\w.\\[\\]]+)\\s*<\\s*([#:$]*\\w+)"; + private static final String LESS_THAN_OR_EQUALS = "\\b([\\w.\\[\\]]+)\\s*<=\\s*([#:$]*\\w+)"; + private static final String GREATER_THAN = "\\b([\\w.\\[\\]]+)\\s*>\\s*([#:$]*\\w+)"; + private static final String GREATER_THAN_OR_EQUALS = "\\b([\\w.\\[\\]]+)\\s*>=\\s*([#:$]*\\w+)"; + private static final String BETWEEN = + "\\b([\\w.\\[\\]]+)\\s+BETWEEN\\s+([#:$]*\\w+)\\s+AND\\s+([#:$]*\\w+)"; + private static final String IN = "\\b([\\w.\\[\\]]+)\\s+IN\\s+\\(([^)]+)\\)"; + private static final String AND = "\\bAND\\b"; + private static final String OR = "\\bOR\\b"; + private static final String NOT = "\\bNOT\\b\\s*"; + + private static final Pattern FIELD_NOT_EXISTS_PATTERN = Pattern.compile(FIELD_NOT_EXISTS); + private static final Pattern FIELD_EXISTS_PATTERN = Pattern.compile(FIELD_EXISTS); + private static final Pattern EQUALS1_PATTERN = Pattern.compile(EQUALS1); + private static final Pattern EQUALS2_PATTERN = Pattern.compile(EQUALS2); + private static final Pattern NOT_EQUALS1_PATTERN = Pattern.compile(NOT_EQUALS1); + private static final Pattern NOT_EQUALS2_PATTERN = Pattern.compile(NOT_EQUALS2); + private static final Pattern LESS_THAN_PATTERN = Pattern.compile(LESS_THAN); + private static final Pattern LESS_THAN_OR_EQUALS_PATTERN = Pattern.compile(LESS_THAN_OR_EQUALS); + private static final Pattern GREATER_THAN_PATTERN = Pattern.compile(GREATER_THAN); + private static final Pattern GREATER_THAN_OR_EQUALS_PATTERN = + Pattern.compile(GREATER_THAN_OR_EQUALS); + private static final Pattern BETWEEN_PATTERN = Pattern.compile(BETWEEN); + private static final Pattern IN_PATTERN = Pattern.compile(IN); + private static final Pattern AND_PATTERN = Pattern.compile(AND); + private static final Pattern OR_PATTERN = Pattern.compile(OR); + private static final Pattern NOT_PATTERN = Pattern.compile(NOT); + + private static final String FUNC_FIELD_NOT_EXISTS = "!exists('$1')"; + private static final String FUNC_FIELD_EXISTS = "exists('$1')"; + private static final String FUNC_EQUALS = "isEquals('$1', '$2')"; + private static final String FUNC_NOT_EQUALS = "!isEquals('$1', '$2')"; + private static final String FUNC_LESS_THAN = "lessThan('$1', '$2')"; + private static final String FUNC_LESS_THAN_OR_EQUALS = "lessThanOrEquals('$1', '$2')"; + private static final String FUNC_GREATER_THAN = "greaterThan('$1', '$2')"; + private static final String FUNC_GREATER_THAN_OR_EQUALS = "greaterThanOrEquals('$1', '$2')"; + private static final String FUNC_BETWEEN = "between('$1', '$2', '$3')"; + private static final String FUNC_IN = "in('$1', '$2')"; + private static final String OP_AND = "&&"; + private static final String OP_OR = "||"; + private static final String OP_NOT = "!"; + + private final RawBsonDocument rawBsonDocument; + private final BsonDocument comparisonValuesDocument; + + public SQLComparisonExpressionUtils(RawBsonDocument rawBsonDocument, + BsonDocument comparisonValuesDocument) { + this.rawBsonDocument = rawBsonDocument; + this.comparisonValuesDocument = comparisonValuesDocument; + } + + public boolean isConditionExpressionMatching(final String conditionExpression) { + String expression = convertExpression(conditionExpression); + LOGGER.info("Evaluating Expression: {}", expression); + try { + Object result = MVEL.eval(expression, this); + return result instanceof Boolean && (Boolean) result; + } catch (Exception e) { + LOGGER.error("Error while evaluating expression: {}", expression, e); + throw new RuntimeException("Expression could not be evaluated: " + expression); + } + } + + public String convertExpression(String expression) { Review Comment: I had an offline discussion with @kadirozde reg this. I will create a separate follow-up Jira to use ANTLR based parsing for Bson SQL style condition expression evaluation. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
