Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008-2024, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.query.impl.predicates;
import com.hazelcast.internal.serialization.BinaryInterface;
import com.hazelcast.internal.util.collection.ArrayUtils;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.IdentifiedDataSerializable;
import com.hazelcast.query.Predicate;
import com.hazelcast.query.Predicates;
import com.hazelcast.query.impl.IndexRegistry;
import com.hazelcast.query.impl.QueryContext;
import com.hazelcast.query.impl.QueryableEntry;
import java.io.IOException;
import java.io.Serial;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.hazelcast.internal.serialization.impl.FactoryIdHelper.PREDICATE_DS_FACTORY_ID;
import static com.hazelcast.internal.util.StringUtil.equalsIgnoreCase;
import static com.hazelcast.query.Predicates.between;
import static com.hazelcast.query.Predicates.equal;
import static com.hazelcast.query.Predicates.ilike;
import static com.hazelcast.query.Predicates.like;
import static com.hazelcast.query.Predicates.regex;
/**
* This class contains methods related to conversion of 'sql' query to predicate.
*/
@BinaryInterface
@SuppressWarnings("checkstyle:methodcount")
public class SqlPredicate
implements IndexAwarePredicate, VisitablePredicate, IdentifiedDataSerializable {
/**
* Disables the skip index syntax. The only reason why this property should be set to true is if
* someone is using % as first character in their fieldname and do not want it to be interpreted
* as 'skipIndex'.
*/
private static final boolean SKIP_INDEX_ENABLED = !Boolean.getBoolean("hazelcast.query.disableSkipIndex");
@Serial
private static final long serialVersionUID = 1;
private interface ComparisonPredicateFactory {
Predicate create(String attribute, Comparable c);
}
private static final ComparisonPredicateFactory EQUAL_FACTORY = Predicates::equal;
private static final ComparisonPredicateFactory NOT_EQUAL_FACTORY = Predicates::notEqual;
private static final ComparisonPredicateFactory GREATER_THAN_FACTORY = Predicates::greaterThan;
private static final ComparisonPredicateFactory GREATER_EQUAL_FACTORY = Predicates::greaterEqual;
private static final ComparisonPredicateFactory LESS_EQUAL_FACTORY = Predicates::lessEqual;
private static final ComparisonPredicateFactory LESS_THAN_FACTORY = Predicates::lessThan;
transient Predicate predicate;
private String sql;
public SqlPredicate(String sql) {
this.sql = sql;
predicate = createPredicate(sql);
}
public SqlPredicate() {
}
@Override
public boolean apply(Map.Entry mapEntry) {
return predicate.apply(mapEntry);
}
@Override
public boolean isIndexed(QueryContext queryContext) {
if (predicate instanceof IndexAwarePredicate awarePredicate) {
return awarePredicate.isIndexed(queryContext);
}
return false;
}
@Override
public Set filter(QueryContext queryContext) {
return ((IndexAwarePredicate) predicate).filter(queryContext);
}
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeString(sql);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
sql = in.readString();
predicate = createPredicate(sql);
}
private int getApostropheIndex(String str, int start) {
return str.indexOf('\'', start);
}
private int getApostropheIndexIgnoringDoubles(String str, int start) {
int i = str.indexOf('\'', start);
int j = str.indexOf('\'', i + 1);
//ignore doubles
while (i == j - 1) {
i = str.indexOf('\'', j + 1);
j = str.indexOf('\'', i + 1);
}
return i;
}
private String removeEscapes(String phrase) {
return (phrase.length() > 2) ? phrase.replace("''", "'") : phrase;
}
@SuppressWarnings({"checkstyle:npathcomplexity", "checkstyle:cyclomaticcomplexity", "checkstyle:methodlength"})
private Predicate createPredicate(String sql) {
String paramSql = sql;
Map mapPhrases = new HashMap<>();
int apoIndex = getApostropheIndex(paramSql, 0);
if (apoIndex != -1) {
int phraseId = 0;
StringBuilder newSql = new StringBuilder();
while (apoIndex != -1) {
phraseId++;
int start = apoIndex + 1;
int end = getApostropheIndexIgnoringDoubles(paramSql, apoIndex + 1);
if (end == -1) {
throw new IllegalArgumentException("Missing ' in sql");
}
String phrase = removeEscapes(paramSql.substring(start, end));
String key = "$" + phraseId;
mapPhrases.put(key, phrase);
String before = paramSql.substring(0, apoIndex);
paramSql = paramSql.substring(end + 1);
newSql.append(before);
newSql.append(key);
apoIndex = getApostropheIndex(paramSql, 0);
}
newSql.append(paramSql);
paramSql = newSql.toString();
}
SqlParser parser = new SqlParser();
List sqlTokens = parser.toPrefix(paramSql);
List