2323// notice. See villagesql/preview/README.md.
2424// =============================================================================
2525
26- #ifndef VILLAGESQL_ABI_PREVIEW_QUERY_HOOK_H
27- #define VILLAGESQL_ABI_PREVIEW_QUERY_HOOK_H
26+ #ifndef VILLAGESQL_ABI_PREVIEW_STATEMENT_EVENT_H
27+ #define VILLAGESQL_ABI_PREVIEW_STATEMENT_EVENT_H
2828
2929#include <stdbool.h>
3030#include <stddef.h>
3636extern "C" {
3737#endif
3838
39- // Preview capability: "vsql::preview::query_hook "
39+ // Preview capability: "vsql::preview::statement_event "
4040//
41- // An extension declares one QueryHookCapability per hook function. The server
42- // invokes registered hooks at the corresponding phase of query processing.
43- // Only the POSTEXECUTE phase is wired up in this version; the other phase
44- // values are reserved for future use without ABI break.
41+ // An extension declares one StatementEventCapability per hook function. The
42+ // server invokes registered hooks at the corresponding phase of query
43+ // processing. Only the POSTEXECUTE phase is wired up in this version; the other
44+ // phase values are reserved for future use without ABI break.
4545//
46- // Capability name: VEF_PREVIEW_QUERY_HOOK_NAME
46+ // Capability name: VEF_PREVIEW_STATEMENT_EVENT_NAME
4747
48- #define VEF_PREVIEW_QUERY_HOOK_NAME "vsql::preview::query_hook "
48+ #define VEF_PREVIEW_STATEMENT_EVENT_NAME "vsql::preview::statement_event "
4949
5050// Capability ABI version compiled into this SDK snapshot.
51- #define VEF_PREVIEW_QUERY_HOOK_ABI_VERSION 1
51+ #define VEF_PREVIEW_STATEMENT_EVENT_ABI_VERSION 1
5252
5353// Phase at which a hook fires.
5454//
@@ -61,64 +61,79 @@ typedef enum {
6161 // EVENT_TRACKING_CONNECTION_CONNECT. Args populated: user, host,
6262 // connection_id, port. Query fields and timing are unset.
6363 // Result.error_msg refuses the connection.
64- VEF_QUERY_HOOK_CONNECT = 0 ,
64+ VEF_STATEMENT_EVENT_CONNECT = 0 ,
6565
6666 // Reserved: client connection closing. Fires from
6767 // EVENT_TRACKING_CONNECTION_DISCONNECT. Same args as CONNECT.
6868 // Result is ignored — the connection is going away.
69- VEF_QUERY_HOOK_DISCONNECT = 1 ,
69+ VEF_STATEMENT_EVENT_DISCONNECT = 1 ,
7070
7171 // Reserved: before the parser runs. Only `query` is populated. Hooked
7272 // inside sql_parse.cc rather than the audit path. Result.error_msg
7373 // blocks the query.
74- VEF_QUERY_HOOK_PREPARSE = 2 ,
74+ VEF_STATEMENT_EVENT_PREPARSE = 2 ,
7575
7676 // Reserved: after the parser runs. Adds sql_command, is_prepared, and
7777 // the SHA-256 digest of the normalized query to args. Result.error_msg
7878 // blocks the query.
79- VEF_QUERY_HOOK_POSTPARSE = 3 ,
79+ VEF_STATEMENT_EVENT_POSTPARSE = 3 ,
8080
8181 // Reserved: after parsing, before execution begins. Fires from
8282 // EVENT_TRACKING_QUERY_START. Args populated: query, user, host,
8383 // connection_id, port, schema, sql_command, in_transaction. Timing/rows/
8484 // status are zero. Result.error_msg blocks the query.
85- VEF_QUERY_HOOK_PREEXECUTE = 4 ,
85+ VEF_STATEMENT_EVENT_PREEXECUTE = 4 ,
8686
8787 // After execution completes (success or failure). All args fields are
8888 // populated; result.error_msg is logged but does not affect the client.
89- VEF_QUERY_HOOK_POSTEXECUTE = 5 ,
90- } vef_query_hook_phase_t ;
89+ VEF_STATEMENT_EVENT_POSTEXECUTE = 5 ,
90+ } vef_statement_event_phase_t ;
9191
9292// Read-only arguments passed to a hook invocation. Which fields are populated
9393// depends on the phase; POSTEXECUTE populates all of them.
94+ //
95+ // Pointer lifetime summary (see per-field comments):
96+ // process lifetime — safe to retain indefinitely; no copy needed.
97+ // connection lifetime — valid until the client disconnects; safe to retain
98+ // across hook calls for the same connection, but copy
99+ // if you may use it after the connection ends.
100+ // copy before return — valid only during this hook invocation; copy the
101+ // string before the hook function returns if you need
102+ // to keep it.
94103typedef struct {
95- vef_query_hook_phase_t phase ;
104+ vef_statement_event_phase_t phase ;
96105
97106 // Query text. Not null-terminated; use query_len.
107+ // Lifetime: copy before return.
98108 const char * query ;
99109 size_t query_len ;
100110
101- // Authenticated user name (priv_user), or empty string.
111+ // Authenticated user name, or empty string.
112+ // Lifetime: connection lifetime.
102113 const char * user ;
103114 // Client IP address, or empty string.
115+ // Lifetime: connection lifetime.
104116 const char * host ;
105117 unsigned long connection_id ;
106118 uint16_t port ;
107119 bool in_transaction ;
108120
109121 // SQL command as a lowercase string (e.g. "select", "insert",
110- // "create_table"). Stable across MySQL version rebases . NULL if unknown.
111- // The pointed-to string has static lifetime and need not be copied .
122+ // "create_table"). Stable across MySQL version rebase . NULL if unknown.
123+ // Lifetime: process lifetime.
112124 const char * sql_command ;
113125
114- // Default schema (USE <db>), or NULL if none selected.
126+ // Current default schema (USE <db>), or NULL if none selected.
127+ // Lifetime: connection lifetime.
115128 const char * schema ;
116129
117130 // Execution status. 0 on success, otherwise the MySQL error code.
118131 int status ;
119132 // 5-character SQLSTATE + NUL, or NULL on success.
133+ // Lifetime: copy before return.
120134 const char * sqlstate ;
121135 // Error message text, or NULL on success.
136+ // Lifetime: copy before return.
122137 const char * error_message ;
123138
124139 // Query start time, microseconds since epoch.
@@ -130,7 +145,38 @@ typedef struct {
130145 uint64_t rows_affected ;
131146 uint64_t bytes_sent ;
132147 uint64_t bytes_received ;
133- } vef_query_hook_args_t ;
148+
149+ // Number of warnings raised during execution (in addition to any error).
150+ uint64_t warning_count ;
151+
152+ // Normalized (digested) form of the query, suitable for grouping similar
153+ // queries regardless of literal values. NULL if digest computation was
154+ // disabled or the query was too long to digest.
155+ // Lifetime: copy before return.
156+ const char * digest_text ;
157+
158+ // Optimizer and execution quality indicators. Non-zero values suggest
159+ // potentially inefficient execution.
160+ uint64_t select_full_join ; // joins without usable index
161+ uint64_t select_full_range_join ; // joins using range on ref table
162+ uint64_t select_range ; // range scans on first table
163+ uint64_t select_range_check ; // joins with key check per row
164+ uint64_t select_scan ; // full scans of first table
165+
166+ // Sort metrics.
167+ uint64_t sort_merge_passes ; // number of merge passes (high = large sort)
168+ uint64_t sort_range ; // sorts using a range
169+ uint64_t sort_rows ; // rows sorted
170+ uint64_t sort_scan ; // sorts using a full table scan
171+
172+ // Temporary table usage.
173+ uint64_t created_tmp_tables ; // tmp tables created (memory or disk)
174+ uint64_t created_tmp_disk_tables ; // tmp tables spilled to disk
175+
176+ // Index usage flags. Non-zero means the query ran without a usable index.
177+ uint8_t no_index_used ; // 1 if no index was used
178+ uint8_t no_good_index_used ; // 1 if no good index was found
179+ } vef_statement_event_args_t ;
134180
135181// Writable result. For POSTEXECUTE error_msg is advisory: the server logs it
136182// but does not propagate to the client.
@@ -141,32 +187,32 @@ typedef struct {
141187 // this pointer before calling the hook. Matches the convention used by
142188 // vef_vdf_result_t and vef_prerun_result_t.
143189 char * error_msg ;
144- } vef_query_hook_result_t ;
190+ } vef_statement_event_result_t ;
145191
146192// Hook callback type. Invoked synchronously on the query's thread.
147193// args is read-only; result is the extension's writeback channel.
148- typedef void (* vef_query_hook_fn_t )(const vef_query_hook_args_t * args ,
149- vef_query_hook_result_t * result );
194+ typedef void (* vef_statement_event_fn_t )(const vef_statement_event_args_t * args ,
195+ vef_statement_event_result_t * result );
150196
151197// Capability config (cc) filled in by the extension and passed to the server
152198// via vef_required_capability_t.capability_config. The phase determines when
153199// the hook fires; the function pointer must remain valid for the lifetime of
154200// the extension.
155201typedef struct {
156- vef_query_hook_phase_t phase ;
157- vef_query_hook_fn_t hook ;
158- } vef_query_hook_cc_t ;
202+ vef_statement_event_phase_t phase ;
203+ vef_statement_event_fn_t hook ;
204+ } vef_statement_event_cc_t ;
159205
160206// Server-side vtable. The version field is always first, matching the
161207// convention used by other preview capabilities. The server exposes no
162208// methods to the extension for this capability — registration happens via
163209// capability_config.
164210typedef struct {
165211 uint32_t version ;
166- } vef_preview_query_hook_t ;
212+ } vef_preview_statement_event_t ;
167213
168214#ifdef __cplusplus
169215}
170216#endif
171217
172- #endif // VILLAGESQL_ABI_PREVIEW_QUERY_HOOK_H
218+ #endif // VILLAGESQL_ABI_PREVIEW_STATEMENT_EVENT_H
0 commit comments