Search in sources :

Example 26 with BlockedException

use of org.teiid.common.buffer.BlockedException in project teiid by teiid.

the class FunctionDescriptor method invokeFunction.

/**
 * Invoke the function described in the function descriptor, using the
 * values provided.  Return the result of the function.
 * @param values Values that should match 1-to-1 with the types described in the
 * function descriptor
 * @param context
 * @param functionTarget TODO
 * @param fd Function descriptor describing the name and types of the arguments
 * @return Result of invoking the function
 */
public Object invokeFunction(Object[] values, CommandContext context, Object functionTarget) throws FunctionExecutionException, BlockedException {
    if (!isNullDependent()) {
        for (int i = requiresContext ? 1 : 0; i < values.length; i++) {
            if (values[i] == null) {
                return null;
            }
        }
    }
    checkMethod();
    // Invoke the method and return the result
    try {
        if (hasWrappedArgs) {
            for (int i = 0; i < values.length; i++) {
                Object val = values[i];
                if (val != null && types[i] == DataTypeManager.DefaultDataClasses.VARBINARY) {
                    values[i] = ((BinaryType) val).getBytesDirect();
                }
            }
        }
        if (method.isVarArgs()) {
            if (calledWithVarArgArrayParam) {
                ArrayImpl av = (ArrayImpl) values[values.length - 1];
                if (av != null) {
                    Object[] vals = av.getValues();
                    values[values.length - 1] = vals;
                    if (hasWrappedArgs && types[types.length - 1] == DataTypeManager.DefaultDataClasses.VARBINARY) {
                        vals = Arrays.copyOf(vals, vals.length);
                        for (int i = 0; i < vals.length; i++) {
                            if (vals[i] != null) {
                                vals[i] = ((BinaryType) vals[i]).getBytesDirect();
                            }
                        }
                        values[values.length - 1] = vals;
                    }
                    Class<?> arrayType = invocationMethod.getParameterTypes()[types.length - 1];
                    if (arrayType.getComponentType() != Object.class && vals.getClass() != arrayType) {
                        Object varArgs = Array.newInstance(arrayType.getComponentType(), vals.length);
                        for (int i = 0; i < vals.length; i++) {
                            Array.set(varArgs, i, vals[i]);
                        }
                        values[values.length - 1] = varArgs;
                    }
                }
            } else {
                int i = invocationMethod.getParameterTypes().length;
                Object[] newValues = Arrays.copyOf(values, i);
                Object varArgs = null;
                if (invocationMethod.getParameterTypes()[i - 1].getComponentType() != Object.class) {
                    int varArgCount = values.length - i + 1;
                    varArgs = Array.newInstance(invocationMethod.getParameterTypes()[i - 1].getComponentType(), varArgCount);
                    for (int j = 0; j < varArgCount; j++) {
                        Array.set(varArgs, j, values[i - 1 + j]);
                    }
                } else {
                    varArgs = Arrays.copyOfRange(values, i - 1, values.length);
                }
                newValues[i - 1] = varArgs;
                values = newValues;
            }
        }
        Object result = null;
        ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
        try {
            if (this.classLoader != null) {
                Thread.currentThread().setContextClassLoader(this.classLoader);
            }
            result = invocationMethod.invoke(functionTarget, values);
        } finally {
            Thread.currentThread().setContextClassLoader(originalCL);
        }
        if (context != null && getDeterministic().ordinal() <= Determinism.USER_DETERMINISTIC.ordinal()) {
            context.setDeterminismLevel(getDeterministic());
        }
        return importValue(result, getReturnType());
    } catch (ArithmeticException e) {
        throw new FunctionExecutionException(QueryPlugin.Event.TEIID30384, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30384, getFullName()));
    } catch (InvocationTargetException e) {
        if (e.getTargetException() instanceof BlockedException) {
            throw (BlockedException) e.getTargetException();
        }
        throw new FunctionExecutionException(QueryPlugin.Event.TEIID30384, e.getTargetException(), QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30384, getFullName()));
    } catch (IllegalAccessException e) {
        throw new FunctionExecutionException(QueryPlugin.Event.TEIID30385, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30385, method.toString()));
    } catch (TransformationException e) {
        throw new FunctionExecutionException(e);
    }
}
Also used : TransformationException(org.teiid.core.types.TransformationException) FunctionExecutionException(org.teiid.api.exception.query.FunctionExecutionException) ArrayImpl(org.teiid.core.types.ArrayImpl) BlockedException(org.teiid.common.buffer.BlockedException) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 27 with BlockedException

