This repository has been archived on 2024-01-15. You can view files and clone it, but cannot push or open issues or pull requests.
vn-mysql/src/functions/sql_printf.c

147 lines
2.6 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mysql/mysql.h>
#define NAME "multimax"
#define NPARAMS 1
#define BLOCK_SIZE 1024
typedef struct
{
int * org_type;
char * data;
unsigned long len;
unsigned long alloc;
}
Buffer;
static void buffer_append (Buffer *buffer, 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 = realloc (buffer->data, sizeof (char) * buffer->alloc);
}
strncpy (&buffer->data[buffer->len], string, len);
buffer->len = new_len;
}
char * sql_printf (UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
{
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)
{
char *delimiter = NULL;
unsigned long aux = j;
while (j < args->lengths[0] && format[j] != '%')
j++;
buffer_append (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, "%", 1);
continue;
default:
*error = 1;
return NULL;
}
if (i >= args->arg_count)
{
*error = 1;
return NULL;
}
char *arg = args->args[i];
unsigned long len = args->lengths[i];
if (!arg)
{
arg = "NULL";
len = strlen (arg);
delimiter = NULL;
}
buffer_append (buffer, delimiter, 1);
buffer_append (buffer, arg, len);
buffer_append (buffer, delimiter, 1);
i++;
}
*length = buffer->len;
return buffer->data;
}
my_bool sql_printf_init (UDF_INIT *initid, UDF_ARGS *args, char *message)
{
if (args->arg_count >= NPARAMS)
{
int i;
Buffer *buffer = malloc (sizeof (Buffer));
buffer->org_type = malloc (sizeof (int) * args->arg_count);
buffer->alloc = BLOCK_SIZE;
buffer->data = 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 = (void *) buffer;
initid->maybe_null = 1;
initid->const_item = 0;
return 0;
}
else
{
sprintf (message, "%s must have at least %d parameters", NAME, NPARAMS);
return 1;
}
}
void sql_printf_deinit (UDF_INIT *initid)
{
Buffer *buffer = (Buffer *) initid->ptr;
free (buffer->org_type);
free (buffer->data);
free (buffer);
}