@Override public Optional<TransactionId> getTransactionId() { return session.getTransactionId(); }
default void activateTransaction(Session session, boolean transactionControl, AccessControl accessControl) { if (!session.getTransactionId().isPresent()) { return; } // reactivate existing transaction TransactionId transactionId = session.getTransactionId().get(); if (transactionControl) { trySetActive(transactionId); } else { checkAndSetActive(transactionId); } } }
@Override public ListenableFuture<?> execute(Rollback statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.getTransactionId().isPresent()) { throw new PrestoException(NOT_IN_TRANSACTION, "No transaction in progress"); } TransactionId transactionId = session.getTransactionId().get(); stateMachine.clearTransactionId(); transactionManager.asyncAbort(transactionId); return immediateFuture(null); }
private SessionBuilder(Session session) { requireNonNull(session, "session is null"); checkArgument(!session.getTransactionId().isPresent(), "Session builder cannot be created from a session in a transaction"); this.sessionPropertyManager = session.sessionPropertyManager; this.queryId = session.queryId; this.transactionId = session.transactionId.orElse(null); this.clientTransactionSupport = session.clientTransactionSupport; this.identity = session.identity; this.source = session.source.orElse(null); this.catalog = session.catalog.orElse(null); this.path = session.path; this.schema = session.schema.orElse(null); this.traceToken = requireNonNull(session.traceToken, "traceToken is null"); this.timeZoneKey = session.timeZoneKey; this.locale = session.locale; this.remoteUserAddress = session.remoteUserAddress.orElse(null); this.userAgent = session.userAgent.orElse(null); this.clientInfo = session.clientInfo.orElse(null); this.clientTags = ImmutableSet.copyOf(session.clientTags); this.startTime = session.startTime; this.systemProperties.putAll(session.systemProperties); this.catalogSessionProperties.putAll(session.unprocessedCatalogProperties); this.preparedStatements.putAll(session.preparedStatements); }
@Override public ListenableFuture<?> execute(Commit statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.getTransactionId().isPresent()) { throw new PrestoException(NOT_IN_TRANSACTION, "No transaction in progress"); } TransactionId transactionId = session.getTransactionId().get(); stateMachine.clearTransactionId(); return transactionManager.asyncCommit(transactionId); }
public static LocalQueryRunner queryRunnerWithInitialTransaction(Session defaultSession) { checkArgument(!defaultSession.getTransactionId().isPresent(), "Already in transaction!"); return new LocalQueryRunner(defaultSession, new FeaturesConfig(), new NodeSpillConfig(), true, false); }
requireNonNull(callback, "callback is null"); boolean managedTransaction = !session.getTransactionId().isPresent(); TransactionInfo transactionInfo = transactionManager.getTransactionInfo(session.getTransactionId().get()); checkState(transactionInfo.getIsolationLevel().meetsRequirementOf(isolationLevel), "Cannot provide %s isolation with existing transaction isolation: %s", isolationLevel, transactionInfo.getIsolationLevel()); checkState(!transactionInfo.isReadOnly() || readOnly, "Cannot provide read-write semantics with existing read-only transaction"); if (managedTransaction && transactionManager.transactionExists(transactionSession.getTransactionId().get())) { if (success) { getFutureValue(transactionManager.asyncCommit(transactionSession.getTransactionId().get())); transactionManager.asyncAbort(transactionSession.getTransactionId().get());
public boolean transitionToFinishing() { queryStateTimer.beginFinishing(); if (!queryState.setIf(FINISHING, currentState -> currentState != FINISHING && !currentState.isDone())) { return false; } Optional<TransactionId> transactionId = session.getTransactionId(); if (transactionId.isPresent() && transactionManager.transactionExists(transactionId.get()) && transactionManager.isAutoCommit(transactionId.get())) { ListenableFuture<?> commitFuture = transactionManager.asyncCommit(transactionId.get()); Futures.addCallback(commitFuture, new FutureCallback<Object>() { @Override public void onSuccess(@Nullable Object result) { transitionToFinished(); } @Override public void onFailure(Throwable throwable) { transitionToFailed(throwable); } }, directExecutor()); } else { transitionToFinished(); } return true; }
properties.build(), session.getPreparedStatements(), session.getTransactionId().map(Object::toString).orElse(null), clientRequestTimeout);
@Override public ListenableFuture<?> execute(StartTransaction statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters) { Session session = stateMachine.getSession(); if (!session.isClientTransactionSupport()) { throw new PrestoException(StandardErrorCode.INCOMPATIBLE_CLIENT, "Client does not support transactions"); } if (session.getTransactionId().isPresent()) { throw new PrestoException(StandardErrorCode.NOT_SUPPORTED, "Nested transactions not supported"); } Optional<IsolationLevel> isolationLevel = extractIsolationLevel(statement); Optional<Boolean> readOnly = extractReadOnly(statement); TransactionId transactionId = transactionManager.beginTransaction( isolationLevel.orElse(TransactionManager.DEFAULT_ISOLATION), readOnly.orElse(TransactionManager.DEFAULT_READ_ONLY), false); stateMachine.setStartedTransactionId(transactionId); // Since the current session does not contain this new transaction ID, we need to manually mark it as inactive // when this statement completes. transactionManager.trySetInactive(transactionId); return immediateFuture(null); }
if (!session.getTransactionId().isPresent() && !transactionControl) {
public boolean transitionToCanceled() { cleanupQueryQuietly(); queryStateTimer.endQuery(); // NOTE: The failure cause must be set before triggering the state change, so // listeners can observe the exception. This is safe because the failure cause // can only be observed if the transition to FAILED is successful. failureCause.compareAndSet(null, toFailure(new PrestoException(USER_CANCELED, "Query was canceled"))); boolean canceled = queryState.setIf(FAILED, currentState -> !currentState.isDone()); if (canceled) { session.getTransactionId().ifPresent(transactionId -> { if (transactionManager.isAutoCommit(transactionId)) { transactionManager.asyncAbort(transactionId); } else { transactionManager.fail(transactionId); } }); } return canceled; }
public boolean transitionToFailed(Throwable throwable) { cleanupQueryQuietly(); queryStateTimer.endQuery(); // NOTE: The failure cause must be set before triggering the state change, so // listeners can observe the exception. This is safe because the failure cause // can only be observed if the transition to FAILED is successful. requireNonNull(throwable, "throwable is null"); failureCause.compareAndSet(null, toFailure(throwable)); boolean failed = queryState.setIf(FAILED, currentState -> !currentState.isDone()); if (failed) { QUERY_STATE_LOG.debug(throwable, "Query %s failed", queryId); session.getTransactionId().ifPresent(transactionId -> { if (transactionManager.isAutoCommit(transactionId)) { transactionManager.asyncAbort(transactionId); } else { transactionManager.fail(transactionId); } }); } else { QUERY_STATE_LOG.debug(throwable, "Failure after query %s finished", queryId); } return failed; }
@Test public void testRollback() { TransactionManager transactionManager = createTestTransactionManager(); Session session = sessionBuilder() .setTransactionId(transactionManager.beginTransaction(false)) .build(); QueryStateMachine stateMachine = createQueryStateMachine("ROLLBACK", session, transactionManager); assertTrue(stateMachine.getSession().getTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); getFutureValue(new RollbackTask().execute(new Rollback(), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertTrue(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); }
@Test public void testCommit() { TransactionManager transactionManager = createTestTransactionManager(); Session session = sessionBuilder() .setTransactionId(transactionManager.beginTransaction(false)) .build(); QueryStateMachine stateMachine = createQueryStateMachine("COMMIT", session, transactionManager); assertTrue(stateMachine.getSession().getTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); getFutureValue(new CommitTask().execute(new Commit(), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertTrue(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); }
@Test public void testNonTransactionalClient() { Session session = sessionBuilder().build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); try { getFutureValue(new StartTransactionTask().execute(new StartTransaction(ImmutableList.of()), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); fail(); } catch (PrestoException e) { assertEquals(e.getErrorCode(), INCOMPATIBLE_CLIENT.toErrorCode()); } assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); }
@Test public void testStartTransaction() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); getFutureValue(new StartTransactionTask().execute(new StartTransaction(ImmutableList.of()), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertTrue(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); TransactionInfo transactionInfo = transactionManager.getTransactionInfo(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().get()); assertFalse(transactionInfo.isAutoCommitContext()); }
@Test public void testStartTransactionTooManyIsolationLevels() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); try { getFutureValue(new StartTransactionTask().execute( new StartTransaction(ImmutableList.of(new Isolation(Isolation.Level.READ_COMMITTED), new Isolation(Isolation.Level.READ_COMMITTED))), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); fail(); } catch (SemanticException e) { assertEquals(e.getCode(), INVALID_TRANSACTION_MODE); } assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); }
@Test public void testStartTransactionExplicitModes() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); getFutureValue(new StartTransactionTask().execute( new StartTransaction(ImmutableList.of(new Isolation(Isolation.Level.SERIALIZABLE), new TransactionAccessMode(true))), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertTrue(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); assertEquals(transactionManager.getAllTransactionInfos().size(), 1); TransactionInfo transactionInfo = transactionManager.getTransactionInfo(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().get()); assertEquals(transactionInfo.getIsolationLevel(), IsolationLevel.SERIALIZABLE); assertTrue(transactionInfo.isReadOnly()); assertFalse(transactionInfo.isAutoCommitContext()); }
@Test public void testStartTransactionTooManyAccessModes() { Session session = sessionBuilder() .setClientTransactionSupport() .build(); TransactionManager transactionManager = createTestTransactionManager(); QueryStateMachine stateMachine = createQueryStateMachine("START TRANSACTION", session, transactionManager); assertFalse(stateMachine.getSession().getTransactionId().isPresent()); try { getFutureValue(new StartTransactionTask().execute( new StartTransaction(ImmutableList.of(new TransactionAccessMode(true), new TransactionAccessMode(true))), transactionManager, metadata, new AllowAllAccessControl(), stateMachine, emptyList())); fail(); } catch (SemanticException e) { assertEquals(e.getCode(), INVALID_TRANSACTION_MODE); } assertTrue(transactionManager.getAllTransactionInfos().isEmpty()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).isClearTransactionId()); assertFalse(stateMachine.getQueryInfo(Optional.empty()).getStartedTransactionId().isPresent()); }