use of org.teiid.common.buffer.BlockedException in project teiid by teiid.

the class QueryRewriter method simplifyParseFormatFunction.

private Criteria simplifyParseFormatFunction(CompareCriteria crit) {
    // TODO: this can be relaxed for order preserving operations
    if (!(crit.getOperator() == CompareCriteria.EQ || crit.getOperator() == CompareCriteria.NE)) {
        return crit;
    }
    boolean isFormat = false;
    Function leftFunction = (Function) crit.getLeftExpression();
    String funcName = leftFunction.getName();
    String inverseFunction = null;
    if (StringUtil.startsWithIgnoreCase(funcName, "parse")) {
        // $NON-NLS-1$
        String type = funcName.substring(5);
        if (!PARSE_FORMAT_TYPES.contains(type)) {
            return crit;
        }
        // $NON-NLS-1$
        inverseFunction = "format" + type;
    } else if (StringUtil.startsWithIgnoreCase(funcName, "format")) {
        // $NON-NLS-1$
        String type = funcName.substring(6);
        if (!PARSE_FORMAT_TYPES.contains(type)) {
            return crit;
        }
        // $NON-NLS-1$
        inverseFunction = "parse" + type;
        isFormat = true;
    } else {
        return crit;
    }
    Expression rightExpr = crit.getRightExpression();
    if (!(rightExpr instanceof Constant)) {
        return crit;
    }
    Expression leftExpr = leftFunction.getArgs()[0];
    Expression formatExpr = leftFunction.getArgs()[1];
    if (!(formatExpr instanceof Constant)) {
        return crit;
    }
    String format = (String) ((Constant) formatExpr).getValue();
    FunctionLibrary funcLib = this.metadata.getFunctionLibrary();
    FunctionDescriptor descriptor = funcLib.findFunction(inverseFunction, new Class[] { rightExpr.getType(), formatExpr.getType() });
    if (descriptor == null) {
        return crit;
    }
    Object value = ((Constant) rightExpr).getValue();
    try {
        Object result = descriptor.invokeFunction(new Object[] { context, ((Constant) rightExpr).getValue(), format }, null, this.context);
        result = leftFunction.getFunctionDescriptor().invokeFunction(new Object[] { context, result, format }, null, this.context);
        if (Constant.COMPARATOR.compare(value, result) != 0) {
            return getSimpliedCriteria(crit, leftExpr, crit.getOperator() != CompareCriteria.EQ, true);
        }
    } catch (FunctionExecutionException e) {
        // Not all numeric formats are invertable, so just return the criteria as it may still be valid
        return crit;
    } catch (BlockedException e) {
        return crit;
    }
    // parseFunctions are all potentially narrowing
    if (!isFormat) {
        return crit;
    }
    // TODO: if format is not lossy, then invert the function
    return crit;
}
Also used : FunctionExecutionException(org.teiid.api.exception.query.FunctionExecutionException) FunctionLibrary(org.teiid.query.function.FunctionLibrary) LanguageObject(org.teiid.query.sql.LanguageObject) FunctionDescriptor(org.teiid.query.function.FunctionDescriptor) BlockedException(org.teiid.common.buffer.BlockedException)

Example 28 with BlockedException

use of org.teiid.common.buffer.BlockedException in project teiid by teiid.

the class ExecDynamicSqlInstruction method process.

/**
 * <p>
 * Processing this instruction executes the ProcessorPlan for the command on
 * the CommandStatement of the update procedure language. Executing this
 * plan does not effect the values of any of the variables defined as part
 * of the update procedure and hence the results of the ProcessPlan
 * execution need not be stored for further processing. The results are
 * removed from the buffer manager immediately after execution. The program
 * counter is incremented after execution of the plan.
 * </p>
 *
 * @throws BlockedException
 *             if this processing the plan throws a currentVarContext
 */
