use of org.z3950.zing.cql.Modifier in project raml-module-builder by folio-org.
the class CQL2PgJSON method queryByLike.
/**
* Create an SQL expression using LIKE query syntax.
*
* @param hasIndex
* @param vals
* @param node
* @param comparator
* @param modifiers
* @return
*/
private String queryByLike(String index, DbIndex dbIndex, IndexTextAndJsonValues vals, CQLTermNode node, String comparator, CqlModifiers modifiers, Table targetTable) throws QueryValidationException {
final String indexText = vals.getIndexText();
final Index schemaIndex = ObjectUtils.firstNonNull(dbIndex.getGinIndex(), dbIndex.getLikeIndex(), dbIndex.getUniqueIndex(), dbIndex.getIndex());
String sql = null;
List<Modifier> relationModifiers = modifiers.getRelationModifiers();
if (!relationModifiers.isEmpty()) {
sql = arrayNode(index, node, modifiers, relationModifiers, schemaIndex, vals, targetTable);
} else {
String likeOperator = comparator.equals("<>") ? "NOT LIKE" : "LIKE";
String term = "'" + Cql2SqlUtil.cql2like(node.getTerm()) + "'";
String indexMod;
if (schemaIndex != null && schemaIndex.getMultiFieldNames() != null) {
indexMod = schemaIndex.getFinalSqlExpression(targetTable.getTableName());
} else if (schemaIndex != null && schemaIndex.getSqlExpression() != null) {
indexMod = schemaIndex.getSqlExpression();
} else {
indexMod = wrapIndexExpression(indexText, schemaIndex);
}
if (schemaIndex != null && schemaIndex == dbIndex.getIndex()) {
sql = createLikeLengthCase(comparator, indexMod, schemaIndex, likeOperator, term);
} else {
sql = indexMod + " " + likeOperator + " " + wrapQueryExpression(term, schemaIndex);
}
}
if (Cql2SqlUtil.hasCqlWildCard(node.getTerm())) {
// FIXME: right truncation "abc*" works with index/uniqueIndex
if (!dbIndex.hasGinIndex() && !dbIndex.hasLikeIndex()) {
String s = String.format("%s, CQL >>> SQL: %s >>> %s", indexText, node.toCQL(), sql);
logger.log(Level.WARNING, "Doing wildcard LIKE search without index for {0}", s);
}
} else {
if (schemaIndex == null) {
String s = String.format("%s, CQL >>> SQL: %s >>> %s", indexText, node.toCQL(), sql);
logger.log(Level.WARNING, "Doing LIKE search without index for {0}", s);
}
}
logger.log(Level.FINE, "index {0} generated SQL {1}", new Object[] { indexText, sql });
return sql;
}
use of org.z3950.zing.cql.Modifier in project raml-module-builder by folio-org.
the class CQL2PgJSON method arrayNode.
private String arrayNode(String index, CQLTermNode node, CqlModifiers modifiers, List<Modifier> relationModifiers, Index schemaIndex, IndexTextAndJsonValues incomingvals, Table targetTable) throws QueryValidationException {
StringBuilder sqlAnd = new StringBuilder();
StringBuilder sqlOr = new StringBuilder();
// avoid recursion
modifiers.setRelationModifiers(new LinkedList<>());
for (Modifier relationModifier : relationModifiers) {
final String modifierName = relationModifier.getType().substring(1);
final String modifierValue = relationModifier.getValue();
String foundModifier = lookupModifier(schemaIndex, modifierName);
if (foundModifier == null) {
throw new QueryValidationException("CQL: Unsupported relation modifier " + relationModifier.getType());
}
if (modifierValue == null) {
if (sqlOr.length() == 0) {
sqlOr.append("(");
} else {
sqlOr.append(" or ");
}
IndexTextAndJsonValues vals = new IndexTextAndJsonValues();
vals.setIndexText(SqlUtil.Cql2PgUtil.cqlNameAsSqlText("t.c", foundModifier));
sqlOr.append(indexNode(index, this.dbTable, node, vals, modifiers));
} else {
final String comparator = relationModifier.getComparison();
if (!"=".equals(comparator)) {
throw new QueryValidationException("CQL: Unsupported comparison for relation modifier " + relationModifier.getType());
}
sqlAnd.append(" and ");
sqlAnd.append(queryByFt(SqlUtil.Cql2PgUtil.cqlNameAsSqlText("t.c", foundModifier), modifierValue, comparator, schemaIndex, targetTable));
}
}
if (sqlOr.length() > 0) {
sqlOr.append(")");
} else {
String modifiersSubfield = null;
if (schemaIndex != null) {
modifiersSubfield = schemaIndex.getArraySubfield();
}
if (modifiersSubfield == null) {
throw new QueryValidationException("CQL: No arraySubfield defined for index " + index);
}
IndexTextAndJsonValues vals = new IndexTextAndJsonValues();
vals.setIndexText(SqlUtil.Cql2PgUtil.cqlNameAsSqlText("t.c", modifiersSubfield));
sqlOr.append(indexNode(index, this.dbTable, node, vals, modifiers));
}
return "id in (select t.id" + " from (select id as id, " + " jsonb_array_elements(" + incomingvals.getIndexJson() + ") as c" + " ) as t" + " where " + sqlOr.toString() + sqlAnd.toString() + ")";
}
use of org.z3950.zing.cql.Modifier in project okapi by folio-org.
the class CQLUtil method reduceBoolean.
private static CQLNode reduceBoolean(CQLBooleanNode n1, CQLTermNode tn, Comparator<CQLTermNode> cmp) {
CQLNode n2 = null;
CQLNode left = reducer(n1.getLeftOperand(), tn, cmp);
CQLNode right = reducer(n1.getRightOperand(), tn, cmp);
ModifierSet mSet = new ModifierSet(n1.getOperator().toString().toLowerCase());
List<Modifier> mods = n1.getModifiers();
for (Modifier m : mods) {
mSet.addModifier(m.getType(), m.getComparison(), m.getValue());
}
if (left == null) {
n2 = right;
} else if (right == null) {
n2 = left;
}
switch(n1.getOperator()) {
case AND:
if (left != null && right != null) {
n2 = new CQLAndNode(left, right, mSet);
}
break;
case OR:
if (left != null && right != null) {
n2 = new CQLOrNode(left, right, mSet);
}
break;
case NOT:
if (left != null && right != null) {
n2 = new CQLNotNode(left, right, mSet);
}
break;
case PROX:
if (left != null && right != null) {
n2 = new CQLProxNode(left, right, mSet);
}
break;
}
return n2;
}
use of org.z3950.zing.cql.Modifier in project raml-module-builder by folio-org.
the class CQL2PgJSON method queryByFt.
/**
* Create an SQL expression using Full Text query syntax.
*
* @param hasIndex
* @param vals
* @param node
* @param comparator
* @param modifiers
* @return
* @throws QueryValidationException
*/
private String queryByFt(String index, DbIndex dbIndex, IndexTextAndJsonValues vals, CQLTermNode node, String comparator, CqlModifiers modifiers, Table targetTable) throws QueryValidationException {
final String indexText = vals.getIndexText();
if (CqlAccents.RESPECT_ACCENTS == modifiers.getCqlAccents()) {
logger.log(Level.WARNING, "Ignoring /respectAccents modifier for FT search {0}", indexText);
}
if (CqlCase.RESPECT_CASE == modifiers.getCqlCase()) {
logger.log(Level.WARNING, "Ignoring /respectCase modifier for FT search {0}", indexText);
}
// Clean the term. Remove stand-alone ' *', not valid word.
String term = node.getTerm().replaceAll(" +\\*", "").trim();
Index schemaIndex = null;
if (targetTable != null) {
schemaIndex = DbSchemaUtils.getIndex(index, targetTable.getFullTextIndex());
}
String sql = queryByFt(indexText, term, comparator, schemaIndex, targetTable);
// array modifier
List<Modifier> relationModifiers = modifiers.getRelationModifiers();
if (!relationModifiers.isEmpty()) {
sql += " AND " + arrayNode(index, node, modifiers, relationModifiers, schemaIndex, vals, targetTable);
}
if (schemaIndex != null && schemaIndex.isCaseSensitive()) {
throw new CQLFeatureUnsupportedException("full text index does not support case sensitive: " + index);
}
if (!dbIndex.hasFullTextIndex() && !"true".equals(sql)) {
String s = String.format("%s, CQL >>> SQL: %s >>> %s", indexText, node.toCQL(), sql);
logger.log(Level.WARNING, "Doing FT search without index for {0}", s);
}
return sql;
}
Aggregations