Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction statement #2012

Merged
merged 1 commit into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/antlr4/Cypher.g4
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ kU_DDL
| kU_CreateRelTableGroup
| kU_CreateRdfGraph
| kU_DropTable
| kU_AlterTable;
| kU_AlterTable
;

kU_CreateNodeTable
: CREATE SP NODE SP TABLE SP oC_SchemaName SP? '(' SP? kU_PropertyDefinitions SP? ( ',' SP? kU_CreateNodeConstraint ) SP? ')' ;
Expand Down Expand Up @@ -173,7 +174,32 @@ oC_Statement
| kU_CopyFromCSV
| kU_CopyTO
| kU_StandaloneCall
| kU_CreateMacro ;
| kU_CreateMacro
| kU_Transaction ;

kU_Transaction
: BEGIN SP READ SP TRANSACTION
| BEGIN SP WRITE SP TRANSACTION
| COMMIT
| COMMIT_SKIP_CHECKPOINT
| ROLLBACK
| ROLLBACK_SKIP_CHECKPOINT;

BEGIN : ( 'B' | 'b' ) ( 'E' | 'e' ) ( 'G' | 'g' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ;

TRANSACTION : ( 'T' | 't' ) ( 'R' | 'r' ) ( 'A' | 'a' ) ( 'N' | 'n' ) ( 'S' | 's' ) ( 'A' | 'a' ) ( 'C' | 'c' ) ( 'T' | 't' ) ( 'I' | 'i' ) ( 'O' | 'o' ) ( 'N' | 'n' ) ;

READ : ( 'R' | 'r' ) ( 'E' | 'e' ) ( 'A' | 'a' ) ( 'D' | 'd' ) ;

WRITE : ( 'W' | 'w' ) ( 'R' | 'r' ) ( 'I' | 'i' ) ( 'T' | 't' ) ( 'E' | 'e' ) ;

COMMIT : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'T' | 't' ) ;

COMMIT_SKIP_CHECKPOINT : ( 'C' | 'c' ) ( 'O' | 'o' ) ( 'M' | 'm' ) ( 'M' | 'm' ) ( 'I' | 'i' ) ( 'T' | 't' ) '_' ( 'S' | 's' ) ( 'K' | 'k' ) ( 'I' | 'i' ) ( 'P' | 'p' ) '_' ( 'C' | 'c' ) ( 'H' | 'h' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'K' | 'k' ) ( 'P' | 'p' ) ( 'O' | 'o' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'T' | 't' ) ;
andyfengHKU marked this conversation as resolved.
Show resolved Hide resolved

ROLLBACK : ( 'R' | 'r' ) ( 'O' | 'o' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'B' | 'b' ) ( 'A' | 'a' ) ( 'C' | 'c' ) ( 'K' | 'k' ) ;

ROLLBACK_SKIP_CHECKPOINT: ( 'R' | 'r' ) ( 'O' | 'o' ) ( 'L' | 'l' ) ( 'L' | 'l' ) ( 'B' | 'b' ) ( 'A' | 'a' ) ( 'C' | 'c' ) ( 'K' | 'k' ) '_' ( 'S' | 's' ) ( 'K' | 'k' ) ( 'I' | 'i' ) ( 'P' | 'p' ) '_' ( 'C' | 'c' ) ( 'H' | 'h' ) ( 'E' | 'e' ) ( 'C' | 'c' ) ( 'K' | 'k' ) ( 'P' | 'p' ) ( 'O' | 'o' ) ( 'I' | 'i' ) ( 'N' | 'n' ) ( 'T' | 't' ) ;

