ruby-informix 0.6.2-i386-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"