@Override public Reference transform(Reference node) { if (!inProjection) { return node; } String name = node.name; String newName = map.getOrDefault(name, name); Reference newReference = new Reference(newName, node.cast, node.esHint); if (newReference.originalName == null) { newReference.originalName = name; } newReference.info = node.info; return newReference; } }
protected void processReference(Reference node) { String prefix = getCorrelatedWildcardPrefix(node.name); int count = prefix.isEmpty() ? 0 : 1; node.setInfo(new PrefixInfo(prefix, count)); }
protected void processExpression(Expression node, List<? extends Operand> operands) { PrefixInfo commonInfo = null; for (Operand operand : operands) { // find longest prefix for the operand PrefixInfo info; if (operand instanceof Reference) { Reference reference = (Reference) operand; info = (PrefixInfo) reference.getInfo(); } else if (operand instanceof Expression) { Expression expression = (Expression) operand; info = (PrefixInfo) expression.getInfo(); } else { info = null; } if (info != null) { if (commonInfo == null) { commonInfo = info; } else if (commonInfo.prefix.equals(info.prefix)) { commonInfo = new PrefixInfo(commonInfo.prefix, commonInfo.count + info.count); } else { commonInfo = PrefixInfo.EMPTY; } } } node.setInfo(commonInfo); } }
@Override public void visitFunction(Function node) { String func = node.name.toUpperCase(); Reference ref = (Reference) node.args.get(0); ref.accept(this); // whatColumns / whatKeys for column // replace column info with aggregate Column col = whatColumns.removeLast(); String key = whatKeys.removeLast(); final String aggFQN = func + "(" + col.getFullQuotedName() + ")"; final ColumnType aggType = getAggregateType(func, col.getType()); final int aggJdbcType = dialect.getJDBCTypeAndString(aggType).jdbcType; Column cc = new Column(col, col.getTable()) { private static final long serialVersionUID = 1L; @Override public String getFullQuotedName() { return aggFQN; } @Override public ColumnType getType() { return aggType; } @Override public int getJdbcType() { return aggJdbcType; } }; whatColumns.add(cc); whatKeys.add(func + "(" + key + ")"); }
@Override public Reference transform(Reference node) { String name = node.name; String newName = map.getOrDefault(name, name); if (newName.equals(name)) { return node; } else { return new Reference(newName, node.cast, node.esHint); } } }
protected SQLQuery addIsNotNullClauses(SQLQuery query, Collection<String> names) { List<Predicate> values = names.stream() .map(name -> new Predicate(new Reference(name), Operator.ISNOTNULL, null)) .collect(toList()); Predicate expr = new Predicate(query.where.predicate, Operator.AND, new MultiExpression(Operator.AND, values)); return query.withPredicate(expr); }
protected void addFacetFilters(List<Predicate> clauses, FacetFilter facetFilter) { if (facetFilter == null) { return; } for (String mixin : facetFilter.required) { // every facet is required, not just any of them, // so do them one by one Predicate expr = new Predicate(new Reference(NXQL.ECM_MIXINTYPE), Operator.EQ, new StringLiteral(mixin)); clauses.add(expr); } if (!facetFilter.excluded.isEmpty()) { LiteralList list = new LiteralList(); for (String mixin : facetFilter.excluded) { list.add(new StringLiteral(mixin)); } Predicate expr = new Predicate(new Reference(NXQL.ECM_MIXINTYPE), Operator.NOTIN, list); clauses.add(expr); } }
protected Boolean walkStartsWithPath(String path) { // resolve path String ancestorId = pathResolver.getIdForPath(path); // don't return early on null ancestorId, we want to walk all references deterministically Object[] ancestorIds = (Object[]) walkReference(new Reference(NXQL_ECM_ANCESTOR_IDS)); if (ancestorId == null) { // no such path return FALSE; } if (ancestorIds == null) { // placeless return FALSE; } for (Object id : ancestorIds) { if (ancestorId.equals(id)) { return TRUE; } } return FALSE; }
public void addFacetFilterClauses(FacetFilter facetFilter) { for (String mixin : facetFilter.required) { // every facet is required, not just any of them, // so do them one by one // expr = getMixinsMatchExpression(Collections.singleton(facet), // true); Predicate predicate = new Predicate(new Reference(NXQL.ECM_MIXINTYPE), Operator.EQ, new StringLiteral(mixin)); toplevelPredicates.add(predicate); } if (!facetFilter.excluded.isEmpty()) { // expr = getMixinsMatchExpression(facetFilter.excluded, false); LiteralList list = new LiteralList(); for (String mixin : facetFilter.excluded) { list.add(new StringLiteral(mixin)); } Predicate predicate = new Predicate(new Reference(NXQL.ECM_MIXINTYPE), Operator.NOTIN, list); toplevelPredicates.add(predicate); } }
/** * Finds all the types to take into account (all concrete types being a subtype of the passed types) based on the * FROM list. * <p> * Adds them as a ecm:primaryType match in the toplevel operands. */ protected void addTypes(List<Predicate> clauses, FromClause node) { onlyRelations = true; Set<String> fromTypes = new HashSet<>(); FromList elements = node.elements; for (String typeName : elements.values()) { if (TYPE_DOCUMENT.equalsIgnoreCase(typeName)) { typeName = TYPE_DOCUMENT; } fromTypes.addAll(getDocumentTypeNamesExtending(typeName)); boolean isRelation = isTypeRelation(typeName); onlyRelations = onlyRelations && isRelation; } fromTypes.remove(TYPE_ROOT); LiteralList list = new LiteralList(); for (String type : fromTypes) { list.add(new StringLiteral(type)); } clauses.add(new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.IN, list)); }
protected Document walkIsTrashed(Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.NOTEQ) { throw new QueryParseException(NXQL.ECM_ISTRASHED + " requires = or <> operator"); } TrashService trashService = Framework.getService(TrashService.class); if (trashService.hasFeature(TRASHED_STATE_IS_DEDUCED_FROM_LIFECYCLE)) { return walkIsTrashed(new Reference(NXQL.ECM_LIFECYCLESTATE), op, rvalue, new StringLiteral(LifeCycleConstants.DELETED_STATE)); } else if (trashService.hasFeature(TRASHED_STATE_IN_MIGRATION)) { Document lifeCycleTrashed = walkIsTrashed(new Reference(NXQL.ECM_LIFECYCLESTATE), op, rvalue, new StringLiteral(LifeCycleConstants.DELETED_STATE)); Document propertyTrashed = walkIsTrashed(new Reference(NXQL.ECM_ISTRASHED), op, rvalue, new BooleanLiteral(true)); return new Document(QueryOperators.OR, new ArrayList<>(Arrays.asList(lifeCycleTrashed, propertyTrashed))); } else if (trashService.hasFeature(TRASHED_STATE_IS_DEDICATED_PROPERTY)) { return walkIsTrashed(new Reference(NXQL.ECM_ISTRASHED), op, rvalue, new BooleanLiteral(true)); } else { throw new UnsupportedOperationException("TrashService is in an unknown state"); } }
protected Boolean walkAncestorId(Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.NOTEQ) { throw new QueryParseException(NXQL.ECM_ANCESTORID + " requires = or <> operator"); } if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException(NXQL.ECM_ANCESTORID + " requires literal id as right argument"); } String ancestorId = ((StringLiteral) rvalue).value; Object[] ancestorIds = (Object[]) walkReference(new Reference(NXQL_ECM_ANCESTOR_IDS)); boolean eq = op == Operator.EQ ? true : false; if (ancestorIds == null) { // placeless return eq ? FALSE : TRUE; } for (Object id : ancestorIds) { if (ancestorId.equals(id)) { return eq ? TRUE : FALSE; } } return eq ? FALSE : TRUE; }
protected Boolean walkEcmFulltext(String name, Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.LIKE) { throw new QueryParseException(NXQL.ECM_FULLTEXT + " requires = or LIKE operator"); } if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException(NXQL.ECM_FULLTEXT + " requires literal string as right argument"); } if (fulltextSearchDisabled) { throw new QueryParseException("Fulltext search disabled by configuration"); } String query = ((StringLiteral) rvalue).value; if (name.equals(NXQL.ECM_FULLTEXT)) { // standard fulltext query hasFulltext = true; String simple = (String) walkReference(new Reference(NXQL_ECM_FULLTEXT_SIMPLE)); String binary = (String) walkReference(new Reference(NXQL_ECM_FULLTEXT_BINARY)); return fulltext(simple, binary, query); } else { // secondary index match with explicit field // do a regexp on the field if (name.charAt(NXQL.ECM_FULLTEXT.length()) != '.') { throw new QueryParseException(name + " has incorrect syntax for a secondary fulltext index"); } String prop = name.substring(NXQL.ECM_FULLTEXT.length() + 1); String ft = query.replace(" ", "%"); rvalue = new StringLiteral(ft); return walkLike(new Reference(prop), rvalue, true, true); } }
if (primaryTypes.size() == 1) { String pt = primaryTypes.iterator().next(); predicate = new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.EQ, new StringLiteral(pt)); } else { // primaryTypes.size() > 1 LiteralList list = new LiteralList(); list.add(new StringLiteral(pt)); predicate = new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.IN, list);
if (primaryTypes.size() == 1) { String pt = primaryTypes.iterator().next(); predicate = new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.EQ, new StringLiteral(pt)); } else { // primaryTypes.size() > 1 LiteralList list = new LiteralList(); list.add(new StringLiteral(pt)); predicate = new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.IN, list);
protected Boolean walkEcmPath(Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.NOTEQ) { throw new QueryParseException(NXQL.ECM_PATH + " requires = or <> operator"); } if (!(rvalue instanceof StringLiteral)) { throw new QueryParseException(NXQL.ECM_PATH + " requires literal path as right argument"); } String path = ((StringLiteral) rvalue).value; if (path.length() > 1 && path.endsWith("/")) { path = path.substring(0, path.length() - 1); } String id = pathResolver.getIdForPath(path); Object right = walkReference(new Reference(NXQL.ECM_UUID)); if (id == null) { return FALSE; } Boolean eq = eq(id, right); return op == Operator.EQ ? eq : not(eq); }
protected void visitExpressionIsTrashedOnLifeCycle(Expression node) { String name = ((Reference) node.lvalue).name; boolean bool = getBooleanRValue(name, node); Operator op = bool ? Operator.EQ : Operator.NOTEQ; visitReference(new Reference(NXQL.ECM_LIFECYCLESTATE)); visitOperator(op); visitStringLiteral(LifeCycleConstants.DELETED_STATE); }
list.add(new StringLiteral(type)); toplevelPredicates.add(new Predicate(new Reference(NXQL.ECM_PRIMARYTYPE), Operator.IN, list));
protected Boolean walkIsTrashed(Operator op, Operand rvalue) { if (op != Operator.EQ && op != Operator.NOTEQ) { throw new QueryParseException(NXQL.ECM_ISTRASHED + " requires = or <> operator"); } TrashService trashService = Framework.getService(TrashService.class); if (trashService.hasFeature(TRASHED_STATE_IS_DEDUCED_FROM_LIFECYCLE)) { return walkIsTrashed(new Reference(NXQL.ECM_LIFECYCLESTATE), op, rvalue, new StringLiteral(LifeCycleConstants.DELETED_STATE)); } else if (trashService.hasFeature(TRASHED_STATE_IN_MIGRATION)) { Boolean lifeCycleTrashed = walkIsTrashed(new Reference(NXQL.ECM_LIFECYCLESTATE), op, rvalue, new StringLiteral(LifeCycleConstants.DELETED_STATE)); Boolean propertyTrashed = walkIsTrashed(new Reference(NXQL.ECM_ISTRASHED), op, rvalue, new IntegerLiteral(1L)); return or(lifeCycleTrashed, propertyTrashed); } else if (trashService.hasFeature(TRASHED_STATE_IS_DEDICATED_PROPERTY)) { return walkIsTrashed(new Reference(NXQL.ECM_ISTRASHED), op, rvalue, new IntegerLiteral(1L)); } else { throw new UnsupportedOperationException("TrashService is in an unknown state"); } }
String ft = fulltextQuery.replace(" ", "%"); rvalue = new StringLiteral(ft); return walkLike(new Reference(prop), rvalue, true, true);