Skip to content

Commit b7fea73

Browse files
Pierre-Luc Gagnéclaude
andcommitted
feat: add SHOW statements, CREATE/DROP PROCEDURE, CALL, CREATE/DROP TRIGGER, GRANT/REVOKE
SHOW: show_databases(), show_tables(), show_columns<T>(), show_create_table<T>() — typed TypedSelectQuery builders with appropriate result_row_type tuples. Stored procedures: create_procedure(name, params, body), drop_procedure(name)[.if_exists()], call_procedure(name[, args]). Triggers: create_trigger<T>(name, TriggerTiming, TriggerEvent, body), drop_trigger<T>(name)[.if_exists()]; TriggerTiming::{Before,After} and TriggerEvent::{Insert,Update,Delete} enums. GRANT/REVOKE: grant(privs, obj, grantee)[.with_grant_option()], revoke(privs, obj, grantee). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8466275 commit b7fea73

3 files changed

Lines changed: 473 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2222
- `release_savepoint(name)``RELEASE SAVEPOINT name`
2323
- `rollback_to_savepoint(name)``ROLLBACK TO SAVEPOINT name`
2424
- `set_transaction_isolation_level(IsolationLevel)``SET TRANSACTION ISOLATION LEVEL ...` with `IsolationLevel::{ReadUncommitted, ReadCommitted, RepeatableRead, Serializable}`
25+
- `show_databases()``SHOW DATABASES` (queryable, result is `std::tuple<std::string>` per row)
26+
- `show_tables()``SHOW TABLES` (queryable, result is `std::tuple<std::string>` per row)
27+
- `show_columns<T>()``SHOW COLUMNS FROM table` (queryable, same row type as `describe<T>()`)
28+
- `show_create_table<T>()``SHOW CREATE TABLE table` (queryable, result is `std::tuple<std::string, std::string>`)
29+
- `create_procedure(name, params, body)``CREATE PROCEDURE name(params) BEGIN body END`
30+
- `drop_procedure(name)` / `.if_exists()``DROP PROCEDURE [IF EXISTS] name`
31+
- `call_procedure(name [, args])``CALL name([args])`
32+
- `create_trigger<T>(name, TriggerTiming, TriggerEvent, body)``CREATE TRIGGER ... ON table FOR EACH ROW body`; `TriggerTiming::{Before, After}`, `TriggerEvent::{Insert, Update, Delete}`
33+
- `drop_trigger<T>(name)` / `.if_exists()``DROP TRIGGER [IF EXISTS] name`
34+
- `grant(privileges, object, grantee)` / `.with_grant_option()``GRANT ... ON ... TO ... [WITH GRANT OPTION]`
35+
- `revoke(privileges, object, grantee)``REVOKE ... ON ... FROM ...`
2536

2637
- `natural_join<T>()`, `natural_left_join<T>()`, `natural_right_join<T>()``NATURAL [LEFT|RIGHT] JOIN` with no ON/USING clause
2738
- `inner_join_using<T, Cols...>()`, `left_join_using<T, Cols...>()`, `right_join_using<T, Cols...>()`, `full_join_using<T, Cols...>()``JOIN ... USING (col1, col2, ...)` with one or more column descriptors

lib/include/ds_mysql/sql_ddl.hpp

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,4 +2473,344 @@ class use_name_builder {
24732473
return ddl_detail::use_name_builder{std::move(name)};
24742474
}
24752475

