Search in sources :

Example 1 with QueryProcessor

use of org.teiid.query.processor.QueryProcessor in project teiid by teiid.

the class SubqueryAwareEvaluator method evaluateSubquery.

@Override
protected ValueIterator evaluateSubquery(SubqueryContainer<?> container, List<?> tuple) throws TeiidProcessingException, BlockedException, TeiidComponentException {
    ContextReference ref = (ContextReference) container;
    String key = ref.getContextSymbol();
    SubqueryState state = this.subqueries.get(key);
    if (state == null) {
        String otherKey = commands.get(container.getCommand());
        if (otherKey != null) {
            state = this.subqueries.get(otherKey);
            if (state != null) {
                key = otherKey;
            }
        }
    }
    if (state == null) {
        state = new SubqueryState();
        state.plan = container.getCommand().getProcessorPlan().clone();
        if (container.getCommand().getCorrelatedReferences() != null) {
            for (ElementSymbol es : container.getCommand().getCorrelatedReferences().getKeys()) {
                if (DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(es.getType()))) {
                    state.comparable = false;
                    break;
                }
            }
        }
        this.subqueries.put(key, state);
        this.commands.put(container.getCommand(), key);
    }
    SymbolMap correlatedRefs = container.getCommand().getCorrelatedReferences();
    VariableContext currentContext = null;
    boolean shouldClose = false;
    boolean deterministic = true;
    if (state.processor != null && correlatedRefs != null) {
        Determinism determinism = state.processor.getContext().getDeterminismLevel();
        deterministic = Determinism.COMMAND_DETERMINISTIC.compareTo(determinism) <= 0;
    }
    boolean removeBuffer = true;
    if (correlatedRefs != null) {
        currentContext = new VariableContext();
        for (Map.Entry<ElementSymbol, Expression> entry : container.getCommand().getCorrelatedReferences().asMap().entrySet()) {
            currentContext.setValue(entry.getKey(), evaluate(entry.getValue(), tuple));
        }
        List<Object> refValues = currentContext.getLocalValues();
        if (!refValues.equals(state.refValues)) {
            if (state.comparable && deterministic) {
                if (state.processor != null) {
                    // cache the old value
                    TupleBuffer tb = state.collector.collectTuples();
                    // recheck determinism as the plan may not have been fully processed by the initial check
                    Determinism determinism = state.processor.getContext().getDeterminismLevel();
                    deterministic = Determinism.COMMAND_DETERMINISTIC.compareTo(determinism) <= 0;
                    if (deterministic) {
                        // allowed to track up to 4x the maximum results size
                        maxTuples = Math.max((int) Math.min(Integer.MAX_VALUE, tb.getRowCount() << 2), maxTuples);
                        ArrayList<Object> cacheKey = new ArrayList<Object>(state.refValues);
                        cacheKey.add(key);
                        // ensure that we aren't leaving large last batches in memory
                        tb.saveBatch();
                        this.cache.put(cacheKey, tb);
                        removeBuffer = false;
                        this.currentTuples += tb.getRowCount();
                        while (this.currentTuples > maxTuples && !cache.isEmpty()) {
                            Iterator<Map.Entry<List<?>, TupleBuffer>> i = this.cache.entrySet().iterator();
                            Map.Entry<List<?>, TupleBuffer> entry = i.next();
                            TupleBuffer buffer = entry.getValue();
                            if (buffer.getRowCount() <= 2) {
                                this.smallCache.put(entry.getKey(), buffer);
                            } else {
                                buffer.remove();
                            }
                            this.currentTuples -= buffer.getRowCount();
                            i.remove();
                        }
                    }
                }
                // find if we have cached values
                List<Object> cacheKey = new ArrayList<Object>(refValues);
                cacheKey.add(key);
                TupleBuffer cachedResult = cache.get(cacheKey);
                if (cachedResult == null) {
                    cachedResult = smallCache.get(cacheKey);
                }
                if (cachedResult != null) {
                    state.close(false);
                    return new TupleSourceValueIterator(cachedResult.createIndexedTupleSource(), 0);
                }
            }
            state.refValues = refValues;
            shouldClose = true;
        }
    }
    if (shouldClose || (!deterministic && !state.blocked)) {
        state.close(removeBuffer);
    }
    state.blocked = true;
    if (state.processor == null) {
        CommandContext subContext = context.clone();
        state.plan.reset();
        state.processor = new QueryProcessor(state.plan, subContext, manager, this.dataMgr);
        if (currentContext != null) {
            state.processor.getContext().pushVariableContext(currentContext);
        }
        state.collector = state.processor.createBatchCollector();
    }
    TupleSourceValueIterator iter = new TupleSourceValueIterator(state.collector.collectTuples().createIndexedTupleSource(), 0);
    state.blocked = false;
    return iter;
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) Determinism(org.teiid.metadata.FunctionMethod.Determinism) CommandContext(org.teiid.query.util.CommandContext) ContextReference(org.teiid.query.sql.symbol.ContextReference) TupleBuffer(org.teiid.common.buffer.TupleBuffer) ArrayList(java.util.ArrayList) SymbolMap(org.teiid.query.sql.util.SymbolMap) VariableContext(org.teiid.query.sql.util.VariableContext) QueryProcessor(org.teiid.query.processor.QueryProcessor) Expression(org.teiid.query.sql.symbol.Expression) List(java.util.List) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 2 with QueryProcessor

