ruby-informix 0.6.2-i386-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/COPYRIGHT +26 -0
  2. data/Changelog +198 -0
  3. data/README +85 -0
  4. data/ifx_except.c +522 -0
  5. data/informix.c +5021 -0
  6. data/informix.so +0 -0
  7. metadata +53 -0
data/informix.c ADDED
@@ -0,0 +1,5021 @@
1
+ #include <sqlhdr.h>
2
+ #include <sqliapi.h>
3
+ #line 1 "informix.ec"
4
+ /* $Id: informix.ec,v 1.12 2007/10/14 00:18:50 santana Exp $ */
5
+ /*
6
+ * Copyright (c) 2006-2007, Gerardo Santana Gomez Garrido <gerardo.santana@gmail.com>
7
+ * All rights reserved.
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted provided that the following conditions
11
+ * are met:
12
+ *
13
+ * 1. Redistributions of source code must retain the above copyright
14
+ * notice, this list of conditions and the following disclaimer.
15
+ * 2. Redistributions in binary form must reproduce the above copyright
16
+ * notice, this list of conditions and the following disclaimer in the
17
+ * documentation and/or other materials provided with the distribution.
18
+ * 3. The name of the author may not be used to endorse or promote products
19
+ * derived from this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
+ * POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
34
+ static const char rcsid[] = "$Id: informix.ec,v 1.12 2007/10/14 00:18:50 santana Exp $";
35
+
36
+ #include "ruby.h"
37
+ #include "ifx_except.h"
38
+
39
+ #include <sqlstype.h>
40
+ #include <sqltypes.h>
41
+
42
+ static VALUE rb_cDate, rb_cBigDecimal;
43
+
44
+ static VALUE rb_mInformix;
45
+ static VALUE rb_mSequentialCursor;
46
+ static VALUE rb_mScrollCursor;
47
+ static VALUE rb_mInsertCursor;
48
+
49
+ static VALUE rb_cSlob, rb_cSlobStat;
50
+ static VALUE rb_cDatabase;
51
+ static VALUE rb_cStatement;
52
+ static VALUE rb_cCursor;
53
+
54
+ static ID s_read, s_new, s_utc, s_day, s_month, s_year;
55
+ static ID s_hour, s_min, s_sec, s_usec, s_to_s, s_to_i;
56
+
57
+ static VALUE sym_name, sym_type, sym_nullable, sym_stype, sym_length;
58
+ static VALUE sym_precision, sym_scale, sym_default, sym_xid;
59
+ static VALUE sym_scroll, sym_hold;
60
+ static VALUE sym_col_info, sym_sbspace, sym_estbytes, sym_extsz;
61
+ static VALUE sym_createflags, sym_openflags, sym_maxbytes;
62
+ static VALUE sym_params;
63
+
64
+ /* Symbols from ifx_except module */
65
+ static ifx_except_symbols_t esyms;
66
+
67
+ #define IDSIZE 30
68
+
69
+ typedef struct {
70
+ short is_select, is_open;
71
+ struct sqlda daInput, *daOutput;
72
+ short *indInput, *indOutput;
73
+ char *bfOutput;
74
+ char cursor_id[IDSIZE];
75
+ char stmt_id[IDSIZE];
76
+ VALUE db, array, hash, field_names;
77
+ char *database_id;
78
+ } cursor_t;
79
+
80
+ typedef struct {
81
+ mint fd;
82
+ ifx_lo_t lo;
83
+ ifx_lo_create_spec_t *spec;
84
+ short type; /* XID_CLOB/XID_BLOB */
85
+ VALUE db;
86
+ char *database_id;
87
+ } slob_t;
88
+
89
+ typedef struct {
90
+ mint atime, ctime, mtime, refcnt;
91
+ ifx_int8_t size;
92
+ } slobstat_t;
93
+
94
+ #define NUM2INT8(num, int8addr) \
95
+ do { \
96
+ VALUE str = rb_funcall(num, s_to_s, 0); \
97
+ char *c_str = StringValueCStr(str); \
98
+ mint ret = ifx_int8cvasc(c_str, strlen(c_str), (int8addr)); \
99
+ if (ret < 0) \
100
+ rb_raise(esyms.eOperationalError, "Could not convert %s to int8", c_str); \
101
+ } while(0)
102
+
103
+ #define INT82NUM(int8addr, num) \
104
+ do { \
105
+ char str[21]; \
106
+ ifx_int8toasc((int8addr), str, sizeof(str) - 1); \
107
+ str[sizeof(str) - 1] = 0; \
108
+ num = rb_cstr2inum(str, 10); \
109
+ } while(0)
110
+
111
+ /* class Slob::Stat ------------------------------------------------------ */
112
+
113
+ static void
114
+ slobstat_free(slobstat_t *stat)
115
+ {
116
+ xfree(stat);
117
+ }
118
+
119
+ static VALUE
120
+ slobstat_alloc(VALUE klass)
121
+ {
122
+ slobstat_t *stat;
123
+
124
+ stat = ALLOC(slobstat_t);
125
+ return Data_Wrap_Struct(klass, 0, slobstat_free, stat);
126
+ }
127
+
128
+ /*
129
+ * call-seq:
130
+ * Slob::Stat.new(slob) => stat
131
+ *
132
+ * Creates an Slob::Stat object with status information for the given Slob
133
+ * object.
134
+ */
135
+ static VALUE
136
+ rb_slobstat_initialize(VALUE self, VALUE slob)
137
+ {
138
+ mint ret;
139
+ slob_t *sb;
140
+ slobstat_t *stat;
141
+ ifx_lo_stat_t *st;
142
+ /*
143
+ * EXEC SQL begin declare section;
144
+ */
145
+ #line 139 "informix.ec"
146
+ #line 140 "informix.ec"
147
+ char *did;
148
+ /*
149
+ * EXEC SQL end declare section;
150
+ */
151
+ #line 141 "informix.ec"
152
+
153
+
154
+ Data_Get_Struct(slob, slob_t, sb);
155
+ Data_Get_Struct(self, slobstat_t, stat);
156
+
157
+ if (sb->fd == -1)
158
+ rb_raise(esyms.eProgrammingError,
159
+ "Open the Slob object before getting its status");
160
+
161
+ did = sb->database_id;
162
+ /*
163
+ * EXEC SQL set connection :did;
164
+ */
165
+ #line 151 "informix.ec"
166
+ {
167
+ #line 151 "informix.ec"
168
+ sqli_connect_set(0, did, 0);
169
+ #line 151 "informix.ec"
170
+ }
171
+ if (SQLCODE < 0)
172
+ raise_ifx_extended();
173
+
174
+ ret = ifx_lo_stat(sb->fd, &st);
175
+
176
+ if (ret < 0)
177
+ raise_ifx_extended();
178
+
179
+ stat->atime = ifx_lo_stat_atime(st);
180
+ stat->ctime = ifx_lo_stat_ctime(st);
181
+ stat->mtime = ifx_lo_stat_mtime_sec(st);
182
+ stat->refcnt = ifx_lo_stat_refcnt(st);
183
+ ret = ifx_lo_stat_size(st, &stat->size);
184
+
185
+ ifx_lo_stat_free(st);
186
+
187
+ if (stat->atime == -1 || stat->ctime == -1 || stat->mtime == -1 ||
188
+ stat->refcnt == -1 || ret == -1) {
189
+ rb_raise(esyms.eOperationalError, "Unable to get status");
190
+ }
191
+
192
+ return self;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * stat <=> other_stat => -1, 0, 1
198
+ *
199
+ * Compares with another <code>Slob::Stat</code> object by comparing their
200
+ * modification times.
201
+ */
202
+ static VALUE
203
+ rb_slobstat_cmp(VALUE self, VALUE other)
204
+ {
205
+ if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
206
+ slobstat_t *stat;
207
+ time_t t1, t2;
208
+
209
+ Data_Get_Struct(self, slobstat_t, stat); t1 = stat->mtime;
210
+ Data_Get_Struct(other, slobstat_t, stat); t2 = stat->mtime;
211
+
212
+ if (t1 == t2)
213
+ return INT2FIX(0);
214
+ else if (t1 < t2)
215
+ return INT2FIX(-1);
216
+ else
217
+ return INT2FIX(1);
218
+ }
219
+
220
+ return Qnil;
221
+ }
222
+
223
+ /*
224
+ * call-seq:
225
+ * stat.atime => time
226
+ *
227
+ * Returns the time of last access as a Time object.
228
+ */
229
+ static VALUE
230
+ rb_slobstat_atime(VALUE self)
231
+ {
232
+ slobstat_t *stat;
233
+
234
+ Data_Get_Struct(self, slobstat_t, stat);
235
+ return rb_time_new(stat->atime, 0);
236
+ }
237
+
238
+ /*
239
+ * call-seq:
240
+ * stat.ctime => time
241
+ *
242
+ * Returns the time of last change in status as a Time object.
243
+ */
244
+ static VALUE
245
+ rb_slobstat_ctime(VALUE self)
246
+ {
247
+ slobstat_t *stat;
248
+
249
+ Data_Get_Struct(self, slobstat_t, stat);
250
+ return rb_time_new(stat->ctime, 0);
251
+ }
252
+
253
+ /*
254
+ * call-seq:
255
+ * stat.mtime => time
256
+ *
257
+ * Returns the time of last modification as a Time object.
258
+ */
259
+ static VALUE
260
+ rb_slobstat_mtime(VALUE self)
261
+ {
262
+ slobstat_t *stat;
263
+
264
+ Data_Get_Struct(self, slobstat_t, stat);
265
+ return rb_time_new(stat->mtime, 0);
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * stat.refcnt => fixnum
271
+ *
272
+ * Returns the number of references
273
+ */
274
+ static VALUE
275
+ rb_slobstat_refcnt(VALUE self)
276
+ {
277
+ slobstat_t *stat;
278
+
279
+ Data_Get_Struct(self, slobstat_t, stat);
280
+ return INT2FIX(stat->refcnt);
281
+ }
282
+
283
+ /*
284
+ * call-seq:
285
+ * stat.size => fixnum or bignum
286
+ *
287
+ * Returns the size in bytes
288
+ */
289
+ static VALUE
290
+ rb_slobstat_size(VALUE self)
291
+ {
292
+ slobstat_t *stat;
293
+ VALUE size;
294
+
295
+ Data_Get_Struct(self, slobstat_t, stat);
296
+ INT82NUM(&stat->size, size);
297
+
298
+ return size;
299
+ }
300
+
301
+ /* class Slob ------------------------------------------------------------ */
302
+
303
+ static void
304
+ slob_mark(slob_t *slob)
305
+ {
306
+ rb_gc_mark(slob->db);
307
+ }
308
+
309
+ static void
310
+ slob_free(slob_t *slob)
311
+ {
312
+ if (slob->fd != -1) {
313
+ /*
314
+ * EXEC SQL begin declare section;
315
+ */
316
+ #line 294 "informix.ec"
317
+ #line 295 "informix.ec"
318
+ char *did;
319
+ /*
320
+ * EXEC SQL end declare section;
321
+ */
322
+ #line 296 "informix.ec"
323
+
324
+
325
+ did = slob->database_id;
326
+ /*
327
+ * EXEC SQL set connection :did;
328
+ */
329
+ #line 299 "informix.ec"
330
+ {
331
+ #line 299 "informix.ec"
332
+ sqli_connect_set(0, did, 0);
333
+ #line 299 "informix.ec"
334
+ }
335
+ if (SQLCODE >= 0)
336
+ ifx_lo_close(slob->fd);
337
+ }
338
+
339
+ if (slob->spec)
340
+ ifx_lo_spec_free(slob->spec);
341
+
342
+ xfree(slob);
343
+ }
344
+
345
+ static VALUE
346
+ slob_alloc(VALUE klass)
347
+ {
348
+ slob_t *slob;
349
+
350
+ slob = ALLOC(slob_t);
351
+ slob->spec = NULL;
352
+ slob->fd = -1;
353
+ slob->database_id = NULL;
354
+ slob->type = XID_CLOB;
355
+ slob->db = 0;
356
+
357
+ return Data_Wrap_Struct(klass, slob_mark, slob_free, slob);
358
+ }
359
+
360
+ static VALUE
361
+ rb_slob_initialize(int argc, VALUE *argv, VALUE self)
362
+ {
363
+ mint ret, error;
364
+ slob_t *slob;
365
+ VALUE db, type, options;
366
+ VALUE col_info, sbspace, estbytes, extsz, createflags, openflags, maxbytes;
367
+ /*
368
+ * EXEC SQL begin declare section;
369
+ */
370
+ #line 332 "informix.ec"
371
+ #line 333 "informix.ec"
372
+ char *did;
373
+ /*
374
+ * EXEC SQL end declare section;
375
+ */
376
+ #line 334 "informix.ec"
377
+
378
+
379
+ rb_scan_args(argc, argv, "12", &db, &type, &options);
380
+ Data_Get_Struct(db, char, did);
381
+
382
+ /*
383
+ * EXEC SQL set connection :did;
384
+ */
385
+ #line 339 "informix.ec"
386
+ {
387
+ #line 339 "informix.ec"
388
+ sqli_connect_set(0, did, 0);
389
+ #line 339 "informix.ec"
390
+ }
391
+ if (SQLCODE < 0)
392
+ raise_ifx_extended();
393
+
394
+ Data_Get_Struct(self, slob_t, slob);
395
+ slob->db = db;
396
+ slob->database_id = did;
397
+
398
+ if (!NIL_P(type)) {
399
+ int t = FIX2INT(type);
400
+ if (t != XID_CLOB && t != XID_BLOB)
401
+ rb_raise(esyms.eInternalError, "Invalid type %d for an SLOB", t);
402
+ slob->type = t;
403
+ }
404
+
405
+ col_info = sbspace = estbytes = extsz = createflags = openflags = maxbytes = Qnil;
406
+
407
+ if (!NIL_P(options)) {
408
+ Check_Type(options, T_HASH);
409
+ col_info = rb_hash_aref(options, sym_col_info);
410
+ sbspace = rb_hash_aref(options, sym_sbspace);
411
+ estbytes = rb_hash_aref(options, sym_estbytes);
412
+ extsz = rb_hash_aref(options, sym_extsz);
413
+ createflags = rb_hash_aref(options, sym_createflags);
414
+ openflags = rb_hash_aref(options, sym_openflags);
415
+ maxbytes = rb_hash_aref(options, sym_maxbytes);
416
+ }
417
+
418
+ ret = ifx_lo_def_create_spec(&slob->spec);
419
+ if (ret < 0)
420
+ raise_ifx_extended();
421
+
422
+ if (!NIL_P(col_info)) {
423
+ ret = ifx_lo_col_info(StringValueCStr(col_info), slob->spec);
424
+
425
+ if (ret < 0)
426
+ raise_ifx_extended();
427
+ }
428
+ if (!NIL_P(sbspace)) {
429
+ char *c_sbspace = StringValueCStr(sbspace);
430
+ ret = ifx_lo_specset_sbspace(slob->spec, c_sbspace);
431
+ if (ret == -1)
432
+ rb_raise(esyms.eOperationalError, "Could not set sbspace name to %s", c_sbspace);
433
+ }
434
+ if (!NIL_P(estbytes)) {
435
+ ifx_int8_t estbytes8;
436
+
437
+ NUM2INT8(estbytes, &estbytes8);
438
+ ret = ifx_lo_specset_estbytes(slob->spec, &estbytes8);
439
+ if (ret == -1)
440
+ rb_raise(esyms.eOperationalError, "Could not set estbytes");
441
+ }
442
+ if (!NIL_P(extsz)) {
443
+ ret = ifx_lo_specset_extsz(slob->spec, FIX2LONG(extsz));
444
+ if (ret == -1)
445
+ rb_raise(esyms.eOperationalError, "Could not set extsz to %d", FIX2LONG(extsz));
446
+ }
447
+ if (!NIL_P(createflags)) {
448
+ ret = ifx_lo_specset_flags(slob->spec, FIX2LONG(createflags));
449
+ if (ret == -1)
450
+ rb_raise(esyms.eOperationalError, "Could not set crate-time flags to 0x%X", FIX2LONG(createflags));
451
+ }
452
+ if (!NIL_P(maxbytes)) {
453
+ ifx_int8_t maxbytes8;
454
+
455
+ NUM2INT8(maxbytes, (&maxbytes8));
456
+ ret = ifx_lo_specset_maxbytes(slob->spec, &maxbytes8);
457
+ if (ret == -1)
458
+ rb_raise(esyms.eOperationalError, "Could not set maxbytes");
459
+ }
460
+
461
+ slob->fd = ifx_lo_create(slob->spec, RTEST(openflags)? FIX2LONG(openflags): LO_RDWR, &slob->lo, &error);
462
+ if (slob->fd == -1)
463
+ raise_ifx_extended();
464
+
465
+ return self;
466
+ }
467
+
468
+ static VALUE rb_slob_close(VALUE self);
469
+ /*
470
+ * call-seq:
471
+ * Slob.new(database, type = Slob::CLOB, options = nil) => slob
472
+ * Slob.new(database, type = Slob::CLOB, options = nil) {|slob| block } => obj
473
+ *
474
+ * Creates a Smart Large Object of type <i>type</i> in <i>database</i>.
475
+ * Returns a <code>Slob</code> object pointing to it.
476
+ *
477
+ * <i>type</i> can be Slob::BLOB or Slob::CLOB
478
+ *
479
+ * <i>options</i> can be nil or a Hash object with the following possible keys:
480
+ *
481
+ * :sbspace => Sbspace name
482
+ * :estbytes => Estimated size, in bytes
483
+ * :extsz => Allocation extent size
484
+ * :createflags => Create-time flags
485
+ * :openflags => Access mode
486
+ * :maxbytes => Maximum size
487
+ * :col_info => Get the previous values from the column-level storage
488
+ * characteristics for the specified database column
489
+ */
490
+ static VALUE
491
+ rb_slob_s_new(int argc, VALUE *argv, VALUE klass)
492
+ {
493
+ VALUE slob;
494
+
495
+ slob = rb_class_new_instance(argc, argv, klass);
496
+
497
+ if (rb_block_given_p())
498
+ return rb_ensure(rb_yield, slob, rb_slob_close, slob);
499
+
500
+ return slob;
501
+ }
502
+
503
+ /*
504
+ * call-seq:
505
+ * slob.open(access = Slob::RDONLY) => slob
506
+ *
507
+ * Opens the Smart Large Object in <i>access</i> mode.
508
+ *
509
+ * Access modes:
510
+ *
511
+ * Slob::RDONLY:: Read only
512
+ * Slob::DIRTY_READ:: Read uncommitted data
513
+ * Slob::WRONLY:: Write only
514
+ * Slob::APPEND:: Append data to the end, if combined with RDWR or WRONLY; read only otherwise
515
+ * Slob::RDWR:: Read/Write
516
+ * Slob::BUFFER:: Use standard database server buffer pool
517
+ * Slob::NOBUFFER:: Use private buffer from the session pool of the database server
518
+ * Slob::LOCKALL:: Lock the entire Smart Large Object
519
+ * Slob::LOCKRANGE:: Lock a range of bytes
520
+ *
521
+ * Returns __self__.
522
+ */
523
+ static VALUE
524
+ rb_slob_open(int argc, VALUE *argv, VALUE self)
525
+ {
526
+ VALUE access;
527
+ slob_t *slob;
528
+ mint error;
529
+ /*
530
+ * EXEC SQL begin declare section;
531
+ */
532
+ #line 478 "informix.ec"
533
+ #line 479 "informix.ec"
534
+ char *did;
535
+ /*
536
+ * EXEC SQL end declare section;
537
+ */
538
+ #line 480 "informix.ec"
539
+
540
+
541
+ Data_Get_Struct(self, slob_t, slob);
542
+
543
+ if (slob->fd != -1) /* Already open */
544
+ return self;
545
+
546
+ did = slob->database_id;
547
+ /*
548
+ * EXEC SQL set connection :did;
549
+ */
550
+ #line 488 "informix.ec"
551
+ {
552
+ #line 488 "informix.ec"
553
+ sqli_connect_set(0, did, 0);
554
+ #line 488 "informix.ec"
555
+ }
556
+ if (SQLCODE < 0)
557
+ raise_ifx_extended();
558
+
559
+ rb_scan_args(argc, argv, "01", &access);
560
+
561
+ slob->fd = ifx_lo_open(&slob->lo, NIL_P(access)? LO_RDONLY: FIX2INT(access), &error);
562
+
563
+ if (slob->fd == -1)
564
+ raise_ifx_extended();
565
+
566
+ return self;
567
+ }
568
+
569
+ /*
570
+ * call-seq:
571
+ * slob.close => slob
572
+ *
573
+ * Closes the Smart Large Object and returns __self__.
574
+ */
575
+ static VALUE
576
+ rb_slob_close(VALUE self)
577
+ {
578
+ slob_t *slob;
579
+
580
+ Data_Get_Struct(self, slob_t, slob);
581
+ if (slob->fd != -1) {
582
+ /*
583
+ * EXEC SQL begin declare section;
584
+ */
585
+ #line 515 "informix.ec"
586
+ #line 516 "informix.ec"
587
+ char *did;
588
+ /*
589
+ * EXEC SQL end declare section;
590
+ */
591
+ #line 517 "informix.ec"
592
+
593
+
594
+ did = slob->database_id;
595
+ /*
596
+ * EXEC SQL set connection :did;
597
+ */
598
+ #line 520 "informix.ec"
599
+ {
600
+ #line 520 "informix.ec"
601
+ sqli_connect_set(0, did, 0);
602
+ #line 520 "informix.ec"
603
+ }
604
+ if (SQLCODE < 0)
605
+ return self;
606
+
607
+ ifx_lo_close(slob->fd);
608
+ slob->fd = -1;
609
+ }
610
+
611
+ return self;
612
+ }
613
+
614
+ /*
615
+ * call-seq:
616
+ * slob.read(nbytes) => string
617
+ *
618
+ * Reads at most <i>nbytes</i> bytes from the Smart Large Object.
619
+ *
620
+ * Returns the bytes read as a String object.
621
+ */
622
+ static VALUE
623
+ rb_slob_read(VALUE self, VALUE nbytes)
624
+ {
625
+ slob_t *slob;
626
+ mint error, ret;
627
+ char *buffer;
628
+ long c_nbytes;
629
+ VALUE str;
630
+ /*
631
+ * EXEC SQL begin declare section;
632
+ */
633
+ #line 547 "informix.ec"
634
+ #line 548 "informix.ec"
635
+ char *did;
636
+ /*
637
+ * EXEC SQL end declare section;
638
+ */
639
+ #line 549 "informix.ec"
640
+
641
+
642
+
643
+ Data_Get_Struct(self, slob_t, slob);
644
+
645
+ if (slob->fd == -1)
646
+ rb_raise(esyms.eProgrammingError, "Open the Slob object before reading");
647
+
648
+ did = slob->database_id;
649
+ /*
650
+ * EXEC SQL set connection :did;
651
+ */
652
+ #line 558 "informix.ec"
653
+ {
654
+ #line 558 "informix.ec"
655
+ sqli_connect_set(0, did, 0);
656
+ #line 558 "informix.ec"
657
+ }
658
+ if (SQLCODE < 0)
659
+ raise_ifx_extended();
660
+
661
+ c_nbytes = FIX2LONG(nbytes);
662
+ buffer = ALLOC_N(char, c_nbytes);
663
+ ret = ifx_lo_read(slob->fd, buffer, c_nbytes, &error);
664
+
665
+ if (ret == -1) {
666
+ xfree(buffer);
667
+ raise_ifx_extended();
668
+ }
669
+
670
+ str = rb_str_new(buffer, ret);
671
+ xfree(buffer);
672
+
673
+ return str;
674
+ }
675
+
676
+ /*
677
+ * call-seq:
678
+ * slob.write(data) => fixnum or bignum
679
+ *
680
+ * Writes <i>data</i> to the Smart Large Object. If <i>data</i> is not a
681
+ * String object it will be converted to String using <code>to_s</code>.
682
+ *
683
+ * Returns the number of bytes written.
684
+ */
685
+ static VALUE
686
+ rb_slob_write(VALUE self, VALUE data)
687
+ {
688
+ slob_t *slob;
689
+ mint error, ret;
690
+ char *buffer;
691
+ long nbytes;
692
+ VALUE str;
693
+ /*
694
+ * EXEC SQL begin declare section;
695
+ */
696
+ #line 594 "informix.ec"
697
+ #line 595 "informix.ec"
698
+ char *did;
699
+ /*
700
+ * EXEC SQL end declare section;
701
+ */
702
+ #line 596 "informix.ec"
703
+
704
+
705
+ Data_Get_Struct(self, slob_t, slob);
706
+
707
+ if (slob->fd == -1)
708
+ rb_raise(esyms.eProgrammingError, "Open the Slob object before writing");
709
+
710
+ did = slob->database_id;
711
+ /*
712
+ * EXEC SQL set connection :did;
713
+ */
714
+ #line 604 "informix.ec"
715
+ {
716
+ #line 604 "informix.ec"
717
+ sqli_connect_set(0, did, 0);
718
+ #line 604 "informix.ec"
719
+ }
720
+ if (SQLCODE < 0)
721
+ raise_ifx_extended();
722
+
723
+ str = rb_obj_as_string(data);
724
+ buffer = RSTRING(str)->ptr;
725
+ nbytes = RSTRING(str)->len;
726
+
727
+ ret = ifx_lo_write(slob->fd, buffer, nbytes, &error);
728
+
729
+ if (ret == -1)
730
+ raise_ifx_extended();
731
+
732
+ return LONG2NUM(ret);
733
+ }
734
+
735
+ /*
736
+ * call-seq:
737
+ * slob << data => slob
738
+ *
739
+ * Writes <i>data</i> to the Smart Large Object. If <i>data</i> is not a
740
+ * String object it will be converted to String using <code>to_s</code>.
741
+ *
742
+ * Returns self.
743
+ */
744
+ static VALUE
745
+ rb_slob_addstr(VALUE self, VALUE data)
746
+ {
747
+ rb_slob_write(self, data);
748
+ return self;
749
+ }
750
+
751
+ /*
752
+ * call-seq:
753
+ * slob.seek(offset, whence) => fixnum or bignum
754
+ *
755
+ * Sets the file position for the next read or write
756
+ * operation on the open Smart Large Object.
757
+ *
758
+ *
759
+ * <i>offset</i> offset from the starting seek position
760
+ * <i>whence</i> identifies the starting seek position
761
+ *
762
+ * Values for <i>whence</i>:
763
+ *
764
+ * Slob::SEEK_SET:: The start of the Smart Large Object
765
+ * Slob::SEEK_CUR:: The current seek position in the Smart Large Object
766
+ * Slob::SEEK_END:: The end of the Smart Large Object
767
+ *
768
+ * Returns the new position.
769
+ */
770
+ static VALUE
771
+ rb_slob_seek(VALUE self, VALUE offset, VALUE whence)
772
+ {
773
+ slob_t *slob;
774
+ mint ret;
775
+ VALUE seek_pos;
776
+ ifx_int8_t offset8, seek_pos8;
777
+ /*
778
+ * EXEC SQL begin declare section;
779
+ */
780
+ #line 662 "informix.ec"
781
+ #line 663 "informix.ec"
782
+ char *did;
783
+ /*
784
+ * EXEC SQL end declare section;
785
+ */
786
+ #line 664 "informix.ec"
787
+
788
+
789
+ Data_Get_Struct(self, slob_t, slob);
790
+
791
+ if (slob->fd == -1)
792
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
793
+
794
+ did = slob->database_id;
795
+ /*
796
+ * EXEC SQL set connection :did;
797
+ */
798
+ #line 672 "informix.ec"
799
+ {
800
+ #line 672 "informix.ec"
801
+ sqli_connect_set(0, did, 0);
802
+ #line 672 "informix.ec"
803
+ }
804
+ if (SQLCODE < 0)
805
+ raise_ifx_extended();
806
+
807
+ NUM2INT8(offset, &offset8);
808
+ ret = ifx_lo_seek(slob->fd, &offset8, FIX2INT(whence), &seek_pos8);
809
+ if (ret < 0)
810
+ raise_ifx_extended();
811
+
812
+ INT82NUM(&seek_pos8, seek_pos);
813
+
814
+ return seek_pos;
815
+ }
816
+
817
+ /*
818
+ * call-seq:
819
+ * slob.pos = integer => integer
820
+ *
821
+ * Seeks to the given position (in bytes) in _slob_.
822
+ */
823
+ static VALUE
824
+ rb_slob_set_pos(VALUE self, VALUE pos)
825
+ {
826
+ return rb_slob_seek(self, pos, LO_SEEK_SET);
827
+ }
828
+
829
+ /*
830
+ * call-seq:
831
+ * slob.rewind => fixnum
832
+ *
833
+ * Moves the cursor position to the start of the Smart Large Object.
834
+ */
835
+ static VALUE
836
+ rb_slob_rewind(VALUE self)
837
+ {
838
+ return rb_slob_seek(self, INT2FIX(0), LO_SEEK_SET);
839
+ }
840
+
841
+ /*
842
+ * call-seq:
843
+ * slob.tell => integer
844
+ * slob.pos => integer
845
+ *
846
+ * Returns the current file or seek position for an open Smart Large Object
847
+ */
848
+ static VALUE
849
+ rb_slob_tell(VALUE self)
850
+ {
851
+ slob_t *slob;
852
+ mint ret;
853
+ VALUE seek_pos;
854
+ ifx_int8_t seek_pos8;
855
+ /*
856
+ * EXEC SQL begin declare section;
857
+ */
858
+ #line 724 "informix.ec"
859
+ #line 725 "informix.ec"
860
+ char *did;
861
+ /*
862
+ * EXEC SQL end declare section;
863
+ */
864
+ #line 726 "informix.ec"
865
+
866
+
867
+ Data_Get_Struct(self, slob_t, slob);
868
+
869
+ if (slob->fd == -1)
870
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
871
+
872
+ did = slob->database_id;
873
+ /*
874
+ * EXEC SQL set connection :did;
875
+ */
876
+ #line 734 "informix.ec"
877
+ {
878
+ #line 734 "informix.ec"
879
+ sqli_connect_set(0, did, 0);
880
+ #line 734 "informix.ec"
881
+ }
882
+ if (SQLCODE < 0)
883
+ raise_ifx_extended();
884
+
885
+ ret = ifx_lo_tell(slob->fd, &seek_pos8);
886
+ if (ret < 0)
887
+ raise_ifx_extended();
888
+
889
+ INT82NUM(&seek_pos8, seek_pos);
890
+
891
+ return seek_pos;
892
+ }
893
+
894
+ /*
895
+ * call-seq:
896
+ * slob.truncate(offset) => slob
897
+ *
898
+ * Truncates a Smart Large Object at a specified byte position.
899
+ *
900
+ * Returns __self__.
901
+ */
902
+ static VALUE
903
+ rb_slob_truncate(VALUE self, VALUE offset)
904
+ {
905
+ slob_t *slob;
906
+ mint ret;
907
+ ifx_int8_t offset8;
908
+ /*
909
+ * EXEC SQL begin declare section;
910
+ */
911
+ #line 761 "informix.ec"
912
+ #line 762 "informix.ec"
913
+ char *did;
914
+ /*
915
+ * EXEC SQL end declare section;
916
+ */
917
+ #line 763 "informix.ec"
918
+
919
+
920
+ Data_Get_Struct(self, slob_t, slob);
921
+
922
+ if (slob->fd == -1)
923
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
924
+
925
+ did = slob->database_id;
926
+ /*
927
+ * EXEC SQL set connection :did;
928
+ */
929
+ #line 771 "informix.ec"
930
+ {
931
+ #line 771 "informix.ec"
932
+ sqli_connect_set(0, did, 0);
933
+ #line 771 "informix.ec"
934
+ }
935
+ if (SQLCODE < 0)
936
+ raise_ifx_extended();
937
+
938
+ NUM2INT8(offset, &offset8);
939
+ ret = ifx_lo_truncate(slob->fd, &offset8);
940
+ if (ret < 0)
941
+ raise_ifx_extended();
942
+
943
+ return self;
944
+ }
945
+
946
+ /*
947
+ * call-seq:
948
+ * slob.stat => stat
949
+ *
950
+ * Creates and returns an Slob::Stat object with status information for _slob_.
951
+ */
952
+ static VALUE
953
+ rb_slob_stat(VALUE self)
954
+ {
955
+ return rb_class_new_instance(1, &self, rb_cSlobStat);
956
+ }
957
+
958
+ /*
959
+ * call-seq:
960
+ * slob.lock(offset, whence, range, mode) => slob
961
+ *
962
+ * Locks _range_ number of bytes, starting from _offset_ bytes from
963
+ * _whence_, in _mode_ mode.
964
+ *
965
+ * Returns _self_.
966
+ *
967
+ * Possible values:
968
+ *
969
+ * offset => integer
970
+ * whence => Slob::SEEK_SET, Slob::SEEK_CUR, Slob::SEEK_END
971
+ * range => integer, Slob::CURRENT_END, Slob::MAX_END
972
+ * mode => Slob::SHARED_MODE, Slob::EXCLUSIVE_MODE
973
+ */
974
+ static VALUE
975
+ rb_slob_lock(VALUE self, VALUE offset, VALUE whence, VALUE range, VALUE mode)
976
+ {
977
+ slob_t *slob;
978
+ mint ret;
979
+ ifx_int8_t offset8, range8;
980
+ /*
981
+ * EXEC SQL begin declare section;
982
+ */
983
+ #line 817 "informix.ec"
984
+ #line 818 "informix.ec"
985
+ char *did;
986
+ /*
987
+ * EXEC SQL end declare section;
988
+ */
989
+ #line 819 "informix.ec"
990
+
991
+
992
+ Data_Get_Struct(self, slob_t, slob);
993
+
994
+ if (slob->fd == -1)
995
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
996
+
997
+ did = slob->database_id;
998
+ /*
999
+ * EXEC SQL set connection :did;
1000
+ */
1001
+ #line 827 "informix.ec"
1002
+ {
1003
+ #line 827 "informix.ec"
1004
+ sqli_connect_set(0, did, 0);
1005
+ #line 827 "informix.ec"
1006
+ }
1007
+ if (SQLCODE < 0)
1008
+ raise_ifx_extended();
1009
+
1010
+ NUM2INT8(offset, &offset8);
1011
+ NUM2INT8(range, &range8);
1012
+ ret = ifx_lo_lock(slob->fd, &offset8, FIX2INT(whence), &range8, FIX2INT(mode));
1013
+ if (ret < 0)
1014
+ raise_ifx_extended();
1015
+
1016
+ return self;
1017
+ }
1018
+
1019
+ /*
1020
+ * call-seq:
1021
+ * slob.unlock(offset, whence, range) => slob
1022
+ *
1023
+ * Unlocks _range_ number of bytes, starting from _offset_ bytes from
1024
+ * _whence_.
1025
+ *
1026
+ * Returns _self_.
1027
+ *
1028
+ * Possible values:
1029
+ *
1030
+ * offset => integer
1031
+ * whence => Slob::SEEK_SET, Slob::SEEK_CUR, Slob::SEEK_END
1032
+ * range => integer
1033
+ */
1034
+ static VALUE
1035
+ rb_slob_unlock(VALUE self, VALUE offset, VALUE whence, VALUE range)
1036
+ {
1037
+ slob_t *slob;
1038
+ mint ret;
1039
+ ifx_int8_t offset8, range8;
1040
+ /*
1041
+ * EXEC SQL begin declare section;
1042
+ */
1043
+ #line 861 "informix.ec"
1044
+ #line 862 "informix.ec"
1045
+ char *did;
1046
+ /*
1047
+ * EXEC SQL end declare section;
1048
+ */
1049
+ #line 863 "informix.ec"
1050
+
1051
+
1052
+ Data_Get_Struct(self, slob_t, slob);
1053
+
1054
+ if (slob->fd == -1)
1055
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
1056
+
1057
+ did = slob->database_id;
1058
+ /*
1059
+ * EXEC SQL set connection :did;
1060
+ */
1061
+ #line 871 "informix.ec"
1062
+ {
1063
+ #line 871 "informix.ec"
1064
+ sqli_connect_set(0, did, 0);
1065
+ #line 871 "informix.ec"
1066
+ }
1067
+ if (SQLCODE < 0)
1068
+ raise_ifx_extended();
1069
+
1070
+ NUM2INT8(offset, &offset8);
1071
+ NUM2INT8(range, &range8);
1072
+ ret = ifx_lo_unlock(slob->fd, &offset8, FIX2INT(whence), &range8);
1073
+ if (ret < 0)
1074
+ raise_ifx_extended();
1075
+
1076
+ return self;
1077
+ }
1078
+
1079
+ typedef enum {
1080
+ slob_estbytes, slob_extsz, slob_flags, slob_maxbytes, slob_sbspace
1081
+ } slob_option_t;
1082
+ static char *str_slob_options[] = {
1083
+ "estbytes", "extsz", "flags", "maxbytes", "sbspace"};
1084
+ /*
1085
+ * Base function for getting storage charasteristics
1086
+ */
1087
+ static VALUE
1088
+ slob_specget(VALUE self, slob_option_t option)
1089
+ {
1090
+ slob_t *slob;
1091
+ mint ret;
1092
+ ifx_lo_stat_t *stat;
1093
+ ifx_lo_create_spec_t *spec;
1094
+ ifx_int8_t int8;
1095
+ char buffer[129];
1096
+ VALUE item;
1097
+ /*
1098
+ * EXEC SQL begin declare section;
1099
+ */
1100
+ #line 902 "informix.ec"
1101
+ #line 903 "informix.ec"
1102
+ char *did;
1103
+ /*
1104
+ * EXEC SQL end declare section;
1105
+ */
1106
+ #line 904 "informix.ec"
1107
+
1108
+
1109
+ Data_Get_Struct(self, slob_t, slob);
1110
+
1111
+ if (slob->fd == -1)
1112
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
1113
+
1114
+ did = slob->database_id;
1115
+ /*
1116
+ * EXEC SQL set connection :did;
1117
+ */
1118
+ #line 912 "informix.ec"
1119
+ {
1120
+ #line 912 "informix.ec"
1121
+ sqli_connect_set(0, did, 0);
1122
+ #line 912 "informix.ec"
1123
+ }
1124
+ if (SQLCODE < 0)
1125
+ raise_ifx_extended();
1126
+
1127
+ ret = ifx_lo_stat(slob->fd, &stat);
1128
+ if (ret < 0)
1129
+ raise_ifx_extended();
1130
+
1131
+ spec = ifx_lo_stat_cspec(stat);
1132
+ if (spec == NULL) {
1133
+ ifx_lo_stat_free(stat);
1134
+ rb_raise(esyms.eOperationalError, "Unable to get storage characteristics");
1135
+ }
1136
+
1137
+ switch(option) {
1138
+ case slob_estbytes:
1139
+ ret = ifx_lo_specget_estbytes(spec, &int8);
1140
+ break;
1141
+ case slob_extsz:
1142
+ ret = ifx_lo_specget_extsz(spec);
1143
+ break;
1144
+ case slob_flags:
1145
+ ret = ifx_lo_specget_flags(spec);
1146
+ break;
1147
+ case slob_maxbytes:
1148
+ ret = ifx_lo_specget_maxbytes(spec, &int8);
1149
+ break;
1150
+ case slob_sbspace:
1151
+ ret = ifx_lo_specget_sbspace(spec, buffer, sizeof(buffer));
1152
+ }
1153
+
1154
+ ifx_lo_stat_free(stat);
1155
+ if (ret == -1)
1156
+ rb_raise(esyms.eOperationalError, "Unable to get information for %s", str_slob_options[option]);
1157
+
1158
+ switch(option) {
1159
+ case slob_estbytes:
1160
+ case slob_maxbytes:
1161
+ INT82NUM(&int8, item);
1162
+ return item;
1163
+ case slob_extsz:
1164
+ case slob_flags:
1165
+ return INT2FIX(ret);
1166
+ case slob_sbspace:
1167
+ return rb_str_new2(buffer);
1168
+ }
1169
+
1170
+ return Qnil; /* Not reached */
1171
+ }
1172
+
1173
+ /*
1174
+ * Base function for setting extsz and flags
1175
+ */
1176
+ static VALUE
1177
+ slob_specset(VALUE self, slob_option_t option, VALUE value)
1178
+ {
1179
+ slob_t *slob;
1180
+ mint ret;
1181
+ ifx_lo_stat_t *stat;
1182
+ ifx_lo_create_spec_t *spec;
1183
+ /*
1184
+ * EXEC SQL begin declare section;
1185
+ */
1186
+ #line 972 "informix.ec"
1187
+ #line 973 "informix.ec"
1188
+ char *did;
1189
+ /*
1190
+ * EXEC SQL end declare section;
1191
+ */
1192
+ #line 974 "informix.ec"
1193
+
1194
+
1195
+ Data_Get_Struct(self, slob_t, slob);
1196
+
1197
+ if (slob->fd == -1)
1198
+ rb_raise(esyms.eProgrammingError, "Open the Slob object first");
1199
+
1200
+ did = slob->database_id;
1201
+ /*
1202
+ * EXEC SQL set connection :did;
1203
+ */
1204
+ #line 982 "informix.ec"
1205
+ {
1206
+ #line 982 "informix.ec"
1207
+ sqli_connect_set(0, did, 0);
1208
+ #line 982 "informix.ec"
1209
+ }
1210
+ if (SQLCODE < 0)
1211
+ raise_ifx_extended();
1212
+
1213
+ ret = ifx_lo_stat(slob->fd, &stat);
1214
+ if (ret < 0)
1215
+ raise_ifx_extended();
1216
+
1217
+ spec = ifx_lo_stat_cspec(stat);
1218
+ if (spec == NULL) {
1219
+ ifx_lo_stat_free(stat);
1220
+ rb_raise(esyms.eOperationalError, "Unable to get storage characteristics");
1221
+ }
1222
+
1223
+ switch(option) {
1224
+ case slob_extsz:
1225
+ ret = ifx_lo_specset_extsz(spec, FIX2INT(value));
1226
+ break;
1227
+ case slob_flags:
1228
+ ret = ifx_lo_specset_flags(spec, FIX2INT(value));
1229
+ break;
1230
+ default:
1231
+ break; /* Not reached */
1232
+ }
1233
+
1234
+ ifx_lo_stat_free(stat);
1235
+ if (ret == -1)
1236
+ rb_raise(esyms.eOperationalError, "Unable to set information for %s", str_slob_options[option]);
1237
+
1238
+ return value;
1239
+ }
1240
+
1241
+ /*
1242
+ * call-seq:
1243
+ * slob.estbytes => fixnum or bignum
1244
+ *
1245
+ * Returns the estimated size of the SLOB
1246
+ */
1247
+ static VALUE
1248
+ rb_slob_estbytes(VALUE self)
1249
+ {
1250
+ return slob_specget(self, slob_estbytes);
1251
+ }
1252
+
1253
+ /*
1254
+ * call-seq:
1255
+ * slob.extsz => fixnum
1256
+ *
1257
+ * Returns the allocation extent size of the SLOB
1258
+ */
1259
+ static VALUE
1260
+ rb_slob_extsz(VALUE self)
1261
+ {
1262
+ return slob_specget(self, slob_extsz);
1263
+ }
1264
+
1265
+ /*
1266
+ * call-seq:
1267
+ * slob.flags => fixnum
1268
+ *
1269
+ * Returns the create-time flags of the SLOB
1270
+ */
1271
+ static VALUE
1272
+ rb_slob_flags(VALUE self)
1273
+ {
1274
+ return slob_specget(self, slob_flags);
1275
+ }
1276
+
1277
+ /*
1278
+ * call-seq:
1279
+ * slob.maxbytes => fixnum or bignum
1280
+ *
1281
+ * Returns the maximum size of the SLOB
1282
+ */
1283
+ static VALUE
1284
+ rb_slob_maxbytes(VALUE self)
1285
+ {
1286
+ return slob_specget(self, slob_maxbytes);
1287
+ }
1288
+
1289
+ /*
1290
+ * call-seq:
1291
+ * slob.sbspace => string
1292
+ *
1293
+ * Returns the name of the sbspace where the SLOB is stored
1294
+ */
1295
+ static VALUE
1296
+ rb_slob_sbspace(VALUE self)
1297
+ {
1298
+ return slob_specget(self, slob_sbspace);
1299
+ }
1300
+
1301
+ /*
1302
+ * call-seq:
1303
+ * slob.extsz = fixnum => fixnum
1304
+ *
1305
+ * Sets the allocation extent size for the SLOB
1306
+ */
1307
+ static VALUE
1308
+ rb_slob_set_extsz(VALUE self, VALUE value)
1309
+ {
1310
+ return slob_specset(self, slob_extsz, value);
1311
+ }
1312
+
1313
+ /*
1314
+ * call-seq:
1315
+ * slob.flags = fixnum => fixnum
1316
+ *
1317
+ * Sets the create-time flags of the SLOB
1318
+ */
1319
+ static VALUE
1320
+ rb_slob_set_flags(VALUE self, VALUE value)
1321
+ {
1322
+ return slob_specset(self, slob_flags, value);
1323
+ }
1324
+
1325
+ typedef enum { slob_atime, slob_ctime, slob_mtime, slob_refcnt, slob_size } slob_stat_t;
1326
+ static char *str_slob_stats[] = {
1327
+ "atime", "ctime", "mtime", "refcnt", "size"
1328
+ };
1329
+
1330
+ /*
1331
+ * Base function for getting status information
1332
+ */
1333
+ static VALUE
1334
+ slob_stat(VALUE self, slob_stat_t stat)
1335
+ {
1336
+ mint ret;
1337
+ slob_t *slob;
1338
+ ifx_lo_stat_t *st;
1339
+ ifx_int8_t int8;
1340
+ VALUE result;
1341
+ /*
1342
+ * EXEC SQL begin declare section;
1343
+ */
1344
+ #line 1114 "informix.ec"
1345
+ #line 1115 "informix.ec"
1346
+ char *did;
1347
+ /*
1348
+ * EXEC SQL end declare section;
1349
+ */
1350
+ #line 1116 "informix.ec"
1351
+
1352
+
1353
+ Data_Get_Struct(self, slob_t, slob);
1354
+
1355
+ if (slob->fd == -1)
1356
+ rb_raise(esyms.eProgrammingError,
1357
+ "Open the Slob object before getting its status");
1358
+
1359
+ did = slob->database_id;
1360
+ /*
1361
+ * EXEC SQL set connection :did;
1362
+ */
1363
+ #line 1125 "informix.ec"
1364
+ {
1365
+ #line 1125 "informix.ec"
1366
+ sqli_connect_set(0, did, 0);
1367
+ #line 1125 "informix.ec"
1368
+ }
1369
+ if (SQLCODE < 0)
1370
+ raise_ifx_extended();
1371
+
1372
+ ret = ifx_lo_stat(slob->fd, &st);
1373
+
1374
+ if (ret < 0)
1375
+ raise_ifx_extended();
1376
+
1377
+ switch(stat) {
1378
+ case slob_atime:
1379
+ ret = ifx_lo_stat_atime(st);
1380
+ break;
1381
+ case slob_ctime:
1382
+ ret = ifx_lo_stat_ctime(st);
1383
+ break;
1384
+ case slob_mtime:
1385
+ ret = ifx_lo_stat_mtime_sec(st);
1386
+ break;
1387
+ case slob_refcnt:
1388
+ ret = ifx_lo_stat_refcnt(st);
1389
+ break;
1390
+ case slob_size:
1391
+ ret = ifx_lo_stat_size(st, &int8);
1392
+ }
1393
+
1394
+ ifx_lo_stat_free(st);
1395
+
1396
+ if (ret == -1)
1397
+ rb_raise(esyms.eOperationalError, "Unable to get value of %s", str_slob_stats[stat]);
1398
+
1399
+ switch(stat) {
1400
+ case slob_atime:
1401
+ case slob_ctime:
1402
+ case slob_mtime:
1403
+ return rb_time_new(ret, 0);
1404
+ case slob_refcnt:
1405
+ return INT2FIX(ret);
1406
+ case slob_size:
1407
+ INT82NUM(&int8, result);
1408
+ return result;
1409
+ }
1410
+
1411
+ return Qnil; /* Not reached */
1412
+ }
1413
+
1414
+ /*
1415
+ * call-seq:
1416
+ * slob.atime => time
1417
+ *
1418
+ * Returns the time of last access as a Time object.
1419
+ */
1420
+ static VALUE
1421
+ rb_slob_atime(VALUE self)
1422
+ {
1423
+ return slob_stat(self, slob_atime);
1424
+ }
1425
+
1426
+ /*
1427
+ * call-seq:
1428
+ * stat.ctime => time
1429
+ *
1430
+ * Returns the time of last change in status as a Time object.
1431
+ */
1432
+ static VALUE
1433
+ rb_slob_ctime(VALUE self)
1434
+ {
1435
+ return slob_stat(self, slob_ctime);
1436
+ }
1437
+
1438
+ /*
1439
+ * call-seq:
1440
+ * stat.mtime => time
1441
+ *
1442
+ * Returns the time of last modification as a Time object.
1443
+ */
1444
+ static VALUE
1445
+ rb_slob_mtime(VALUE self)
1446
+ {
1447
+ return slob_stat(self, slob_mtime);
1448
+ }
1449
+
1450
+ /*
1451
+ * call-seq:
1452
+ * stat.refcnt => fixnum
1453
+ *
1454
+ * Returns the number of references
1455
+ */
1456
+ static VALUE
1457
+ rb_slob_refcnt(VALUE self)
1458
+ {
1459
+ return slob_stat(self, slob_refcnt);
1460
+ }
1461
+
1462
+ /*
1463
+ * call-seq:
1464
+ * stat.size => fixnum or bignum
1465
+ *
1466
+ * Returns the size in bytes
1467
+ */
1468
+ static VALUE
1469
+ rb_slob_size(VALUE self)
1470
+ {
1471
+ return slob_stat(self, slob_size);
1472
+ }
1473
+
1474
+ /* Helper functions ------------------------------------------------------- */
1475
+
1476
+ /*
1477
+ * Counts the number of markers '?' in the query
1478
+ */
1479
+ static int
1480
+ count_markers(const char *query)
1481
+ {
1482
+ register char c, quote = 0;
1483
+ register int count = 0;
1484
+
1485
+ while((c = *query++)) {
1486
+ if (quote && c != quote)
1487
+ ;
1488
+ else if (quote == c) {
1489
+ quote = 0;
1490
+ }
1491
+ else if (c == '\'' || c == '"') {
1492
+ quote = c;
1493
+ }
1494
+ else if (c == '?') {
1495
+ ++count;
1496
+ }
1497
+ }
1498
+ return count;
1499
+ }
1500
+
1501
+ /*
1502
+ * Allocates memory for the indicators array and slots for the input
1503
+ * parameters, if any. Freed by free_input_slots.
1504
+ */
1505
+ static void
1506
+ alloc_input_slots(cursor_t *c, const char *query)
1507
+ {
1508
+ register int n;
1509
+
1510
+ n = count_markers(query);
1511
+ c->daInput.sqld = n;
1512
+ if (n) {
1513
+ c->daInput.sqlvar = ALLOC_N(struct sqlvar_struct, n);
1514
+ memset(c->daInput.sqlvar, 0, n*sizeof(struct sqlvar_struct));
1515
+ c->indInput = ALLOC_N(short, n);
1516
+ while(n--)
1517
+ c->daInput.sqlvar[n].sqlind = &c->indInput[n];
1518
+ }
1519
+ else {
1520
+ c->daInput.sqlvar = NULL;
1521
+ c->indInput = NULL;
1522
+ }
1523
+ }
1524
+
1525
+ /*
1526
+ * Allocates memory for the output data slots and its indicators array.
1527
+ * Freed by free_output_slots.
1528
+ */
1529
+ static void
1530
+ alloc_output_slots(cursor_t *c)
1531
+ {
1532
+ register int i, count;
1533
+ register short *ind;
1534
+ struct sqlvar_struct *var;
1535
+ register char *buffer;
1536
+
1537
+ c->field_names = rb_ary_new2(c->daOutput->sqld);
1538
+
1539
+ ind = c->indOutput = ALLOC_N(short, c->daOutput->sqld);
1540
+
1541
+ var = c->daOutput->sqlvar;
1542
+ for (i = count = 0; i < c->daOutput->sqld; i++, ind++, var++) {
1543
+ var->sqlind = ind;
1544
+ rb_ary_store(c->field_names, i, rb_str_new2(var->sqlname));
1545
+ if (ISSMARTBLOB(var->sqltype, var->sqlxid)) {
1546
+ var->sqldata = (char *)ALLOC(ifx_lo_t);
1547
+ continue;
1548
+ }
1549
+ var->sqllen = rtypmsize(var->sqltype, var->sqllen);
1550
+ count = rtypalign(count, var->sqltype) + var->sqllen;
1551
+ }
1552
+
1553
+ buffer = c->bfOutput = ALLOC_N(char, count);
1554
+ memset(buffer, 0, count);
1555
+
1556
+ var = c->daOutput->sqlvar;
1557
+ for (i = count = 0; i < c->daOutput->sqld; i++, var++) {
1558
+ if (var->sqldata)
1559
+ continue;
1560
+ count = rtypalign(count, var->sqltype);
1561
+ var->sqldata = buffer + count;
1562
+ count += var->sqllen;
1563
+ if (ISBYTESTYPE(var->sqltype) || ISTEXTTYPE(var->sqltype)) {
1564
+ loc_t *p;
1565
+ p = (loc_t *)var->sqldata;
1566
+ byfill((char *)p, sizeof(loc_t), 0);
1567
+ p->loc_loctype = LOCMEMORY;
1568
+ p->loc_bufsize = -1;
1569
+ }
1570
+ if (var->sqltype == SQLDTIME) {
1571
+ var->sqllen = 0;
1572
+ }
1573
+ }
1574
+ }
1575
+
1576
+ /*
1577
+ * Frees the allocated memory of the input parameters, but not the slots
1578
+ * nor the indicators array. Allocated by bind_input_params.
1579
+ */
1580
+ static void
1581
+ clean_input_slots(cursor_t *c)
1582
+ {
1583
+ register int count;
1584
+ register struct sqlvar_struct *var;
1585
+
1586
+ if (c->daInput.sqlvar == NULL)
1587
+ return;
1588
+ var = c->daInput.sqlvar;
1589
+ count = c->daInput.sqld;
1590
+ while(count--) {
1591
+ if (var->sqldata != NULL) {
1592
+ if (var->sqltype == CLOCATORTYPE) {
1593
+ loc_t *p = (loc_t *)var->sqldata;
1594
+ if (p->loc_buffer != NULL) {
1595
+ xfree(p->loc_buffer);
1596
+ }
1597
+ }
1598
+ xfree(var->sqldata);
1599
+ var->sqldata = NULL;
1600
+ var++;
1601
+ }
1602
+ }
1603
+ }
1604
+
1605
+ /*
1606
+ * Frees the memory for the input parameters, their slots, and the indicators
1607
+ * array. Allocated by alloc_input_slots and bind_input_params.
1608
+ */
1609
+ static void
1610
+ free_input_slots(cursor_t *c)
1611
+ {
1612
+ clean_input_slots(c);
1613
+ if (c->daInput.sqlvar) {
1614
+ xfree(c->daInput.sqlvar);
1615
+ c->daInput.sqlvar = NULL;
1616
+ c->daInput.sqld = 0;
1617
+ }
1618
+ if (c->indInput) {
1619
+ xfree(c->indInput);
1620
+ c->indInput = NULL;
1621
+ }
1622
+ }
1623
+
1624
+ /*
1625
+ * Frees the memory for the output parameters, their slots, and the indicators
1626
+ * array. Allocated by alloc_output_slots.
1627
+ */
1628
+ static void
1629
+ free_output_slots(cursor_t *c)
1630
+ {
1631
+ if (c->daOutput != NULL) {
1632
+ struct sqlvar_struct *var = c->daOutput->sqlvar;
1633
+ if (var) {
1634
+ register int i;
1635
+ for (i = 0; i < c->daOutput->sqld; i++, var++) {
1636
+ if (ISBLOBTYPE(var->sqltype)) {
1637
+ loc_t *p = (loc_t *) var->sqldata;
1638
+ if(p -> loc_buffer)
1639
+ xfree(p->loc_buffer);
1640
+ }
1641
+ if (ISSMARTBLOB(var->sqltype, var->sqlxid))
1642
+ xfree(var->sqldata);
1643
+ }
1644
+ }
1645
+ xfree(c->daOutput);
1646
+ c->daOutput = NULL;
1647
+ }
1648
+ if (c->indOutput != NULL) {
1649
+ xfree(c->indOutput);
1650
+ c->indOutput = NULL;
1651
+ }
1652
+ if (c->bfOutput != NULL) {
1653
+ xfree(c->bfOutput);
1654
+ c->bfOutput = NULL;
1655
+ }
1656
+ }
1657
+
1658
+ /*
1659
+ * Gets an array of Ruby objects as input parameters and place them in input
1660
+ * slots, converting data types and allocating memory as needed.
1661
+ */
1662
+ static void
1663
+ bind_input_params(cursor_t *c, VALUE *argv)
1664
+ {
1665
+ VALUE data, klass;
1666
+ register int i;
1667
+ register struct sqlvar_struct *var;
1668
+
1669
+ var = c->daInput.sqlvar;
1670
+ for (i = 0; i < c->daInput.sqld; i++, var++) {
1671
+ data = argv[i];
1672
+
1673
+ switch(TYPE(data)) {
1674
+ case T_NIL:
1675
+ var->sqltype = CSTRINGTYPE;
1676
+ var->sqldata = NULL;
1677
+ var->sqllen = 0;
1678
+ *var->sqlind = -1;
1679
+ break;
1680
+ case T_FIXNUM:
1681
+ var->sqldata = (char *)ALLOC(long);
1682
+ *((long *)var->sqldata) = FIX2LONG(data);
1683
+ var->sqltype = CLONGTYPE;
1684
+ var->sqllen = sizeof(long);
1685
+ *var->sqlind = 0;
1686
+ break;
1687
+ case T_FLOAT:
1688
+ var->sqldata = (char *)ALLOC(double);
1689
+ *((double *)var->sqldata) = NUM2DBL(data);
1690
+ var->sqltype = CDOUBLETYPE;
1691
+ var->sqllen = sizeof(double);
1692
+ *var->sqlind = 0;
1693
+ break;
1694
+ case T_TRUE:
1695
+ case T_FALSE:
1696
+ var->sqldata = ALLOC(char);
1697
+ *var->sqldata = TYPE(data) == T_TRUE? 't': 'f';
1698
+ var->sqltype = CCHARTYPE;
1699
+ var->sqllen = sizeof(char);
1700
+ *var->sqlind = 0;
1701
+ break;
1702
+ default:
1703
+ klass = rb_obj_class(data);
1704
+ if (klass == rb_cDate) {
1705
+ int2 mdy[3];
1706
+ int4 date;
1707
+
1708
+ mdy[0] = FIX2INT(rb_funcall(data, s_month, 0));
1709
+ mdy[1] = FIX2INT(rb_funcall(data, s_day, 0));
1710
+ mdy[2] = FIX2INT(rb_funcall(data, s_year, 0));
1711
+ rmdyjul(mdy, &date);
1712
+
1713
+ var->sqldata = (char *)ALLOC(int4);
1714
+ *((int4 *)var->sqldata) = date;
1715
+ var->sqltype = CDATETYPE;
1716
+ var->sqllen = sizeof(int4);
1717
+ *var->sqlind = 0;
1718
+ break;
1719
+ }
1720
+ if (klass == rb_cTime) {
1721
+ char buffer[30];
1722
+ short year, month, day, hour, minute, second;
1723
+ int usec;
1724
+ dtime_t *dt;
1725
+
1726
+ year = FIX2INT(rb_funcall(data, s_year, 0));
1727
+ month = FIX2INT(rb_funcall(data, s_month, 0));
1728
+ day = FIX2INT(rb_funcall(data, s_day, 0));
1729
+ hour = FIX2INT(rb_funcall(data, s_hour, 0));
1730
+ minute = FIX2INT(rb_funcall(data, s_min, 0));
1731
+ second = FIX2INT(rb_funcall(data, s_sec, 0));
1732
+ usec = FIX2INT(rb_funcall(data, s_usec, 0));
1733
+
1734
+ dt = ALLOC(dtime_t);
1735
+
1736
+ dt->dt_qual = TU_DTENCODE(TU_YEAR, TU_F5);
1737
+ snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d.%d",
1738
+ year, month, day, hour, minute, second, usec/10);
1739
+ dtcvasc(buffer, dt);
1740
+
1741
+ var->sqldata = (char *)dt;
1742
+ var->sqltype = CDTIMETYPE;
1743
+ var->sqllen = sizeof(dtime_t);
1744
+ *var->sqlind = 0;
1745
+ break;
1746
+ }
1747
+ if (klass == rb_cSlob) {
1748
+ slob_t *slob;
1749
+
1750
+ Data_Get_Struct(data, slob_t, slob);
1751
+
1752
+ var->sqldata = (char *)ALLOC(ifx_lo_t);
1753
+ memcpy(var->sqldata, &slob->lo, sizeof(slob->lo));
1754
+ var->sqltype = SQLUDTFIXED;
1755
+ var->sqlxid = slob->type;
1756
+ var->sqllen = sizeof(ifx_lo_t);
1757
+ *var->sqlind = 0;
1758
+ break;
1759
+ }
1760
+ if (klass == rb_cBigDecimal) {
1761
+ data = rb_funcall(data, s_to_s, 0);
1762
+ var->sqldata = (char *)ALLOC(dec_t);
1763
+ deccvasc(RSTRING(data)->ptr, RSTRING(data)->len,
1764
+ (dec_t *)var->sqldata);
1765
+ var->sqltype = CDECIMALTYPE;
1766
+ var->sqllen = sizeof(dec_t);
1767
+ *var->sqlind = 0;
1768
+ break;
1769
+ }
1770
+ if (rb_respond_to(data, s_read)) {
1771
+ char *str;
1772
+ loc_t *loc;
1773
+ long len;
1774
+
1775
+ data = rb_funcall(data, s_read, 0);
1776
+ data = StringValue(data);
1777
+ str = RSTRING(data)->ptr;
1778
+ len = RSTRING(data)->len;
1779
+
1780
+ loc = (loc_t *)ALLOC(loc_t);
1781
+ byfill((char *)loc, sizeof(loc_t), 0);
1782
+ loc->loc_loctype = LOCMEMORY;
1783
+ loc->loc_buffer = (char *)ALLOC_N(char, len);
1784
+ memcpy(loc->loc_buffer, str, len);
1785
+ loc->loc_bufsize = loc->loc_size = len;
1786
+
1787
+ var->sqldata = (char *)loc;
1788
+ var->sqltype = CLOCATORTYPE;
1789
+ var->sqllen = sizeof(loc_t);
1790
+ *var->sqlind = 0;
1791
+ break;
1792
+ }
1793
+ {
1794
+ VALUE str;
1795
+ str = rb_check_string_type(data);
1796
+ if (NIL_P(str)) {
1797
+ data = rb_obj_as_string(data);
1798
+ }
1799
+ else {
1800
+ data = str;
1801
+ }
1802
+ }
1803
+ case T_STRING: {
1804
+ char *str;
1805
+ long len;
1806
+
1807
+ str = RSTRING(data)->ptr;
1808
+ len = RSTRING(data)->len;
1809
+ var->sqldata = ALLOC_N(char, len + 1);
1810
+ memcpy(var->sqldata, str, len);
1811
+ var->sqldata[len] = 0;
1812
+ var->sqltype = CSTRINGTYPE;
1813
+ var->sqllen = len;
1814
+ *var->sqlind = 0;
1815
+ break;
1816
+ }
1817
+ }
1818
+ }
1819
+ }
1820
+
1821
+ /*
1822
+ * Returns an array or a hash of Ruby objects containing the record fetched.
1823
+ */
1824
+ static VALUE
1825
+ make_result(cursor_t *c, VALUE record)
1826
+ {
1827
+ VALUE item;
1828
+ register int i;
1829
+ register struct sqlvar_struct *var;
1830
+
1831
+ var = c->daOutput->sqlvar;
1832
+ for (i = 0; i < c->daOutput->sqld; i++, var++) {
1833
+ if (*var->sqlind == -1) {
1834
+ item = Qnil;
1835
+ } else {
1836
+ switch(var->sqltype) {
1837
+ case SQLCHAR:
1838
+ case SQLVCHAR:
1839
+ case SQLNCHAR:
1840
+ case SQLNVCHAR:
1841
+ item = rb_str_new2(var->sqldata);
1842
+ break;
1843
+ case SQLSMINT:
1844
+ item = INT2FIX(*(int2 *)var->sqldata);
1845
+ break;
1846
+ case SQLINT:
1847
+ case SQLSERIAL:
1848
+ item = INT2NUM(*(int4 *)var->sqldata);
1849
+ break;
1850
+ case SQLINT8:
1851
+ case SQLSERIAL8:
1852
+ INT82NUM((ifx_int8_t *)var->sqldata, item);
1853
+ break;
1854
+ case SQLSMFLOAT:
1855
+ item = rb_float_new(*(float *)var->sqldata);
1856
+ break;
1857
+ case SQLFLOAT:
1858
+ item = rb_float_new(*(double *)var->sqldata);
1859
+ break;
1860
+ case SQLDATE: {
1861
+ VALUE year, month, day;
1862
+ int2 mdy[3];
1863
+
1864
+ rjulmdy(*(int4 *)var->sqldata, mdy);
1865
+ year = INT2FIX(mdy[2]);
1866
+ month = INT2FIX(mdy[0]);
1867
+ day = INT2FIX(mdy[1]);
1868
+ item = rb_funcall(rb_cDate, s_new, 3, year, month, day);
1869
+ break;
1870
+ }
1871
+ case SQLDTIME: {
1872
+ register short qual, i;
1873
+ short year, month, day, hour, minute, second;
1874
+ int usec;
1875
+ dtime_t dt;
1876
+ register char *dgts;
1877
+
1878
+ month = day = 1;
1879
+ year = hour = minute = second = usec = 0;
1880
+ dt.dt_qual = TU_DTENCODE(TU_YEAR, TU_F5);
1881
+ dtextend((dtime_t *)var->sqldata, &dt);
1882
+ dgts = dt.dt_dec.dec_dgts;
1883
+
1884
+ for (i = 0, qual = TU_YEAR;
1885
+ qual <= TU_F5 && i < dt.dt_dec.dec_ndgts; qual++) {
1886
+ switch(qual) {
1887
+ case TU_YEAR:
1888
+ year = 100*dgts[i++];
1889
+ year += dgts[i++];
1890
+ break;
1891
+ case TU_MONTH:
1892
+ month = dgts[i++];
1893
+ break;
1894
+ case TU_DAY:
1895
+ day = dgts[i++];
1896
+ break;
1897
+ case TU_HOUR:
1898
+ hour = dgts[i++];
1899
+ break;
1900
+ case TU_MINUTE:
1901
+ minute = dgts[i++];
1902
+ break;
1903
+ case TU_SECOND:
1904
+ second = dgts[i++];
1905
+ break;
1906
+ case TU_F1:
1907
+ usec = 10000*dgts[i++];
1908
+ break;
1909
+ case TU_F3:
1910
+ usec += 100*dgts[i++];
1911
+ break;
1912
+ case TU_F5:
1913
+ usec += dgts[i++];
1914
+ break;
1915
+ }
1916
+ }
1917
+
1918
+ item = rb_funcall(rb_cTime, s_utc, 7,
1919
+ INT2FIX(year), INT2FIX(month), INT2FIX(day),
1920
+ INT2FIX(hour), INT2FIX(minute), INT2FIX(second),
1921
+ INT2FIX(usec));
1922
+
1923
+ break;
1924
+ }
1925
+ case SQLDECIMAL:
1926
+ case SQLMONEY: {
1927
+ char buffer[40];
1928
+ mint ret;
1929
+
1930
+ ret = dectoasc((dec_t *)var->sqldata, buffer,
1931
+ sizeof(buffer) - 1, -1);
1932
+ if (ret)
1933
+ rb_raise(esyms.eOperationalError,
1934
+ "Unable to convert DECIMAL to BigDecimal");
1935
+
1936
+ buffer[sizeof(buffer) - 1] = 0;
1937
+ item = rb_funcall(rb_cBigDecimal, s_new, 1, rb_str_new2(buffer));
1938
+ break;
1939
+ }
1940
+ case SQLBOOL:
1941
+ item = var->sqldata[0]? Qtrue: Qfalse;
1942
+ break;
1943
+ case SQLBYTES:
1944
+ case SQLTEXT: {
1945
+ loc_t *loc;
1946
+ loc = (loc_t *)var->sqldata;
1947
+ item = rb_str_new(loc->loc_buffer, loc->loc_size);
1948
+ break;
1949
+ }
1950
+ case SQLUDTFIXED:
1951
+ if (ISSMARTBLOB(var->sqltype, var->sqlxid)) {
1952
+ slob_t *slob;
1953
+
1954
+ item = slob_alloc(rb_cSlob);
1955
+ Data_Get_Struct(item, slob_t, slob);
1956
+ memcpy(&slob->lo, var->sqldata, sizeof(ifx_lo_t));
1957
+ slob->type = var->sqlxid;
1958
+ slob->database_id = c->database_id;
1959
+ slob->db = c->db;
1960
+ break;
1961
+ }
1962
+ case SQLSET:
1963
+ case SQLMULTISET:
1964
+ case SQLLIST:
1965
+ case SQLROW:
1966
+ case SQLCOLLECTION:
1967
+ case SQLROWREF:
1968
+ case SQLUDTVAR:
1969
+ case SQLREFSER8:
1970
+ case SQLLVARCHAR:
1971
+ case SQLSENDRECV:
1972
+ case SQLIMPEXP:
1973
+ case SQLIMPEXPBIN:
1974
+ case SQLUNKNOWN:
1975
+ default:
1976
+ item = Qnil;
1977
+ break;
1978
+ }
1979
+ }
1980
+ if (BUILTIN_TYPE(record) == T_ARRAY) {
1981
+ rb_ary_store(record, i, item);
1982
+ }
1983
+ else {
1984
+ rb_hash_aset(record, RARRAY(c->field_names)->ptr[i], item);
1985
+ }
1986
+ }
1987
+ return record;
1988
+ }
1989
+
1990
+ /* module Informix -------------------------------------------------------- */
1991
+
1992
+ static VALUE rb_database_s_open(int argc, VALUE *argv, VALUE klass);
1993
+ /*
1994
+ * call-seq:
1995
+ * Informix.connect(dbname, user=nil, password=nil) => database
1996
+ * Informix.connect(dbname, user=nil, password=nil) {|database| block } => obj
1997
+ *
1998
+ * Creates a <code>Database</code> object connected to <i>dbname</i> as
1999
+ * <i>user</i> with <i>password</i>. If these are not given, connects to
2000
+ * <i>dbname</i> as the current user.
2001
+ *
2002
+ * The Database object is passed to the block if it's given, and automatically
2003
+ * closes the connection when the block terminates, returning the value of
2004
+ * the block.
2005
+ */
2006
+ static VALUE
2007
+ rb_informix_connect(int argc, VALUE *argv, VALUE self)
2008
+ {
2009
+ return rb_database_s_open(argc, argv, rb_cDatabase);
2010
+ }
2011
+
2012
+ /*
2013
+ * call-seq:
2014
+ * Informix.version => string
2015
+ *
2016
+ * Returns the version of this Ruby/Informix driver.
2017
+ * Note that this is NOT the Informix database version.
2018
+ */
2019
+ static VALUE rb_informix_version(void)
2020
+ {
2021
+ static const char * const ver = "0.6.1";
2022
+ static VALUE driver_version;
2023
+
2024
+ if (driver_version == 0)
2025
+ driver_version = rb_str_freeze(rb_str_new2(ver));
2026
+
2027
+ return driver_version;
2028
+ }
2029
+
2030
+ /* class Database --------------------------------------------------------- */
2031
+
2032
+ static void
2033
+ database_free(void *p)
2034
+ {
2035
+ /*
2036
+ * EXEC SQL begin declare section;
2037
+ */
2038
+ #line 1792 "informix.ec"
2039
+ #line 1793 "informix.ec"
2040
+ char *did;
2041
+ /*
2042
+ * EXEC SQL end declare section;
2043
+ */
2044
+ #line 1794 "informix.ec"
2045
+
2046
+
2047
+ did = p;
2048
+ /*
2049
+ * EXEC SQL disconnect :did;
2050
+ */
2051
+ #line 1797 "informix.ec"
2052
+ {
2053
+ #line 1797 "informix.ec"
2054
+ sqli_connect_close(0, did, 0, 0);
2055
+ #line 1797 "informix.ec"
2056
+ }
2057
+ xfree(p);
2058
+ }
2059
+
2060
+ static VALUE
2061
+ database_alloc(VALUE klass)
2062
+ {
2063
+ char *did;
2064
+
2065
+ did = ALLOC_N(char, IDSIZE<<1);
2066
+ did[0] = did[IDSIZE] = 0;
2067
+ return Data_Wrap_Struct(klass, 0, database_free, did);
2068
+ }
2069
+
2070
+ static VALUE
2071
+ rb_database_initialize(int argc, VALUE *argv, VALUE self)
2072
+ {
2073
+ VALUE arg[3];
2074
+
2075
+ /*
2076
+ * EXEC SQL begin declare section;
2077
+ */
2078
+ #line 1816 "informix.ec"
2079
+ #line 1817 "informix.ec"
2080
+ char *dbname, *user = NULL, *pass = NULL, *did;
2081
+ /*
2082
+ * EXEC SQL end declare section;
2083
+ */
2084
+ #line 1818 "informix.ec"
2085
+
2086
+
2087
+ rb_scan_args(argc, argv, "12", &arg[0], &arg[1], &arg[2]);
2088
+
2089
+ if (NIL_P(arg[0]))
2090
+ rb_raise(esyms.eProgrammingError, "A database name must be specified");
2091
+
2092
+ Data_Get_Struct(self, char, did);
2093
+
2094
+ dbname = StringValueCStr(arg[0]);
2095
+ snprintf(did, IDSIZE, "DB%lX", self);
2096
+
2097
+ if (!NIL_P(arg[1]))
2098
+ user = StringValueCStr(arg[1]);
2099
+
2100
+ if (!NIL_P(arg[2]))
2101
+ pass = StringValueCStr(arg[2]);
2102
+
2103
+ if (user && pass)
2104
+ /*
2105
+ * EXEC SQL connect to :dbname as :did user :user
2106
+ * using :pass with concurrent transaction;
2107
+ */
2108
+ #line 1837 "informix.ec"
2109
+ {
2110
+ #line 1838 "informix.ec"
2111
+ ifx_conn_t *_sqiconn;
2112
+ _sqiconn = (ifx_conn_t *)ifx_alloc_conn_user(user, pass);
2113
+ sqli_connect_open(ESQLINTVERSION, 0, dbname, did, _sqiconn, 1);
2114
+ ifx_free_conn_user(&_sqiconn);
2115
+ #line 1838 "informix.ec"
2116
+ }
2117
+ else
2118
+ /*
2119
+ * EXEC SQL connect to :dbname as :did with concurrent transaction;
2120
+ */
2121
+ #line 1840 "informix.ec"
2122
+ {
2123
+ #line 1840 "informix.ec"
2124
+ sqli_connect_open(ESQLINTVERSION, 0, dbname, did, (ifx_conn_t *)0, 1);
2125
+ #line 1840 "informix.ec"
2126
+ }
2127
+
2128
+ if (SQLCODE < 0)
2129
+ raise_ifx_extended();
2130
+
2131
+ return self;
2132
+ }
2133
+
2134
+ /*
2135
+ * call-seq:
2136
+ * Database.new(dbname, user = nil, password = nil) => database
2137
+ * Database.open(dbname, user = nil, password = nil) => database
2138
+ * Database.new(dbname, user = nil, password = nil) {|database| block } => obj
2139
+ * Database.open(dbname, user = nil, password = nil) {|database| block } => obj
2140
+ *
2141
+ * Creates a <code>Database</code> object connected to <i>dbname</i> as
2142
+ * <i>user</i> with <i>password</i>. If these are not given, connects to
2143
+ * <i>dbname</i> as the current user.
2144
+ *
2145
+ * The Database object is passed to the block if it's given, and automatically
2146
+ * closes the connection when the block terminates, returning the value of
2147
+ * the block.
2148
+ */
2149
+ static VALUE rb_database_close(VALUE self);
2150
+ static VALUE
2151
+ rb_database_s_open(int argc, VALUE *argv, VALUE klass)
2152
+ {
2153
+ VALUE database;
2154
+
2155
+ database = rb_class_new_instance(argc, argv, klass);
2156
+
2157
+ if (rb_block_given_p())
2158
+ return rb_ensure(rb_yield, database, rb_database_close, database);
2159
+
2160
+ return database;
2161
+ }
2162
+
2163
+ /*
2164
+ * call-seq:
2165
+ * db.close => db
2166
+ *
2167
+ * Disconnects <i>db</i> and returns __self__
2168
+ */
2169
+ static VALUE
2170
+ rb_database_close(VALUE self)
2171
+ {
2172
+ /*
2173
+ * EXEC SQL begin declare section;
2174
+ */
2175
+ #line 1886 "informix.ec"
2176
+ #line 1887 "informix.ec"
2177
+ char *did;
2178
+ /*
2179
+ * EXEC SQL end declare section;
2180
+ */
2181
+ #line 1888 "informix.ec"
2182
+
2183
+
2184
+ Data_Get_Struct(self, char, did);
2185
+ did += IDSIZE;
2186
+ if (*did)
2187
+ /*
2188
+ * EXEC SQL free :did;
2189
+ */
2190
+ #line 1893 "informix.ec"
2191
+ {
2192
+ #line 1893 "informix.ec"
2193
+ sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, did, 258));
2194
+ #line 1893 "informix.ec"
2195
+ }
2196
+ did -= IDSIZE;
2197
+ /*
2198
+ * EXEC SQL disconnect :did;
2199
+ */
2200
+ #line 1895 "informix.ec"
2201
+ {
2202
+ #line 1895 "informix.ec"
2203
+ sqli_connect_close(0, did, 0, 0);
2204
+ #line 1895 "informix.ec"
2205
+ }
2206
+
2207
+ return self;
2208
+ }
2209
+
2210
+ /*
2211
+ * call-seq:
2212
+ * db.immediate(query) => fixnum
2213
+ * db.execute(query) => fixnum
2214
+ *
2215
+ * Executes <i>query</i> and returns the number of rows affected.
2216
+ * <i>query</i> must not return rows. Executes efficiently any
2217
+ * non-parameterized or DQL statement.
2218
+ */
2219
+
2220
+ static VALUE
2221
+ rb_database_immediate(VALUE self, VALUE arg)
2222
+ {
2223
+ /*
2224
+ * EXEC SQL begin declare section;
2225
+ */
2226
+ #line 1913 "informix.ec"
2227
+ #line 1914 "informix.ec"
2228
+ char *query, *did;
2229
+ /*
2230
+ * EXEC SQL end declare section;
2231
+ */
2232
+ #line 1915 "informix.ec"
2233
+
2234
+
2235
+ Data_Get_Struct(self, char, did);
2236
+
2237
+ /*
2238
+ * EXEC SQL set connection :did;
2239
+ */
2240
+ #line 1919 "informix.ec"
2241
+ {
2242
+ #line 1919 "informix.ec"
2243
+ sqli_connect_set(0, did, 0);
2244
+ #line 1919 "informix.ec"
2245
+ }
2246
+ if (SQLCODE < 0)
2247
+ raise_ifx_extended();
2248
+
2249
+ query = StringValueCStr(arg);
2250
+ /*
2251
+ * EXEC SQL execute immediate :query;
2252
+ */
2253
+ #line 1924 "informix.ec"
2254
+ {
2255
+ #line 1924 "informix.ec"
2256
+ sqli_exec_immed(query);
2257
+ #line 1924 "informix.ec"
2258
+ }
2259
+ if (SQLCODE < 0)
2260
+ raise_ifx_extended();
2261
+
2262
+ return INT2FIX(sqlca.sqlerrd[2]);
2263
+ }
2264
+
2265
+ /*
2266
+ * call-seq:
2267
+ * db.rollback => db
2268
+ *
2269
+ * Rolls back a transaction and returns __self__.
2270
+ */
2271
+ static VALUE
2272
+ rb_database_rollback(VALUE self)
2273
+ {
2274
+ /*
2275
+ * EXEC SQL begin declare section;
2276
+ */
2277
+ #line 1940 "informix.ec"
2278
+ #line 1941 "informix.ec"
2279
+ char *did;
2280
+ /*
2281
+ * EXEC SQL end declare section;
2282
+ */
2283
+ #line 1942 "informix.ec"
2284
+
2285
+
2286
+ Data_Get_Struct(self, char, did);
2287
+
2288
+ /*
2289
+ * EXEC SQL set connection :did;
2290
+ */
2291
+ #line 1946 "informix.ec"
2292
+ {
2293
+ #line 1946 "informix.ec"
2294
+ sqli_connect_set(0, did, 0);
2295
+ #line 1946 "informix.ec"
2296
+ }
2297
+ if (SQLCODE < 0)
2298
+ raise_ifx_extended();
2299
+
2300
+ /*
2301
+ * EXEC SQL rollback;
2302
+ */
2303
+ #line 1950 "informix.ec"
2304
+ {
2305
+ #line 1950 "informix.ec"
2306
+ sqli_trans_rollback();
2307
+ #line 1950 "informix.ec"
2308
+ }
2309
+ return self;
2310
+ }
2311
+
2312
+ /*
2313
+ * call-seq:
2314
+ * db.commit => db
2315
+ *
2316
+ * Commits a transaction and returns __self__.
2317
+ */
2318
+ static VALUE
2319
+ rb_database_commit(VALUE self)
2320
+ {
2321
+ /*
2322
+ * EXEC SQL begin declare section;
2323
+ */
2324
+ #line 1963 "informix.ec"
2325
+ #line 1964 "informix.ec"
2326
+ char *did;
2327
+ /*
2328
+ * EXEC SQL end declare section;
2329
+ */
2330
+ #line 1965 "informix.ec"
2331
+
2332
+
2333
+ Data_Get_Struct(self, char, did);
2334
+
2335
+ /*
2336
+ * EXEC SQL set connection :did;
2337
+ */
2338
+ #line 1969 "informix.ec"
2339
+ {
2340
+ #line 1969 "informix.ec"
2341
+ sqli_connect_set(0, did, 0);
2342
+ #line 1969 "informix.ec"
2343
+ }
2344
+ if (SQLCODE < 0)
2345
+ raise_ifx_extended();
2346
+
2347
+ /*
2348
+ * EXEC SQL commit;
2349
+ */
2350
+ #line 1973 "informix.ec"
2351
+ {
2352
+ #line 1973 "informix.ec"
2353
+ sqli_trans_commit();
2354
+ #line 1973 "informix.ec"
2355
+ }
2356
+ return self;
2357
+ }
2358
+
2359
+ static VALUE
2360
+ database_transfail(VALUE self)
2361
+ {
2362
+ rb_database_rollback(self);
2363
+ return Qundef;
2364
+ }
2365
+
2366
+ /*
2367
+ * call-seq:
2368
+ * db.transaction {|db| block } => db
2369
+ *
2370
+ * Opens a transaction and executes <i>block</i>, passing __self__ as parameter.
2371
+ * If an exception is raised, the transaction is rolled back. It is commited
2372
+ * otherwise.
2373
+ *
2374
+ * Returns __self__.
2375
+ */
2376
+ static VALUE
2377
+ rb_database_transaction(VALUE self)
2378
+ {
2379
+ VALUE ret;
2380
+ /*
2381
+ * EXEC SQL begin declare section;
2382
+ */
2383
+ #line 1998 "informix.ec"
2384
+ #line 1999 "informix.ec"
2385
+ char *did;
2386
+ /*
2387
+ * EXEC SQL end declare section;
2388
+ */
2389
+ #line 2000 "informix.ec"
2390
+
2391
+
2392
+ Data_Get_Struct(self, char, did);
2393
+
2394
+ /*
2395
+ * EXEC SQL set connection :did;
2396
+ */
2397
+ #line 2004 "informix.ec"
2398
+ {
2399
+ #line 2004 "informix.ec"
2400
+ sqli_connect_set(0, did, 0);
2401
+ #line 2004 "informix.ec"
2402
+ }
2403
+ if (SQLCODE < 0)
2404
+ raise_ifx_extended();
2405
+
2406
+ /*
2407
+ * EXEC SQL commit;
2408
+ */
2409
+ #line 2008 "informix.ec"
2410
+ {
2411
+ #line 2008 "informix.ec"
2412
+ sqli_trans_commit();
2413
+ #line 2008 "informix.ec"
2414
+ }
2415
+
2416
+ /*
2417
+ * EXEC SQL begin work;
2418
+ */
2419
+ #line 2010 "informix.ec"
2420
+ {
2421
+ #line 2010 "informix.ec"
2422
+ sqli_trans_begin2((mint)1);
2423
+ #line 2010 "informix.ec"
2424
+ }
2425
+ ret = rb_rescue(rb_yield, self, database_transfail, self);
2426
+ if (ret == Qundef)
2427
+ rb_raise(esyms.eOperationalError, "Transaction rolled back");
2428
+ /*
2429
+ * EXEC SQL commit;
2430
+ */
2431
+ #line 2014 "informix.ec"
2432
+ {
2433
+ #line 2014 "informix.ec"
2434
+ sqli_trans_commit();
2435
+ #line 2014 "informix.ec"
2436
+ }
2437
+ return self;
2438
+ }
2439
+
2440
+ static VALUE statement_s_new(int, VALUE *, VALUE);
2441
+ /*
2442
+ * call-seq:
2443
+ * db.prepare(query) => statement
2444
+ * db.prepare(query) {|stmt| block } => obj
2445
+ *
2446
+ * Creates a <code>Statement</code> object based on <i>query</i>.
2447
+ * In the first form the Statement object is returned.
2448
+ * In the second form the Statement object is passed to the block and when it
2449
+ * terminates, the Statement object is dropped, returning the value of the
2450
+ * block.
2451
+ *
2452
+ * <i>query</i> may contain '?' placeholders for input parameters;
2453
+ * it must not be a query returning more than one row
2454
+ * (use <code>Database#cursor</code> instead.)
2455
+ */
2456
+ static VALUE
2457
+ rb_database_prepare(VALUE self, VALUE query)
2458
+ {
2459
+ VALUE argv[2];
2460
+
2461
+ argv[0] = self; argv[1] = query;
2462
+ return statement_s_new(2, argv, rb_cStatement);
2463
+ }
2464
+
2465
+ static VALUE rb_cursor_s_new(int argc, VALUE *argv, VALUE klass);
2466
+ /*
2467
+ * call-seq:
2468
+ * db.cursor(query, options = nil) => cursor
2469
+ *
2470
+ * Returns a <code>Cursor</code> object based on <i>query</i>.
2471
+ * <i>query</i> may contain '?' placeholders for input parameters.
2472
+ *
2473
+ * <i>options</i> must be a hash with the following possible keys:
2474
+ *
2475
+ * :scroll => true or false
2476
+ * :hold => true or false
2477
+ *
2478
+ */
2479
+ static VALUE
2480
+ rb_database_cursor(int argc, VALUE *argv, VALUE self)
2481
+ {
2482
+ VALUE arg[3];
2483
+
2484
+ arg[0] = self;
2485
+ rb_scan_args(argc, argv, "11", &arg[1], &arg[2]);
2486
+ return rb_cursor_s_new(3, arg, rb_cCursor);
2487
+ }
2488
+
2489
+ /*
2490
+ * call-seq:
2491
+ * db.slob(type = Slob::CLOB, options = nil) => slob
2492
+ * db.slob(type = Slob::CLOB, options = nil) {|slob| block } => obj
2493
+ *
2494
+ * Creates a Smart Large Object of type <i>type</i>.
2495
+ * Returns a <code>Slob</code> object pointing to it.
2496
+ *
2497
+ * <i>type</i> can be Slob::BLOB or Slob::CLOB
2498
+ *
2499
+ * <i>options</i> can be nil or a Hash object with the following possible keys:
2500
+ *
2501
+ * :sbspace => Sbspace name
2502
+ * :estbytes => Estimated size, in bytes
2503
+ * :extsz => Allocation extent size
2504
+ * :createflags => Create-time flags
2505
+ * :openflags => Access mode
2506
+ * :maxbytes => Maximum size
2507
+ * :col_info => Get the previous values from the column-level storage
2508
+ * characteristics for the specified database column
2509
+ */
2510
+ static VALUE
2511
+ rb_database_slob(int argc, VALUE *argv, VALUE self)
2512
+ {
2513
+ VALUE arg[3];
2514
+
2515
+ arg[0] = self;
2516
+ rb_scan_args(argc, argv, "02", &arg[1], &arg[2]);
2517
+ return rb_slob_s_new(3, arg, rb_cSlob);
2518
+ }
2519
+
2520
+ /*
2521
+ * call-seq:
2522
+ * db.columns(tablename) => array
2523
+ *
2524
+ * Returns an array with information for every column of the given table.
2525
+ */
2526
+ static VALUE
2527
+ rb_database_columns(VALUE self, VALUE tablename)
2528
+ {
2529
+ VALUE v, column, result;
2530
+ char *stype;
2531
+ static char *stypes[] = {
2532
+ "CHAR", "SMALLINT", "INTEGER", "FLOAT", "SMALLFLOAT", "DECIMAL",
2533
+ "SERIAL", "DATE", "MONEY", "NULL", "DATETIME", "BYTE",
2534
+ "TEXT", "VARCHAR", "INTERVAL", "NCHAR", "NVARCHAR", "INT8",
2535
+ "SERIAL8", "SET", "MULTISET", "LIST", "UNNAMED ROW", "NAMED ROW",
2536
+ "VARIABLE-LENGTH OPAQUE TYPE"
2537
+ };
2538
+
2539
+ static char *qualifiers[] = {
2540
+ "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND"
2541
+ };
2542
+
2543
+ /*
2544
+ * EXEC SQL begin declare section;
2545
+ */
2546
+ #line 2121 "informix.ec"
2547
+ #line 2122 "informix.ec"
2548
+ char *did, *cid;
2549
+ char *tabname;
2550
+ int tabid, xid;
2551
+ char colname[129];
2552
+ short coltype, collength;
2553
+ char deftype[2];
2554
+ char defvalue[257];
2555
+ /*
2556
+ * EXEC SQL end declare section;
2557
+ */
2558
+ #line 2129 "informix.ec"
2559
+
2560
+
2561
+ Data_Get_Struct(self, char, did);
2562
+
2563
+ /*
2564
+ * EXEC SQL set connection :did;
2565
+ */
2566
+ #line 2133 "informix.ec"
2567
+ {
2568
+ #line 2133 "informix.ec"
2569
+ sqli_connect_set(0, did, 0);
2570
+ #line 2133 "informix.ec"
2571
+ }
2572
+ if (SQLCODE < 0)
2573
+ raise_ifx_extended();
2574
+
2575
+ tabname = StringValueCStr(tablename);
2576
+
2577
+ /*
2578
+ * EXEC SQL select tabid into :tabid from systables where tabname = :tabname;
2579
+ */
2580
+ #line 2139 "informix.ec"
2581
+ {
2582
+ #line 2139 "informix.ec"
2583
+ static const char *sqlcmdtxt[] =
2584
+ #line 2139 "informix.ec"
2585
+ {
2586
+ #line 2139 "informix.ec"
2587
+ "select tabid from systables where tabname = ?",
2588
+ 0
2589
+ };
2590
+ #line 2139 "informix.ec"
2591
+ static ifx_cursor_t _SQ0 = {0};
2592
+ static ifx_sqlvar_t _sqibind[] =
2593
+ {
2594
+ { 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2595
+ #line 2139 "informix.ec"
2596
+ };
2597
+ static ifx_sqlvar_t _sqobind[] =
2598
+ {
2599
+ { 102, sizeof(tabid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2600
+ #line 2139 "informix.ec"
2601
+ };
2602
+ #line 2139 "informix.ec"
2603
+ _sqibind[0].sqldata = tabname;
2604
+ #line 2139 "informix.ec"
2605
+ _sqobind[0].sqldata = (char *) &tabid;
2606
+ #line 2139 "informix.ec"
2607
+ sqli_slct(ESQLINTVERSION, &_SQ0,sqlcmdtxt,1,_sqibind,1,_sqobind,0,(ifx_literal_t *)0,(ifx_namelist_t *)0,0);
2608
+ #line 2139 "informix.ec"
2609
+ }
2610
+
2611
+ if (SQLCODE == SQLNOTFOUND)
2612
+ rb_raise(esyms.eProgrammingError, "Table '%s' doesn't exist", tabname);
2613
+
2614
+ result = rb_ary_new();
2615
+
2616
+ cid = did + IDSIZE;
2617
+
2618
+ if (!*cid) {
2619
+ /*
2620
+ * EXEC SQL begin declare section;
2621
+ */
2622
+ #line 2149 "informix.ec"
2623
+ #line 2150 "informix.ec"
2624
+ char sid[IDSIZE];
2625
+ /*
2626
+ * EXEC SQL end declare section;
2627
+ */
2628
+ #line 2151 "informix.ec"
2629
+
2630
+
2631
+ snprintf(sid, IDSIZE, "COLS%lX", self);
2632
+ snprintf(cid, IDSIZE, "COLC%lX", self);
2633
+
2634
+ /*
2635
+ * EXEC SQL prepare :sid from
2636
+ * 'select colname, coltype, collength, extended_id,
2637
+ * type, default, c.colno
2638
+ * from syscolumns c, outer sysdefaults d
2639
+ * where c.tabid = ? and c.tabid = d.tabid
2640
+ * and c.colno = d.colno
2641
+ * order by c.colno';
2642
+ */
2643
+ #line 2156 "informix.ec"
2644
+ {
2645
+ #line 2162 "informix.ec"
2646
+ sqli_prep(ESQLINTVERSION, sid, "select colname, coltype, collength, extended_id, type, default, c.colno from syscolumns c, outer sysdefaults d where c.tabid = ? and c.tabid = d.tabid and c.colno = d.colno order by c.colno",(ifx_literal_t *)0, (ifx_namelist_t *)0, 2, 0, 0 );
2647
+ #line 2162 "informix.ec"
2648
+ }
2649
+ /*
2650
+ * EXEC SQL declare :cid cursor for :sid;
2651
+ */
2652
+ #line 2163 "informix.ec"
2653
+ {
2654
+ #line 2163 "informix.ec"
2655
+ sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 0, 0);
2656
+ #line 2163 "informix.ec"
2657
+ }
2658
+ if (SQLCODE < 0) {
2659
+ cid[0] = 0;
2660
+ raise_ifx_extended();
2661
+ }
2662
+ }
2663
+
2664
+ /*
2665
+ * EXEC SQL open :cid using :tabid;
2666
+ */
2667
+ #line 2170 "informix.ec"
2668
+ {
2669
+ #line 2170 "informix.ec"
2670
+ static ifx_sqlvar_t _sqibind[] =
2671
+ {
2672
+ { 102, sizeof(tabid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2673
+ #line 2170 "informix.ec"
2674
+ };
2675
+ static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
2676
+ #line 2170 "informix.ec"
2677
+ _sqibind[0].sqldata = (char *) &tabid;
2678
+ sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, (char *)0, (struct value *)0, 1, 0);
2679
+ #line 2170 "informix.ec"
2680
+ }
2681
+ if (SQLCODE < 0)
2682
+ raise_ifx_extended();
2683
+
2684
+ for(;;) {
2685
+ /*
2686
+ * EXEC SQL fetch :cid into :colname, :coltype, :collength, :xid,
2687
+ * :deftype, :defvalue;
2688
+ */
2689
+ #line 2175 "informix.ec"
2690
+ {
2691
+ #line 2176 "informix.ec"
2692
+ static ifx_sqlvar_t _sqobind[] =
2693
+ {
2694
+ { 114, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2695
+ { 101, sizeof(coltype), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2696
+ { 101, sizeof(collength), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2697
+ { 102, sizeof(xid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2698
+ { 100, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2699
+ { 114, 257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2700
+ #line 2176 "informix.ec"
2701
+ };
2702
+ static ifx_sqlda_t _SD0 = { 6, _sqobind, {0}, 6, 0 };
2703
+ static _FetchSpec _FS1 = { 0, 1, 0 };
2704
+ #line 2176 "informix.ec"
2705
+ _sqobind[0].sqldata = colname;
2706
+ #line 2176 "informix.ec"
2707
+ _sqobind[1].sqldata = (char *) &coltype;
2708
+ #line 2176 "informix.ec"
2709
+ _sqobind[2].sqldata = (char *) &collength;
2710
+ #line 2176 "informix.ec"
2711
+ _sqobind[3].sqldata = (char *) &xid;
2712
+ #line 2176 "informix.ec"
2713
+ _sqobind[4].sqldata = deftype;
2714
+ #line 2176 "informix.ec"
2715
+ _sqobind[5].sqldata = defvalue;
2716
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, &_SD0, (char *)0, &_FS1);
2717
+ #line 2176 "informix.ec"
2718
+ }
2719
+ if (SQLCODE < 0)
2720
+ raise_ifx_extended();
2721
+
2722
+ if (SQLCODE == SQLNOTFOUND)
2723
+ break;
2724
+
2725
+ column = rb_hash_new();
2726
+ rb_hash_aset(column, sym_name, rb_str_new2(colname));
2727
+ rb_hash_aset(column, sym_type, INT2FIX(coltype));
2728
+ rb_hash_aset(column, sym_nullable, coltype&0x100? Qfalse: Qtrue);
2729
+ rb_hash_aset(column, sym_xid, INT2FIX(xid));
2730
+
2731
+ if ((coltype&0xFF) < 23) {
2732
+ stype = coltype == 4118? stypes[23]: stypes[coltype&0xFF];
2733
+ }
2734
+ else {
2735
+ stype = stypes[24];
2736
+ }
2737
+ rb_hash_aset(column, sym_stype, rb_str_new2(stype));
2738
+ rb_hash_aset(column, sym_length, INT2FIX(collength));
2739
+
2740
+ switch(coltype&0xFF) {
2741
+ case SQLVCHAR:
2742
+ case SQLNVCHAR:
2743
+ case SQLMONEY:
2744
+ case SQLDECIMAL:
2745
+ rb_hash_aset(column, sym_precision, INT2FIX(collength >> 8));
2746
+ rb_hash_aset(column, sym_scale, INT2FIX(collength&0xFF));
2747
+ break;
2748
+ case SQLDATE:
2749
+ case SQLDTIME:
2750
+ case SQLINTERVAL:
2751
+ rb_hash_aset(column, sym_length, INT2FIX(collength >> 8));
2752
+ rb_hash_aset(column, sym_precision, INT2FIX((collength&0xF0) >> 4));
2753
+ rb_hash_aset(column, sym_scale, INT2FIX(collength&0xF));
2754
+ break;
2755
+ default:
2756
+ rb_hash_aset(column, sym_precision, INT2FIX(0));
2757
+ rb_hash_aset(column, sym_scale, INT2FIX(0));
2758
+ }
2759
+
2760
+ if (!deftype[0]) {
2761
+ v = Qnil;
2762
+ }
2763
+ else {
2764
+ switch(deftype[0]) {
2765
+ case 'C': {
2766
+ char current[28];
2767
+ snprintf(current, sizeof(current), "CURRENT %s TO %s",
2768
+ qualifiers[(collength&0xF0) >> 5],
2769
+ qualifiers[(collength&0xF)>>1]);
2770
+ v = rb_str_new2(current);
2771
+ break;
2772
+ }
2773
+ case 'L':
2774
+ switch (coltype & 0xFF) {
2775
+ case SQLCHAR:
2776
+ case SQLNCHAR:
2777
+ case SQLVCHAR:
2778
+ case SQLNVCHAR:
2779
+ v = rb_str_new2(defvalue);
2780
+ break;
2781
+ default: {
2782
+ char *s = defvalue;
2783
+ while(*s++ != ' ');
2784
+ if ((coltype&0xFF) == SQLFLOAT ||
2785
+ (coltype&0xFF) == SQLSMFLOAT ||
2786
+ (coltype&0xFF) == SQLMONEY ||
2787
+ (coltype&0xFF) == SQLDECIMAL)
2788
+ v = rb_float_new(atof(s));
2789
+ else
2790
+ v = LONG2FIX(atol(s));
2791
+ }
2792
+ }
2793
+ break;
2794
+ case 'N':
2795
+ v = rb_str_new2("NULL");
2796
+ break;
2797
+ case 'T':
2798
+ v = rb_str_new2("today");
2799
+ break;
2800
+ case 'U':
2801
+ v = rb_str_new2("user");
2802
+ break;
2803
+ case 'S':
2804
+ default: /* XXX */
2805
+ v = Qnil;
2806
+ }
2807
+ }
2808
+ rb_hash_aset(column, sym_default, v);
2809
+ rb_ary_push(result, column);
2810
+ }
2811
+
2812
+ /*
2813
+ * EXEC SQL close :cid;
2814
+ */
2815
+ #line 2270 "informix.ec"
2816
+ {
2817
+ #line 2270 "informix.ec"
2818
+ sqli_curs_close(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256));
2819
+ #line 2270 "informix.ec"
2820
+ }
2821
+
2822
+ return result;
2823
+ }
2824
+
2825
+ /* class Statement ------------------------------------------------------- */
2826
+
2827
+ static void
2828
+ statement_mark(cursor_t *c)
2829
+ {
2830
+ rb_gc_mark(c->db);
2831
+ if (c->array)
2832
+ rb_gc_mark(c->array);
2833
+ if (c->hash)
2834
+ rb_gc_mark(c->hash);
2835
+ if (c->field_names)
2836
+ rb_gc_mark(c->field_names);
2837
+ }
2838
+
2839
+ static void
2840
+ statement_free(void *p)
2841
+ {
2842
+ /*
2843
+ * EXEC SQL begin declare section;
2844
+ */
2845
+ #line 2292 "informix.ec"
2846
+ #line 2293 "informix.ec"
2847
+ char *sid, *did;
2848
+ /*
2849
+ * EXEC SQL end declare section;
2850
+ */
2851
+ #line 2294 "informix.ec"
2852
+
2853
+
2854
+ free_input_slots(p);
2855
+ free_output_slots(p);
2856
+
2857
+ did = ((cursor_t *)p)->database_id;
2858
+ /*
2859
+ * EXEC SQL set connection :did;
2860
+ */
2861
+ #line 2300 "informix.ec"
2862
+ {
2863
+ #line 2300 "informix.ec"
2864
+ sqli_connect_set(0, did, 0);
2865
+ #line 2300 "informix.ec"
2866
+ }
2867
+ if (SQLCODE >= 0) {
2868
+ sid = ((cursor_t *)p)->stmt_id;
2869
+ /*
2870
+ * EXEC SQL free :sid;
2871
+ */
2872
+ #line 2303 "informix.ec"
2873
+ {
2874
+ #line 2303 "informix.ec"
2875
+ sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
2876
+ #line 2303 "informix.ec"
2877
+ }
2878
+ }
2879
+
2880
+ xfree(p);
2881
+ }
2882
+
2883
+ static VALUE
2884
+ statement_alloc(VALUE klass)
2885
+ {
2886
+ cursor_t *c;
2887
+
2888
+ c = ALLOC(cursor_t);
2889
+ memset(c, 0, sizeof(cursor_t));
2890
+ return Data_Wrap_Struct(klass, statement_mark, statement_free, c);
2891
+ }
2892
+
2893
+ static VALUE
2894
+ statement_initialize(VALUE self, VALUE db, VALUE query)
2895
+ {
2896
+ struct sqlda *output;
2897
+ cursor_t *c;
2898
+ /*
2899
+ * EXEC SQL begin declare section;
2900
+ */
2901
+ #line 2324 "informix.ec"
2902
+ #line 2325 "informix.ec"
2903
+ char *c_query, *sid, *did;
2904
+ /*
2905
+ * EXEC SQL end declare section;
2906
+ */
2907
+ #line 2326 "informix.ec"
2908
+
2909
+
2910
+ Data_Get_Struct(db, char, did);
2911
+ /*
2912
+ * EXEC SQL set connection :did;
2913
+ */
2914
+ #line 2329 "informix.ec"
2915
+ {
2916
+ #line 2329 "informix.ec"
2917
+ sqli_connect_set(0, did, 0);
2918
+ #line 2329 "informix.ec"
2919
+ }
2920
+ if (SQLCODE < 0)
2921
+ raise_ifx_extended();
2922
+
2923
+ Data_Get_Struct(self, cursor_t, c);
2924
+ c->db = db;
2925
+ c->database_id = did;
2926
+ output = c->daOutput;
2927
+ snprintf(c->stmt_id, sizeof(c->stmt_id), "STMT%lX", self);
2928
+ sid = c->stmt_id;
2929
+ c_query = StringValueCStr(query);
2930
+
2931
+ /*
2932
+ * EXEC SQL prepare :sid from :c_query;
2933
+ */
2934
+ #line 2341 "informix.ec"
2935
+ {
2936
+ #line 2341 "informix.ec"
2937
+ sqli_prep(ESQLINTVERSION, sid, c_query,(ifx_literal_t *)0, (ifx_namelist_t *)0, -1, 0, 0 );
2938
+ #line 2341 "informix.ec"
2939
+ }
2940
+ if (SQLCODE < 0)
2941
+ raise_ifx_extended();
2942
+
2943
+ alloc_input_slots(c, c_query);
2944
+ /*
2945
+ * EXEC SQL describe :sid into output;
2946
+ */
2947
+ #line 2346 "informix.ec"
2948
+ {
2949
+ #line 2346 "informix.ec"
2950
+ sqli_describe_stmt(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), &output, 0);
2951
+ #line 2346 "informix.ec"
2952
+ }
2953
+ c->daOutput = output;
2954
+
2955
+ c->is_select = (SQLCODE == 0 || SQLCODE == SQ_EXECPROC);
2956
+
2957
+ if (c->is_select)
2958
+ alloc_output_slots(c);
2959
+ else {
2960
+ xfree(c->daOutput);
2961
+ c->daOutput = NULL;
2962
+ }
2963
+
2964
+ return self;
2965
+ }
2966
+
2967
+ static VALUE statement_drop(VALUE);
2968
+ /*
2969
+ * call-seq:
2970
+ * Statement.new(database, query) => statement
2971
+ * Statement.new(database, query) {|stmt| block } => obj
2972
+ *
2973
+ * Creates a <code>Statement</code> object based on <i>query</i> in the
2974
+ * context of <i>database</i>.
2975
+ * In the first form the <code>Statement</code> object is returned.
2976
+ * In the second form the Statement object is passed to the block and when it
2977
+ * terminates, the Statement object is dropped, returning the value of the
2978
+ * block.
2979
+ *
2980
+ * <i>query</i> may contain '?' placeholders for input parameters;
2981
+ * it must not be a query returning more than one row
2982
+ * (use <code>Cursor</code> instead.)
2983
+ */
2984
+ static VALUE
2985
+ statement_s_new(int argc, VALUE *argv, VALUE klass)
2986
+ {
2987
+ VALUE stmt;
2988
+
2989
+ stmt = rb_class_new_instance(argc, argv, klass);
2990
+
2991
+ if (rb_block_given_p())
2992
+ return rb_ensure(rb_yield, stmt, statement_drop, stmt);
2993
+
2994
+ return stmt;
2995
+ }
2996
+
2997
+ /*
2998
+ * call-seq:
2999
+ * stmt[*params] => fixnum or hash
3000
+ *
3001
+ * Executes the previously prepared statement, binding <i>params</i> as
3002
+ * input parameters.
3003
+ *
3004
+ * Returns the record retrieved, in the case of a singleton select, or the
3005
+ * number of rows affected, in the case of any other statement.
3006
+ */
3007
+ static VALUE
3008
+ statement_call(int argc, VALUE *argv, VALUE self)
3009
+ {
3010
+ struct sqlda *input, *output;
3011
+ cursor_t *c;
3012
+ /*
3013
+ * EXEC SQL begin declare section;
3014
+ */
3015
+ #line 2406 "informix.ec"
3016
+ #line 2407 "informix.ec"
3017
+ char *sid, *did;
3018
+ /*
3019
+ * EXEC SQL end declare section;
3020
+ */
3021
+ #line 2408 "informix.ec"
3022
+
3023
+
3024
+ Data_Get_Struct(self, cursor_t, c);
3025
+
3026
+ did = c->database_id;
3027
+ /*
3028
+ * EXEC SQL set connection :did;
3029
+ */
3030
+ #line 2413 "informix.ec"
3031
+ {
3032
+ #line 2413 "informix.ec"
3033
+ sqli_connect_set(0, did, 0);
3034
+ #line 2413 "informix.ec"
3035
+ }
3036
+ if (SQLCODE < 0)
3037
+ raise_ifx_extended();
3038
+
3039
+ output = c->daOutput;
3040
+ input = &c->daInput;
3041
+ sid = c->stmt_id;
3042
+
3043
+ if (argc != input->sqld)
3044
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
3045
+ argc, input->sqld);
3046
+
3047
+ if (c->is_select) {
3048
+ if (argc) {
3049
+ bind_input_params(c, argv);
3050
+ /*
3051
+ * EXEC SQL execute :sid into descriptor output
3052
+ * using descriptor input;
3053
+ */
3054
+ #line 2428 "informix.ec"
3055
+ {
3056
+ #line 2429 "informix.ec"
3057
+ sqli_exec(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), input, (char *)0, (struct value *)0, output, (char *)0, (struct value *)0, 0);
3058
+ #line 2429 "informix.ec"
3059
+ }
3060
+ clean_input_slots(c);
3061
+ }
3062
+ else
3063
+ /*
3064
+ * EXEC SQL execute :sid into descriptor output;
3065
+ */
3066
+ #line 2433 "informix.ec"
3067
+ {
3068
+ #line 2433 "informix.ec"
3069
+ sqli_exec(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, output, (char *)0, (struct value *)0, 0);
3070
+ #line 2433 "informix.ec"
3071
+ }
3072
+
3073
+ if (SQLCODE < 0)
3074
+ raise_ifx_extended();
3075
+
3076
+ if (SQLCODE == SQLNOTFOUND)
3077
+ return Qnil;
3078
+ return make_result(c, rb_hash_new());
3079
+ }
3080
+ else {
3081
+ if (argc) {
3082
+ bind_input_params(c, argv);
3083
+ /*
3084
+ * EXEC SQL execute :sid using descriptor input;
3085
+ */
3086
+ #line 2445 "informix.ec"
3087
+ {
3088
+ #line 2445 "informix.ec"
3089
+ sqli_exec(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), input, (char *)0, (struct value *)0, (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0);
3090
+ #line 2445 "informix.ec"
3091
+ }
3092
+ clean_input_slots(c);
3093
+ }
3094
+ else
3095
+ /*
3096
+ * EXEC SQL execute :sid;
3097
+ */
3098
+ #line 2449 "informix.ec"
3099
+ {
3100
+ #line 2449 "informix.ec"
3101
+ sqli_exec(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0);
3102
+ #line 2449 "informix.ec"
3103
+ }
3104
+ }
3105
+ if (SQLCODE < 0)
3106
+ raise_ifx_extended();
3107
+
3108
+ return INT2FIX(sqlca.sqlerrd[2]);
3109
+ }
3110
+
3111
+ /*
3112
+ * call-seq:
3113
+ * stmt.drop
3114
+ *
3115
+ * Frees the statement and the memory associated with it.
3116
+ */
3117
+ static VALUE
3118
+ statement_drop(VALUE self)
3119
+ {
3120
+ cursor_t *c;
3121
+ /*
3122
+ * EXEC SQL begin declare section;
3123
+ */
3124
+ #line 2467 "informix.ec"
3125
+ #line 2468 "informix.ec"
3126
+ char *sid, *did;
3127
+ /*
3128
+ * EXEC SQL end declare section;
3129
+ */
3130
+ #line 2469 "informix.ec"
3131
+
3132
+
3133
+ Data_Get_Struct(self, cursor_t, c);
3134
+ free_input_slots(c);
3135
+ free_output_slots(c);
3136
+
3137
+ did = c->database_id;
3138
+ /*
3139
+ * EXEC SQL set connection :did;
3140
+ */
3141
+ #line 2476 "informix.ec"
3142
+ {
3143
+ #line 2476 "informix.ec"
3144
+ sqli_connect_set(0, did, 0);
3145
+ #line 2476 "informix.ec"
3146
+ }
3147
+ if (SQLCODE < 0)
3148
+ return Qnil;
3149
+ sid = c->stmt_id;
3150
+ /*
3151
+ * EXEC SQL free :sid;
3152
+ */
3153
+ #line 2480 "informix.ec"
3154
+ {
3155
+ #line 2480 "informix.ec"
3156
+ sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
3157
+ #line 2480 "informix.ec"
3158
+ }
3159
+
3160
+ return Qnil;
3161
+ }
3162
+
3163
+ /* module SequentialCursor ----------------------------------------------- */
3164
+
3165
+ /* Decides whether to use an Array or a Hash, and instantiate a new
3166
+ * object or reuse an existing one.
3167
+ */
3168
+ #define RECORD(c, type, bang, record) \
3169
+ do {\
3170
+ if (type == T_ARRAY) {\
3171
+ if (bang) {\
3172
+ if (!c->array)\
3173
+ c->array = rb_ary_new2(c->daOutput->sqld);\
3174
+ record = c->array;\
3175
+ }\
3176
+ else\
3177
+ record = rb_ary_new2(c->daOutput->sqld);\
3178
+ }\
3179
+ else {\
3180
+ if (bang) {\
3181
+ if (!c->hash)\
3182
+ c->hash = rb_hash_new();\
3183
+ record = c->hash;\
3184
+ }\
3185
+ else\
3186
+ record = rb_hash_new();\
3187
+ }\
3188
+ }while(0)
3189
+
3190
+ /*
3191
+ * Base function for fetch* methods, except *_many
3192
+ */
3193
+ static VALUE
3194
+ fetch(VALUE self, VALUE type, int bang)
3195
+ {
3196
+ /*
3197
+ * EXEC SQL begin declare section;
3198
+ */
3199
+ #line 2518 "informix.ec"
3200
+ #line 2519 "informix.ec"
3201
+ char *cid, *did;
3202
+ /*
3203
+ * EXEC SQL end declare section;
3204
+ */
3205
+ #line 2520 "informix.ec"
3206
+
3207
+ cursor_t *c;
3208
+ struct sqlda *output;
3209
+ VALUE record;
3210
+
3211
+ Data_Get_Struct(self, cursor_t, c);
3212
+ if (!c->is_open)
3213
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3214
+
3215
+ did = c->database_id;
3216
+ /*
3217
+ * EXEC SQL set connection :did;
3218
+ */
3219
+ #line 2530 "informix.ec"
3220
+ {
3221
+ #line 2530 "informix.ec"
3222
+ sqli_connect_set(0, did, 0);
3223
+ #line 2530 "informix.ec"
3224
+ }
3225
+ if (SQLCODE < 0)
3226
+ raise_ifx_extended();
3227
+
3228
+ output = c->daOutput;
3229
+ cid = c->cursor_id;
3230
+
3231
+ /*
3232
+ * EXEC SQL fetch :cid using descriptor output;
3233
+ */
3234
+ #line 2537 "informix.ec"
3235
+ {
3236
+ #line 2537 "informix.ec"
3237
+ static _FetchSpec _FS0 = { 0, 1, 0 };
3238
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
3239
+ #line 2537 "informix.ec"
3240
+ }
3241
+ if (SQLCODE < 0)
3242
+ raise_ifx_extended();
3243
+
3244
+ if (SQLCODE == SQLNOTFOUND)
3245
+ return Qnil;
3246
+
3247
+ RECORD(c, type, bang, record);
3248
+ return make_result(c, record);
3249
+ }
3250
+
3251
+ /*
3252
+ * call-seq:
3253
+ * cursor.fetch => array or nil
3254
+ *
3255
+ * Fetches the next record.
3256
+ *
3257
+ * Returns the record fetched as an array, or nil if there are no
3258
+ * records left.
3259
+ */
3260
+ static VALUE
3261
+ seqcur_fetch(VALUE self)
3262
+ {
3263
+ return fetch(self, T_ARRAY, 0);
3264
+ }
3265
+
3266
+ /*
3267
+ * call-seq:
3268
+ * cursor.fetch! => array or nil
3269
+ *
3270
+ * Fetches the next record, storing it in the same Array object every time
3271
+ * it is called.
3272
+ *
3273
+ * Returns the record fetched as an array, or nil if there are no
3274
+ * records left.
3275
+ */
3276
+ static VALUE
3277
+ seqcur_fetch_bang(VALUE self)
3278
+ {
3279
+ return fetch(self, T_ARRAY, 1);
3280
+ }
3281
+
3282
+ /*
3283
+ * call-seq:
3284
+ * cursor.fetch_hash => hash or nil
3285
+ *
3286
+ * Fetches the next record.
3287
+ *
3288
+ * Returns the record fetched as a hash, or nil if there are no
3289
+ * records left.
3290
+ */
3291
+ static VALUE
3292
+ seqcur_fetch_hash(VALUE self)
3293
+ {
3294
+ return fetch(self, T_HASH, 0);
3295
+ }
3296
+
3297
+ /*
3298
+ * call-seq:
3299
+ * cursor.fetch_hash! => hash or nil
3300
+ *
3301
+ * Fetches the next record, storing it in the same Hash object every time
3302
+ * it is called.
3303
+ *
3304
+ * Returns the record fetched as a hash, or nil if there are no
3305
+ * records left.
3306
+ */
3307
+ static VALUE
3308
+ seqcur_fetch_hash_bang(VALUE self)
3309
+ {
3310
+ return fetch(self, T_HASH, 1);
3311
+ }
3312
+
3313
+ /*
3314
+ * Base function for fetch*_many, fetch*_all and each_by methods
3315
+ */
3316
+ static VALUE
3317
+ fetch_many(VALUE self, VALUE n, VALUE type)
3318
+ {
3319
+ /*
3320
+ * EXEC SQL begin declare section;
3321
+ */
3322
+ #line 2616 "informix.ec"
3323
+ #line 2617 "informix.ec"
3324
+ char *cid, *did;
3325
+ /*
3326
+ * EXEC SQL end declare section;
3327
+ */
3328
+ #line 2618 "informix.ec"
3329
+
3330
+ cursor_t *c;
3331
+ struct sqlda *output;
3332
+ VALUE record, records;
3333
+ register long i, max;
3334
+ register int all = n == Qnil;
3335
+
3336
+ Data_Get_Struct(self, cursor_t, c);
3337
+ if (!c->is_open)
3338
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3339
+
3340
+ did = c->database_id;
3341
+ /*
3342
+ * EXEC SQL set connection :did;
3343
+ */
3344
+ #line 2630 "informix.ec"
3345
+ {
3346
+ #line 2630 "informix.ec"
3347
+ sqli_connect_set(0, did, 0);
3348
+ #line 2630 "informix.ec"
3349
+ }
3350
+ if (SQLCODE < 0)
3351
+ raise_ifx_extended();
3352
+
3353
+ output = c->daOutput;
3354
+ cid = c->cursor_id;
3355
+
3356
+ if (!all) {
3357
+ max = FIX2LONG(n);
3358
+ records = rb_ary_new2(max);
3359
+ }
3360
+ else {
3361
+ records = rb_ary_new();
3362
+ }
3363
+
3364
+ for(i = 0; all || i < max; i++) {
3365
+ /*
3366
+ * EXEC SQL fetch :cid using descriptor output;
3367
+ */
3368
+ #line 2646 "informix.ec"
3369
+ {
3370
+ #line 2646 "informix.ec"
3371
+ static _FetchSpec _FS0 = { 0, 1, 0 };
3372
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
3373
+ #line 2646 "informix.ec"
3374
+ }
3375
+ if (SQLCODE < 0)
3376
+ raise_ifx_extended();
3377
+
3378
+ if (SQLCODE == SQLNOTFOUND)
3379
+ break;
3380
+
3381
+ if (type == T_ARRAY)
3382
+ record = rb_ary_new2(c->daOutput->sqld);
3383
+ else
3384
+ record = rb_hash_new();
3385
+ rb_ary_store(records, i, make_result(c, record));
3386
+ }
3387
+
3388
+ return records;
3389
+ }
3390
+
3391
+ /*
3392
+ * call-seq:
3393
+ * cursor.fetch_many(n) => array
3394
+ *
3395
+ * Reads at most <i>n</i> records.
3396
+ *
3397
+ * Returns the records read as an array of arrays
3398
+ */
3399
+ static VALUE
3400
+ seqcur_fetch_many(VALUE self, VALUE n)
3401
+ {
3402
+ return fetch_many(self, n, T_ARRAY);
3403
+ }
3404
+
3405
+ /*
3406
+ * call-seq:
3407
+ * cursor.fetch_hash_many(n) => array
3408
+ *
3409
+ * Reads at most <i>n</i> records.
3410
+ * Returns the records read as an array of hashes.
3411
+ */
3412
+ static VALUE
3413
+ seqcur_fetch_hash_many(VALUE self, VALUE n)
3414
+ {
3415
+ return fetch_many(self, n, T_HASH);
3416
+ }
3417
+
3418
+ /*
3419
+ * call-seq:
3420
+ * cursor.fetch_all => array
3421
+ *
3422
+ * Returns all the records left as an array of arrays
3423
+ */
3424
+ static VALUE
3425
+ seqcur_fetch_all(VALUE self)
3426
+ {
3427
+ return fetch_many(self, Qnil, T_ARRAY);
3428
+ }
3429
+
3430
+ /*
3431
+ * call-seq:
3432
+ * cursor.fetch_hash_all => array
3433
+ *
3434
+ * Returns all the records left as an array of hashes
3435
+ */
3436
+ static VALUE
3437
+ seqcur_fetch_hash_all(VALUE self)
3438
+ {
3439
+ return fetch_many(self, Qnil, T_HASH);
3440
+ }
3441
+
3442
+ /*
3443
+ * Base function for each* methods, except each*_by
3444
+ */
3445
+ static VALUE
3446
+ each(VALUE self, VALUE type, int bang)
3447
+ {
3448
+ cursor_t *c;
3449
+ /*
3450
+ * EXEC SQL begin declare section;
3451
+ */
3452
+ #line 2721 "informix.ec"
3453
+ #line 2722 "informix.ec"
3454
+ char *cid, *did;
3455
+ /*
3456
+ * EXEC SQL end declare section;
3457
+ */
3458
+ #line 2723 "informix.ec"
3459
+
3460
+ struct sqlda *output;
3461
+ VALUE record;
3462
+
3463
+ Data_Get_Struct(self, cursor_t, c);
3464
+ if (!c->is_open)
3465
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3466
+
3467
+ did = c->database_id;
3468
+ /*
3469
+ * EXEC SQL set connection :did;
3470
+ */
3471
+ #line 2732 "informix.ec"
3472
+ {
3473
+ #line 2732 "informix.ec"
3474
+ sqli_connect_set(0, did, 0);
3475
+ #line 2732 "informix.ec"
3476
+ }
3477
+ if (SQLCODE < 0)
3478
+ raise_ifx_extended();
3479
+
3480
+ output = c->daOutput;
3481
+ cid = c->cursor_id;
3482
+
3483
+ for(;;) {
3484
+ /*
3485
+ * EXEC SQL fetch :cid using descriptor output;
3486
+ */
3487
+ #line 2740 "informix.ec"
3488
+ {
3489
+ #line 2740 "informix.ec"
3490
+ static _FetchSpec _FS0 = { 0, 1, 0 };
3491
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
3492
+ #line 2740 "informix.ec"
3493
+ }
3494
+ if (SQLCODE < 0)
3495
+ raise_ifx_extended();
3496
+
3497
+ if (SQLCODE == SQLNOTFOUND)
3498
+ return self;
3499
+ RECORD(c, type, bang, record);
3500
+ rb_yield(make_result(c, record));
3501
+ }
3502
+ }
3503
+
3504
+ /*
3505
+ * Base function for each*_by methods
3506
+ */
3507
+ static VALUE
3508
+ each_by(VALUE self, VALUE n, VALUE type)
3509
+ {
3510
+ VALUE records;
3511
+
3512
+ for(;;) {
3513
+ records = fetch_many(self, n, type);
3514
+ if (RARRAY(records)->len == 0)
3515
+ return self;
3516
+ rb_yield(records);
3517
+ }
3518
+ }
3519
+
3520
+ /*
3521
+ * call-seq:
3522
+ * cursor.each {|record| block } => cursor
3523
+ *
3524
+ * Iterates over the remaining records, passing each <i>record</i> to the
3525
+ * <i>block</i> as an array.
3526
+ *
3527
+ * Returns __self__.
3528
+ */
3529
+ static VALUE
3530
+ seqcur_each(VALUE self)
3531
+ {
3532
+ return each(self, T_ARRAY, 0);
3533
+ }
3534
+
3535
+ /*
3536
+ * call-seq:
3537
+ * cursor.each! {|record| block } => cursor
3538
+ *
3539
+ * Iterates over the remaining records, passing each <i>record</i> to the
3540
+ * <i>block</i> as an array. No new Array objects are created for each record.
3541
+ * The same Array object is reused in each call.
3542
+ *
3543
+ * Returns __self__.
3544
+ */
3545
+ static VALUE
3546
+ seqcur_each_bang(VALUE self)
3547
+ {
3548
+ return each(self, T_ARRAY, 1);
3549
+ }
3550
+
3551
+ /*
3552
+ * call-seq:
3553
+ * cursor.each_hash {|record| block } => cursor
3554
+ *
3555
+ * Iterates over the remaining records, passing each <i>record</i> to the
3556
+ * <i>block</i> as a hash.
3557
+ *
3558
+ * Returns __self__.
3559
+ */
3560
+ static VALUE
3561
+ seqcur_each_hash(VALUE self)
3562
+ {
3563
+ return each(self, T_HASH, 0);
3564
+ }
3565
+
3566
+ /*
3567
+ * call-seq:
3568
+ * cursor.each_hash! {|record| block } => cursor
3569
+ *
3570
+ * Iterates over the remaining records, passing each <i>record</i> to the
3571
+ * <i>block</i> as a hash. No new Hash objects are created for each record.
3572
+ * The same Hash object is reused in each call.
3573
+ *
3574
+ * Returns __self__.
3575
+ */
3576
+ static VALUE
3577
+ seqcur_each_hash_bang(VALUE self)
3578
+ {
3579
+ return each(self, T_HASH, 1);
3580
+ }
3581
+
3582
+ /*
3583
+ * call-seq:
3584
+ * cursor.each_by(n) {|records| block } => cursor
3585
+ *
3586
+ * Iterates over the remaining records, passing at most <i>n</i> <i>records</i>
3587
+ * to the <i>block</i> as arrays.
3588
+ *
3589
+ * Returns __self__.
3590
+ */
3591
+ static VALUE
3592
+ seqcur_each_by(VALUE self, VALUE n)
3593
+ {
3594
+ return each_by(self, n, T_ARRAY);
3595
+ }
3596
+
3597
+ /*
3598
+ * call-seq:
3599
+ * cursor.each_hash_by(n) {|records| block } => cursor
3600
+ *
3601
+ * Iterates over the remaining records, passing at most <i>n</i> <i>records</i>
3602
+ * to the <i>block</i> as hashes.
3603
+ *
3604
+ * Returns __self__.
3605
+ */
3606
+ static VALUE
3607
+ seqcur_each_hash_by(VALUE self, VALUE n)
3608
+ {
3609
+ return each_by(self, n, T_HASH);
3610
+ }
3611
+
3612
+ /* module InsertCursor --------------------------------------------------- */
3613
+
3614
+ /*
3615
+ * call-seq:
3616
+ * cursor.put(*params)
3617
+ *
3618
+ * Binds <i>params</i> as input parameters and executes the insert statement.
3619
+ * The records are not written immediatly to disk, unless the insert buffer
3620
+ * is full, the <code>flush</code> method is called, the cursor is closed or
3621
+ * the transaction is commited.
3622
+ */
3623
+ static VALUE
3624
+ inscur_put(int argc, VALUE *argv, VALUE self)
3625
+ {
3626
+ struct sqlda *input;
3627
+ cursor_t *c;
3628
+ /*
3629
+ * EXEC SQL begin declare section;
3630
+ */
3631
+ #line 2875 "informix.ec"
3632
+ #line 2876 "informix.ec"
3633
+ char *cid, *did;
3634
+ /*
3635
+ * EXEC SQL end declare section;
3636
+ */
3637
+ #line 2877 "informix.ec"
3638
+
3639
+
3640
+ Data_Get_Struct(self, cursor_t, c);
3641
+ if (!c->is_open)
3642
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3643
+
3644
+ did = c->database_id;
3645
+ /*
3646
+ * EXEC SQL set connection :did;
3647
+ */
3648
+ #line 2884 "informix.ec"
3649
+ {
3650
+ #line 2884 "informix.ec"
3651
+ sqli_connect_set(0, did, 0);
3652
+ #line 2884 "informix.ec"
3653
+ }
3654
+ if (SQLCODE < 0)
3655
+ raise_ifx_extended();
3656
+
3657
+ input = &c->daInput;
3658
+ cid = c->cursor_id;
3659
+
3660
+ bind_input_params(c, argv);
3661
+ if (argc != input->sqld)
3662
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
3663
+ argc, input->sqld);
3664
+
3665
+ /*
3666
+ * EXEC SQL put :cid using descriptor input;
3667
+ */
3668
+ #line 2896 "informix.ec"
3669
+ {
3670
+ #line 2896 "informix.ec"
3671
+ sqli_curs_put(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), input, (char *)0);
3672
+ #line 2896 "informix.ec"
3673
+ }
3674
+ clean_input_slots(c);
3675
+ if (SQLCODE < 0)
3676
+ raise_ifx_extended();
3677
+
3678
+ /* XXX 2-448, Guide to SQL: Sytax*/
3679
+ return INT2FIX(sqlca.sqlerrd[2]);
3680
+ }
3681
+
3682
+ /*
3683
+ * call-seq:
3684
+ * cursor.flush => cursor
3685
+ *
3686
+ * Flushes the insert buffer, writing data to disk.
3687
+ *
3688
+ * Returns __self__.
3689
+ */
3690
+ static VALUE
3691
+ inscur_flush(VALUE self)
3692
+ {
3693
+ cursor_t *c;
3694
+ /*
3695
+ * EXEC SQL begin declare section;
3696
+ */
3697
+ #line 2917 "informix.ec"
3698
+ #line 2918 "informix.ec"
3699
+ char *cid, *did;
3700
+ /*
3701
+ * EXEC SQL end declare section;
3702
+ */
3703
+ #line 2919 "informix.ec"
3704
+
3705
+
3706
+ Data_Get_Struct(self, cursor_t, c);
3707
+ if (!c->is_open)
3708
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3709
+
3710
+ did = c->database_id;
3711
+ /*
3712
+ * EXEC SQL set connection :did;
3713
+ */
3714
+ #line 2926 "informix.ec"
3715
+ {
3716
+ #line 2926 "informix.ec"
3717
+ sqli_connect_set(0, did, 0);
3718
+ #line 2926 "informix.ec"
3719
+ }
3720
+ if (SQLCODE < 0)
3721
+ raise_ifx_extended();
3722
+
3723
+ cid = c->cursor_id;
3724
+ /*
3725
+ * EXEC SQL flush :cid;
3726
+ */
3727
+ #line 2931 "informix.ec"
3728
+ {
3729
+ #line 2931 "informix.ec"
3730
+ sqli_curs_flush(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256));
3731
+ #line 2931 "informix.ec"
3732
+ }
3733
+ return self;
3734
+ }
3735
+
3736
+ /* module ScrollCursor --------------------------------------------------- */
3737
+
3738
+ /*
3739
+ * Provides the Array-like functionality for scroll cursors when using the
3740
+ * cursor[index] syntax
3741
+ */
3742
+ static VALUE
3743
+ scrollcur_entry(VALUE self, VALUE index, VALUE type, int bang)
3744
+ {
3745
+ cursor_t *c;
3746
+ struct sqlda *output;
3747
+ VALUE record;
3748
+ /*
3749
+ * EXEC SQL begin declare section;
3750
+ */
3751
+ #line 2947 "informix.ec"
3752
+ #line 2948 "informix.ec"
3753
+ char *cid, *did;
3754
+ long pos;
3755
+ /*
3756
+ * EXEC SQL end declare section;
3757
+ */
3758
+ #line 2950 "informix.ec"
3759
+
3760
+
3761
+ Data_Get_Struct(self, cursor_t, c);
3762
+ if (!c->is_open)
3763
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
3764
+
3765
+ did = c->database_id;
3766
+ /*
3767
+ * EXEC SQL set connection :did;
3768
+ */
3769
+ #line 2957 "informix.ec"
3770
+ {
3771
+ #line 2957 "informix.ec"
3772
+ sqli_connect_set(0, did, 0);
3773
+ #line 2957 "informix.ec"
3774
+ }
3775
+ if (SQLCODE < 0)
3776
+ return Qnil;
3777
+
3778
+ output = c->daOutput;
3779
+ cid = c->cursor_id;
3780
+
3781
+ if (NIL_P(index))
3782
+ /*
3783
+ * EXEC SQL fetch current :cid using descriptor output;
3784
+ */
3785
+ #line 2965 "informix.ec"
3786
+ {
3787
+ #line 2965 "informix.ec"
3788
+ static _FetchSpec _FS0 = { 0, 5, 0 };
3789
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
3790
+ #line 2965 "informix.ec"
3791
+ }
3792
+ else if ((pos = NUM2LONG(index) + 1) > 0)
3793
+ /*
3794
+ * EXEC SQL fetch absolute :pos :cid using descriptor output;
3795
+ */
3796
+ #line 2967 "informix.ec"
3797
+ {
3798
+ #line 2967 "informix.ec"
3799
+ static ifx_sqlvar_t _sqibind[] =
3800
+ {
3801
+ { 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3802
+ #line 2967 "informix.ec"
3803
+ };
3804
+ static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
3805
+ static _FetchSpec _FS1 = { 0, 6, 0 };
3806
+ #line 2967 "informix.ec"
3807
+ _sqibind[0].sqldata = (char *) &pos;
3808
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
3809
+ #line 2967 "informix.ec"
3810
+ }
3811
+ else {
3812
+ /*
3813
+ * EXEC SQL fetch last :cid;
3814
+ */
3815
+ #line 2969 "informix.ec"
3816
+ {
3817
+ #line 2969 "informix.ec"
3818
+ static _FetchSpec _FS0 = { 0, 4, 0 };
3819
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (ifx_sqlda_t *)0, (char *)0, &_FS0);
3820
+ #line 2969 "informix.ec"
3821
+ }
3822
+ /*
3823
+ * EXEC SQL fetch relative :pos :cid using descriptor output;
3824
+ */
3825
+ #line 2970 "informix.ec"
3826
+ {
3827
+ #line 2970 "informix.ec"
3828
+ static ifx_sqlvar_t _sqibind[] =
3829
+ {
3830
+ { 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3831
+ #line 2970 "informix.ec"
3832
+ };
3833
+ static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
3834
+ static _FetchSpec _FS1 = { 0, 7, 0 };
3835
+ #line 2970 "informix.ec"
3836
+ _sqibind[0].sqldata = (char *) &pos;
3837
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
3838
+ #line 2970 "informix.ec"
3839
+ }
3840
+ }
3841
+
3842
+ if (SQLCODE == SQLNOTFOUND)
3843
+ return Qnil;
3844
+
3845
+ if (SQLCODE < 0)
3846
+ raise_ifx_extended();
3847
+
3848
+ RECORD(c, type, bang, record);
3849
+ return make_result(c, record);
3850
+ }
3851
+
3852
+ /*
3853
+ * Provides the Array-like functionality for scroll cursors when using the
3854
+ * cursor[start, length] syntax
3855
+ */
3856
+ static VALUE
3857
+ scrollcur_subseq(VALUE self, VALUE start, VALUE length, VALUE type)
3858
+ {
3859
+ VALUE first, records;
3860
+ /*
3861
+ * EXEC SQL begin declare section;
3862
+ */
3863
+ #line 2991 "informix.ec"
3864
+ #line 2992 "informix.ec"
3865
+ long pos;
3866
+ /*
3867
+ * EXEC SQL end declare section;
3868
+ */
3869
+ #line 2993 "informix.ec"
3870
+
3871
+
3872
+ first = scrollcur_entry(self, start, type, 0);
3873
+ if (NIL_P(first))
3874
+ return Qnil;
3875
+
3876
+ pos = NUM2LONG(length) - 1;
3877
+
3878
+ if (pos > 0) {
3879
+ length = LONG2NUM(pos);
3880
+ records = fetch_many(self, length, type);
3881
+ }
3882
+ else
3883
+ records = rb_ary_new();
3884
+
3885
+ rb_ary_unshift(records, first);
3886
+
3887
+ return records;
3888
+ }
3889
+
3890
+ /*
3891
+ * Base function for slice and slice_hash methods
3892
+ */
3893
+ static VALUE
3894
+ slice(int argc, VALUE *argv, VALUE self, VALUE type)
3895
+ {
3896
+ if (argc == 2) {
3897
+ if (NUM2LONG(argv[1]) <= 0)
3898
+ rb_raise(rb_eArgError, "length must be positive");
3899
+ return scrollcur_subseq(self, argv[0], argv[1], type);
3900
+ }
3901
+ if (argc != 1)
3902
+ rb_scan_args(argc, argv, "11", 0, 0);
3903
+
3904
+ return scrollcur_entry(self, argv[0], type, 0);
3905
+ }
3906
+
3907
+ /*
3908
+ * call-seq:
3909
+ * cursor[index] => array or nil
3910
+ * cursor[start, length] => array or nil
3911
+ * cursor.slice(index) => array or nil
3912
+ * cursor.slice(start, length) => array or nil
3913
+ *
3914
+ * Returns the record at _index_, or returns a subarray starting at _start_
3915
+ * and continuing for _length_ records. Negative indices count backward from
3916
+ * the end of the cursor (-1 is the last element). Returns nil if the
3917
+ * (starting) index is out of range.
3918
+ *
3919
+ * <b>Warning</b>: if the (starting) index is negative and out of range, the
3920
+ * position in the cursor is set to the last record. Otherwise the current
3921
+ * position in the cursor is preserved.
3922
+ */
3923
+ static VALUE
3924
+ scrollcur_slice(int argc, VALUE *argv, VALUE self)
3925
+ {
3926
+ return slice(argc, argv, self, T_ARRAY);
3927
+ }
3928
+
3929
+ /*
3930
+ * call-seq:
3931
+ * cursor.slice!(index) => array or nil
3932
+ *
3933
+ * Returns the record at _index_. Negative indices count backward from
3934
+ * the end of the cursor (-1 is the last element). Returns nil if the index
3935
+ * is out of range.
3936
+ *
3937
+ * Stores the record fetched always in the same Array object.
3938
+ *
3939
+ * <b>Warning</b>: if the index is negative and out of range, the
3940
+ * position in the cursor is set to the last record. Otherwise the current
3941
+ * position in the cursor is preserved.
3942
+ */
3943
+ static VALUE
3944
+ scrollcur_slice_bang(VALUE self, VALUE index)
3945
+ {
3946
+ return scrollcur_entry(self, index, T_ARRAY, 1);
3947
+ }
3948
+
3949
+ /*
3950
+ * call-seq:
3951
+ * cursor.slice_hash(index) => hash or nil
3952
+ * cursor.slice_hash(start, length) => array or nil
3953
+ *
3954
+ * Returns the record at _index_, or returns a subarray starting at _start_
3955
+ * and continuing for _length_ records. Negative indices count backward from
3956
+ * the end of the cursor (-1 is the last element). Returns nil if the
3957
+ * (starting) index is out of range.
3958
+ *
3959
+ * <b>Warning</b>: if the (starting) index is negative and out of range, the
3960
+ * position in the cursor is set to the last record. Otherwise the current
3961
+ * position in the cursor is preserved.
3962
+ */
3963
+ static VALUE
3964
+ scrollcur_slice_hash(int argc, VALUE *argv, VALUE self)
3965
+ {
3966
+ return slice(argc, argv, self, T_HASH);
3967
+ }
3968
+
3969
+ /*
3970
+ * call-seq:
3971
+ * cursor.slice_hash!(index) => hash or nil
3972
+ *
3973
+ * Returns the record at _index_. Negative indices count backward from
3974
+ * the end of the cursor (-1 is the last element). Returns nil if the index
3975
+ * is out of range.
3976
+ *
3977
+ * Stores the record fetched always in the same Hash object.
3978
+ *
3979
+ * <b>Warning</b>: if the index is negative and out of range, the
3980
+ * position in the cursor is set to the last record. Otherwise the current
3981
+ * position in the cursor is preserved.
3982
+ */
3983
+ static VALUE
3984
+ scrollcur_slice_hash_bang(VALUE self, VALUE index)
3985
+ {
3986
+ return scrollcur_entry(self, index, T_HASH, 1);
3987
+ }
3988
+
3989
+ /*
3990
+ * Base function for prev* and next* methods
3991
+ */
3992
+ static VALUE
3993
+ scrollcur_rel(int argc, VALUE *argv, VALUE self, int dir, VALUE type, int bang)
3994
+ {
3995
+ cursor_t *c;
3996
+ struct sqlda *output;
3997
+ VALUE offset, record;
3998
+ /*
3999
+ * EXEC SQL begin declare section;
4000
+ */
4001
+ #line 3121 "informix.ec"
4002
+ #line 3122 "informix.ec"
4003
+ char *cid, *did;
4004
+ long pos;
4005
+ /*
4006
+ * EXEC SQL end declare section;
4007
+ */
4008
+ #line 3124 "informix.ec"
4009
+
4010
+
4011
+ Data_Get_Struct(self, cursor_t, c);
4012
+ if (!c->is_open)
4013
+ rb_raise(esyms.eProgrammingError, "Open the cursor object first");
4014
+
4015
+ did = c->database_id;
4016
+ /*
4017
+ * EXEC SQL set connection :did;
4018
+ */
4019
+ #line 3131 "informix.ec"
4020
+ {
4021
+ #line 3131 "informix.ec"
4022
+ sqli_connect_set(0, did, 0);
4023
+ #line 3131 "informix.ec"
4024
+ }
4025
+ if (SQLCODE < 0)
4026
+ return Qnil;
4027
+
4028
+ rb_scan_args(argc, argv, "01", &offset);
4029
+ pos = dir*(NIL_P(offset)? 1: NUM2LONG(offset));
4030
+
4031
+ output = c->daOutput;
4032
+ cid = c->cursor_id;
4033
+ /*
4034
+ * EXEC SQL fetch relative :pos :cid using descriptor output;
4035
+ */
4036
+ #line 3140 "informix.ec"
4037
+ {
4038
+ #line 3140 "informix.ec"
4039
+ static ifx_sqlvar_t _sqibind[] =
4040
+ {
4041
+ { 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
4042
+ #line 3140 "informix.ec"
4043
+ };
4044
+ static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
4045
+ static _FetchSpec _FS1 = { 0, 7, 0 };
4046
+ #line 3140 "informix.ec"
4047
+ _sqibind[0].sqldata = (char *) &pos;
4048
+ sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
4049
+ #line 3140 "informix.ec"
4050
+ }
4051
+
4052
+ if (SQLCODE == SQLNOTFOUND)
4053
+ return Qnil;
4054
+
4055
+ if (SQLCODE < 0)
4056
+ raise_ifx_extended();
4057
+
4058
+ RECORD(c, type, bang, record);
4059
+ return make_result(c, record);
4060
+ }
4061
+
4062
+ /* call-seq:
4063
+ * cursor.prev(offset = 1) => array or nil
4064
+ *
4065
+ * Returns the previous _offset_ th record. Negative indices count
4066
+ * forward from the current position. Returns nil if the _offset_ is out of
4067
+ * range.
4068
+ */
4069
+ static VALUE
4070
+ scrollcur_prev(int argc, VALUE *argv, VALUE self)
4071
+ {
4072
+ return scrollcur_rel(argc, argv, self, -1, T_ARRAY, 0);
4073
+ }
4074
+
4075
+ /* call-seq:
4076
+ * cursor.prev!(offset = 1) => array or nil
4077
+ *
4078
+ * Returns the previous _offset_ th record. Negative indices count
4079
+ * forward from the current position. Returns nil if the _offset_ is out of
4080
+ * range.
4081
+ *
4082
+ * Stores the record fetched always in the same Array object.
4083
+ */
4084
+ static VALUE
4085
+ scrollcur_prev_bang(int argc, VALUE *argv, VALUE self)
4086
+ {
4087
+ return scrollcur_rel(argc, argv, self, -1, T_ARRAY, 1);
4088
+ }
4089
+
4090
+ /* call-seq:
4091
+ * cursor.prev_hash(offset = 1) => hash or nil
4092
+ *
4093
+ * Returns the previous _offset_ th record. Negative indices count
4094
+ * forward from the current position. Returns nil if the _offset_ is out of
4095
+ * range.
4096
+ */
4097
+ static VALUE
4098
+ scrollcur_prev_hash(int argc, VALUE *argv, VALUE self)
4099
+ {
4100
+ return scrollcur_rel(argc, argv, self, -1, T_HASH, 0);
4101
+ }
4102
+
4103
+ /* call-seq:
4104
+ * cursor.prev_hash!(offset = 1) => hash or nil
4105
+ *
4106
+ * Returns the previous _offset_ th record. Negative indices count
4107
+ * forward from the current position. Returns nil if the _offset_ is out of
4108
+ * range.
4109
+ *
4110
+ * Stores the record fetched always in the same Hash object.
4111
+ */
4112
+ static VALUE
4113
+ scrollcur_prev_hash_bang(int argc, VALUE *argv, VALUE self)
4114
+ {
4115
+ return scrollcur_rel(argc, argv, self, -1, T_HASH, 1);
4116
+ }
4117
+
4118
+ /* call-seq:
4119
+ * cursor.next(offset = 1) => array or nil
4120
+ *
4121
+ * Returns the next _offset_ th record. Negative indices count
4122
+ * backward from the current position. Returns nil if the _offset_ is out of
4123
+ * range.
4124
+ */
4125
+ static VALUE
4126
+ scrollcur_next(int argc, VALUE *argv, VALUE self)
4127
+ {
4128
+ return scrollcur_rel(argc, argv, self, 1, T_ARRAY, 0);
4129
+ }
4130
+
4131
+ /* call-seq:
4132
+ * cursor.next!(offset = 1) => array or nil
4133
+ *
4134
+ * Returns the next _offset_ th record. Negative indices count
4135
+ * backward from the current position. Returns nil if the _offset_ is out of
4136
+ * range.
4137
+ *
4138
+ * Stores the record fetched always in the same Array object.
4139
+ */
4140
+ static VALUE
4141
+ scrollcur_next_bang(int argc, VALUE *argv, VALUE self)
4142
+ {
4143
+ return scrollcur_rel(argc, argv, self, 1, T_ARRAY, 1);
4144
+ }
4145
+
4146
+ /* call-seq:
4147
+ * cursor.next_hash(offset = 1) => hash or nil
4148
+ *
4149
+ * Returns the next _offset_ th record. Negative indices count
4150
+ * backward from the current position. Returns nil if the _offset_ is out of
4151
+ * range.
4152
+ */
4153
+ static VALUE
4154
+ scrollcur_next_hash(int argc, VALUE *argv, VALUE self)
4155
+ {
4156
+ return scrollcur_rel(argc, argv, self, 1, T_HASH, 0);
4157
+ }
4158
+
4159
+ /* call-seq:
4160
+ * cursor.next_hash!(offset = 1) => hash or nil
4161
+ *
4162
+ * Returns the next _offset_ th record. Negative indices count
4163
+ * backward from the current position. Returns nil if the _offset_ is out of
4164
+ * range.
4165
+ *
4166
+ * Stores the record fetched always in the same Hash object.
4167
+ */
4168
+ static VALUE
4169
+ scrollcur_next_hash_bang(int argc, VALUE *argv, VALUE self)
4170
+ {
4171
+ return scrollcur_rel(argc, argv, self, 1, T_HASH, 1);
4172
+ }
4173
+
4174
+ /*
4175
+ * call-seq:
4176
+ * cursor.first => array or nil
4177
+ *
4178
+ * Returns the first record of the cursor. If the cursor is empty,
4179
+ * returns nil.
4180
+ */
4181
+ static VALUE
4182
+ scrollcur_first(VALUE self)
4183
+ {
4184
+ return scrollcur_entry(self, INT2FIX(0), T_ARRAY, 0);
4185
+ }
4186
+
4187
+ /*
4188
+ * call-seq:
4189
+ * cursor.first! => array or nil
4190
+ *
4191
+ * Returns the first record of the cursor. If the cursor is empty,
4192
+ * returns nil.
4193
+ *
4194
+ * Stores the record fetched always in the same Array object.
4195
+ */
4196
+ static VALUE
4197
+ scrollcur_first_bang(VALUE self)
4198
+ {
4199
+ return scrollcur_entry(self, INT2FIX(0), T_ARRAY, 1);
4200
+ }
4201
+
4202
+ /*
4203
+ * call-seq:
4204
+ * cursor.first_hash => hash or nil
4205
+ *
4206
+ * Returns the first record of the cursor. If the cursor is empty,
4207
+ * returns nil.
4208
+ */
4209
+ static VALUE
4210
+ scrollcur_first_hash(VALUE self)
4211
+ {
4212
+ return scrollcur_entry(self, INT2FIX(0), T_HASH, 0);
4213
+ }
4214
+
4215
+ /*
4216
+ * call-seq:
4217
+ * cursor.first_hash! => hash or nil
4218
+ *
4219
+ * Returns the first record of the cursor. If the cursor is empty,
4220
+ * returns nil.
4221
+ *
4222
+ * Stores the record fetched always in the same Hash object.
4223
+ */
4224
+ static VALUE
4225
+ scrollcur_first_hash_bang(VALUE self)
4226
+ {
4227
+ return scrollcur_entry(self, INT2FIX(0), T_HASH, 1);
4228
+ }
4229
+
4230
+ /*
4231
+ * call-seq:
4232
+ * cursor.last => array or nil
4233
+ *
4234
+ * Returns the last record of the cursor. If the cursor is empty,
4235
+ * returns nil.
4236
+ */
4237
+ static VALUE
4238
+ scrollcur_last(VALUE self)
4239
+ {
4240
+ return scrollcur_entry(self, INT2FIX(-1), T_ARRAY, 0);
4241
+ }
4242
+
4243
+ /*
4244
+ * call-seq:
4245
+ * cursor.last! => array or nil
4246
+ *
4247
+ * Returns the last record of the cursor. If the cursor is empty,
4248
+ * returns nil.
4249
+ *
4250
+ * Stores the record fetched always in the same Array object.
4251
+ */
4252
+ static VALUE
4253
+ scrollcur_last_bang(VALUE self)
4254
+ {
4255
+ return scrollcur_entry(self, INT2FIX(-1), T_ARRAY, 1);
4256
+ }
4257
+
4258
+ /*
4259
+ * call-seq:
4260
+ * cursor.last_hash => hash or nil
4261
+ *
4262
+ * Returns the last record of the cursor. If the cursor is empty,
4263
+ * returns nil.
4264
+ */
4265
+ static VALUE
4266
+ scrollcur_last_hash(VALUE self)
4267
+ {
4268
+ return scrollcur_entry(self, INT2FIX(-1), T_HASH, 0);
4269
+ }
4270
+
4271
+ /*
4272
+ * call-seq:
4273
+ * cursor.last_hash! => hash or nil
4274
+ *
4275
+ * Returns the last record of the cursor. If the cursor is empty,
4276
+ * returns nil.
4277
+ *
4278
+ * Stores the record fetched always in the same Hash object.
4279
+ */
4280
+ static VALUE
4281
+ scrollcur_last_hash_bang(VALUE self)
4282
+ {
4283
+ return scrollcur_entry(self, INT2FIX(-1), T_HASH, 1);
4284
+ }
4285
+
4286
+ /*
4287
+ * call-seq:
4288
+ * cursor.current => array or nil
4289
+ *
4290
+ * Returns the current record of the cursor. If the cursor is empty,
4291
+ * returns nil.
4292
+ */
4293
+ static VALUE
4294
+ scrollcur_current(VALUE self)
4295
+ {
4296
+ return scrollcur_entry(self, Qnil, T_ARRAY, 0);
4297
+ }
4298
+
4299
+ /*
4300
+ * call-seq:
4301
+ * cursor.current! => array or nil
4302
+ *
4303
+ * Returns the current record of the cursor. If the cursor is empty,
4304
+ * returns nil.
4305
+ *
4306
+ * Stores the record fetched always in the same Array object.
4307
+ */
4308
+ static VALUE
4309
+ scrollcur_current_bang(VALUE self)
4310
+ {
4311
+ return scrollcur_entry(self, Qnil, T_ARRAY, 1);
4312
+ }
4313
+
4314
+ /*
4315
+ * call-seq:
4316
+ * cursor.current_hash => hash or nil
4317
+ *
4318
+ * Returns the current record of the cursor. If the cursor is empty,
4319
+ * returns nil.
4320
+ */
4321
+ static VALUE
4322
+ scrollcur_current_hash(VALUE self)
4323
+ {
4324
+ return scrollcur_entry(self, Qnil, T_HASH, 0);
4325
+ }
4326
+
4327
+ /*
4328
+ * call-seq:
4329
+ * cursor.current_hash! => hash or nil
4330
+ *
4331
+ * Returns the current record of the cursor. If the cursor is empty,
4332
+ * returns nil.
4333
+ *
4334
+ * Stores the record fetched always in the same Hash object.
4335
+ */
4336
+ static VALUE
4337
+ scrollcur_current_hash_bang(VALUE self)
4338
+ {
4339
+ return scrollcur_entry(self, Qnil, T_HASH, 1);
4340
+ }
4341
+
4342
+ /* class Cursor ---------------------------------------------------------- */
4343
+ static void
4344
+ cursor_close_or_free(cursor_t *c, short op)
4345
+ {
4346
+ /*
4347
+ * EXEC SQL begin declare section;
4348
+ */
4349
+ #line 3436 "informix.ec"
4350
+ #line 3437 "informix.ec"
4351
+ char *cid, *sid, *did;
4352
+ /*
4353
+ * EXEC SQL end declare section;
4354
+ */
4355
+ #line 3438 "informix.ec"
4356
+
4357
+
4358
+ if (op == 1 && !c->is_open)
4359
+ return;
4360
+
4361
+ c->is_open = 0;
4362
+ if (op == 1)
4363
+ clean_input_slots(c);
4364
+ else {
4365
+ free_input_slots(c);
4366
+ free_output_slots(c);
4367
+ }
4368
+
4369
+ did = c->database_id;
4370
+ /*
4371
+ * EXEC SQL set connection :did;
4372
+ */
4373
+ #line 3452 "informix.ec"
4374
+ {
4375
+ #line 3452 "informix.ec"
4376
+ sqli_connect_set(0, did, 0);
4377
+ #line 3452 "informix.ec"
4378
+ }
4379
+ if (SQLCODE < 0)
4380
+ return;
4381
+
4382
+ cid = c->cursor_id;
4383
+ /*
4384
+ * EXEC SQL close :cid;
4385
+ */
4386
+ #line 3457 "informix.ec"
4387
+ {
4388
+ #line 3457 "informix.ec"
4389
+ sqli_curs_close(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256));
4390
+ #line 3457 "informix.ec"
4391
+ }
4392
+
4393
+ if (op == 2) {
4394
+ sid = c->stmt_id;
4395
+ /*
4396
+ * EXEC SQL free :cid;
4397
+ */
4398
+ #line 3461 "informix.ec"
4399
+ {
4400
+ #line 3461 "informix.ec"
4401
+ sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 258));
4402
+ #line 3461 "informix.ec"
4403
+ }
4404
+ /*
4405
+ * EXEC SQL free :sid;
4406
+ */
4407
+ #line 3461 "informix.ec"
4408
+ {
4409
+ #line 3461 "informix.ec"
4410
+ sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
4411
+ #line 3461 "informix.ec"
4412
+ }
4413
+ }
4414
+ }
4415
+
4416
+ static void
4417
+ cursor_mark(cursor_t *c)
4418
+ {
4419
+ rb_gc_mark(c->db);
4420
+ if (c->array)
4421
+ rb_gc_mark(c->array);
4422
+ if (c->hash)
4423
+ rb_gc_mark(c->hash);
4424
+ if (c->field_names)
4425
+ rb_gc_mark(c->field_names);
4426
+ }
4427
+
4428
+ static void
4429
+ cursor_free(void *p)
4430
+ {
4431
+ cursor_close_or_free(p, 2);
4432
+ xfree(p);
4433
+ }
4434
+
4435
+ static VALUE
4436
+ cursor_alloc(VALUE klass)
4437
+ {
4438
+ cursor_t *c;
4439
+
4440
+ c = ALLOC(cursor_t);
4441
+ memset(c, 0, sizeof(cursor_t));
4442
+ return Data_Wrap_Struct(klass, cursor_mark, cursor_free, c);
4443
+ }
4444
+
4445
+ static VALUE
4446
+ cursor_initialize(int argc, VALUE *argv, VALUE self)
4447
+ {
4448
+ VALUE db, query, options;
4449
+ VALUE scroll, hold;
4450
+ struct sqlda *output;
4451
+ cursor_t *c;
4452
+ /*
4453
+ * EXEC SQL begin declare section;
4454
+ */
4455
+ #line 3501 "informix.ec"
4456
+ #line 3502 "informix.ec"
4457
+ char *c_query;
4458
+ char *cid, *sid, *did;
4459
+ /*
4460
+ * EXEC SQL end declare section;
4461
+ */
4462
+ #line 3504 "informix.ec"
4463
+
4464
+
4465
+ rb_scan_args(argc, argv, "21", &db, &query, &options);
4466
+ Data_Get_Struct(db, char, did);
4467
+
4468
+ /*
4469
+ * EXEC SQL set connection :did;
4470
+ */
4471
+ #line 3509 "informix.ec"
4472
+ {
4473
+ #line 3509 "informix.ec"
4474
+ sqli_connect_set(0, did, 0);
4475
+ #line 3509 "informix.ec"
4476
+ }
4477
+ if (SQLCODE < 0)
4478
+ raise_ifx_extended();
4479
+
4480
+ Data_Get_Struct(self, cursor_t, c);
4481
+ c->db = db;
4482
+ c->database_id = did;
4483
+ scroll = hold = Qfalse;
4484
+ snprintf(c->cursor_id, sizeof(c->cursor_id), "CUR%lX", self);
4485
+ snprintf(c->stmt_id, sizeof(c->stmt_id), "STMT%lX", self);
4486
+ cid = c->cursor_id; sid = c->stmt_id;
4487
+ c_query = StringValueCStr(query);
4488
+
4489
+ if (!NIL_P(options)) {
4490
+ Check_Type(options, T_HASH);
4491
+ scroll = rb_hash_aref(options, sym_scroll);
4492
+ hold = rb_hash_aref(options, sym_hold);
4493
+ }
4494
+
4495
+ /*
4496
+ * EXEC SQL prepare :sid from :c_query;
4497
+ */
4498
+ #line 3528 "informix.ec"
4499
+ {
4500
+ #line 3528 "informix.ec"
4501
+ sqli_prep(ESQLINTVERSION, sid, c_query,(ifx_literal_t *)0, (ifx_namelist_t *)0, -1, 0, 0 );
4502
+ #line 3528 "informix.ec"
4503
+ }
4504
+ if (SQLCODE < 0)
4505
+ raise_ifx_extended();
4506
+
4507
+ if (RTEST(scroll) && RTEST(hold))
4508
+ /*
4509
+ * EXEC SQL declare :cid scroll cursor with hold for :sid;
4510
+ */
4511
+ #line 3533 "informix.ec"
4512
+ {
4513
+ #line 3533 "informix.ec"
4514
+ sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 4128, 0);
4515
+ #line 3533 "informix.ec"
4516
+ }
4517
+ else if (RTEST(hold))
4518
+ /*
4519
+ * EXEC SQL declare :cid cursor with hold for :sid;
4520
+ */
4521
+ #line 3535 "informix.ec"
4522
+ {
4523
+ #line 3535 "informix.ec"
4524
+ sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 4096, 0);
4525
+ #line 3535 "informix.ec"
4526
+ }
4527
+ else if (RTEST(scroll))
4528
+ /*
4529
+ * EXEC SQL declare :cid scroll cursor for :sid;
4530
+ */
4531
+ #line 3537 "informix.ec"
4532
+ {
4533
+ #line 3537 "informix.ec"
4534
+ sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 32, 0);
4535
+ #line 3537 "informix.ec"
4536
+ }
4537
+ else
4538
+ /*
4539
+ * EXEC SQL declare :cid cursor for :sid;
4540
+ */
4541
+ #line 3539 "informix.ec"
4542
+ {
4543
+ #line 3539 "informix.ec"
4544
+ sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 0, 0);
4545
+ #line 3539 "informix.ec"
4546
+ }
4547
+
4548
+ if (SQLCODE < 0)
4549
+ raise_ifx_extended();
4550
+
4551
+ alloc_input_slots(c, c_query);
4552
+ /*
4553
+ * EXEC SQL describe :sid into output;
4554
+ */
4555
+ #line 3545 "informix.ec"
4556
+ {
4557
+ #line 3545 "informix.ec"
4558
+ sqli_describe_stmt(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), &output, 0);
4559
+ #line 3545 "informix.ec"
4560
+ }
4561
+ c->daOutput = output;
4562
+
4563
+ c->is_select = (SQLCODE == 0 || SQLCODE == SQ_EXECPROC);
4564
+
4565
+ if (c->is_select) {
4566
+ alloc_output_slots(c);
4567
+ rb_extend_object(self, rb_mSequentialCursor);
4568
+ if (scroll)
4569
+ rb_extend_object(self, rb_mScrollCursor);
4570
+ }
4571
+ else {
4572
+ xfree(c->daOutput);
4573
+ c->daOutput = NULL;
4574
+ rb_extend_object(self, rb_mInsertCursor);
4575
+ }
4576
+ return self;
4577
+ }
4578
+
4579
+ static VALUE cursor_drop(VALUE self);
4580
+ /*
4581
+ * call-seq:
4582
+ * Cursor.new(database, query, options) => cursor
4583
+ * Cursor.new(database, query, options) {|cursor| block } => obj
4584
+ *
4585
+ * Creates a Cursor object based on <i>query</i> using <i>options</i>
4586
+ * in the context of <i>database</i> but does not open it.
4587
+ * In the first form the Cursor object is returned.
4588
+ * In the second form the Cursor object is passed to the block and when it
4589
+ * terminates, the Cursor object is dropped, returning the value of the block.
4590
+ *
4591
+ * <i>options</i> can be nil or a Hash object with the following possible keys:
4592
+ *
4593
+ * :scroll => true or false
4594
+ * :hold => true or false
4595
+ */
4596
+ static VALUE
4597
+ rb_cursor_s_new(int argc, VALUE *argv, VALUE klass)
4598
+ {
4599
+ VALUE cursor;
4600
+
4601
+ cursor = rb_class_new_instance(argc, argv, klass);
4602
+
4603
+ if (rb_block_given_p())
4604
+ return rb_ensure(rb_yield, cursor, cursor_drop, cursor);
4605
+
4606
+ return cursor;
4607
+ }
4608
+
4609
+ static VALUE cursor_open(int argc, VALUE *argv, VALUE self);
4610
+ /*
4611
+ * call-seq:
4612
+ * Cursor.open(database, query, options) => cursor
4613
+ * Cursor.open(database, query, options) {|cursor| block } => obj
4614
+ *
4615
+ * Creates and opens a Cursor object based on <i>query</i> using <i>options</i>
4616
+ * in the context of <i>database</i>.
4617
+ * In the first form the Cursor object is returned.
4618
+ * In the second form the Cursor object is passed to the block and when it
4619
+ * terminates, the Cursor object is dropped, returning the value of the block.
4620
+ *
4621
+ * <i>options</i> can be nil or a Hash object with the following possible keys:
4622
+ *
4623
+ * :scroll => true or false
4624
+ * :hold => true or false
4625
+ * :params => input parameters as an Array or nil
4626
+ */
4627
+ static VALUE
4628
+ cursor_s_open(int argc, VALUE *argv, VALUE klass)
4629
+ {
4630
+ VALUE cursor, options, params;
4631
+ int open_argc;
4632
+
4633
+ rb_scan_args(argc, argv, "21", 0, 0, &options);
4634
+ open_argc = 0; params = Qnil;
4635
+
4636
+ if (!NIL_P(options)) {
4637
+ Check_Type(options, T_HASH);
4638
+ params = rb_hash_aref(options, sym_params);
4639
+
4640
+ if (TYPE(params) == T_ARRAY)
4641
+ open_argc = RARRAY(params)->len;
4642
+ else if (params != Qnil)
4643
+ rb_raise(rb_eArgError, "Parameters must be supplied as an Array");
4644
+ }
4645
+
4646
+ cursor = rb_class_new_instance(argc, argv, klass);
4647
+ cursor_open(open_argc, &params, cursor);
4648
+
4649
+ if (rb_block_given_p())
4650
+ return rb_ensure(rb_yield, cursor, cursor_drop, cursor);
4651
+
4652
+ return cursor;
4653
+ }
4654
+
4655
+ /*
4656
+ * call-seq:
4657
+ * cursor.id => string
4658
+ *
4659
+ * Returns the cursor ID
4660
+ */
4661
+ static VALUE
4662
+ cursor_id(VALUE self)
4663
+ {
4664
+ cursor_t *c;
4665
+
4666
+ Data_Get_Struct(self, cursor_t, c);
4667
+ return rb_str_new2(c->cursor_id);
4668
+ }
4669
+
4670
+ /*
4671
+ * call-seq:
4672
+ * cursor.open(*params) => cursor
4673
+ *
4674
+ * Executes the previously prepared select statement, binding <i>params</i> as
4675
+ * input parameters.
4676
+ *
4677
+ * Returns __self__.
4678
+ */
4679
+ static VALUE
4680
+ cursor_open(int argc, VALUE *argv, VALUE self)
4681
+ {
4682
+ struct sqlda *input;
4683
+ cursor_t *c;
4684
+ /*
4685
+ * EXEC SQL begin declare section;
4686
+ */
4687
+ #line 3669 "informix.ec"
4688
+ #line 3670 "informix.ec"
4689
+ char *cid, *did;
4690
+ /*
4691
+ * EXEC SQL end declare section;
4692
+ */
4693
+ #line 3671 "informix.ec"
4694
+
4695
+
4696
+ Data_Get_Struct(self, cursor_t, c);
4697
+
4698
+ if (c->is_open)
4699
+ return self;
4700
+
4701
+ did = c->database_id;
4702
+ /*
4703
+ * EXEC SQL set connection :did;
4704
+ */
4705
+ #line 3679 "informix.ec"
4706
+ {
4707
+ #line 3679 "informix.ec"
4708
+ sqli_connect_set(0, did, 0);
4709
+ #line 3679 "informix.ec"
4710
+ }
4711
+ if (SQLCODE < 0)
4712
+ raise_ifx_extended();
4713
+
4714
+ input = &c->daInput;
4715
+ cid = c->cursor_id;
4716
+
4717
+ if (c->is_select) {
4718
+ if (argc != input->sqld) {
4719
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
4720
+ argc, input->sqld);
4721
+ }
4722
+ if (argc) {
4723
+ bind_input_params(c, argv);
4724
+ /*
4725
+ * EXEC SQL open :cid using descriptor input
4726
+ * with reoptimization;
4727
+ */
4728
+ #line 3693 "informix.ec"
4729
+ {
4730
+ #line 3694 "informix.ec"
4731
+ sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), input, (char *)0, (struct value *)0, 1, 1);
4732
+ #line 3694 "informix.ec"
4733
+ }
4734
+ clean_input_slots(c);
4735
+ }
4736
+ else
4737
+ /*
4738
+ * EXEC SQL open :cid with reoptimization;
4739
+ */
4740
+ #line 3698 "informix.ec"
4741
+ {
4742
+ #line 3698 "informix.ec"
4743
+ sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0, 1);
4744
+ #line 3698 "informix.ec"
4745
+ }
4746
+ }
4747
+ else
4748
+ /*
4749
+ * EXEC SQL open :cid;
4750
+ */
4751
+ #line 3701 "informix.ec"
4752
+ {
4753
+ #line 3701 "informix.ec"
4754
+ sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0, 0);
4755
+ #line 3701 "informix.ec"
4756
+ }
4757
+
4758
+ if (SQLCODE < 0)
4759
+ raise_ifx_extended();
4760
+
4761
+ c->is_open = 1;
4762
+ return self;
4763
+ }
4764
+
4765
+ /*
4766
+ * call-seq:
4767
+ * cursor.close => cursor
4768
+ *
4769
+ * Closes the cursor and returns __self__.
4770
+ */
4771
+ static VALUE
4772
+ cursor_close(VALUE self)
4773
+ {
4774
+ cursor_t *c;
4775
+
4776
+ Data_Get_Struct(self, cursor_t, c);
4777
+ cursor_close_or_free(c, 1);
4778
+ return self;
4779
+ }
4780
+
4781
+ /*
4782
+ * call-seq:
4783
+ * cursor.drop => nil
4784
+ *
4785
+ * Closes the cursor and frees the memory associated with it. The cursor
4786
+ * cannot be opened again.
4787
+ */
4788
+ static VALUE
4789
+ cursor_drop(VALUE self)
4790
+ {
4791
+ cursor_t *c;
4792
+
4793
+ Data_Get_Struct(self, cursor_t, c);
4794
+ cursor_close_or_free(c, 2);
4795
+
4796
+ return Qnil;
4797
+ }
4798
+
4799
+ /* Entry point ------------------------------------------------------------ */
4800
+
4801
+ void Init_informix(void)
4802
+ {
4803
+ /* module Informix ---------------------------------------------------- */
4804
+ rb_mInformix = rb_define_module("Informix");
4805
+ rb_mScrollCursor = rb_define_module_under(rb_mInformix, "ScrollCursor");
4806
+ rb_mInsertCursor = rb_define_module_under(rb_mInformix, "InsertCursor");
4807
+ rb_define_module_function(rb_mInformix, "connect", rb_informix_connect, -1);
4808
+ rb_define_module_function(rb_mInformix, "version", rb_informix_version, 0);
4809
+
4810
+ /* class Slob --------------------------------------------------------- */
4811
+ rb_cSlob = rb_define_class_under(rb_mInformix, "Slob", rb_cObject);
4812
+ rb_define_alloc_func(rb_cSlob, slob_alloc);
4813
+ rb_define_method(rb_cSlob, "initialize", rb_slob_initialize, -1);
4814
+ rb_define_singleton_method(rb_cSlob, "new", rb_slob_s_new, -1);
4815
+ rb_define_method(rb_cSlob, "open", rb_slob_open, -1);
4816
+ rb_define_method(rb_cSlob, "close", rb_slob_close, 0);
4817
+ rb_define_method(rb_cSlob, "read", rb_slob_read, 1);
4818
+ rb_define_method(rb_cSlob, "write", rb_slob_write, 1);
4819
+ rb_define_method(rb_cSlob, "seek", rb_slob_seek, 2);
4820
+ rb_define_method(rb_cSlob, "tell", rb_slob_tell, 0);
4821
+ rb_define_alias(rb_cSlob, "pos", "tell");
4822
+ rb_define_method(rb_cSlob, "pos=", rb_slob_set_pos, 1);
4823
+ rb_define_method(rb_cSlob, "truncate", rb_slob_truncate, 1);
4824
+ rb_define_method(rb_cSlob, "stat", rb_slob_stat, 0);
4825
+ rb_define_method(rb_cSlob, "<<", rb_slob_addstr, 1);
4826
+ rb_define_method(rb_cSlob, "rewind", rb_slob_rewind, 0);
4827
+ rb_define_method(rb_cSlob, "lock", rb_slob_lock, 4);
4828
+ rb_define_method(rb_cSlob, "unlock", rb_slob_unlock, 3);
4829
+
4830
+ rb_define_method(rb_cSlob, "atime", rb_slob_atime, 0);
4831
+ rb_define_method(rb_cSlob, "ctime", rb_slob_ctime, 0);
4832
+ rb_define_method(rb_cSlob, "mtime", rb_slob_mtime, 0);
4833
+ rb_define_method(rb_cSlob, "refcnt", rb_slob_refcnt, 0);
4834
+ rb_define_method(rb_cSlob, "size", rb_slob_size, 0);
4835
+
4836
+ rb_define_method(rb_cSlob, "estbytes", rb_slob_estbytes, 0);
4837
+ rb_define_method(rb_cSlob, "extsz", rb_slob_extsz, 0);
4838
+ rb_define_method(rb_cSlob, "flags", rb_slob_flags, 0);
4839
+ rb_define_method(rb_cSlob, "maxbytes", rb_slob_maxbytes, 0);
4840
+ rb_define_method(rb_cSlob, "sbspace", rb_slob_sbspace, 0);
4841
+
4842
+ rb_define_method(rb_cSlob, "extsz=", rb_slob_set_extsz, 1);
4843
+ rb_define_method(rb_cSlob, "flags=", rb_slob_set_flags, 1);
4844
+
4845
+ rb_define_const(rb_cSlob, "CLOB", INT2FIX(XID_CLOB));
4846
+ rb_define_const(rb_cSlob, "BLOB", INT2FIX(XID_BLOB));
4847
+
4848
+ #define DEF_SLOB_CONST(k) rb_define_const(rb_cSlob, #k, INT2FIX(LO_##k))
4849
+
4850
+ /* Access modes */
4851
+ DEF_SLOB_CONST(RDONLY);
4852
+ DEF_SLOB_CONST(DIRTY_READ);
4853
+ DEF_SLOB_CONST(WRONLY);
4854
+ DEF_SLOB_CONST(APPEND);
4855
+ DEF_SLOB_CONST(RDWR);
4856
+ DEF_SLOB_CONST(BUFFER);
4857
+ DEF_SLOB_CONST(NOBUFFER);
4858
+ DEF_SLOB_CONST(LOCKALL);
4859
+ DEF_SLOB_CONST(LOCKRANGE);
4860
+ DEF_SLOB_CONST(SEEK_SET);
4861
+ DEF_SLOB_CONST(SEEK_CUR);
4862
+ DEF_SLOB_CONST(SEEK_END);
4863
+
4864
+ /* Creation-time flags */
4865
+ DEF_SLOB_CONST(LOG);
4866
+ DEF_SLOB_CONST(NOLOG);
4867
+ DEF_SLOB_CONST(KEEP_LASTACCESS_TIME);
4868
+ DEF_SLOB_CONST(NOKEEP_LASTACCESS_TIME);
4869
+
4870
+ /* Ranges */
4871
+ DEF_SLOB_CONST(CURRENT_END);
4872
+ DEF_SLOB_CONST(MAX_END);
4873
+
4874
+ /* Lock modes */
4875
+ DEF_SLOB_CONST(SHARED_MODE);
4876
+ DEF_SLOB_CONST(EXCLUSIVE_MODE);
4877
+
4878
+ /* class Slob::Stat --------------------------------------------------- */
4879
+
4880
+ rb_cSlobStat = rb_define_class_under(rb_cSlob, "Stat", rb_cObject);
4881
+ rb_define_alloc_func(rb_cSlobStat, slobstat_alloc);
4882
+ rb_define_method(rb_cSlobStat, "initialize", rb_slobstat_initialize, 1);
4883
+
4884
+ rb_include_module(rb_cSlobStat, rb_mComparable);
4885
+ rb_define_method(rb_cSlobStat, "<=>", rb_slobstat_cmp, 1);
4886
+
4887
+ rb_define_method(rb_cSlobStat, "atime", rb_slobstat_atime, 0);
4888
+ rb_define_method(rb_cSlobStat, "ctime", rb_slobstat_ctime, 0);
4889
+ rb_define_method(rb_cSlobStat, "mtime", rb_slobstat_mtime, 0);
4890
+ rb_define_method(rb_cSlobStat, "refcnt", rb_slobstat_refcnt, 0);
4891
+ rb_define_method(rb_cSlobStat, "size", rb_slobstat_size, 0);
4892
+
4893
+ /* class Database ----------------------------------------------------- */
4894
+ rb_cDatabase = rb_define_class_under(rb_mInformix, "Database", rb_cObject);
4895
+ rb_define_alloc_func(rb_cDatabase, database_alloc);
4896
+ rb_define_method(rb_cDatabase, "initialize", rb_database_initialize, -1);
4897
+ rb_define_singleton_method(rb_cDatabase, "open", rb_database_s_open, -1);
4898
+ rb_define_alias(rb_cDatabase, "new", "open");
4899
+ rb_define_method(rb_cDatabase, "close", rb_database_close, 0);
4900
+ rb_define_alias(rb_cDatabase, "disconnect", "close");
4901
+ rb_define_method(rb_cDatabase, "immediate", rb_database_immediate, 1);
4902
+ rb_define_alias(rb_cDatabase, "do", "immediate");
4903
+ rb_define_alias(rb_cDatabase, "execute", "immediate");
4904
+ rb_define_method(rb_cDatabase, "rollback", rb_database_rollback, 0);
4905
+ rb_define_method(rb_cDatabase, "commit", rb_database_commit, 0);
4906
+ rb_define_method(rb_cDatabase, "transaction", rb_database_transaction, 0);
4907
+ rb_define_method(rb_cDatabase, "prepare", rb_database_prepare, 1);
4908
+ rb_define_method(rb_cDatabase, "columns", rb_database_columns, 1);
4909
+ rb_define_method(rb_cDatabase, "cursor", rb_database_cursor, -1);
4910
+ rb_define_method(rb_cDatabase, "slob", rb_database_slob, -1);
4911
+
4912
+ /* class Statement ---------------------------------------------------- */
4913
+ rb_cStatement = rb_define_class_under(rb_mInformix, "Statement", rb_cObject);
4914
+ rb_define_alloc_func(rb_cStatement, statement_alloc);
4915
+ rb_define_method(rb_cStatement, "initialize", statement_initialize, 2);
4916
+ rb_define_singleton_method(rb_cStatement, "new", statement_s_new, -1);
4917
+ rb_define_method(rb_cStatement, "[]", statement_call, -1);
4918
+ rb_define_alias(rb_cStatement, "call", "[]");
4919
+ rb_define_alias(rb_cStatement, "execute", "[]");
4920
+ rb_define_method(rb_cStatement, "drop", statement_drop, 0);
4921
+
4922
+ /* module SequentialCursor -------------------------------------------- */
4923
+ rb_mSequentialCursor = rb_define_module_under(rb_mInformix, "SequentialCursor");
4924
+ rb_define_method(rb_mSequentialCursor, "fetch", seqcur_fetch, 0);
4925
+ rb_define_method(rb_mSequentialCursor, "fetch!", seqcur_fetch_bang, 0);
4926
+ rb_define_method(rb_mSequentialCursor, "fetch_hash", seqcur_fetch_hash, 0);
4927
+ rb_define_method(rb_mSequentialCursor, "fetch_hash!", seqcur_fetch_hash_bang, 0);
4928
+ rb_define_method(rb_mSequentialCursor, "fetch_many", seqcur_fetch_many, 1);
4929
+ rb_define_method(rb_mSequentialCursor, "fetch_hash_many", seqcur_fetch_hash_many, 1);
4930
+ rb_define_method(rb_mSequentialCursor, "fetch_all", seqcur_fetch_all, 0);
4931
+ rb_define_method(rb_mSequentialCursor, "fetch_hash_all", seqcur_fetch_hash_all, 0);
4932
+ rb_define_method(rb_mSequentialCursor, "each", seqcur_each, 0);
4933
+ rb_define_method(rb_mSequentialCursor, "each!", seqcur_each_bang, 0);
4934
+ rb_define_method(rb_mSequentialCursor, "each_hash", seqcur_each_hash, 0);
4935
+ rb_define_method(rb_mSequentialCursor, "each_hash!", seqcur_each_hash_bang, 0);
4936
+ rb_define_method(rb_mSequentialCursor, "each_by", seqcur_each_by, 1);
4937
+ rb_define_method(rb_mSequentialCursor, "each_hash_by", seqcur_each_hash_by, 1);
4938
+
4939
+ /* InsertCursor ------------------------------------------------------- */
4940
+ rb_define_method(rb_mInsertCursor, "put", inscur_put, -1);
4941
+ rb_define_method(rb_mInsertCursor, "flush", inscur_flush, 0);
4942
+
4943
+ /* ScrollCursor ------------------------------------------------------- */
4944
+ rb_define_method(rb_mScrollCursor, "[]", scrollcur_slice, -1);
4945
+ rb_define_alias(rb_mScrollCursor, "slice", "[]");
4946
+ rb_define_method(rb_mScrollCursor, "slice!", scrollcur_slice_bang, 1);
4947
+ rb_define_method(rb_mScrollCursor, "slice_hash", scrollcur_slice_hash, -1);
4948
+ rb_define_method(rb_mScrollCursor, "slice_hash!", scrollcur_slice_hash_bang, 1);
4949
+ rb_define_method(rb_mScrollCursor, "prev", scrollcur_prev, -1);
4950
+ rb_define_method(rb_mScrollCursor, "prev!", scrollcur_prev_bang, -1);
4951
+ rb_define_method(rb_mScrollCursor, "prev_hash", scrollcur_prev_hash, -1);
4952
+ rb_define_method(rb_mScrollCursor, "prev_hash!", scrollcur_prev_hash_bang, -1);
4953
+ rb_define_method(rb_mScrollCursor, "next", scrollcur_next, -1);
4954
+ rb_define_method(rb_mScrollCursor, "next!", scrollcur_next_bang, -1);
4955
+ rb_define_method(rb_mScrollCursor, "next_hash", scrollcur_next_hash, -1);
4956
+ rb_define_method(rb_mScrollCursor, "next_hash!", scrollcur_next_hash_bang, -1);
4957
+ rb_define_method(rb_mScrollCursor, "first", scrollcur_first, 0);
4958
+ rb_define_method(rb_mScrollCursor, "first!", scrollcur_first_bang, 0);
4959
+ rb_define_method(rb_mScrollCursor, "first_hash", scrollcur_first_hash, 0);
4960
+ rb_define_method(rb_mScrollCursor, "first_hash!", scrollcur_first_hash_bang, 0);
4961
+ rb_define_method(rb_mScrollCursor, "last", scrollcur_last, 0);
4962
+ rb_define_method(rb_mScrollCursor, "last!", scrollcur_last_bang, 0);
4963
+ rb_define_method(rb_mScrollCursor, "last_hash", scrollcur_last_hash, 0);
4964
+ rb_define_method(rb_mScrollCursor, "last_hash!", scrollcur_last_hash_bang, 0);
4965
+ rb_define_method(rb_mScrollCursor, "current", scrollcur_current, 0);
4966
+ rb_define_method(rb_mScrollCursor, "current!", scrollcur_current_bang, 0);
4967
+ rb_define_method(rb_mScrollCursor, "current_hash", scrollcur_current_hash, 0);
4968
+ rb_define_method(rb_mScrollCursor, "current_hash!", scrollcur_current_hash_bang, 0);
4969
+
4970
+ /* class Cursor ------------------------------------------------------- */
4971
+ rb_cCursor = rb_define_class_under(rb_mInformix, "Cursor", rb_cObject);
4972
+ rb_define_alloc_func(rb_cCursor, cursor_alloc);
4973
+ rb_define_method(rb_cCursor, "initialize", cursor_initialize, -1);
4974
+ rb_define_singleton_method(rb_cCursor, "new", rb_cursor_s_new, -1);
4975
+ rb_define_singleton_method(rb_cCursor, "open", cursor_s_open, -1);
4976
+ rb_define_method(rb_cCursor, "id", cursor_id, 0);
4977
+ rb_define_method(rb_cCursor, "open", cursor_open, -1);
4978
+ rb_define_method(rb_cCursor, "close", cursor_close, 0);
4979
+ rb_define_method(rb_cCursor, "drop", cursor_drop, 0);
4980
+
4981
+ /* Global constants --------------------------------------------------- */
4982
+ rb_require("date");
4983
+ rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
4984
+ rb_require("bigdecimal");
4985
+ rb_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
4986
+
4987
+ /* Global symbols ----------------------------------------------------- */
4988
+ #define INTERN(sym) s_##sym = rb_intern(#sym)
4989
+ INTERN(read); INTERN(new);
4990
+ INTERN(utc); INTERN(day); INTERN(month); INTERN(year);
4991
+ INTERN(hour); INTERN(min); INTERN(sec); INTERN(usec);
4992
+ INTERN(to_s); INTERN(to_i);
4993
+
4994
+ sym_name = ID2SYM(rb_intern("name"));
4995
+ sym_type = ID2SYM(rb_intern("type"));
4996
+ sym_nullable = ID2SYM(rb_intern("nullable"));
4997
+ sym_stype = ID2SYM(rb_intern("stype"));
4998
+ sym_length = ID2SYM(rb_intern("length"));
4999
+ sym_precision = ID2SYM(rb_intern("precision"));
5000
+ sym_scale = ID2SYM(rb_intern("scale"));
5001
+ sym_default = ID2SYM(rb_intern("default"));
5002
+ sym_xid = ID2SYM(rb_intern("xid"));
5003
+
5004
+ sym_scroll = ID2SYM(rb_intern("scroll"));
5005
+ sym_hold = ID2SYM(rb_intern("hold"));
5006
+
5007
+ sym_col_info = ID2SYM(rb_intern("col_info"));
5008
+ sym_sbspace = ID2SYM(rb_intern("sbspace"));
5009
+ sym_estbytes = ID2SYM(rb_intern("estbytes"));
5010
+ sym_extsz = ID2SYM(rb_intern("extsz"));
5011
+ sym_createflags = ID2SYM(rb_intern("createflags"));
5012
+ sym_openflags = ID2SYM(rb_intern("openflags"));
5013
+ sym_maxbytes = ID2SYM(rb_intern("maxbytes"));
5014
+
5015
+ sym_params = ID2SYM(rb_intern("params"));
5016
+
5017
+ /* Initialize ifx_except module */
5018
+ rbifx_except_init(rb_mInformix, &esyms);
5019
+ }
5020
+
5021
+ #line 3964 "informix.ec"