This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-cpp-sqlpp11-adapter.git


The following commit(s) were added to refs/heads/master by this push:
     new b4f134c  fix: make the adapter build against casbin-cpp and sqlpp11's 
MySQL connector
b4f134c is described below

commit b4f134cb166817d6b89b6892d63027f62515aba5
Author: Yang Luo <[email protected]>
AuthorDate: Wed Oct 7 10:37:59 2026 +0800

    fix: make the adapter build against casbin-cpp and sqlpp11's MySQL connector
---
 .github/workflows/ci.yml  |  12 ++--
 CMakeLists.txt            |   7 +-
 include/sqlpp11_adapter.h |  22 ++++---
 sqlpp11_adapter.cpp       | 160 +++++++++++++++++++++++++++-------------------
 test.cpp                  |  30 ++++-----
 5 files changed, 131 insertions(+), 100 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6b9e080..817da52 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -66,16 +66,16 @@ jobs:
           git clone https://github.com/nlohmann/json.git
           cd json
           mkdir build && cd build
-          cmake .. -DCMAKE_BUILD_TYPE=Release
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=OFF
           sudo cmake --build . --target install
           cd ../..
             
       - name: Install Casbin-CPP
         run: |
-          git clone https://github.com/casbin/casbin-cpp.git
+          git clone https://github.com/apache/casbin-cpp.git
           cd casbin-cpp
           mkdir build && cd build
-          cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/local
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/local 
-DCASBIN_BUILD_TEST=OFF -DCASBIN_BUILD_BENCHMARK=OFF 
-DCASBIN_BUILD_PYTHON_BINDINGS=OFF
           sudo cmake --build . --target install
           cd ../..
           
@@ -84,7 +84,7 @@ jobs:
           git clone https://github.com/rbock/sqlpp11.git
           cd sqlpp11
           mkdir build && cd build
-          cmake .. -DCMAKE_BUILD_TYPE=Release
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_MYSQL_CONNECTOR=ON 
-DBUILD_TESTING=OFF
           sudo cmake --build . --target install
           cd ../..
           
@@ -106,6 +106,4 @@ jobs:
       - name: Run tests
         env:
           MYSQL_HOST: 127.0.0.1
-        run: |
-          cd build
-          ./test || echo "Tests require MySQL connection"
+        run: ./build/test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e0f6245..712cf28 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
 
 # Find required packages
 find_package(casbin REQUIRED)
