protected OrderByEvaluator<Collection<Order>, Object> compileOrderBy(OrderBy orderBy) { final LinkedHashMap<String, Boolean> orders = new LinkedHashMap<String, Boolean>(); for (OrderByElement idOrder : orderBy.getOrders()) { if (!(idOrder.getIdentifier() instanceof Field)) { throw new IllegalArgumentException("Only field identifier supported by order by operator."); } String idName = idOrder.getIdentifier().getName(); if (INSTANCE_STATUS_FIELD.equals(idName)) { if (orderBy.getOrders().size() > 1) { // TODO throw appropriate exception throw new RuntimeException( "Status field should be used alone in <order by> construction."); } orderByStatus = true; orderByStatusDesc = idOrder.getType() == OrderByType.DESC; return null; } String dbField = getDBField(idName); orders.put(dbField, idOrder.getType() == null || idOrder.getType() == OrderByType.ASC); } return new OrderByEvaluator<Collection<Order>, Object>() { public Collection<Order> evaluate(Object paramValue) { Collection<Order> hibernateOrders = new ArrayList<Order>(orders.size()); for (Map.Entry<String, Boolean> order : orders.entrySet()) { hibernateOrders.add( order.getValue() ? Order.asc(order.getKey()) : Order.desc(order.getKey())); } return hibernateOrders; } }; }
public <T> List<T> findByNamedQuery(SearchParameters sp) { if (sp == null || !sp.hasNamedQuery()) { throw new IllegalArgumentException( "searchParameters must be non null and must have a namedQuery"); } Query query = entityManager.createNamedQuery(sp.getNamedQuery()); String queryString = getQueryString(query); // append order by if needed if (queryString != null && sp.hasOrders()) { // create the sql restriction clausis StringBuilder orderClausis = new StringBuilder("order by "); boolean first = true; for (OrderBy orderBy : sp.getOrders()) { if (!first) { orderClausis.append(", "); } orderClausis.append(orderBy.getColumn()); orderClausis.append(orderBy.isOrderDesc() ? " desc" : " asc"); first = false; } if (log.isDebugEnabled()) { log.debug("appending: [" + orderClausis.toString() + "] to " + queryString); } query = recreateQuery(query, queryString + " " + orderClausis.toString()); } // pagination if (sp.getFirstResult() >= 0) { query.setFirstResult(sp.getFirstResult()); } if (sp.getMaxResults() > 0) { query.setMaxResults(sp.getMaxResults()); } // named parameters setQueryParameters(query, sp); // execute @SuppressWarnings("unchecked") List<T> result = (List<T>) query.getResultList(); if (result != null && log.isDebugEnabled()) { log.debug(sp.getNamedQuery() + " returned a List of size: " + result.size()); } return result; }
/** * please use #setOrderBy instead * * @param column * @return */ @Deprecated public SearchTemplate setOrderDesc(boolean desc) { int orderBySize = this.orderBys.size(); if (orderBySize == 0) { this.orderBys.add(new OrderBy("", desc ? DESC : ASC)); } else if (orderBySize == 1) { OrderBy orderBy = this.orderBys.get(0); this.orderBys.clear(); this.orderBys.add(new OrderBy(orderBy.getColumn(), desc ? DESC : ASC)); } else { throw new IllegalStateException("Please use addOderBy"); } return this; }
/** * please use #setOrderBy instead * * @param column * @return */ @Deprecated public SearchTemplate setOrderBy(String column) { int orderBySize = this.orderBys.size(); if (orderBySize == 0) { this.orderBys.add(new OrderBy(column)); } else if (orderBySize == 1) { OrderBy orderBy = this.orderBys.get(0); this.orderBys.clear(); this.orderBys.add(new OrderBy(column, orderBy.getDirection())); } else { throw new IllegalStateException("Please use addOderBy"); } return this; }
@Override public StorageResults visit(OrderBy orderBy) { TypedExpression field = orderBy.getExpression(); if (field instanceof Field) { FieldMetadata fieldMetadata = ((Field) field).getFieldMetadata(); SortField sortField = new SortField( fieldMetadata.getName(), getSortType(fieldMetadata), orderBy.getDirection() == OrderBy.Direction.DESC); query.setSort(new Sort(sortField)); return null; } else { throw new NotImplementedException( "No support for order by for full text search on non-field."); } }
private static String getSelectString(final Class<?> klass, final SelectFrom from) { final String columnString = getColumnString(klass); final String fromString = getFromString(klass, from); final String selectString = String.format("SELECT %s FROM (%s)", columnString, fromString); final StringBuilder selectBuilder = new StringBuilder(); selectBuilder.append(selectString); final GroupBy groupBy = klass.getAnnotation(GroupBy.class); if (groupBy != null) { selectBuilder.append(String.format(" GROUP BY %s", groupBy.value())); } final OrderBy orderBy = klass.getAnnotation(OrderBy.class); if (orderBy != null) { selectBuilder.append(String.format(" ORDER BY %s", orderBy.value())); } return selectBuilder.toString(); }
@SuppressWarnings("rawtypes") public static List<Object> performSearch( Condition where, OrderBy orderby, String cacheName, InfinispanConnection conn) throws TranslatorException { QueryBuilder qb = getQueryBuilder(cacheName, conn); if (orderby != null) { List<SortSpecification> sss = orderby.getSortSpecifications(); for (SortSpecification spec : sss) { Expression exp = spec.getExpression(); Column mdIDElement = ((ColumnReference) exp).getMetadataObject(); SortOrder so = SortOrder.ASC; if (spec.getOrdering().name().equalsIgnoreCase(SortOrder.DESC.name())) { so = SortOrder.DESC; } qb = qb.orderBy(mdIDElement.getSourceName(), so); } } FilterConditionContext fcc = buildQueryFromWhereClause(where, qb, null); List<Object> results = null; Query query = null; if (fcc != null) { query = fcc.toBuilder().build(); results = query.list(); if (results == null) { return Collections.emptyList(); } } else if (orderby != null) { query = qb.build(); results = query.list(); if (results == null) { return Collections.emptyList(); } } else { results = new ArrayList<Object>(); RemoteCache<?, Object> c = (RemoteCache<?, Object>) conn.getCache(); for (Object id : c.keySet()) { results.add(c.get(id)); } } return results; }
protected RelationalNode convertNode(PlanNode node) throws TeiidComponentException, TeiidProcessingException { RelationalNode processNode = null; switch (node.getType()) { case NodeConstants.Types.PROJECT: GroupSymbol intoGroup = (GroupSymbol) node.getProperty(NodeConstants.Info.INTO_GROUP); if (intoGroup != null) { try { Insert insert = (Insert) node.getFirstChild().getProperty(Info.VIRTUAL_COMMAND); List<ElementSymbol> allIntoElements = insert.getVariables(); Object groupID = intoGroup.getMetadataID(); Object modelID = metadata.getModelID(groupID); String modelName = metadata.getFullName(modelID); if (metadata.isVirtualGroup(groupID)) { InsertPlanExecutionNode ipen = new InsertPlanExecutionNode(getID(), metadata); ipen.setProcessorPlan( (ProcessorPlan) node.getFirstChild().getProperty(Info.PROCESSOR_PLAN)); ipen.setReferences(insert.getValues()); processNode = ipen; } else { ProjectIntoNode pinode = new ProjectIntoNode(getID()); pinode.setIntoGroup(intoGroup); pinode.setIntoElements(allIntoElements); pinode.setModelName(modelName); pinode.setConstraint((Criteria) node.getProperty(Info.CONSTRAINT)); processNode = pinode; SourceCapabilities caps = capFinder.findCapabilities(modelName); if (caps.supportsCapability(Capability.INSERT_WITH_ITERATOR)) { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.ITERATOR); } else if (caps.supportsCapability(Capability.BATCHED_UPDATES)) { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.BATCH); } else { pinode.setMode(org.teiid.query.processor.relational.ProjectIntoNode.Mode.SINGLE); } } } catch (QueryMetadataException e) { throw new TeiidComponentException(QueryPlugin.Event.TEIID30247, e); } } else { List<Expression> symbols = (List) node.getProperty(NodeConstants.Info.PROJECT_COLS); ProjectNode pnode = new ProjectNode(getID()); pnode.setSelectSymbols(symbols); processNode = pnode; if (node.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) { WindowFunctionProjectNode wfpn = new WindowFunctionProjectNode(getID()); // with partial projection the window function may already be pushed, we'll check for // that here ArrayList<Expression> filtered = new ArrayList<Expression>(); List<Expression> childSymbols = (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS); for (Expression ex : symbols) { ex = SymbolMap.getExpression(ex); if (childSymbols.contains(ex)) { continue; } filtered.add(ex); } Set<WindowFunction> windowFunctions = RuleAssignOutputElements.getWindowFunctions(filtered); if (!windowFunctions.isEmpty()) { // TODO: check for selecting all window functions List<Expression> outputElements = new ArrayList<Expression>(windowFunctions); // collect the other projected expressions for (Expression singleElementSymbol : (List<Expression>) node.getFirstChild().getProperty(Info.OUTPUT_COLS)) { outputElements.add(singleElementSymbol); } wfpn.setElements(outputElements); wfpn.init(); pnode.addChild(wfpn); } } } break; case NodeConstants.Types.JOIN: JoinType jtype = (JoinType) node.getProperty(NodeConstants.Info.JOIN_TYPE); JoinStrategyType stype = (JoinStrategyType) node.getProperty(NodeConstants.Info.JOIN_STRATEGY); JoinNode jnode = new JoinNode(getID()); jnode.setJoinType(jtype); jnode.setLeftDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_LEFT_DISTINCT)); jnode.setRightDistinct(node.hasBooleanProperty(NodeConstants.Info.IS_RIGHT_DISTINCT)); List joinCrits = (List) node.getProperty(NodeConstants.Info.JOIN_CRITERIA); String depValueSource = (String) node.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE); SortOption leftSort = (SortOption) node.getProperty(NodeConstants.Info.SORT_LEFT); if (stype == JoinStrategyType.MERGE || stype == JoinStrategyType.ENHANCED_SORT) { MergeJoinStrategy mjStrategy = null; if (stype.equals(JoinStrategyType.ENHANCED_SORT)) { EnhancedSortMergeJoinStrategy esmjStrategy = new EnhancedSortMergeJoinStrategy( leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT)); esmjStrategy.setSemiDep(node.hasBooleanProperty(Info.IS_SEMI_DEP)); mjStrategy = esmjStrategy; } else { mjStrategy = new MergeJoinStrategy( leftSort, (SortOption) node.getProperty(NodeConstants.Info.SORT_RIGHT), false); } jnode.setJoinStrategy(mjStrategy); List leftExpressions = (List) node.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS); List rightExpressions = (List) node.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS); jnode.setJoinExpressions(leftExpressions, rightExpressions); joinCrits = (List) node.getProperty(NodeConstants.Info.NON_EQUI_JOIN_CRITERIA); } else if (stype == JoinStrategyType.NESTED_TABLE) { NestedTableJoinStrategy ntjStrategy = new NestedTableJoinStrategy(); jnode.setJoinStrategy(ntjStrategy); SymbolMap references = (SymbolMap) node.getProperty(Info.LEFT_NESTED_REFERENCES); ntjStrategy.setLeftMap(references); references = (SymbolMap) node.getProperty(Info.RIGHT_NESTED_REFERENCES); ntjStrategy.setRightMap(references); } else { NestedLoopJoinStrategy nljStrategy = new NestedLoopJoinStrategy(); jnode.setJoinStrategy(nljStrategy); } Criteria joinCrit = Criteria.combineCriteria(joinCrits); jnode.setJoinCriteria(joinCrit); processNode = jnode; jnode.setDependentValueSource(depValueSource); break; case NodeConstants.Types.ACCESS: ProcessorPlan plan = (ProcessorPlan) node.getProperty(NodeConstants.Info.PROCESSOR_PLAN); if (plan != null) { PlanExecutionNode peNode = null; Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA); if (crit != null) { List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS); List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS); peNode = new DependentProcedureExecutionNode(getID(), crit, references, defaults); } else { peNode = new PlanExecutionNode(getID()); } peNode.setProcessorPlan(plan); processNode = peNode; } else { AccessNode aNode = null; Command command = (Command) node.getProperty(NodeConstants.Info.ATOMIC_REQUEST); Object modelID = node.getProperty(NodeConstants.Info.MODEL_ID); if (modelID != null) { String fullName = metadata.getFullName(modelID); if (!capFinder.isValid(fullName)) { // TODO: we ideally want to handle the partial resutls case here differently // by adding a null node / and a source warning // for now it's just as easy to say that the user needs to take steps to // return static capabilities SourceCapabilities caps = capFinder.findCapabilities(fullName); Exception cause = null; if (caps != null) { cause = (Exception) caps.getSourceProperty(Capability.INVALID_EXCEPTION); } throw new QueryPlannerException( QueryPlugin.Event.TEIID30498, cause, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30498, fullName)); } } EvaluatableVisitor ev = null; if (node.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) { if (command instanceof StoredProcedure) { List references = (List) node.getProperty(NodeConstants.Info.PROCEDURE_INPUTS); List defaults = (List) node.getProperty(NodeConstants.Info.PROCEDURE_DEFAULTS); Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.PROCEDURE_CRITERIA); DependentProcedureAccessNode depAccessNode = new DependentProcedureAccessNode(getID(), crit, references, defaults); processNode = depAccessNode; aNode = depAccessNode; } else { // create dependent access node DependentAccessNode depAccessNode = new DependentAccessNode(getID()); if (modelID != null) { depAccessNode.setPushdown( CapabilitiesUtil.supports( Capability.DEPENDENT_JOIN, modelID, metadata, capFinder)); depAccessNode.setMaxSetSize( CapabilitiesUtil.getMaxInCriteriaSize(modelID, metadata, capFinder)); depAccessNode.setMaxPredicates( CapabilitiesUtil.getMaxDependentPredicates(modelID, metadata, capFinder)); depAccessNode.setUseBindings( CapabilitiesUtil.supports( Capability.DEPENDENT_JOIN_BINDINGS, modelID, metadata, capFinder)); // TODO: allow the translator to drive this property // simplistic check of whether this query is complex to re-execute Query query = (Query) command; if (query.getGroupBy() != null || query.getFrom().getClauses().size() > 1 || !(query.getFrom().getClauses().get(0) instanceof UnaryFromClause) || query.getWith() != null) { depAccessNode.setComplexQuery(true); } else { // check to see if there in an index on at least one of the dependent sets Set<GroupSymbol> groups = new HashSet<GroupSymbol>(query.getFrom().getGroups()); boolean found = false; for (Criteria crit : Criteria.separateCriteriaByAnd(query.getCriteria())) { if (crit instanceof DependentSetCriteria) { DependentSetCriteria dsc = (DependentSetCriteria) crit; if (NewCalculateCostUtil.getKeyUsed( ElementCollectorVisitor.getElements(dsc.getExpression(), true), groups, metadata, null) != null) { found = true; break; } } } if (!found) { depAccessNode.setComplexQuery(true); } } } processNode = depAccessNode; aNode = depAccessNode; } aNode.setShouldEvaluateExpressions(true); } else { // create access node aNode = new AccessNode(getID()); processNode = aNode; } // -- special handling for system tables. currently they cannot perform projection try { if (command instanceof Query) { processNode = correctProjectionInternalTables(node, aNode); } } catch (QueryMetadataException err) { throw new TeiidComponentException(QueryPlugin.Event.TEIID30248, err); } setRoutingName(aNode, node, command); boolean shouldEval = false; if (command instanceof Insert) { Insert insert = (Insert) command; if (insert.getQueryExpression() != null) { insert.setQueryExpression( (QueryCommand) aliasCommand(aNode, insert.getQueryExpression(), modelID)); } else { for (int i = 0; i < insert.getValues().size(); i++) { Expression ex = (Expression) insert.getValues().get(i); if (!CriteriaCapabilityValidatorVisitor.canPushLanguageObject( ex, modelID, metadata, capFinder, analysisRecord)) { // replace with an expression symbol to let the rewriter know that it should be // replaced insert.getValues().set(i, new ExpressionSymbol("x", ex)); shouldEval = true; } } } } else if (command instanceof QueryCommand) { command = aliasCommand(aNode, command, modelID); } ev = EvaluatableVisitor.needsEvaluation(command, modelID, metadata, capFinder); aNode.setShouldEvaluateExpressions( ev.requiresEvaluation(EvaluationLevel.PROCESSING) || shouldEval); aNode.setCommand(command); Map<GroupSymbol, PlanNode> subPlans = (Map<GroupSymbol, PlanNode>) node.getProperty(Info.SUB_PLANS); // it makes more sense to allow the multisource affect to be elevated above just access // nodes if (aNode.getModelId() != null && metadata.isMultiSource(aNode.getModelId())) { VDBMetaData vdb = context.getVdb(); aNode.setShouldEvaluateExpressions(true); // forces a rewrite aNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS)); if (node.hasBooleanProperty(Info.IS_MULTI_SOURCE)) { Expression ex = rewriteMultiSourceCommand(aNode.getCommand()); aNode.setConnectorBindingExpression(ex); aNode.setMultiSource(true); } else { String sourceName = (String) node.getProperty(Info.SOURCE_NAME); aNode.setConnectorBindingExpression(new Constant(sourceName)); } } else if (subPlans == null) { if (!aNode.isShouldEvaluate()) { aNode.minimizeProject(command); } // check if valid to share this with other nodes if (ev != null && ev.getDeterminismLevel().compareTo(Determinism.COMMAND_DETERMINISTIC) >= 0 && command.areResultsCachable()) { checkForSharedSourceCommand(aNode); } } if (subPlans != null) { QueryCommand qc = (QueryCommand) command; if (qc.getWith() == null) { qc.setWith(new ArrayList<WithQueryCommand>(subPlans.size())); } Map<GroupSymbol, RelationalPlan> plans = new LinkedHashMap<GroupSymbol, RelationalPlan>(); for (Map.Entry<GroupSymbol, PlanNode> entry : subPlans.entrySet()) { RelationalPlan subPlan = convert(entry.getValue()); List<ElementSymbol> elems = ResolverUtil.resolveElementsInGroup(entry.getKey(), metadata); subPlan.setOutputElements(elems); plans.put(entry.getKey(), subPlan); WithQueryCommand withQueryCommand = new WithQueryCommand(entry.getKey(), elems, null); qc.getWith().add(withQueryCommand); } aNode.setSubPlans(plans); } } break; case NodeConstants.Types.SELECT: Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA); if (!node.hasCollectionProperty(Info.OUTPUT_COLS)) { // the late optimization to create a dependent join from a subquery introduces // criteria that have no output elements set // TODO that should be cleaner, but the logic currently expects to be run after join // implementation // and rerunning assign output elements seems excessive node.setProperty(Info.OUTPUT_COLS, node.getFirstChild().getProperty(Info.OUTPUT_COLS)); } SelectNode selnode = new SelectNode(getID()); selnode.setCriteria(crit); // in case the parent was a source selnode.setProjectedExpressions( (List<Expression>) node.getProperty(NodeConstants.Info.PROJECT_COLS)); processNode = selnode; break; case NodeConstants.Types.SORT: case NodeConstants.Types.DUP_REMOVE: if (node.getType() == NodeConstants.Types.DUP_REMOVE) { processNode = new DupRemoveNode(getID()); } else { SortNode sortNode = new SortNode(getID()); OrderBy orderBy = (OrderBy) node.getProperty(NodeConstants.Info.SORT_ORDER); if (orderBy != null) { sortNode.setSortElements(orderBy.getOrderByItems()); } if (node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)) { sortNode.setMode(Mode.DUP_REMOVE_SORT); } processNode = sortNode; } break; case NodeConstants.Types.GROUP: GroupingNode gnode = new GroupingNode(getID()); gnode.setRollup(node.hasBooleanProperty(Info.ROLLUP)); SymbolMap groupingMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP); gnode.setOutputMapping(groupingMap); gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)); List<Expression> gCols = (List) node.getProperty(NodeConstants.Info.GROUP_COLS); OrderBy orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER); if (orderBy == null) { if (gCols != null) { LinkedHashSet<Expression> exprs = new LinkedHashSet<Expression>(); for (Expression ex : gCols) { exprs.add(SymbolMap.getExpression(ex)); } orderBy = new OrderBy( RuleChooseJoinStrategy.createExpressionSymbols( new ArrayList<Expression>(exprs))); } } else { HashSet<Expression> seen = new HashSet<Expression>(); for (int i = 0; i < gCols.size(); i++) { if (i < orderBy.getOrderByItems().size()) { OrderByItem orderByItem = orderBy.getOrderByItems().get(i); Expression ex = SymbolMap.getExpression(orderByItem.getSymbol()); if (!seen.add(ex)) { continue; } if (ex instanceof ElementSymbol) { ex = groupingMap.getMappedExpression((ElementSymbol) ex); orderByItem.setSymbol(new ExpressionSymbol("expr", ex)); // $NON-NLS-1$ } } else { orderBy.addVariable( new ExpressionSymbol("expr", gCols.get(i)), OrderBy.ASC); // $NON-NLS-1$ } } } if (orderBy != null) { gnode.setOrderBy(orderBy.getOrderByItems()); } processNode = gnode; break; case NodeConstants.Types.SOURCE: Object source = node.getProperty(NodeConstants.Info.TABLE_FUNCTION); if (source instanceof XMLTable) { XMLTable xt = (XMLTable) source; XMLTableNode xtn = new XMLTableNode(getID()); // we handle the projection filtering once here rather than repeating the // path analysis on a per plan basis updateGroupName(node, xt); Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols()); List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS); int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols); ArrayList<XMLColumn> filteredColumns = new ArrayList<XMLColumn>(projectionIndexes.length); for (int col : projectionIndexes) { filteredColumns.add(xt.getColumns().get(col)); } xt.getXQueryExpression().useDocumentProjection(filteredColumns, analysisRecord); xtn.setProjectedColumns(filteredColumns); xtn.setTable(xt); processNode = xtn; break; } if (source instanceof ObjectTable) { ObjectTable ot = (ObjectTable) source; ObjectTableNode otn = new ObjectTableNode(getID()); // we handle the projection filtering once here rather than repeating the // path analysis on a per plan basis updateGroupName(node, ot); Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(ot.getProjectedSymbols()); List<Expression> cols = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS); int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols); ArrayList<ObjectColumn> filteredColumns = new ArrayList<ObjectColumn>(projectionIndexes.length); for (int col : projectionIndexes) { filteredColumns.add(ot.getColumns().get(col)); } otn.setProjectedColumns(filteredColumns); otn.setTable(ot); processNode = otn; break; } if (source instanceof TextTable) { TextTableNode ttn = new TextTableNode(getID()); TextTable tt = (TextTable) source; updateGroupName(node, tt); ttn.setTable(tt); processNode = ttn; break; } if (source instanceof ArrayTable) { ArrayTableNode atn = new ArrayTableNode(getID()); ArrayTable at = (ArrayTable) source; updateGroupName(node, at); atn.setTable(at); processNode = atn; break; } SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP); if (symbolMap != null) { PlanNode child = node.getLastChild(); if (child.getType() == NodeConstants.Types.PROJECT || child.getType() == NodeConstants.Types.SELECT) { // update the project cols based upon the original output child.setProperty( NodeConstants.Info.PROJECT_COLS, child.getProperty(NodeConstants.Info.OUTPUT_COLS)); } child.setProperty( NodeConstants.Info.OUTPUT_COLS, node.getProperty(NodeConstants.Info.OUTPUT_COLS)); } return null; case NodeConstants.Types.SET_OP: Operation setOp = (Operation) node.getProperty(NodeConstants.Info.SET_OPERATION); boolean useAll = ((Boolean) node.getProperty(NodeConstants.Info.USE_ALL)).booleanValue(); if (setOp == Operation.UNION) { RelationalNode unionAllNode = new UnionAllNode(getID()); if (useAll) { processNode = unionAllNode; } else { boolean onlyDupRemoval = node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL); if (onlyDupRemoval) { processNode = new DupRemoveNode(getID()); } else { SortNode sNode = new SortNode(getID()); sNode.setMode(Mode.DUP_REMOVE_SORT); processNode = sNode; } unionAllNode.setElements((List) node.getProperty(NodeConstants.Info.OUTPUT_COLS)); processNode.addChild(unionAllNode); } } else { JoinNode joinAsSet = new JoinNode(getID()); joinAsSet.setJoinStrategy( new MergeJoinStrategy(SortOption.SORT_DISTINCT, SortOption.SORT_DISTINCT, true)); // If we push these sorts, we will have to enforce null order, since nulls are equal here List leftExpressions = (List) node.getFirstChild().getProperty(NodeConstants.Info.OUTPUT_COLS); List rightExpressions = (List) node.getLastChild().getProperty(NodeConstants.Info.OUTPUT_COLS); joinAsSet.setJoinType( setOp == Operation.EXCEPT ? JoinType.JOIN_ANTI_SEMI : JoinType.JOIN_SEMI); joinAsSet.setJoinExpressions(leftExpressions, rightExpressions); processNode = joinAsSet; } break; case NodeConstants.Types.TUPLE_LIMIT: Expression rowLimit = (Expression) node.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT); Expression offset = (Expression) node.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT); LimitNode ln = new LimitNode(getID(), rowLimit, offset); ln.setImplicit(node.hasBooleanProperty(Info.IS_IMPLICIT_LIMIT)); processNode = ln; break; case NodeConstants.Types.NULL: processNode = new NullNode(getID()); break; default: throw new QueryPlannerException( QueryPlugin.Event.TEIID30250, QueryPlugin.Util.gs( QueryPlugin.Event.TEIID30250, NodeConstants.getNodeTypeString(node.getType()))); } if (processNode != null) { processNode = prepareToAdd(node, processNode); } return processNode; }
@Override public StorageResults visit(Select select) { // TMDM-4654: Checks if entity has a composite PK. Set<ComplexTypeMetadata> compositeKeyTypes = new HashSet<ComplexTypeMetadata>(); // TMDM-7496: Search should include references to reused types Collection<ComplexTypeMetadata> types = new HashSet<ComplexTypeMetadata>(select.accept(new SearchTransitiveClosure())); for (ComplexTypeMetadata type : types) { if (type.getKeyFields().size() > 1) { compositeKeyTypes.add(type); } } if (!compositeKeyTypes.isEmpty()) { StringBuilder message = new StringBuilder(); Iterator it = compositeKeyTypes.iterator(); while (it.hasNext()) { ComplexTypeMetadata compositeKeyType = (ComplexTypeMetadata) it.next(); message.append(compositeKeyType.getName()); if (it.hasNext()) { message.append(','); } } throw new FullTextQueryCompositeKeyException(message.toString()); } // Removes Joins and joined fields. List<Join> joins = select.getJoins(); if (!joins.isEmpty()) { Set<ComplexTypeMetadata> joinedTypes = new HashSet<ComplexTypeMetadata>(); for (Join join : joins) { joinedTypes.add(join.getRightField().getFieldMetadata().getContainingType()); } for (ComplexTypeMetadata joinedType : joinedTypes) { types.remove(joinedType); } List<TypedExpression> filteredFields = new LinkedList<TypedExpression>(); for (TypedExpression expression : select.getSelectedFields()) { if (expression instanceof Field) { FieldMetadata fieldMetadata = ((Field) expression).getFieldMetadata(); if (joinedTypes.contains(fieldMetadata.getContainingType())) { TypeMapping mapping = mappings.getMappingFromDatabase(fieldMetadata.getContainingType()); filteredFields.add( new Alias( new StringConstant(StringUtils.EMPTY), mapping.getUser(fieldMetadata).getName())); } else { filteredFields.add(expression); } } else { filteredFields.add(expression); } } selectedFields.clear(); selectedFields.addAll(filteredFields); } // Handle condition Condition condition = select.getCondition(); if (condition == null) { throw new IllegalArgumentException("Expected a condition in select clause but got 0."); } // Create Lucene query (concatenates all sub queries together). FullTextSession fullTextSession = Search.getFullTextSession(session); Query parsedQuery = select.getCondition().accept(new LuceneQueryGenerator(types)); // Create Hibernate Search query Set<Class> classes = new HashSet<Class>(); for (ComplexTypeMetadata type : types) { String className = ClassCreator.getClassName(type.getName()); try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); classes.add(contextClassLoader.loadClass(className)); } catch (ClassNotFoundException e) { throw new RuntimeException("Could not find class '" + className + "'.", e); } } FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( parsedQuery, classes.toArray(new Class<?>[classes.size()])); // Very important to leave this null (would disable ability to search across different types) fullTextQuery.setCriteriaQuery(null); fullTextQuery.setSort(Sort.RELEVANCE); // Default sort (if no order by specified). query = EntityFinder.wrap( fullTextQuery, (HibernateStorage) storage, session); // ensures only MDM entity objects are returned. // Order by for (OrderBy current : select.getOrderBy()) { current.accept(this); } // Paging Paging paging = select.getPaging(); paging.accept(this); pageSize = paging.getLimit(); boolean hasPaging = pageSize < Integer.MAX_VALUE; if (!hasPaging) { return createResults(query.scroll(ScrollMode.FORWARD_ONLY)); } else { return createResults(query.list()); } }
private SubTreeDescriptor buildTree( final int queryPlanDepth, final int currentDepth, final DbIterator queryPlan, final int currentStartPosition, final int parentUpperBarStartShift) { if (queryPlan == null) return null; int adjustDepth = currentDepth == 0 ? -1 : 0; SubTreeDescriptor thisNode = new SubTreeDescriptor(null, null); if (queryPlan instanceof SeqScan) { SeqScan s = (SeqScan) queryPlan; String tableName = s.getTableName(); String alias = s.getAlias(); // TupleDesc td = s.getTupleDesc(); if (!tableName.equals(alias)) alias = " " + alias; else alias = ""; thisNode.text = String.format("%1$s(%2$s)", SCAN, tableName + alias); if (SCAN.length() / 2 < parentUpperBarStartShift) { thisNode.upBarPosition = currentStartPosition + parentUpperBarStartShift; thisNode.textStartPosition = thisNode.upBarPosition - SCAN.length() / 2; } else { thisNode.upBarPosition = currentStartPosition + SCAN.length() / 2; thisNode.textStartPosition = currentStartPosition; } thisNode.width = thisNode.textStartPosition - currentStartPosition + thisNode.text.length(); int embedHeight = (queryPlanDepth - currentDepth) / 2 - 1; thisNode.height = currentDepth + 2 * embedHeight; int currentHeight = thisNode.height; SubTreeDescriptor parentNode = thisNode; for (int i = 0; i < embedHeight; i++) { parentNode = new SubTreeDescriptor(parentNode, null); parentNode.text = "|"; parentNode.upBarPosition = thisNode.upBarPosition; parentNode.width = thisNode.width; parentNode.height = currentHeight - 2; parentNode.textStartPosition = thisNode.upBarPosition; currentHeight -= 2; } thisNode = parentNode; } else { Operator plan = (Operator) queryPlan; DbIterator[] children = plan.getChildren(); if (plan instanceof Join) { Join j = (Join) plan; TupleDesc td = j.getTupleDesc(); JoinPredicate jp = j.getJoinPredicate(); String field1 = td.getFieldName(jp.getField1()); String field2 = td.getFieldName(jp.getField2() + children[0].getTupleDesc().numFields()); thisNode.text = String.format( "%1$s(%2$s),card:%3$d", JOIN, field1 + jp.getOperator() + field2, j.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (JOIN.length() / 2 > parentUpperBarStartShift) upBarShift = JOIN.length() / 2; SubTreeDescriptor left = buildTree( queryPlanDepth, currentDepth + adjustDepth + 3, children[0], currentStartPosition, upBarShift); SubTreeDescriptor right = buildTree( queryPlanDepth, currentDepth + adjustDepth + 3, children[1], currentStartPosition + left.width + SPACE.length(), 0); thisNode.upBarPosition = (left.upBarPosition + right.upBarPosition) / 2; thisNode.textStartPosition = thisNode.upBarPosition - JOIN.length() / 2; thisNode.width = Math.max( left.width + right.width + SPACE.length(), thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = left; thisNode.rightChild = right; thisNode.height = currentDepth; } else if (plan instanceof HashEquiJoin) { HashEquiJoin j = (HashEquiJoin) plan; JoinPredicate jp = j.getJoinPredicate(); TupleDesc td = j.getTupleDesc(); String field1 = td.getFieldName(jp.getField1()); String field2 = td.getFieldName(jp.getField2() + children[0].getTupleDesc().numFields()); thisNode.text = String.format( "%1$s(%2$s),card:%3$d", HASH_JOIN, field1 + jp.getOperator() + field2, j.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (HASH_JOIN.length() / 2 > parentUpperBarStartShift) upBarShift = HASH_JOIN.length() / 2; SubTreeDescriptor left = buildTree( queryPlanDepth, currentDepth + 3 + adjustDepth, children[0], currentStartPosition, upBarShift); SubTreeDescriptor right = buildTree( queryPlanDepth, currentDepth + 3 + adjustDepth, children[1], currentStartPosition + left.width + SPACE.length(), 0); thisNode.upBarPosition = (left.upBarPosition + right.upBarPosition) / 2; thisNode.textStartPosition = thisNode.upBarPosition - HASH_JOIN.length() / 2; thisNode.width = Math.max( left.width + right.width + SPACE.length(), thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = left; thisNode.rightChild = right; thisNode.height = currentDepth; } else if (plan instanceof Aggregate) { Aggregate a = (Aggregate) plan; int upBarShift = parentUpperBarStartShift; String alignTxt; TupleDesc td = a.getTupleDesc(); int gfield = a.groupField(); if (gfield == Aggregator.NO_GROUPING) { thisNode.text = String.format( "%1$s(%2$s),card:%3$d", a.aggregateOp(), a.aggregateFieldName(), a.getEstimatedCardinality()); alignTxt = td.getFieldName(00); } else { thisNode.text = String.format( "%1$s(%2$s), %3$s(%4$s),card:%5$d", GROUPBY, a.groupFieldName(), a.aggregateOp(), a.aggregateFieldName(), a.getEstimatedCardinality()); alignTxt = GROUPBY; } if (alignTxt.length() / 2 > parentUpperBarStartShift) upBarShift = alignTxt.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - alignTxt.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; thisNode.height = currentDepth; } else if (plan instanceof Filter) { Filter f = (Filter) plan; Predicate p = f.getPredicate(); thisNode.text = String.format( "%1$s(%2$s),card:%3$d", SELECT, children[0].getTupleDesc().getFieldName(p.getField()) + p.getOp() + p.getOperand(), f.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (SELECT.length() / 2 > parentUpperBarStartShift) upBarShift = SELECT.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - SELECT.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; thisNode.height = currentDepth; } else if (plan instanceof OrderBy) { OrderBy o = (OrderBy) plan; thisNode.text = String.format( "%1$s(%2$s),card:%3$d", ORDERBY, children[0].getTupleDesc().getFieldName(o.getOrderByField()), o.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (ORDERBY.length() / 2 > parentUpperBarStartShift) upBarShift = ORDERBY.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - ORDERBY.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; thisNode.height = currentDepth; } else if (plan instanceof Project) { Project p = (Project) plan; String fields = ""; Iterator<TDItem> it = p.getTupleDesc().iterator(); while (it.hasNext()) fields += it.next().fieldName + ","; fields = fields.substring(0, fields.length() - 1); thisNode.text = String.format("%1$s(%2$s),card:%3$d", PROJECT, fields, p.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (PROJECT.length() / 2 > parentUpperBarStartShift) upBarShift = PROJECT.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - PROJECT.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; thisNode.height = currentDepth; } else if (plan.getClass() .getSuperclass() .getSuperclass() .getSimpleName() .equals("Exchange")) { String name = "Exchange"; int card = 0; try { name = (String) plan.getClass().getMethod("getName").invoke(plan); card = (Integer) plan.getClass().getMethod("getEstimatedCardinality").invoke(plan); } catch (Exception e) { e.printStackTrace(); } thisNode.text = String.format("%1$s,card:%2$d", name, card); int upBarShift = parentUpperBarStartShift; if (name.length() / 2 > parentUpperBarStartShift) upBarShift = name.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); if (child == null) { thisNode.upBarPosition = upBarShift; thisNode.textStartPosition = thisNode.upBarPosition - name.length() / 2; thisNode.width = thisNode.textStartPosition + thisNode.text.length() - currentStartPosition; } else { thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - name.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; } thisNode.height = currentDepth; } else if (plan.getClass().getName().equals("simpledb.Rename")) { String newName = null; int fieldIdx = 0; try { newName = (String) plan.getClass().getMethod("newName", (Class<?>[]) null).invoke(plan); fieldIdx = (Integer) plan.getClass().getMethod("renamedField", (Class<?>[]) null).invoke(plan); } catch (Exception e) { e.printStackTrace(); } String oldName = plan.getChildren()[0].getTupleDesc().getFieldName(fieldIdx); thisNode.text = String.format( "%1$s,%2$s->%3$s,card:%4$d", RENAME, oldName, newName, plan.getEstimatedCardinality()); int upBarShift = parentUpperBarStartShift; if (RENAME.length() / 2 > parentUpperBarStartShift) upBarShift = RENAME.length() / 2; SubTreeDescriptor child = buildTree( queryPlanDepth, currentDepth + 2 + adjustDepth, children[0], currentStartPosition, upBarShift); if (child == null) { thisNode.upBarPosition = upBarShift; thisNode.textStartPosition = thisNode.upBarPosition - RENAME.length() / 2; thisNode.width = thisNode.textStartPosition + thisNode.text.length() - currentStartPosition; } else { thisNode.upBarPosition = child.upBarPosition; thisNode.textStartPosition = thisNode.upBarPosition - RENAME.length() / 2; thisNode.width = Math.max( child.width, thisNode.textStartPosition + thisNode.text.length() - currentStartPosition); thisNode.leftChild = child; } thisNode.height = currentDepth; } } return thisNode; }