public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
    VariableContext localContext = procEnv.getCurrentVariableContext();
    String query = null;
    try {
        Clob value = (Clob) procEnv.evaluateExpression(dynamicCommand.getSql());
        if (value == null) {
            throw new QueryProcessingException(QueryPlugin.Util.getString(// $NON-NLS-1$
            "ExecDynamicSqlInstruction.0"));
        }
        if (value.length() > MAX_SQL_LENGTH) {
            throw new QueryProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31204, MAX_SQL_LENGTH));
        }
        query = value.getSubString(1, MAX_SQL_LENGTH);
        LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, // $NON-NLS-1$
        new Object[] { "Executing dynamic sql ", query });
        Command command = QueryParser.getQueryParser().parseCommand(query);
        // special handling for dynamic anon blocks
        if (command instanceof CreateProcedureCommand) {
            if (dynamicCommand.getIntoGroup() != null || returnable) {
                // and the creation of an inline view
                throw new QueryProcessingException(QueryPlugin.Event.TEIID31250, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31250));
            }
            ((CreateProcedureCommand) command).setResultSetColumns(Collections.EMPTY_LIST);
        }
        command.setExternalGroupContexts(dynamicCommand.getExternalGroupContexts());
        command.setTemporaryMetadata(dynamicCommand.getTemporaryMetadata().clone());
        updateContextWithUsingValues(procEnv, localContext);
        TempMetadataStore metadataStore = command.getTemporaryMetadata();
        if (dynamicCommand.getUsing() != null && !dynamicCommand.getUsing().isEmpty()) {
            metadataStore.addTempGroup(Reserved.USING, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
            GroupSymbol using = new GroupSymbol(Reserved.USING);
            using.setMetadataID(metadataStore.getTempGroupID(Reserved.USING));
            command.addExternalGroupToContext(using);
            metadataStore.addTempGroup(ProcedureReservedWords.DVARS, new LinkedList<ElementSymbol>(dynamicCommand.getUsing().getClauseMap().keySet()));
            using = new GroupSymbol(ProcedureReservedWords.DVARS);
            using.setMetadataID(metadataStore.getTempGroupID(ProcedureReservedWords.DVARS));
            command.addExternalGroupToContext(using);
        }
        QueryResolver.resolveCommand(command, metadata.getDesignTimeMetadata());
        validateDynamicCommand(procEnv, command, value.toString());
        // create a new set of variables including vars
        Map<ElementSymbol, Expression> nameValueMap = createVariableValuesMap(localContext);
        ValidationVisitor visitor = new ValidationVisitor();
        Request.validateWithVisitor(visitor, metadata, command);
        boolean insertInto = false;
        boolean updateCommand = false;
        if (!command.returnsResultSet() && !(command instanceof StoredProcedure)) {
            if (dynamicCommand.isAsClauseSet()) {
                if (dynamicCommand.getProjectedSymbols().size() != 1 || ((Expression) dynamicCommand.getProjectedSymbols().get(0)).getType() != DataTypeManager.DefaultDataClasses.INTEGER) {
                    throw new QueryProcessingException(QueryPlugin.Event.TEIID31157, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31157));
                }
            }
            updateCommand = true;
        } else if (dynamicCommand.getAsColumns() != null && !dynamicCommand.getAsColumns().isEmpty()) {
            // $NON-NLS-1$
            command = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), command, metadata, dynamicCommand.getAsColumns());
            if (dynamicCommand.getIntoGroup() != null) {
                Insert insert = new Insert(dynamicCommand.getIntoGroup(), dynamicCommand.getAsColumns(), Collections.emptyList());
                insert.setQueryExpression((Query) command);
                command = insert;
                insertInto = true;
            }
        }
        // if this is an update procedure, it could reassign variables
        command = QueryRewriter.rewrite(command, metadata, procEnv.getContext(), command instanceof CreateProcedureCommand ? Collections.EMPTY_MAP : nameValueMap);
        ProcessorPlan commandPlan = QueryOptimizer.optimizePlan(command, metadata, idGenerator, capFinder, AnalysisRecord.createNonRecordingRecord(), procEnv.getContext());
        if (command instanceof CreateProcedureCommand && commandPlan instanceof ProcedurePlan) {
            ((ProcedurePlan) commandPlan).setValidateAccess(procEnv.isValidateAccess());
        }
        CreateCursorResultSetInstruction inst = new CreateCursorResultSetInstruction(null, commandPlan, (insertInto || updateCommand) ? Mode.UPDATE : returnable ? Mode.HOLD : Mode.NOHOLD) {

            @Override
            public void process(ProcedurePlan procEnv) throws BlockedException, TeiidComponentException, TeiidProcessingException {
                boolean done = true;
                try {
                    super.process(procEnv);
                } catch (BlockedException e) {
                    done = false;
                    throw e;
                } finally {
                    if (done) {
                        procEnv.getContext().popCall();
                    }
                }
            }
        };
        dynamicProgram = new Program(false);
        dynamicProgram.addInstruction(inst);
        if (dynamicCommand.getIntoGroup() != null) {
            String groupName = dynamicCommand.getIntoGroup().getName();
            if (!procEnv.getTempTableStore().hasTempTable(groupName, true)) {
                // create the temp table in the parent scope
                Create create = new Create();
                create.setTable(new GroupSymbol(groupName));
                for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
                    Column c = new Column();
                    c.setName(es.getShortName());
                    c.setRuntimeType(DataTypeManager.getDataTypeName(es.getType()));
                    create.getColumns().add(c);
                }
                procEnv.getDataManager().registerRequest(procEnv.getContext(), create, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
            }
            // backwards compatibility to support into with a rowcount
            if (updateCommand) {
                Insert insert = new Insert();
                insert.setGroup(new GroupSymbol(groupName));
                for (ElementSymbol es : (List<ElementSymbol>) dynamicCommand.getAsColumns()) {
                    ElementSymbol col = new ElementSymbol(es.getShortName(), insert.getGroup());
                    col.setType(es.getType());
                    insert.addVariable(col);
                }
                insert.addValue(new Constant(procEnv.getCurrentVariableContext().getValue(ProcedurePlan.ROWCOUNT)));
                QueryResolver.resolveCommand(insert, metadata.getDesignTimeMetadata());
                TupleSource ts = procEnv.getDataManager().registerRequest(procEnv.getContext(), insert, TempMetadataAdapter.TEMP_MODEL.getName(), new RegisterRequestParameter());
                ts.nextTuple();
                ts.closeSource();
            }
        }
        // Add group to recursion stack
        if (parentProcCommand.getUpdateType() != Command.TYPE_UNKNOWN) {
            // $NON-NLS-1$
            procEnv.getContext().pushCall(Command.getCommandToken(parentProcCommand.getUpdateType()) + " " + parentProcCommand.getVirtualGroup());
        } else {
            if (parentProcCommand.getVirtualGroup() != null) {
                procEnv.getContext().pushCall(parentProcCommand.getVirtualGroup().toString());
            }
        }
        procEnv.push(dynamicProgram);
    } catch (SQLException e) {
        Object[] params = { dynamicCommand, dynamicCommand.getSql(), e.getMessage() };
        throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
    } catch (TeiidProcessingException e) {
        Object[] params = { dynamicCommand, query == null ? dynamicCommand.getSql() : query, e.getMessage() };
        throw new QueryProcessingException(QueryPlugin.Event.TEIID30168, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30168, params));
    }
}
Also used : ElementSymbol(org.teiid.query.sql.symbol.ElementSymbol) ValidationVisitor(org.teiid.query.validator.ValidationVisitor) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) Query(org.teiid.query.sql.lang.Query) SQLException(java.sql.SQLException) Constant(org.teiid.query.sql.symbol.Constant) Insert(org.teiid.query.sql.lang.Insert) BlockedException(org.teiid.common.buffer.BlockedException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) Column(org.teiid.metadata.Column) Create(org.teiid.query.sql.lang.Create) List(java.util.List) LinkedList(java.util.LinkedList) VariableContext(org.teiid.query.sql.util.VariableContext) RegisterRequestParameter(org.teiid.query.processor.RegisterRequestParameter) StoredProcedure(org.teiid.query.sql.lang.StoredProcedure) CreateProcedureCommand(org.teiid.query.sql.proc.CreateProcedureCommand) Command(org.teiid.query.sql.lang.Command) DynamicCommand(org.teiid.query.sql.lang.DynamicCommand) Expression(org.teiid.query.sql.symbol.Expression) TupleSource(org.teiid.common.buffer.TupleSource) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) Clob(java.sql.Clob) ProcessorPlan(org.teiid.query.processor.ProcessorPlan) TempMetadataStore(org.teiid.query.metadata.TempMetadataStore) QueryProcessingException(org.teiid.api.exception.query.QueryProcessingException)

