cubrid 0.65 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (11) hide show
  1. data/README.rdoc +1 -1
  2. data/ext/build_cci.sh +19 -0
  3. data/ext/cci.bz2 +0 -0
  4. data/ext/conn.c +57 -39
  5. data/ext/cubrid.c +194 -197
  6. data/ext/cubrid.h +122 -98
  7. data/ext/error.c +151 -144
  8. data/ext/extconf.rb +52 -19
  9. data/ext/stmt.c +1012 -1019
  10. metadata +28 -31
  11. checksums.yaml +0 -7
@@ -31,23 +31,56 @@
31
31
  require 'mkmf'
32
32
  require 'rbconfig'
33
33
 
34
- if ENV["CUBRID"]
35
- cci_lib_path = ENV["CUBRID"] + "/lib"
36
- cci_inc_path = ENV["CUBRID"] + "/include"
37
-
38
- $INCFLAGS = ($INCFLAGS ? $INCFLAGS : "") + " -I" + cci_inc_path
39
-
40
- if !$LIBPATH
41
- $LIBPATH = []
42
- end
43
-
44
- $LIBPATH.push(cci_lib_path)
45
-
46
- if have_library("cascci", "cci_init")
47
- create_makefile("cubrid")
48
- else
49
- puts "cascci could not be found. Possibly you have not installed CUBRID Database yet."
50
- end
51
- else
52
- puts "$CUBRID_BROKER is not defined. Possibly you have not installed CUBRID Database yet."
34
+
35
+ if RUBY_PLATFORM.include?"linux"
36
+
37
+ if RUBY_PLATFORM.include?"64"
38
+ $os_type="x64"
39
+ else
40
+ $os_type="x86"
41
+ end
42
+
43
+ system("chmod +x build_cci.sh")
44
+ system("./build_cci.sh",$os_type)
45
+
46
+ cci_lib_path = "cci-src/cci/.libs/libcascci.a"
47
+ cci_base_inc_path = "./cci-src/src/base"
48
+ cci_cci_inc_path = "./cci-src/src/cci"
49
+ cci_broker_inc_path = "./cci-src/src/broker"
50
+
51
+ $INCFLAGS = ($INCFLAGS ? $INCFLAGS : "") + " -I" + cci_base_inc_path \
52
+ +" -I" + cci_cci_inc_path +" -I" + cci_broker_inc_path
53
+
54
+ if !$LIBPATH
55
+ $LIBPATH = []
56
+ end
57
+
58
+ $LIBPATH.push(cci_lib_path)
59
+
60
+ if have_library("supc++") and have_library("stdc++")
61
+ create_makefile("cubrid")
62
+ else
63
+ puts "your system can not support supc++ or stdc++,install failed."
64
+ end
65
+
66
+ else
67
+ if ENV["CUBRID"]
68
+ cci_lib_path = ENV["CUBRID"] + "\\lib"
69
+ cci_inc_path = ENV["CUBRID"] + "\\include"
70
+
71
+ $INCFLAGS = ($INCFLAGS ? $INCFLAGS : "") + " -I" + cci_inc_path
72
+
73
+ if !$LIBPATH
74
+ $LIBPATH = []
75
+ end
76
+
77
+ $LIBPATH.push(cci_lib_path)
78
+ if have_library("cascci", "cci_init")
79
+ create_makefile("cubrid")
80
+ else
81
+ puts "cascci could not be found.\nPlease check if CUBRID database is installed and if the $CUBRID environment variable is correctly set to the location where cubrid is installed."
82
+ end
83
+ else
84
+ puts "$CUBRID environment variable is not defined.\nPlease check that you have installed CUBRID database and if the $CUBRID environment variable is correctly set to the location where cubrid is installed."
85
+ end
53
86
  end