oC_Query
: oC_RegularQuery ;
Expand Down
1 change: 1 addition & 0 deletions src/binder/bind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_library(
kuzu_binder_bind
OBJECT
bind_standalone_call.cpp
bind_transaction.cpp
bind_create_macro.cpp
bind_copy.cpp
bind_ddl.cpp
Expand Down
16 changes: 16 additions & 0 deletions src/binder/bind/bind_transaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "binder/binder.h"
#include "binder/bound_transaction_statement.h"
#include "parser/transaction_statement.h"

using namespace kuzu::parser;

namespace kuzu {
namespace binder {

std::unique_ptr<BoundStatement> Binder::bindTransaction(const Statement& statement) {
auto transactionStatement = reinterpret_cast<const TransactionStatement&>(statement);
return std::make_unique<BoundTransactionStatement>(transactionStatement.getTransactionAction());
}

} // namespace binder
} // namespace kuzu
3 changes: 3 additions & 0 deletions src/binder/binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ std::unique_ptr<BoundStatement> Binder::bind(const Statement& statement) {
case StatementType::CREATE_MACRO: {
boundStatement = bindCreateMacro(statement);
} break;
case StatementType::TRANSACTION: {
boundStatement = bindTransaction(statement);
} break;
default:
throw NotImplementedException("Binder::bind");
}
Expand Down
3 changes: 3 additions & 0 deletions src/binder/bound_statement_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ void BoundStatementVisitor::visit(const kuzu::binder::BoundStatement& statement)
case StatementType::CREATE_MACRO: {
visitCreateMacro(statement);
} break;
case StatementType::TRANSACTION: {
visitTransaction(statement);
} break;
default:
throw NotImplementedException("BoundStatementVisitor::visit");
}
Expand Down
4 changes: 3 additions & 1 deletion src/binder/visitor/statement_read_write_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ bool StatementReadWriteAnalyzer::isReadOnly(const kuzu::binder::BoundStatement&
}

void StatementReadWriteAnalyzer::visitQueryPart(const NormalizedQueryPart& queryPart) {
readOnly = !queryPart.hasUpdatingClause();
if (queryPart.hasUpdatingClause()) {
readOnly = false;
}
}

} // namespace binder
Expand Down
16 changes: 0 additions & 16 deletions src/c_api/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,6 @@ void kuzu_connection_destroy(kuzu_connection* connection) {
free(connection);
}

void kuzu_connection_begin_read_only_transaction(kuzu_connection* connection) {
static_cast<Connection*>(connection->_connection)->beginReadOnlyTransaction();
}

void kuzu_connection_begin_write_transaction(kuzu_connection* connection) {
static_cast<Connection*>(connection->_connection)->beginWriteTransaction();
}

void kuzu_connection_commit(kuzu_connection* connection) {
static_cast<Connection*>(connection->_connection)->commit();
}

void kuzu_connection_rollback(kuzu_connection* connection) {
static_cast<Connection*>(connection->_connection)->rollback();
}

