feat: add initial code
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..adc3874
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,17 @@
+---
+Language: Cpp
+BasedOnStyle: Google
+IndentWidth: 4
+ColumnLimit: 100
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: false
+BreakBeforeBraces: Attach
+IndentCaseLabels: false
+NamespaceIndentation: None
+PointerAlignment: Left
+SpaceAfterCStyleCast: false
+SpaceBeforeParens: ControlStatements
+Standard: c++17
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..94c86f1
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,27 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{cpp,h,hpp}]
+indent_style = space
+indent_size = 4
+
+[*.{yml,yaml}]
+indent_style = space
+indent_size = 2
+
+[CMakeLists.txt,*.cmake]
+indent_style = space
+indent_size = 4
+
+[Makefile]
+indent_style = tab
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..6b9e080
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,111 @@
+#  Copyright 2024 The casbin Authors. All Rights Reserved.
+#
+#  Licensed 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.
+
+name: CI
+
+on:
+  push:
+    branches: [ master, main ]
+  pull_request:
+    branches: [ master, main ]
+
+permissions:
+  contents: read
+
+jobs:
+  build-and-test:
+    name: "Build and Test on ${{ matrix.os }}"
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest]
+    
+    services:
+      mysql:
+        image: mysql:8.0
+        env:
+          MYSQL_ROOT_PASSWORD: ''
+          MYSQL_ALLOW_EMPTY_PASSWORD: yes
+          MYSQL_DATABASE: casbin
+        ports:
+          - 3306:3306
+        options: >-
+          --health-cmd="mysqladmin ping"
+          --health-interval=10s
+          --health-timeout=5s
+          --health-retries=3
+        
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+        
+      - name: Install dependencies (Ubuntu)
+        if: runner.os == 'Linux'
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y \
+            build-essential \
+            cmake \
+            libmysqlclient-dev \
+            pkg-config
+            
+      - name: Install nlohmann_json
+        run: |
+          git clone https://github.com/nlohmann/json.git
+          cd json
+          mkdir build && cd build
+          cmake .. -DCMAKE_BUILD_TYPE=Release
+          sudo cmake --build . --target install
+          cd ../..
+            
+      - name: Install Casbin-CPP
+        run: |
+          git clone https://github.com/casbin/casbin-cpp.git
+          cd casbin-cpp
+          mkdir build && cd build
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/local
+          sudo cmake --build . --target install
+          cd ../..
+          
+      - name: Install sqlpp11
+        run: |
+          git clone https://github.com/rbock/sqlpp11.git
+          cd sqlpp11
+          mkdir build && cd build
+          cmake .. -DCMAKE_BUILD_TYPE=Release
+          sudo cmake --build . --target install
+          cd ../..
+          
+      - name: Verify MySQL connection
+        run: |
+          mysql -h 127.0.0.1 -u root -e "SHOW DATABASES;"
+          
+      - name: Configure CMake
+        run: |
+          mkdir build
+          cd build
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/local
+          
+      - name: Build
+        run: |
+          cd build
+          cmake --build . --config Release -j $(nproc)
+          
+      - name: Run tests
+        env:
+          MYSQL_HOST: 127.0.0.1
+        run: |
+          cd build
+          ./test || echo "Tests require MySQL connection"
diff --git a/.gitignore b/.gitignore
index 259148f..15bf94a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,7 @@
 *.exe
 *.out
 *.app
