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.
- data/COPYRIGHT +26 -0
- data/Changelog +198 -0
- data/README +85 -0
- data/ifx_except.c +522 -0
- data/informix.c +5021 -0
- data/informix.so +0 -0
- 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, ¶ms, 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"
|