data/ext/stmt.c CHANGED
@@ -1,1019 +1,1012 @@
1
- /*
2
- * Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution.
3
- *
4
- * Redistribution and use in source and binary forms, with or without modification,
5
- * are permitted provided that the following conditions are met:
6
- *
7
- * - Redistributions of source code must retain the above copyright notice,
8
- * this list of conditions and the following disclaimer.
9
- *
10
- * - Redistributions in binary form must reproduce the above copyright notice,
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- *
14
- * - Neither the name of the <ORGANIZATION> nor the names of its contributors
15
- * may be used to endorse or promote products derived from this software without
16
- * specific prior written permission.
17
- *
18
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
- * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27
- * OF SUCH DAMAGE.
28
- *
29
- */
30
-
31
- #include "cubrid.h"
32
-
33
- extern VALUE cubrid_conn_end_tran(Connection *con, int type);
34
-
35
- extern VALUE cStatement, cOid;
36
-
37
- void
38
- cubrid_stmt_free(void *p)
39
- {
40
- free(p);
41
- }
42
-
43
- VALUE
44
- cubrid_stmt_new(Connection *con, char *sql, int option)
45
- {
46
- VALUE cursor;
47
- Statement *stmt;
48
- int handle, param_cnt;
49
- T_CCI_ERROR error;
50
-
51
- /* printf("%s\n", sql); */
52
-
53
- handle = cci_prepare(con->handle, sql, option, &error);
54
- if (handle < 0) {
55
- cubrid_handle_error(handle, &error);
56
- return Qnil;
57
- }
58
-
59
- param_cnt = cci_get_bind_num(handle);
60
- if (param_cnt < 0) {
61
- cubrid_handle_error(param_cnt, NULL);
62
- return Qnil;
63
- }
64
-
65
- cursor = Data_Make_Struct(cStatement, Statement, 0, cubrid_stmt_free, stmt);
66
- stmt->con = con;
67
- stmt->handle = handle;
68
- stmt->param_cnt = param_cnt;
69
- stmt->bound = 0;
70
-
71
- return cursor;
72
- }
73
-
74
- /* call-seq:
75
- * close() -> nil
76
- *
77
- * Statement를 종료합니다.
78
- */
79
- VALUE
80
- cubrid_stmt_close(VALUE self)
81
- {
82
- Statement *stmt;
83
-
84
- GET_STMT_STRUCT(self, stmt);
85
-
86
- if (stmt->handle) {
87
- cci_close_req_handle(stmt->handle);
88
- stmt->handle = 0;
89
- }
90
-
91
- return Qnil;
92
- }
93
-
94
- T_CCI_SET
95
- cubrid_stmt_make_set(VALUE data, int u_type) /* TODO: check if all item has same type */
96
- {
97
- int i, arr_size, res;
98
- T_CCI_SET set = NULL;
99
- void *val = NULL;
100
- int *ind;
101
-
102
- arr_size = RARRAY(data)->len;
103
- ind = ALLOCA_N(int, arr_size);
104
- if (ind == NULL) {
105
- rb_raise(rb_eNoMemError, "Not enough memory");
106
- return NULL;
107
- }
108
-
109
- switch (TYPE(rb_ary_entry(data, 0))) {
110
- case T_FIXNUM:
111
- case T_BIGNUM:
112
- {
113
- int *int_ary = ALLOCA_N(int, arr_size);
114
- if (int_ary == NULL) {
115
- rb_raise(rb_eNoMemError, "Not enough memory");
116
- return NULL;
117
- }
118
-
119
- for(i = 0; i < arr_size; i++) {
120
- if (NIL_P(rb_ary_entry(data, i))) {
121
- ind[i] = 1;
122
- }
123
- else {
124
- int_ary[i] = NUM2INT(rb_ary_entry(data, i));
125
- ind[i] = 0;
126
- }
127
- }
128
-
129
- if (u_type == CCI_U_TYPE_UNKNOWN) {
130
- u_type = CCI_U_TYPE_INT;
131
- }
132
- val = int_ary;
133
- }
134
- break;
135
- case T_FLOAT:
136
- {
137
- double *dbl_ary;
138
-
139
- dbl_ary = ALLOCA_N(double, arr_size);
140
- if (dbl_ary == NULL) {
141
- rb_raise(rb_eNoMemError, "Not enough memory");
142
- return NULL;
143
- }
144
-
145
- for(i = 0; i < arr_size; i++) {
146
- if (NIL_P(rb_ary_entry(data, i))) {
147
- ind[i] = 1;
148
- }
149
- else {
150
- dbl_ary[i] = NUM2DBL(rb_ary_entry(data, i));
151
- ind[i] = 0;
152
- }
153
- }
154
-
155
- if (u_type == CCI_U_TYPE_UNKNOWN) {
156
- u_type = CCI_U_TYPE_DOUBLE;
157
- }
158
- val = dbl_ary;
159
- }
160
- break;
161
- case T_STRING:
162
- {
163
- if (u_type == CCI_U_TYPE_BIT || u_type == CCI_U_TYPE_VARBIT) {
164
- T_CCI_BIT *bit_ary;
165
-
166
- bit_ary = ALLOCA_N(T_CCI_BIT, arr_size);
167
- if (bit_ary == NULL) {
168
- rb_raise(rb_eNoMemError, "Not enough memory");
169
- return NULL;
170
- }
171
-
172
- for(i = 0; i < arr_size; i++) {
173
- if (NIL_P(rb_ary_entry(data, i))) {
174
- ind[i] = 1;
175
- }
176
- else {
177
- bit_ary[i].size = RSTRING(rb_ary_entry(data, i))->len;
178
- bit_ary[i].buf = RSTRING(rb_ary_entry(data, i))->ptr;
179
- ind[i] = 0;
180
- }
181
- }
182
-
183
- val = bit_ary;
184
- } else {
185
- char **str_ary;
186
-
187
- str_ary = ALLOCA_N(char*, arr_size);
188
- if (str_ary == NULL) {
189
- rb_raise(rb_eNoMemError, "Not enough memory");
190
- return NULL;
191
- }
192
-
193
- for(i = 0; i < arr_size; i++) {
194
- if (NIL_P(rb_ary_entry(data, i))) {
195
- ind[i] = 1;
196
- }
197
- else {
198
- str_ary[i] = RSTRING(rb_ary_entry(data, i))->ptr;
199
- ind[i] = 0;
200
- }
201
- }
202
-
203
- if (u_type == CCI_U_TYPE_UNKNOWN) {
204
- u_type = CCI_U_TYPE_STRING;
205
- }
206
- val = str_ary;
207
- }
208
- }
209
- break;
210
- case T_DATA:
211
- if (CLASS_OF(rb_ary_entry(data, 0)) == rb_cTime) {
212
- VALUE a;
213
- T_CCI_DATE *date_ary;
214
-
215
- date_ary = ALLOCA_N(T_CCI_DATE, arr_size);
216
- if (date_ary == NULL) {
217
- rb_raise(rb_eNoMemError, "Not enough memory");
218
- return NULL;
219
- }
220
-
221
- for(i = 0; i < arr_size; i++) {
222
- if (NIL_P(rb_ary_entry(data, i))) {
223
- ind[i] = 1;
224
- }
225
- else {
226
- a = rb_funcall(rb_ary_entry(data, i), rb_intern("to_a"), 0);
227
- date_ary[i].ss = FIX2INT(RARRAY(a)->ptr[0]);
228
- date_ary[i].mm = FIX2INT(RARRAY(a)->ptr[1]);
229
- date_ary[i].hh = FIX2INT(RARRAY(a)->ptr[2]);
230
- date_ary[i].day = FIX2INT(RARRAY(a)->ptr[3]);
231
- date_ary[i].mon = FIX2INT(RARRAY(a)->ptr[4]);
232
- date_ary[i].yr = FIX2INT(RARRAY(a)->ptr[5]);
233
-
234
- ind[i] = 0;
235
- }
236
- }
237
-
238
- if (u_type == CCI_U_TYPE_UNKNOWN) {
239
- u_type = CCI_U_TYPE_TIMESTAMP;
240
- }
241
- val = date_ary;
242
- } else if (CLASS_OF(rb_ary_entry(data, 0)) == cOid) {
243
- char **str_ary;
244
- Oid *oid;
245
-
246
- str_ary = ALLOCA_N(char*, arr_size);
247
- if (str_ary == NULL) {
248
- rb_raise(rb_eNoMemError, "Not enough memory");
249
- return NULL;
250
- }
251
-
252
- for(i = 0; i < arr_size; i++) {
253
- if (NIL_P(rb_ary_entry(data, i))) {
254
- ind[i] = 1;
255
- }
256
- else {
257
- Data_Get_Struct(rb_ary_entry(data, i), Oid, oid);
258
- str_ary[i] = oid->oid_str;
259
- ind[i] = 0;
260
- }
261
- }
262
-
263
- if (u_type == CCI_U_TYPE_UNKNOWN) {
264
- u_type = CCI_U_TYPE_OBJECT;
265
- }
266
- val = str_ary;
267
- }
268
- break;
269
- default:
270
- rb_raise(rb_eArgError, "Wrong data type");
271
- break;
272
- }
273
-
274
- res = cci_set_make(&set, u_type, arr_size, val, ind);
275
- if (res < 0) {
276
- cubrid_handle_error(res, NULL);
277
- return NULL;
278
- }
279
-
280
- return set;
281
- }
282
-
283
- static void
284
- cubrid_stmt_bind_internal(Statement *stmt, int index, VALUE data, int u_type, int set_type)
285
- {
286
- int res, int_val, a_type = CCI_A_TYPE_STR;
287
- char *str_val;
288
- double dbl_val;
289
- void *val = NULL;
290
- T_CCI_SET set = NULL;
291
- T_CCI_DATE date;
292
- T_CCI_BIT bit;
293
-
294
- switch (TYPE(data)) {
295
- case T_NIL:
296
- a_type = CCI_A_TYPE_STR;
297
- val = NULL;
298
- u_type = CCI_U_TYPE_NULL;
299
- break;
300
-
301
- case T_FIXNUM:
302
- case T_BIGNUM:
303
- int_val = NUM2INT(data);
304
- a_type = CCI_A_TYPE_INT;
305
- val = &int_val;
306
- if (u_type == CCI_U_TYPE_UNKNOWN) {
307
- u_type = CCI_U_TYPE_INT;
308
- }
309
- break;
310
-
311
- case T_FLOAT:
312
- dbl_val = NUM2DBL(data);
313
- a_type = CCI_A_TYPE_DOUBLE;
314
- val = &dbl_val;
315
- if (u_type == CCI_U_TYPE_UNKNOWN) {
316
- u_type = CCI_U_TYPE_DOUBLE;
317
- }
318
- break;
319
-
320
- case T_STRING:
321
- str_val = RSTRING(data)->ptr;
322
- a_type = CCI_A_TYPE_STR;
323
- val = str_val;
324
- if (u_type == CCI_U_TYPE_UNKNOWN) {
325
- u_type = CCI_U_TYPE_STRING;
326
- } else if (u_type == CCI_U_TYPE_BIT || u_type == CCI_U_TYPE_VARBIT) {
327
- bit.size = RSTRING(data)->len;
328
- bit.buf = str_val;
329
- a_type = CCI_A_TYPE_BIT;
330
- val = &bit;
331
- }
332
- break;
333
-
334
- case T_DATA:
335
- if (CLASS_OF(data) == rb_cTime) {
336
- VALUE a;
337
-
338
- a = rb_funcall(data, rb_intern("to_a"), 0);
339
- date.ss = FIX2INT(RARRAY(a)->ptr[0]);
340
- date.mm = FIX2INT(RARRAY(a)->ptr[1]);
341
- date.hh = FIX2INT(RARRAY(a)->ptr[2]);
342
- date.day = FIX2INT(RARRAY(a)->ptr[3]);
343
- date.mon = FIX2INT(RARRAY(a)->ptr[4]);
344
- date.yr = FIX2INT(RARRAY(a)->ptr[5]);
345
-
346
- a_type = CCI_A_TYPE_DATE;
347
- val = &date;
348
- if (u_type == CCI_U_TYPE_UNKNOWN) {
349
- u_type = CCI_U_TYPE_TIMESTAMP;
350
- }
351
- } else if (CLASS_OF(data) == cOid) {
352
- Oid *oid;
353
-
354
- Data_Get_Struct(data, Oid, oid);
355
- a_type = CCI_A_TYPE_STR;
356
- val = oid->oid_str;
357
- if (u_type == CCI_U_TYPE_UNKNOWN) {
358
- u_type = CCI_U_TYPE_OBJECT;
359
- }
360
- }
361
- break;
362
-
363
- case T_ARRAY:
364
- set = cubrid_stmt_make_set(data, set_type);
365
- a_type = CCI_A_TYPE_SET;
366
- val = set;
367
- if (u_type == CCI_U_TYPE_UNKNOWN) {
368
- u_type = CCI_U_TYPE_SET;
369
- }
370
- break;
371
-
372
- default:
373
- rb_raise(rb_eArgError, "Wrong data type");
374
- return;
375
- }
376
-
377
- res = cci_bind_param(stmt->handle, index, a_type, val, u_type, 0);
378
-
379
- if (TYPE(data) == T_ARRAY && set) {
380
- cci_set_free(set);
381
- }
382
-
383
- if (res < 0) {
384
- cubrid_handle_error(res, NULL);
385
- return;
386
- }
387
-
388
- return;
389
- }
390
-
391
- /* call-seq:
392
- * bind(index, data <, db_type, set_type>) -> nil
393
- *
394
- * prepare된 Statement의 호스트변수에 데이터를 바인딩합니다.
395
- * db_type은 ruby의 데이터가 바인딩될 때 적용될 데이터베이스의 타입을 지정합니다.
396
- * db_type이 주어지지 않으면 아래와 같이 기본 타입으로 적용됩니다.
397
- *
398
- * *fixnum, bignum -> integer
399
- * *float -> double
400
- * *string -> string(varchar)
401
- * *Time -> timestamp
402
- * *Oid -> object
403
- * *array -> collection
404
- *
405
- * set_type은 data가 배열인 경우 배열의 원소에 적용될 데이터베이스 타입을 지정합니다.
406
- * 배열의 모든 원소들은 동일한 타입이어야 합니다.
407
- * set_type이 주어지지 않으면 배열의 원소들은 기본 타입으로 바인딩됩니다.
408
- *
409
- * con = Cubrid.connect('demodb')
410
- * con.auto_commit = true
411
- * con.query('create table a (a int, b double, c string, d date)')
412
- * con.prepare('insert into a values (?, ?, ?, ?)') { |stmt|
413
- * stmt.bind(1, 10)
414
- * stmt.bind(2, 3.141592)
415
- * stmt.bind(3, 'hello')
416
- * stmt.bind(4, Time.local(2007, 12, 25, 10, 10, 10), CUBRID::DATE)
417
- * stmt.execute
418
- * }
419
- * con.close
420
- */
421
- VALUE
422
- cubrid_stmt_bind(int argc, VALUE* argv, VALUE self)
423
- {
424
- Statement *stmt;
425
- VALUE index, u_type, data, set_type;
426
-
427
- GET_STMT_STRUCT(self, stmt);
428
- CHECK_HANDLE(stmt, self);
429
-
430
- rb_scan_args(argc, argv, "22", &index, &data, &u_type, &set_type);
431
-
432
- if (NIL_P(u_type)) {
433
- u_type = INT2NUM(CCI_U_TYPE_UNKNOWN);
434
- }
435
-
436
- if (NIL_P(set_type)) {
437
- set_type = INT2NUM(CCI_U_TYPE_UNKNOWN);
438
- }
439
-
440
- cubrid_stmt_bind_internal(stmt, NUM2INT(index), data, NUM2INT(u_type), NUM2INT(set_type));
441
- stmt->bound = 1;
442
-
443
- return Qnil;
444
- }
445
-
446
- static int
447
- cubrid_stmt_is_auto_commitable(T_CCI_SQLX_CMD cmd)
448
- {
449
- switch(cmd) {
450
- case SQLX_CMD_SELECT:
451
- case SQLX_CMD_CALL:
452
- case SQLX_CMD_CALL_SP:
453
- case SQLX_CMD_COMMIT_WORK:
454
- case SQLX_CMD_ROLLBACK_WORK:
455
- case SQLX_CMD_GET_ISO_LVL:
456
- case SQLX_CMD_GET_TIMEOUT:
457
- case SQLX_CMD_GET_OPT_LVL:
458
- case SQLX_CMD_GET_TRIGGER:
459
- case SQLX_CMD_SAVEPOINT:
460
- case SQLX_CMD_GET_LDB:
461
- case SQLX_CMD_GET_STATS:
462
- return 0;
463
- }
464
-
465
- return 1;
466
- }
467
-
468
- /* call-seq:
469
- * execute() -> int
470
- * execute(...) -> int
471
- *
472
- * prepare된 Statement를 실행하고 검색되거나 영향을 받은 row의 개수를 반환합니다.
473
- *
474
- * 인수가 주어지면 prepare된 Statement의 호스트 변수에 데이터를 바인딩합니다.
475
- * 인수는 순서대로 호스트 변수에 바인딩 되기 때문에 인수의 개수와 호스트 변수의 개수가 일치해야 합니다.
476
- * 인수는 묵시적으로 기본 타입으로 바인딩 됩니다.
477
- *
478
- * connection의 auto commit 모드가 true이면 commit이 곧바로 수행됩니다.
479
- *
480
- * con = Cubrid.connect('demodb')
481
- * con.prepare('insert into a values (?, ?, ?, ?)') { |stmt|
482
- * stmt.execute (10, 3.141592, 'hello', Time.local(2007, 12, 25))
483
- * }
484
- * con.close
485
- */
486
- VALUE
487
- cubrid_stmt_execute(int argc, VALUE* argv, VALUE self)
488
- {
489
- T_CCI_ERROR error;
490
- T_CCI_COL_INFO *res_col_info;
491
- T_CCI_SQLX_CMD res_sql_type;
492
- int res_col_count, row_count;
493
- Statement *stmt;
494
-
495
- GET_STMT_STRUCT(self, stmt);
496
- CHECK_HANDLE(stmt, self);
497
-
498
- if (!stmt->bound && stmt->param_cnt != argc) {
499
- rb_raise(rb_eStandardError, "execute: param_count(%d) != number of argument(%d)",
500
- stmt->param_cnt, argc);
501
- return INT2NUM(0);
502
- }
503
-
504
- if (argc > 0) {
505
- int i;
506
- for (i = 0; i < argc; i++) {
507
- cubrid_stmt_bind_internal(stmt, i + 1, argv[i], CCI_U_TYPE_UNKNOWN, CCI_U_TYPE_UNKNOWN);
508
- }
509
- }
510
-
511
- row_count = cci_execute(stmt->handle, 0, 0, &error);
512
- if (row_count < 0) {
513
- cubrid_handle_error(row_count, &error);
514
- return INT2NUM(0);
515
- }
516
-
517
- res_col_info = cci_get_result_info(stmt->handle, &res_sql_type, &res_col_count);
518
- if (res_sql_type == SQLX_CMD_SELECT && !res_col_info) {
519
- cubrid_handle_error(CUBRID_ER_CANNOT_GET_COLUMN_INFO, &error);
520
- return INT2NUM(0);
521
- }
522
-
523
- stmt->col_info = res_col_info;
524
- stmt->sql_type = res_sql_type;
525
- stmt->col_count = res_col_count;
526
- stmt->affected_rows = row_count;
527
-
528
- if(stmt->con->auto_commit == Qtrue && cubrid_stmt_is_auto_commitable(stmt->sql_type)) {
529
- cubrid_stmt_close(self);
530
- cubrid_conn_end_tran(stmt->con, CCI_TRAN_COMMIT);
531
- }
532
-
533
- stmt->bound = 0;
534
- return INT2NUM(row_count);
535
- }
536
-
537
- /* call-seq:
538
- * affected_rows() -> int
539
- *
540
- * 수행된 SQL로 영향을 받았거나 검색된 row의 개수를 반환합니다.
541
- */
542
- VALUE
543
- cubrid_stmt_affected_rows(VALUE self)
544
- {
545
- Statement *stmt;
546
-
547
- GET_STMT_STRUCT(self, stmt);
548
- CHECK_HANDLE(stmt, self);
549
-
550
- return INT2NUM(stmt->affected_rows);
551
- }
552
-
553
- static VALUE
554
- cubrid_stmt_dbval_to_ruby_value(int req_handle, int type, int index, Connection *con)
555
- {
556
- int res, ind;
557
- VALUE val;
558
- char *res_buf;
559
- int int_val;
560
- double double_val;
561
- T_CCI_DATE date;
562
- T_CCI_BIT bit;
563
-
564
- switch (type) {
565
- case CCI_U_TYPE_INT:
566
- case CCI_U_TYPE_SHORT:
567
- res = cci_get_data(req_handle, index, CCI_A_TYPE_INT, &int_val, &ind);
568
- if (res < 0) {
569
- cubrid_handle_error(res, NULL);
570
- return Qnil;
571
- }
572
- if (ind < 0) {
573
- val = Qnil;
574
- } else {
575
- val = INT2NUM(int_val);
576
- }
577
- break;
578
-
579
- case CCI_U_TYPE_FLOAT:
580
- case CCI_U_TYPE_DOUBLE:
581
- case CCI_U_TYPE_NUMERIC:
582
- case CCI_U_TYPE_MONETARY:
583
- res = cci_get_data(req_handle, index, CCI_A_TYPE_STR, &res_buf, &ind);
584
- if (res < 0) {
585
- cubrid_handle_error(res, NULL);
586
- return Qnil;
587
- }
588
- if (ind < 0) {
589
- val = Qnil;
590
- } else {
591
- double_val = atof(res_buf);
592
- val = rb_float_new(double_val);
593
- }
594
- break;
595
-
596
- case CCI_U_TYPE_DATE:
597
- case CCI_U_TYPE_TIME:
598
- case CCI_U_TYPE_TIMESTAMP:
599
- res = cci_get_data(req_handle, index, CCI_A_TYPE_DATE, &date, &ind);
600
- if (res < 0) {
601
- cubrid_handle_error(res, NULL);
602
- return Qnil;
603
- }
604
- if (ind < 0) {
605
- val = Qnil;
606
- } else {
607
- if (type == CCI_U_TYPE_DATE) {
608
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 3,
609
- INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day));
610
- } else if (type == CCI_U_TYPE_TIME) {
611
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
612
- INT2NUM(1970), INT2NUM(1), INT2NUM(1),
613
- INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
614
- } else {
615
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
616
- INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day),
617
- INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
618
- }
619
- }
620
- break;
621
-
622
- case CCI_U_TYPE_BIT:
623
- case CCI_U_TYPE_VARBIT:
624
- res = cci_get_data(req_handle, index, CCI_A_TYPE_BIT, &bit, &ind);
625
- if (res < 0) {
626
- cubrid_handle_error(res, NULL);
627
- return Qnil;
628
- }
629
- if (ind < 0) {
630
- val = Qnil;
631
- } else {
632
- val = rb_tainted_str_new(bit.buf, bit.size);
633
- }
634
- break;
635
-
636
- default:
637
- res = cci_get_data(req_handle, index, CCI_A_TYPE_STR, &res_buf, &ind);
638
- if (res < 0) {
639
- cubrid_handle_error(res, NULL);
640
- return Qnil;
641
- }
642
- if (ind < 0) {
643
- val = Qnil;
644
- } else {
645
- val = rb_str_new2(res_buf);
646
- }
647
- break;
648
- }
649
-
650
- return val;
651
- }
652
-
653
- static VALUE
654
- cubrid_stmt_dbval_to_ruby_value_from_set(T_CCI_SET set, int type, int index, Connection *con)
655
- {
656
- int res, ind;
657
- VALUE val;
658
- char *res_buf;
659
- int int_val;
660
- double double_val;
661
- T_CCI_DATE date;
662
- T_CCI_BIT bit;
663
-
664
- switch (type) {
665
- case CCI_U_TYPE_INT:
666
- case CCI_U_TYPE_SHORT:
667
- res = cci_set_get(set, index, CCI_A_TYPE_INT, &int_val, &ind);
668
- if (res < 0) {
669
- cubrid_handle_error(res, NULL);
670
- return Qnil;
671
- }
672
- if (ind < 0) {
673
- val = Qnil;
674
- } else {
675
- val = INT2NUM(int_val);
676
- }
677
- break;
678
-
679
- case CCI_U_TYPE_FLOAT:
680
- case CCI_U_TYPE_DOUBLE:
681
- case CCI_U_TYPE_NUMERIC:
682
- case CCI_U_TYPE_MONETARY:
683
- res = cci_set_get(set, index, CCI_A_TYPE_STR, &res_buf, &ind);
684
- if (res < 0) {
685
- cubrid_handle_error(res, NULL);
686
- return Qnil;
687
- }
688
- if (ind < 0) {
689
- val = Qnil;
690
- } else {
691
- double_val = atof(res_buf);
692
- val = rb_float_new(double_val);
693
- }
694
- break;
695
-
696
- case CCI_U_TYPE_DATE:
697
- case CCI_U_TYPE_TIME:
698
- case CCI_U_TYPE_TIMESTAMP:
699
- res = cci_set_get(set, index, CCI_A_TYPE_DATE, &date, &ind);
700
- if (res < 0) {
701
- cubrid_handle_error(res, NULL);
702
- return Qnil;
703
- }
704
- if (ind < 0) {
705
- val = Qnil;
706
- } else {
707
- if (type == CCI_U_TYPE_DATE) {
708
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 3,
709
- INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day));
710
- } else if (type == CCI_U_TYPE_TIME) {
711
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
712
- INT2NUM(1970), INT2NUM(1), INT2NUM(1),
713
- INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
714
- } else {
715
- val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
716
- INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day),
717
- INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
718
- }
719
- }
720
- break;
721
-
722
- case CCI_U_TYPE_BIT:
723
- case CCI_U_TYPE_VARBIT:
724
- res = cci_set_get(set, index, CCI_A_TYPE_BIT, &bit, &ind);
725
- if (res < 0) {
726
- cubrid_handle_error(res, NULL);
727
- return Qnil;
728
- }
729
- if (ind < 0) {
730
- val = Qnil;
731
- } else {
732
- val = rb_tainted_str_new(bit.buf, bit.size);
733
- }
734
- break;
735
-
736
- default:
737
- res = cci_set_get(set, index, CCI_A_TYPE_STR, &res_buf, &ind);
738
- if (res < 0) {
739
- cubrid_handle_error(res, NULL);
740
- return Qnil;
741
- }
742
- if (ind < 0) {
743
- val = Qnil;
744
- } else {
745
- val = rb_str_new2(res_buf);
746
- }
747
- break;
748
- }
749
-
750
- return val;
751
- }
752
-
753
- static VALUE
754
- cubrid_stmt_dbset_to_ruby_value(int req_handle, int index, Connection *con)
755
- {
756
- int i, res, ind, e_type;
757
- VALUE val, e;
758
- T_CCI_SET set = NULL;
759
- int set_size;
760
-
761
- res = cci_get_data(req_handle, index, CCI_A_TYPE_SET, &set, &ind);
762
- if (res < 0) {
763
- cubrid_handle_error(res, NULL);
764
- return Qnil;
765
- }
766
-
767
- if (set == NULL)
768
- return Qnil;
769
-
770
- set_size = cci_set_size(set);
771
- val = rb_ary_new2(set_size);
772
-
773
- e_type = cci_set_element_type(set);
774
-
775
- for (i = 0; i < set_size; i++) {
776
- e = cubrid_stmt_dbval_to_ruby_value_from_set(set, e_type, i + 1, con);
777
- rb_ary_push(val, e);
778
- }
779
- cci_set_free(set);
780
-
781
- return val;
782
- }
783
-
784
- VALUE
785
- cubrid_stmt_fetch_one_row(int req_handle, int col_count, T_CCI_COL_INFO *col_info, Connection *con)
786
- {
787
- int i, type;
788
- VALUE row, val;
789
-
790
- row = rb_ary_new();
791
-
792
- for (i = 0; i < col_count; i++) {
793
- type = CCI_GET_RESULT_INFO_TYPE(col_info, i + 1);
794
-
795
- if (CCI_IS_COLLECTION_TYPE(type)) {
796
- val = cubrid_stmt_dbset_to_ruby_value(req_handle, i + 1, con);
797
- } else {
798
- val = cubrid_stmt_dbval_to_ruby_value(req_handle, type, i + 1, con);
799
- }
800
-
801
- rb_ary_push(row, val);
802
- }
803
-
804
- return row;
805
- }
806
-
807
- /* call-seq:
808
- * fetch() -> array or nil
809
- *
810
- * 검색된 결과에서 현재 커서가 위치한 row를 반환하고 커서의 위치를 다음으로 옮깁니다.
811
- * row의 column들은 배열에 저장되어 반환됩니다.
812
- * 이상 fetch할 row가 없으면 nil을 반환합니다.
813
- *
814
- * con = Cubrid.connect('demodb')
815
- * con.prepare('SELECT * FROM db_user') { |stmt|
816
- * stmt.execute
817
- * r = stmt.fetch
818
- * print r[0]
819
- * }
820
- * con.close
821
- *
822
- * 데이터베이스의 타입은 아래와 같이 루비의 타입으로 대응됩니다.
823
- *
824
- * *int, short -> fixnum, bignum
825
- * *float, double, numeric, monetary -> float
826
- * *char, varchar, ncahr, varnchar -> string
827
- * *bit, varbit -> string
828
- * *date, time, timestamp -> Time
829
- * *object -> Oid
830
- * *collection -> array
831
- *
832
- */
833
- VALUE
834
- cubrid_stmt_fetch(VALUE self)
835
- {
836
- int res;
837
- T_CCI_ERROR error;
838
- Statement *stmt;
839
-
840
- GET_STMT_STRUCT(self, stmt);
841
- CHECK_HANDLE(stmt, self);
842
-
843
- res = cci_cursor(stmt->handle, 1, CCI_CURSOR_CURRENT, &error);
844
- if (res == CCI_ER_NO_MORE_DATA) {
845
- return Qnil;
846
- } else if (res < 0) {
847
- cubrid_handle_error(res, &error);
848
- return Qnil;
849
- }
850
-
851
- res = cci_fetch(stmt->handle, &error);
852
- if (res < 0) {
853
- cubrid_handle_error(res, &error);
854
- return Qnil;
855
- }
856
-
857
- return cubrid_stmt_fetch_one_row(stmt->handle, stmt->col_count, stmt->col_info, stmt->con);
858
- }
859
-
860
- /* call-seq:
861
- * fetch_hash() -> hash or nil
862
- *
863
- * 검색된 결과에서 현재 커서가 위치한 row를 반환하고 커서의 위치를 다음으로 옮깁니다.
864
- * row의 column들은 hash에 저장되어 반환됩니다.
865
- * hash의 key는 column 이름이거나 SELECT 문에 주어진 alias 입니다.
866
- * 더 이상 fetch할 row가 없으면 nil을 반환합니다.
867
- *
868
- * con = Cubrid.connect('demodb')
869
- * con.prepare('SELECT * FROM db_user') { |stmt|
870
- * stmt.execute
871
- * r = stmt.fetch_hash
872
- * print r['name']
873
- * }
874
- * con.close
875
- */
876
- VALUE
877
- cubrid_stmt_fetch_hash(VALUE self)
878
- {
879
- VALUE row, col, hash;
880
- int i;
881
- char colName[128];
882
- Statement *stmt;
883
-
884
- GET_STMT_STRUCT(self, stmt);
885
- CHECK_HANDLE(stmt, self);
886
-
887
- row = cubrid_stmt_fetch(self);
888
- if (NIL_P(row))
889
- return Qnil;
890
-
891
- hash = rb_hash_new();
892
- for(i = 0; i < stmt->col_count; i++) {
893
- col = RARRAY(row)->ptr[i];
894
- strcpy(colName, CCI_GET_RESULT_INFO_NAME(stmt->col_info, i+1));
895
- rb_hash_aset(hash, rb_str_new2(colName), col);
896
- }
897
-
898
- return hash;
899
- }
900
-
901
- /* call-seq:
902
- * each() { |row| block } -> nil
903
- *
904
- * row를 fetch하여 주어진 block에 전달하여 수행시킵니다. 전달되는 row는 array입니다.
905
- * block은 row fetch될 때마다 수행됩니다.
906
- *
907
- * con = Cubrid.connect('demodb')
908
- * con.prepare('SELECT * FROM db_user') { |stmt|
909
- * stmt.execute
910
- * stmt.each { |r|
911
- * print r[0]
912
- * }
913
- * }
914
- * con.close
915
- */
916
- VALUE
917
- cubrid_stmt_each(VALUE self)
918
- {
919
- VALUE row;
920
-
921
- while(1) {
922
- row = cubrid_stmt_fetch(self);
923
- if (NIL_P(row)) {
924
- break;
925
- }
926
- rb_yield(row);
927
- }
928
-
929
- return Qnil;
930
- }
931
-
932
- /* call-seq:
933
- * each_hash() { |hash| block } -> nil
934
- *
935
- * row를 fetch하여 주어진 block에 전달하여 수행시킵니다. 전달되는 row는 hash입니다.
936
- * block은 row가 fetch될 때마다 수행됩니다.
937
- *
938
- * con = Cubrid.connect('demodb')
939
- * con.prepare('SELECT * FROM db_user') { |stmt|
940
- * stmt.execute
941
- * stmt.each_hash { |r|
942
- * print r['name']
943
- * }
944
- * }
945
- * con.close
946
- */
947
- VALUE
948
- cubrid_stmt_each_hash(VALUE self)
949
- {
950
- VALUE row;
951
-
952
- while(1) {
953
- row = cubrid_stmt_fetch_hash(self);
954
- if (NIL_P(row)) {
955
- break;
956
- }
957
- rb_yield(row);
958
- }
959
-
960
- return Qnil;
961
- }
962
-
963
- /* call-seq:
964
- * column_info() -> array
965
- *
966
- * fetch 될 row의 column 정보를 반환합니다.
967
- * 한 컬럼의 정보가 hash로 구성되기 때문에, 결국 전체 컬럼 정보는 hash를 저장하고 있는 array로 반환됩니다.
968
- * hash의 key는 name, type_name, precision, scale, nullable 이며,
969
- * 각각 컬럼 이름, 컬럼의 데이터 타입, 정밀도, 스케일, 널가능 여부를 의미합니다.
970
- *
971
- * con = Cubrid.connect('demodb')
972
- * con.prepare('SELECT * FROM db_user') { |stmt|
973
- * stmt.column_info.each { |col|
974
- * print col['name']
975
- * print col['type_name']
976
- * print col['precision']
977
- * print col['scale']
978
- * print col['nullable']
979
- * }
980
- * }
981
- * con.close
982
- */
983
- VALUE
984
- cubrid_stmt_column_info(VALUE self)
985
- {
986
- VALUE desc;
987
- int i;
988
- char col_name[MAX_STR_LEN];
989
- int datatype, precision, scale, nullable;
990
- Statement *stmt;
991
-
992
- GET_STMT_STRUCT(self, stmt);
993
- CHECK_HANDLE(stmt, self);
994
-
995
- desc = rb_ary_new2(stmt->col_count);
996
-
997
- for (i = 0; i < stmt->col_count; i++) {
998
- VALUE item;
999
-
1000
- item = rb_hash_new();
1001
-
1002
- strcpy(col_name, CCI_GET_RESULT_INFO_NAME(stmt->col_info, i+1));
1003
- precision = CCI_GET_RESULT_INFO_PRECISION(stmt->col_info, i+1);
1004
- scale = CCI_GET_RESULT_INFO_SCALE(stmt->col_info, i+1);
1005
- nullable = CCI_GET_RESULT_INFO_IS_NON_NULL(stmt->col_info, i+1);
1006
- datatype = CCI_GET_RESULT_INFO_TYPE(stmt->col_info, i+1);
1007
-
1008
- rb_hash_aset(item, rb_str_new2("name"), rb_str_new2(col_name));
1009
- rb_hash_aset(item, rb_str_new2("type_name"), INT2NUM(datatype));
1010
- rb_hash_aset(item, rb_str_new2("precision"), INT2NUM(precision));
1011
- rb_hash_aset(item, rb_str_new2("scale"), INT2NUM(scale));
1012
- rb_hash_aset(item, rb_str_new2("nullable"), INT2NUM(nullable));
1013
-
1014
- rb_ary_push(desc, item);
1015
- }
1016
-
1017
- return desc;
1018
- }
1019
-
1
+ /*
2
+ * Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without modification,
5
+ * are permitted provided that the following conditions are met:
6
+ *
7
+ * - Redistributions of source code must retain the above copyright notice,
8
+ * this list of conditions and the following disclaimer.
9
+ *
10
+ * - Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the documentation
12
+ * and/or other materials provided with the distribution.
13
+ *
14
+ * - Neither the name of the <ORGANIZATION> nor the names of its contributors
15
+ * may be used to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27
+ * OF SUCH DAMAGE.
28
+ *
29
+ */
30
+
31
+ #include "cubrid.h"
32
+
33
+ extern VALUE cubrid_conn_end_tran(Connection *con, int type);
34
+
35
+ extern VALUE cStatement, cOid;
36
+
37
+ void
38
+ cubrid_stmt_free(void *p)
39
+ {
40
+ free(p);
41
+ }
42
+
43
+ VALUE
44
+ cubrid_stmt_new(Connection *con, char *sql, int option)
45
+ {
46
+ VALUE cursor;
47
+ Statement *stmt;
48
+ int handle, param_cnt;
49
+ T_CCI_ERROR error;
50
+
51
+ /* printf("%s\n", sql); */
52
+
53
+ handle = cci_prepare(con->handle, sql, option, &error);
54
+ if (handle < 0) {
55
+ cubrid_handle_error(handle, &error);
56
+ return Qnil;
57
+ }
58
+
59
+ param_cnt = cci_get_bind_num(handle);
60
+ if (param_cnt < 0) {
61
+ cubrid_handle_error(param_cnt, NULL);
62
+ return Qnil;
63
+ }
64
+
65
+ cursor = Data_Make_Struct(cStatement, Statement, 0, cubrid_stmt_free, stmt);
66
+ stmt->con = con;
67
+ stmt->handle = handle;
68
+ stmt->param_cnt = param_cnt;
69
+ stmt->bound = 0;
70
+
71
+ return cursor;
72
+ }
73
+
74
+ /* call-seq:
75
+ * close() -> nil
76
+ */
77
+ VALUE
78
+ cubrid_stmt_close(VALUE self)
79
+ {
80
+ Statement *stmt;
81
+
82
+ GET_STMT_STRUCT(self, stmt);
83
+
84
+ if (stmt->handle) {
85
+ cci_close_req_handle(stmt->handle);
86
+ stmt->handle = 0;
87
+ }
88
+
89
+ return Qnil;
90
+ }
91
+
92
+ T_CCI_SET
93
+ cubrid_stmt_make_set(VALUE data, int u_type) /* TODO: check if all item has same type */
94
+ {
95
+ int i, arr_size, res;
96
+ T_CCI_SET set = NULL;
97
+ void *val = NULL;
98
+ int *ind;
99
+
100
+ arr_size = RARRAY_LEN(data);//RARRAY(data)->len;
101
+ ind = ALLOCA_N(int, arr_size);
102
+ if (ind == NULL) {
103
+ rb_raise(rb_eNoMemError, "Not enough memory");
104
+ return NULL;
105
+ }
106
+
107
+ switch (TYPE(rb_ary_entry(data, 0))) {
108
+ case T_FIXNUM:
109
+ case T_BIGNUM:
110
+ {
111
+ int *int_ary = ALLOCA_N(int, arr_size);
112
+ if (int_ary == NULL) {
113
+ rb_raise(rb_eNoMemError, "Not enough memory");
114
+ return NULL;
115
+ }
116
+
117
+ for(i = 0; i < arr_size; i++) {
118
+ if (NIL_P(rb_ary_entry(data, i))) {
119
+ ind[i] = 1;
120
+ }
121
+ else {
122
+ int_ary[i] = NUM2INT(rb_ary_entry(data, i));
123
+ ind[i] = 0;
124
+ }
125
+ }
126
+
127
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
128
+ u_type = CCI_U_TYPE_INT;
129
+ }
130
+ val = int_ary;
131
+ }
132
+ break;
133
+ case T_FLOAT:
134
+ {
135
+ double *dbl_ary;
136
+
137
+ dbl_ary = ALLOCA_N(double, arr_size);
138
+ if (dbl_ary == NULL) {
139
+ rb_raise(rb_eNoMemError, "Not enough memory");
140
+ return NULL;
141
+ }
142
+
143
+ for(i = 0; i < arr_size; i++) {
144
+ if (NIL_P(rb_ary_entry(data, i))) {
145
+ ind[i] = 1;
146
+ }
147
+ else {
148
+ dbl_ary[i] = NUM2DBL(rb_ary_entry(data, i));
149
+ ind[i] = 0;
150
+ }
151
+ }
152
+
153
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
154
+ u_type = CCI_U_TYPE_DOUBLE;
155
+ }
156
+ val = dbl_ary;
157
+ }
158
+ break;
159
+ case T_STRING:
160
+ {
161
+ if (u_type == CCI_U_TYPE_BIT || u_type == CCI_U_TYPE_VARBIT) {
162
+ T_CCI_BIT *bit_ary;
163
+
164
+ bit_ary = ALLOCA_N(T_CCI_BIT, arr_size);
165
+ if (bit_ary == NULL) {
166
+ rb_raise(rb_eNoMemError, "Not enough memory");
167
+ return NULL;
168
+ }
169
+
170
+ for(i = 0; i < arr_size; i++) {
171
+ if (NIL_P(rb_ary_entry(data, i))) {
172
+ ind[i] = 1;
173
+ }
174
+ else {
175
+ bit_ary[i].size =RSTRING_LEN(rb_ary_entry(data, i));//RSTRING(rb_ary_entry(data, i))->len;
176
+ bit_ary[i].buf =RSTRING_PTR(rb_ary_entry(data, i)); //RSTRING(rb_ary_entry(data, i))->ptr;
177
+ ind[i] = 0;
178
+ }
179
+ }
180
+
181
+ val = bit_ary;
182
+ } else {
183
+ char **str_ary;
184
+
185
+ str_ary = ALLOCA_N(char*, arr_size);
186
+ if (str_ary == NULL) {
187
+ rb_raise(rb_eNoMemError, "Not enough memory");
188
+ return NULL;
189
+ }
190
+
191
+ for(i = 0; i < arr_size; i++) {
192
+ if (NIL_P(rb_ary_entry(data, i))) {
193
+ ind[i] = 1;
194
+ }
195
+ else {
196
+ str_ary[i] =RARRAY_PTR(rb_ary_entry(data, i));// RSTRING(rb_ary_entry(data, i))->ptr;
197
+ ind[i] = 0;
198
+ }
199
+ }
200
+
201
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
202
+ u_type = CCI_U_TYPE_STRING;
203
+ }
204
+ val = str_ary;
205
+ }
206
+ }
207
+ break;
208
+ case T_DATA:
209
+ if (CLASS_OF(rb_ary_entry(data, 0)) == rb_cTime) {
210
+ VALUE a;
211
+ T_CCI_DATE *date_ary;
212
+
213
+ date_ary = ALLOCA_N(T_CCI_DATE, arr_size);
214
+ if (date_ary == NULL) {
215
+ rb_raise(rb_eNoMemError, "Not enough memory");
216
+ return NULL;
217
+ }
218
+
219
+ for(i = 0; i < arr_size; i++) {
220
+ if (NIL_P(rb_ary_entry(data, i))) {
221
+ ind[i] = 1;
222
+ }
223
+ else {
224
+ a = rb_funcall(rb_ary_entry(data, i), rb_intern("to_a"), 0);
225
+ date_ary[i].ss = FIX2INT(RARRAY_PTR(a)[0]);
226
+ date_ary[i].mm = FIX2INT(RARRAY_PTR(a)[1]);
227
+ date_ary[i].hh = FIX2INT(RARRAY_PTR(a)[2]);
228
+ date_ary[i].day = FIX2INT(RARRAY_PTR(a)[3]);
229
+ date_ary[i].mon = FIX2INT(RARRAY_PTR(a)[4]);
230
+ date_ary[i].yr = FIX2INT(RARRAY_PTR(a)[5]);
231
+
232
+ ind[i] = 0;
233
+ }
234
+ }
235
+
236
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
237
+ u_type = CCI_U_TYPE_TIMESTAMP;
238
+ }
239
+ val = date_ary;
240
+ } else if (CLASS_OF(rb_ary_entry(data, 0)) == cOid) {
241
+ char **str_ary;
242
+ Oid *oid;
243
+
244
+ str_ary = ALLOCA_N(char*, arr_size);
245
+ if (str_ary == NULL) {
246
+ rb_raise(rb_eNoMemError, "Not enough memory");
247
+ return NULL;
248
+ }
249
+
250
+ for(i = 0; i < arr_size; i++) {
251
+ if (NIL_P(rb_ary_entry(data, i))) {
252
+ ind[i] = 1;
253
+ }
254
+ else {
255
+ Data_Get_Struct(rb_ary_entry(data, i), Oid, oid);
256
+ str_ary[i] = oid->oid_str;
257
+ ind[i] = 0;
258
+ }
259
+ }
260
+
261
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
262
+ u_type = CCI_U_TYPE_OBJECT;
263
+ }
264
+ val = str_ary;
265
+ }
266
+ break;
267
+ default:
268
+ rb_raise(rb_eArgError, "Wrong data type");
269
+ break;
270
+ }
271
+
272
+ res = cci_set_make(&set, u_type, arr_size, val, ind);
273
+ if (res < 0) {
274
+ cubrid_handle_error(res, NULL);
275
+ return NULL;
276
+ }
277
+
278
+ return set;
279
+ }
280
+
281
+ static void
282
+ cubrid_stmt_bind_internal(Statement *stmt, int index, VALUE data, int u_type, int set_type)
283
+ {
284
+ int res, int_val, a_type = CCI_A_TYPE_STR;
285
+ char *str_val;
286
+ double dbl_val;
287
+ void *val = NULL;
288
+ T_CCI_SET set = NULL;
289
+ T_CCI_DATE date;
290
+ T_CCI_BIT bit;
291
+
292
+ switch (TYPE(data)) {
293
+ case T_NIL:
294
+ a_type = CCI_A_TYPE_STR;
295
+ val = NULL;
296
+ u_type = CCI_U_TYPE_NULL;
297
+ break;
298
+
299
+ case T_FIXNUM:
300
+ case T_BIGNUM:
301
+ int_val = NUM2INT(data);
302
+ a_type = CCI_A_TYPE_INT;
303
+ val = &int_val;
304
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
305
+ u_type = CCI_U_TYPE_INT;
306
+ }
307
+ break;
308
+
309
+ case T_FLOAT:
310
+ dbl_val = NUM2DBL(data);
311
+ a_type = CCI_A_TYPE_DOUBLE;
312
+ val = &dbl_val;
313
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
314
+ u_type = CCI_U_TYPE_DOUBLE;
315
+ }
316
+ break;
317
+
318
+ case T_STRING:
319
+ str_val = RARRAY_PTR(data);
320
+ a_type = CCI_A_TYPE_STR;
321
+ val = str_val;
322
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
323
+ u_type = CCI_U_TYPE_STRING;
324
+ } else if (u_type == CCI_U_TYPE_BIT || u_type == CCI_U_TYPE_VARBIT) {
325
+ bit.size = RARRAY_LEN(data);
326
+ bit.buf = str_val;
327
+ a_type = CCI_A_TYPE_BIT;
328
+ val = &bit;
329
+ }
330
+ break;
331
+
332
+ case T_DATA:
333
+ if (CLASS_OF(data) == rb_cTime) {
334
+ VALUE a;
335
+
336
+ a = rb_funcall(data, rb_intern("to_a"), 0);
337
+ date.ss = FIX2INT(RARRAY_PTR(a)[0]);
338
+ date.mm = FIX2INT(RARRAY_PTR(a)[1]);
339
+ date.hh = FIX2INT(RARRAY_PTR(a)[2]);
340
+ date.day = FIX2INT(RARRAY_PTR(a)[3]);
341
+ date.mon = FIX2INT(RARRAY_PTR(a)[4]);
342
+ date.yr = FIX2INT(RARRAY_PTR(a)[5]);
343
+
344
+ a_type = CCI_A_TYPE_DATE;
345
+ val = &date;
346
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
347
+ u_type = CCI_U_TYPE_TIMESTAMP;
348
+ }
349
+ } else if (CLASS_OF(data) == cOid) {
350
+ Oid *oid;
351
+
352
+ Data_Get_Struct(data, Oid, oid);
353
+ a_type = CCI_A_TYPE_STR;
354
+ val = oid->oid_str;
355
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
356
+ u_type = CCI_U_TYPE_OBJECT;
357
+ }
358
+ }
359
+ break;
360
+
361
+ case T_ARRAY:
362
+ set = cubrid_stmt_make_set(data, set_type);
363
+ a_type = CCI_A_TYPE_SET;
364
+ val = set;
365
+ if (u_type == CCI_U_TYPE_UNKNOWN) {
366
+ u_type = CCI_U_TYPE_SET;
367
+ }
368
+ break;
369
+
370
+ default:
371
+ rb_raise(rb_eArgError, "Wrong data type");
372
+ return;
373
+ }
374
+
375
+ res = cci_bind_param(stmt->handle, index, a_type, val, u_type, 0);
376
+
377
+ if (TYPE(data) == T_ARRAY && set) {
378
+ cci_set_free(set);
379
+ }
380
+
381
+ if (res < 0) {
382
+ cubrid_handle_error(res, NULL);
383
+ return;
384
+ }
385
+
386
+ return;
387
+ }
388
+
389
+ /* call-seq:
390
+ * bind(index, data <, db_type, set_type>) -> nil
391
+ *
392
+ * *fixnum, bignum -> integer
393
+ * *float -> double
394
+ * *string -> string(varchar)
395
+ * *Time -> timestamp
396
+ * *Oid -> object
397
+ * *array -> collection
398
+ *
399
+ *
400
+ * con = Cubrid.connect('demodb')
401
+ * con.auto_commit = true
402
+ * con.query('create table a (a int, b double, c string, d date)')
403
+ * con.prepare('insert into a values (?, ?, ?, ?)') { |stmt|
404
+ * stmt.bind(1, 10)
405
+ * stmt.bind(2, 3.141592)
406
+ * stmt.bind(3, 'hello')
407
+ * stmt.bind(4, Time.local(2007, 12, 25, 10, 10, 10), CUBRID::DATE)
408
+ * stmt.execute
409
+ * }
410
+ * con.close
411
+ */
412
+ VALUE
413
+ cubrid_stmt_bind(int argc, VALUE* argv, VALUE self)
414
+ {
415
+ Statement *stmt;
416
+ VALUE index, u_type, data, set_type;
417
+
418
+ GET_STMT_STRUCT(self, stmt);
419
+ CHECK_HANDLE(stmt, self);
420
+
421
+ rb_scan_args(argc, argv, "22", &index, &data, &u_type, &set_type);
422
+
423
+ if (NIL_P(u_type)) {
424
+ u_type = INT2NUM(CCI_U_TYPE_UNKNOWN);
425
+ }
426
+
427
+ if (NIL_P(set_type)) {
428
+ set_type = INT2NUM(CCI_U_TYPE_UNKNOWN);
429
+ }
430
+
431
+ cubrid_stmt_bind_internal(stmt, NUM2INT(index), data, NUM2INT(u_type), NUM2INT(set_type));
432
+ stmt->bound = 1;
433
+
434
+ return Qnil;
435
+ }
436
+
437
+ static int
438
+ cubrid_stmt_is_auto_commitable(T_CCI_SQLX_CMD cmd)
439
+ {
440
+ switch(cmd) {
441
+ case SQLX_CMD_SELECT:
442
+ case SQLX_CMD_CALL:
443
+ case SQLX_CMD_CALL_SP:
444
+ case SQLX_CMD_COMMIT_WORK:
445
+ case SQLX_CMD_ROLLBACK_WORK:
446
+ case SQLX_CMD_GET_ISO_LVL:
447
+ case SQLX_CMD_GET_TIMEOUT:
448
+ case SQLX_CMD_GET_OPT_LVL:
449
+ case SQLX_CMD_GET_TRIGGER:
450
+ case SQLX_CMD_SAVEPOINT:
451
+ case SQLX_CMD_GET_LDB:
452
+ case SQLX_CMD_GET_STATS:
453
+ return 0;
454
+ }
455
+
456
+ return 1;
457
+ }
458
+
459
+ /* call-seq:
460
+ * execute() -> int
461
+ * execute(...) -> int
462
+ *
463
+ * con = Cubrid.connect('demodb')
464
+ * con.prepare('insert into a values (?, ?, ?, ?)') { |stmt|
465
+ * stmt.execute (10, 3.141592, 'hello', Time.local(2007, 12, 25))
466
+ * }
467
+ * con.close
468
+ */
469
+ VALUE
470
+ cubrid_stmt_execute(int argc, VALUE* argv, VALUE self)
471
+ {
472
+ T_CCI_ERROR error;
473
+ T_CCI_COL_INFO *res_col_info;
474
+ T_CCI_SQLX_CMD res_sql_type;
475
+ int res_col_count, row_count;
476
+ Statement *stmt;
477
+
478
+ GET_STMT_STRUCT(self, stmt);
479
+ CHECK_HANDLE(stmt, self);
480
+
481
+ if (!stmt->bound && stmt->param_cnt != argc) {
482
+ rb_raise(rb_eStandardError, "execute: param_count(%d) != number of argument(%d)",
483
+ stmt->param_cnt, argc);
484
+ return INT2NUM(0);
485
+ }
486
+
487
+ if (argc > 0) {
488
+ int i;
489
+ for (i = 0; i < argc; i++) {
490
+ cubrid_stmt_bind_internal(stmt, i + 1, argv[i], CCI_U_TYPE_UNKNOWN, CCI_U_TYPE_UNKNOWN);
491
+ }
492
+ }
493
+
494
+ row_count = cci_execute(stmt->handle, 0, 0, &error);
495
+ if (row_count < 0) {
496
+ cubrid_handle_error(row_count, &error);
497
+ return INT2NUM(0);
498
+ }
499
+
500
+ res_col_info = cci_get_result_info(stmt->handle, &res_sql_type, &res_col_count);
501
+ if (res_sql_type == SQLX_CMD_SELECT && !res_col_info) {
502
+ cubrid_handle_error(CUBRID_ER_CANNOT_GET_COLUMN_INFO, &error);
503
+ return INT2NUM(0);
504
+ }
505
+
506
+ stmt->col_info = res_col_info;
507
+ stmt->sql_type = res_sql_type;
508
+ stmt->col_count = res_col_count;
509
+ stmt->affected_rows = row_count;
510
+
511
+ if(stmt->con->auto_commit == Qtrue && cubrid_stmt_is_auto_commitable(stmt->sql_type)) {
512
+ cubrid_stmt_close(self);
513
+ cubrid_conn_end_tran(stmt->con, CCI_TRAN_COMMIT);
514
+ }
515
+
516
+ stmt->bound = 0;
517
+ return INT2NUM(row_count);
518
+ }
519
+
520
+ /* call-seq:
521
+ * affected_rows() -> int
522
+ */
523
+ VALUE
524
+ cubrid_stmt_affected_rows(VALUE self)
525
+ {
526
+ Statement *stmt;
527
+
528
+ GET_STMT_STRUCT(self, stmt);
529
+ CHECK_HANDLE(stmt, self);
530
+
531
+ return INT2NUM(stmt->affected_rows);
532
+ }
533
+
534
+ static int ut_str_to_bigint (char *str, CUBRID_LONG_LONG * value)
535
+ { char *end_p;
536
+ CUBRID_LONG_LONG bi_val;
537
+ bi_val = strtoll (str, &end_p, 10);
538
+ if (*end_p == 0 || *end_p == '.' || isspace ((int) *end_p))
539
+ {
540
+ *value = bi_val;
541
+ return 0;
542
+ }
543
+
544
+ return (-1);
545
+
546
+ }
547
+
548
+
549
+ static VALUE
550
+ cubrid_stmt_dbval_to_ruby_value(int req_handle, int type, int index, Connection *con)
551
+ {
552
+ int res, ind;
553
+ VALUE val;
554
+ char *res_buf;
555
+ int int_val;
556
+ double double_val;
557
+ T_CCI_DATE date;
558
+ T_CCI_BIT bit;
559
+ CUBRID_LONG_LONG l_val;
560
+
561
+ switch (type) {
562
+ case CCI_U_TYPE_INT:
563
+ case CCI_U_TYPE_SHORT:
564
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_INT, &int_val, &ind);
565
+ if (res < 0) {
566
+ cubrid_handle_error(res, NULL);
567
+ return Qnil;
568
+ }
569
+
570
+ if (ind < 0) {
571
+ val = Qnil;
572
+ } else {
573
+ val = INT2NUM(int_val);
574
+ }
575
+ break;
576
+ case CCI_U_TYPE_BIGINT:
577
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_STR, &res_buf, &ind);
578
+ if (res < 0) {
579
+ cubrid_handle_error(res, NULL);
580
+ return Qnil;
581
+ }
582
+
583
+ res = ut_str_to_bigint(res_buf,&l_val);
584
+ if(res < 0){
585
+ cubrid_handle_error(res, NULL);
586
+ return Qnil;
587
+ }
588
+ if (ind < 0) {
589
+ val = Qnil;
590
+ } else {
591
+ val = LL2NUM(l_val);
592
+ }
593
+ break;
594
+ case CCI_U_TYPE_FLOAT:
595
+ case CCI_U_TYPE_DOUBLE:
596
+ //case CCI_U_TYPE_NUMERIC:
597
+ case CCI_U_TYPE_MONETARY:
598
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_STR, &res_buf, &ind);
599
+ if (res < 0) {
600
+ cubrid_handle_error(res, NULL);
601
+ return Qnil;
602
+ }
603
+ if (ind < 0) {
604
+ val = Qnil;
605
+ } else {
606
+ double_val = atof(res_buf);
607
+ val = rb_float_new(double_val);
608
+ }
609
+ break;
610
+ case CCI_U_TYPE_DATE:
611
+ case CCI_U_TYPE_TIME:
612
+ case CCI_U_TYPE_TIMESTAMP:
613
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_DATE, &date, &ind);
614
+ if (res < 0) {
615
+ cubrid_handle_error(res, NULL);
616
+ return Qnil;
617
+ }
618
+ if (ind < 0) {
619
+ val = Qnil;
620
+ } else {
621
+ if (type == CCI_U_TYPE_DATE) {
622
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 3,
623
+ INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day));
624
+ } else if (type == CCI_U_TYPE_TIME) {
625
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
626
+ INT2NUM(1970), INT2NUM(1), INT2NUM(1),
627
+ INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
628
+ } else {
629
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
630
+ INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day),
631
+ INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
632
+ }
633
+ }
634
+ break;
635
+
636
+ case CCI_U_TYPE_BIT:
637
+ case CCI_U_TYPE_VARBIT:
638
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_BIT, &bit, &ind);
639
+ if (res < 0) {
640
+ cubrid_handle_error(res, NULL);
641
+ return Qnil;
642
+ }
643
+ if (ind < 0) {
644
+ val = Qnil;
645
+ } else {
646
+ val = rb_tainted_str_new(bit.buf, bit.size);
647
+ }
648
+ break;
649
+
650
+ default:
651
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_STR, &res_buf, &ind);
652
+ if (res < 0) {
653
+ cubrid_handle_error(res, NULL);
654
+ return Qnil;
655
+ }
656
+ if (ind < 0) {
657
+ val = Qnil;
658
+ } else {
659
+ val = rb_str_new2(res_buf);
660
+ }
661
+ break;
662
+ }
663
+
664
+ return val;
665
+ }
666
+
667
+ static VALUE
668
+ cubrid_stmt_dbval_to_ruby_value_from_set(T_CCI_SET set, int type, int index, Connection *con)
669
+ {
670
+ int res, ind;
671
+ VALUE val;
672
+ char *res_buf;
673
+ int int_val;
674
+ double double_val;
675
+ T_CCI_DATE date;
676
+ T_CCI_BIT bit;
677
+
678
+ switch (type) {
679
+ case CCI_U_TYPE_INT:
680
+ case CCI_U_TYPE_SHORT:
681
+ res = cci_set_get(set, index, CCI_A_TYPE_INT, &int_val, &ind);
682
+ if (res < 0) {
683
+ cubrid_handle_error(res, NULL);
684
+ return Qnil;
685
+ }
686
+ if (ind < 0) {
687
+ val = Qnil;
688
+ } else {
689
+ val = INT2NUM(int_val);
690
+ }
691
+ break;
692
+
693
+ case CCI_U_TYPE_FLOAT:
694
+ case CCI_U_TYPE_DOUBLE:
695
+ case CCI_U_TYPE_NUMERIC:
696
+ case CCI_U_TYPE_MONETARY:
697
+ res = cci_set_get(set, index, CCI_A_TYPE_STR, &res_buf, &ind);
698
+ if (res < 0) {
699
+ cubrid_handle_error(res, NULL);
700
+ return Qnil;
701
+ }
702
+ if (ind < 0) {
703
+ val = Qnil;
704
+ } else {
705
+ double_val = atof(res_buf);
706
+ val = rb_float_new(double_val);
707
+ }
708
+ break;
709
+
710
+ case CCI_U_TYPE_DATE:
711
+ case CCI_U_TYPE_TIME:
712
+ case CCI_U_TYPE_TIMESTAMP:
713
+ res = cci_set_get(set, index, CCI_A_TYPE_DATE, &date, &ind);
714
+ if (res < 0) {
715
+ cubrid_handle_error(res, NULL);
716
+ return Qnil;
717
+ }
718
+ if (ind < 0) {
719
+ val = Qnil;
720
+ } else {
721
+ if (type == CCI_U_TYPE_DATE) {
722
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 3,
723
+ INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day));
724
+ } else if (type == CCI_U_TYPE_TIME) {
725
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
726
+ INT2NUM(1970), INT2NUM(1), INT2NUM(1),
727
+ INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
728
+ } else {
729
+ val = rb_funcall(rb_cTime, rb_intern("mktime"), 7,
730
+ INT2NUM(date.yr), INT2NUM(date.mon), INT2NUM(date.day),
731
+ INT2NUM(date.hh), INT2NUM(date.mm), INT2NUM(date.ss), INT2NUM(0));
732
+ }
733
+ }
734
+ break;
735
+
736
+ case CCI_U_TYPE_BIT:
737
+ case CCI_U_TYPE_VARBIT:
738
+ res = cci_set_get(set, index, CCI_A_TYPE_BIT, &bit, &ind);
739
+ if (res < 0) {
740
+ cubrid_handle_error(res, NULL);
741
+ return Qnil;
742
+ }
743
+ if (ind < 0) {
744
+ val = Qnil;
745
+ } else {
746
+ val = rb_tainted_str_new(bit.buf, bit.size);
747
+ }
748
+ break;
749
+
750
+ default:
751
+ res = cci_set_get(set, index, CCI_A_TYPE_STR, &res_buf, &ind);
752
+ if (res < 0) {
753
+ cubrid_handle_error(res, NULL);
754
+ return Qnil;
755
+ }
756
+ if (ind < 0) {
757
+ val = Qnil;
758
+ } else {
759
+ val = rb_str_new2(res_buf);
760
+ }
761
+ break;
762
+ }
763
+
764
+ return val;
765
+ }
766
+
767
+ static VALUE
768
+ cubrid_stmt_dbset_to_ruby_value(int req_handle, int index, Connection *con)
769
+ {
770
+ int i, res, ind, e_type;
771
+ VALUE val, e;
772
+ T_CCI_SET set = NULL;
773
+ int set_size;
774
+
775
+ res = cci_get_data(req_handle, index, CCI_A_TYPE_SET, &set, &ind);
776
+ if (res < 0) {
777
+ cubrid_handle_error(res, NULL);
778
+ return Qnil;
779
+ }
780
+
781
+ if (set == NULL)
782
+ return Qnil;
783
+
784
+ set_size = cci_set_size(set);
785
+ val = rb_ary_new2(set_size);
786
+
787
+ e_type = cci_set_element_type(set);
788
+
789
+ for (i = 0; i < set_size; i++) {
790
+ e = cubrid_stmt_dbval_to_ruby_value_from_set(set, e_type, i + 1, con);
791
+ rb_ary_push(val, e);
792
+ }
793
+ cci_set_free(set);
794
+
795
+ return val;
796
+ }
797
+
798
+ VALUE
799
+ cubrid_stmt_fetch_one_row(int req_handle, int col_count, T_CCI_COL_INFO *col_info, Connection *con)
800
+ {
801
+ int i, type;
802
+ VALUE row, val;
803
+
804
+ row = rb_ary_new();
805
+
806
+ for (i = 0; i < col_count; i++) {
807
+ type = CCI_GET_RESULT_INFO_TYPE(col_info, i + 1);
808
+
809
+ if (CCI_IS_COLLECTION_TYPE(type)) {
810
+ val = cubrid_stmt_dbset_to_ruby_value(req_handle, i + 1, con);
811
+ } else {
812
+ val = cubrid_stmt_dbval_to_ruby_value(req_handle, type, i + 1, con);
813
+ }
814
+
815
+ rb_ary_push(row, val);
816
+ }
817
+
818
+ return row;
819
+ }
820
+
821
+ /* call-seq:
822
+ * fetch() -> array or nil
823
+ *
824
+ * con = Cubrid.connect('demodb')
825
+ * con.prepare('SELECT * FROM db_user') { |stmt|
826
+ * stmt.execute
827
+ * r = stmt.fetch
828
+ * print r[0]
829
+ * }
830
+ * con.close
831
+ *
832
+ * *int, short -> fixnum, bignum
833
+ * *float, double, numeric, monetary -> float
834
+ * *char, varchar, ncahr, varnchar -> string
835
+ * *bit, varbit -> string
836
+ * *date, time, timestamp -> Time
837
+ * *object -> Oid
838
+ * *collection -> array
839
+ *
840
+ */
841
+ VALUE
842
+ cubrid_stmt_fetch(VALUE self)
843
+ {
844
+ int res;
845
+ T_CCI_ERROR error;
846
+ Statement *stmt;
847
+
848
+ GET_STMT_STRUCT(self, stmt);
849
+ CHECK_HANDLE(stmt, self);
850
+
851
+ res = cci_cursor(stmt->handle, 1, CCI_CURSOR_CURRENT, &error);
852
+ if (res == CCI_ER_NO_MORE_DATA) {
853
+ return Qnil;
854
+ } else if (res < 0) {
855
+ cubrid_handle_error(res, &error);
856
+ return Qnil;
857
+ }
858
+
859
+ res = cci_fetch(stmt->handle, &error);
860
+ if (res < 0) {
861
+ cubrid_handle_error(res, &error);
862
+ return Qnil;
863
+ }
864
+
865
+ return cubrid_stmt_fetch_one_row(stmt->handle, stmt->col_count, stmt->col_info, stmt->con);
866
+ }
867
+
868
+ /* call-seq:
869
+ * fetch_hash() -> hash or nil
870
+
871
+ * con = Cubrid.connect('demodb')
872
+ * con.prepare('SELECT * FROM db_user') { |stmt|
873
+ * stmt.execute
874
+ * r = stmt.fetch_hash
875
+ * print r['name']
876
+ * }
877
+ * con.close
878
+ */
879
+ VALUE
880
+ cubrid_stmt_fetch_hash(VALUE self)
881
+ {
882
+ VALUE row, col, hash;
883
+ int i;
884
+ char colName[128];
885
+ Statement *stmt;
886
+
887
+ GET_STMT_STRUCT(self, stmt);
888
+ CHECK_HANDLE(stmt, self);
889
+
890
+ row = cubrid_stmt_fetch(self);
891
+ if (NIL_P(row))
892
+ return Qnil;
893
+
894
+ hash = rb_hash_new();
895
+ for(i = 0; i < stmt->col_count; i++) {
896
+ col = RARRAY_PTR(row)[i];
897
+ strcpy(colName, CCI_GET_RESULT_INFO_NAME(stmt->col_info, i+1));
898
+ rb_hash_aset(hash, rb_str_new2(colName), col);
899
+ }
900
+
901
+ return hash;
902
+ }
903
+
904
+ /* call-seq:
905
+ * each() { |row| block } -> nil
906
+ *
907
+ *
908
+ * con = Cubrid.connect('demodb')
909
+ * con.prepare('SELECT * FROM db_user') { |stmt|
910
+ * stmt.execute
911
+ * stmt.each { |r|
912
+ * print r[0]
913
+ * }
914
+ * }
915
+ * con.close
916
+ */
917
+ VALUE
918
+ cubrid_stmt_each(VALUE self)
919
+ {
920
+ VALUE row;
921
+
922
+ while(1) {
923
+ row = cubrid_stmt_fetch(self);
924
+ if (NIL_P(row)) {
925
+ break;
926
+ }
927
+ rb_yield(row);
928
+ }
929
+
930
+ return Qnil;
931
+ }
932
+
933
+ /* call-seq:
934
+ * each_hash() { |hash| block } -> nil
935
+ *
936
+ * con = Cubrid.connect('demodb')
937
+ * con.prepare('SELECT * FROM db_user') { |stmt|
938
+ * stmt.execute
939
+ * stmt.each_hash { |r|
940
+ * print r['name']
941
+ * }
942
+ * }
943
+ * con.close
944
+ */
945
+ VALUE
946
+ cubrid_stmt_each_hash(VALUE self)
947
+ {
948
+ VALUE row;
949
+
950
+ while(1) {
951
+ row = cubrid_stmt_fetch_hash(self);
952
+ if (NIL_P(row)) {
953
+ break;
954
+ }
955
+ rb_yield(row);
956
+ }
957
+
958
+ return Qnil;
959
+ }
960
+
961
+ /* call-seq:
962
+ * column_info() -> array
963
+ *
964
+ * con = Cubrid.connect('demodb')
965
+ * con.prepare('SELECT * FROM db_user') { |stmt|
966
+ * stmt.column_info.each { |col|
967
+ * print col['name']
968
+ * print col['type_name']
969
+ * print col['precision']
970
+ * print col['scale']
971
+ * print col['nullable']
972
+ * }
973
+ * }
974
+ * con.close
975
+ */
976
+ VALUE
977
+ cubrid_stmt_column_info(VALUE self)
978
+ {
979
+ VALUE desc;
980
+ int i;
981
+ char col_name[MAX_STR_LEN];
982
+ int datatype, precision, scale, nullable;
983
+ Statement *stmt;
984
+
985
+ GET_STMT_STRUCT(self, stmt);
986
+ CHECK_HANDLE(stmt, self);
987
+
988
+ desc = rb_ary_new2(stmt->col_count);
989
+
990
+ for (i = 0; i < stmt->col_count; i++) {
991
+ VALUE item;
992
+
993
+ item = rb_hash_new();
994
+
995
+ strcpy(col_name, CCI_GET_RESULT_INFO_NAME(stmt->col_info, i+1));
996
+ precision = CCI_GET_RESULT_INFO_PRECISION(stmt->col_info, i+1);
997
+ scale = CCI_GET_RESULT_INFO_SCALE(stmt->col_info, i+1);
998
+ nullable = CCI_GET_RESULT_INFO_IS_NON_NULL(stmt->col_info, i+1);
999
+ datatype = CCI_GET_RESULT_INFO_TYPE(stmt->col_info, i+1);
1000
+
1001
+ rb_hash_aset(item, rb_str_new2("name"), rb_str_new2(col_name));
1002
+ rb_hash_aset(item, rb_str_new2("type_name"), INT2NUM(datatype));
1003
+ rb_hash_aset(item, rb_str_new2("precision"), INT2NUM(precision));
1004
+ rb_hash_aset(item, rb_str_new2("scale"), INT2NUM(scale));
1005
+ rb_hash_aset(item, rb_str_new2("nullable"), INT2NUM(nullable));
1006
+
1007
+ rb_ary_push(desc, item);
1008
+ }
1009
+
1010
+ return desc;
1011
+ }
1012
+