+find_package(Sqlpp11 REQUIRED COMPONENTS MySQL)
 
 # Add library target
 add_library(sqlpp11_adapter STATIC
@@ -36,7 +37,8 @@ target_include_directories(sqlpp11_adapter
 
 target_link_libraries(sqlpp11_adapter
     PUBLIC
-        casbin
+        casbin::casbin
+        sqlpp11::mysql
 )
 
 # Add test executable
@@ -52,7 +54,8 @@ target_include_directories(test
 
 target_link_libraries(test
     PRIVATE
-        casbin
+        casbin::casbin
+        sqlpp11::mysql
 )
 
 # Installation rules
diff --git a/include/sqlpp11_adapter.h b/include/sqlpp11_adapter.h
index 8e085e4..b160b00 100644
--- a/include/sqlpp11_adapter.h
+++ b/include/sqlpp11_adapter.h
@@ -20,34 +20,36 @@
 #include <vector>
 
 #include "casbin/persist/adapter.h"
-#include "casbin/util/util.h"
 #include "sqlpp11/mysql/mysql.h"
 #include "sqlpp11/sqlpp11.h"
 #include "CasbinRule.h"
 
 namespace casbin {
 
-class Model;
-
 class Sqlpp11Adapter : public Adapter {
 public:
     Sqlpp11Adapter(const std::string& host, const std::string& user,
                    const std::string& password, const std::string& database,
                    unsigned int port = 3306);
-    
+
     void LoadPolicy(const std::shared_ptr<Model>& model) override;
-    void SavePolicy(Model& model) override;
-    
+    void SavePolicy(const std::shared_ptr<Model>& model) override;
+    void AddPolicy(std::string sec, std::string p_type, 
std::vector<std::string> rule) override;
+    void RemovePolicy(std::string sec, std::string p_type, 
std::vector<std::string> rule) override;
+    void RemoveFilteredPolicy(std::string sec, std::string p_type, int 
field_index, std::vector<std::string> field_values) override;
+    bool IsFiltered() override;
+    bool IsValid() override;
+
     void CreateTable();
     void DropTable();
 
 private:
-    sqlpp::mysql::connection_config config_;
+    std::shared_ptr<sqlpp::mysql::connection_config> config_;
     std::shared_ptr<sqlpp::mysql::connection> db_;
     std::string table_name_;
-    
-    template<typename Row>
-    void LoadPolicyLine(const Row& row, const std::shared_ptr<Model>& model);
+
+    void InsertRule(const std::string& p_type, const std::vector<std::string>& 
rule);
+    void RemoveRules(const std::string& p_type, int field_index, const 
std::vector<std::string>& field_values);
 };
 
 } // namespace casbin
diff --git a/sqlpp11_adapter.cpp b/sqlpp11_adapter.cpp
index 2a3c0eb..d65b50b 100644
--- a/sqlpp11_adapter.cpp
+++ b/sqlpp11_adapter.cpp
@@ -26,13 +26,16 @@ Sqlpp11Adapter::Sqlpp11Adapter(const std::string& host, 
const std::string& user,
                                const std::string& password, const std::string& 
database,
                                unsigned int port)
     : table_name_(kDefaultTableName) {
-    config_.host = host;
-    config_.user = user;
-    config_.password = password;
-    config_.database = database;
-    config_.port = port;
-    config_.debug = false;
-    
+    filtered = false;
+
+    config_ = std::make_shared<sqlpp::mysql::connection_config>();
+    config_->host = host;
+    config_->user = user;
+    config_->password = password;
+    config_->database = database;
+    config_->port = port;
+    config_->debug = false;
+
     db_ = std::make_shared<sqlpp::mysql::connection>(config_);
 }
 
@@ -40,9 +43,23 @@ void Sqlpp11Adapter::LoadPolicy(const 
std::shared_ptr<Model>& model) {
     CasbinRuleTable casbin_rule;
 
     try {
-        auto result = 
(*db_)(sqlpp::select(all_of(casbin_rule)).from(casbin_rule).unconditionally());
-        for (const auto& row : result) {
-            LoadPolicyLine(row, model);
+        for (const auto& row : 
(*db_)(sqlpp::select(all_of(casbin_rule)).from(casbin_rule).unconditionally())) 
{
+            std::string line = row.ptype.value();
+            bool done = false;
+            auto append = [&line, &done](const auto& field) {
+                if (done || field.is_null()) {
+                    done = true;
+                    return;
+                }
+                line += ", " + field.value();
+            };
+            append(row.v0);
+            append(row.v1);
+            append(row.v2);
+            append(row.v3);
+            append(row.v4);
+            append(row.v5);
+            LoadPolicyLine(line, model);
         }
     } catch (const sqlpp::exception& e) {
         std::cerr << "Error loading policy: " << e.what() << std::endl;
@@ -50,66 +67,19 @@ void Sqlpp11Adapter::LoadPolicy(const 
std::shared_ptr<Model>& model) {
     }
 }
 
-template<typename Row>
-void Sqlpp11Adapter::LoadPolicyLine(const Row& row,
-                                    const std::shared_ptr<Model>& model) {
-    std::vector<std::string> tokens;
-    tokens.push_back(row.ptype);
-    
-    if (!row.v0.is_null()) tokens.push_back(row.v0.value());
-    if (!row.v1.is_null()) tokens.push_back(row.v1.value());
-    if (!row.v2.is_null()) tokens.push_back(row.v2.value());
-    if (!row.v3.is_null()) tokens.push_back(row.v3.value());
-    if (!row.v4.is_null()) tokens.push_back(row.v4.value());
-    if (!row.v5.is_null()) tokens.push_back(row.v5.value());
-
-    if (tokens.size() < 2) {
-        return;  // Need at least ptype and one value
-    }
-
-    std::string key = tokens[0];
-    std::vector<std::string> sec_tokens(tokens.begin() + 1, tokens.end());
-    
-    if (model->HasSection("p") && model->HasAssertion("p", key)) {
-        model->AddPolicy("p", key, sec_tokens);
-    } else if (model->HasSection("g") && model->HasAssertion("g", key)) {
-        model->AddPolicy("g", key, sec_tokens);
-    }
-}
-
-void Sqlpp11Adapter::SavePolicy(Model& model) {
+void Sqlpp11Adapter::SavePolicy(const std::shared_ptr<Model>& model) {
     try {
         DropTable();
         CreateTable();
 
-        CasbinRuleTable casbin_rule;
-
-        // Helper lambda to insert a single policy rule
-        auto insertRule = [this, &casbin_rule](const std::string& ptype, 
-                                                const 
std::vector<std::string>& rule) {
-            auto insert = sqlpp::insert_into(casbin_rule).set(
-                casbin_rule.ptype = ptype,
-                casbin_rule.v0 = rule.size() > 0 ? sqlpp::value(rule[0]) : 
sqlpp::null,
-                casbin_rule.v1 = rule.size() > 1 ? sqlpp::value(rule[1]) : 
sqlpp::null,
-                casbin_rule.v2 = rule.size() > 2 ? sqlpp::value(rule[2]) : 
sqlpp::null,
-                casbin_rule.v3 = rule.size() > 3 ? sqlpp::value(rule[3]) : 
sqlpp::null,
-                casbin_rule.v4 = rule.size() > 4 ? sqlpp::value(rule[4]) : 
sqlpp::null,
-                casbin_rule.v5 = rule.size() > 5 ? sqlpp::value(rule[5]) : 
sqlpp::null
-            );
-            (*db_)(insert);
-        };
-
-        // Save policy rules
-        for (const auto& [ptype, ast] : model.m["p"].assertion_map) {
-            for (const auto& rule : ast->policy) {
-                insertRule(ptype, rule);
+        for (const std::string sec : {"p", "g"}) {
+            if (model->m.find(sec) == model->m.end()) {
+                continue;
             }
-        }
-
-        // Save grouping rules
-        for (const auto& [ptype, ast] : model.m["g"].assertion_map) {
-            for (const auto& rule : ast->policy) {
-                insertRule(ptype, rule);
+            for (const auto& [p_type, ast] : model->m[sec].assertion_map) {
+                for (const auto& rule : ast->policy) {
+                    InsertRule(p_type, rule);
+                }
             }
         }
     } catch (const sqlpp::exception& e) {
@@ -118,6 +88,64 @@ void Sqlpp11Adapter::SavePolicy(Model& model) {
     }
 }
 
+void Sqlpp11Adapter::AddPolicy(std::string sec, std::string p_type, 
std::vector<std::string> rule) {
+    InsertRule(p_type, rule);
+}
+
+void Sqlpp11Adapter::RemovePolicy(std::string sec, std::string p_type, 
std::vector<std::string> rule) {
+    RemoveRules(p_type, 0, rule);
+}
+
+void Sqlpp11Adapter::RemoveFilteredPolicy(std::string sec, std::string p_type, 
int field_index, std::vector<std::string> field_values) {
+    RemoveRules(p_type, field_index, field_values);
+}
+
+bool Sqlpp11Adapter::IsFiltered() {
+    return filtered;
+}
+
+bool Sqlpp11Adapter::IsValid() {
+    return db_ != nullptr;
+}
+
+void Sqlpp11Adapter::InsertRule(const std::string& p_type, const 
std::vector<std::string>& rule) {
+    CasbinRuleTable casbin_rule;
+
+    auto field = [&rule](size_t i) {
+        return i < rule.size() ? sqlpp::value_or_null(rule[i]) : 
sqlpp::value_or_null<sqlpp::text>(sqlpp::null);
+    };
+
+    (*db_)(sqlpp::insert_into(casbin_rule).set(
+        casbin_rule.ptype = p_type,
+        casbin_rule.v0 = field(0),
+        casbin_rule.v1 = field(1),
+        casbin_rule.v2 = field(2),
+        casbin_rule.v3 = field(3),
+        casbin_rule.v4 = field(4),
+        casbin_rule.v5 = field(5)));
+}
+
+void Sqlpp11Adapter::RemoveRules(const std::string& p_type, int field_index, 
const std::vector<std::string>& field_values) {
+    CasbinRuleTable casbin_rule;
+
+    auto remove = sqlpp::dynamic_remove_from(*db_, 
casbin_rule).dynamic_where(casbin_rule.ptype == p_type);
+    for (size_t i = 0; i < field_values.size(); i++) {
+        const std::string& value = field_values[i];
+        if (value.empty()) {
+            continue;
+        }
+        switch (field_index + i) {
+        case 0: remove.where.add(casbin_rule.v0 == value); break;
+        case 1: remove.where.add(casbin_rule.v1 == value); break;
+        case 2: remove.where.add(casbin_rule.v2 == value); break;
+        case 3: remove.where.add(casbin_rule.v3 == value); break;
+        case 4: remove.where.add(casbin_rule.v4 == value); break;
+        case 5: remove.where.add(casbin_rule.v5 == value); break;
+        }
+    }
+    (*db_)(remove);
+}
+
 void Sqlpp11Adapter::CreateTable() {
     try {
         db_->execute("CREATE TABLE IF NOT EXISTS " + table_name_ +
@@ -144,4 +172,4 @@ void Sqlpp11Adapter::DropTable() {
     }
 }
 
-} // namespace casbin
\ No newline at end of file
+} // namespace casbin
diff --git a/test.cpp b/test.cpp
index 7990a2f..2f7218b 100644
--- a/test.cpp
+++ b/test.cpp
@@ -20,7 +20,7 @@
 
 using namespace casbin;
 
-void TestBasicOperations() {
+bool TestBasicOperations() {
     std::cout << "Testing basic adapter operations..." << std::endl;
     
     try {
@@ -43,13 +43,13 @@ void TestBasicOperations() {
         auto enforcer = std::make_shared<Enforcer>("examples/rbac_model.conf", 
adapter);
         
         // Add policies
-        enforcer->AddPolicy("alice", "data1", "read");
-        enforcer->AddPolicy("bob", "data2", "write");
-        enforcer->AddPolicy("data2_admin", "data2", "read");
-        enforcer->AddPolicy("data2_admin", "data2", "write");
+        enforcer->AddPolicy({"alice", "data1", "read"});
+        enforcer->AddPolicy({"bob", "data2", "write"});
+        enforcer->AddPolicy({"data2_admin", "data2", "read"});
+        enforcer->AddPolicy({"data2_admin", "data2", "write"});
         
         // Add roles
-        enforcer->AddGroupingPolicy("alice", "data2_admin");
+        enforcer->AddGroupingPolicy({"alice", "data2_admin"});
         
         // Save policy to database
         enforcer->SavePolicy();
@@ -61,11 +61,11 @@ void TestBasicOperations() {
         std::cout << "Policy loaded successfully" << std::endl;
         
         // Test enforcement
-        bool result1 = enforcer->Enforce("alice", "data1", "read");
-        bool result2 = enforcer->Enforce("alice", "data1", "write");
-        bool result3 = enforcer->Enforce("alice", "data2", "read");
-        bool result4 = enforcer->Enforce("alice", "data2", "write");
-        bool result5 = enforcer->Enforce("bob", "data2", "write");
+        bool result1 = enforcer->Enforce({"alice", "data1", "read"});
+        bool result2 = enforcer->Enforce({"alice", "data1", "write"});
+        bool result3 = enforcer->Enforce({"alice", "data2", "read"});
+        bool result4 = enforcer->Enforce({"alice", "data2", "write"});
+        bool result5 = enforcer->Enforce({"bob", "data2", "write"});
         
         std::cout << "Enforcement results:" << std::endl;
         std::cout << "  alice, data1, read: " << (result1 ? "PASS" : "FAIL") 
<< std::endl;
@@ -76,16 +76,16 @@ void TestBasicOperations() {
         
         if (result1 && !result2 && result3 && result4 && result5) {
             std::cout << "All tests PASSED!" << std::endl;
-        } else {
-            std::cerr << "Some tests FAILED!" << std::endl;
+            return true;
         }
+        std::cerr << "Some tests FAILED!" << std::endl;
         
     } catch (const std::exception& e) {
         std::cerr << "Error: " << e.what() << std::endl;
     }
+    return false;
 }
 
 int main(int argc, char** argv) {
-    TestBasicOperations();
-    return 0;
+    return TestBasicOperations() ? 0 : 1;
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to