4.8 KiB
sqlgen::update
The sqlgen::update interface provides a type-safe way to update records in a SQL database. It supports composable query building with where clauses to specify which records should be updated, and allows setting multiple columns to either literal values or other column values.
Usage
Basic Update
Update specific columns in a table:
const auto conn = sqlgen::sqlite::connect("database.db");
using namespace sqlgen;
using namespace sqlgen::literals;
const auto query = update<Person>("age"_c.set(100), "first_name"_c.set("New Name"));
query(conn).value();
This generates the following SQL:
UPDATE "Person"
SET "age" = 100, "first_name" = 'New 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:
// sqlgen::Result<Ref<Connection>>
const auto result = sqlgen::sqlite::connect("database.db").and_then(
update<Person>("age"_c.set(100), "first_name"_c.set("New Name")));
Please refer to the documentation on sqlgen::Result<...> for more information on error handling.
With where clause
Update specific records using a where clause:
using namespace sqlgen;
using namespace sqlgen::literals;
const auto query = update<Person>("age"_c.set(100)) |
where("first_name"_c == "Hugo");
query(conn).value();
This generates the following SQL:
UPDATE "Person"
SET "age" = 100
WHERE "first_name" = 'Hugo';
Note that "..."_c refers to the name of the column. If such a field does not
exist on the struct Person, the code will fail to compile. It is defined
in the namespace sqlgen::literals.
You can also use monadic error handling here:
using namespace sqlgen;
using namespace sqlgen::literals;
const auto query = update<Person>("age"_c.set(100)) |
where("first_name"_c == "Hugo");
// sqlgen::Result<Ref<Connection>>
const auto result = sqlite::connect("database.db").and_then(query);
Setting Columns to Other Column Values
You can set a column's value to another column's value:
using namespace sqlgen;
using namespace sqlgen::literals;
const auto query = update<Person>("first_name"_c.set("last_name"_c)) |
where("age"_c > 18);
query(conn).value();
This generates the following SQL:
UPDATE "Person"
SET "first_name" = "last_name"
WHERE "age" > 18;
Setting Nullable Values
Columns can be set using std::optional values. Passing std::nullopt will set the column to NULL in the database, and passing a std::optional with a value will set the column to that value.
using namespace sqlgen;
using namespace sqlgen::literals;
// set to NULL
const auto query1 = update<Person>("age"_c.set(std::nullopt)) |
where("first_name"_c == "Hugo");
// set to a value
const auto query2 = update<Person>("age"_c.set(std::optional<int>(11))) |
where("first_name"_c == "Bart");
query1(conn).and_then(query2).value();
This generates the following SQL:
UPDATE "Person"
SET "age" = NULL
WHERE "first_name" = 'Hugo';
UPDATE "Person"
SET "age" = 11
WHERE "first_name" = 'Bart';
Example: Full Query Composition
using namespace sqlgen;
using namespace sqlgen::literals;
const auto query = update<Person>(
"first_name"_c.set("last_name"_c),
"age"_c.set(100)) |
where("age"_c > 0);
const auto result = query(conn);
if (!result) {
// Error handling
}
This generates the following SQL:
UPDATE "Person"
SET
"first_name" = "last_name",
"age" = 100
WHERE "age" > 0;
It is strongly recommended that you use using namespace sqlgen
and using namespace sqlgen::literals. However,
if you do not want to do that, you can rewrite the example above as follows:
const auto query = sqlgen::update<Person>(
sqlgen::col<"first_name">.set(sqlgen::col<"last_name">),
sqlgen::col<"age">.set(100)) |
sqlgen::where(sqlgen::col<"age"> > 0);
const auto result = query(conn);
Notes
- You must specify at least one column to update
- The
whereclause is optional - if omitted, all records will be updated - 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 onsqlgen::Result<...>for other forms of error handling "..."_crefers to the name of the column. It is defined in the namespacesqlgen::literals.- You can set columns to either literal values or other column values
- The update operation is atomic - either all specified columns are updated or none are