Implement insert_or_replace (#45)

Co-authored-by: Dr. Patrick Urbanke <patrick@getml.com>
This commit is contained in:
Demian Nave
2025-09-07 05:14:02 -04:00
committed by GitHub
parent 82e1c193d3
commit 8b6b6c5a59
24 changed files with 675 additions and 39 deletions

View File

@@ -68,6 +68,58 @@ sqlgen::sqlite::connect("database.db")
.value();
```
### With Replacement
Replace existing rows:
```cpp
const auto people1 = std::vector<Person>({
Person{.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10}
});
const auto people2 = std::vector<Person>({
Person{.id = 1, .first_name = "Bartholomew", .last_name = "Simpson", .age = 10}
});
using namespace sqlgen;
const auto result = sqlite::connect()
.and_then(create_table<Person> | if_not_exists)
.and_then(insert(std::ref(people1)))
.and_then(insert_or_replace(std::ref(people2)))
.value();
```
This generates the following SQL:
```sql
CREATE TABLE IF NOT EXISTS "Person" (
"id" INTEGER PRIMARY KEY,
"first_name" TEXT NOT NULL,
"last_name" TEXT NOT NULL,
"age" INTEGER NOT NULL
);
INSERT INTO "Person" ("id", "first_name", "last_name", "age") VALUES (?, ?, ?, ?);
INSERT INTO "Person" ("id", "first_name", "last_name", "age") VALUES (?, ?, ?, ?)
ON CONFLICT (id) DO UPDATE SET
id=excluded.id,
first_name=excluded.first_name,
last_name=excluded.last_name,
age=excluded.age;
```
The SQL generated by the PostgreSQL backend for `insert_or_replace(...)` is similar. The MySQL backend generates `ON DUPLICATE KEY UPDATE` instead:
```sql
...
INSERT INTO `Person` (`id`, `first_name`, `last_name`, `age`) VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
id=VALUES(id),
first_name=VALUES(first_name),
last_name=VALUES(last_name),
age=VALUES(age);
```
## Example: Full Transaction Usage
Here's a complete example showing how to use `insert` within a transaction:
@@ -195,5 +247,4 @@ While both `insert` and `write` can be used to add data to a database, they serv
4. Takes a connection and a reference wrapper to a container
- Unlike `write`, `insert` does not create tables automatically - you must create tables separately using `create_table`
- The insert operation is atomic within a transaction
- When using reference wrappers (`std::ref`), the data is not copied, which can be more efficient for large datasets
- When using reference wrappers (`std::ref`), the data is not copied, which can be more efficient for large datasets