2476+
// ===================================================================
2477+
// SHOW Statements
2478+
//
2479+
// Entry points (all queryable via db.query()):
2480+
// show_databases() — SHOW DATABASES
2481+
// show_tables() — SHOW TABLES (current database)
2482+
// show_columns<T>() — SHOW COLUMNS FROM table
2483+
// show_create_table<T>() — SHOW CREATE TABLE table
2484+
// ===================================================================
2485+
2486+
namespace ddl_detail {
2487+
2488+
class show_databases_builder {
2489+
public:
2490+
using result_row_type = std::tuple<std::string>;
2491+
2492+
[[nodiscard]] std::string build_sql() const {
2493+
return "SHOW DATABASES";
2494+
}
2495+
};
2496+
2497+
class show_tables_builder {
2498+
public:
2499+
using result_row_type = std::tuple<std::string>;
2500+
2501+
[[nodiscard]] std::string build_sql() const {
2502+
return "SHOW TABLES";
2503+
}
2504+
};
2505+
2506+
template <typename T>
2507+
class show_columns_builder {
2508+
public:
2509+
// Field, Type, Null, Key, Default (nullable), Extra
2510+
using result_row_type =
2511+
std::tuple<std::string, std::string, std::string, std::string, std::optional<std::string>, std::string>;
2512+
2513+
[[nodiscard]] std::string build_sql() const {
2514+
return "SHOW COLUMNS FROM " + std::string(table_name_for<T>::value().to_string_view());
2515+
}
2516+
};
2517+
2518+
template <typename T>
2519+
class show_create_table_builder {
2520+
public:
2521+
// Table name, CREATE TABLE statement
2522+
using result_row_type = std::tuple<std::string, std::string>;
2523+
2524+
[[nodiscard]] std::string build_sql() const {
2525+
return "SHOW CREATE TABLE " + std::string(table_name_for<T>::value().to_string_view());
2526+
}
2527+
};
2528+
2529+
} // namespace ddl_detail
2530+
2531+
[[nodiscard]] inline ddl_detail::show_databases_builder show_databases() {
2532+
return {};
2533+
}
2534+
2535+
[[nodiscard]] inline ddl_detail::show_tables_builder show_tables() {
2536+
return {};
2537+
}
2538+
2539+
template <ValidTable T>
2540+
[[nodiscard]] ddl_detail::show_columns_builder<T> show_columns() {
2541+
return {};
2542+
}
2543+
2544+
template <ValidTable T>
2545+
[[nodiscard]] ddl_detail::show_create_table_builder<T> show_create_table() {
2546+
return {};
2547+
}
2548+
2549+
// ===================================================================
2550+
// Stored Procedures
2551+
//
2552+
// Entry points (executeable via db.execute()):
2553+
// create_procedure(name, params, body) — CREATE PROCEDURE name(params) BEGIN body END
2554+
// drop_procedure(name) — DROP PROCEDURE name
2555+
// drop_procedure(name).if_exists() — DROP PROCEDURE IF EXISTS name
2556+
// call_procedure(name) — CALL name()
2557+
// call_procedure(name, args) — CALL name(args)
2558+
// ===================================================================
2559+
2560+
namespace ddl_detail {
2561+
2562+
class drop_procedure_if_exists_builder {
2563+
public:
2564+
explicit drop_procedure_if_exists_builder(std::string name) : name_(std::move(name)) {
2565+
}
2566+
2567+
[[nodiscard]] std::string build_sql() const {
2568+
return "DROP PROCEDURE IF EXISTS " + name_;
2569+
}
2570+
2571+
private:
2572+
std::string name_;
2573+
};
2574+
2575+
class drop_procedure_builder {
2576+
public:
2577+
explicit drop_procedure_builder(std::string name) : name_(std::move(name)) {
2578+
}
2579+
2580+
[[nodiscard]] drop_procedure_if_exists_builder if_exists() const {
2581+
return drop_procedure_if_exists_builder{name_};
2582+
}
2583+
2584+
[[nodiscard]] std::string build_sql() const {
2585+
return "DROP PROCEDURE " + name_;
2586+
}
2587+
2588+
private:
2589+
std::string name_;
2590+
};
2591+
2592+
class create_procedure_builder {
2593+
public:
2594+
create_procedure_builder(std::string name, std::string params, std::string body)
2595+
: name_(std::move(name)), params_(std::move(params)), body_(std::move(body)) {
2596+
}
2597+
2598+
[[nodiscard]] std::string build_sql() const {
2599+
return "CREATE PROCEDURE " + name_ + "(" + params_ + ")\nBEGIN\n" + body_ + "\nEND";
2600+
}
2601+
2602+
private:
2603+
std::string name_;
2604+
std::string params_;
2605+
std::string body_;
2606+
};
2607+
2608+
class call_builder {
2609+
public:
2610+
explicit call_builder(std::string name, std::string args = {})
2611+
: name_(std::move(name)), args_(std::move(args)) {
2612+
}
2613+
2614+
[[nodiscard]] std::string build_sql() const {
2615+
return "CALL " + name_ + "(" + args_ + ")";
2616+
}
2617+
2618+
private:
2619+
std::string name_;
2620+
std::string args_;
2621+
};
2622+
2623+
} // namespace ddl_detail
2624+
2625+
[[nodiscard]] inline ddl_detail::create_procedure_builder create_procedure(std::string name, std::string params,
2626+
std::string body) {
2627+
return {std::move(name), std::move(params), std::move(body)};
2628+
}
2629+
2630+
[[nodiscard]] inline ddl_detail::drop_procedure_builder drop_procedure(std::string name) {
2631+
return ddl_detail::drop_procedure_builder{std::move(name)};
2632+
}
2633+
2634+
[[nodiscard]] inline ddl_detail::call_builder call_procedure(std::string name, std::string args = {}) {
2635+
return ddl_detail::call_builder{std::move(name), std::move(args)};
2636+
}
2637+
2638+
// ===================================================================
2639+
// Triggers
2640+
//
2641+
// Entry points (executeable via db.execute()):
2642+
// create_trigger<T>(name, timing, event, body) — CREATE TRIGGER name timing event ON table FOR EACH ROW body
2643+
// drop_trigger<T>(name) — DROP TRIGGER name
2644+
// drop_trigger<T>(name).if_exists() — DROP TRIGGER IF EXISTS name
2645+
// ===================================================================
2646+
2647+
enum class TriggerTiming {
2648+
Before,
2649+
After,
2650+
};
2651+
2652+
enum class TriggerEvent {
2653+
Insert,
2654+
Update,
2655+
Delete,
2656+
};
2657+
2658+
namespace ddl_detail {
2659+
2660+
[[nodiscard]] inline std::string to_sql_trigger_timing(TriggerTiming timing) {
2661+
return timing == TriggerTiming::Before ? "BEFORE" : "AFTER";
2662+
}
2663+
2664+
[[nodiscard]] inline std::string to_sql_trigger_event(TriggerEvent event) {
2665+
switch (event) {
2666+
case TriggerEvent::Insert:
2667+
return "INSERT";
2668+
case TriggerEvent::Update:
2669+
return "UPDATE";
2670+
case TriggerEvent::Delete:
2671+
return "DELETE";
2672+
}
2673+
return "INSERT";
2674+
}
2675+
2676+
template <typename T>
2677+
class drop_trigger_if_exists_builder {
2678+
public:
2679+
explicit drop_trigger_if_exists_builder(std::string trigger_name) : trigger_name_(std::move(trigger_name)) {
2680+
}
2681+
2682+
[[nodiscard]] std::string build_sql() const {
2683+
return "DROP TRIGGER IF EXISTS " + trigger_name_;
2684+
}
2685+
2686+
private:
2687+
std::string trigger_name_;
2688+
};
2689+
2690+
template <typename T>
2691+
class drop_trigger_builder {
2692+
public:
2693+
explicit drop_trigger_builder(std::string trigger_name) : trigger_name_(std::move(trigger_name)) {
2694+
}
2695+
2696+
[[nodiscard]] drop_trigger_if_exists_builder<T> if_exists() const {
2697+
return drop_trigger_if_exists_builder<T>{trigger_name_};
2698+
}
2699+
2700+
[[nodiscard]] std::string build_sql() const {
2701+
return "DROP TRIGGER " + trigger_name_;
2702+
}
2703+
2704+
private:
2705+
std::string trigger_name_;
2706+
};
2707+
2708+
template <typename T>
2709+
class create_trigger_builder {
2710+
public:
2711+
create_trigger_builder(std::string trigger_name, TriggerTiming timing, TriggerEvent event, std::string body)
2712+
: trigger_name_(std::move(trigger_name)), timing_(timing), event_(event), body_(std::move(body)) {
2713+
}
2714+
2715+
[[nodiscard]] std::string build_sql() const {
2716+
const auto table_name = table_name_for<T>::value().to_string_view();
2717+
return "CREATE TRIGGER " + trigger_name_ + " " + to_sql_trigger_timing(timing_) + " " +
2718+
to_sql_trigger_event(event_) + " ON " + std::string(table_name) + " FOR EACH ROW\n" + body_;
2719+
}
2720+
2721+
private:
2722+
std::string trigger_name_;
2723+
TriggerTiming timing_;
2724+
TriggerEvent event_;
2725+
std::string body_;
2726+
};
2727+
2728+
} // namespace ddl_detail
2729+
2730+
template <ValidTable T>
2731+
[[nodiscard]] ddl_detail::create_trigger_builder<T> create_trigger(std::string name, TriggerTiming timing,
2732+
TriggerEvent event, std::string body) {
2733+
return {std::move(name), timing, event, std::move(body)};
2734+
}
2735+
2736+
template <ValidTable T>
2737+
[[nodiscard]] ddl_detail::drop_trigger_builder<T> drop_trigger(std::string name) {
2738+
return ddl_detail::drop_trigger_builder<T>{std::move(name)};
2739+
}
2740+
2741+
// ===================================================================
2742+
// GRANT / REVOKE
2743+
//
2744+
// Entry points (executeable via db.execute()):
2745+
// grant(privileges, object, grantee) — GRANT privileges ON object TO grantee
2746+
// grant(privileges, object, grantee).with_grant_option() — ... WITH GRANT OPTION
2747+
// revoke(privileges, object, grantee) — REVOKE privileges ON object FROM grantee
2748+
// ===================================================================
2749+
2750+
namespace ddl_detail {
2751+
2752+
class grant_with_option_builder {
2753+
public:
2754+
grant_with_option_builder(std::string privileges, std::string object, std::string grantee)
2755+
: privileges_(std::move(privileges)), object_(std::move(object)), grantee_(std::move(grantee)) {
2756+
}
2757+
2758+
[[nodiscard]] std::string build_sql() const {
2759+
return "GRANT " + privileges_ + " ON " + object_ + " TO " + grantee_ + " WITH GRANT OPTION";
2760+
}
2761+
2762+
private:
2763+
std::string privileges_;
2764+
std::string object_;
2765+
std::string grantee_;
2766+
};
2767+
2768+
class grant_builder {
2769+
public:
2770+
grant_builder(std::string privileges, std::string object, std::string grantee)
2771+
: privileges_(std::move(privileges)), object_(std::move(object)), grantee_(std::move(grantee)) {
2772+
}
2773+
2774+
[[nodiscard]] grant_with_option_builder with_grant_option() const {
2775+
return {privileges_, object_, grantee_};
2776+
}
2777+
2778+
[[nodiscard]] std::string build_sql() const {
2779+
return "GRANT " + privileges_ + " ON " + object_ + " TO " + grantee_;
2780+
}
2781+
2782+
private:
2783+
std::string privileges_;
2784+
std::string object_;
2785+
std::string grantee_;
2786+
};
2787+
2788+
class revoke_builder {
2789+
public:
2790+
revoke_builder(std::string privileges, std::string object, std::string grantee)
2791+
: privileges_(std::move(privileges)), object_(std::move(object)), grantee_(std::move(grantee)) {
2792+
}
2793+
2794+
[[nodiscard]] std::string build_sql() const {
2795+
return "REVOKE " + privileges_ + " ON " + object_ + " FROM " + grantee_;
2796+
}
2797+
2798+
private:
2799+
std::string privileges_;
2800+
std::string object_;
2801+
std::string grantee_;
2802+
};
2803+
2804+
} // namespace ddl_detail
2805+
2806+
[[nodiscard]] inline ddl_detail::grant_builder grant(std::string privileges, std::string object,
2807+
std::string grantee) {
2808+
return {std::move(privileges), std::move(object), std::move(grantee)};
2809+
}
2810+
2811+
[[nodiscard]] inline ddl_detail::revoke_builder revoke(std::string privileges, std::string object,
2812+
std::string grantee) {
2813+
return {std::move(privileges), std::move(object), std::move(grantee)};
2814+
}
2815+
24762816
} // namespace ds_mysql

0 commit comments

Comments
 (0)