Example 29 with BlockedException

use of org.teiid.common.buffer.BlockedException in project teiid by teiid.

the class ProcedurePlan method processProcedure.

/**
 * <p>Process the procedure, using the stack of Programs supplied by the
 * ProcessorEnvironment.  With each pass through the loop, the
 * current Program is gotten off the top of the stack, and the
 * current instruction is gotten from that program; each call
 * to an instruction's process method may alter the Program
 * Stack and/or the current instruction pointer of a Program,
 * so it's important that this method's loop refer to the
 * call stack of the ProcessorEnvironment each time, and not
 * cache things in local variables.  If the current Program's
 * current instruction is null, then it's time to pop that
 * Program off the stack.</p>
 *
 * @return List a single tuple containing one Integer: the update
 * count resulting from the procedure execution.
 */
private TupleSource processProcedure() throws TeiidComponentException, TeiidProcessingException, BlockedException {
    // execute plan
    ProgramInstruction inst = null;
    while (!this.programs.empty()) {
        Program program = peek();
        inst = program.getCurrentInstruction();
        if (inst == null) {
            // $NON-NLS-1$
            LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Finished program", program);
            // look ahead to see if we need to process in place
            VariableContext vc = this.cursorStates.getParentContext();
            CursorState last = (CursorState) this.cursorStates.getValue(null);
            if (last != null) {
                if (last.resultsBuffer == null && (last.usesLocalTemp || !txnTupleSources.isEmpty())) {
                    last.resultsBuffer = bufferMgr.createTupleBuffer(last.processor.getOutputElements(), getContext().getConnectionId(), TupleSourceType.PROCESSOR);
                    last.returning = true;
                }
                if (last.returning) {
                    while (last.ts.hasNext()) {
                        List<?> tuple = last.ts.nextTuple();
                        last.resultsBuffer.addTuple(tuple);
                    }
                    last.resultsBuffer.close();
                    last.ts = last.resultsBuffer.createIndexedTupleSource(true);
                    last.returning = false;
                }
            }
            this.pop(true);
            continue;
        }
        try {
            getContext().setCurrentTimestamp(System.currentTimeMillis());
            if (inst instanceof RepeatedInstruction) {
                // $NON-NLS-1$
                LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing repeated instruction", inst);
                RepeatedInstruction loop = (RepeatedInstruction) inst;
                if (loop.testCondition(this)) {
                    // $NON-NLS-1$
                    LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Passed condition, executing program " + loop.getNestedProgram());
                    inst.process(this);
                    this.push(loop.getNestedProgram());
                    continue;
                }
                // $NON-NLS-1$
                LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Exiting repeated instruction", inst);
                loop.postInstruction(this);
            } else {
                // $NON-NLS-1$
                LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Executing instruction", inst);
                inst.process(this);
                this.evaluator.close();
            }
        } catch (TeiidComponentException e) {
            throw e;
        } catch (Exception e) {
            // processing or teiidsqlexception
            boolean atomic = program.isAtomic();
            while (program.getExceptionGroup() == null) {
                this.pop(false);
                if (this.programs.empty()) {
                    // reached the top without a handler, so throw
                    if (e instanceof TeiidProcessingException) {
                        throw (TeiidProcessingException) e;
                    }
                    throw new ProcedureErrorInstructionException(QueryPlugin.Event.TEIID30167, e);
                }
                program = peek();
                atomic |= program.isAtomic();
            }
            try {
                // allow the current program to go out of scope
                this.pop(false);
                if (atomic) {
                    TransactionContext tc = this.getContext().getTransactionContext();
                    if (tc != null && tc.getTransactionType() != Scope.NONE) {
                        // a non-completing atomic block under a higher level transaction
                        // this will not work correctly until we support
                        // checkpoints/subtransactions
                        tc.getTransaction().setRollbackOnly();
                        getContext().addWarning(TeiidSQLException.create(e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31266)));
                    }
                }
            } catch (IllegalStateException | SystemException | TeiidComponentException e1) {
                // $NON-NLS-1$
                LogManager.logDetail(LogConstants.CTX_DQP, "Caught exception while rolling back transaction", e1);
            } catch (Throwable e1) {
                LogManager.logWarning(LogConstants.CTX_DQP, e1);
            }
            if (e instanceof RuntimeException) {
                LogManager.logWarning(LogConstants.CTX_DQP, e);
            } else {
                // $NON-NLS-1$
                LogManager.logDetail(LogConstants.CTX_DQP, "Caught exception in exception hanlding block", e);
            }
            if (program.getExceptionProgram() == null) {
                continue;
            }
            Program exceptionProgram = program.getExceptionProgram();
            this.push(exceptionProgram);
            TeiidSQLException tse = TeiidSQLException.create(e);
            GroupSymbol gs = new GroupSymbol(program.getExceptionGroup());
            this.currentVarContext.setValue(exceptionSymbol(gs, 0), tse.getSQLState());
            this.currentVarContext.setValue(exceptionSymbol(gs, 1), tse.getErrorCode());
            this.currentVarContext.setValue(exceptionSymbol(gs, 2), tse.getTeiidCode());
            this.currentVarContext.setValue(exceptionSymbol(gs, 3), tse);
            this.currentVarContext.setValue(exceptionSymbol(gs, 4), tse.getCause());
            continue;
        }
        program.incrementProgramCounter();
    }
    CursorState last = (CursorState) this.cursorStates.getValue(null);
    if (last == null) {
        return CollectionTupleSource.createNullTupleSource();
    }
    return last.ts;
}
Also used : TeiidSQLException(org.teiid.jdbc.TeiidSQLException) ProcedureErrorInstructionException(org.teiid.client.ProcedureErrorInstructionException) VariableContext(org.teiid.query.sql.util.VariableContext) TeiidComponentException(org.teiid.core.TeiidComponentException) QueryMetadataException(org.teiid.api.exception.query.QueryMetadataException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) ProcedureErrorInstructionException(org.teiid.client.ProcedureErrorInstructionException) TeiidSQLException(org.teiid.jdbc.TeiidSQLException) BlockedException(org.teiid.common.buffer.BlockedException) XATransactionException(org.teiid.client.xa.XATransactionException) QueryValidatorException(org.teiid.api.exception.query.QueryValidatorException) SystemException(javax.transaction.SystemException) TeiidProcessingException(org.teiid.core.TeiidProcessingException) TransactionContext(org.teiid.dqp.service.TransactionContext) GroupSymbol(org.teiid.query.sql.symbol.GroupSymbol) TeiidComponentException(org.teiid.core.TeiidComponentException)

