jrmey-mysqlplus 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/mysql.c ADDED
@@ -0,0 +1,2828 @@
1
+ /* ruby mysql module
2
+ * $Id: mysql.c 229 2008-06-20 07:44:04Z tommy $
3
+ * modified 2008-08-26 Muhammad A. Ali
4
+ * added an async interface
5
+ */
6
+
7
+ #include <ruby.h>
8
+ #include <errno.h>
9
+ #include <stdarg.h>
10
+ #ifndef RSTRING_PTR
11
+ #define RSTRING_PTR(str) RSTRING(str)->ptr
12
+ #endif
13
+ #ifndef RSTRING_LEN
14
+ #define RSTRING_LEN(str) RSTRING(str)->len
15
+ #endif
16
+ #ifndef RARRAY_PTR
17
+ #define RARRAY_PTR(ary) RARRAY(ary)->ptr
18
+ #endif
19
+ #ifndef HAVE_RB_STR_SET_LEN
20
+ #define rb_str_set_len(str, length) (RSTRING_LEN(str) = (length))
21
+ #endif
22
+
23
+ #ifdef RUBY19
24
+ #include <ruby/encoding.h>
25
+ #define DEFAULT_ENCODING (rb_enc_get(rb_enc_default_external()))
26
+ #else
27
+ #define DEFAULT_ENCODING NULL
28
+ #define rb_enc_str_new(ptr, len, enc) rb_str_new(ptr, len)
29
+ #endif
30
+
31
+ VALUE
32
+ rb_enc_tainted_str_new(const char *ptr, long len)
33
+ {
34
+ VALUE str = rb_enc_str_new(ptr, len, DEFAULT_ENCODING);
35
+
36
+ OBJ_TAINT(str);
37
+ return str;
38
+ }
39
+
40
+ VALUE
41
+ rb_enc_tainted_str_new2(const char *ptr)
42
+ {
43
+ VALUE str = rb_enc_str_new(ptr, strlen(ptr), DEFAULT_ENCODING);
44
+
45
+ OBJ_TAINT(str);
46
+ return str;
47
+ }
48
+
49
+
50
+
51
+
52
+ #ifdef HAVE_MYSQL_H
53
+ #include <mysql.h>
54
+ #include <mysql_com.h>
55
+ //#include <violite.h>
56
+ #include <errmsg.h>
57
+ #include <mysqld_error.h>
58
+ #else
59
+ #include <mysql/mysql.h>
60
+ #include <mysql/mysql_com.h>
61
+ //#include <mysql/violite.h>
62
+ #include <mysql/errmsg.h>
63
+ #include <mysql/mysqld_error.h>
64
+ #endif
65
+
66
+ #define MYSQL_RUBY_VERSION 20800
67
+
68
+ #define GC_STORE_RESULT_LIMIT 20
69
+
70
+ #if MYSQL_VERSION_ID < 32224
71
+ #define mysql_field_count mysql_num_fields
72
+ #endif
73
+
74
+ #define NILorSTRING(obj) (NIL_P(obj)? NULL: StringValuePtr(obj))
75
+ #define NILorINT(obj) (NIL_P(obj)? 0: NUM2INT(obj))
76
+
77
+ #define GetMysqlStruct(obj) (Check_Type(obj, T_DATA), (struct mysql*)DATA_PTR(obj))
78
+ #define GetHandler(obj) (Check_Type(obj, T_DATA), &(((struct mysql*)DATA_PTR(obj))->handler))
79
+ #define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res)
80
+ #define GetMysqlStmt(obj) (Check_Type(obj, T_DATA), ((struct mysql_stmt*)DATA_PTR(obj))->stmt)
81
+
82
+ VALUE cMysql;
83
+ VALUE cMysqlRes;
84
+ VALUE cMysqlField;
85
+ VALUE cMysqlStmt;
86
+ VALUE cMysqlRowOffset;
87
+ VALUE cMysqlTime;
88
+ VALUE eMysql;
89
+
90
+ static int store_result_count = 0;
91
+
92
+ struct mysql {
93
+ MYSQL handler;
94
+ char connection;
95
+ char query_with_result;
96
+ char gc_disabled;
97
+ char blocking;
98
+ int async_in_progress;
99
+ char busy;
100
+ };
101
+
102
+ // a wrapper for mysql_res's so we can detect double frees
103
+ struct mysql_res {
104
+ MYSQL_RES* res;
105
+ char freed;
106
+ };
107
+
108
+ #if MYSQL_VERSION_ID >= 40101
109
+ struct mysql_stmt {
110
+ MYSQL_STMT *stmt;
111
+ char closed;
112
+ struct {
113
+ int n;
114
+ MYSQL_BIND *bind;
115
+ unsigned long *length;
116
+ MYSQL_TIME *buffer;
117
+ } param;
118
+ struct {
119
+ int n;
120
+ MYSQL_BIND *bind;
121
+ my_bool *is_null;
122
+ unsigned long *length;
123
+ } result;
124
+ MYSQL_RES *res;
125
+ };
126
+ #endif
127
+
128
+ /* free Mysql class object */
129
+ static void free_mysql(struct mysql* my)
130
+ {
131
+ if (my->connection == Qtrue)
132
+ mysql_close(&my->handler);
133
+ xfree(my);
134
+ }
135
+
136
+ static void free_mysqlres(struct mysql_res* resp)
137
+ {
138
+ if (resp->freed == Qfalse) {
139
+ mysql_free_result(resp->res);
140
+ store_result_count--;
141
+ }
142
+ xfree(resp);
143
+ }
144
+
145
+ #if MYSQL_VERSION_ID >= 40101
146
+ static void free_mysqlstmt_memory(struct mysql_stmt *s)
147
+ {
148
+ if (s->param.bind) {
149
+ xfree(s->param.bind);
150
+ s->param.bind = NULL;
151
+ }
152
+ if (s->param.length) {
153
+ xfree(s->param.length);
154
+ s->param.length = NULL;
155
+ }
156
+ if (s->param.buffer) {
157
+ xfree(s->param.buffer);
158
+ s->param.buffer = NULL;
159
+ }
160
+ s->param.n = 0;
161
+ if (s->res) {
162
+ mysql_free_result(s->res);
163
+ s->res = NULL;
164
+ }
165
+ if (s->result.bind) {
166
+ int i;
167
+ for (i = 0; i < s->result.n; i++) {
168
+ if (s->result.bind[i].buffer)
169
+ xfree(s->result.bind[i].buffer);
170
+ s->result.bind[i].buffer = NULL;
171
+ }
172
+ xfree(s->result.bind);
173
+ s->result.bind = NULL;
174
+ }
175
+ if (s->result.is_null) {
176
+ xfree(s->result.is_null);
177
+ s->result.is_null = NULL;
178
+ }
179
+ if (s->result.length) {
180
+ xfree(s->result.length);
181
+ s->result.length = NULL;
182
+ }
183
+ s->result.n = 0;
184
+ }
185
+
186
+ static void free_execute_memory(struct mysql_stmt *s)
187
+ {
188
+ if (s->res && s->result.bind) {
189
+ int i;
190
+ for (i = 0; i < s->result.n; i++) {
191
+ if (s->result.bind[i].buffer)
192
+ xfree(s->result.bind[i].buffer);
193
+ s->result.bind[i].buffer = NULL;
194
+ }
195
+ }
196
+ mysql_stmt_free_result(s->stmt);
197
+ }
198
+
199
+ static void free_mysqlstmt(struct mysql_stmt* s)
200
+ {
201
+ free_mysqlstmt_memory(s);
202
+ if (s->closed == Qfalse)
203
+ mysql_stmt_close(s->stmt);
204
+ if (s->res)
205
+ mysql_free_result(s->res);
206
+ xfree(s);
207
+ }
208
+ #endif
209
+
210
+ static void mysql_raise(MYSQL* m)
211
+ {
212
+ VALUE e = rb_exc_new2(eMysql, mysql_error(m));
213
+ rb_iv_set(e, "errno", INT2FIX(mysql_errno(m)));
214
+ #if MYSQL_VERSION_ID >= 40101
215
+ rb_iv_set(e, "sqlstate", rb_enc_tainted_str_new2(mysql_sqlstate(m)));
216
+ #endif
217
+ rb_exc_raise(e);
218
+ }
219
+
220
+ static VALUE mysqlres2obj(MYSQL_RES* res, VALUE gc_disabled)
221
+ {
222
+ VALUE obj;
223
+ struct mysql_res* resp;
224
+ obj = Data_Make_Struct(cMysqlRes, struct mysql_res, 0, free_mysqlres, resp);
225
+ rb_iv_set(obj, "colname", Qnil);
226
+ rb_iv_set(obj, "tblcolname", Qnil);
227
+ resp->res = res;
228
+ resp->freed = Qfalse;
229
+ rb_obj_call_init(obj, 0, NULL);
230
+ /* disabled until it can be reviewed further--rely on the normal GC for now.
231
+ if (++store_result_count > GC_STORE_RESULT_LIMIT)
232
+ rb_gc();
233
+ */
234
+ return obj;
235
+ }
236
+
237
+ /* make Mysql::Field object */
238
+ static VALUE make_field_obj(MYSQL_FIELD* f)
239
+ {
240
+ VALUE obj;
241
+ if (f == NULL)
242
+ return Qnil;
243
+ obj = rb_obj_alloc(cMysqlField);
244
+ rb_iv_set(obj, "name", f->name? rb_str_freeze(rb_enc_tainted_str_new2(f->name)): Qnil);
245
+ rb_iv_set(obj, "table", f->table? rb_str_freeze(rb_enc_tainted_str_new2(f->table)): Qnil);
246
+ rb_iv_set(obj, "def", f->def? rb_str_freeze(rb_enc_tainted_str_new2(f->def)): Qnil);
247
+ rb_iv_set(obj, "type", INT2NUM(f->type));
248
+ rb_iv_set(obj, "length", INT2NUM(f->length));
249
+ rb_iv_set(obj, "max_length", INT2NUM(f->max_length));
250
+ rb_iv_set(obj, "flags", INT2NUM(f->flags));
251
+ rb_iv_set(obj, "decimals", INT2NUM(f->decimals));
252
+ return obj;
253
+ }
254
+
255
+ /*-------------------------------
256
+ * Mysql class method
257
+ */
258
+
259
+ /* init() */
260
+ static VALUE init(VALUE klass)
261
+ {
262
+ struct mysql* myp;
263
+ VALUE obj;
264
+
265
+ obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp);
266
+ mysql_init(&myp->handler);
267
+ myp->connection = Qfalse;
268
+ myp->query_with_result = Qtrue;
269
+ myp->gc_disabled = Qtrue;
270
+ rb_obj_call_init(obj, 0, NULL);
271
+ return obj;
272
+ }
273
+
274
+ // =========== a 1.9 rb_thread_blocking_region simplifier attempt
275
+ #ifdef HAVE_TBR
276
+
277
+ typedef struct
278
+ {
279
+ void *func_pointer;
280
+ int param_count;
281
+ void *args[10];
282
+ } arg_holder, *arg_holder2;
283
+
284
+ // here's how to make rb_thread_blocking_region much cleaner and easier
285
+ // syntax: param_count+2, func_pointer to call, [RUBY_UBF_IO or RUBY_UBF_PROCESS], param1, param2...
286
+ // the third parameter is the interuptor--possible values appear to be RUBY_UBF_IO or RUBY_UBF_PROCESS http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/ad8c1326b2a8e404/00447b9aa15979be?lnk=raot
287
+ // ex: (int) returned_this = rb_thread_blocking_region_variable_params(10, &method_name, RUBY_UBF_IO, param1, param2, param3, param4, param5, param6, param7, param8)
288
+
289
+ static void *call_single_function_rb_thread_blocking_region(void *arg_holder_in);
290
+
291
+ void *rb_thread_blocking_region_variable_params(int number, ...)
292
+ {
293
+ va_list param_pt;
294
+ va_start(param_pt, number);
295
+ int index;
296
+ arg_holder param_storer;
297
+ void *func_pointer = va_arg(param_pt, void *);
298
+ void *interrupter = va_arg(param_pt, void *);
299
+ param_storer.func_pointer = func_pointer;
300
+ int real_param_count = number - 2;
301
+ param_storer.param_count = real_param_count;
302
+ for(index = 0 ; index < real_param_count ; index++)
303
+ {
304
+ void *arg = va_arg(param_pt, void *);
305
+ param_storer.args[index] = arg;
306
+
307
+ }
308
+ va_end(param_pt);
309
+
310
+ return (void *) rb_thread_blocking_region((rb_blocking_function_t *)call_single_function_rb_thread_blocking_region, (void *) &param_storer, interrupter, 0);
311
+
312
+ }
313
+
314
+ // used internally
315
+ static void * call_single_function_rb_thread_blocking_region(void *arg_holder_in)
316
+ {
317
+ arg_holder *params_and_func = (arg_holder *) arg_holder_in;
318
+ int param_count = params_and_func->param_count;
319
+ void *result;
320
+ switch(param_count)
321
+ {
322
+ case 3:;
323
+ void * (*pt3Func)(void *, void *, void *) = params_and_func->func_pointer;
324
+ result = (*pt3Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2]);
325
+ break;
326
+ case 6:;
327
+ void * (*pt6Func)(void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
328
+ result = (*pt6Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5]);
329
+ break;
330
+ case 8:;
331
+ void * (*pt8Func)(void *, void *, void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
332
+ result = (*pt8Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5], params_and_func->args[6], params_and_func->args[7]);
333
+ break;
334
+ default:;
335
+ printf("UNknown param count--please add it! %d\n", param_count);
336
+ result = (void *) Qnil;
337
+ }
338
+
339
+ return result;
340
+ }
341
+
342
+ #endif
343
+
344
+ static VALUE connection_identifier( VALUE obj )
345
+ {
346
+ MYSQL* m = GetHandler(obj);
347
+ return mysql_thread_id( m );
348
+ }
349
+
350
+ static VALUE async_in_progress( VALUE obj )
351
+ {
352
+ struct mysql* m = GetMysqlStruct(obj);
353
+ return ( m->async_in_progress == connection_identifier(obj) ) ? Qtrue : Qfalse;
354
+ }
355
+
356
+ static VALUE async_in_progress_set( VALUE obj, VALUE flag )
357
+ {
358
+ struct mysql* m = GetMysqlStruct(obj);
359
+ m->async_in_progress = (flag == Qnil || flag == Qfalse) ? 0 : connection_identifier(obj);
360
+ return flag;
361
+ }
362
+
363
+ // does this actually really do anything helpful? Not sure.
364
+ static void optimize_for_async( VALUE obj )
365
+ {
366
+ struct mysql* m = GetMysqlStruct(obj);
367
+ my_bool was_blocking;
368
+ vio_blocking(m->handler.net.vio, 0, &was_blocking);
369
+ m->blocking = vio_is_blocking( m->handler.net.vio );
370
+
371
+ vio_fastsend( m->handler.net.vio );
372
+ async_in_progress_set( obj, Qfalse );
373
+ }
374
+
375
+ // TODO does nothing currently
376
+ static void schedule_connect(VALUE obj )
377
+ {
378
+ /* TODO is this old?
379
+ MYSQL* m = GetHandler(obj);
380
+ fd_set read;
381
+
382
+ struct timeval tv = { tv_sec: m->options.connect_timeout, tv_usec: 0 };
383
+ if (rb_thread_select(0, NULL, NULL, NULL, &tv) < 0) {
384
+ rb_raise(eMysql, "connect: timeout");
385
+ }
386
+ */
387
+
388
+ /*
389
+ FD_ZERO(&read);
390
+ FD_SET(m->net.fd, &read);
391
+
392
+ if (rb_thread_select(m->net.fd + 1, &read, NULL, NULL, &tv) < 0) {
393
+ rb_raise(eMysql, "connect: timeout");
394
+ }
395
+ */
396
+ }
397
+
398
+ /* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */
399
+ static VALUE real_connect(int argc, VALUE* argv, VALUE klass)
400
+ {
401
+ VALUE host, user, passwd, db, port, sock, flag;
402
+ char *h, *u, *p, *d, *s;
403
+ unsigned int pp, f;
404
+ struct mysql* myp;
405
+ VALUE obj;
406
+
407
+ #if MYSQL_VERSION_ID >= 32200
408
+ rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag);
409
+ d = NILorSTRING(db);
410
+ f = NILorINT(flag);
411
+ #elif MYSQL_VERSION_ID >= 32115
412
+ rb_scan_args(argc, argv, "06", &host, &user, &passwd, &port, &sock, &flag);
413
+ f = NILorINT(flag);
414
+ #else
415
+ rb_scan_args(argc, argv, "05", &host, &user, &passwd, &port, &sock);
416
+ #endif
417
+ h = NILorSTRING(host);
418
+ u = NILorSTRING(user);
419
+ p = NILorSTRING(passwd);
420
+ pp = NILorINT(port);
421
+ s = NILorSTRING(sock);
422
+
423
+ obj = Data_Make_Struct(klass, struct mysql, 0, free_mysql, myp);
424
+ #if MYSQL_VERSION_ID >= 32200
425
+ mysql_init(&myp->handler); /* we get here */
426
+ # ifdef HAVE_TBR
427
+ if( (MYSQL *) rb_thread_blocking_region_variable_params(10, &mysql_real_connect, RUBY_UBF_IO, &myp->handler, h, u, p, d, pp, s, f) == NULL)
428
+ # else
429
+ if(mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL)
430
+ # endif
431
+ #elif MYSQL_VERSION_ID >= 32115
432
+ if (mysql_real_connect(&myp->handler, h, u, p, pp, s, f) == NULL)
433
+ #else
434
+ if (mysql_real_connect(&myp->handler, h, u, p, pp, s) == NULL)
435
+ #endif
436
+ mysql_raise(&myp->handler);
437
+
438
+ myp->handler.reconnect = 0;
439
+ myp->connection = Qtrue;
440
+
441
+ optimize_for_async(obj);
442
+
443
+ myp->query_with_result = Qtrue;
444
+ rb_obj_call_init(obj, argc, argv);
445
+
446
+ //schedule_connect(obj);
447
+
448
+ return obj;
449
+ }
450
+
451
+ /* escape_string(string) */
452
+ static VALUE escape_string(VALUE klass, VALUE str)
453
+ {
454
+ VALUE ret;
455
+ Check_Type(str, T_STRING);
456
+ ret = rb_enc_str_new(0, (RSTRING_LEN(str))*2+1, DEFAULT_ENCODING);
457
+ rb_str_set_len(ret, mysql_escape_string(RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str)));
458
+ return ret;
459
+ }
460
+
461
+ /* client_info() */
462
+ static VALUE client_info(VALUE klass)
463
+ {
464
+ return rb_enc_tainted_str_new2(mysql_get_client_info());
465
+ }
466
+
467
+ #if MYSQL_VERSION_ID >= 32332
468
+ /* my_debug(string) */
469
+ static VALUE my_debug(VALUE obj, VALUE str)
470
+ {
471
+ mysql_debug(StringValuePtr(str));
472
+ return obj;
473
+ }
474
+ #endif
475
+
476
+ #if MYSQL_VERSION_ID >= 40000
477
+ /* client_version() */
478
+ static VALUE client_version(VALUE obj)
479
+ {
480
+ return INT2NUM(mysql_get_client_version());
481
+ }
482
+ #endif
483
+
484
+ /*-------------------------------
485
+ * Mysql object method
486
+ */
487
+
488
+ #if MYSQL_VERSION_ID >= 32200
489
+ /* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */
490
+ static VALUE real_connect2(int argc, VALUE* argv, VALUE obj)
491
+ {
492
+ VALUE host, user, passwd, db, port, sock, flag;
493
+ char *h, *u, *p, *d, *s;
494
+ unsigned int pp, f;
495
+ MYSQL* m = GetHandler(obj);
496
+ rb_scan_args(argc, argv, "07", &host, &user, &passwd, &db, &port, &sock, &flag);
497
+ d = NILorSTRING(db);
498
+ f = NILorINT(flag);
499
+ h = NILorSTRING(host);
500
+ u = NILorSTRING(user);
501
+ p = NILorSTRING(passwd);
502
+ pp = NILorINT(port);
503
+ s = NILorSTRING(sock);
504
+
505
+ if (mysql_real_connect(m, h, u, p, d, pp, s, f) == NULL)
506
+ mysql_raise(m);
507
+ m->reconnect = 0;
508
+ GetMysqlStruct(obj)->connection = Qtrue;
509
+
510
+ optimize_for_async(obj);
511
+ //schedule_connect(obj);
512
+
513
+ return obj;
514
+ }
515
+
516
+ /* options(opt, value=nil) */
517
+ static VALUE options(int argc, VALUE* argv, VALUE obj)
518
+ {
519
+ VALUE opt, val;
520
+ int n;
521
+ my_bool b;
522
+ char* v;
523
+ MYSQL* m = GetHandler(obj);
524
+
525
+ rb_scan_args(argc, argv, "11", &opt, &val);
526
+ switch(NUM2INT(opt)) {
527
+ case MYSQL_OPT_CONNECT_TIMEOUT:
528
+ #if MYSQL_VERSION_ID >= 40100
529
+ case MYSQL_OPT_PROTOCOL:
530
+ #endif
531
+ #if MYSQL_VERSION_ID >= 40101
532
+ case MYSQL_OPT_READ_TIMEOUT:
533
+ case MYSQL_OPT_WRITE_TIMEOUT:
534
+ #endif
535
+ if (val == Qnil)
536
+ rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)");
537
+ n = NUM2INT(val);
538
+ v = (char*)&n;
539
+ break;
540
+ case MYSQL_INIT_COMMAND:
541
+ case MYSQL_READ_DEFAULT_FILE:
542
+ case MYSQL_READ_DEFAULT_GROUP:
543
+ #if MYSQL_VERSION_ID >= 32349
544
+ case MYSQL_SET_CHARSET_DIR:
545
+ case MYSQL_SET_CHARSET_NAME:
546
+ #endif
547
+ #if MYSQL_VERSION_ID >= 40100
548
+ case MYSQL_SHARED_MEMORY_BASE_NAME:
549
+ #endif
550
+ #if MYSQL_VERSION_ID >= 40101
551
+ case MYSQL_SET_CLIENT_IP:
552
+ #endif
553
+ if (val == Qnil)
554
+ rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)");
555
+ v = StringValuePtr(val);
556
+ break;
557
+ #if MYSQL_VERSION_ID >= 40101
558
+ case MYSQL_SECURE_AUTH:
559
+ if (val == Qnil || val == Qfalse)
560
+ b = 1;
561
+ else
562
+ b = 0;
563
+ v = (char*)&b;
564
+ break;
565
+ #endif
566
+ #if MYSQL_VERSION_ID >= 32349
567
+ case MYSQL_OPT_LOCAL_INFILE:
568
+ if (val == Qnil || val == Qfalse)
569
+ v = NULL;
570
+ else {
571
+ n = 1;
572
+ v = (char*)&n;
573
+ }
574
+ break;
575
+ #endif
576
+ default:
577
+ v = NULL;
578
+ }
579
+
580
+ if (mysql_options(m, NUM2INT(opt), v) != 0)
581
+ rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
582
+ return obj;
583
+ }
584
+ #endif
585
+
586
+ #if MYSQL_VERSION_ID >= 32332
587
+ /* real_escape_string(string) */
588
+ static VALUE real_escape_string(VALUE obj, VALUE str)
589
+ {
590
+ MYSQL* m = GetHandler(obj);
591
+ VALUE ret;
592
+ Check_Type(str, T_STRING);
593
+ ret = rb_enc_str_new(0, (RSTRING_LEN(str))*2+1, DEFAULT_ENCODING);
594
+ rb_str_set_len(ret, mysql_real_escape_string(m, RSTRING_PTR(ret), RSTRING_PTR(str), RSTRING_LEN(str)));
595
+ return ret;
596
+ }
597
+ #endif
598
+
599
+ /* initialize() */
600
+ static VALUE initialize(int argc, VALUE* argv, VALUE obj)
601
+ {
602
+ return obj;
603
+ }
604
+
605
+ /* affected_rows() */
606
+ static VALUE affected_rows(VALUE obj)
607
+ {
608
+ return INT2NUM(mysql_affected_rows(GetHandler(obj)));
609
+ }
610
+
611
+ #if MYSQL_VERSION_ID >= 32303
612
+ /* change_user(user=nil, passwd=nil, db=nil) */
613
+ static VALUE change_user(int argc, VALUE* argv, VALUE obj)
614
+ {
615
+ VALUE user, passwd, db;
616
+ char *u, *p, *d;
617
+ MYSQL* m = GetHandler(obj);
618
+ rb_scan_args(argc, argv, "03", &user, &passwd, &db);
619
+ u = NILorSTRING(user);
620
+ p = NILorSTRING(passwd);
621
+ d = NILorSTRING(db);
622
+ if (mysql_change_user(m, u, p, d) != 0)
623
+ mysql_raise(m);
624
+ return obj;
625
+ }
626
+ #endif
627
+
628
+ #if MYSQL_VERSION_ID >= 32321
629
+ /* character_set_name() */
630
+ static VALUE character_set_name(VALUE obj)
631
+ {
632
+ return rb_enc_tainted_str_new2(mysql_character_set_name(GetHandler(obj)));
633
+ }
634
+ #endif
635
+
636
+ /* close() */
637
+ static VALUE my_close(VALUE obj)
638
+ {
639
+ MYSQL* m = GetHandler(obj);
640
+ mysql_close(m);
641
+ GetMysqlStruct(obj)->connection = Qfalse;
642
+ return obj;
643
+ }
644
+
645
+ #if MYSQL_VERSION_ID < 40000
646
+ /* create_db(db) */
647
+ static VALUE create_db(VALUE obj, VALUE db)
648
+ {
649
+ MYSQL* m = GetHandler(obj);
650
+ if (mysql_create_db(m, StringValuePtr(db)) != 0)
651
+ mysql_raise(m);
652
+ return obj;
653
+ }
654
+
655
+ /* drop_db(db) */
656
+ static VALUE drop_db(VALUE obj, VALUE db)
657
+ {
658
+ MYSQL* m = GetHandler(obj);
659
+ if (mysql_drop_db(m, StringValuePtr(db)) != 0)
660
+ mysql_raise(m);
661
+ return obj;
662
+ }
663
+ #endif
664
+
665
+ #if MYSQL_VERSION_ID >= 32332
666
+ /* dump_debug_info() */
667
+ static VALUE dump_debug_info(VALUE obj)
668
+ {
669
+ MYSQL* m = GetHandler(obj);
670
+ if (mysql_dump_debug_info(m) != 0)
671
+ mysql_raise(m);
672
+ return obj;
673
+ }
674
+ #endif
675
+
676
+ /* errno() */
677
+ static VALUE my_errno(VALUE obj)
678
+ {
679
+ return INT2NUM(mysql_errno(GetHandler(obj)));
680
+ }
681
+
682
+ /* error() */
683
+ static VALUE my_error(VALUE obj)
684
+ {
685
+ return rb_str_new2(mysql_error(GetHandler(obj)));
686
+ }
687
+
688
+ /* field_count() */
689
+ static VALUE field_count(VALUE obj)
690
+ {
691
+ return INT2NUM(mysql_field_count(GetHandler(obj)));
692
+ }
693
+
694
+ /* host_info() */
695
+ static VALUE host_info(VALUE obj)
696
+ {
697
+ return rb_enc_tainted_str_new2(mysql_get_host_info(GetHandler(obj)));
698
+ }
699
+
700
+ /* proto_info() */
701
+ static VALUE proto_info(VALUE obj)
702
+ {
703
+ return INT2NUM(mysql_get_proto_info(GetHandler(obj)));
704
+ }
705
+
706
+ /* server_info() */
707
+ static VALUE server_info(VALUE obj)
708
+ {
709
+ return rb_enc_tainted_str_new2(mysql_get_server_info(GetHandler(obj)));
710
+ }
711
+
712
+ /* info() */
713
+ static VALUE info(VALUE obj)
714
+ {
715
+ const char* p = mysql_info(GetHandler(obj));
716
+ return p? rb_enc_tainted_str_new2(p): Qnil;
717
+ }
718
+
719
+ /* insert_id() */
720
+ static VALUE insert_id(VALUE obj)
721
+ {
722
+ return INT2NUM(mysql_insert_id(GetHandler(obj)));
723
+ }
724
+
725
+ /* kill(pid) */
726
+ static VALUE my_kill(VALUE obj, VALUE pid)
727
+ {
728
+ int p = NUM2INT(pid);
729
+ MYSQL* m = GetHandler(obj);
730
+ if (mysql_kill(m, p) != 0)
731
+ mysql_raise(m);
732
+ return obj;
733
+ }
734
+
735
+ /* list_dbs(db=nil) */
736
+ static VALUE list_dbs(int argc, VALUE* argv, VALUE obj)
737
+ {
738
+ unsigned int i, n;
739
+ VALUE db, ret;
740
+ MYSQL* m = GetHandler(obj);
741
+ MYSQL_RES* res;
742
+
743
+ rb_scan_args(argc, argv, "01", &db);
744
+ res = mysql_list_dbs(m, NILorSTRING(db));
745
+ if (res == NULL)
746
+ mysql_raise(m);
747
+
748
+ n = mysql_num_rows(res);
749
+ ret = rb_ary_new2(n);
750
+ for (i=0; i<n; i++)
751
+ rb_ary_store(ret, i, rb_enc_tainted_str_new2(mysql_fetch_row(res)[0]));
752
+ mysql_free_result(res);
753
+ return ret;
754
+ }
755
+
756
+ /* list_fields(table, field=nil) */
757
+ static VALUE list_fields(int argc, VALUE* argv, VALUE obj)
758
+ {
759
+ VALUE table, field;
760
+ MYSQL* m = GetHandler(obj);
761
+ MYSQL_RES* res;
762
+ rb_scan_args(argc, argv, "11", &table, &field);
763
+ res = mysql_list_fields(m, StringValuePtr(table), NILorSTRING(field));
764
+ if (res == NULL)
765
+ mysql_raise(m);
766
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
767
+ }
768
+
769
+ /* list_processes() */
770
+ static VALUE list_processes(VALUE obj)
771
+ {
772
+ MYSQL* m = GetHandler(obj);
773
+ MYSQL_RES* res = mysql_list_processes(m);
774
+ if (res == NULL)
775
+ mysql_raise(m);
776
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
777
+ }
778
+
779
+ /* list_tables(table=nil) */
780
+ static VALUE list_tables(int argc, VALUE* argv, VALUE obj)
781
+ {
782
+ VALUE table;
783
+ MYSQL* m = GetHandler(obj);
784
+ MYSQL_RES* res;
785
+ unsigned int i, n;
786
+ VALUE ret;
787
+
788
+ rb_scan_args(argc, argv, "01", &table);
789
+ res = mysql_list_tables(m, NILorSTRING(table));
790
+ if (res == NULL)
791
+ mysql_raise(m);
792
+
793
+ n = mysql_num_rows(res);
794
+ ret = rb_ary_new2(n);
795
+ for (i=0; i<n; i++)
796
+ rb_ary_store(ret, i, rb_enc_tainted_str_new2(mysql_fetch_row(res)[0]));
797
+ mysql_free_result(res);
798
+ return ret;
799
+ }
800
+
801
+ /* ping() */
802
+ static VALUE ping(VALUE obj)
803
+ {
804
+ MYSQL* m = GetHandler(obj);
805
+ if (mysql_ping(m) != 0)
806
+ mysql_raise(m);
807
+ return obj;
808
+ }
809
+
810
+ /* refresh(r) */
811
+ static VALUE refresh(VALUE obj, VALUE r)
812
+ {
813
+ MYSQL* m = GetHandler(obj);
814
+ if (mysql_refresh(m, NUM2INT(r)) != 0)
815
+ mysql_raise(m);
816
+ return obj;
817
+ }
818
+
819
+ /* reload() */
820
+ static VALUE reload(VALUE obj)
821
+ {
822
+ MYSQL* m = GetHandler(obj);
823
+ if (mysql_reload(m) != 0)
824
+ mysql_raise(m);
825
+ return obj;
826
+ }
827
+
828
+ /* select_db(db) */
829
+ static VALUE select_db(VALUE obj, VALUE db)
830
+ {
831
+ MYSQL* m = GetHandler(obj);
832
+ if (mysql_select_db(m, StringValuePtr(db)) != 0)
833
+ mysql_raise(m);
834
+ return obj;
835
+ }
836
+
837
+ /* shutdown() */
838
+ static VALUE my_shutdown(int argc, VALUE* argv, VALUE obj)
839
+ {
840
+ MYSQL* m = GetHandler(obj);
841
+ VALUE level;
842
+
843
+ rb_scan_args(argc, argv, "01", &level);
844
+ #if MYSQL_VERSION_ID >= 40103
845
+ if (mysql_shutdown(m, NIL_P(level) ? SHUTDOWN_DEFAULT : NUM2INT(level)) != 0)
846
+ #else
847
+ if (mysql_shutdown(m) != 0)
848
+ #endif
849
+ mysql_raise(m);
850
+ return obj;
851
+ }
852
+
853
+ /* stat() */
854
+ static VALUE my_stat(VALUE obj)
855
+ {
856
+ MYSQL* m = GetHandler(obj);
857
+ const char* s = mysql_stat(m);
858
+ if (s == NULL)
859
+ mysql_raise(m);
860
+ return rb_enc_tainted_str_new2(s);
861
+ }
862
+
863
+ // 1.9 friendly
864
+ typedef struct
865
+ {
866
+ MYSQL *mysql_instance;
867
+ MYSQL_RES **store_it_here;
868
+
869
+ } mysql_result_to_here_t,
870
+ *shared_stuff_p;
871
+
872
+ static VALUE store_result_to_location(void *settings_in)
873
+ {
874
+ mysql_result_to_here_t *settings = (mysql_result_to_here_t *) settings_in;
875
+ *(settings->store_it_here) = mysql_store_result(settings->mysql_instance); // this one line runs a good long while for very large queries
876
+ return Qnil;
877
+ }
878
+
879
+ /* store_result() */
880
+ static VALUE store_result(VALUE obj)
881
+ {
882
+ MYSQL* m = GetHandler(obj);
883
+ MYSQL_RES* res = NULL;
884
+ #ifndef HAVE_TBR
885
+ res = mysql_store_result(m);
886
+ #else
887
+ mysql_result_to_here_t linker;
888
+ linker.mysql_instance = m;
889
+ linker.store_it_here = &res;
890
+ rb_thread_blocking_region(store_result_to_location, (void *) &linker, RUBY_UBF_IO, 0);
891
+ #endif
892
+
893
+ if (res == NULL)
894
+ mysql_raise(m);
895
+
896
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
897
+ }
898
+
899
+ /* thread_id() */
900
+ static VALUE thread_id(VALUE obj)
901
+ {
902
+ return INT2NUM(mysql_thread_id(GetHandler(obj)));
903
+ }
904
+
905
+ /* use_result() */
906
+ static VALUE use_result(VALUE obj)
907
+ {
908
+ MYSQL* m = GetHandler(obj);
909
+ MYSQL_RES* res = mysql_use_result(m);
910
+ if (res == NULL)
911
+ mysql_raise(m);
912
+ return mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
913
+ }
914
+
915
+ static VALUE res_free(VALUE);
916
+
917
+ typedef struct {
918
+ MYSQL *m;
919
+ const char *data;
920
+ unsigned long len;
921
+ } QueryArgs;
922
+
923
+ static VALUE blocking_query(void *data)
924
+ {
925
+ QueryArgs *args = (QueryArgs *) data;
926
+ return (VALUE) mysql_real_query(args->m, args->data, args->len);
927
+ }
928
+
929
+ /* query(sql) */
930
+ static VALUE query(VALUE obj, VALUE sql)
931
+ {
932
+ int loop = 0;
933
+ MYSQL* m = GetHandler(obj);
934
+ QueryArgs args;
935
+ int result;
936
+
937
+ Check_Type(sql, T_STRING);
938
+ if (GetMysqlStruct(obj)->connection == Qfalse) {
939
+ rb_raise(eMysql, "query: not connected");
940
+ }
941
+ if (rb_block_given_p()) {
942
+ #ifdef RUBY_VM
943
+ args.m = m;
944
+ args.data = RSTRING_PTR(sql);
945
+ args.len = RSTRING_LEN(sql);
946
+ result = (int) rb_thread_blocking_region(blocking_query, &args, RUBY_UBF_PROCESS, 0);
947
+ #else
948
+ result = mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql));
949
+ #endif
950
+ if (result != 0)
951
+ mysql_raise(m);
952
+
953
+ do {
954
+ MYSQL_RES* res = mysql_store_result(m);
955
+ if (res == NULL) {
956
+ if (mysql_field_count(m) != 0)
957
+ mysql_raise(m);
958
+ } else {
959
+ VALUE robj = mysqlres2obj(res, GetMysqlStruct(obj)->gc_disabled);
960
+ rb_ensure(rb_yield, robj, res_free, robj);
961
+ }
962
+ #if MYSQL_VERSION_ID >= 40101
963
+ if ((loop = mysql_next_result(m)) > 0)
964
+ mysql_raise(m);
965
+ } while (loop == 0);
966
+ #else
967
+ } while (0);
968
+ #endif
969
+ return obj;
970
+ }
971
+
972
+ #ifdef RUBY_VM
973
+ args.m = m;
974
+ args.data = RSTRING_PTR(sql);
975
+ args.len = RSTRING_LEN(sql);
976
+ result = (int) rb_thread_blocking_region(blocking_query, &args, RUBY_UBF_PROCESS, 0);
977
+ #else
978
+ result = mysql_real_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql));
979
+ #endif
980
+ if (result != 0)
981
+ mysql_raise(m);
982
+ if (GetMysqlStruct(obj)->query_with_result == Qfalse)
983
+ return obj;
984
+ if (mysql_field_count(m) == 0)
985
+ return Qnil;
986
+ return store_result(obj);
987
+ }
988
+
989
+ /* socket */
990
+ static VALUE socket(VALUE obj)
991
+ {
992
+ MYSQL* m = GetHandler(obj);
993
+ return INT2NUM(m->net.fd);
994
+ }
995
+
996
+ /* socket_type --currently returns true or false, needs some work */
997
+ static VALUE socket_type(VALUE obj)
998
+ {
999
+ MYSQL* m = GetHandler(obj);
1000
+ if(vio_description(m->net.vio))
1001
+ return Qtrue; // TODO return a ruby string
1002
+ else
1003
+ return Qnil;
1004
+ }
1005
+
1006
+ /* blocking */
1007
+ static VALUE blocking(VALUE obj){
1008
+ return ( GetMysqlStruct(obj)->blocking ? Qtrue : Qfalse );
1009
+ }
1010
+
1011
+ /* is_busy */
1012
+ static VALUE is_busy(VALUE obj){
1013
+ return ( GetMysqlStruct(obj)->busy ? Qtrue : Qfalse );
1014
+ }
1015
+
1016
+ static VALUE is_idle(VALUE obj){
1017
+ return ( is_busy(obj) == Qtrue ) ? Qfalse : Qtrue;
1018
+ }
1019
+
1020
+ /* busy(true|false) */
1021
+ static VALUE busy_set(VALUE obj, VALUE flag)
1022
+ {
1023
+ if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE)
1024
+ rb_raise(rb_eTypeError, "invalid type, required true or false.");
1025
+ GetMysqlStruct(obj)->busy = flag;
1026
+ return flag;
1027
+ }
1028
+
1029
+ static void busy( VALUE obj ){
1030
+ busy_set( obj, Qtrue );
1031
+ }
1032
+
1033
+ static void idle( VALUE obj ){
1034
+ busy_set( obj, Qfalse );
1035
+ }
1036
+
1037
+ /* readable(timeout=nil) */
1038
+ static VALUE readable( int argc, VALUE* argv, VALUE obj )
1039
+ {
1040
+ MYSQL* m = GetHandler(obj);
1041
+
1042
+ VALUE timeout;
1043
+
1044
+ rb_scan_args(argc, argv, "01", &timeout);
1045
+
1046
+ if ( NIL_P( timeout ) ){
1047
+ timeout = m->net.read_timeout;
1048
+ }
1049
+ // todo could do a rb_blocking_region here
1050
+ return ( vio_poll_read( m->net.vio, INT2NUM(timeout) ) == 0 ? Qtrue : Qfalse );
1051
+ }
1052
+
1053
+ /* retry */
1054
+ static VALUE retry( VALUE obj )
1055
+ {
1056
+ MYSQL* m = GetHandler(obj);
1057
+ return ( vio_should_retry( m->net.vio ) == 1 ? Qtrue : Qfalse );
1058
+ }
1059
+
1060
+ /* interrupted */
1061
+ static VALUE interrupted( VALUE obj )
1062
+ {
1063
+ MYSQL* m = GetHandler(obj);
1064
+ return ( vio_was_interrupted( m->net.vio ) == 1 ? Qtrue : Qfalse );
1065
+ }
1066
+
1067
+ /* reconnected */
1068
+ static VALUE reconnected( VALUE obj ){
1069
+ MYSQL* m = GetHandler(obj);
1070
+ int current_connection_id = mysql_thread_id( m );
1071
+ mysql_ping(m);
1072
+ return ( current_connection_id == mysql_thread_id( m ) ) ? Qfalse : Qtrue;
1073
+ }
1074
+
1075
+ /* disable_gc(true|false) */
1076
+ static VALUE disable_gc_set(VALUE obj, VALUE flag)
1077
+ {
1078
+ if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE)
1079
+ rb_raise(rb_eTypeError, "invalid type, required true or false.");
1080
+ GetMysqlStruct(obj)->gc_disabled = flag;
1081
+ return flag;
1082
+ }
1083
+
1084
+ /* gc_disabled */
1085
+ static VALUE gc_disabled( VALUE obj ){
1086
+ return GetMysqlStruct(obj)->gc_disabled ? Qtrue: Qfalse;
1087
+ }
1088
+
1089
+ static void validate_async_query( VALUE obj )
1090
+ {
1091
+ if( async_in_progress(obj) == Qtrue ){
1092
+ async_in_progress_set(obj, Qfalse);
1093
+ rb_raise(eMysql, "Query out of sequence: Each call to Mysql#send_query requires a successive Mysql#get_result.");
1094
+ }
1095
+ }
1096
+
1097
+ /* for testing */
1098
+ static VALUE simulate_disconnect( VALUE obj )
1099
+ {
1100
+ MYSQL* m = GetHandler(obj);
1101
+ mysql_library_end();
1102
+ return Qnil;
1103
+ }
1104
+
1105
+
1106
+ /* send_query(sql) */
1107
+ static VALUE send_query(VALUE obj, VALUE sql)
1108
+ {
1109
+ MYSQL* m = GetHandler(obj);
1110
+
1111
+ Check_Type(sql, T_STRING);
1112
+
1113
+ if (GetMysqlStruct(obj)->connection == Qfalse && async_in_progress(obj) == Qtrue ) {
1114
+ idle( obj );
1115
+ rb_raise(eMysql, "query: not connected");
1116
+ }
1117
+
1118
+ validate_async_query(obj);
1119
+
1120
+ if (mysql_send_query(m, RSTRING_PTR(sql), RSTRING_LEN(sql)) != 0){
1121
+ idle( obj );
1122
+ mysql_raise(m);
1123
+ }
1124
+ async_in_progress_set( obj, Qtrue );
1125
+
1126
+ return Qnil;
1127
+ }
1128
+
1129
+ /*
1130
+ get_result
1131
+ returns the mysql_result set (default) [i.e. all rows in said said]
1132
+ or nil if query_with_result == false
1133
+ */
1134
+ static VALUE get_result(VALUE obj)
1135
+ {
1136
+ MYSQL* m = GetHandler(obj);
1137
+
1138
+ async_in_progress_set( obj, Qfalse );
1139
+
1140
+ if (GetMysqlStruct(obj)->connection == Qfalse) {
1141
+ idle( obj );
1142
+ rb_raise(eMysql, "query: not connected");
1143
+ }
1144
+ if (mysql_read_query_result(m) != 0){
1145
+ idle( obj );
1146
+ mysql_raise(m);
1147
+ }
1148
+
1149
+ if (GetMysqlStruct(obj)->query_with_result == Qfalse)
1150
+ return obj;
1151
+
1152
+ if (mysql_field_count(m) == 0)
1153
+ return Qnil;
1154
+
1155
+ return store_result(obj);
1156
+ }
1157
+
1158
+ static void schedule_query(VALUE obj, VALUE timeout)
1159
+ {
1160
+ MYSQL* m = GetHandler(obj);
1161
+ fd_set read;
1162
+ int ret;
1163
+
1164
+ timeout = ( NIL_P(timeout) ? m->net.read_timeout : INT2NUM(timeout) );
1165
+
1166
+ struct timeval tv = { tv_sec: timeout, tv_usec: 0 };
1167
+
1168
+ for(;;){
1169
+ FD_ZERO(&read);
1170
+ FD_SET(m->net.fd, &read);
1171
+
1172
+ ret = rb_thread_select(m->net.fd + 1, &read, NULL, NULL, &tv);
1173
+ if (ret < 0) {
1174
+ idle( obj );
1175
+ rb_raise(eMysql, "query: timeout");
1176
+ }
1177
+
1178
+ if (ret == 0) {
1179
+ continue;
1180
+ }
1181
+
1182
+ if (m->status == MYSQL_STATUS_READY){
1183
+ break;
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+ static int should_schedule_query(){
1189
+ return rb_thread_alone() != 1;
1190
+ }
1191
+
1192
+ /* async_query(sql,timeout=nil)
1193
+ optionally take a block
1194
+ */
1195
+ static VALUE async_query(int argc, VALUE* argv, VALUE obj)
1196
+ {
1197
+ MYSQL* m = GetHandler(obj);
1198
+ VALUE sql, timeout;
1199
+
1200
+ rb_scan_args(argc, argv, "11", &sql, &timeout);
1201
+
1202
+ async_in_progress_set( obj, Qfalse );
1203
+
1204
+ busy(obj);
1205
+
1206
+ send_query( obj, sql );
1207
+
1208
+ if ( should_schedule_query() ){
1209
+ schedule_query(obj, timeout);
1210
+ }
1211
+
1212
+ if (rb_block_given_p()) {
1213
+ rb_yield( get_result(obj) );
1214
+ idle( obj );
1215
+ return obj;
1216
+ }else{
1217
+ idle( obj );
1218
+ return get_result(obj);
1219
+ }
1220
+ }
1221
+
1222
+ #if MYSQL_VERSION_ID >= 40100
1223
+ /* server_version() */
1224
+ static VALUE server_version(VALUE obj)
1225
+ {
1226
+ return INT2NUM(mysql_get_server_version(GetHandler(obj)));
1227
+ }
1228
+
1229
+ /* warning_count() */
1230
+ static VALUE warning_count(VALUE obj)
1231
+ {
1232
+ return INT2NUM(mysql_warning_count(GetHandler(obj)));
1233
+ }
1234
+
1235
+ /* commit() */
1236
+ static VALUE commit(VALUE obj)
1237
+ {
1238
+ MYSQL* m = GetHandler(obj);
1239
+ if (mysql_commit(m) != 0)
1240
+ mysql_raise(m);
1241
+ return obj;
1242
+ }
1243
+
1244
+ /* rollback() */
1245
+ static VALUE rollback(VALUE obj)
1246
+ {
1247
+ MYSQL* m = GetHandler(obj);
1248
+ if (mysql_rollback(m) != 0)
1249
+ mysql_raise(m);
1250
+ return obj;
1251
+ }
1252
+
1253
+ /* autocommit() */
1254
+ static VALUE autocommit(VALUE obj, VALUE mode)
1255
+ {
1256
+ MYSQL* m = GetHandler(obj);
1257
+ int f;
1258
+ f = (mode == Qnil || mode == Qfalse || (rb_type(mode) == T_FIXNUM && NUM2INT(mode) == 0)) ? 0 : 1;
1259
+ if (mysql_autocommit(m, f) != 0)
1260
+ mysql_raise(m);
1261
+ return obj;
1262
+ }
1263
+ #endif
1264
+
1265
+ #ifdef HAVE_MYSQL_SSL_SET
1266
+ /* ssl_set(key=nil, cert=nil, ca=nil, capath=nil, cipher=nil) */
1267
+ static VALUE ssl_set(int argc, VALUE* argv, VALUE obj)
1268
+ {
1269
+ VALUE key, cert, ca, capath, cipher;
1270
+ char *s_key, *s_cert, *s_ca, *s_capath, *s_cipher;
1271
+ MYSQL* m = GetHandler(obj);
1272
+ rb_scan_args(argc, argv, "05", &key, &cert, &ca, &capath, &cipher);
1273
+ s_key = NILorSTRING(key);
1274
+ s_cert = NILorSTRING(cert);
1275
+ s_ca = NILorSTRING(ca);
1276
+ s_capath = NILorSTRING(capath);
1277
+ s_cipher = NILorSTRING(cipher);
1278
+ mysql_ssl_set(m, s_key, s_cert, s_ca, s_capath, s_cipher);
1279
+ return obj;
1280
+ }
1281
+ #endif
1282
+
1283
+ #if MYSQL_VERSION_ID >= 40100
1284
+ /* more_results() */
1285
+ static VALUE more_results(VALUE obj)
1286
+ {
1287
+ if (mysql_more_results(GetHandler(obj)) == 0)
1288
+ return Qfalse;
1289
+ else
1290
+ return Qtrue;
1291
+ }
1292
+
1293
+ static VALUE next_result(VALUE obj)
1294
+ {
1295
+ MYSQL* m = GetHandler(obj);
1296
+ int ret;
1297
+ ret = mysql_next_result(m);
1298
+ if (ret > 0)
1299
+ mysql_raise(m);
1300
+ if (ret == 0)
1301
+ return Qtrue;
1302
+ return Qfalse;
1303
+ }
1304
+ #endif
1305
+
1306
+ #if MYSQL_VERSION_ID >= 40101
1307
+ /* set_server_option(option) */
1308
+ static VALUE set_server_option(VALUE obj, VALUE option)
1309
+ {
1310
+ MYSQL *m = GetHandler(obj);
1311
+ if (mysql_set_server_option(m, NUM2INT(option)) != 0)
1312
+ mysql_raise(m);
1313
+ return obj;
1314
+ }
1315
+
1316
+ /* sqlstate() */
1317
+ static VALUE sqlstate(VALUE obj)
1318
+ {
1319
+ MYSQL *m = GetHandler(obj);
1320
+ return rb_enc_tainted_str_new2(mysql_sqlstate(m));
1321
+ }
1322
+ #endif
1323
+
1324
+ #if MYSQL_VERSION_ID >= 40102
1325
+ /* stmt_init() */
1326
+ static VALUE stmt_init(VALUE obj)
1327
+ {
1328
+ MYSQL *m = GetHandler(obj);
1329
+ MYSQL_STMT *s;
1330
+ struct mysql_stmt* stmt;
1331
+ my_bool true = 1;
1332
+ VALUE st_obj;
1333
+
1334
+ if ((s = mysql_stmt_init(m)) == NULL)
1335
+ mysql_raise(m);
1336
+ if (mysql_stmt_attr_set(s, STMT_ATTR_UPDATE_MAX_LENGTH, &true))
1337
+ rb_raise(rb_eArgError, "mysql_stmt_attr_set() failed");
1338
+ st_obj = Data_Make_Struct(cMysqlStmt, struct mysql_stmt, 0, free_mysqlstmt, stmt);
1339
+ memset(stmt, 0, sizeof(*stmt));
1340
+ stmt->stmt = s;
1341
+ stmt->closed = Qfalse;
1342
+ return st_obj;
1343
+ }
1344
+
1345
+ static VALUE stmt_prepare(VALUE obj, VALUE query);
1346
+ /* prepare(query) */
1347
+ static VALUE prepare(VALUE obj, VALUE query)
1348
+ {
1349
+ VALUE st;
1350
+ st = stmt_init(obj);
1351
+ return stmt_prepare(st, query);
1352
+ }
1353
+ #endif
1354
+
1355
+ /* query_with_result() */
1356
+ static VALUE query_with_result(VALUE obj)
1357
+ {
1358
+ return GetMysqlStruct(obj)->query_with_result? Qtrue: Qfalse;
1359
+ }
1360
+
1361
+ /* query_with_result=(flag) */
1362
+ static VALUE query_with_result_set(VALUE obj, VALUE flag)
1363
+ {
1364
+ if (TYPE(flag) != T_TRUE && TYPE(flag) != T_FALSE)
1365
+ rb_raise(rb_eTypeError, "invalid type, required true or false.");
1366
+ GetMysqlStruct(obj)->query_with_result = flag;
1367
+ return flag;
1368
+ }
1369
+
1370
+ /* reconnect() */
1371
+ static VALUE reconnect(VALUE obj)
1372
+ {
1373
+ return GetHandler(obj)->reconnect ? Qtrue : Qfalse;
1374
+ }
1375
+
1376
+ /* reconnect=(flag) */
1377
+ static VALUE reconnect_set(VALUE obj, VALUE flag)
1378
+ {
1379
+ GetHandler(obj)->reconnect = (flag == Qnil || flag == Qfalse) ? 0 : 1;
1380
+ return flag;
1381
+ }
1382
+
1383
+ /*-------------------------------
1384
+ * Mysql::Result object method
1385
+ */
1386
+
1387
+ /* check if already freed */
1388
+ static void check_free(VALUE obj)
1389
+ {
1390
+ struct mysql_res* resp = DATA_PTR(obj);
1391
+ if (resp->freed == Qtrue)
1392
+ rb_raise(eMysql, "Mysql::Result object is already freed");
1393
+ }
1394
+
1395
+ /* data_seek(offset) */
1396
+ static VALUE data_seek(VALUE obj, VALUE offset)
1397
+ {
1398
+ check_free(obj);
1399
+ mysql_data_seek(GetMysqlRes(obj), NUM2INT(offset));
1400
+ return obj;
1401
+ }
1402
+
1403
+ /* fetch_field() */
1404
+ static VALUE fetch_field(VALUE obj)
1405
+ {
1406
+ check_free(obj);
1407
+ return make_field_obj(mysql_fetch_field(GetMysqlRes(obj)));
1408
+ }
1409
+
1410
+ /* fetch_fields() */
1411
+ static VALUE fetch_fields(VALUE obj)
1412
+ {
1413
+ MYSQL_RES* res;
1414
+ MYSQL_FIELD* f;
1415
+ unsigned int n;
1416
+ VALUE ret;
1417
+ unsigned int i;
1418
+ check_free(obj);
1419
+ res = GetMysqlRes(obj);
1420
+ f = mysql_fetch_fields(res);
1421
+ n = mysql_num_fields(res);
1422
+ ret = rb_ary_new2(n);
1423
+ for (i=0; i<n; i++)
1424
+ rb_ary_store(ret, i, make_field_obj(&f[i]));
1425
+ return ret;
1426
+ }
1427
+
1428
+ /* fetch_field_direct(nr) */
1429
+ static VALUE fetch_field_direct(VALUE obj, VALUE nr)
1430
+ {
1431
+ MYSQL_RES* res;
1432
+ unsigned int max;
1433
+ unsigned int n;
1434
+ check_free(obj);
1435
+ res = GetMysqlRes(obj);
1436
+ max = mysql_num_fields(res);
1437
+ n = NUM2INT(nr);
1438
+ if (n >= max)
1439
+ rb_raise(eMysql, "%d: out of range (max: %d)", n, max-1);
1440
+ #if MYSQL_VERSION_ID >= 32226
1441
+ return make_field_obj(mysql_fetch_field_direct(res, n));
1442
+ #else
1443
+ return make_field_obj(&mysql_fetch_field_direct(res, n));
1444
+ #endif
1445
+ }
1446
+
1447
+ /* fetch_lengths() */
1448
+ static VALUE fetch_lengths(VALUE obj)
1449
+ {
1450
+ MYSQL_RES* res;
1451
+ unsigned int n;
1452
+ unsigned long* lengths;
1453
+ VALUE ary;
1454
+ unsigned int i;
1455
+ check_free(obj);
1456
+ res = GetMysqlRes(obj);
1457
+ n = mysql_num_fields(res);
1458
+ lengths = mysql_fetch_lengths(res);
1459
+ if (lengths == NULL)
1460
+ return Qnil;
1461
+ ary = rb_ary_new2(n);
1462
+ for (i=0; i<n; i++)
1463
+ rb_ary_store(ary, i, INT2NUM(lengths[i]));
1464
+ return ary;
1465
+ }
1466
+
1467
+ /* fetch_row() */
1468
+ static VALUE fetch_row(VALUE obj)
1469
+ {
1470
+ MYSQL_RES* res;
1471
+ unsigned int n;
1472
+ MYSQL_ROW row;
1473
+ unsigned long* lengths;
1474
+ VALUE ary;
1475
+ unsigned int i;
1476
+ check_free(obj);
1477
+ res = GetMysqlRes(obj);
1478
+ n = mysql_num_fields(res);
1479
+ row = mysql_fetch_row(res);
1480
+ lengths = mysql_fetch_lengths(res);
1481
+ if (row == NULL)
1482
+ return Qnil;
1483
+ ary = rb_ary_new2(n);
1484
+ for (i=0; i<n; i++)
1485
+ rb_ary_store(ary, i, row[i]? rb_enc_tainted_str_new(row[i], lengths[i]): Qnil);
1486
+ return ary;
1487
+ }
1488
+
1489
+ /* process_all_hashes (internal helper) */
1490
+ static VALUE process_all_hashes(VALUE obj, VALUE with_table, int build_array, int yield)
1491
+ {
1492
+ MYSQL_RES* res = GetMysqlRes(obj);
1493
+ unsigned int n = mysql_num_fields(res);
1494
+ VALUE ary = Qnil;
1495
+ if(build_array)
1496
+ ary = rb_ary_new();
1497
+ MYSQL_ROW row = mysql_fetch_row(res); // grab one off the top, to determine the rows
1498
+ if (row == NULL){
1499
+ if(build_array){
1500
+ return ary;
1501
+ }else{
1502
+ return Qnil;
1503
+ }
1504
+ }
1505
+ MYSQL_FIELD* fields = mysql_fetch_fields(res);
1506
+ unsigned int i;
1507
+ VALUE hash;
1508
+ VALUE colname;
1509
+
1510
+ if (with_table == Qfalse) {
1511
+ colname = rb_iv_get(obj, "colname");
1512
+ if (colname == Qnil) {
1513
+ colname = rb_ary_new2(n);
1514
+ for (i=0; i<n; i++) {
1515
+ VALUE s = rb_enc_tainted_str_new2(fields[i].name);
1516
+ rb_obj_freeze(s);
1517
+ rb_ary_store(colname, i, s);
1518
+ }
1519
+ rb_obj_freeze(colname);
1520
+ rb_iv_set(obj, "colname", colname);
1521
+ }
1522
+ } else {
1523
+ colname = rb_iv_get(obj, "tblcolname");
1524
+ if (colname == Qnil) {
1525
+ colname = rb_ary_new2(n);
1526
+ for (i=0; i<n; i++) {
1527
+ int len = strlen(fields[i].table)+strlen(fields[i].name)+1;
1528
+ VALUE s = rb_enc_tainted_str_new(NULL, len);
1529
+ snprintf(RSTRING_PTR(s), len+1, "%s.%s", fields[i].table, fields[i].name);
1530
+ rb_obj_freeze(s);
1531
+ rb_ary_store(colname, i, s);
1532
+ }
1533
+ rb_obj_freeze(colname);
1534
+ rb_iv_set(obj, "tblcolname", colname);
1535
+ }
1536
+ }
1537
+
1538
+ unsigned long* lengths = NULL;
1539
+ while(row != NULL)
1540
+ {
1541
+ hash = rb_hash_new();
1542
+ lengths = mysql_fetch_lengths(res);
1543
+ for (i=0; i<n; i++) {
1544
+ rb_hash_aset(hash, rb_ary_entry(colname, i), row[i]? rb_enc_tainted_str_new(row[i], lengths[i]): Qnil);
1545
+ }
1546
+ if(build_array)
1547
+ rb_ary_push(ary, hash);
1548
+
1549
+ if(yield)
1550
+ rb_yield(hash);
1551
+
1552
+ row = mysql_fetch_row(res);
1553
+ }
1554
+
1555
+ /* pass back apropriate return values */
1556
+ if(build_array)
1557
+ return ary;
1558
+
1559
+ if(yield)
1560
+ return obj;
1561
+
1562
+ return Qnil; /* we should never get here -- this takes out a compiler warning */
1563
+ }
1564
+
1565
+ /* fetch_hash2 (internal) */
1566
+ static VALUE fetch_hash2(VALUE obj, VALUE with_table)
1567
+ {
1568
+ MYSQL_RES* res = GetMysqlRes(obj);
1569
+ unsigned int n = mysql_num_fields(res);
1570
+ MYSQL_ROW row = mysql_fetch_row(res);
1571
+ unsigned long* lengths = mysql_fetch_lengths(res);
1572
+ MYSQL_FIELD* fields = mysql_fetch_fields(res);
1573
+ unsigned int i;
1574
+ VALUE hash;
1575
+ VALUE colname;
1576
+ if (row == NULL)
1577
+ return Qnil;
1578
+ hash = rb_hash_new();
1579
+
1580
+ if (with_table == Qnil || with_table == Qfalse) {
1581
+ colname = rb_iv_get(obj, "colname");
1582
+ if (colname == Qnil) {
1583
+ colname = rb_ary_new2(n);
1584
+ for (i=0; i<n; i++) {
1585
+ VALUE s = rb_enc_tainted_str_new2(fields[i].name);
1586
+ rb_obj_freeze(s);
1587
+ rb_ary_store(colname, i, s);
1588
+ }
1589
+ rb_obj_freeze(colname);
1590
+ rb_iv_set(obj, "colname", colname);
1591
+ }
1592
+ } else {
1593
+ colname = rb_iv_get(obj, "tblcolname");
1594
+ if (colname == Qnil) {
1595
+ colname = rb_ary_new2(n);
1596
+ for (i=0; i<n; i++) {
1597
+ int len = strlen(fields[i].table)+strlen(fields[i].name)+1;
1598
+ VALUE s = rb_enc_tainted_str_new(NULL, len);
1599
+ snprintf(RSTRING_PTR(s), len+1, "%s.%s", fields[i].table, fields[i].name);
1600
+ rb_obj_freeze(s);
1601
+ rb_ary_store(colname, i, s);
1602
+ }
1603
+ rb_obj_freeze(colname);
1604
+ rb_iv_set(obj, "tblcolname", colname);
1605
+ }
1606
+ }
1607
+ for (i=0; i<n; i++) {
1608
+ rb_hash_aset(hash, rb_ary_entry(colname, i), row[i]? rb_enc_tainted_str_new(row[i], lengths[i]): Qnil);
1609
+ }
1610
+ return hash;
1611
+ }
1612
+
1613
+ /* fetch_hash(with_table=false) */
1614
+ static VALUE fetch_hash(int argc, VALUE* argv, VALUE obj)
1615
+ {
1616
+ VALUE with_table;
1617
+ check_free(obj);
1618
+ rb_scan_args(argc, argv, "01", &with_table);
1619
+ if (with_table == Qnil)
1620
+ with_table = Qfalse;
1621
+ return fetch_hash2(obj, with_table);
1622
+ }
1623
+
1624
+ /* field_seek(offset) */
1625
+ static VALUE field_seek(VALUE obj, VALUE offset)
1626
+ {
1627
+ check_free(obj);
1628
+ return INT2NUM(mysql_field_seek(GetMysqlRes(obj), NUM2INT(offset)));
1629
+ }
1630
+
1631
+ /* field_tell() */
1632
+ static VALUE field_tell(VALUE obj)
1633
+ {
1634
+ check_free(obj);
1635
+ return INT2NUM(mysql_field_tell(GetMysqlRes(obj)));
1636
+ }
1637
+
1638
+ /* free() */
1639
+ static VALUE res_free(VALUE obj)
1640
+ {
1641
+ struct mysql_res* resp = DATA_PTR(obj);
1642
+ check_free(obj);
1643
+ mysql_free_result(resp->res);
1644
+ resp->freed = Qtrue;
1645
+ store_result_count--;
1646
+ return Qnil;
1647
+ }
1648
+
1649
+ /* num_fields() */
1650
+ static VALUE num_fields(VALUE obj)
1651
+ {
1652
+ check_free(obj);
1653
+ return INT2NUM(mysql_num_fields(GetMysqlRes(obj)));
1654
+ }
1655
+
1656
+ /* num_rows() */
1657
+ static VALUE num_rows(VALUE obj)
1658
+ {
1659
+ check_free(obj);
1660
+ return INT2NUM(mysql_num_rows(GetMysqlRes(obj)));
1661
+ }
1662
+
1663
+ /* row_seek(offset) */
1664
+ static VALUE row_seek(VALUE obj, VALUE offset)
1665
+ {
1666
+ MYSQL_ROW_OFFSET prev_offset;
1667
+ if (CLASS_OF(offset) != cMysqlRowOffset)
1668
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
1669
+ check_free(obj);
1670
+ prev_offset = mysql_row_seek(GetMysqlRes(obj), DATA_PTR(offset));
1671
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);
1672
+ }
1673
+
1674
+ /* row_tell() */
1675
+ static VALUE row_tell(VALUE obj)
1676
+ {
1677
+ MYSQL_ROW_OFFSET offset;
1678
+ check_free(obj);
1679
+ offset = mysql_row_tell(GetMysqlRes(obj));
1680
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);
1681
+ }
1682
+
1683
+ /* each {...} */
1684
+ static VALUE each(VALUE obj)
1685
+ {
1686
+ VALUE row;
1687
+ check_free(obj);
1688
+ while ((row = fetch_row(obj)) != Qnil)
1689
+ rb_yield(row);
1690
+ return obj;
1691
+ }
1692
+
1693
+ /* each_hash(with_table=false) {...} */
1694
+ static VALUE each_hash(int argc, VALUE* argv, VALUE obj)
1695
+ {
1696
+ VALUE with_table;
1697
+ check_free(obj);
1698
+ rb_scan_args(argc, argv, "01", &with_table);
1699
+ if (with_table == Qnil)
1700
+ with_table = Qfalse;
1701
+ process_all_hashes(obj, with_table, 0, 1);
1702
+ return obj;
1703
+ }
1704
+
1705
+ /* all_hashes(with_table=false) -- returns an array of hashes, one hash per row */
1706
+ static VALUE all_hashes(int argc, VALUE* argv, VALUE obj)
1707
+ {
1708
+ VALUE with_table;
1709
+ check_free(obj);
1710
+ rb_scan_args(argc, argv, "01", &with_table);
1711
+ if (with_table == Qnil)
1712
+ with_table = Qfalse;
1713
+ return process_all_hashes(obj, with_table, 1, 0);
1714
+ }
1715
+
1716
+
1717
+ /*-------------------------------
1718
+ * Mysql::Field object method
1719
+ */
1720
+
1721
+ /* hash */
1722
+ static VALUE field_hash(VALUE obj)
1723
+ {
1724
+ VALUE h = rb_hash_new();
1725
+ rb_hash_aset(h, rb_str_new2("name"), rb_iv_get(obj, "name"));
1726
+ rb_hash_aset(h, rb_str_new2("table"), rb_iv_get(obj, "table"));
1727
+ rb_hash_aset(h, rb_str_new2("def"), rb_iv_get(obj, "def"));
1728
+ rb_hash_aset(h, rb_str_new2("type"), rb_iv_get(obj, "type"));
1729
+ rb_hash_aset(h, rb_str_new2("length"), rb_iv_get(obj, "length"));
1730
+ rb_hash_aset(h, rb_str_new2("max_length"), rb_iv_get(obj, "max_length"));
1731
+ rb_hash_aset(h, rb_str_new2("flags"), rb_iv_get(obj, "flags"));
1732
+ rb_hash_aset(h, rb_str_new2("decimals"), rb_iv_get(obj, "decimals"));
1733
+ return h;
1734
+ }
1735
+
1736
+ /* inspect */
1737
+ static VALUE field_inspect(VALUE obj)
1738
+ {
1739
+ VALUE n = rb_iv_get(obj, "name");
1740
+ VALUE s = rb_enc_str_new(0, RSTRING_LEN(n) + 16, DEFAULT_ENCODING);
1741
+ sprintf(RSTRING_PTR(s), "#<Mysql::Field:%s>", RSTRING_PTR(n));
1742
+ return s;
1743
+ }
1744
+
1745
+ #define DefineMysqlFieldMemberMethod(m)\
1746
+ static VALUE field_##m(VALUE obj)\
1747
+ {return rb_iv_get(obj, #m);}
1748
+
1749
+ DefineMysqlFieldMemberMethod(name)
1750
+ DefineMysqlFieldMemberMethod(table)
1751
+ DefineMysqlFieldMemberMethod(def)
1752
+ DefineMysqlFieldMemberMethod(type)
1753
+ DefineMysqlFieldMemberMethod(length)
1754
+ DefineMysqlFieldMemberMethod(max_length)
1755
+ DefineMysqlFieldMemberMethod(flags)
1756
+ DefineMysqlFieldMemberMethod(decimals)
1757
+
1758
+ #ifdef IS_NUM
1759
+ /* is_num? */
1760
+ static VALUE field_is_num(VALUE obj)
1761
+ {
1762
+ return IS_NUM(NUM2INT(rb_iv_get(obj, "type"))) ? Qtrue : Qfalse;
1763
+ }
1764
+ #endif
1765
+
1766
+ #ifdef IS_NOT_NULL
1767
+ /* is_not_null? */
1768
+ static VALUE field_is_not_null(VALUE obj)
1769
+ {
1770
+ return IS_NOT_NULL(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse;
1771
+ }
1772
+ #endif
1773
+
1774
+ #ifdef IS_PRI_KEY
1775
+ /* is_pri_key? */
1776
+ static VALUE field_is_pri_key(VALUE obj)
1777
+ {
1778
+ return IS_PRI_KEY(NUM2INT(rb_iv_get(obj, "flags"))) ? Qtrue : Qfalse;
1779
+ }
1780
+ #endif
1781
+
1782
+ #if MYSQL_VERSION_ID >= 40102
1783
+ /*-------------------------------
1784
+ * Mysql::Stmt object method
1785
+ */
1786
+
1787
+ /* check if stmt is already closed */
1788
+ static void check_stmt_closed(VALUE obj)
1789
+ {
1790
+ struct mysql_stmt* s = DATA_PTR(obj);
1791
+ if (s->closed == Qtrue)
1792
+ rb_raise(eMysql, "Mysql::Stmt object is already closed");
1793
+ }
1794
+
1795
+ static void mysql_stmt_raise(MYSQL_STMT* s)
1796
+ {
1797
+ VALUE e = rb_exc_new2(eMysql, mysql_stmt_error(s));
1798
+ rb_iv_set(e, "errno", INT2FIX(mysql_stmt_errno(s)));
1799
+ rb_iv_set(e, "sqlstate", rb_enc_tainted_str_new2(mysql_stmt_sqlstate(s)));
1800
+ rb_exc_raise(e);
1801
+ }
1802
+
1803
+ /* affected_rows() */
1804
+ static VALUE stmt_affected_rows(VALUE obj)
1805
+ {
1806
+ struct mysql_stmt* s = DATA_PTR(obj);
1807
+ my_ulonglong n;
1808
+ check_stmt_closed(obj);
1809
+ n = mysql_stmt_affected_rows(s->stmt);
1810
+ return INT2NUM(n);
1811
+ }
1812
+
1813
+ #if 0
1814
+ /* attr_get(option) */
1815
+ static VALUE stmt_attr_get(VALUE obj, VALUE opt)
1816
+ {
1817
+ struct mysql_stmt* s = DATA_PTR(obj);
1818
+ check_stmt_closed(obj);
1819
+ if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
1820
+ my_bool arg;
1821
+ mysql_stmt_attr_get(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
1822
+ return arg == 1 ? Qtrue : Qfalse;
1823
+ }
1824
+ rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
1825
+ }
1826
+
1827
+ /* attr_set(option, arg) */
1828
+ static VALUE stmt_attr_set(VALUE obj, VALUE opt, VALUE val)
1829
+ {
1830
+ struct mysql_stmt* s = DATA_PTR(obj);
1831
+ check_stmt_closed(obj);
1832
+ if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
1833
+ my_bool arg;
1834
+ arg = (val == Qnil || val == Qfalse) ? 0 : 1;
1835
+ mysql_stmt_attr_set(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
1836
+ return obj;
1837
+ }
1838
+ rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
1839
+ }
1840
+ #endif
1841
+
1842
+ /* bind_result(bind,...) */
1843
+ static VALUE stmt_bind_result(int argc, VALUE *argv, VALUE obj)
1844
+ {
1845
+ struct mysql_stmt* s = DATA_PTR(obj);
1846
+ int i;
1847
+ MYSQL_FIELD *field;
1848
+
1849
+ check_stmt_closed(obj);
1850
+ if (argc != s->result.n)
1851
+ rb_raise(eMysql, "bind_result: result value count(%d) != number of argument(%d)", s->result.n, argc);
1852
+ for (i = 0; i < argc; i++) {
1853
+ if (argv[i] == Qnil || argv[i] == rb_cNilClass) {
1854
+ field = mysql_fetch_fields(s->res);
1855
+ s->result.bind[i].buffer_type = field[i].type;
1856
+ }
1857
+ else if (argv[i] == rb_cString)
1858
+ s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
1859
+ else if (argv[i] == rb_cNumeric || argv[i] == rb_cInteger || argv[i] == rb_cFixnum)
1860
+ s->result.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
1861
+ else if (argv[i] == rb_cFloat)
1862
+ s->result.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
1863
+ else if (argv[i] == cMysqlTime)
1864
+ s->result.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1865
+ else
1866
+ rb_raise(rb_eTypeError, "unrecognized class: %s", RSTRING_PTR(rb_inspect(argv[i])));
1867
+ if (mysql_stmt_bind_result(s->stmt, s->result.bind))
1868
+ mysql_stmt_raise(s->stmt);
1869
+ }
1870
+ return obj;
1871
+ }
1872
+
1873
+ /* close() */
1874
+ static VALUE stmt_close(VALUE obj)
1875
+ {
1876
+ struct mysql_stmt* s = DATA_PTR(obj);
1877
+ check_stmt_closed(obj);
1878
+ mysql_stmt_close(s->stmt);
1879
+ s->closed = Qtrue;
1880
+ return Qnil;
1881
+ }
1882
+
1883
+ /* data_seek(offset) */
1884
+ static VALUE stmt_data_seek(VALUE obj, VALUE offset)
1885
+ {
1886
+ struct mysql_stmt* s = DATA_PTR(obj);
1887
+ check_stmt_closed(obj);
1888
+ mysql_stmt_data_seek(s->stmt, NUM2INT(offset));
1889
+ return obj;
1890
+ }
1891
+
1892
+ /* execute(arg,...) */
1893
+ static VALUE stmt_execute(int argc, VALUE *argv, VALUE obj)
1894
+ {
1895
+ struct mysql_stmt *s = DATA_PTR(obj);
1896
+ MYSQL_STMT *stmt = s->stmt;
1897
+ int i;
1898
+
1899
+ check_stmt_closed(obj);
1900
+ free_execute_memory(s);
1901
+ if (s->param.n != argc)
1902
+ rb_raise(eMysql, "execute: param_count(%d) != number of argument(%d)", s->param.n, argc);
1903
+ if (argc > 0) {
1904
+ memset(s->param.bind, 0, sizeof(*(s->param.bind))*argc);
1905
+ for (i = 0; i < argc; i++) {
1906
+ switch (TYPE(argv[i])) {
1907
+ case T_NIL:
1908
+ s->param.bind[i].buffer_type = MYSQL_TYPE_NULL;
1909
+ break;
1910
+ case T_FIXNUM:
1911
+ #if SIZEOF_INT < SIZEOF_LONG
1912
+ s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
1913
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1914
+ *(LONG_LONG*)(s->param.bind[i].buffer) = FIX2LONG(argv[i]);
1915
+ #else
1916
+ s->param.bind[i].buffer_type = MYSQL_TYPE_LONG;
1917
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1918
+ *(int*)(s->param.bind[i].buffer) = FIX2INT(argv[i]);
1919
+ #endif
1920
+ break;
1921
+ case T_BIGNUM:
1922
+ s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
1923
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1924
+ *(LONG_LONG*)(s->param.bind[i].buffer) = rb_big2ll(argv[i]);
1925
+ break;
1926
+ case T_FLOAT:
1927
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
1928
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1929
+ *(double*)(s->param.bind[i].buffer) = NUM2DBL(argv[i]);
1930
+ break;
1931
+ case T_STRING:
1932
+ s->param.bind[i].buffer_type = MYSQL_TYPE_STRING;
1933
+ s->param.bind[i].buffer = RSTRING_PTR(argv[i]);
1934
+ s->param.bind[i].buffer_length = RSTRING_LEN(argv[i]);
1935
+ s->param.length[i] = RSTRING_LEN(argv[i]);
1936
+ s->param.bind[i].length = &(s->param.length[i]);
1937
+ break;
1938
+ default:
1939
+ if (CLASS_OF(argv[i]) == rb_cTime) {
1940
+ MYSQL_TIME t;
1941
+ VALUE a = rb_funcall(argv[i], rb_intern("to_a"), 0);
1942
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1943
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1944
+ t.second_part = 0;
1945
+ t.neg = 0;
1946
+ t.second = FIX2INT(rb_ary_entry(a, 0));
1947
+ t.minute = FIX2INT(rb_ary_entry(a, 1));
1948
+ t.hour = FIX2INT(rb_ary_entry(a, 2));
1949
+ t.day = FIX2INT(rb_ary_entry(a, 3));
1950
+ t.month = FIX2INT(rb_ary_entry(a, 4));
1951
+ t.year = FIX2INT(rb_ary_entry(a, 5));
1952
+ *(MYSQL_TIME*)&(s->param.buffer[i]) = t;
1953
+ } else if (CLASS_OF(argv[i]) == cMysqlTime) {
1954
+ MYSQL_TIME t;
1955
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1956
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1957
+ t.second_part = 0;
1958
+ t.neg = 0;
1959
+ t.second = NUM2INT(rb_iv_get(argv[i], "second"));
1960
+ t.minute = NUM2INT(rb_iv_get(argv[i], "minute"));
1961
+ t.hour = NUM2INT(rb_iv_get(argv[i], "hour"));
1962
+ t.day = NUM2INT(rb_iv_get(argv[i], "day"));
1963
+ t.month = NUM2INT(rb_iv_get(argv[i], "month"));
1964
+ t.year = NUM2INT(rb_iv_get(argv[i], "year"));
1965
+ *(MYSQL_TIME*)&(s->param.buffer[i]) = t;
1966
+ } else
1967
+ rb_raise(rb_eTypeError, "unsupported type: %d", TYPE(argv[i]));
1968
+ }
1969
+ }
1970
+ if (mysql_stmt_bind_param(stmt, s->param.bind))
1971
+ mysql_stmt_raise(stmt);
1972
+ }
1973
+
1974
+ if (mysql_stmt_execute(stmt))
1975
+ mysql_stmt_raise(stmt);
1976
+ if (s->res) {
1977
+ MYSQL_FIELD *field;
1978
+ if (mysql_stmt_store_result(stmt))
1979
+ mysql_stmt_raise(stmt);
1980
+ field = mysql_fetch_fields(s->res);
1981
+ for (i = 0; i < s->result.n; i++) {
1982
+ switch(s->result.bind[i].buffer_type) {
1983
+ case MYSQL_TYPE_NULL:
1984
+ break;
1985
+ case MYSQL_TYPE_TINY:
1986
+ case MYSQL_TYPE_SHORT:
1987
+ case MYSQL_TYPE_YEAR:
1988
+ case MYSQL_TYPE_INT24:
1989
+ case MYSQL_TYPE_LONG:
1990
+ case MYSQL_TYPE_LONGLONG:
1991
+ case MYSQL_TYPE_FLOAT:
1992
+ case MYSQL_TYPE_DOUBLE:
1993
+ s->result.bind[i].buffer = xmalloc(8);
1994
+ s->result.bind[i].buffer_length = 8;
1995
+ memset(s->result.bind[i].buffer, 0, 8);
1996
+ break;
1997
+ case MYSQL_TYPE_DECIMAL:
1998
+ case MYSQL_TYPE_STRING:
1999
+ case MYSQL_TYPE_VAR_STRING:
2000
+ case MYSQL_TYPE_TINY_BLOB:
2001
+ case MYSQL_TYPE_BLOB:
2002
+ case MYSQL_TYPE_MEDIUM_BLOB:
2003
+ case MYSQL_TYPE_LONG_BLOB:
2004
+ #if MYSQL_VERSION_ID >= 50003
2005
+ case MYSQL_TYPE_NEWDECIMAL:
2006
+ case MYSQL_TYPE_BIT:
2007
+ #endif
2008
+ s->result.bind[i].buffer = xmalloc(field[i].max_length);
2009
+ memset(s->result.bind[i].buffer, 0, field[i].max_length);
2010
+ s->result.bind[i].buffer_length = field[i].max_length;
2011
+ break;
2012
+ case MYSQL_TYPE_TIME:
2013
+ case MYSQL_TYPE_DATE:
2014
+ case MYSQL_TYPE_DATETIME:
2015
+ case MYSQL_TYPE_TIMESTAMP:
2016
+ s->result.bind[i].buffer = xmalloc(sizeof(MYSQL_TIME));
2017
+ s->result.bind[i].buffer_length = sizeof(MYSQL_TIME);
2018
+ memset(s->result.bind[i].buffer, 0, sizeof(MYSQL_TIME));
2019
+ break;
2020
+ default:
2021
+ rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
2022
+ }
2023
+ }
2024
+ if (mysql_stmt_bind_result(s->stmt, s->result.bind))
2025
+ mysql_stmt_raise(s->stmt);
2026
+ }
2027
+ return obj;
2028
+ }
2029
+
2030
+ /* fetch() */
2031
+ static VALUE stmt_fetch(VALUE obj)
2032
+ {
2033
+ struct mysql_stmt* s = DATA_PTR(obj);
2034
+ VALUE ret;
2035
+ int i;
2036
+ int r;
2037
+
2038
+ check_stmt_closed(obj);
2039
+ r = mysql_stmt_fetch(s->stmt);
2040
+ if (r == MYSQL_NO_DATA)
2041
+ return Qnil;
2042
+ #ifdef MYSQL_DATA_TRUNCATED
2043
+ if (r == MYSQL_DATA_TRUNCATED)
2044
+ rb_raise(rb_eRuntimeError, "unexpectedly data truncated");
2045
+ #endif
2046
+ if (r == 1)
2047
+ mysql_stmt_raise(s->stmt);
2048
+
2049
+ ret = rb_ary_new2(s->result.n);
2050
+ for (i = 0; i < s->result.n; i++) {
2051
+ if (s->result.is_null[i])
2052
+ rb_ary_push(ret, Qnil);
2053
+ else {
2054
+ VALUE v;
2055
+ MYSQL_TIME *t;
2056
+ switch (s->result.bind[i].buffer_type) {
2057
+ case MYSQL_TYPE_TINY:
2058
+ if (s->result.bind[i].is_unsigned)
2059
+ v = UINT2NUM(*(unsigned char *)s->result.bind[i].buffer);
2060
+ else
2061
+ v = INT2NUM(*(signed char *)s->result.bind[i].buffer);
2062
+ break;
2063
+ case MYSQL_TYPE_SHORT:
2064
+ case MYSQL_TYPE_YEAR:
2065
+ if (s->result.bind[i].is_unsigned)
2066
+ v = UINT2NUM(*(unsigned short *)s->result.bind[i].buffer);
2067
+ else
2068
+ v = INT2NUM(*(short *)s->result.bind[i].buffer);
2069
+ break;
2070
+ case MYSQL_TYPE_INT24:
2071
+ case MYSQL_TYPE_LONG:
2072
+ if (s->result.bind[i].is_unsigned)
2073
+ v = UINT2NUM(*(unsigned int *)s->result.bind[i].buffer);
2074
+ else
2075
+ v = INT2NUM(*(int *)s->result.bind[i].buffer);
2076
+ break;
2077
+ case MYSQL_TYPE_LONGLONG:
2078
+ if (s->result.bind[i].is_unsigned)
2079
+ v = ULL2NUM(*(unsigned long long *)s->result.bind[i].buffer);
2080
+ else
2081
+ v = LL2NUM(*(long long *)s->result.bind[i].buffer);
2082
+ break;
2083
+ case MYSQL_TYPE_FLOAT:
2084
+ v = rb_float_new((double)(*(float *)s->result.bind[i].buffer));
2085
+ break;
2086
+ case MYSQL_TYPE_DOUBLE:
2087
+ v = rb_float_new(*(double *)s->result.bind[i].buffer);
2088
+ break;
2089
+ case MYSQL_TYPE_TIME:
2090
+ case MYSQL_TYPE_DATE:
2091
+ case MYSQL_TYPE_DATETIME:
2092
+ case MYSQL_TYPE_TIMESTAMP:
2093
+ t = (MYSQL_TIME *)s->result.bind[i].buffer;
2094
+ v = rb_obj_alloc(cMysqlTime);
2095
+ rb_funcall(v, rb_intern("initialize"), 8,
2096
+ INT2FIX(t->year), INT2FIX(t->month),
2097
+ INT2FIX(t->day), INT2FIX(t->hour),
2098
+ INT2FIX(t->minute), INT2FIX(t->second),
2099
+ (t->neg ? Qtrue : Qfalse),
2100
+ INT2FIX(t->second_part));
2101
+ break;
2102
+ case MYSQL_TYPE_DECIMAL:
2103
+ case MYSQL_TYPE_STRING:
2104
+ case MYSQL_TYPE_VAR_STRING:
2105
+ case MYSQL_TYPE_TINY_BLOB:
2106
+ case MYSQL_TYPE_BLOB:
2107
+ case MYSQL_TYPE_MEDIUM_BLOB:
2108
+ case MYSQL_TYPE_LONG_BLOB:
2109
+ #if MYSQL_VERSION_ID >= 50003
2110
+ case MYSQL_TYPE_NEWDECIMAL:
2111
+ case MYSQL_TYPE_BIT:
2112
+ #endif
2113
+ v = rb_enc_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]);
2114
+ break;
2115
+ default:
2116
+ rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
2117
+ }
2118
+ rb_ary_push(ret, v);
2119
+ }
2120
+ }
2121
+ return ret;
2122
+ }
2123
+
2124
+ /* each {...} */
2125
+ static VALUE stmt_each(VALUE obj)
2126
+ {
2127
+ VALUE row;
2128
+ check_stmt_closed(obj);
2129
+ while ((row = stmt_fetch(obj)) != Qnil)
2130
+ rb_yield(row);
2131
+ return obj;
2132
+ }
2133
+
2134
+ /* field_count() */
2135
+ static VALUE stmt_field_count(VALUE obj)
2136
+ {
2137
+ struct mysql_stmt* s = DATA_PTR(obj);
2138
+ unsigned int n;
2139
+ check_stmt_closed(obj);
2140
+ n = mysql_stmt_field_count(s->stmt);
2141
+ return INT2NUM(n);
2142
+ }
2143
+
2144
+ /* free_result() */
2145
+ static VALUE stmt_free_result(VALUE obj)
2146
+ {
2147
+ struct mysql_stmt* s = DATA_PTR(obj);
2148
+ check_stmt_closed(obj);
2149
+ if (mysql_stmt_free_result(s->stmt))
2150
+ mysql_stmt_raise(s->stmt);
2151
+ return obj;
2152
+ }
2153
+
2154
+ /* insert_id() */
2155
+ static VALUE stmt_insert_id(VALUE obj)
2156
+ {
2157
+ struct mysql_stmt* s = DATA_PTR(obj);
2158
+ my_ulonglong n;
2159
+ check_stmt_closed(obj);
2160
+ n = mysql_stmt_insert_id(s->stmt);
2161
+ return INT2NUM(n);
2162
+ }
2163
+
2164
+ /* num_rows() */
2165
+ static VALUE stmt_num_rows(VALUE obj)
2166
+ {
2167
+ struct mysql_stmt* s = DATA_PTR(obj);
2168
+ my_ulonglong n;
2169
+ check_stmt_closed(obj);
2170
+ n = mysql_stmt_num_rows(s->stmt);
2171
+ return INT2NUM(n);
2172
+ }
2173
+
2174
+ /* param_count() */
2175
+ static VALUE stmt_param_count(VALUE obj)
2176
+ {
2177
+ struct mysql_stmt* s = DATA_PTR(obj);
2178
+ unsigned long n;
2179
+ check_stmt_closed(obj);
2180
+ n = mysql_stmt_param_count(s->stmt);
2181
+ return INT2NUM(n);
2182
+ }
2183
+
2184
+ /* prepare(query) */
2185
+ static VALUE stmt_prepare(VALUE obj, VALUE query)
2186
+ {
2187
+ struct mysql_stmt* s = DATA_PTR(obj);
2188
+ int n;
2189
+ int i;
2190
+ MYSQL_FIELD *field;
2191
+
2192
+ free_mysqlstmt_memory(s);
2193
+ check_stmt_closed(obj);
2194
+ Check_Type(query, T_STRING);
2195
+ if (mysql_stmt_prepare(s->stmt, RSTRING_PTR(query), RSTRING_LEN(query)))
2196
+ mysql_stmt_raise(s->stmt);
2197
+
2198
+ n = mysql_stmt_param_count(s->stmt);
2199
+ s->param.n = n;
2200
+ s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n);
2201
+ s->param.length = xmalloc(sizeof(s->param.length[0]) * n);
2202
+ s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n);
2203
+
2204
+ s->res = mysql_stmt_result_metadata(s->stmt);
2205
+ if (s->res) {
2206
+ n = s->result.n = mysql_num_fields(s->res);
2207
+ s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n);
2208
+ s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n);
2209
+ s->result.length = xmalloc(sizeof(s->result.length[0]) * n);
2210
+ field = mysql_fetch_fields(s->res);
2211
+ memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n);
2212
+ for (i = 0; i < n; i++) {
2213
+ s->result.bind[i].buffer_type = field[i].type;
2214
+ #if MYSQL_VERSION_ID < 50003
2215
+ if (field[i].type == MYSQL_TYPE_DECIMAL)
2216
+ s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
2217
+ #endif
2218
+ s->result.bind[i].is_null = &(s->result.is_null[i]);
2219
+ s->result.bind[i].length = &(s->result.length[i]);
2220
+ s->result.bind[i].is_unsigned = ((field[i].flags & UNSIGNED_FLAG) != 0);
2221
+ }
2222
+ } else {
2223
+ if (mysql_stmt_errno(s->stmt))
2224
+ mysql_stmt_raise(s->stmt);
2225
+ }
2226
+
2227
+ return obj;
2228
+ }
2229
+
2230
+ #if 0
2231
+ /* reset() */
2232
+ static VALUE stmt_reset(VALUE obj)
2233
+ {
2234
+ struct mysql_stmt* s = DATA_PTR(obj);
2235
+ check_stmt_closed(obj);
2236
+ if (mysql_stmt_reset(s->stmt))
2237
+ mysql_stmt_raise(s->stmt);
2238
+ return obj;
2239
+ }
2240
+ #endif
2241
+
2242
+ /* result_metadata() */
2243
+ static VALUE stmt_result_metadata(VALUE obj)
2244
+ {
2245
+ struct mysql_stmt* s = DATA_PTR(obj);
2246
+ MYSQL_RES *res;
2247
+ check_stmt_closed(obj);
2248
+ res = mysql_stmt_result_metadata(s->stmt);
2249
+ if (res == NULL) {
2250
+ if (mysql_stmt_errno(s->stmt) != 0)
2251
+ mysql_stmt_raise(s->stmt);
2252
+ return Qnil;
2253
+ }
2254
+ return mysqlres2obj(res, Qfalse);
2255
+ }
2256
+
2257
+ /* row_seek(offset) */
2258
+ static VALUE stmt_row_seek(VALUE obj, VALUE offset)
2259
+ {
2260
+ struct mysql_stmt* s = DATA_PTR(obj);
2261
+ MYSQL_ROW_OFFSET prev_offset;
2262
+ if (CLASS_OF(offset) != cMysqlRowOffset)
2263
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
2264
+ check_stmt_closed(obj);
2265
+ prev_offset = mysql_stmt_row_seek(s->stmt, DATA_PTR(offset));
2266
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);
2267
+ }
2268
+
2269
+ /* row_tell() */
2270
+ static VALUE stmt_row_tell(VALUE obj)
2271
+ {
2272
+ struct mysql_stmt* s = DATA_PTR(obj);
2273
+ MYSQL_ROW_OFFSET offset;
2274
+ check_stmt_closed(obj);
2275
+ offset = mysql_stmt_row_tell(s->stmt);
2276
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);
2277
+ }
2278
+
2279
+ #if 0
2280
+ /* send_long_data(col, data) */
2281
+ static VALUE stmt_send_long_data(VALUE obj, VALUE col, VALUE data)
2282
+ {
2283
+ struct mysql_stmt* s = DATA_PTR(obj);
2284
+ int c;
2285
+ check_stmt_closed(obj);
2286
+ c = NUM2INT(col);
2287
+ if (0 <= c && c < s->param.n) {
2288
+ s->param.bind[c].buffer_type = MYSQL_TYPE_STRING;
2289
+ if (mysql_stmt_bind_param(s->stmt, s->param.bind))
2290
+ mysql_stmt_raise(s->stmt);
2291
+ }
2292
+ if (mysql_stmt_send_long_data(s->stmt, c, RSTRING_PTR(data), RSTRING_LEN(data)))
2293
+ mysql_stmt_raise(s->stmt);
2294
+ return obj;
2295
+ }
2296
+ #endif
2297
+
2298
+ /* sqlstate() */
2299
+ static VALUE stmt_sqlstate(VALUE obj)
2300
+ {
2301
+ struct mysql_stmt* s = DATA_PTR(obj);
2302
+ return rb_enc_tainted_str_new2(mysql_stmt_sqlstate(s->stmt));
2303
+ }
2304
+
2305
+ /*-------------------------------
2306
+ * Mysql::Time object method
2307
+ */
2308
+
2309
+ static VALUE time_initialize(int argc, VALUE* argv, VALUE obj)
2310
+ {
2311
+ VALUE year, month, day, hour, minute, second, neg, second_part;
2312
+ rb_scan_args(argc, argv, "08", &year, &month, &day, &hour, &minute, &second, &neg, &second_part);
2313
+ #define NILorFIXvalue(o) (NIL_P(o) ? INT2FIX(0) : (Check_Type(o, T_FIXNUM), o))
2314
+ rb_iv_set(obj, "year", NILorFIXvalue(year));
2315
+ rb_iv_set(obj, "month", NILorFIXvalue(month));
2316
+ rb_iv_set(obj, "day", NILorFIXvalue(day));
2317
+ rb_iv_set(obj, "hour", NILorFIXvalue(hour));
2318
+ rb_iv_set(obj, "minute", NILorFIXvalue(minute));
2319
+ rb_iv_set(obj, "second", NILorFIXvalue(second));
2320
+ rb_iv_set(obj, "neg", (neg == Qnil || neg == Qfalse) ? Qfalse : Qtrue);
2321
+ rb_iv_set(obj, "second_part", NILorFIXvalue(second_part));
2322
+ return obj;
2323
+ }
2324
+
2325
+ static VALUE time_inspect(VALUE obj)
2326
+ {
2327
+ char buf[36];
2328
+ sprintf(buf, "#<Mysql::Time:%04d-%02d-%02d %02d:%02d:%02d>",
2329
+ NUM2INT(rb_iv_get(obj, "year")),
2330
+ NUM2INT(rb_iv_get(obj, "month")),
2331
+ NUM2INT(rb_iv_get(obj, "day")),
2332
+ NUM2INT(rb_iv_get(obj, "hour")),
2333
+ NUM2INT(rb_iv_get(obj, "minute")),
2334
+ NUM2INT(rb_iv_get(obj, "second")));
2335
+ return rb_str_new2(buf);
2336
+ }
2337
+
2338
+ static VALUE time_to_s(VALUE obj)
2339
+ {
2340
+ char buf[20];
2341
+ sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
2342
+ NUM2INT(rb_iv_get(obj, "year")),
2343
+ NUM2INT(rb_iv_get(obj, "month")),
2344
+ NUM2INT(rb_iv_get(obj, "day")),
2345
+ NUM2INT(rb_iv_get(obj, "hour")),
2346
+ NUM2INT(rb_iv_get(obj, "minute")),
2347
+ NUM2INT(rb_iv_get(obj, "second")));
2348
+ return rb_str_new2(buf);
2349
+ }
2350
+
2351
+ #define DefineMysqlTimeGetMethod(m)\
2352
+ static VALUE time_get_##m(VALUE obj)\
2353
+ {return rb_iv_get(obj, #m);}
2354
+
2355
+ DefineMysqlTimeGetMethod(year)
2356
+ DefineMysqlTimeGetMethod(month)
2357
+ DefineMysqlTimeGetMethod(day)
2358
+ DefineMysqlTimeGetMethod(hour)
2359
+ DefineMysqlTimeGetMethod(minute)
2360
+ DefineMysqlTimeGetMethod(second)
2361
+ DefineMysqlTimeGetMethod(neg)
2362
+ DefineMysqlTimeGetMethod(second_part)
2363
+
2364
+ #define DefineMysqlTimeSetMethod(m)\
2365
+ static VALUE time_set_##m(VALUE obj, VALUE v)\
2366
+ {rb_iv_set(obj, #m, NILorFIXvalue(v)); return v;}
2367
+
2368
+ DefineMysqlTimeSetMethod(year)
2369
+ DefineMysqlTimeSetMethod(month)
2370
+ DefineMysqlTimeSetMethod(day)
2371
+ DefineMysqlTimeSetMethod(hour)
2372
+ DefineMysqlTimeSetMethod(minute)
2373
+ DefineMysqlTimeSetMethod(second)
2374
+ DefineMysqlTimeSetMethod(second_part)
2375
+
2376
+ static VALUE time_set_neg(VALUE obj, VALUE v)
2377
+ {
2378
+ rb_iv_set(obj, "neg", (v == Qnil || v == Qfalse) ? Qfalse : Qtrue);
2379
+ return v;
2380
+ }
2381
+
2382
+ static VALUE time_equal(VALUE obj, VALUE v)
2383
+ {
2384
+ if (CLASS_OF(v) == cMysqlTime &&
2385
+ NUM2INT(rb_iv_get(obj, "year")) == NUM2INT(rb_iv_get(v, "year")) &&
2386
+ NUM2INT(rb_iv_get(obj, "month")) == NUM2INT(rb_iv_get(v, "month")) &&
2387
+ NUM2INT(rb_iv_get(obj, "day")) == NUM2INT(rb_iv_get(v, "day")) &&
2388
+ NUM2INT(rb_iv_get(obj, "hour")) == NUM2INT(rb_iv_get(v, "hour")) &&
2389
+ NUM2INT(rb_iv_get(obj, "minute")) == NUM2INT(rb_iv_get(v, "minute")) &&
2390
+ NUM2INT(rb_iv_get(obj, "second")) == NUM2INT(rb_iv_get(v, "second")) &&
2391
+ rb_iv_get(obj, "neg") == rb_iv_get(v, "neg") &&
2392
+ NUM2INT(rb_iv_get(obj, "second_part")) == NUM2INT(rb_iv_get(v, "second_part")))
2393
+ return Qtrue;
2394
+ return Qfalse;
2395
+ }
2396
+
2397
+ #endif
2398
+
2399
+ /*-------------------------------
2400
+ * Mysql::Error object method
2401
+ */
2402
+
2403
+ static VALUE error_error(VALUE obj)
2404
+ {
2405
+ return rb_iv_get(obj, "mesg");
2406
+ }
2407
+
2408
+ static VALUE error_errno(VALUE obj)
2409
+ {
2410
+ return rb_iv_get(obj, "errno");
2411
+ }
2412
+
2413
+ static VALUE error_sqlstate(VALUE obj)
2414
+ {
2415
+ return rb_iv_get(obj, "sqlstate");
2416
+ }
2417
+
2418
+ /*-------------------------------
2419
+ * Initialize
2420
+ */
2421
+
2422
+ void Init_mysql(void)
2423
+ {
2424
+ cMysql = rb_define_class("Mysql", rb_cObject);
2425
+ cMysqlRes = rb_define_class_under(cMysql, "Result", rb_cObject);
2426
+ cMysqlField = rb_define_class_under(cMysql, "Field", rb_cObject);
2427
+ #if MYSQL_VERSION_ID >= 40102
2428
+ cMysqlStmt = rb_define_class_under(cMysql, "Stmt", rb_cObject);
2429
+ cMysqlRowOffset = rb_define_class_under(cMysql, "RowOffset", rb_cObject);
2430
+ cMysqlTime = rb_define_class_under(cMysql, "Time", rb_cObject);
2431
+ #endif
2432
+ eMysql = rb_define_class_under(cMysql, "Error", rb_eStandardError);
2433
+
2434
+ rb_define_global_const("MysqlRes", cMysqlRes);
2435
+ rb_define_global_const("MysqlField", cMysqlField);
2436
+ rb_define_global_const("MysqlError", eMysql);
2437
+
2438
+ /* Mysql class method */
2439
+ rb_define_singleton_method(cMysql, "init", init, 0);
2440
+ rb_define_singleton_method(cMysql, "real_connect", real_connect, -1);
2441
+ rb_define_singleton_method(cMysql, "connect", real_connect, -1);
2442
+ rb_define_singleton_method(cMysql, "new", real_connect, -1);
2443
+ rb_define_singleton_method(cMysql, "escape_string", escape_string, 1);
2444
+ rb_define_singleton_method(cMysql, "quote", escape_string, 1);
2445
+ rb_define_singleton_method(cMysql, "client_info", client_info, 0);
2446
+ rb_define_singleton_method(cMysql, "get_client_info", client_info, 0);
2447
+ #if MYSQL_VERSION_ID >= 32332
2448
+ rb_define_singleton_method(cMysql, "debug", my_debug, 1);
2449
+ #endif
2450
+ #if MYSQL_VERSION_ID >= 40000
2451
+ rb_define_singleton_method(cMysql, "get_client_version", client_version, 0);
2452
+ rb_define_singleton_method(cMysql, "client_version", client_version, 0);
2453
+ #endif
2454
+
2455
+ /* Mysql object method */
2456
+ #if MYSQL_VERSION_ID >= 32200
2457
+ rb_define_method(cMysql, "real_connect", real_connect2, -1);
2458
+ rb_define_method(cMysql, "connect", real_connect2, -1);
2459
+ rb_define_method(cMysql, "options", options, -1);
2460
+ #endif
2461
+ rb_define_method(cMysql, "initialize", initialize, -1);
2462
+ #if MYSQL_VERSION_ID >= 32332
2463
+ rb_define_method(cMysql, "escape_string", real_escape_string, 1);
2464
+ rb_define_method(cMysql, "quote", real_escape_string, 1);
2465
+ #else
2466
+ rb_define_method(cMysql, "escape_string", escape_string, 1);
2467
+ rb_define_method(cMysql, "quote", escape_string, 1);
2468
+ #endif
2469
+ rb_define_method(cMysql, "client_info", client_info, 0);
2470
+ rb_define_method(cMysql, "get_client_info", client_info, 0);
2471
+ rb_define_method(cMysql, "affected_rows", affected_rows, 0);
2472
+ #if MYSQL_VERSION_ID >= 32303
2473
+ rb_define_method(cMysql, "change_user", change_user, -1);
2474
+ #endif
2475
+ #if MYSQL_VERSION_ID >= 32321
2476
+ rb_define_method(cMysql, "character_set_name", character_set_name, 0);
2477
+ #endif
2478
+ rb_define_method(cMysql, "close", my_close, 0);
2479
+ #if MYSQL_VERSION_ID < 40000
2480
+ rb_define_method(cMysql, "create_db", create_db, 1);
2481
+ rb_define_method(cMysql, "drop_db", drop_db, 1);
2482
+ #endif
2483
+ #if MYSQL_VERSION_ID >= 32332
2484
+ rb_define_method(cMysql, "dump_debug_info", dump_debug_info, 0);
2485
+ #endif
2486
+ rb_define_method(cMysql, "errno", my_errno, 0);
2487
+ rb_define_method(cMysql, "error", my_error, 0);
2488
+ rb_define_method(cMysql, "field_count", field_count, 0);
2489
+ #if MYSQL_VERSION_ID >= 40000
2490
+ rb_define_method(cMysql, "get_client_version", client_version, 0);
2491
+ rb_define_method(cMysql, "client_version", client_version, 0);
2492
+ #endif
2493
+ rb_define_method(cMysql, "get_host_info", host_info, 0);
2494
+ rb_define_method(cMysql, "host_info", host_info, 0);
2495
+ rb_define_method(cMysql, "get_proto_info", proto_info, 0);
2496
+ rb_define_method(cMysql, "proto_info", proto_info, 0);
2497
+ rb_define_method(cMysql, "get_server_info", server_info, 0);
2498
+ rb_define_method(cMysql, "server_info", server_info, 0);
2499
+ rb_define_method(cMysql, "info", info, 0);
2500
+ rb_define_method(cMysql, "insert_id", insert_id, 0);
2501
+ rb_define_method(cMysql, "kill", my_kill, 1);
2502
+ rb_define_method(cMysql, "list_dbs", list_dbs, -1);
2503
+ rb_define_method(cMysql, "list_fields", list_fields, -1);
2504
+ rb_define_method(cMysql, "list_processes", list_processes, 0);
2505
+ rb_define_method(cMysql, "list_tables", list_tables, -1);
2506
+ #if MYSQL_VERSION_ID >= 32200
2507
+ rb_define_method(cMysql, "ping", ping, 0);
2508
+ #endif
2509
+ rb_define_method(cMysql, "query", query, 1);
2510
+ rb_define_method(cMysql, "real_query", query, 1);
2511
+ rb_define_method(cMysql, "c_async_query", async_query, -1);
2512
+ rb_define_method(cMysql, "async_in_progress?", async_in_progress, 0);
2513
+ rb_define_method(cMysql, "async_in_progress=", async_in_progress_set, 1);
2514
+ rb_define_method(cMysql, "send_query", send_query, 1);
2515
+ rb_define_method(cMysql, "simulate_disconnect", simulate_disconnect, 0);
2516
+ rb_define_method(cMysql, "reconnected?", reconnected, 0);
2517
+ rb_define_method(cMysql, "get_result", get_result, 0);
2518
+ rb_define_method(cMysql, "readable?", readable, -1);
2519
+ rb_define_method(cMysql, "retry?", retry, 0);
2520
+ rb_define_method(cMysql, "interrupted?", interrupted, 0);
2521
+ rb_define_method(cMysql, "blocking?", blocking, 0);
2522
+ rb_define_method(cMysql, "gc_disabled?", gc_disabled, 0);
2523
+ rb_define_method(cMysql, "disable_gc=", disable_gc_set, 1);
2524
+ rb_define_method(cMysql, "busy?", is_busy, 0);
2525
+ rb_define_method(cMysql, "idle?", is_idle, 0);
2526
+ rb_define_method(cMysql, "busy=", busy_set, 1);
2527
+ rb_define_method(cMysql, "socket", socket, 0);
2528
+ rb_define_method(cMysql, "refresh", refresh, 1);
2529
+ rb_define_method(cMysql, "reload", reload, 0);
2530
+ rb_define_method(cMysql, "select_db", select_db, 1);
2531
+ rb_define_method(cMysql, "shutdown", my_shutdown, -1);
2532
+ rb_define_method(cMysql, "stat", my_stat, 0);
2533
+ rb_define_method(cMysql, "store_result", store_result, 0);
2534
+ rb_define_method(cMysql, "thread_id", thread_id, 0);
2535
+ rb_define_method(cMysql, "use_result", use_result, 0);
2536
+ #if MYSQL_VERSION_ID >= 40100
2537
+ rb_define_method(cMysql, "get_server_version", server_version, 0);
2538
+ rb_define_method(cMysql, "server_version", server_version, 0);
2539
+ rb_define_method(cMysql, "warning_count", warning_count, 0);
2540
+ rb_define_method(cMysql, "commit", commit, 0);
2541
+ rb_define_method(cMysql, "rollback", rollback, 0);
2542
+ rb_define_method(cMysql, "autocommit", autocommit, 1);
2543
+ #endif
2544
+ #ifdef HAVE_MYSQL_SSL_SET
2545
+ rb_define_method(cMysql, "ssl_set", ssl_set, -1);
2546
+ #endif
2547
+ #if MYSQL_VERSION_ID >= 40102
2548
+ rb_define_method(cMysql, "stmt_init", stmt_init, 0);
2549
+ rb_define_method(cMysql, "prepare", prepare, 1);
2550
+ #endif
2551
+ #if MYSQL_VERSION_ID >= 40100
2552
+ rb_define_method(cMysql, "more_results", more_results, 0);
2553
+ rb_define_method(cMysql, "more_results?", more_results, 0);
2554
+ rb_define_method(cMysql, "next_result", next_result, 0);
2555
+ #endif
2556
+ #if MYSQL_VERSION_ID >= 40101
2557
+ rb_define_method(cMysql, "set_server_option", set_server_option, 1);
2558
+ rb_define_method(cMysql, "sqlstate", sqlstate, 0);
2559
+ #endif
2560
+ rb_define_method(cMysql, "query_with_result", query_with_result, 0);
2561
+ rb_define_method(cMysql, "query_with_result=", query_with_result_set, 1);
2562
+
2563
+ rb_define_method(cMysql, "reconnect", reconnect, 0);
2564
+ rb_define_method(cMysql, "reconnect=", reconnect_set, 1);
2565
+
2566
+ /* Mysql constant */
2567
+ rb_define_const(cMysql, "VERSION", INT2FIX(MYSQL_RUBY_VERSION));
2568
+ #if MYSQL_VERSION_ID >= 32200
2569
+ rb_define_const(cMysql, "OPT_CONNECT_TIMEOUT", INT2NUM(MYSQL_OPT_CONNECT_TIMEOUT));
2570
+ rb_define_const(cMysql, "OPT_COMPRESS", INT2NUM(MYSQL_OPT_COMPRESS));
2571
+ rb_define_const(cMysql, "OPT_NAMED_PIPE", INT2NUM(MYSQL_OPT_NAMED_PIPE));
2572
+ rb_define_const(cMysql, "INIT_COMMAND", INT2NUM(MYSQL_INIT_COMMAND));
2573
+ rb_define_const(cMysql, "READ_DEFAULT_FILE", INT2NUM(MYSQL_READ_DEFAULT_FILE));
2574
+ rb_define_const(cMysql, "READ_DEFAULT_GROUP", INT2NUM(MYSQL_READ_DEFAULT_GROUP));
2575
+ #endif
2576
+ #if MYSQL_VERSION_ID >= 32349
2577
+ rb_define_const(cMysql, "SET_CHARSET_DIR", INT2NUM(MYSQL_SET_CHARSET_DIR));
2578
+ rb_define_const(cMysql, "SET_CHARSET_NAME", INT2NUM(MYSQL_SET_CHARSET_NAME));
2579
+ rb_define_const(cMysql, "OPT_LOCAL_INFILE", INT2NUM(MYSQL_OPT_LOCAL_INFILE));
2580
+ #endif
2581
+ #if MYSQL_VERSION_ID >= 40100
2582
+ rb_define_const(cMysql, "OPT_PROTOCOL", INT2NUM(MYSQL_OPT_PROTOCOL));
2583
+ rb_define_const(cMysql, "SHARED_MEMORY_BASE_NAME", INT2NUM(MYSQL_SHARED_MEMORY_BASE_NAME));
2584
+ #endif
2585
+ #if MYSQL_VERSION_ID >= 40101
2586
+ rb_define_const(cMysql, "OPT_READ_TIMEOUT", INT2NUM(MYSQL_OPT_READ_TIMEOUT));
2587
+ rb_define_const(cMysql, "OPT_WRITE_TIMEOUT", INT2NUM(MYSQL_OPT_WRITE_TIMEOUT));
2588
+ rb_define_const(cMysql, "SECURE_AUTH", INT2NUM(MYSQL_SECURE_AUTH));
2589
+ rb_define_const(cMysql, "OPT_GUESS_CONNECTION", INT2NUM(MYSQL_OPT_GUESS_CONNECTION));
2590
+ rb_define_const(cMysql, "OPT_USE_EMBEDDED_CONNECTION", INT2NUM(MYSQL_OPT_USE_EMBEDDED_CONNECTION));
2591
+ rb_define_const(cMysql, "OPT_USE_REMOTE_CONNECTION", INT2NUM(MYSQL_OPT_USE_REMOTE_CONNECTION));
2592
+ rb_define_const(cMysql, "SET_CLIENT_IP", INT2NUM(MYSQL_SET_CLIENT_IP));
2593
+ #endif
2594
+ rb_define_const(cMysql, "REFRESH_GRANT", INT2NUM(REFRESH_GRANT));
2595
+ rb_define_const(cMysql, "REFRESH_LOG", INT2NUM(REFRESH_LOG));
2596
+ rb_define_const(cMysql, "REFRESH_TABLES", INT2NUM(REFRESH_TABLES));
2597
+ #ifdef REFRESH_HOSTS
2598
+ rb_define_const(cMysql, "REFRESH_HOSTS", INT2NUM(REFRESH_HOSTS));
2599
+ #endif
2600
+ #ifdef REFRESH_STATUS
2601
+ rb_define_const(cMysql, "REFRESH_STATUS", INT2NUM(REFRESH_STATUS));
2602
+ #endif
2603
+ #ifdef REFRESH_THREADS
2604
+ rb_define_const(cMysql, "REFRESH_THREADS", INT2NUM(REFRESH_THREADS));
2605
+ #endif
2606
+ #ifdef REFRESH_SLAVE
2607
+ rb_define_const(cMysql, "REFRESH_SLAVE", INT2NUM(REFRESH_SLAVE));
2608
+ #endif
2609
+ #ifdef REFRESH_MASTER
2610
+ rb_define_const(cMysql, "REFRESH_MASTER", INT2NUM(REFRESH_MASTER));
2611
+ #endif
2612
+ #ifdef CLIENT_LONG_PASSWORD
2613
+ #endif
2614
+ #ifdef CLIENT_FOUND_ROWS
2615
+ rb_define_const(cMysql, "CLIENT_FOUND_ROWS", INT2NUM(CLIENT_FOUND_ROWS));
2616
+ #endif
2617
+ #ifdef CLIENT_LONG_FLAG
2618
+ #endif
2619
+ #ifdef CLIENT_CONNECT_WITH_DB
2620
+ #endif
2621
+ #ifdef CLIENT_NO_SCHEMA
2622
+ rb_define_const(cMysql, "CLIENT_NO_SCHEMA", INT2NUM(CLIENT_NO_SCHEMA));
2623
+ #endif
2624
+ #ifdef CLIENT_COMPRESS
2625
+ rb_define_const(cMysql, "CLIENT_COMPRESS", INT2NUM(CLIENT_COMPRESS));
2626
+ #endif
2627
+ #ifdef CLIENT_ODBC
2628
+ rb_define_const(cMysql, "CLIENT_ODBC", INT2NUM(CLIENT_ODBC));
2629
+ #endif
2630
+ #ifdef CLIENT_LOCAL_FILES
2631
+ rb_define_const(cMysql, "CLIENT_LOCAL_FILES", INT2NUM(CLIENT_LOCAL_FILES));
2632
+ #endif
2633
+ #ifdef CLIENT_IGNORE_SPACE
2634
+ rb_define_const(cMysql, "CLIENT_IGNORE_SPACE", INT2NUM(CLIENT_IGNORE_SPACE));
2635
+ #endif
2636
+ #ifdef CLIENT_CHANGE_USER
2637
+ rb_define_const(cMysql, "CLIENT_CHANGE_USER", INT2NUM(CLIENT_CHANGE_USER));
2638
+ #endif
2639
+ #ifdef CLIENT_INTERACTIVE
2640
+ rb_define_const(cMysql, "CLIENT_INTERACTIVE", INT2NUM(CLIENT_INTERACTIVE));
2641
+ #endif
2642
+ #ifdef CLIENT_SSL
2643
+ rb_define_const(cMysql, "CLIENT_SSL", INT2NUM(CLIENT_SSL));
2644
+ #endif
2645
+ #ifdef CLIENT_IGNORE_SIGPIPE
2646
+ rb_define_const(cMysql, "CLIENT_IGNORE_SIGPIPE", INT2NUM(CLIENT_IGNORE_SIGPIPE));
2647
+ #endif
2648
+ #ifdef CLIENT_TRANSACTIONS
2649
+ rb_define_const(cMysql, "CLIENT_TRANSACTIONS", INT2NUM(CLIENT_TRANSACTIONS));
2650
+ #endif
2651
+ #ifdef CLIENT_MULTI_STATEMENTS
2652
+ rb_define_const(cMysql, "CLIENT_MULTI_STATEMENTS", INT2NUM(CLIENT_MULTI_STATEMENTS));
2653
+ #endif
2654
+ #ifdef CLIENT_MULTI_RESULTS
2655
+ rb_define_const(cMysql, "CLIENT_MULTI_RESULTS", INT2NUM(CLIENT_MULTI_RESULTS));
2656
+ #endif
2657
+ #if MYSQL_VERSION_ID >= 40101
2658
+ rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_ON", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON));
2659
+ rb_define_const(cMysql, "OPTION_MULTI_STATEMENTS_OFF", INT2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF));
2660
+ #endif
2661
+
2662
+ /* Mysql::Result object method */
2663
+ rb_define_method(cMysqlRes, "data_seek", data_seek, 1);
2664
+ rb_define_method(cMysqlRes, "fetch_field", fetch_field, 0);
2665
+ rb_define_method(cMysqlRes, "fetch_fields", fetch_fields, 0);
2666
+ rb_define_method(cMysqlRes, "fetch_field_direct", fetch_field_direct, 1);
2667
+ rb_define_method(cMysqlRes, "fetch_lengths", fetch_lengths, 0);
2668
+ rb_define_method(cMysqlRes, "fetch_row", fetch_row, 0);
2669
+ rb_define_method(cMysqlRes, "fetch_hash", fetch_hash, -1);
2670
+ rb_define_method(cMysqlRes, "field_seek", field_seek, 1);
2671
+ rb_define_method(cMysqlRes, "field_tell", field_tell, 0);
2672
+ rb_define_method(cMysqlRes, "free", res_free, 0);
2673
+ rb_define_method(cMysqlRes, "num_fields", num_fields, 0);
2674
+ rb_define_method(cMysqlRes, "num_rows", num_rows, 0);
2675
+ rb_define_method(cMysqlRes, "row_seek", row_seek, 1);
2676
+ rb_define_method(cMysqlRes, "row_tell", row_tell, 0);
2677
+ rb_define_method(cMysqlRes, "each", each, 0);
2678
+ rb_define_method(cMysqlRes, "each_hash", each_hash, -1);
2679
+ rb_define_method(cMysqlRes, "all_hashes", all_hashes, -1);
2680
+
2681
+ /* MysqlField object method */
2682
+ rb_define_method(cMysqlField, "name", field_name, 0);
2683
+ rb_define_method(cMysqlField, "table", field_table, 0);
2684
+ rb_define_method(cMysqlField, "def", field_def, 0);
2685
+ rb_define_method(cMysqlField, "type", field_type, 0);
2686
+ rb_define_method(cMysqlField, "length", field_length, 0);
2687
+ rb_define_method(cMysqlField, "max_length", field_max_length, 0);
2688
+ rb_define_method(cMysqlField, "flags", field_flags, 0);
2689
+ rb_define_method(cMysqlField, "decimals", field_decimals, 0);
2690
+ rb_define_method(cMysqlField, "hash", field_hash, 0);
2691
+ rb_define_method(cMysqlField, "inspect", field_inspect, 0);
2692
+ #ifdef IS_NUM
2693
+ rb_define_method(cMysqlField, "is_num?", field_is_num, 0);
2694
+ #endif
2695
+ #ifdef IS_NOT_NULL
2696
+ rb_define_method(cMysqlField, "is_not_null?", field_is_not_null, 0);
2697
+ #endif
2698
+ #ifdef IS_PRI_KEY
2699
+ rb_define_method(cMysqlField, "is_pri_key?", field_is_pri_key, 0);
2700
+ #endif
2701
+
2702
+ /* Mysql::Field constant: TYPE */
2703
+ rb_define_const(cMysqlField, "TYPE_TINY", INT2NUM(FIELD_TYPE_TINY));
2704
+ #if MYSQL_VERSION_ID >= 32115
2705
+ rb_define_const(cMysqlField, "TYPE_ENUM", INT2NUM(FIELD_TYPE_ENUM));
2706
+ #endif
2707
+ rb_define_const(cMysqlField, "TYPE_DECIMAL", INT2NUM(FIELD_TYPE_DECIMAL));
2708
+ rb_define_const(cMysqlField, "TYPE_SHORT", INT2NUM(FIELD_TYPE_SHORT));
2709
+ rb_define_const(cMysqlField, "TYPE_LONG", INT2NUM(FIELD_TYPE_LONG));
2710
+ rb_define_const(cMysqlField, "TYPE_FLOAT", INT2NUM(FIELD_TYPE_FLOAT));
2711
+ rb_define_const(cMysqlField, "TYPE_DOUBLE", INT2NUM(FIELD_TYPE_DOUBLE));
2712
+ rb_define_const(cMysqlField, "TYPE_NULL", INT2NUM(FIELD_TYPE_NULL));
2713
+ rb_define_const(cMysqlField, "TYPE_TIMESTAMP", INT2NUM(FIELD_TYPE_TIMESTAMP));
2714
+ rb_define_const(cMysqlField, "TYPE_LONGLONG", INT2NUM(FIELD_TYPE_LONGLONG));
2715
+ rb_define_const(cMysqlField, "TYPE_INT24", INT2NUM(FIELD_TYPE_INT24));
2716
+ rb_define_const(cMysqlField, "TYPE_DATE", INT2NUM(FIELD_TYPE_DATE));
2717
+ rb_define_const(cMysqlField, "TYPE_TIME", INT2NUM(FIELD_TYPE_TIME));
2718
+ rb_define_const(cMysqlField, "TYPE_DATETIME", INT2NUM(FIELD_TYPE_DATETIME));
2719
+ #if MYSQL_VERSION_ID >= 32130
2720
+ rb_define_const(cMysqlField, "TYPE_YEAR", INT2NUM(FIELD_TYPE_YEAR));
2721
+ #endif
2722
+ #if MYSQL_VERSION_ID >= 50003
2723
+ rb_define_const(cMysqlField, "TYPE_BIT", INT2NUM(FIELD_TYPE_BIT));
2724
+ rb_define_const(cMysqlField, "TYPE_NEWDECIMAL", INT2NUM(FIELD_TYPE_NEWDECIMAL));
2725
+ #endif
2726
+ rb_define_const(cMysqlField, "TYPE_SET", INT2NUM(FIELD_TYPE_SET));
2727
+ rb_define_const(cMysqlField, "TYPE_BLOB", INT2NUM(FIELD_TYPE_BLOB));
2728
+ rb_define_const(cMysqlField, "TYPE_STRING", INT2NUM(FIELD_TYPE_STRING));
2729
+ #if MYSQL_VERSION_ID >= 40000
2730
+ rb_define_const(cMysqlField, "TYPE_VAR_STRING", INT2NUM(FIELD_TYPE_VAR_STRING));
2731
+ #endif
2732
+ rb_define_const(cMysqlField, "TYPE_CHAR", INT2NUM(FIELD_TYPE_CHAR));
2733
+
2734
+ /* Mysql::Field constant: FLAG */
2735
+ rb_define_const(cMysqlField, "NOT_NULL_FLAG", INT2NUM(NOT_NULL_FLAG));
2736
+ rb_define_const(cMysqlField, "PRI_KEY_FLAG", INT2NUM(PRI_KEY_FLAG));
2737
+ rb_define_const(cMysqlField, "UNIQUE_KEY_FLAG", INT2NUM(UNIQUE_KEY_FLAG));
2738
+ rb_define_const(cMysqlField, "MULTIPLE_KEY_FLAG", INT2NUM(MULTIPLE_KEY_FLAG));
2739
+ rb_define_const(cMysqlField, "BLOB_FLAG", INT2NUM(BLOB_FLAG));
2740
+ rb_define_const(cMysqlField, "UNSIGNED_FLAG", INT2NUM(UNSIGNED_FLAG));
2741
+ rb_define_const(cMysqlField, "ZEROFILL_FLAG", INT2NUM(ZEROFILL_FLAG));
2742
+ rb_define_const(cMysqlField, "BINARY_FLAG", INT2NUM(BINARY_FLAG));
2743
+ #ifdef ENUM_FLAG
2744
+ rb_define_const(cMysqlField, "ENUM_FLAG", INT2NUM(ENUM_FLAG));
2745
+ #endif
2746
+ #ifdef AUTO_INCREMENT_FLAG
2747
+ rb_define_const(cMysqlField, "AUTO_INCREMENT_FLAG", INT2NUM(AUTO_INCREMENT_FLAG));
2748
+ #endif
2749
+ #ifdef TIMESTAMP_FLAG
2750
+ rb_define_const(cMysqlField, "TIMESTAMP_FLAG", INT2NUM(TIMESTAMP_FLAG));
2751
+ #endif
2752
+ #ifdef SET_FLAG
2753
+ rb_define_const(cMysqlField, "SET_FLAG", INT2NUM(SET_FLAG));
2754
+ #endif
2755
+ #ifdef NUM_FLAG
2756
+ rb_define_const(cMysqlField, "NUM_FLAG", INT2NUM(NUM_FLAG));
2757
+ #endif
2758
+ #ifdef PART_KEY_FLAG
2759
+ rb_define_const(cMysqlField, "PART_KEY_FLAG", INT2NUM(PART_KEY_FLAG));
2760
+ #endif
2761
+
2762
+ #if MYSQL_VERSION_ID >= 40102
2763
+ /* Mysql::Stmt object method */
2764
+ rb_define_method(cMysqlStmt, "affected_rows", stmt_affected_rows, 0);
2765
+ #if 0
2766
+ rb_define_method(cMysqlStmt, "attr_get", stmt_attr_get, 1);
2767
+ rb_define_method(cMysqlStmt, "attr_set", stmt_attr_set, 2);
2768
+ #endif
2769
+ rb_define_method(cMysqlStmt, "bind_result", stmt_bind_result, -1);
2770
+ rb_define_method(cMysqlStmt, "close", stmt_close, 0);
2771
+ rb_define_method(cMysqlStmt, "data_seek", stmt_data_seek, 1);
2772
+ rb_define_method(cMysqlStmt, "each", stmt_each, 0);
2773
+ rb_define_method(cMysqlStmt, "execute", stmt_execute, -1);
2774
+ rb_define_method(cMysqlStmt, "fetch", stmt_fetch, 0);
2775
+ rb_define_method(cMysqlStmt, "field_count", stmt_field_count, 0);
2776
+ rb_define_method(cMysqlStmt, "free_result", stmt_free_result, 0);
2777
+ rb_define_method(cMysqlStmt, "insert_id", stmt_insert_id, 0);
2778
+ rb_define_method(cMysqlStmt, "num_rows", stmt_num_rows, 0);
2779
+ rb_define_method(cMysqlStmt, "param_count", stmt_param_count, 0);
2780
+ rb_define_method(cMysqlStmt, "prepare", stmt_prepare, 1);
2781
+ #if 0
2782
+ rb_define_method(cMysqlStmt, "reset", stmt_reset, 0);
2783
+ #endif
2784
+ rb_define_method(cMysqlStmt, "result_metadata", stmt_result_metadata, 0);
2785
+ rb_define_method(cMysqlStmt, "row_seek", stmt_row_seek, 1);
2786
+ rb_define_method(cMysqlStmt, "row_tell", stmt_row_tell, 0);
2787
+ #if 0
2788
+ rb_define_method(cMysqlStmt, "send_long_data", stmt_send_long_data, 2);
2789
+ #endif
2790
+ rb_define_method(cMysqlStmt, "sqlstate", stmt_sqlstate, 0);
2791
+
2792
+ #if 0
2793
+ rb_define_const(cMysqlStmt, "ATTR_UPDATE_MAX_LENGTH", INT2NUM(STMT_ATTR_UPDATE_MAX_LENGTH));
2794
+ #endif
2795
+
2796
+ /* Mysql::Time object method */
2797
+ rb_define_method(cMysqlTime, "initialize", time_initialize, -1);
2798
+ rb_define_method(cMysqlTime, "inspect", time_inspect, 0);
2799
+ rb_define_method(cMysqlTime, "to_s", time_to_s, 0);
2800
+ rb_define_method(cMysqlTime, "year", time_get_year, 0);
2801
+ rb_define_method(cMysqlTime, "month", time_get_month, 0);
2802
+ rb_define_method(cMysqlTime, "day", time_get_day, 0);
2803
+ rb_define_method(cMysqlTime, "hour", time_get_hour, 0);
2804
+ rb_define_method(cMysqlTime, "minute", time_get_minute, 0);
2805
+ rb_define_method(cMysqlTime, "second", time_get_second, 0);
2806
+ rb_define_method(cMysqlTime, "neg", time_get_neg, 0);
2807
+ rb_define_method(cMysqlTime, "second_part", time_get_second_part, 0);
2808
+ rb_define_method(cMysqlTime, "year=", time_set_year, 1);
2809
+ rb_define_method(cMysqlTime, "month=", time_set_month, 1);
2810
+ rb_define_method(cMysqlTime, "day=", time_set_day, 1);
2811
+ rb_define_method(cMysqlTime, "hour=", time_set_hour, 1);
2812
+ rb_define_method(cMysqlTime, "minute=", time_set_minute, 1);
2813
+ rb_define_method(cMysqlTime, "second=", time_set_second, 1);
2814
+ rb_define_method(cMysqlTime, "neg=", time_set_neg, 1);
2815
+ rb_define_method(cMysqlTime, "second_part=", time_set_second_part, 1);
2816
+ rb_define_method(cMysqlTime, "==", time_equal, 1);
2817
+
2818
+ #endif
2819
+
2820
+ /* Mysql::Error object method */
2821
+ rb_define_method(eMysql, "error", error_error, 0);
2822
+ rb_define_method(eMysql, "errno", error_errno, 0);
2823
+ rb_define_method(eMysql, "sqlstate", error_sqlstate, 0);
2824
+
2825
+ /* Mysql::Error constant */
2826
+ #define rb_define_mysql_const(s) rb_define_const(eMysql, #s, INT2NUM(s))
2827
+ #include "error_const.h"
2828
+ }