2
//#define SUPPORT_PBMS_TRIGGERS
3
#ifdef SUPPORT_PBMS_TRIGGERS
4
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
6
* PrimeBase Media Stream for MySQL
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
* User Defined Functions for use in triggers for non PBMS enabled engines.
32
#include "cslib/CSConfig.h"
38
//#include "mysql_priv.h"
43
#include "cslib/CSGlobal.h"
44
#include "cslib/CSStrUtil.h"
45
#include "cslib/CSThread.h"
47
#include "engine_ms.h"
49
#ifdef MOVE_THIS_TO_ITS_OWN_FILE
50
bool pbms_enabled(const char *name)
53
PBMSSharedMemoryPtr sh_mem = StreamingEngines->sharedMemory;
57
for (int i = 0; i<sh_mem->sm_list_len && !found; i++) {
58
if (engine = sh_mem->sm_engine_list[i]) {
59
found = (strcasecmp(name, engine->ms_engine_name) == 0);
67
// =============================
68
#define PBMS_ENGINE_NAME_LEN 64 // This should be big enough.
69
bool pbms_engine_is_enabled(char *name, size_t len)
73
if (len < PBMS_ENGINE_NAME_LEN) {
74
char engine_name[PBMS_ENGINE_NAME_LEN];
75
memcpy(engine_name, name, len);
78
found = pbms_enabled(engine_name);
84
// =============================
85
static bool trig_open_table(void **open_table, char *table_path, PBMSResultPtr result)
87
return do_open_table(open_table, table_path, result);
90
char *pbms_trig_use_blob(const char *database, size_t db_len, const char *table, size_t tab_len, unsigned short col_position, char *url, size_t url_len, char *out_url, PBMSResultPtr result)
92
void *open_table = NULL;
94
char blob_url[PBMS_BLOB_URL_SIZE], *ret_blob_url;
95
char table_path[PATH_MAX];
97
if (url_len >= PBMS_BLOB_URL_SIZE) {
98
pbms_error_result(CS_CONTEXT, MS_ERR_INCORRECT_URL, "Incorrect URL", result);
102
if (pbms_table_path(database, db_len, table, tab_len, table_path, result) || trig_open_table(&open_table, table_path, result))
105
memcpy(blob_url, url, url_len);
106
blob_url[url_len] = 0;
108
// Internally col_position are '0' based for consistency with the internal PBXT calls to PBMS.
109
if (!(rtc = ms_use_blob(open_table, &ret_blob_url, blob_url, col_position -1, result))) {
110
if (!(rtc = ms_retain_blobs(open_table, result)))
111
cs_strcpy(PBMS_BLOB_URL_SIZE, out_url, ret_blob_url);
114
ms_close_table(open_table);
122
// =============================
123
char *pbms_use_blob(const char *database, const char *table, unsigned short col_position, char *url, size_t url_len, char *out_url, PBMSResultPtr result)
125
return pbms_trig_use_blob(database, strlen(database), table, strlen(table), col_position, url, url_len, out_url, result);
128
// =============================
129
int pbms_trig_release_blob(const char *database, size_t db_len, const char *table, size_t tab_len, unsigned short col_position, const char *url, size_t url_len, PBMSResultPtr result)
131
void *open_table = NULL;
133
char blob_url[PBMS_BLOB_URL_SIZE];
134
char table_path[PATH_MAX];
136
if (url_len >= PBMS_BLOB_URL_SIZE)
137
return 0; // url is too long to be a valid blob url.
139
if (pbms_table_path(database, db_len, table, tab_len, table_path, result) || trig_open_table(&open_table, table_path, result))
142
memcpy(blob_url, url, url_len);
143
blob_url[url_len] = 0;
145
rtc = ms_release_blob(open_table, blob_url, result);
147
ms_close_table(open_table);
152
// =============================
153
int pbms_release_blob(const char *database, const char *table, unsigned short col_position, const char *url, size_t url_len, PBMSResultPtr result)
155
return pbms_trig_release_blob(database, strlen(database), table, strlen(table), col_position, url, url_len, result);
158
// =============================
159
int pbms_new_blob(const char *database, const char *table, unsigned short col_position, unsigned char *blob, size_t blob_len, char *out_url, PBMSResultPtr result)
161
void *open_table = NULL;
162
char table_path[PATH_MAX];
165
if (pbms_table_path(database, strlen(database), table, strlen(table), table_path, result) || trig_open_table(&open_table, table_path, result))
168
rtc = ms_create_blob(open_table, blob, blob_len, out_url, col_position -1, result);
170
ms_close_table(open_table);
175
// =============================
176
int pbms_trig_drop_table(const char *database, size_t db_len, const char *table, size_t tab_len, PBMSResultPtr result)
178
char table_path[PATH_MAX];
180
if (pbms_table_path(database, db_len, table, tab_len, table_path, result))
183
return ms_drop_table(table_path, result);
186
// =============================
187
int pbms_drop_table(const char *database, const char *table, PBMSResultPtr result)
189
return pbms_trig_drop_table(database, strlen(database), table, strlen(table), result);
192
// =============================
193
int pbms_trig_rename_table(const char *database, size_t db_len, const char *o_table, size_t o_tab_len, const char *n_table, size_t n_tab_len, PBMSResultPtr result)
195
char o_table_path[PATH_MAX], n_table_path[PATH_MAX];
197
if (pbms_table_path(database, db_len, o_table, o_tab_len, o_table_path, result) || pbms_table_path(database, db_len, n_table, n_tab_len, n_table_path, result) )
200
return ms_rename_table(o_table_path, n_table_path, result);
203
// =============================
204
int pbms_rename_table(const char *database, const char *o_table, const char *n_table, PBMSResultPtr result)
206
return pbms_trig_rename_table(database, strlen(database), o_table, strlen(o_table), n_table, strlen(n_table), result);
209
#endif MOVE_THIS_TO_ITS_OWN_FILE
212
my_bool pbms_insert_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
213
char *pbms_insert_blob_trig(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error);
214
void pbms_insert_blob_trig_deinit(UDF_INIT *initid);
217
my_bool pbms_update_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
218
char *pbms_update_blob_trig(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error);
219
void pbms_update_blob_trig_deinit(UDF_INIT *initid);
222
my_bool pbms_delete_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
223
longlong pbms_delete_blob_trig(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
226
my_bool pbms_delete_all_blobs_in_table_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
227
longlong pbms_delete_all_blobs_in_table(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
230
my_bool pbms_rename_table_with_blobs_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
231
longlong pbms_rename_table_with_blobs(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
234
my_bool pbms_enabled_engine_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
235
longlong pbms_enabled_engine(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
238
static void report_udf_error(UDF_INIT *initid __attribute__((unused)), char *error, const char *func, const char *message)
242
// I wish there were a way to pass the error text up to the caller but I do not know if/how it can be done.
243
// So for now just send it to stderr.
244
fprintf(stderr, "PBMS UDF Error (%s): %s\n", func, message);
247
static char *local_reference_blob(UDF_INIT *initid, char *database, size_t db_len, char *table, size_t tab_len, unsigned short col_position, char *url, size_t url_len, char *result, char *error, const char *func)
249
char *out_url = NULL, blob_url[PBMS_BLOB_URL_SIZE];
250
PBMSResultRec pbmsResult = {0};
252
out_url = pbms_trig_use_blob(database, db_len, table, tab_len, col_position, url, url_len, blob_url, &pbmsResult);
255
size_t url_len = strlen(out_url) +1;
257
cs_strcpy(255, result, out_url);
260
initid->ptr = (char*) malloc(url_len);
262
cs_strcpy(url_len, initid->ptr, out_url);
263
out_url = initid->ptr;
265
report_udf_error(initid, error, func, "Couldn't allocate memory");
269
} else if (pbmsResult.mr_code == MS_ERR_INCORRECT_URL)
270
out_url = url; // Not a URL so just return it so that it is inserted as is.
272
report_udf_error(initid, error, func, pbmsResult.mr_message);
278
//======================================================================
279
// CREATE FUNCTION pbms_insert_blob_trig RETURNS STRING SONAME "libpbms.so";
280
// pbms_insert_blob_trig(database, table, col_position, blob_url);
281
my_bool pbms_insert_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
283
if (args->arg_count != 4 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != INT_RESULT || args->arg_type[3] != STRING_RESULT)
285
strcpy(message,"Wrong arguments to pbms_insert_blob_trig()");
288
args->maybe_null[0] = 0;
289
args->maybe_null[1] = 0;
290
args->maybe_null[2] = 0;
291
args->maybe_null[3] = 1;
293
initid->max_length=PBMS_BLOB_URL_SIZE;
294
initid->maybe_null=1;
299
void pbms_insert_blob_trig_deinit(UDF_INIT *initid)
304
#define INT_ARG(a) (*((longlong*) a))
306
char *pbms_insert_blob_trig(UDF_INIT *initid, UDF_ARGS *args,
307
char *result, unsigned long *res_length, char *is_null,
314
// The first parameter is the table name which should never be NULL or an empty string.
315
if (!args->args[0] || !args->lengths[0] || !args->args[1] || !args->lengths[1]) {
316
report_udf_error(initid, error, __FUNC__, "Bad arguments");
320
if (!args->args[3] || !args->lengths[3]) {
324
out_url = local_reference_blob(initid, args->args[0], args->lengths[0], args->args[1], args->lengths[1], INT_ARG(args->args[2]), args->args[3], args->lengths[3], result, error, __FUNC__);
329
*res_length = strlen(out_url);
333
//======================================================================
334
// CREATE FUNCTION pbms_update_blob_trig RETURNS STRING SONAME "libpbms.so";
335
// pbms_update_blob_trig(database, table, col_position, old_blob_url, new_blob_url);
336
my_bool pbms_update_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
338
if (args->arg_count != 5 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != INT_RESULT || args->arg_type[3] != STRING_RESULT || args->arg_type[4] != STRING_RESULT)
340
strcpy(message,"Wrong arguments to pbms_update_blob_trig()");
343
args->maybe_null[0] = 0;
344
args->maybe_null[1] = 0;
345
args->maybe_null[2] = 0;
346
args->maybe_null[3] = 1;
347
args->maybe_null[4] = 1;
349
initid->maybe_null=1;
354
void pbms_update_blob_trig_deinit(UDF_INIT *initid)
359
char *pbms_update_blob_trig(UDF_INIT *initid, UDF_ARGS *args,
360
char *result, unsigned long *res_length, char *is_null,
363
char *out_url = NULL;
366
// The first parameter is the table name which should never be NULL or an empty string.
367
if (!args->args[0] || !args->lengths[0] || !args->args[1] || !args->lengths[1]) {
368
report_udf_error(initid, error, __FUNC__, "Bad arguments");
372
// Check to see if the blob url changed
373
if (args->lengths[2] == args->lengths[3] && !memcmp(args->args[2], args->args[3], args->lengths[3])) {
374
if (args->lengths[2]) {
376
*res_length = args->lengths[2];
377
return args->args[2];
385
if (args->lengths[4] && args->args[4]) { // Reference the new blob.
386
out_url = local_reference_blob(initid, args->args[0], args->lengths[0], args->args[1], args->lengths[1], INT_ARG(args->args[2]), args->args[4], args->lengths[4], result, error, __FUNC__);
391
if (args->lengths[3] && args->args[3]) { // Dereference the old blob
392
PBMSResultRec pbmsResult = {0};
393
if (pbms_trig_release_blob(args->args[0], args->lengths[0], args->args[1], args->lengths[1], INT_ARG(args->args[2]), args->args[3], args->lengths[3], &pbmsResult)) {
394
report_udf_error(initid, error, __FUNC__, pbmsResult.mr_message);
396
pbms_trig_release_blob(args->args[0], args->lengths[0], args->args[1], args->lengths[1], INT_ARG(args->args[2]), out_url, strlen(out_url), &pbmsResult);
403
*res_length = strlen(out_url);
409
//======================================================================
410
// CREATE FUNCTION pbms_delete_blob_trig RETURNS INT SONAME "libpbms.so";
411
// pbms_delete_blob_trig(database, table, col_position, blob_url);
412
my_bool pbms_delete_blob_trig_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
414
if (args->arg_count != 4 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != INT_RESULT || args->arg_type[3] != STRING_RESULT)
416
strcpy(message,"Wrong arguments to pbms_delete_blob_trig()");
419
args->maybe_null[0] = 0;
420
args->maybe_null[1] = 0;
421
args->maybe_null[2] = 0;
422
args->maybe_null[3] = 1;
423
initid->maybe_null=0;
428
longlong pbms_delete_blob_trig(UDF_INIT *initid, UDF_ARGS *args, char *is_null __attribute__((unused)), char *error)
430
PBMSResultRec pbmsResult = {0};
432
// The first parameter is the table name which should never be NULL or an empty string.
433
if (!args->args[0] || !args->lengths[0] || !args->args[1] || !args->lengths[1]) {
434
report_udf_error(initid, error, __FUNC__, "Bad arguments");
438
if (!args->args[3] || !args->lengths[3]) {
439
return 0; //Dropping a NULL blob.
442
if (! pbms_trig_release_blob(args->args[0], args->lengths[0], args->args[1], args->lengths[1], INT_ARG(args->args[2]), args->args[3], args->lengths[3], &pbmsResult))
445
report_udf_error(initid, error, __FUNC__, pbmsResult.mr_message);
450
//======================================================================
451
// CREATE FUNCTION pbms_delete_all_blobs_in_table RETURNS INT SONAME "libpbms.so";
452
// pbms_delete_all_blobs_in_table(database, table);
453
my_bool pbms_delete_all_blobs_in_table_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
455
if (args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT)
457
strcpy(message,"Wrong arguments to pbms_delete_all_blobs_in_table()");
460
args->maybe_null[0] = 0;
461
args->maybe_null[1] = 0;
462
initid->maybe_null=0;
467
longlong pbms_delete_all_blobs_in_table(UDF_INIT *initid, UDF_ARGS *args, char *is_null __attribute__((unused)), char *error)
469
PBMSResultRec pbmsResult = {0};
471
// The first parameter is the table name which should never be NULL or an empty string.
472
if (args->arg_count != 2 || !args->args[0] || !args->lengths[0] || !args->args[1] || !args->lengths[1]) {
473
report_udf_error(initid, error, __FUNC__, "Bad arguments");
477
if (!pbms_trig_drop_table(args->args[0], args->lengths[0], args->args[1], args->lengths[1], &pbmsResult))
480
report_udf_error(initid, error, __FUNC__, pbmsResult.mr_message);
484
//======================================================================
485
// CREATE FUNCTION pbms_rename_table_with_blobs RETURNS INT SONAME "libpbms.so";
486
// pbms_rename_table_with_blobs(database, old_table, new_table);
487
my_bool pbms_rename_table_with_blobs_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
489
if (args->arg_count != 3 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != STRING_RESULT)
491
strcpy(message,"Wrong arguments to pbms_rename_table_with_blobs()");
494
args->maybe_null[0] = 0;
495
args->maybe_null[1] = 0;
496
args->maybe_null[2] = 0;
497
initid->maybe_null=0;
502
longlong pbms_rename_table_with_blobs(UDF_INIT *initid, UDF_ARGS *args, char *is_null __attribute__((unused)), char *error)
504
PBMSResultRec pbmsResult = {0};
506
// The first parameter is the table name which should never be NULL or an empty string.
507
if (args->arg_count != 3 || !args->args[0] || !args->lengths[0] || !args->args[1] || !args->lengths[1] || !args->args[2] || !args->lengths[2]) {
508
report_udf_error(initid, error, __FUNC__, "Bad arguments");
512
if (!pbms_trig_rename_table(args->args[0], args->lengths[0], args->args[1], args->lengths[1], args->args[2], args->lengths[2], &pbmsResult))
515
report_udf_error(initid, error, __FUNC__, pbmsResult.mr_message);
519
//======================================================================
520
// CREATE FUNCTION pbms_enabled_engine RETURNS INT SONAME "libpbms.so";
521
// pbms_enabled_engine(database, table);
522
my_bool pbms_enabled_engine_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
524
if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT)
526
strcpy(message,"Wrong arguments to pbms_enabled_engine()");
529
args->maybe_null[0] = 0;
530
initid->maybe_null=0;
535
longlong pbms_enabled_engine(UDF_INIT *initid, UDF_ARGS *args, char *is_null __attribute__((unused)), char *error)
537
// The first parameter is the engine name which should never be NULL or an empty string.
538
if (args->arg_count != 1 || !args->args[0] || !args->lengths[0]) {
539
report_udf_error(initid, error, __FUNC__, "Bad arguments");
543
return pbms_engine_is_enabled(args->args[0], args->lengths[0]);
546
#endif // SUPPORT_PBMS_TRIGGERS