Example 30 with BlockedException

use of org.teiid.common.buffer.BlockedException in project teiid by teiid.

the class SortUtility method sortWorking.

private void sortWorking(int rowLimit) throws TeiidComponentException, TeiidProcessingException {
    // sub-phase 2 - perform a memory sort on the workingbuffer/source
    int totalReservedBuffers = 0;
    try {
        int maxRows = this.batchSize;
        Collection<List<?>> workingTuples = null;
        boolean done = false;
        /*
			 * we can balance the work between the initial / multi-pass sort based upon the row count
			 * and an updated estimate of the batch memory size 
			 */
        this.workingBuffer.close();
        schemaSize = Math.max(1, this.workingBuffer.getRowSizeEstimate() * this.batchSize);
        long rowCount = workingBuffer.getRowCount();
        long memorySpaceNeeded = rowCount * this.workingBuffer.getRowSizeEstimate();
        totalReservedBuffers = bufferManager.reserveBuffers(Math.min(bufferManager.getMaxProcessingSize(), (int) Math.min(memorySpaceNeeded, Integer.MAX_VALUE)), BufferReserveMode.FORCE);
        if (totalReservedBuffers != memorySpaceNeeded) {
            int processingSublists = Math.max(2, bufferManager.getMaxProcessingSize() / schemaSize);
            int desiredSpace = (int) Math.min(Integer.MAX_VALUE, (workingBuffer.getRowCount() / processingSublists + (workingBuffer.getRowCount() % processingSublists)) * this.workingBuffer.getRowSizeEstimate());
            if (desiredSpace > totalReservedBuffers) {
                totalReservedBuffers += bufferManager.reserveBuffers(desiredSpace - totalReservedBuffers, BufferReserveMode.NO_WAIT);
            // TODO: wait to force 2/3 pass processing
            } else if (memorySpaceNeeded <= Integer.MAX_VALUE) {
                totalReservedBuffers += bufferManager.reserveBuffers((int) memorySpaceNeeded - totalReservedBuffers, BufferReserveMode.NO_WAIT);
            }
            if (totalReservedBuffers > schemaSize) {
                int additional = totalReservedBuffers % schemaSize;
                totalReservedBuffers -= additional;
                // release any excess
                bufferManager.releaseBuffers(additional);
            }
        }
        TupleBufferTupleSource ts = workingBuffer.createIndexedTupleSource(source != null);
        ts.setReverse(!stableSort && workingBuffer.getRowCount() > this.batchSize);
        maxRows = Math.max(1, (totalReservedBuffers / schemaSize)) * batchSize;
        boolean checkLimit = rowLimit > -1 && rowCount <= maxRows;
        if (mode == Mode.SORT) {
            workingTuples = new AccessibleArrayList<>();
        } else {
            workingTuples = new TreeSet<List<?>>(comparator);
        }
        outer: while (!done) {
            while (!done) {
                if (workingTuples.size() >= maxRows) {
                    break;
                }
                List<?> tuple = ts.nextTuple();
                if (tuple == null) {
                    done = true;
                    if (workingTuples.isEmpty()) {
                        break outer;
                    }
                    break;
                }
                workingTuples.add(tuple);
            }
            TupleBuffer sublist = createTupleBuffer();
            activeTupleBuffers.add(sublist);
            if (this.mode == Mode.SORT) {
                // perform a stable sort
                if (workingTuples.size() > (1 << 18)) {
                    Arrays.parallelSort(((AccessibleArrayList) workingTuples).elementData, 0, workingTuples.size(), comparator);
                } else {
                    Collections.sort((List<List<?>>) workingTuples, comparator);
                }
            }
            for (List<?> list : workingTuples) {
                sublist.addTuple(list);
                if (checkLimit && sublist.getRowCount() == rowLimit) {
                    sublist.saveBatch();
                    break outer;
                }
            }
            workingTuples.clear();
            sublist.saveBatch();
        }
    } catch (BlockedException e) {
        // $NON-NLS-1$
        Assertion.failed("should not block during memory sublist sorting");
    } finally {
        bufferManager.releaseBuffers(totalReservedBuffers);
        if (this.workingBuffer != null) {
            if (this.source != null) {
                this.workingBuffer.remove();
            }
            this.workingBuffer = null;
        }
    }
    if (this.activeTupleBuffers.isEmpty()) {
        activeTupleBuffers.add(createTupleBuffer());
    }
    this.phase = MERGE;
}
Also used : TupleBufferTupleSource(org.teiid.common.buffer.TupleBuffer.TupleBufferTupleSource) TupleBuffer(org.teiid.common.buffer.TupleBuffer) AbstractList(java.util.AbstractList) ArrayList(java.util.ArrayList) List(java.util.List) BlockedException(org.teiid.common.buffer.BlockedException)

