|
| 1 | +# SQLiteCpp LLM Coding Guide |
| 2 | + |
| 3 | +## Non-Negotiables (MUST Follow) |
| 4 | +- RAII only. Acquire in constructors, release in destructors. |
| 5 | +- NEVER throw in destructors. Use `SQLITECPP_ASSERT()` instead. |
| 6 | +- Errors: use `SQLite::Exception` for throwing APIs; `tryExec()`, `tryExecuteStep()`, `tryReset()` return SQLite codes. |
| 7 | +- C++11 only in core library. C++14 only in `VariadicBind.h` and `ExecuteMany.h`. |
| 8 | +- Public API headers must NOT include `sqlite3.h`. Use `SQLite::OPEN_*` flags from `Database.h`. |
| 9 | +- Export public API with `SQLITECPP_API` from `SQLiteCppExport.h`. |
| 10 | +- Threading: one `Database`/`Statement`/`Column` per thread. |
| 11 | +- Public API must have Doxygen: `@brief`, `@param`, `@return`, `@throw`. |
| 12 | +- Tests required for new functionality in `tests/`. |
| 13 | +- Portability: Windows, Linux, macOS. |
| 14 | +- Style: ASCII only, 4 spaces, Allman braces, max 120 chars, LF line endings, final newline, `#pragma once`. |
| 15 | + |
| 16 | +## Workflow (Common Tasks) |
| 17 | +### Add a Method |
| 18 | +1. Declare in `include/SQLiteCpp/<Class>.h` with Doxygen. |
| 19 | +2. Implement in `src/<Class>.cpp`. |
| 20 | +3. Add tests in `tests/<Class>_test.cpp`. |
| 21 | +4. Update `CHANGELOG.md`. |
| 22 | + |
| 23 | +### Add a Class |
| 24 | +1. Create `include/SQLiteCpp/NewClass.h` and `src/NewClass.cpp`. |
| 25 | +2. Add to `CMakeLists.txt` (`SQLITECPP_SRC` and `SQLITECPP_INC`). |
| 26 | +3. Add to `meson.build`. |
| 27 | +4. Include in `SQLiteCpp.h` if public API. |
| 28 | +5. Create `tests/NewClass_test.cpp`. |
| 29 | +6. Add test to `CMakeLists.txt` and `meson.build`. |
| 30 | + |
| 31 | +### Git Workflow (GitHub Issues) |
| 32 | +**When to create a new branch:** |
| 33 | +- User explicitly mentions working on a task, issue, or feature (e.g., "work on issue #123", "implement feature X") |
| 34 | +- User references a GitHub issue number |
| 35 | + |
| 36 | +**Before starting work:** |
| 37 | +1. Run `git status` to check current branch. |
| 38 | +2. If on `master` or wrong branch, create a task-specific branch from `master`. |
| 39 | + |
| 40 | +**Branch naming:** `<issue>-<type>-<short-description>` |
| 41 | +- `123-fix-short-description` for bug fixes |
| 42 | +- `123-feature-short-description` for new features |
| 43 | + |
| 44 | +**Commits:** |
| 45 | +- Imperative mood, ~50 char first line, body wrapped at 72 chars. |
| 46 | +- Reference issue: `Closes #123` or `Fixes #123`. |
| 47 | + |
| 48 | +```bash |
| 49 | +git fetch origin |
| 50 | +git checkout -b 123-fix-short-description origin/master |
| 51 | +``` |
| 52 | + |
| 53 | +## Common Pitfalls |
| 54 | +- `bind()` is 1-based; `getColumn()` is 0-based. |
| 55 | +- Reusing `Statement` requires `reset()` and `clearBindings()`. |
| 56 | +- `bindNoCopy()` only if data lifetime exceeds statement execution. |
| 57 | +- `execAndGet()` returns a temporary `Column`, copy immediately. |
| 58 | +- `exec()` returns changes for DML, 0 for DDL. |
| 59 | + |
| 60 | +## Build and Test |
| 61 | +### Quick Build Commands |
| 62 | +**Windows (Visual Studio 2022):** |
| 63 | +```batch |
| 64 | +mkdir build |
| 65 | +cd build |
| 66 | +cmake -G "Visual Studio 17 2022" -DSQLITECPP_BUILD_TESTS=ON -DSQLITECPP_BUILD_EXAMPLES=ON .. |
| 67 | +cmake --build . --config Release |
| 68 | +``` |
| 69 | + |
| 70 | +**Windows (using build.bat):** |
| 71 | +```batch |
| 72 | +build.bat |
| 73 | +``` |
| 74 | + |
| 75 | +**Unix/macOS:** |
| 76 | +```bash |
| 77 | +mkdir build && cd build |
| 78 | +cmake -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_BUILD_TESTS=ON -DSQLITECPP_BUILD_EXAMPLES=ON .. |
| 79 | +cmake --build . |
| 80 | +``` |
| 81 | + |
| 82 | +**Meson:** |
| 83 | +```bash |
| 84 | +meson setup builddir -DSQLITECPP_BUILD_TESTS=true -DSQLITECPP_BUILD_EXAMPLES=true |
| 85 | +meson compile -C builddir |
| 86 | +``` |
| 87 | + |
| 88 | +### Essential CMake Options |
| 89 | +| Option | Default | Description | |
| 90 | +|--------|---------|-------------| |
| 91 | +| `SQLITECPP_BUILD_TESTS` | OFF | Build unit tests | |
| 92 | +| `SQLITECPP_BUILD_EXAMPLES` | OFF | Build examples | |
| 93 | +| `SQLITECPP_INTERNAL_SQLITE` | ON | Use bundled sqlite3/ | |
| 94 | +| `BUILD_SHARED_LIBS` | OFF | Build as DLL/shared library | |
| 95 | +| `SQLITE_ENABLE_COLUMN_METADATA` | ON | Enable `getColumnOriginName()` | |
| 96 | + |
| 97 | +### Running Tests |
| 98 | +```bash |
| 99 | +cd build |
| 100 | +ctest --output-on-failure |
| 101 | +ctest --output-on-failure -V |
| 102 | +ctest --output-on-failure -R "Database" |
| 103 | +``` |
| 104 | +```bash |
| 105 | +meson test -C builddir |
| 106 | +meson test -C builddir -v |
| 107 | +``` |
| 108 | + |
| 109 | +### Style Checking |
| 110 | +```bash |
| 111 | +python cpplint.py src/*.cpp include/SQLiteCpp/*.h |
| 112 | +``` |
| 113 | + |
| 114 | +## Troubleshooting |
| 115 | +**MSVC:** |
| 116 | +``` |
| 117 | +c:\path\to\file.cpp(42): error C2065: 'undeclaredVar': undeclared identifier |
| 118 | +c:\path\to\file.cpp(50,15): error C2039: 'foo': is not a member of 'SQLite::Database' |
| 119 | +``` |
| 120 | + |
| 121 | +**GCC/Clang:** |
| 122 | +``` |
| 123 | +src/Database.cpp:42:5: error: use of undeclared identifier 'undeclaredVar' |
| 124 | +include/SQLiteCpp/Database.h:100:10: error: no member named 'foo' in 'SQLite::Database' |
| 125 | +``` |
| 126 | + |
| 127 | +**Linker:** |
| 128 | +``` |
| 129 | +error LNK2019: unresolved external symbol "SQLite::Database::exec" |
| 130 | +``` |
| 131 | + |
| 132 | +Usually means missing SQLiteCpp library or missing source file in build. |
| 133 | + |
| 134 | +## Reference |
| 135 | +### Project Snapshot |
| 136 | +- SQLiteCpp is a lean C++11 RAII wrapper around SQLite3 C APIs. |
| 137 | +- Minimal dependencies (C++11 STL + SQLite3). |
| 138 | +- Cross-platform, thread-safe at SQLite multi-thread level. |
| 139 | +- Keep naming close to SQLite. |
| 140 | +- Public headers avoid `sqlite3.h`; use `SQLite::OPEN_*` flags from `Database.h`. |
| 141 | + |
| 142 | +### Repository Structure |
| 143 | +``` |
| 144 | +SQLiteCpp/ |
| 145 | ++-- include/SQLiteCpp/ # Public headers |
| 146 | +| +-- SQLiteCpp.h # Umbrella include + version macros |
| 147 | +| +-- Database.h # Connection + open flags |
| 148 | +| +-- Statement.h # Prepared statements |
| 149 | +| +-- Column.h # Result column access |
| 150 | +| +-- Transaction.h # RAII transaction |
| 151 | +| +-- Savepoint.h # RAII savepoint |
| 152 | +| +-- Backup.h # Online backup |
| 153 | +| +-- Exception.h # SQLite::Exception |
| 154 | +| +-- Assertion.h # SQLITECPP_ASSERT macro |
| 155 | +| +-- VariadicBind.h # Bind helper (C++11/14) |
| 156 | +| +-- ExecuteMany.h # Batch execute (C++14) |
| 157 | +| +-- SQLiteCppExport.h # SQLITECPP_API macro |
| 158 | ++-- src/ # Implementations |
| 159 | ++-- tests/ # Unit tests (*_test.cpp) |
| 160 | ++-- sqlite3/ # Bundled SQLite3 source |
| 161 | ++-- examples/ # Example applications |
| 162 | ++-- CMakeLists.txt / meson.build / build.bat / build.sh |
| 163 | +``` |
| 164 | + |
| 165 | +### Naming Rules |
| 166 | +| Element | Convention | Example | |
| 167 | +|---------|------------|---------| |
| 168 | +| Types | PascalCase | `Database`, `Statement`, `TransactionBehavior` | |
| 169 | +| Files | Named like contained class | `Database.h`, `Statement.cpp` | |
| 170 | +| Functions and variables | camelCase | `executeStep()`, `getColumn()` | |
| 171 | +| Member variables | Prefix `m` | `mDatabase`, `mQuery` | |
| 172 | +| Function arguments | Prefix `a` | `aDatabase`, `aQuery` | |
| 173 | +| Boolean variables | Prefix `b`/`mb` | `bExists`, `mbDone` | |
| 174 | +| Pointer variables | Prefix `p`/`mp` | `pValue`, `mpSQLite` | |
| 175 | +| Constants | ALL_CAPS | `OPEN_READONLY`, `SQLITE_OK` | |
| 176 | + |
| 177 | +### File Header Template |
| 178 | +```cpp |
| 179 | +/** |
| 180 | + * @file ClassName.h |
| 181 | + * @ingroup SQLiteCpp |
| 182 | + * @brief Brief description of the file. |
| 183 | + * |
| 184 | + * Copyright (c) 2012-2025 Sebastien Rombauts (sebastien.rombauts@gmail.com) |
| 185 | + * |
| 186 | + * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt |
| 187 | + * or copy at http://opensource.org/licenses/MIT) |
| 188 | + */ |
| 189 | +#pragma once |
| 190 | + |
| 191 | +#include <SQLiteCpp/SQLiteCppExport.h> |
| 192 | +// other includes... |
| 193 | +``` |
| 194 | + |
| 195 | +### Doxygen Format |
| 196 | +```cpp |
| 197 | +/** |
| 198 | + * @brief Execute a step of the prepared query to fetch one row of results. |
| 199 | + * |
| 200 | + * @param[in] aIndex Index of the column (0-based) |
| 201 | + * |
| 202 | + * @return - true (SQLITE_ROW) if there is another row ready |
| 203 | + * - false (SQLITE_DONE) if the query has finished executing |
| 204 | + * |
| 205 | + * @throw SQLite::Exception in case of error |
| 206 | + */ |
| 207 | +``` |
| 208 | + |
| 209 | +### Error Handling |
| 210 | +- Use `SQLite::Exception` for errors (inherits `std::runtime_error`). |
| 211 | +- Use `check(ret)` after SQLite C API calls. |
| 212 | +- In destructors, use `SQLITECPP_ASSERT()` instead of throwing. |
| 213 | + |
| 214 | +### Minimal API Example |
| 215 | +```cpp |
| 216 | +SQLite::Database db("example.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); |
| 217 | + |
| 218 | +SQLite::Statement query(db, "SELECT * FROM test WHERE id > ? AND name = :name"); |
| 219 | +query.bind(1, 5); |
| 220 | +query.bind(":name", "John"); |
| 221 | +while (query.executeStep()) |
| 222 | +{ |
| 223 | + int id = query.getColumn(0); |
| 224 | + std::string value = query.getColumn(1); |
| 225 | +} |
| 226 | + |
| 227 | +SQLite::Statement insert(db, "INSERT INTO test VALUES (?, ?)"); |
| 228 | +insert.bind(1, 42); |
| 229 | +insert.bind(2, "value"); |
| 230 | +int changes = insert.exec(); |
| 231 | +``` |
0 commit comments