public void push(Program program) throws XATransactionException { this.evaluator.close(); program.reset(this.getContext().getConnectionId()); program.setTrappingExceptions( program.getExceptionGroup() != null || (!this.programs.isEmpty() && this.programs.peek().isTrappingExceptions())); TempTableStore tts = getTempTableStore(); getContext().setTempTableStore(program.getTempTableStore()); program.getTempTableStore().setParentTempTableStore(tts); this.programs.push(program); VariableContext context = new VariableContext(true); context.setParentContext(this.currentVarContext); this.currentVarContext = context; VariableContext cc = new VariableContext(true); cc.setParentContext(this.cursorStates); this.cursorStates = cc; if (program.isAtomic() && this.blockContext == null) { TransactionContext tc = this.getContext().getTransactionContext(); if (tc != null && tc.getTransactionType() == Scope.NONE) { // start a transaction this.getContext().getTransactionServer().begin(tc); this.blockContext = tc; program.setStartedTxn(true); } } }
private TempTableSynchronization getSynchronization(CommandContext context) throws TeiidProcessingException { TempTableSynchronization synch = null; if (context == null || transactionMode == TransactionMode.NONE) { return null; } TransactionContext tc = context.getTransactionContext(); if (tc == null || tc.getTransactionType() == Scope.NONE) { return null; } String transactionId = tc.getTransactionId(); synch = synchronizations.get(transactionId); if (synch == null) { boolean success = false; try { synch = new TempTableSynchronization(transactionId); synchronizations.put(transactionId, synch); tc.getTransaction().registerSynchronization(synch); success = true; } catch (RollbackException e) { throw new TeiidProcessingException(QueryPlugin.Event.TEIID30223, e); } catch (SystemException e) { throw new TeiidProcessingException(QueryPlugin.Event.TEIID30224, e); } finally { if (!success) { synchronizations.remove(transactionId); } } } return synch; }
private TempTable getTempTable( String tempTableID, Command command, BufferManager buffer, boolean delegate, boolean forUpdate, CommandContext context) throws TeiidProcessingException { final TempTable tempTable = tempTables.get(tempTableID); if (tempTable != null) { // isolate if needed if (forUpdate) { if (transactionMode == TransactionMode.ISOLATE_WRITES) { TransactionContext tc = context.getTransactionContext(); if (tc != null) { TempTableSynchronization synch = getSynchronization(context); if (synch != null && synch.existingTables.contains(tempTable.getId())) { TempTable result = synch.tables.get(tempTableID); if (result == null) { synchronized (synch) { if (synch.isCompleted()) { throw new AssertionError("Expected active transaction"); // $NON-NLS-1$ } if (!tempTable.getActive().compareAndSet(0, 1)) { throw new TeiidProcessingException( QueryPlugin.Event.TEIID30227, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30227, tempTableID)); } synch.tables.put(tempTableID, tempTable.clone()); } } return tempTable; } } else if (tempTable.getActive().get() != 0) { throw new TeiidProcessingException( QueryPlugin.Event.TEIID30227, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30227, tempTableID)); } } } else if (transactionMode == TransactionMode.ISOLATE_READS) { TransactionContext tc = context.getTransactionContext(); if (tc != null && tc.getIsolationLevel() > Connection.TRANSACTION_READ_COMMITTED) { TempTableSynchronization synch = getSynchronization(context); if (synch != null) { TempTable result = synch.tables.get(tempTableID); if (result == null) { result = tempTable; synchronized (synch) { if (!synch.isCompleted()) { synch.tables.put(tempTableID, tempTable); result.getActive().getAndIncrement(); } } } return result; } } } return tempTable; } if (delegate && this.parentTempTableStore != null) { return this.parentTempTableStore.getTempTable( tempTableID, command, buffer, delegate, forUpdate, context); } return null; }
/** * 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. * * @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) { LogManager.logTrace( org.teiid.logging.LogConstants.CTX_DQP, "Finished program", program); // $NON-NLS-1$ // 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 { if (inst instanceof RepeatedInstruction) { LogManager.logTrace( org.teiid.logging.LogConstants.CTX_DQP, "Executing repeated instruction", inst); //$NON-NLS-1$ RepeatedInstruction loop = (RepeatedInstruction) inst; if (loop.testCondition(this)) { LogManager.logTrace( org.teiid.logging.LogConstants.CTX_DQP, "Passed condition, executing program " + loop.getNestedProgram()); // $NON-NLS-1$ inst.process(this); this.push(loop.getNestedProgram()); continue; } LogManager.logTrace( org.teiid.logging.LogConstants.CTX_DQP, "Exiting repeated instruction", inst); //$NON-NLS-1$ loop.postInstruction(this); } else { LogManager.logTrace( org.teiid.logging.LogConstants.CTX_DQP, "Executing instruction", inst); // $NON-NLS-1$ inst.process(this); this.evaluator.close(); } } catch (RuntimeException e) { throw e; } 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(); } this.pop(false); // allow the current program to go out of scope 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 try { tc.getTransaction().setRollbackOnly(); } catch (IllegalStateException e1) { throw new TeiidComponentException(e1); } catch (SystemException e1) { throw new TeiidComponentException(e1); } } } 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; }