# `sqlgen::...::to_sql` The `to_sql` functions in each dialect namespace (e.g., `sqlgen::postgres::to_sql`, `sqlgen::sqlite::to_sql`) provide a way to transpile C++ SQL operations into dialect-specific SQL strings. This is particularly useful for testing, debugging, logging, and understanding the exact SQL that will be executed by sqlgen. ## Usage ### Basic Usage Transpile any SQL operation to a dialect-specific SQL string: ```cpp using namespace sqlgen; using namespace sqlgen::literals; // Define a query const auto query = sqlgen::read> | where("age"_c < 18 and "first_name"_c != "Hugo") | order_by("age"_c); // Transpile to PostgreSQL dialect const auto postgres_sql = postgres::to_sql(query); ``` This generates the following PostgreSQL SQL: ```sql SELECT "id", "first_name", "last_name", "age" FROM "Person" WHERE ("age" < 18) AND ("first_name" != 'Hugo') ORDER BY "age"; ``` Or for SQLite: ```cpp // Transpile to SQLite dialect const auto sqlite_sql = sqlite::to_sql(query); ``` ### Supported Operations `to_sql` supports transpilation of all sqlgen operations: #### SELECT Queries ```cpp using namespace sqlgen; using namespace sqlgen::literals; // Basic select const auto select_query = sqlgen::read>; const auto sql = postgres::to_sql(select_query); ``` This generates the following SQL: ```sql SELECT "id", "first_name", "last_name", "age" FROM "Person"; ``` With a where clause: ```cpp // With where clause const auto filtered_query = sqlgen::read> | where("age"_c >= 18); const auto sql = postgres::to_sql(filtered_query); ``` This generates the following SQL: ```sql SELECT "id", "first_name", "last_name", "age" FROM "Person" WHERE "age" >= 18; ``` #### CREATE TABLE Operations Note that every call to `sqlgen::write` calls a `CREATE TABLE` operation before actually inserting the data. ```cpp using namespace sqlgen; using namespace sqlgen::literals; // Define a table structure struct TestTable { std::string field1; int32_t field2; sqlgen::PrimaryKey id; std::optional nullable; }; // Create table query const auto create_query = create_table | if_not_exists; const auto sql = postgres::to_sql(create_query); ``` This generates the following PostgreSQL SQL: ```sql CREATE TABLE IF NOT EXISTS "TestTable" ( "field1" TEXT NOT NULL, "field2" INTEGER NOT NULL, "id" INTEGER NOT NULL, "nullable" TEXT, PRIMARY KEY ("id") ); ``` #### INSERT Operations ```cpp using namespace sqlgen; using namespace sqlgen::literals; const auto insert_query = Insert{}; const auto sql = postgres::to_sql(insert_query); ``` This generates the following PostgreSQL SQL: ```sql COPY "public"."TestTable"("field1", "field2", "id", "nullable") FROM STDIN WITH DELIMITER '\t' NULL '\e' QUOTE '\a'; ``` For SQLite, the same operation generates: ```sql INSERT INTO "TestTable"("field1", "field2", "id", "nullable") VALUES (?, ?, ?, ?); ``` #### DELETE Operations ```cpp using namespace sqlgen; using namespace sqlgen::literals; const auto delete_query = delete_from | where("field2"_c > 0); const auto sql = postgres::to_sql(delete_query); ``` This generates the following SQL: ```sql DELETE FROM "TestTable" WHERE "field2" > 0; ``` ### Dialect-Specific Features Each database dialect implements its own version of `to_sql` with dialect-specific features: #### PostgreSQL (`sqlgen::postgres::to_sql`) - Uses `COPY` for bulk inserts - Supports schema names (e.g., "public") - Uses PostgreSQL-specific escaping rules #### SQLite (`sqlgen::sqlite::to_sql`) - Uses `INSERT INTO` for inserts - Uses SQLite-specific escaping rules - Simpler schema (no schema names) ## Notes - Each dialect's `to_sql` is a template function that works with any sqlgen operation - The functions are `noexcept` and return a `std::string` - The generated SQL is properly escaped and safe to use - The functions are particularly useful for: - Debugging complex queries - Logging SQL operations - Understanding the exact SQL that will be executed - Testing and validation - Each dialect's implementation ensures the generated SQL is compatible with that specific database - The functions preserve all SQL operations' semantics while adapting to dialect-specific syntax