-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mrb_eval.cc
141 lines (126 loc) · 3.39 KB
/
mrb_eval.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifdef _WIN32
#define _TIMESPEC_DEFINED
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#define _SSIZE_T_
#define _NO_OLDNAMES
#ifndef RTL_SRWLOCK_INIT
typedef PVOID RTL_SRWLOCK;
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE;
#endif
#endif
#include <my_global.h>
extern "C" {
#include <my_sys.h>
#include <mysql.h>
#include <mruby.h>
#undef INCLUDE_ENCODING
#include <mruby/compile.h>
#include <mruby/proc.h>
#include <mruby/string.h>
#include <mruby/array.h>
#include <mruby/variable.h>
}
#ifdef _WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
#include <cstring>
extern "C" {
EXPORT my_bool mrb_eval_init(UDF_INIT* initid, UDF_ARGS* args, char* message);
EXPORT void mrb_eval_deinit(UDF_INIT* initid);
EXPORT char* mrb_eval(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error);
}
typedef struct {
mrb_state* mrb;
struct mrbc_context* ctx;
} mrb_mysql;
EXPORT
my_bool
mrb_eval_init(UDF_INIT* initid, UDF_ARGS* args, char* message) {
if (args->arg_count == 0) {
strncpy(message, "mrb_eval: required just one argument at least", MYSQL_ERRMSG_SIZE);
return 1;
}
if (args->arg_type[0] != STRING_RESULT) {
strncpy(message, "mrb_eval: argument should be a string", MYSQL_ERRMSG_SIZE);
return 1;
}
args->maybe_null[0] = 0;
mrb_mysql* m = (mrb_mysql*) malloc(sizeof(mrb_mysql));
m->mrb = mrb_open();
m->ctx = mrbc_context_new(m->mrb);
initid->ptr = (char *)(void *) m;
initid->const_item = 1;
return 0;
}
EXPORT
void
mrb_eval_deinit(UDF_INIT* initid) {
mrb_mysql* m = (mrb_mysql*) initid->ptr;
mrb_state* mrb = m->mrb;
mrbc_context_free(mrb, m->ctx);
mrb_close(mrb);
free(m);
}
void
mrb_init_mrblib(mrb_state *mrb) {
}
void
mrb_init_mrbgems(mrb_state* mrb) {
}
EXPORT
char*
mrb_eval(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length, char* is_null, char* error) {
if (args->arg_count > 0) {
mrb_mysql* m = (mrb_mysql*) initid->ptr;
mrb_state* mrb = m->mrb;
char *p;
int n;
mrb_value argv = mrb_ary_new(mrb);
for (n = 1; n < args->arg_count; n++) {
switch (args->arg_type[n]) {
case STRING_RESULT:
mrb_ary_push(mrb, argv, mrb_str_new(mrb, args->args[n], args->lengths[n]));
break;
case INT_RESULT:
mrb_ary_push(mrb, argv, mrb_fixnum_value((mrb_int)*(long long*)(args->args[n])));
break;
case REAL_RESULT:
mrb_ary_push(mrb, argv, mrb_float_value(mrb, (mrb_float)*(double*)&(args->args[n])));
break;
case DECIMAL_RESULT:
mrb_ary_push(mrb, argv, mrb_str_new(mrb, args->args[n], args->lengths[n]));
break;
default:
*error = 1;
return strdup("invalid type");
}
}
mrb_define_global_const(mrb, "ARGV", argv);
mrb_value v = mrb_load_string_cxt(mrb, args->args[0], m->ctx);
if (mrb->exc == 0) {
v = mrb_funcall(mrb, v, "to_s", 0);
if (mrb->exc == 0) {
*length = RSTRING_LEN(v);
p = (char*) malloc(RSTRING_LEN(v) + 1);
if (p) {
strcpy(p, RSTRING_PTR(v));
return p;
}
*is_null = 1;
return NULL;
}
}
mrb_value exc = mrb_obj_value(mrb->exc);
mrb_value inspect = mrb_inspect(mrb, exc);
*error = 1;
p = mrb_str_to_cstr(mrb, inspect);
*length = strlen(p);
return strdup(p);
}
*is_null = 1;
return NULL;
}