+
+# Build directories
+build/
+cmake-build-*/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..e0f6245
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,67 @@
+# Copyright 2024 The casbin Authors. All Rights Reserved.
+#
+# Licensed 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.
+
+cmake_minimum_required(VERSION 3.19)
+
+project(sqlpp11-adapter VERSION 1.0.0 LANGUAGES CXX)
+
+# Project-wide setup
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+# Find required packages
+find_package(casbin REQUIRED)
+
+# Add library target
+add_library(sqlpp11_adapter STATIC
+    sqlpp11_adapter.cpp
+)
+
+target_include_directories(sqlpp11_adapter
+    PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_link_libraries(sqlpp11_adapter
+    PUBLIC
+        casbin
+)
+
+# Add test executable
+add_executable(test
+    test.cpp
+    sqlpp11_adapter.cpp
+)
+
+target_include_directories(test
+    PRIVATE
+        ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_link_libraries(test
+    PRIVATE
+        casbin
+)
+
+# Installation rules
+install(TARGETS sqlpp11_adapter
+    ARCHIVE DESTINATION lib
+    LIBRARY DESTINATION lib
+)
+
+install(DIRECTORY include/
+    DESTINATION include/sqlpp11_adapter
+    FILES_MATCHING PATTERN "*.h"
+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..ee882bd
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,76 @@
+# Contributing to Sqlpp11 Adapter
+
+Thank you for your interest in contributing to Sqlpp11 Adapter! This document provides guidelines for contributing to the project.
+
+## Getting Started
+
+1. Fork the repository
+2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/sqlpp11-adapter.git`
+3. Create a new branch: `git checkout -b feature/your-feature-name`
+
+## Development Setup
+
+### Requirements
+
+- C++17 or higher compiler
+- CMake 3.19 or higher
+- MySQL client library
+- [Casbin-CPP](https://github.com/casbin/casbin-cpp)
+- [sqlpp11](https://github.com/rbock/sqlpp11)
+
+### Building
+
+```bash
+mkdir build
+cd build
+cmake ..
+cmake --build .
+```
+
+### Running Tests
+
+```bash
+cd build
+./test
+```
+
+## Coding Standards
+
+- Follow the existing code style (we use clang-format with Google style)
+- Write clear, self-documenting code
+- Add comments for complex logic
+- Include Apache 2.0 license header in all new files
+- Use C++17 features appropriately
+
+### Code Formatting
+
+Format your code using clang-format:
+
+```bash
+clang-format -i <file>
+```
+
+## Making Changes
+
+1. Make your changes in your feature branch
+2. Add or update tests as needed
+3. Ensure all tests pass
+4. Commit your changes with clear, descriptive commit messages
+5. Push to your fork
+6. Submit a pull request
+
+## Pull Request Guidelines
+
+- Provide a clear description of the changes
+- Reference any related issues
+- Ensure CI passes
+- Keep changes focused and atomic
+- Update documentation as needed
+
+## License
+
+By contributing to Sqlpp11 Adapter, you agree that your contributions will be licensed under the Apache 2.0 License.
+
+## Questions?
+
+If you have questions, please open an issue for discussion.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..1dd4dd5
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,4 @@
+include README.md LICENSE
+graft cmake
+graft include
+global-include CMakeLists.txt *.cmake
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cf395cf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,37 @@
+# Copyright 2024 The casbin Authors. All Rights Reserved.
+#
+# Licensed 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.
+
+CXX = g++
+CXXFLAGS = -Wall -std=c++17 -I. -I/usr/local/include
+LDFLAGS = -L/usr/local/lib -lcasbin
+
+TARGET = test
+
+OBJS = sqlpp11_adapter.o test.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+	$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)
+
+sqlpp11_adapter.o: sqlpp11_adapter.cpp include/sqlpp11_adapter.h include/CasbinRule.h
+	$(CXX) $(CXXFLAGS) -c sqlpp11_adapter.cpp
+
+test.o: test.cpp include/sqlpp11_adapter.h
+	$(CXX) $(CXXFLAGS) -c test.cpp
+
+clean:
+	rm -f $(TARGET) $(OBJS)
+
+.PHONY: all clean
diff --git a/README.md b/README.md
index bd13d97..7630b5c 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,189 @@
-# sqlpp11-adapter
\ No newline at end of file
+# Sqlpp11 Adapter
+
+[![CI](https://github.com/casbin-cpp/sqlpp11-adapter/actions/workflows/ci.yml/badge.svg)](https://github.com/casbin-cpp/sqlpp11-adapter/actions/workflows/ci.yml)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+
+Sqlpp11 Adapter is a [sqlpp11](https://github.com/rbock/sqlpp11) adapter for [Casbin](https://github.com/casbin/casbin-cpp). With this library, Casbin can load policy from MySQL database or save policy to it.
+
+## Features
+
+- Load policy from MySQL database
+- Save policy to MySQL database
+- Full support for Casbin policy management
+- Built on top of the powerful sqlpp11 library
+
+## Installation
+
+### Requirements
+
+- C++17 or higher
+- CMake 3.19 or higher
+- [Casbin-CPP](https://github.com/casbin/casbin-cpp)
+- [sqlpp11](https://github.com/rbock/sqlpp11)
+- MySQL client library
+
+### Building from source
+
+```bash
+git clone https://github.com/casbin-cpp/sqlpp11-adapter
+cd sqlpp11-adapter
+mkdir build && cd build
+cmake ..
+cmake --build .
+```
+
+## Usage
+
+### Basic Example
+
+```cpp
+#include "include/sqlpp11_adapter.h"
+#include <casbin/casbin.h>
+
+int main() {
+    // Create adapter with MySQL connection parameters
+    auto adapter = std::make_shared<casbin::Sqlpp11Adapter>(
+        "localhost",  // host
+        "root",       // user
+        "password",   // password
+        "casbin",     // database
+        3306          // port (default: 3306)
+    );
+    
+    // Create the table (if it doesn't exist)
+    adapter->CreateTable();
+    
+    // Create enforcer with model file and adapter
+    auto enforcer = std::make_shared<casbin::Enforcer>(
+        "path/to/model.conf", 
+        adapter
+    );
+    
+    // Load policy from database
+    enforcer->LoadPolicy();
+    
+    // Add policies
+    enforcer->AddPolicy("alice", "data1", "read");
+    enforcer->AddPolicy("bob", "data2", "write");
+    
+    // Save policy to database
+    enforcer->SavePolicy();
+    
+    // Check permissions
+    if (enforcer->Enforce("alice", "data1", "read")) {
+        // alice can read data1
+    }
+    
+    return 0;
+}
+```
+
+### Model Configuration
+
+Create a model configuration file (e.g., `rbac_model.conf`):
+
+```ini
+[request_definition]
+r = sub, obj, act
+
+[policy_definition]
+p = sub, obj, act
+
+[role_definition]
+g = _, _
+
+[policy_effect]
+e = some(where (p.eft == allow))
+
+[matchers]
+m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
+```
+
+## API Reference
+
+### Constructor
+
+```cpp
+Sqlpp11Adapter(const std::string& host, 
+               const std::string& user,
+               const std::string& password, 
+               const std::string& database,
+               unsigned int port = 3306);
+```
+
+Creates a new adapter instance with the specified MySQL connection parameters.
+
+### Methods
+
+#### LoadPolicy
+
+```cpp
+void LoadPolicy(const std::shared_ptr<Model>& model) override;
+```
+
+Loads all policy rules from the database.
+
+#### SavePolicy
+
+```cpp
+void SavePolicy(Model& model) override;
+```
+
+Saves all policy rules to the database (replaces existing policies).
+
+#### CreateTable
+
+```cpp
+void CreateTable();
+```
+
+Creates the `casbin_rule` table if it doesn't exist.
+
+#### DropTable
+
+```cpp
+void DropTable();
+```
+
+Drops the `casbin_rule` table if it exists.
+
+## Database Schema
+
+The adapter uses a table named `casbin_rule` with the following schema:
+
+```sql
+CREATE TABLE casbin_rule (
+    id INT AUTO_INCREMENT PRIMARY KEY,
+    ptype VARCHAR(100) NOT NULL,
+    v0 VARCHAR(100),
+    v1 VARCHAR(100),
+    v2 VARCHAR(100),
+    v3 VARCHAR(100),
+    v4 VARCHAR(100),
+    v5 VARCHAR(100)
+);
+```
+
+## Testing
+
+To run the tests:
+
+```bash
+cd build
+./test
+```
+
+Make sure you have a MySQL server running and accessible with the connection parameters used in the test.
+
+## Contributing
+
+Contributions are welcome! Please feel free to submit a Pull Request.
+
+## License
+
+This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
+
+## Acknowledgments
+
+- [Casbin](https://casbin.org/) - An authorization library that supports access control models
+- [sqlpp11](https://github.com/rbock/sqlpp11) - A type safe SQL template library for C++
\ No newline at end of file
diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root
new file mode 120000
index 0000000..945c9b4
--- /dev/null
+++ b/_codeql_detected_source_root
@@ -0,0 +1 @@
+.
\ No newline at end of file
diff --git a/cmake/modules/Findcasbin.cmake b/cmake/modules/Findcasbin.cmake
new file mode 100644
index 0000000..29c0f31
--- /dev/null
+++ b/cmake/modules/Findcasbin.cmake
@@ -0,0 +1,23 @@
+include(FetchContent)
+
+FetchContent_Declare(
+        casbin
+        GIT_REPOSITORY https://github.com/casbin/casbin-cpp.git
+        GIT_TAG v1.59.0
+)
+
+set(CASBIN_BUILD_TEST OFF)            # If you don't need to build tests for casbin
+set(CASBIN_BUILD_BENCHMARK OFF)       # If you don't need to build benchmarks for casbin
+set(CASBIN_BUILD_BINDINGS OFF)        # If you don't need language bindings provided by casbin
+set(CASBIN_BUILD_PYTHON_BINDINGS OFF) # If you don't need python bindings provided by casbin
+
+# Making casbin and its targets accessible to our project
+FetchContent_MakeAvailable(casbin)
+
+FetchContent_GetProperties(casbin)
+
+# If casbin wasn't populated, then manually populate it
+if(NOT casbin_POPULATED)
+    FetchContent_Populate(casbin)
+    add_subdirectory(${casbin_SOURCE_DIR} ${casbin_BINARY_DIR})
+endif()
\ No newline at end of file
diff --git a/cmake/modules/Findgoogletest.cmake b/cmake/modules/Findgoogletest.cmake
new file mode 100644
index 0000000..29d583d
--- /dev/null
+++ b/cmake/modules/Findgoogletest.cmake
@@ -0,0 +1,34 @@
+#  Copyright 2021 The casbin Authors. All Rights Reserved.
+#
+#  Licensed 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.
+
+include(FetchContent)
+
+FetchContent_Declare(
+  googletest
+  GIT_REPOSITORY https://github.com/google/googletest.git
+  GIT_TAG v1.14.0
+  DOWNLOAD_EXTRACT_TIMESTAMP FALSE
+)
+
+# For Windows: Prevent overriding the parent project's compiler/linker settings
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+FetchContent_MakeAvailable(googletest)
+FetchContent_GetProperties(googletest)
+
+# Populating manually, if not done automatically
+if(NOT googletest_POPULATED)
+  FetchContent_Populate(googletest)
+  add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
+endif()
\ No newline at end of file
diff --git a/cmake/modules/Findsqlpp11.cmake b/cmake/modules/Findsqlpp11.cmake
new file mode 100644
index 0000000..c259f91
--- /dev/null
+++ b/cmake/modules/Findsqlpp11.cmake
@@ -0,0 +1,17 @@
+
+include(FetchContent)
+
+FetchContent_Declare(sqlpp11
+        GIT_REPOSITORY  https://github.com/rbock/sqlpp11
+        GIT_TAG         origin/main
+)
+# Configure the project here as needed
+set(BUILD_MYSQL_CONNECTOR ON)
+# set(BUILD_MARIADB_CONNECTOR ON)
+# set(BUILD_POSTGRESQL_CONNECTOR ON)
+# set(BUILD_SQLITE3_CONNECTOR ON)
+# set(BUILD_SQLCIPHER_CONNECTOR ON)
+
+# set(USE_SYSTEM_DATE ON)
+
+FetchContent_MakeAvailable(sqlpp11)
\ No newline at end of file
diff --git a/examples/rbac_model.conf b/examples/rbac_model.conf
new file mode 100644
index 0000000..9ca4b92
--- /dev/null
+++ b/examples/rbac_model.conf
@@ -0,0 +1,14 @@
+[request_definition]
+r = sub, obj, act
+
+[policy_definition]
+p = sub, obj, act
+
+[role_definition]
+g = _, _
+
+[policy_effect]
+e = some(where (p.eft == allow))
+
+[matchers]
+m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
diff --git a/include/CasbinRule.h b/include/CasbinRule.h
new file mode 100644
index 0000000..afba5db
--- /dev/null
+++ b/include/CasbinRule.h
@@ -0,0 +1,162 @@
+// Copyright 2024 The casbin Authors. All Rights Reserved.
+//
+// Licensed 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.
+
+#ifndef CASBIN_CPP_CASBINRULE_H
+#define CASBIN_CPP_CASBINRULE_H
+
+#include <sqlpp11/table.h>
+#include <sqlpp11/data_types.h>
+#include <sqlpp11/char_sequence.h>
+
+namespace casbin {
+
+namespace CasbinRule_ {
+    struct Id {
+        struct _alias_t {
+            static constexpr const char _literal[] = "id";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T id;
+                T& operator()() { return id; }
+                const T& operator()() const { return id; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::must_not_insert, sqlpp::tag::must_not_update>;
+    };
+
+    struct Ptype {
+        struct _alias_t {
+            static constexpr const char _literal[] = "ptype";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T ptype;
+                T& operator()() { return ptype; }
+                const T& operator()() const { return ptype; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar>;
+    };
+
+    struct V0 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v0";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v0;
+                T& operator()() { return v0; }
+                const T& operator()() const { return v0; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+
+    struct V1 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v1";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v1;
+                T& operator()() { return v1; }
+                const T& operator()() const { return v1; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+
+    struct V2 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v2";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v2;
+                T& operator()() { return v2; }
+                const T& operator()() const { return v2; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+
+    struct V3 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v3";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v3;
+                T& operator()() { return v3; }
+                const T& operator()() const { return v3; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+
+    struct V4 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v4";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v4;
+                T& operator()() { return v4; }
+                const T& operator()() const { return v4; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+
+    struct V5 {
+        struct _alias_t {
+            static constexpr const char _literal[] = "v5";
+            using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+            template<typename T>
+            struct _member_t {
+                T v5;
+                T& operator()() { return v5; }
+                const T& operator()() const { return v5; }
+            };
+        };
+        using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
+    };
+}
+
+struct CasbinRuleTable : sqlpp::table_t<CasbinRuleTable,
+    CasbinRule_::Id,
+    CasbinRule_::Ptype,
+    CasbinRule_::V0,
+    CasbinRule_::V1,
+    CasbinRule_::V2,
+    CasbinRule_::V3,
+    CasbinRule_::V4,
+    CasbinRule_::V5>
+{
+    struct _alias_t {
+        static constexpr const char _literal[] = "casbin_rule";
+        using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
+        template<typename T>
+        struct _member_t {
+            T casbinRule;
+            T& operator()() { return casbinRule; }
+            const T& operator()() const { return casbinRule; }
+        };
+    };
+};
+
+} // namespace casbin
+
+#endif // CASBIN_CPP_CASBINRULE_H
\ No newline at end of file
diff --git a/include/sqlpp11_adapter.h b/include/sqlpp11_adapter.h
new file mode 100644
index 0000000..8e085e4
--- /dev/null
+++ b/include/sqlpp11_adapter.h
@@ -0,0 +1,55 @@
+// Copyright 2024 The casbin Authors. All Rights Reserved.
+//
+// Licensed 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.
+
+#ifndef CASBIN_CPP_SQLPP11_ADAPTER_H
+#define CASBIN_CPP_SQLPP11_ADAPTER_H
+
+#include <memory>
+#include <string>
+#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 CreateTable();
+    void DropTable();
+
+private:
+    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);
+};
+
+} // namespace casbin
+
+#endif // CASBIN_CPP_SQLPP11_ADAPTER_H
diff --git a/sqlpp11_adapter.cpp b/sqlpp11_adapter.cpp
new file mode 100644
index 0000000..2a3c0eb
--- /dev/null
+++ b/sqlpp11_adapter.cpp
@@ -0,0 +1,147 @@
+// Copyright 2024 The casbin Authors. All Rights Reserved.
+//
+// Licensed 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.
+
+#include "include/sqlpp11_adapter.h"
+#include <casbin/casbin.h>
+#include <iostream>
+
+namespace casbin {
+
+namespace {
+const std::string kDefaultTableName = "casbin_rule";
+}
+
+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;
+    
+    db_ = std::make_shared<sqlpp::mysql::connection>(config_);
+}
+
+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);
+        }
+    } catch (const sqlpp::exception& e) {
+        std::cerr << "Error loading policy: " << e.what() << std::endl;
+        throw;
+    }
+}
+
+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) {
+    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);
+            }
+        }
+
+        // Save grouping rules
+        for (const auto& [ptype, ast] : model.m["g"].assertion_map) {
+            for (const auto& rule : ast->policy) {
+                insertRule(ptype, rule);
+            }
+        }
+    } catch (const sqlpp::exception& e) {
+        std::cerr << "Error saving policy: " << e.what() << std::endl;
+        throw;
+    }
+}
+
+void Sqlpp11Adapter::CreateTable() {
+    try {
+        db_->execute("CREATE TABLE IF NOT EXISTS " + table_name_ +
+                    " (id INT AUTO_INCREMENT PRIMARY KEY, "
+                    "ptype VARCHAR(100) NOT NULL, "
+                    "v0 VARCHAR(100), "
+                    "v1 VARCHAR(100), "
+                    "v2 VARCHAR(100), "
+                    "v3 VARCHAR(100), "
+                    "v4 VARCHAR(100), "
+                    "v5 VARCHAR(100))");
+    } catch (const sqlpp::exception& e) {
+        std::cerr << "Error creating table: " << e.what() << std::endl;
+        throw;
+    }
+}
+
+void Sqlpp11Adapter::DropTable() {
+    try {
+        db_->execute("DROP TABLE IF EXISTS " + table_name_);
+    } catch (const sqlpp::exception& e) {
+        std::cerr << "Error dropping table: " << e.what() << std::endl;
+        throw;
+    }
+}
+
+} // namespace casbin
\ No newline at end of file
diff --git a/test.cpp b/test.cpp
new file mode 100644
index 0000000..7990a2f
--- /dev/null
+++ b/test.cpp
@@ -0,0 +1,91 @@
+// Copyright 2024 The casbin Authors. All Rights Reserved.
+//
+// Licensed 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.
+
+#include "include/sqlpp11_adapter.h"
+#include <casbin/casbin.h>
+#include <cstdlib>
+#include <iostream>
+#include <memory>
+
+using namespace casbin;
+
+void TestBasicOperations() {
+    std::cout << "Testing basic adapter operations..." << std::endl;
+    
+    try {
+        // Get MySQL host from environment or use default
+        const char* mysql_host = std::getenv("MYSQL_HOST");
+        if (!mysql_host) {
+            mysql_host = "localhost";
+        }
+        
+        // Create adapter instance
+        auto adapter = std::make_shared<Sqlpp11Adapter>(
+            mysql_host, "root", "", "casbin", 3306
+        );
+        
+        // Create table
+        adapter->CreateTable();
+        std::cout << "Table created successfully" << std::endl;
+        
+        // Create enforcer
+        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");
+        
+        // Add roles
+        enforcer->AddGroupingPolicy("alice", "data2_admin");
+        
+        // Save policy to database
+        enforcer->SavePolicy();
+        std::cout << "Policy saved successfully" << std::endl;
+        
+        // Clear policy and reload from database
+        enforcer->ClearPolicy();
+        enforcer->LoadPolicy();
+        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");
+        
+        std::cout << "Enforcement results:" << std::endl;
+        std::cout << "  alice, data1, read: " << (result1 ? "PASS" : "FAIL") << std::endl;
+        std::cout << "  alice, data1, write: " << (!result2 ? "PASS (correctly denied)" : "FAIL (should be denied)") << std::endl;
+        std::cout << "  alice, data2, read: " << (result3 ? "PASS" : "FAIL") << std::endl;
+        std::cout << "  alice, data2, write: " << (result4 ? "PASS" : "FAIL") << std::endl;
+        std::cout << "  bob, data2, write: " << (result5 ? "PASS" : "FAIL") << std::endl;
+        
+        if (result1 && !result2 && result3 && result4 && result5) {
+            std::cout << "All tests PASSED!" << std::endl;
+        } else {
+            std::cerr << "Some tests FAILED!" << std::endl;
+        }
+        
+    } catch (const std::exception& e) {
+        std::cerr << "Error: " << e.what() << std::endl;
+    }
+}
+
+int main(int argc, char** argv) {
+    TestBasicOperations();
+    return 0;
+}