mirror of
https://github.com/getml/sqlgen.git
synced 2026-01-05 00:49:58 -06:00
Added documentation for create_index and create_table
This commit is contained in:
141
docs/create_index.md
Normal file
141
docs/create_index.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# `sqlgen::create_index`
|
||||
|
||||
The `sqlgen::create_index` interface provides a type-safe way to create indexes on SQL database tables. It supports creating both regular and unique indexes, with optional `if_not_exists` clause to handle cases where the index may already exist.
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Index Creation
|
||||
|
||||
Create an index on one or more columns:
|
||||
|
||||
```cpp
|
||||
const auto conn = sqlgen::sqlite::connect("database.db");
|
||||
|
||||
sqlgen::create_index<"person_ix", Person>("first_name"_c, "last_name"_c)(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE INDEX "person_ix" ON "Person" ("first_name", "last_name");
|
||||
```
|
||||
|
||||
Note that `conn` is actually a connection wrapped into an `sqlgen::Result<...>`.
|
||||
This means you can use monadic error handling and fit this into a single line:
|
||||
|
||||
```cpp
|
||||
// sqlgen::Result<Ref<Connection>>
|
||||
const auto result = sqlgen::sqlite::connect("database.db").and_then(
|
||||
sqlgen::create_index<"person_ix", Person>("first_name"_c, "last_name"_c));
|
||||
```
|
||||
|
||||
Please refer to the documentation on `sqlgen::Result<...>` for more information on error handling.
|
||||
|
||||
### With `if_not_exists` clause
|
||||
|
||||
Create an index only if it doesn't already exist:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_index<"person_ix", Person>("first_name"_c, "last_name"_c) | if_not_exists;
|
||||
|
||||
query(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE INDEX IF NOT EXISTS "person_ix" ON "Person" ("first_name", "last_name");
|
||||
```
|
||||
|
||||
You can also use monadic error handling here:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_index<"person_ix", Person>("first_name"_c, "last_name"_c) | if_not_exists;
|
||||
|
||||
// sqlgen::Result<Ref<Connection>>
|
||||
const auto result = sqlite::connect("database.db").and_then(query);
|
||||
```
|
||||
|
||||
### Creating Unique Indexes
|
||||
|
||||
Create a unique index to enforce uniqueness constraints:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_unique_index<"person_ix", Person>("first_name"_c, "last_name"_c);
|
||||
|
||||
query(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE UNIQUE INDEX "person_ix" ON "Person" ("first_name", "last_name");
|
||||
```
|
||||
|
||||
### Creating Indexes with WHERE Clause
|
||||
|
||||
Create a partial index by adding a WHERE clause to filter which rows are included in the index:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_index<"test_table_ix", TestTable>("field1"_c, "field2"_c) |
|
||||
if_not_exists |
|
||||
where("field2"_c > 0);
|
||||
|
||||
query(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE INDEX IF NOT EXISTS "test_table_ix" ON "TestTable"("field1", "field2") WHERE "field2" > 0;
|
||||
```
|
||||
|
||||
The WHERE clause can be combined with other modifiers like `if_not_exists` and works with both regular and unique indexes. This is particularly useful for creating partial indexes that only include rows matching certain conditions, which can improve index performance and reduce index size.
|
||||
|
||||
## Example: Full Query Composition
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_index<"person_ix", Person>("first_name"_c, "last_name"_c) | if_not_exists;
|
||||
|
||||
const auto result = query(conn);
|
||||
|
||||
if (!result) {
|
||||
// Error handling
|
||||
}
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE INDEX IF NOT EXISTS "person_ix" ON "Person" ("first_name", "last_name");
|
||||
```
|
||||
|
||||
It is strongly recommended that you use `using namespace sqlgen`. However,
|
||||
if you do not want to do that, you can rewrite the example above as follows:
|
||||
|
||||
```cpp
|
||||
const auto query = sqlgen::create_index<"person_ix", Person>("first_name"_c, "last_name"_c) |
|
||||
sqlgen::if_not_exists;
|
||||
|
||||
const auto result = query(conn);
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The `if_not_exists` clause is optional - if omitted, the query will fail if the index already exists
|
||||
- The `Result<Ref<Connection>>` type provides error handling; use `.value()` to extract the result (will throw an exception if there's an error) or handle errors as needed or refer to the documentation on `sqlgen::Result<...>` for other forms of error handling.
|
||||
- `"..."_c` refers to the name of the column. If such a field does not exist on the struct (e.g., `Person`), the code will fail to compile.
|
||||
- Index names must be unique within a database
|
||||
- You can create indexes on multiple columns by providing multiple column names
|
||||
- Use `create_unique_index` when you need to enforce uniqueness constraints on the indexed columns
|
||||
|
||||
104
docs/create_table.md
Normal file
104
docs/create_table.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# `sqlgen::create_table`
|
||||
|
||||
The `sqlgen::create_table` interface provides a type-safe way to create tables in a SQL database. It supports the `if_not_exists` clause to handle cases where the table may already exist.
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Create Table
|
||||
|
||||
Create a table:
|
||||
|
||||
```cpp
|
||||
const auto conn = sqlgen::sqlite::connect("database.db");
|
||||
|
||||
sqlgen::create_table<Person>(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE TABLE "Person" ("id" INTEGER NOT NULL, "first_name" TEXT NOT NULL, "last_name" TEXT NOT NULL, "age" INTEGER NOT NULL);
|
||||
```
|
||||
|
||||
Note that `conn` is actually a connection wrapped into an `sqlgen::Result<...>`.
|
||||
This means you can use monadic error handling and fit this into a single line:
|
||||
|
||||
```cpp
|
||||
// sqlgen::Result<Ref<Connection>>
|
||||
const auto result = sqlgen::sqlite::connect("database.db").and_then(
|
||||
sqlgen::create_table<Person>);
|
||||
```
|
||||
|
||||
Please refer to the documentation on `sqlgen::Result<...>` for more information on error handling.
|
||||
|
||||
### With `if_not_exists` clause
|
||||
|
||||
Create a table only if it doesn't exist:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_table<Person> | if_not_exists;
|
||||
|
||||
query(conn).value();
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS "Person" ("id" INTEGER NOT NULL, "first_name" TEXT NOT NULL, "last_name" TEXT NOT NULL, "age" INTEGER NOT NULL);
|
||||
```
|
||||
|
||||
You can also use monadic error handling here:
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_table<Person> | if_not_exists;
|
||||
|
||||
// sqlgen::Result<Ref<Connection>>
|
||||
const auto result = sqlite::connect("database.db").and_then(query);
|
||||
```
|
||||
|
||||
## Example: Full Query Composition
|
||||
|
||||
```cpp
|
||||
using namespace sqlgen;
|
||||
|
||||
const auto query = create_table<Person> | if_not_exists;
|
||||
|
||||
const auto result = query(conn);
|
||||
|
||||
if (!result) {
|
||||
// Error handling
|
||||
}
|
||||
```
|
||||
|
||||
This generates the following SQL:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS "Person" ("id" INTEGER NOT NULL, "first_name" TEXT NOT NULL, "last_name" TEXT NOT NULL, "age" INTEGER NOT NULL);
|
||||
```
|
||||
|
||||
It is strongly recommended that you use `using namespace sqlgen`. However,
|
||||
if you do not want to do that, you can rewrite the example above as follows:
|
||||
|
||||
```cpp
|
||||
const auto query = sqlgen::create_table<Person> | sqlgen::if_not_exists;
|
||||
|
||||
const auto result = query(conn);
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The `if_not_exists` clause is optional - if omitted, the query will fail if the table already exists
|
||||
- The `Result<Ref<Connection>>` type provides error handling; use `.value()` to extract the result (will throw an exception if there's an error) or handle errors as needed or refer to the documentation on `sqlgen::Result<...>` for other forms of error handling.
|
||||
- The table name is derived from the struct name (e.g., `Person` becomes `"Person"` in SQL)
|
||||
- Column types are automatically mapped from C++ types:
|
||||
- `std::string` → `TEXT`
|
||||
- `int`/`int32_t` → `INTEGER`
|
||||
- `uint32_t` → `INTEGER`
|
||||
- `std::optional<T>` → nullable column of type T
|
||||
- `sqlgen::PrimaryKey<T>` → column of type T with PRIMARY KEY constraint
|
||||
- All columns are NOT NULL by default unless they are `std::optional`
|
||||
|
||||
Reference in New Issue
Block a user