From 0b076bcf3f74a6458f19b3a1941521efd24dac17 Mon Sep 17 00:00:00 2001 From: xiyang Date: Sun, 21 May 2023 14:07:55 -0400 Subject: [PATCH] Add statement read write analyzer --- src/binder/visitor/CMakeLists.txt | 3 ++- .../visitor/statement_read_write_analyzer.cpp | 16 ++++++++++++++ src/include/binder/bound_statement.h | 2 -- src/include/binder/bound_statement_visitor.h | 6 ++--- .../binder/query/bound_regular_query.h | 9 -------- .../binder/query/normalized_single_query.h | 9 -------- .../visitor/statement_read_write_analyzer.h | 22 +++++++++++++++++++ src/main/connection.cpp | 4 +++- 8 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 src/binder/visitor/statement_read_write_analyzer.cpp create mode 100644 src/include/binder/visitor/statement_read_write_analyzer.h diff --git a/src/binder/visitor/CMakeLists.txt b/src/binder/visitor/CMakeLists.txt index ddf93f29dd..d352a04838 100644 --- a/src/binder/visitor/CMakeLists.txt +++ b/src/binder/visitor/CMakeLists.txt @@ -1,7 +1,8 @@ add_library( kuzu_binder_visitor OBJECT - property_collector.cpp) + property_collector.cpp + statement_read_write_analyzer.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ diff --git a/src/binder/visitor/statement_read_write_analyzer.cpp b/src/binder/visitor/statement_read_write_analyzer.cpp new file mode 100644 index 0000000000..981081bdee --- /dev/null +++ b/src/binder/visitor/statement_read_write_analyzer.cpp @@ -0,0 +1,16 @@ +#include "binder/visitor/statement_read_write_analyzer.h" + +namespace kuzu { +namespace binder { + +bool StatementReadWriteAnalyzer::isReadOnly(const kuzu::binder::BoundStatement& statement) { + visit(statement); + return readOnly; +} + +void StatementReadWriteAnalyzer::visitQueryPart(const NormalizedQueryPart& queryPart) { + readOnly = !queryPart.hasUpdatingClause(); +} + +} // namespace binder +} // namespace kuzu diff --git a/src/include/binder/bound_statement.h b/src/include/binder/bound_statement.h index 963b86ab3e..a2d6af8e32 100644 --- a/src/include/binder/bound_statement.h +++ b/src/include/binder/bound_statement.h @@ -18,8 +18,6 @@ class BoundStatement { inline BoundStatementResult* getStatementResult() const { return statementResult.get(); } - virtual inline bool isReadOnly() const { return false; } - private: common::StatementType statementType; std::unique_ptr statementResult; diff --git a/src/include/binder/bound_statement_visitor.h b/src/include/binder/bound_statement_visitor.h index 0bbd75d33e..e911c017f2 100644 --- a/src/include/binder/bound_statement_visitor.h +++ b/src/include/binder/bound_statement_visitor.h @@ -13,9 +13,9 @@ class BoundStatementVisitor { void visit(const BoundStatement& statement); - void visitRegularQuery(const BoundRegularQuery& regularQuery); - void visitSingleQuery(const NormalizedSingleQuery& singleQuery); - void visitQueryPart(const NormalizedQueryPart& queryPart); + virtual void visitRegularQuery(const BoundRegularQuery& regularQuery); + virtual void visitSingleQuery(const NormalizedSingleQuery& singleQuery); + virtual void visitQueryPart(const NormalizedQueryPart& queryPart); protected: virtual void visitCreateNodeTable(const BoundStatement& statement) {} diff --git a/src/include/binder/query/bound_regular_query.h b/src/include/binder/query/bound_regular_query.h index 74b51fa095..f29e9a2c02 100644 --- a/src/include/binder/query/bound_regular_query.h +++ b/src/include/binder/query/bound_regular_query.h @@ -15,15 +15,6 @@ class BoundRegularQuery : public BoundStatement { ~BoundRegularQuery() override = default; - inline bool isReadOnly() const override { - for (auto& singleQuery : singleQueries) { - if (!singleQuery->isReadOnly()) { - return false; - } - } - return true; - } - inline void addSingleQuery(std::unique_ptr singleQuery) { singleQueries.push_back(std::move(singleQuery)); } diff --git a/src/include/binder/query/normalized_single_query.h b/src/include/binder/query/normalized_single_query.h index 043b239f55..9e4c394497 100644 --- a/src/include/binder/query/normalized_single_query.h +++ b/src/include/binder/query/normalized_single_query.h @@ -11,15 +11,6 @@ class NormalizedSingleQuery { NormalizedSingleQuery() = default; ~NormalizedSingleQuery() = default; - inline bool isReadOnly() const { - for (auto& queryPart : queryParts) { - if (queryPart->hasUpdatingClause()) { - return false; - } - } - return true; - } - inline void appendQueryPart(std::unique_ptr queryPart) { queryParts.push_back(std::move(queryPart)); } diff --git a/src/include/binder/visitor/statement_read_write_analyzer.h b/src/include/binder/visitor/statement_read_write_analyzer.h new file mode 100644 index 0000000000..c63e85ebe6 --- /dev/null +++ b/src/include/binder/visitor/statement_read_write_analyzer.h @@ -0,0 +1,22 @@ +#pragma once + +#include "binder/bound_statement_visitor.h" + +namespace kuzu { +namespace binder { + +class StatementReadWriteAnalyzer : public BoundStatementVisitor { +public: + StatementReadWriteAnalyzer() : BoundStatementVisitor(), readOnly{false} {} + + bool isReadOnly(const BoundStatement& statement); + +private: + void visitQueryPart(const NormalizedQueryPart& queryPart) final; + +private: + bool readOnly; +}; + +} // namespace binder +} // namespace kuzu diff --git a/src/main/connection.cpp b/src/main/connection.cpp index 18e731770a..c62155ec12 100644 --- a/src/main/connection.cpp +++ b/src/main/connection.cpp @@ -1,6 +1,7 @@ #include "main/connection.h" #include "binder/binder.h" +#include "binder/visitor/statement_read_write_analyzer.h" #include "json.hpp" #include "main/database.h" #include "main/plan_printer.h" @@ -165,7 +166,8 @@ std::unique_ptr Connection::prepareNoLock( auto binder = Binder(*database->catalog); auto boundStatement = binder.bind(*statement); preparedStatement->statementType = boundStatement->getStatementType(); - preparedStatement->readOnly = boundStatement->isReadOnly(); + preparedStatement->readOnly = + binder::StatementReadWriteAnalyzer().isReadOnly(*boundStatement); preparedStatement->parameterMap = binder.getParameterMap(); preparedStatement->statementResult = boundStatement->getStatementResult()->copy(); // planning