@@ -173,6 +173,9 @@ typedef enum : unsigned int {
173173 // + get_variable/set_variable/read_keyring/write_keyring
174174 // function pointers in vef_register_arg_t: access to
175175 // MySQL system variables and keyring component.
176+ // + run_query function pointer in vef_register_arg_t:
177+ // execute a SQL query from a background thread and
178+ // receive results row by row via callbacks.
176179} vef_protocol_t ;
177180
178181// Max length of error messages in caller-provided buffers.
@@ -253,6 +256,75 @@ typedef vef_keyring_result_t (*vef_write_keyring_fn)(const char *data_id,
253256 const unsigned char *data,
254257 size_t data_len);
255258
259+ // =============================================================================
260+ // Query execution service (protocol >= VEF_PROTOCOL_2)
261+ // =============================================================================
262+ //
263+ // run_query lets extensions execute SQL from a background thread and receive
264+ // results row by row. It is intended for use from threads registered via
265+ // on_install / register_background_thread (Protocol 4), but can be called from
266+ // any thread that has a MySQL THD attached.
267+ //
268+ // Column metadata is delivered via vef_column_meta_fn before the first row.
269+ // Each row is delivered as an array of vef_col_value_t values via
270+ // vef_row_fn. All string values (including numeric types requested as text)
271+ // point into server-managed memory valid only for the duration of that
272+ // callback; copy any values you need to retain.
273+ //
274+ // Return values for callbacks:
275+ // 0 continue processing
276+ // 1 abort — the query is cancelled and run_query returns an error
277+
278+ // A single column value delivered to vef_row_fn.
279+ // The server always uses text representation (CS_TEXT_REPRESENTATION), so
280+ // every value arrives as a null-terminated string in `str` / `str_len`, or
281+ // is_null == true for SQL NULL.
282+ typedef struct {
283+ bool is_null;
284+ const char *str; // null-terminated; valid only during the row callback
285+ size_t str_len;
286+ } vef_col_value_t ;
287+
288+ // Called once before the first row with column names and count.
289+ // col_names: array of col_count null-terminated column name strings.
290+ // col_count: number of columns in the result set.
291+ // ctx: the user context pointer passed to run_query.
292+ // Return 0 to continue, 1 to abort.
293+ typedef int (*vef_column_meta_fn)(const char *const *col_names,
294+ unsigned int col_count, void *ctx);
295+
296+ // Called once per result row.
297+ // values: array of col_count vef_col_value_t, one per column.
298+ // col_count: number of columns (matches the value from vef_column_meta_fn).
299+ // ctx: the user context pointer passed to run_query.
300+ // Return 0 to continue, 1 to abort.
301+ typedef int (*vef_row_fn)(const vef_col_value_t *values, unsigned int col_count,
302+ void *ctx);
303+
304+ typedef enum {
305+ VEF_QUERY_OK = 0 , // query executed successfully
306+ VEF_QUERY_ERROR = 1 , // server returned an error (SQL error)
307+ VEF_QUERY_ABORTED = 2 , // a callback returned 1
308+ } vef_run_query_result_t ;
309+
310+ // run_query: execute a SQL statement and stream rows to the caller.
311+ // sql: null-terminated SQL string.
312+ // sql_len: byte length of sql (not including the null terminator).
313+ // meta_cb: called once with column metadata before the first row;
314+ // may be NULL if metadata is not needed.
315+ // row_cb: called once per result row; may be NULL for statements
316+ // that return no rows (INSERT, SET, etc.).
317+ // ctx: opaque pointer forwarded to meta_cb and row_cb.
318+ // error_msg: on VEF_QUERY_ERROR, a null-terminated description is written
319+ // here; must point to a buffer of at least VEF_MAX_ERROR_LEN
320+ // bytes; may be NULL if the caller does not need the message.
321+ // Returns VEF_QUERY_OK, VEF_QUERY_ERROR, or VEF_QUERY_ABORTED.
322+ typedef vef_run_query_result_t (*vef_run_query_fn)(const char *sql,
323+ size_t sql_len,
324+ vef_column_meta_fn meta_cb,
325+ vef_row_fn row_cb, void *ctx,
326+ char *error_msg);
327+
256328typedef struct {
257329 // protocol >= VEF_PROTOCOL_1
258330 vef_protocol_t protocol;
@@ -270,6 +342,7 @@ typedef struct {
270342 vef_set_variable_fn set_variable;
271343 vef_read_keyring_fn read_keyring;
272344 vef_write_keyring_fn write_keyring;
345+ vef_run_query_fn run_query;
273346} vef_register_arg_t ;
274347
275348typedef struct {
0 commit comments