use of org.teiid.query.processor.QueryProcessor in project teiid by teiid.

the class SubqueryAwareEvaluator method evaluateProcedure.

/**
 * Implements procedure function handling.
 * TODO: cache results
 */
@Override
protected Object evaluateProcedure(Function function, List<?> tuple, Object[] values) throws TeiidComponentException, TeiidProcessingException {
    QueryProcessor qp = null;
    List<?> key = Arrays.asList(function, Arrays.asList(values));
    if (procedureState != null) {
        qp = this.procedureState.get(key);
    }
    if (qp == null) {
        String args = Collections.nCopies(values.length, '?').toString().substring(1);
        args = args.substring(0, args.length() - 1);
        String fullName = function.getFunctionDescriptor().getFullName();
        // $NON-NLS-1$
        String call = String.format("call %1$s(%2$s)", fullName, args);
        qp = this.context.getQueryProcessorFactory().createQueryProcessor(call, fullName, this.context, values);
        if (this.procedureState == null) {
            this.procedureState = new HashMap<List<?>, QueryProcessor>();
        }
        this.procedureState.put(key, qp);
    }
    // just in case validate the rows being returned
    TupleBatch tb = qp.nextBatch();
    TupleBatch next = tb;
    while (!next.getTerminationFlag()) {
        if (next.getEndRow() >= 2) {
            break;
        }
        next = qp.nextBatch();
    }
    if (next.getEndRow() >= 2) {
        throw new ExpressionEvaluationException(QueryPlugin.Event.TEIID30345, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30345, function));
    }
    Object result = null;
    if (next.getRowCount() > 0) {
        result = next.getTuples().get(0).get(0);
    }
    this.procedureState.remove(key);
    qp.closeProcessing();
    return result;
}
Also used : ExpressionEvaluationException(org.teiid.api.exception.query.ExpressionEvaluationException) List(java.util.List) ArrayList(java.util.ArrayList) QueryProcessor(org.teiid.query.processor.QueryProcessor) TupleBatch(org.teiid.common.buffer.TupleBatch)

Example 3 with QueryProcessor

use of org.teiid.query.processor.QueryProcessor in project teiid by teiid.

the class AccessNode method openInternal.

