com.tangosol.util.QueryHelper Maven / Gradle / Ivy
Show all versions of coherence Show documentation
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.util;
import com.tangosol.coherence.config.ResolvableParameterList;
import com.tangosol.coherence.dslquery.CoherenceQueryLanguage;
import com.tangosol.coherence.dslquery.ExecutionContext;
import com.tangosol.coherence.dslquery.FilterBuilder;
import com.tangosol.coherence.dslquery.Statement;
import com.tangosol.coherence.dslquery.StatementResult;
import com.tangosol.coherence.dsltools.precedence.OPParser;
import com.tangosol.coherence.dsltools.precedence.TokenTable;
import com.tangosol.coherence.dsltools.termtrees.Term;
import com.tangosol.coherence.dsltools.termtrees.NodeTerm;
import com.tangosol.net.CacheFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* QueryHelper is a utility class that provides a set of factory methods
* used for building instances of {@link Filter} or
* {@link ValueExtractor}.
*
*
* The QueryHelper API accepts a String that specifies the creation of rich
* Filters in a format similar to SQL WHERE
clauses. For example,
* the String "street = 'Main' and state = 'TX'"
will create a
* tree of Filters similar to the following Java code:
*
*
*
* new AndFilter(
* new EqualsFilter("getStreet","Main"),
* new EqualsFilter("getState","TX"));
*
*
*
* The following keywords are currently supported (words between brackets
* are optional):
*
* - Comparison operators:
=, >, >=, <, <=, <> [ NOT ] BETWEEN,
* [ NOT ] LIKE, [ NOT ] IN, IS [ NOT ] NULL , CONTAINS [ ALL | ANY ]
* - Logical operators:
(AND, OR, NOT)
* - Literal numbers, and the constants
true, false
, and
* null
*
*
* Each argument to an operator is converted into a
* {@link com.tangosol.util.extractor.ReflectionExtractor}. Additionally,
* the "."
operator will use
* {@link com.tangosol.util.extractor.ChainedExtractor}. Pseudo functions
* key()
and value()
may be used to specify the use
* of a key as in "key() between 10 and 50"
. The
* value()
pseudo function is a shorthand for
* {@link com.tangosol.util.extractor.IdentityExtractor}.
*
*
* Query bind variables are supported in two forms. One form is a
* "?"
followed by a position number; for example:
* "dept = ?1 and serviceCode in [10,20,30]"
. For this usage,
* supply an Object array of parameters to
* {@link #createFilter(String, Object[])}. Note: this scheme
* treats 1 as the starting index into the array.
*
*
* Additionally, named bind parameters are supported. The above example could
* be: "dept = :deptNum and serviceCode in :myList"
.
* This style requires the use of a Map with
* {@link #createFilter(String, Map)}. Both forms can be used in the
* same specification.
*
*
* The factory methods catch a number of Exceptions from the implementation
* stages and subsequently may throw an unchecked
* {@link FilterBuildingException}.
*
* @author djl 2009.9.3
*/
public class QueryHelper
{
// ----- FilterBuilder API ----------------------------------------------
/**
* Make a new Filter from the given String.
*
* @param sWhereClause a String in the Coherence Query Language
* representing a Filter
*
* @return the constructed Filter
*
* @throws FilterBuildingException may be thrown
*/
public static Filter createFilter(String sWhereClause)
{
return createFilter(sWhereClause, new Object[0], new HashMap(), f_language);
}
/**
* Make a new Filter from the given String.
*
* @param sWhereClause a String in the Coherence Query Language
* representing a Filter
* @param aBindings the array of Objects to use for Bind variables
*
* @return the constructed Filter
*
* @throws FilterBuildingException may be thrown
*/
public static Filter createFilter(String sWhereClause, Object[] aBindings)
{
return createFilter(sWhereClause, aBindings, new HashMap(), f_language);
}
/**
* Make a new Filter from the given String.
*
* @param sWhereClause a String in the Coherence Query Language
* representing a Filter
* @param mapBindings the Map of Objects to use for Bind variables
*
* @return the constructed Filter
*
* @throws FilterBuildingException may be thrown
*/
public static Filter createFilter(String sWhereClause, Map mapBindings)
{
return createFilter(sWhereClause, new Object[0], mapBindings, f_language);
}
/**
* Make a new Filter from the given String.
*
* @param sWhereClause a String in the Coherence Query Language
* representing a Filter
* @param aBindings the array of Objects to use for Bind variables
* @param mapBindings the Map of Objects to use for Bind variables
*
* @return the constructed Filter
*
* @throws FilterBuildingException may be thrown
*/
public static Filter createFilter(String sWhereClause, Object[] aBindings, Map mapBindings)
{
return createFilter(sWhereClause, aBindings, mapBindings, f_language);
}
/**
* Make a new Filter from the given String.
*
* @param sWhereClause a String in the Coherence Query Language
* representing a Filter
* @param aBindings the array of Objects to use for indexed Bind variables
* @param mapBindings the Map of Objects to use for named Bind variables
* @param language the CoherenceQueryLanguage instance to use
*
* @return the constructed Filter
*
* @throws FilterBuildingException may be thrown
*/
public static Filter createFilter(String sWhereClause, Object[] aBindings,
Map mapBindings, CoherenceQueryLanguage language)
{
try
{
FilterBuilder filterBuilder = new FilterBuilder(
aBindings == null ? Collections.emptyList() : Arrays.asList(aBindings),
new ResolvableParameterList(mapBindings), language);
return filterBuilder.makeFilter(parse(sWhereClause));
}
catch (RuntimeException e)
{
throw new FilterBuildingException(e.getMessage(), sWhereClause, e);
}
}
/**
* Make a new ValueExtractor from the given String.
*
* @param s a String in the Coherence Query Language representing
* a ValueExtractor
*
* @return the constructed ValueExtractor
*
* @throws FilterBuildingException may be thrown
*/
public static ValueExtractor createExtractor(String s)
{
return createExtractor(s, f_language);
}
/**
* Make a new ValueExtractor from the given String.
*
* @param sQuery a String in the Coherence Query Language representing
* a ValueExtractor
* @param language the CoherenceQueryLanguage instance to use
*
* @return the constructed ValueExtractor
*
* @throws FilterBuildingException may be thrown
*/
public static ValueExtractor createExtractor(String sQuery, CoherenceQueryLanguage language)
{
try
{
return new FilterBuilder(language).makeExtractor((NodeTerm) parse(sQuery));
}
catch (RuntimeException e)
{
throw new FilterBuildingException(e.getMessage(), sQuery, e);
}
}
/**
* Return the {@link Term} representing the AST produced by
* parsing the specified CohQL query String.
*
* @param sQuery the CohQL query to be parsed
*
* @return the Term representing the AST produced by
* parsing the specified CohQL query String
*/
protected static Term parse(String sQuery)
{
return parse(sQuery, f_language);
}
/**
* Return the {@link Term} representing the AST produced by
* parsing the specified CohQL query String.
* This method takes a CoherenceQueryLanguage parameter which
* allows CohQL customisations to be applied to the CohQL syntax.
*
* @param sQuery the CohQL query to be parsed
* @param language the CoherenceQueryLanguage instance to use
*
* @return the Term representing the AST produced by
* parsing the specified CohQL query String
*/
protected static Term parse(String sQuery, CoherenceQueryLanguage language)
{
OPParser parser = new OPParser(sQuery, language.filtersTokenTable(), language.getOperators());
return parser.parse();
}
/**
* Execute a CohQL statement. This method accepts a complete query
* string as the argument. The type of object returned depends on the query:
*
* Examples on CohQL
*
* Return Type
* Query Description
*
*
* Cache entry value
* If the statement is an INSERT
operation
* the previous entry for the given key will be returned; otherwise null
*
*
* {@link java.lang.Number}
* If the query is an aggregation that returns a single numerical
* value; for example: count()
, avg()
,
* max()
, min()
*
*
* {@link java.util.Map}
* If query has a grouping
*
*
* {@link java.util.Collection}
* For all other SELECT
, DELETE
,
* UPDATE
statements
*
*
* null
* If the query returns no results or for
* create/delete
index or drop/create
cache,
* or backup/restore
*
*
*
* @param sStatement a Coherence Query Language statement
*
* @return the query results
*
* @throws RuntimeException if an invalid query is provided
*/
public static Object executeStatement(String sStatement)
{
PrintWriter out = new PrintWriter(System.out);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
ExecutionContext ctx = new ExecutionContext();
ctx.setWriter(out);
ctx.setReader(in);
ctx.setSilentMode(true);
ctx.setSanityCheckingEnabled(true);
ctx.setCoherenceQueryLanguage(f_language);
ctx.setCacheFactory(CacheFactory.getConfigurableCacheFactory());
ctx.setCluster(CacheFactory.ensureCluster());
return executeStatement(sStatement, ctx);
}
/**
* Execute a CohQL statement. This method accepts a complete query
* string as the argument. The type of object returned depends on the query:
*
* Query return types
*
* Return Type
* Query Description
*
*
* Cache entry value
* If the statement is an INSERT
operation
* the previous entry for the given key will be returned; otherwise null
*
*
* {@link java.lang.Number}
* If the query is an aggregation that returns a single numerical
* value; for example: count()
, avg()
,
* max()
, min()
*
*
* {@link java.util.Map}
* If query has a grouping
*
*
* {@link java.util.Collection}
* For all other SELECT
, DELETE
,
* UPDATE
statements
*
*
* null
* If the query returns no results or for
* create/delete
index or drop/create
cache,
* or backup/restore
*
*
*
* @param sStatement a Coherence Query Language statement
* @param context the {@link ExecutionContext} to use
*
* @return the query results
*
* @throws RuntimeException if an invalid query is provided
*/
public static Object executeStatement(String sStatement, ExecutionContext context)
{
if (sStatement == null || sStatement.length() == 0)
{
return null;
}
CoherenceQueryLanguage language = context.getCoherenceQueryLanguage();
TokenTable toks = language.extendedSqlTokenTable();
OPParser parser = new OPParser(sStatement, toks, language.getOperators());
Term term = parser.parse();
Statement statement = language.prepareStatement((NodeTerm) term, context, null, null);
if (context.isSanityChecking())
{
statement.sanityCheck(context);
}
StatementResult result = statement.execute(context);
return result.getResult();
}
/**
* The default {@link CoherenceQueryLanguage} used by this QueryHelper when no language
* is provided to methods.
*/
protected static final CoherenceQueryLanguage f_language = new CoherenceQueryLanguage();
}