136 lines
2.8 KiB
C++
136 lines
2.8 KiB
C++
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <mysql/mysql.h>
|
|
|
|
#define NAME "sql_printf"
|
|
#define N_ARGS 1
|
|
#define BLOCK_SIZE 1024
|
|
|
|
extern "C" {
|
|
|
|
typedef struct {
|
|
int * org_type;
|
|
char * data;
|
|
unsigned long len;
|
|
unsigned long alloc;
|
|
}
|
|
Buffer;
|
|
|
|
static void buffer_append_len(Buffer *buffer, const char *string, unsigned long len) {
|
|
if (!string) return;
|
|
unsigned long new_len = buffer->len + len;
|
|
|
|
if (new_len > buffer->alloc) {
|
|
buffer->alloc = new_len + BLOCK_SIZE - (new_len % BLOCK_SIZE);
|
|
buffer->data = (char *) realloc(buffer->data, sizeof(char) * buffer->alloc);
|
|
}
|
|
|
|
strncpy(&buffer->data[buffer->len], string, len);
|
|
buffer->len = new_len;
|
|
}
|
|
|
|
static void buffer_append(Buffer *buffer, const char *string) {
|
|
if (!string) return;
|
|
buffer_append_len(buffer, string, strlen(string));
|
|
}
|
|
|
|
char * sql_printf(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) {
|
|
unsigned int i = 1;
|
|
unsigned long j = 0;
|
|
Buffer *buffer = (Buffer *) initid->ptr;
|
|
char *format = args->args[0];
|
|
|
|
if (!format) {
|
|
*is_null = 1;
|
|
return NULL;
|
|
}
|
|
|
|
while (1) {
|
|
const char *delimiter = NULL;
|
|
unsigned long aux = j;
|
|
|
|
while (j < args->lengths[0] && format[j] != '%')
|
|
j++;
|
|
|
|
buffer_append_len(buffer, &format[aux], j - aux);
|
|
|
|
if (j == args->lengths[0])
|
|
break;
|
|
|
|
char c = format[j+1];
|
|
j += 2;
|
|
|
|
switch (c) {
|
|
case 't':
|
|
delimiter = "`";
|
|
break;
|
|
case 'v':
|
|
if (buffer->org_type[i] == STRING_RESULT)
|
|
delimiter = "'";
|
|
break;
|
|
case 's':
|
|
break;
|
|
case '%':
|
|
buffer_append(buffer, "%");
|
|
continue;
|
|
default:
|
|
*error = 1;
|
|
return NULL;
|
|
}
|
|
|
|
if (i >= args->arg_count) {
|
|
*error = 1;
|
|
return NULL;
|
|
}
|
|
|
|
char *arg = args->args[i];
|
|
|
|
if (arg != NULL) {
|
|
buffer_append(buffer, delimiter);
|
|
buffer_append_len(buffer, arg, args->lengths[i]);
|
|
buffer_append(buffer, delimiter);
|
|
} else
|
|
buffer_append(buffer, "NULL");
|
|
|
|
i++;
|
|
}
|
|
|
|
*length = buffer->len;
|
|
return buffer->data;
|
|
}
|
|
|
|
bool sql_printf_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
|
|
if (args->arg_count >= N_ARGS) {
|
|
unsigned int i;
|
|
Buffer *buffer = (Buffer *) malloc(sizeof(Buffer));
|
|
buffer->org_type = (int *) malloc(sizeof(int) * args->arg_count);
|
|
buffer->alloc = BLOCK_SIZE;
|
|
buffer->data = (char *) malloc(sizeof(char) * buffer->alloc);
|
|
buffer->len = 0;
|
|
|
|
for (i = 0; i < args->arg_count; i++) {
|
|
buffer->org_type[i] = args->arg_type[i];
|
|
args->arg_type[i] = STRING_RESULT;
|
|
}
|
|
|
|
initid->ptr = (char *) buffer;
|
|
initid->maybe_null = 1;
|
|
initid->const_item = 0;
|
|
return 0;
|
|
} else {
|
|
sprintf(message, "%s must have at least %d parameters", NAME, N_ARGS);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void sql_printf_deinit(UDF_INIT *initid) {
|
|
Buffer *buffer = (Buffer *) initid->ptr;
|
|
free(buffer->org_type);
|
|
free(buffer->data);
|
|
free(buffer);
|
|
}
|
|
|
|
}
|