private void openInternal() throws TeiidComponentException, TeiidProcessingException {
    // TODO: support a partitioning concept with multi-source and full dependent join pushdown
    if (subPlans != null) {
        if (this.evaluatedPlans == null) {
            this.evaluatedPlans = new HashMap<GroupSymbol, SubqueryState>();
            for (Map.Entry<GroupSymbol, RelationalPlan> entry : subPlans.entrySet()) {
                SubqueryState state = new SubqueryState();
                RelationalPlan value = entry.getValue();
                value.reset();
                state.processor = new QueryProcessor(value, getContext().clone(), getBufferManager(), getDataManager());
                state.collector = state.processor.createBatchCollector();
                this.evaluatedPlans.put(entry.getKey(), state);
            }
        }
        BlockedException be = null;
        for (SubqueryState state : evaluatedPlans.values()) {
            try {
                state.collector.collectTuples();
            } catch (BlockedException e) {
                be = e;
            }
        }
        if (be != null) {
            throw be;
        }
    }
    /*
		 * Check to see if we need a multi-source expansion.  If the connectorBindingExpression != null, then 
		 * the logic below will handle that case
		 */
    if (multiSource && connectorBindingExpression == null) {
        synchronized (this) {
            // the description can be obtained asynchly, so we need to synchronize
            VDBMetaData vdb = getContext().getVdb();
            ModelMetaData model = vdb.getModel(getModelName());
            List<String> sources = model.getSourceNames();
            // make sure that we have the right nodes
            if (this.getChildCount() != 0 && (this.sourceNames == null || !this.sourceNames.equals(sources))) {
                this.childCount--;
                this.getChildren()[0] = null;
            }
            if (this.getChildCount() == 0) {
                sourceNames = sources;
                RelationalNode node = multiSourceModify(this, connectorBindingExpression, getContext().getMetadata(), sourceNames);
                RelationalPlan.connectExternal(node, getContext(), getDataManager(), getBufferManager());
                this.addChild(node);
            }
        }
        this.getChildren()[0].open();
        return;
    }
    // Copy command and resolve references if necessary
    if (processingCommand == null) {
        processingCommand = command;
        isUpdate = RelationalNodeUtil.isUpdate(command);
    }
    boolean needProcessing = true;
    if (this.connectorBindingExpression != null && connectorBindingId == null) {
        this.connectorBindingId = (String) getEvaluator(Collections.emptyMap()).evaluate(this.connectorBindingExpression, null);
        VDBMetaData vdb = getContext().getVdb();
        ModelMetaData model = vdb.getModel(getModelName());
        List<String> sources = model.getSourceNames();
        String replacement = this.connectorBindingId;
        if (!sources.contains(this.connectorBindingId)) {
            shouldExecute = false;
            if (command instanceof StoredProcedure) {
                StoredProcedure sp = (StoredProcedure) command;
                if (sp.returnParameters() && sp.getProjectedSymbols().size() > sp.getResultSetColumns().size()) {
                    throw new TeiidProcessingException(QueryPlugin.Event.TEIID30561, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30561, command));
                }
            }
            return;
        }
        if (!(command instanceof StoredProcedure || command instanceof Insert)) {
            processingCommand = (Command) command.clone();
            MultiSourceElementReplacementVisitor.visit(replacement, getContext().getMetadata(), processingCommand);
        }
    }
    do {
        Command atomicCommand = nextCommand();
        if (shouldEvaluate) {
            needProcessing = prepareNextCommand(atomicCommand);
            nextCommand = null;
        } else {
            needProcessing = RelationalNodeUtil.shouldExecute(atomicCommand, true);
        }
        if (needProcessing) {
            registerRequest(atomicCommand);
        }
    // We use an upper limit here to the currency because these commands have potentially large in-memory value sets
    } while (!processCommandsIndividually() && hasNextCommand() && this.tupleSources.size() < Math.max(Math.min(MAX_CONCURRENT, this.getContext().getUserRequestSourceConcurrency()), this.getContext().getUserRequestSourceConcurrency() / 2));
}
Also used : SubqueryState(org.teiid.query.processor.relational.SubqueryAwareEvaluator.SubqueryState) Insert(org.teiid.query.sql.lang.Insert) BlockedException(org.teiid.common.buffer.BlockedException) QueryProcessor(org.teiid.query.processor.QueryProcessor) ModelMetaData(org.teiid.adminapi.impl.ModelMetaData) TeiidProcessingException(org.teiid.core.TeiidProcessingException) StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) QueryCommand(org.teiid.query.sql.lang.QueryCommand) Command(org.teiid.query.sql.lang.Command) WithQueryCommand(org.teiid.query.sql.lang.WithQueryCommand) VDBMetaData(org.teiid.adminapi.impl.VDBMetaData) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) SymbolMap(org.teiid.query.sql.util.SymbolMap)

Example 4 with QueryProcessor

use of org.teiid.query.processor.QueryProcessor in project teiid by teiid.

the class ForEachRowPlan method nextBatch.

