xtern commented on code in PR #2846: URL: https://github.com/apache/ignite-3/pull/2846#discussion_r1409593572
########## modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/tx/ScriptTransactionHandler.java: ########## @@ -0,0 +1,319 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.sql.engine.tx; + +import static org.apache.ignite.lang.ErrorGroups.Sql.RUNTIME_ERR; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import org.apache.calcite.sql.SqlNode; +import org.apache.ignite.internal.sql.engine.SqlQueryType; +import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCommitTransaction; +import org.apache.ignite.internal.sql.engine.sql.IgniteSqlStartTransaction; +import org.apache.ignite.internal.sql.engine.sql.IgniteSqlStartTransactionMode; +import org.apache.ignite.internal.sql.engine.sql.ParsedResult; +import org.apache.ignite.internal.sql.engine.util.Commons; +import org.apache.ignite.internal.tx.InternalTransaction; +import org.apache.ignite.internal.util.AsyncCursor; +import org.apache.ignite.sql.ExternalTransactionNotSupportedException; +import org.apache.ignite.sql.SqlException; +import org.apache.ignite.tx.IgniteTransactions; +import org.apache.ignite.tx.TransactionOptions; +import org.jetbrains.annotations.Nullable; + +/** + * Starts an implicit transaction if there is no external transaction. Supports script transaction management using + * {@link SqlQueryType#TX_CONTROL} statements. + */ +public class ScriptTransactionHandler extends QueryTransactionHandler { + /** No-op transaction wrapper. */ + private static final QueryTransactionWrapper NOOP_TX_WRAPPER = new NoopTransactionWrapper(); + + /** Wraps a transaction, which is managed by SQL engine via {@link SqlQueryType#TX_CONTROL} statements. */ + private volatile @Nullable ManagedTransactionWrapper wrapper; + + public ScriptTransactionHandler(IgniteTransactions transactions, @Nullable InternalTransaction externalTransaction) { + super(transactions, externalTransaction); + } + + @Override + protected @Nullable InternalTransaction activeTransaction() { + return externalTransaction == null ? scriptTransaction() : externalTransaction; + } + + /** + * Starts a transaction if there is no external transaction. + * + * @param parsedResult Parse result. + * @param cursorFut Cursor future for the current statement. + * @return Transaction wrapper. + */ + public QueryTransactionWrapper startScriptTxIfNeeded( + ParsedResult parsedResult, + CompletableFuture<? extends AsyncCursor<?>> cursorFut + ) { + try { + SqlQueryType queryType = parsedResult.queryType(); + + if (queryType == SqlQueryType.TX_CONTROL) { + if (externalTransaction != null) { + throw new ExternalTransactionNotSupportedException(); + } + + return handleTxControlStatement(parsedResult.parsedTree()); + } + + ManagedTransactionWrapper wrapper = this.wrapper; + + if (wrapper == null) { + return startTxIfNeeded(queryType); + } + + validateStatement(parsedResult.queryType(), wrapper.unwrap()); + + return wrapper.forStatement(queryType, cursorFut); + } catch (SqlException e) { + InternalTransaction scriptTx = scriptTransaction(); + + if (scriptTx != null) { + scriptTx.rollback(); + } + + throw e; + } + } + + private @Nullable InternalTransaction scriptTransaction() { + ManagedTransactionWrapper hld = wrapper; + + return hld != null ? hld.unwrap() : null; + } + + private QueryTransactionWrapper handleTxControlStatement(SqlNode node) { + ManagedTransactionWrapper txWrapper = this.wrapper; + + if (node instanceof IgniteSqlCommitTransaction) { + if (txWrapper == null) { + return NOOP_TX_WRAPPER; + } + + this.wrapper = null; + + return txWrapper.forCommit(); Review Comment: We have decided that in the current implementation, only the RW transaction have limitation - that all cursors must be closed. Because our current RO transactions are just a timestamp, and it looks like we don't need to block script execution with the RO transaction. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
