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);
}
}
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;
}
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));
}
}
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;
}
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;
}
Aggregations