@Override
public TupleBatch nextBatch() throws BlockedException, TeiidComponentException, TeiidProcessingException {
    if (planContext != null) {
        this.getContext().getTransactionServer().resume(planContext);
    }
    try {
        while (true) {
            if (currentTuple == null) {
                if (nextTuple != null) {
                    currentTuple = nextTuple;
                } else if (!nextNull) {
                    currentTuple = tupleSource.nextTuple();
                }
                if (currentTuple == null) {
                    if (this.planContext != null) {
                        TransactionService ts = this.getContext().getTransactionServer();
                        ts.commit(this.planContext);
                        this.planContext = null;
                    }
                    TupleBatch result = new TupleBatch(1, new List[] { Arrays.asList((int) Math.min(Integer.MAX_VALUE, updateCount)) });
                    result.setTerminationFlag(true);
                    return result;
                }
            }
            if (first) {
                TransactionContext tc = this.getContext().getTransactionContext();
                if (this.planContext == null && tc != null && tc.getTransactionType() == Scope.NONE) {
                    Boolean txnRequired = rowProcedure.requiresTransaction(false);
                    boolean start = false;
                    if (txnRequired == null) {
                        nextTuple = tupleSource.nextTuple();
                        if (nextTuple != null) {
                            start = true;
                        } else {
                            nextNull = true;
                        }
                    } else if (Boolean.TRUE.equals(txnRequired)) {
                        start = true;
                    }
                    if (start) {
                        this.getContext().getTransactionServer().begin(tc);
                        this.planContext = tc;
                    }
                }
                first = false;
            }
            if (this.rowProcessor == null) {
                rowProcedure.reset();
                CommandContext context = getContext().clone();
                this.rowProcessor = new QueryProcessor(rowProcedure, context, this.bufferMgr, this.dataMgr);
                Evaluator eval = new Evaluator(lookupMap, dataMgr, context);
                for (Map.Entry<ElementSymbol, Expression> entry : this.params.entrySet()) {
                    Integer index = this.lookupMap.get(entry.getValue());
                    if (index != null) {
                        rowProcedure.getCurrentVariableContext().setValue(entry.getKey(), this.currentTuple.get(index));
                    } else {
                        rowProcedure.getCurrentVariableContext().setValue(entry.getKey(), eval.evaluate(entry.getValue(), this.currentTuple));
                    }
                }
            }
            // save the variable context to get the key information
            VariableContext vc = rowProcedure.getCurrentVariableContext();
            // just getting the next batch is enough
            this.rowProcessor.nextBatch();
            if (insert) {
                assignGeneratedKey(vc);
            }
            this.rowProcessor.closeProcessing();
            this.rowProcessor = null;
            this.currentTuple = null;
            this.updateCount++;
        }
    } finally {
        if (planContext != null) {
            this.getContext().getTransactionServer().suspend(planContext);
        }
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) TransactionService(org.teiid.dqp.service.TransactionService) CommandContext(org.teiid.query.util.CommandContext) Evaluator(org.teiid.query.eval.Evaluator) VariableContext(org.teiid.query.sql.util.VariableContext) QueryProcessor(org.teiid.query.processor.QueryProcessor) Expression(org.teiid.query.sql.symbol.Expression) TransactionContext(org.teiid.dqp.service.TransactionContext) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) TupleBatch(org.teiid.common.buffer.TupleBatch)

Example 5 with QueryProcessor

use of org.teiid.query.processor.QueryProcessor in project teiid by teiid.

the class QueryProcessorFactoryImpl method createQueryProcessor.

@Override
public QueryProcessor createQueryProcessor(String query, String recursionGroup, CommandContext commandContext, Object... params) throws TeiidProcessingException, TeiidComponentException {
    CommandContext copy = commandContext.clone();
    copy.resetDeterminismLevel(true);
    copy.setDataObjects(null);
    QueryMetadataInterface metadata = commandContext.getMetadata();
    if (metadata == null) {
        metadata = defaultMetadata;
    }
    PreparedPlan pp = getPreparedPlan(query, recursionGroup, copy, metadata);
    copy.pushVariableContext(new VariableContext());
    PreparedStatementRequest.resolveParameterValues(pp.getReferences(), Arrays.asList(params), copy, metadata);
    return new QueryProcessor(pp.getPlan().clone(), copy, bufferMgr, dataMgr);
}
Also used : CommandContext(org.teiid.query.util.CommandContext) QueryMetadataInterface(org.teiid.query.metadata.QueryMetadataInterface) VariableContext(org.teiid.query.sql.util.VariableContext) QueryProcessor(org.teiid.query.processor.QueryProcessor)

Aggregations

QueryProcessor (org.teiid.query.processor.QueryProcessor)14 ArrayList (java.util.ArrayList)4 BatchCollector (org.teiid.query.processor.BatchCollector)4 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)4 CommandContext (org.teiid.query.util.CommandContext)4 List (java.util.List)3 Map (java.util.Map)3 TransactionContext (org.teiid.dqp.service.TransactionContext)3 Determinism (org.teiid.metadata.FunctionMethod.Determinism)3 VariableContext (org.teiid.query.sql.util.VariableContext)3 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 LinkedList (java.util.LinkedList)2 ExpressionEvaluationException (org.teiid.api.exception.query.ExpressionEvaluationException)2 QueryProcessingException (org.teiid.api.exception.query.QueryProcessingException)2 BlockedException (org.teiid.common.buffer.BlockedException)2 TupleBatch (org.teiid.common.buffer.TupleBatch)2 TupleBuffer (org.teiid.common.buffer.TupleBuffer)2 TupleSource (org.teiid.common.buffer.TupleSource)2 TeiidProcessingException (org.teiid.core.TeiidProcessingException)2