2021-03-31 17:55:04 +00:00
|
|
|
#include <Interpreters/InterpreterTransactionControlQuery.h>
|
|
|
|
#include <Parsers/ASTTransactionControl.h>
|
|
|
|
#include <Interpreters/TransactionLog.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int LOGICAL_ERROR;
|
|
|
|
extern const int INVALID_TRANSACTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockIO InterpreterTransactionControlQuery::execute()
|
|
|
|
{
|
2021-05-13 18:48:36 +00:00
|
|
|
if (!getContext()->hasSessionContext())
|
2021-03-31 17:55:04 +00:00
|
|
|
throw Exception(ErrorCodes::INVALID_TRANSACTION, "Transaction Control Language queries are allowed only inside session");
|
|
|
|
|
2021-05-13 18:48:36 +00:00
|
|
|
ContextPtr session_context = getContext()->getSessionContext();
|
2021-03-31 17:55:04 +00:00
|
|
|
const auto & tcl = query_ptr->as<const ASTTransactionControl &>();
|
|
|
|
|
|
|
|
switch (tcl.action)
|
|
|
|
{
|
|
|
|
case ASTTransactionControl::BEGIN:
|
|
|
|
return executeBegin(session_context);
|
|
|
|
case ASTTransactionControl::COMMIT:
|
|
|
|
return executeCommit(session_context);
|
|
|
|
case ASTTransactionControl::ROLLBACK:
|
|
|
|
return executeRollback(session_context);
|
|
|
|
}
|
2021-06-02 20:03:44 +00:00
|
|
|
assert(false);
|
|
|
|
__builtin_unreachable();
|
2021-03-31 17:55:04 +00:00
|
|
|
}
|
|
|
|
|
2021-05-13 18:48:36 +00:00
|
|
|
BlockIO InterpreterTransactionControlQuery::executeBegin(ContextPtr session_context)
|
2021-03-31 17:55:04 +00:00
|
|
|
{
|
2021-05-13 18:48:36 +00:00
|
|
|
if (session_context->getCurrentTransaction())
|
2021-03-31 17:55:04 +00:00
|
|
|
throw Exception(ErrorCodes::INVALID_TRANSACTION, "Nested transactions are not supported");
|
|
|
|
|
|
|
|
auto txn = TransactionLog::instance().beginTransaction();
|
2021-05-13 18:48:36 +00:00
|
|
|
session_context->initCurrentTransaction(txn);
|
|
|
|
getContext()->setCurrentTransaction(txn);
|
2021-03-31 17:55:04 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-05-13 18:48:36 +00:00
|
|
|
BlockIO InterpreterTransactionControlQuery::executeCommit(ContextPtr session_context)
|
2021-03-31 17:55:04 +00:00
|
|
|
{
|
2021-05-13 18:48:36 +00:00
|
|
|
auto txn = session_context->getCurrentTransaction();
|
2021-03-31 17:55:04 +00:00
|
|
|
if (!txn)
|
|
|
|
throw Exception(ErrorCodes::INVALID_TRANSACTION, "There is no current transaction");
|
|
|
|
if (txn->getState() != MergeTreeTransaction::RUNNING)
|
|
|
|
throw Exception(ErrorCodes::INVALID_TRANSACTION, "Transaction is not in RUNNING state");
|
|
|
|
|
|
|
|
TransactionLog::instance().commitTransaction(txn);
|
2021-05-13 18:48:36 +00:00
|
|
|
session_context->setCurrentTransaction(nullptr);
|
2021-03-31 17:55:04 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-05-13 18:48:36 +00:00
|
|
|
BlockIO InterpreterTransactionControlQuery::executeRollback(ContextPtr session_context)
|
2021-03-31 17:55:04 +00:00
|
|
|
{
|
2021-05-13 18:48:36 +00:00
|
|
|
auto txn = session_context->getCurrentTransaction();
|
2021-03-31 17:55:04 +00:00
|
|
|
if (!txn)
|
|
|
|
throw Exception(ErrorCodes::INVALID_TRANSACTION, "There is no current transaction");
|
|
|
|
if (txn->getState() == MergeTreeTransaction::COMMITTED)
|
|
|
|
throw Exception(ErrorCodes::LOGICAL_ERROR, "Transaction is in COMMITTED state");
|
|
|
|
|
|
|
|
if (txn->getState() == MergeTreeTransaction::RUNNING)
|
|
|
|
TransactionLog::instance().rollbackTransaction(txn);
|
2021-05-13 18:48:36 +00:00
|
|
|
session_context->setCurrentTransaction(nullptr);
|
2021-03-31 17:55:04 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|