void kuzu_connection_set_max_num_thread_for_exec(
kuzu_connection* connection, uint64_t num_threads) {
static_cast<Connection*>(connection->_connection)->setMaxNumThreadForExec(num_threads);
Expand Down
1 change: 0 additions & 1 deletion src/catalog/catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "catalog/rel_table_group_schema.h"
#include "common/ser_deser.h"
#include "common/string_utils.h"
#include "storage/storage_utils.h"

using namespace kuzu::common;
using namespace kuzu::storage;
Expand Down
3 changes: 3 additions & 0 deletions src/include/binder/binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class Binder {
/*** bind create macro ***/
std::unique_ptr<BoundStatement> bindCreateMacro(const parser::Statement& statement);

/*** bind transaction ***/
std::unique_ptr<BoundStatement> bindTransaction(const parser::Statement& statement);

/*** bind explain ***/
std::unique_ptr<BoundStatement> bindExplain(const parser::Statement& statement);

Expand Down
1 change: 1 addition & 0 deletions src/include/binder/bound_statement_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class BoundStatementVisitor {
virtual void visitStandaloneCall(const BoundStatement& statement) {}
virtual void visitExplain(const BoundStatement& statement);
virtual void visitCreateMacro(const BoundStatement& statement) {}
virtual void visitTransaction(const BoundStatement& statement) {}

void visitReadingClause(const BoundReadingClause& readingClause);
virtual void visitMatch(const BoundReadingClause& readingClause) {}
Expand Down
23 changes: 23 additions & 0 deletions src/include/binder/bound_transaction_statement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include "bound_statement.h"
#include "transaction/transaction_action.h"

namespace kuzu {
namespace binder {

class BoundTransactionStatement : public BoundStatement {
public:
explicit BoundTransactionStatement(transaction::TransactionAction transactionAction)
: BoundStatement{common::StatementType::TRANSACTION,
BoundStatementResult::createEmptyResult()},
transactionAction{transactionAction} {}

inline transaction::TransactionAction getTransactionAction() const { return transactionAction; }

private:
transaction::TransactionAction transactionAction;
};

} // namespace binder
} // namespace kuzu
10 changes: 9 additions & 1 deletion src/include/binder/visitor/statement_read_write_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@ namespace binder {

class StatementReadWriteAnalyzer : public BoundStatementVisitor {
public:
StatementReadWriteAnalyzer() : BoundStatementVisitor(), readOnly{false} {}
StatementReadWriteAnalyzer() : BoundStatementVisitor(), readOnly{true} {}

bool isReadOnly(const BoundStatement& statement);

private:
void visitCreateTable(const BoundStatement& statement) override { readOnly = false; }
andyfengHKU marked this conversation as resolved.
Show resolved Hide resolved
void visitDropTable(const BoundStatement& statement) override { readOnly = false; }
void visitRenameTable(const BoundStatement& statement) override { readOnly = false; }
void visitAddProperty(const BoundStatement& statement) override { readOnly = false; }
void visitDropProperty(const BoundStatement& statement) override { readOnly = false; }
void visitRenameProperty(const BoundStatement& statement) override { readOnly = false; }
void visitCopy(const BoundStatement& statement) override { readOnly = false; }
void visitCreateMacro(const BoundStatement& statement) override { readOnly = false; }
void visitQueryPart(const NormalizedQueryPart& queryPart) final;

private:
Expand Down
20 changes: 0 additions & 20 deletions src/include/c_api/kuzu.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,26 +217,6 @@ KUZU_C_API kuzu_connection* kuzu_connection_init(kuzu_database* database);
* @param connection The connection instance to destroy.
*/
KUZU_C_API void kuzu_connection_destroy(kuzu_connection* connection);
/**
* @brief Begins a read-only transaction in the given connection.
* @param connection The connection instance to begin read-only transaction.
*/
KUZU_C_API void kuzu_connection_begin_read_only_transaction(kuzu_connection* connection);
/**
* @brief Begins a write transaction in the given connection.
* @param connection The connection instance to begin write transaction.
*/
KUZU_C_API void kuzu_connection_begin_write_transaction(kuzu_connection* connection);
/**
* @brief Commits the current transaction.
* @param connection The connection instance to commit transaction.
*/
KUZU_C_API void kuzu_connection_commit(kuzu_connection* connection);
/**
* @brief Rollbacks the current transaction.
* @param connection The connection instance to rollback transaction.
*/
KUZU_C_API void kuzu_connection_rollback(kuzu_connection* connection);
/**
* @brief Sets the maximum number of threads to use for executing queries.
* @param connection The connection instance to set max number of threads for execution.
Expand Down
1 change: 1 addition & 0 deletions src/include/common/statement_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum class StatementType : uint8_t {
STANDALONE_CALL = 21,
EXPLAIN = 22,
CREATE_MACRO = 23,
TRANSACTION = 30,
};

struct StatementTypeUtils {
Expand Down
9 changes: 7 additions & 2 deletions src/include/main/client_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Binder;
}

namespace main {
class Database;

struct ActiveQuery {
explicit ActiveQuery();
Expand All @@ -38,9 +39,9 @@ class ClientContext {
friend class VarLengthExtendMaxDepthSetting;

public:
explicit ClientContext();
explicit ClientContext(Database* database);

~ClientContext() = default;
~ClientContext();

inline void interrupt() { activeQuery.interrupted = true; }

Expand All @@ -56,13 +57,17 @@ class ClientContext {

std::string getCurrentSetting(std::string optionName);

transaction::Transaction* getActiveTransaction() const;
transaction::TransactionContext* getTransactionContext() const;

private:
inline void resetActiveQuery() { activeQuery.reset(); }

uint64_t numThreadsForExecution;
ActiveQuery activeQuery;
uint64_t timeoutInMS;
uint32_t varLengthExtendMaxDepth;
std::unique_ptr<transaction::TransactionContext> transactionContext;
};

} // namespace main
Expand Down
54 changes: 1 addition & 53 deletions src/include/main/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,6 @@ class Connection {
friend class kuzu::benchmark::Benchmark;
friend class kuzu::testing::TinySnbDDLTest;

public:
/**
* If the connection is in AUTO_COMMIT mode any query over the connection will be wrapped around
* a transaction and committed (even if the query is READ_ONLY).
* If the connection is in MANUAL transaction mode, which happens only if an application
* manually begins a transaction (see below), then an application has to manually commit or
* rollback the transaction by calling commit() or rollback().
*
* AUTO_COMMIT is the default mode when a Connection is created. If an application calls
* begin[ReadOnly/Write]Transaction at any point, the mode switches to MANUAL. This creates
* an "active transaction" in the connection. When a connection is in MANUAL mode and the
* active transaction is rolled back or committed, then the active transaction is removed (so
* the connection no longer has an active transaction) and the mode automatically switches
* back to AUTO_COMMIT.
* Note: When a Connection object is deconstructed, if the connection has an active (manual)
* transaction, then the active transaction is rolled back.
*/
enum class ConnectionTransactionMode : uint8_t { AUTO_COMMIT = 0, MANUAL = 1 };

public:
/**
* @brief Creates a connection to the database.
Expand Down Expand Up @@ -180,32 +161,9 @@ class Connection {
}

protected:
ConnectionTransactionMode getTransactionMode();
void setTransactionModeNoLock(ConnectionTransactionMode newTransactionMode);

std::unique_ptr<QueryResult> query(const std::string& query, const std::string& encodedJoin);
// Note: This is only added for testing recovery algorithms in unit tests. Do not use
// this otherwise.
void commitButSkipCheckpointingForTestingRecovery();
// Note: This is only added for testing recovery algorithms in unit tests. Do not use
// this otherwise.
void rollbackButSkipCheckpointingForTestingRecovery();
// Note: This is only added for testing recovery algorithms in unit tests. Do not use
// this otherwise.
transaction::Transaction* getActiveTransaction();
// used in API test

uint64_t getActiveTransactionID();
bool hasActiveTransaction();
void commitNoLock();
void rollbackIfNecessaryNoLock();

void beginTransactionNoLock(transaction::TransactionType type);

void commitOrRollbackNoLock(
transaction::TransactionAction action, bool skipCheckpointForTesting = false);

std::unique_ptr<QueryResult> queryResultWithError(std::string& errMsg);
std::unique_ptr<QueryResult> queryResultWithError(const std::string& errMsg);

std::unique_ptr<PreparedStatement> prepareNoLock(const std::string& query,
bool enumerateAllPlans = false, std::string joinOrder = std::string{});
Expand All @@ -226,21 +184,11 @@ class Connection {
std::unique_ptr<QueryResult> executeAndAutoCommitIfNecessaryNoLock(
PreparedStatement* preparedStatement, uint32_t planIdx = 0u);

void beginTransactionIfAutoCommit(PreparedStatement* preparedStatement);

private:
inline std::unique_ptr<QueryResult> getQueryResultWithError(std::string exceptionMessage) {
rollbackIfNecessaryNoLock();
return queryResultWithError(exceptionMessage);
}

void addScalarFunction(std::string name, function::vector_function_definitions definitions);

protected:
Database* database;
std::unique_ptr<ClientContext> clientContext;
std::unique_ptr<transaction::Transaction> activeTransaction;
ConnectionTransactionMode transactionMode;
std::mutex mtx;
};

Expand Down
1 change: 1 addition & 0 deletions src/include/main/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Database {
friend class Connection;
friend class StorageDriver;
friend class kuzu::testing::BaseGraphTest;
friend class transaction::TransactionContext;

public:
/**
Expand Down
3 changes: 1 addition & 2 deletions src/include/main/kuzu_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ class PhysicalPlan;

namespace transaction {
class Transaction;
enum class TransactionType : uint8_t;
enum class TransactionAction : uint8_t;
class TransactionManager;
class TransactionContext;
} // namespace transaction

} // namespace kuzu
Expand Down
1 change: 1 addition & 0 deletions src/include/main/prepared_statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class PreparedStatement {
* @return the prepared statement is allowed to be part of an active transaction.
*/
KUZU_API bool allowActiveTransaction() const;
bool isTransactionStatement() const;
/**
* @return the query is prepared successfully or not.
*/
Expand Down
3 changes: 1 addition & 2 deletions src/include/parser/explain_statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ namespace parser {

class ExplainStatement : public Statement {
public:
explicit ExplainStatement(
std::unique_ptr<Statement> statementToExplain, common::ExplainType explainType)
ExplainStatement(std::unique_ptr<Statement> statementToExplain, common::ExplainType explainType)
: Statement{common::StatementType::EXPLAIN},
statementToExplain{std::move(statementToExplain)}, explainType{explainType} {}

Expand Down
Loading