Aggregations

BlockedException (org.teiid.common.buffer.BlockedException)45 TupleBatch (org.teiid.common.buffer.TupleBatch)16 ArrayList (java.util.ArrayList)15 List (java.util.List)15 TeiidProcessingException (org.teiid.core.TeiidProcessingException)15 TeiidComponentException (org.teiid.core.TeiidComponentException)13 TupleBuffer (org.teiid.common.buffer.TupleBuffer)10 CommandContext (org.teiid.query.util.CommandContext)10 TupleSource (org.teiid.common.buffer.TupleSource)8 ElementSymbol (org.teiid.query.sql.symbol.ElementSymbol)8 Test (org.junit.Test)6 BufferManager (org.teiid.common.buffer.BufferManager)6 ExpressionEvaluationException (org.teiid.api.exception.query.ExpressionEvaluationException)5 FunctionExecutionException (org.teiid.api.exception.query.FunctionExecutionException)5 QueryValidatorException (org.teiid.api.exception.query.QueryValidatorException)5 Command (org.teiid.query.sql.lang.Command)5 GroupSymbol (org.teiid.query.sql.symbol.GroupSymbol)5 CollectionTupleSource (org.teiid.query.processor.CollectionTupleSource)4 SQLException (java.sql.SQLException)3 QueryProcessingException (org.teiid.api.exception.query.QueryProcessingException)3