ruby-informix 0.4.0
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 +84 -0
- data/README +80 -0
- data/extconf.rb +36 -0
- data/informix.c +4048 -0
- data/informix.ec +3093 -0
- metadata +50 -0
data/COPYRIGHT
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Copyright (c) 2006-2007, Gerardo Santana Gomez Garrido <gerardo.santana@gmail.com>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
3. The name of the author may not be used to endorse or promote products
|
14
|
+
derived from this software without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
17
|
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
22
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
23
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
24
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
25
|
+
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
26
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/Changelog
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
0.4.0 12/13/2006
|
2
|
+
------------------
|
3
|
+
New features:
|
4
|
+
* Support for multiple connections to databases
|
5
|
+
* Support for scroll cursors. Methods available:
|
6
|
+
- [], slice
|
7
|
+
- prev, next, first, last, current
|
8
|
+
- prev_hash, next_hash, first_hash, last_hash, current_hash
|
9
|
+
- slice!, prev!, next!, first!, last!, current!
|
10
|
+
- slice_hash, prev_hash, next_hash, first_hash, last_hash,
|
11
|
+
current_hash!
|
12
|
+
- slice_hash!, prev_hash!, next_hash!, first_hash!, last_hash!,
|
13
|
+
current_hash!
|
14
|
+
* New Cursor#id method that returns the cursor name for use in
|
15
|
+
update cursors
|
16
|
+
|
17
|
+
Bugs fixed:
|
18
|
+
* Memory for input parameters was allocated before statement/cursor
|
19
|
+
preparation but not freed if preparation failed.
|
20
|
+
|
21
|
+
|
22
|
+
0.3.0 11/26/2006
|
23
|
+
------------------
|
24
|
+
New features:
|
25
|
+
* Initial support for Smart Large Objects (BLOB/CLOB).
|
26
|
+
Operations supported:
|
27
|
+
- new
|
28
|
+
- open, close
|
29
|
+
- read, write
|
30
|
+
- seek, tell
|
31
|
+
- truncate
|
32
|
+
* Database#columns now also returns the extended id (xid)
|
33
|
+
* small documentation improvements and fixes
|
34
|
+
|
35
|
+
|
36
|
+
0.2.1 11/11/2006
|
37
|
+
------------------
|
38
|
+
Bugs fixed:
|
39
|
+
* changing free() for xfree() avoids crashes on Windows XP SP1. Noticed
|
40
|
+
by Dinko <dsrkoc at helix hr>
|
41
|
+
|
42
|
+
|
43
|
+
0.2.0 04/24/2006
|
44
|
+
------------------
|
45
|
+
New features:
|
46
|
+
* Methods added to SequentialCursor:
|
47
|
+
|
48
|
+
- fetch_hash_many(n), fetch_hash_all
|
49
|
+
- each_by(n), each_hash_by(n)
|
50
|
+
- fetch!, fetch_hash!, each!, each_hash!
|
51
|
+
|
52
|
+
where !-methods reduce object creation by reusing the same result
|
53
|
+
object in each call
|
54
|
+
|
55
|
+
Remarks:
|
56
|
+
* fetch*many and fetch*all methods now return [] instead of nil when
|
57
|
+
no records are found
|
58
|
+
|
59
|
+
Bugs fixed:
|
60
|
+
* When freeing a cursor that was opened but never used, a segmentation
|
61
|
+
fault occurred
|
62
|
+
|
63
|
+
|
64
|
+
0.1.0 04/10/2006
|
65
|
+
-------------------
|
66
|
+
Features:
|
67
|
+
* Support for all built-in data types, except INTERVAL
|
68
|
+
* immediate statements
|
69
|
+
* prepared statements
|
70
|
+
* select cursors and bulk inserts (insert cursors)
|
71
|
+
* transactions
|
72
|
+
* #columns method for retrieving column information
|
73
|
+
* rows retrieved as arrays or hashes
|
74
|
+
* IO-based and IO-like (StringIO) objects for storing a BYTE/TEXT
|
75
|
+
column, and retrieved as a String object
|
76
|
+
* NULL, DATE and DATETIME mapped to nil, Date and Time objects and
|
77
|
+
viceversa
|
78
|
+
* #drop method for freeing Informix resources immediatly
|
79
|
+
* source code documented with RDoc
|
80
|
+
|
81
|
+
Caveats:
|
82
|
+
* INTERVAL not supported
|
83
|
+
* cursors must be closed before reopening them
|
84
|
+
* only one open connection at a time is supported
|
data/README
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
Ruby/Informix
|
2
|
+
---------------
|
3
|
+
Ruby extension for connecting to IBM Informix Dynamic Server, written in ESQL/C.
|
4
|
+
|
5
|
+
For installation instructions please read INSTALL.
|
6
|
+
|
7
|
+
1. Supported platforms
|
8
|
+
2. Documentation
|
9
|
+
3. Data types
|
10
|
+
4. Recommendations
|
11
|
+
5. Caveats
|
12
|
+
6. Support
|
13
|
+
|
14
|
+
|
15
|
+
1. Supported platforms
|
16
|
+
|
17
|
+
Ruby/Informix has been tested succesfully on the following platforms:
|
18
|
+
|
19
|
+
Operating System Architecture Informix CSDK
|
20
|
+
-------------------------------------------------------------
|
21
|
+
Solaris 9 SPARC 9.40FC6 2.90UC3
|
22
|
+
Linux Fedora Core 4 i386 10.00.UC3R1 2.90UC4
|
23
|
+
Linux Fedora Core 5 i386 10.00.UC3R1 2.90UC4
|
24
|
+
SuSE Linux 9.3 i386 9.30TC1 2.90UC4
|
25
|
+
Windows XP Pro SP i386 9.40TC3 2.90TC1
|
26
|
+
Windows XP i386 9.30TC1 2.90TC4
|
27
|
+
HP-UX 11.11 PA-RISC 2.0 10.00.FC3R1TL 2.81
|
28
|
+
64-bit
|
29
|
+
|
30
|
+
Send me an e-mail if you have [un]succesfully tested Ruby/Informix on another
|
31
|
+
platform.
|
32
|
+
|
33
|
+
|
34
|
+
2. Documentation
|
35
|
+
|
36
|
+
Documentation generated by RDoc for each class, module and method can be found
|
37
|
+
under the doc/ directory in this distribution and at the following web address:
|
38
|
+
|
39
|
+
http://ruby-informix.rubyforge.org/doc/
|
40
|
+
|
41
|
+
Examples of use can be found at:
|
42
|
+
|
43
|
+
http://ruby-informix.rubyforge.org
|
44
|
+
|
45
|
+
|
46
|
+
3. Data types
|
47
|
+
|
48
|
+
All built-in data types are supported, except interval. As you would expect,
|
49
|
+
numeric, string and boolean data types are mapped to their respective objects
|
50
|
+
in Ruby; DATE, DATETIME and NULL are mapped to Date, Time and nil respectively.
|
51
|
+
|
52
|
+
The notable exception is TEXT/BYTE columns, where Ruby/Informix expects an
|
53
|
+
IO-based (File) or IO-like (StringIO) object as input, and returns an String
|
54
|
+
object as output.
|
55
|
+
|
56
|
+
An Slob class exists in the Informix module for working with Smart Large
|
57
|
+
Objects (CLOB/BLOB).
|
58
|
+
|
59
|
+
|
60
|
+
4. Recommendations
|
61
|
+
|
62
|
+
* use #drop for prepared statements and cursors to release Informix resources
|
63
|
+
* you can optimize cursor execution by changing the fetch and insert buffers,
|
64
|
+
setting the environment variable FET_BUF_SIZE to up to 32767 for Informix 9.x,
|
65
|
+
or BIG_FET_BUF_SIZE for Informix 10.x
|
66
|
+
|
67
|
+
|
68
|
+
5. Caveats
|
69
|
+
|
70
|
+
* INTERVAL not implemented yet
|
71
|
+
|
72
|
+
6. Support
|
73
|
+
|
74
|
+
Feel free to send me bug reports, feature requests, comments, patches or
|
75
|
+
questions to my mailbox or Ruby/Informix's forums at Rubyforge.
|
76
|
+
|
77
|
+
|
78
|
+
-----------------------------------------
|
79
|
+
Gerardo Santana <gerardo.santana gmail>
|
80
|
+
http://santanatechnotes.blogspot.com
|
data/extconf.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
env = nil
|
4
|
+
informixdir = ENV["INFORMIXDIR"]
|
5
|
+
|
6
|
+
if informixdir.nil?
|
7
|
+
informixdir = RUBY_PLATFORM =~ /mswin/ ? "C:\\informix" : "/usr/informix"
|
8
|
+
end
|
9
|
+
|
10
|
+
esql = File.join(informixdir, "bin", "esql")
|
11
|
+
idefault = File.join(informixdir, "incl", "esql")
|
12
|
+
ldefault = [ File.join(informixdir, "lib") ]
|
13
|
+
ldefault << File.join(informixdir, "lib", "esql") if RUBY_PLATFORM !~ /mswin/
|
14
|
+
|
15
|
+
dir_config("informix", idefault, ldefault)
|
16
|
+
|
17
|
+
if RUBY_PLATFORM =~ /mswin/
|
18
|
+
$libs += " isqlt09a.lib"
|
19
|
+
else
|
20
|
+
env = "/usr/bin/env"
|
21
|
+
|
22
|
+
%w(ifsql ifasf ifgen ifos ifgls).each do |lib|
|
23
|
+
$libs += " " + format(LIBARG, lib)
|
24
|
+
end
|
25
|
+
$LIBPATH.each {|path|
|
26
|
+
checkapi = path + "/checkapi.o"
|
27
|
+
if File.exist?(checkapi)
|
28
|
+
$libs += " " + checkapi
|
29
|
+
break
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
`#{env} #{esql} -e informix.ec`
|
36
|
+
create_makefile("informix")
|
data/informix.c
ADDED
@@ -0,0 +1,4048 @@
|
|
1
|
+
#include <sqlhdr.h>
|
2
|
+
#include <sqliapi.h>
|
3
|
+
static const char _Cn1[] = "cur";
|
4
|
+
#line 1 "informix.ec"
|
5
|
+
/* $Id: informix.ec,v 1.56 2006/12/13 08:19:52 santana Exp $ */
|
6
|
+
/*
|
7
|
+
* Copyright (c) 2006, Gerardo Santana Gomez Garrido <gerardo.santana@gmail.com>
|
8
|
+
* All rights reserved.
|
9
|
+
*
|
10
|
+
* Redistribution and use in source and binary forms, with or without
|
11
|
+
* modification, are permitted provided that the following conditions
|
12
|
+
* are met:
|
13
|
+
*
|
14
|
+
* 1. Redistributions of source code must retain the above copyright
|
15
|
+
* notice, this list of conditions and the following disclaimer.
|
16
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
17
|
+
* notice, this list of conditions and the following disclaimer in the
|
18
|
+
* documentation and/or other materials provided with the distribution.
|
19
|
+
* 3. The name of the author may not be used to endorse or promote products
|
20
|
+
* derived from this software without specific prior written permission.
|
21
|
+
*
|
22
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
23
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
24
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
25
|
+
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
26
|
+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
27
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
28
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
29
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
30
|
+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
31
|
+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
*/
|
34
|
+
|
35
|
+
#include "ruby.h"
|
36
|
+
|
37
|
+
#include <sqlstype.h>
|
38
|
+
#include <sqltypes.h>
|
39
|
+
|
40
|
+
static VALUE rb_cDate;
|
41
|
+
|
42
|
+
static VALUE rb_mInformix;
|
43
|
+
static VALUE rb_mSequentialCursor;
|
44
|
+
static VALUE rb_mScrollCursor;
|
45
|
+
static VALUE rb_mInsertCursor;
|
46
|
+
|
47
|
+
static VALUE rb_cSlob;
|
48
|
+
static VALUE rb_cDatabase;
|
49
|
+
static VALUE rb_cStatement;
|
50
|
+
static VALUE rb_cCursor;
|
51
|
+
|
52
|
+
static ID s_read, s_new, s_utc, s_day, s_month, s_year;
|
53
|
+
static ID s_hour, s_min, s_sec, s_usec, s_to_s, s_to_i;
|
54
|
+
static VALUE sym_name, sym_type, sym_nullable, sym_stype, sym_length;
|
55
|
+
static VALUE sym_precision, sym_scale, sym_default, sym_xid;
|
56
|
+
static VALUE sym_scroll, sym_hold;
|
57
|
+
static VALUE sym_col_info, sym_sbspace, sym_estbytes, sym_extsz;
|
58
|
+
static VALUE sym_createflags, sym_openflags;
|
59
|
+
|
60
|
+
#define IDSIZE 30
|
61
|
+
|
62
|
+
static char *currentdid = NULL;
|
63
|
+
|
64
|
+
typedef struct {
|
65
|
+
short is_select, is_open;
|
66
|
+
struct sqlda daInput, *daOutput;
|
67
|
+
short *indInput, *indOutput;
|
68
|
+
char *bfOutput;
|
69
|
+
char cursor_id[IDSIZE];
|
70
|
+
char stmt_id[IDSIZE];
|
71
|
+
VALUE db, array, hash, field_names;
|
72
|
+
char *database_id;
|
73
|
+
} cursor_t;
|
74
|
+
|
75
|
+
typedef struct {
|
76
|
+
mint fd;
|
77
|
+
ifx_lo_t lo;
|
78
|
+
ifx_lo_create_spec_t *spec;
|
79
|
+
short type; /* XID_CLOB/XID_BLOB */
|
80
|
+
VALUE db;
|
81
|
+
char *database_id;
|
82
|
+
} slob_t;
|
83
|
+
|
84
|
+
#define NUM2INT8(num, int8addr) do { \
|
85
|
+
VALUE str = rb_funcall(num, s_to_s, 0); \
|
86
|
+
char *c_str = StringValueCStr(str); \
|
87
|
+
mint ret = ifx_int8cvasc(c_str, strlen(c_str), (int8addr)); \
|
88
|
+
if (ret < 0) \
|
89
|
+
rb_raise(rb_eRuntimeError, "Could not convert %s to int8", c_str); \
|
90
|
+
}while(0)
|
91
|
+
|
92
|
+
#define INT82NUM(int8addr, num) do { \
|
93
|
+
char str[21]; \
|
94
|
+
mint ret = ifx_int8toasc((int8addr), str, sizeof(str) - 1); \
|
95
|
+
str[sizeof(str) - 1] = 0; \
|
96
|
+
num = rb_cstr2inum(str, 10); \
|
97
|
+
}while(0)
|
98
|
+
|
99
|
+
/* class Slob ------------------------------------------------------------ */
|
100
|
+
|
101
|
+
static void
|
102
|
+
slob_mark(slob_t *slob)
|
103
|
+
{
|
104
|
+
rb_gc_mark(slob->db);
|
105
|
+
}
|
106
|
+
|
107
|
+
static void
|
108
|
+
slob_free(slob_t *slob)
|
109
|
+
{
|
110
|
+
if (slob->fd != -1) {
|
111
|
+
/*
|
112
|
+
* EXEC SQL begin declare section;
|
113
|
+
*/
|
114
|
+
#line 107 "informix.ec"
|
115
|
+
#line 108 "informix.ec"
|
116
|
+
char *did;
|
117
|
+
/*
|
118
|
+
* EXEC SQL end declare section;
|
119
|
+
*/
|
120
|
+
#line 109 "informix.ec"
|
121
|
+
|
122
|
+
|
123
|
+
did = slob->database_id;
|
124
|
+
if (currentdid != did) {
|
125
|
+
/*
|
126
|
+
* EXEC SQL set connection :did;
|
127
|
+
*/
|
128
|
+
#line 113 "informix.ec"
|
129
|
+
{
|
130
|
+
#line 113 "informix.ec"
|
131
|
+
sqli_connect_set(0, did, 0);
|
132
|
+
#line 113 "informix.ec"
|
133
|
+
}
|
134
|
+
if (SQLCODE < 0)
|
135
|
+
goto exit;
|
136
|
+
currentdid = did;
|
137
|
+
}
|
138
|
+
ifx_lo_close(slob->fd);
|
139
|
+
}
|
140
|
+
|
141
|
+
exit:
|
142
|
+
if (slob->spec)
|
143
|
+
ifx_lo_spec_free(slob->spec);
|
144
|
+
|
145
|
+
xfree(slob);
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE
|
149
|
+
slob_alloc(VALUE klass)
|
150
|
+
{
|
151
|
+
slob_t *slob;
|
152
|
+
|
153
|
+
slob = ALLOC(slob_t);
|
154
|
+
slob->spec = NULL;
|
155
|
+
slob->fd = -1;
|
156
|
+
slob->type = XID_CLOB;
|
157
|
+
|
158
|
+
return Data_Wrap_Struct(klass, slob_mark, slob_free, slob);
|
159
|
+
}
|
160
|
+
|
161
|
+
/*
|
162
|
+
* call-seq:
|
163
|
+
* Slob.new(database, type = Slob::CLOB, options = nil) => slob
|
164
|
+
*
|
165
|
+
* Creates a Smart Large Object of type <i>type</i> in <i>database</i>.
|
166
|
+
* Returns a <code>Slob</code> object pointing to it.
|
167
|
+
*
|
168
|
+
* <i>type</i> can be Slob::BLOB or Slob::CLOB
|
169
|
+
*
|
170
|
+
* <i>options</i> must be a hash with the following possible keys:
|
171
|
+
*
|
172
|
+
* :sbspace => Sbspace name
|
173
|
+
* :estbytes => Estimated size, in bytes
|
174
|
+
* :extsz => Allocation extent size
|
175
|
+
* :createflags => Create-time flags
|
176
|
+
* :openflags => Access mode
|
177
|
+
* :maxbytes => Maximum size
|
178
|
+
* :col_info => Get the previous values from the column-level storage
|
179
|
+
* characteristics for the specified database column
|
180
|
+
*/
|
181
|
+
static VALUE
|
182
|
+
slob_initialize(int argc, VALUE *argv, VALUE self)
|
183
|
+
{
|
184
|
+
mint ret, error;
|
185
|
+
slob_t *slob;
|
186
|
+
VALUE db, type, options;
|
187
|
+
VALUE col_info, sbspace, estbytes, extsz, createflags, openflags, maxbytes;
|
188
|
+
/*
|
189
|
+
* EXEC SQL begin declare section;
|
190
|
+
*/
|
191
|
+
#line 168 "informix.ec"
|
192
|
+
#line 169 "informix.ec"
|
193
|
+
char *did;
|
194
|
+
/*
|
195
|
+
* EXEC SQL end declare section;
|
196
|
+
*/
|
197
|
+
#line 170 "informix.ec"
|
198
|
+
|
199
|
+
|
200
|
+
rb_scan_args(argc, argv, "12", &db, &type, &options);
|
201
|
+
Data_Get_Struct(db, char, did);
|
202
|
+
|
203
|
+
if (currentdid != did) {
|
204
|
+
/*
|
205
|
+
* EXEC SQL set connection :did;
|
206
|
+
*/
|
207
|
+
#line 176 "informix.ec"
|
208
|
+
{
|
209
|
+
#line 176 "informix.ec"
|
210
|
+
sqli_connect_set(0, did, 0);
|
211
|
+
#line 176 "informix.ec"
|
212
|
+
}
|
213
|
+
if (SQLCODE < 0)
|
214
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
215
|
+
currentdid = did;
|
216
|
+
}
|
217
|
+
|
218
|
+
Data_Get_Struct(self, slob_t, slob);
|
219
|
+
slob->db = db;
|
220
|
+
slob->database_id = did;
|
221
|
+
|
222
|
+
if (RTEST(type)) {
|
223
|
+
int t = FIX2INT(type);
|
224
|
+
if (t != XID_CLOB && t != XID_BLOB)
|
225
|
+
rb_raise(rb_eRuntimeError, "Invalid type %d for an SLOB", t);
|
226
|
+
slob->type = t;
|
227
|
+
}
|
228
|
+
|
229
|
+
col_info = sbspace = estbytes = extsz = createflags = openflags = maxbytes = Qnil;
|
230
|
+
|
231
|
+
if (RTEST(options)) {
|
232
|
+
col_info = rb_hash_aref(options, sym_col_info);
|
233
|
+
sbspace = rb_hash_aref(options, sym_sbspace);
|
234
|
+
estbytes = rb_hash_aref(options, sym_estbytes);
|
235
|
+
extsz = rb_hash_aref(options, sym_extsz);
|
236
|
+
createflags = rb_hash_aref(options, sym_createflags);
|
237
|
+
openflags = rb_hash_aref(options, sym_openflags);
|
238
|
+
}
|
239
|
+
|
240
|
+
ret = ifx_lo_def_create_spec(&slob->spec);
|
241
|
+
if (ret < 0)
|
242
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", ret);
|
243
|
+
|
244
|
+
if (RTEST(col_info)) {
|
245
|
+
ret = ifx_lo_col_info(StringValueCStr(col_info), slob->spec);
|
246
|
+
|
247
|
+
if (ret < 0)
|
248
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", ret);
|
249
|
+
}
|
250
|
+
if (RTEST(sbspace)) {
|
251
|
+
char *c_sbspace = StringValueCStr(sbspace);
|
252
|
+
ret = ifx_lo_specset_sbspace(slob->spec, c_sbspace);
|
253
|
+
if (ret == -1)
|
254
|
+
rb_raise(rb_eRuntimeError, "Could not set sbspace name to %s", c_sbspace);
|
255
|
+
}
|
256
|
+
if (RTEST(estbytes)) {
|
257
|
+
ifx_int8_t estbytes8;
|
258
|
+
|
259
|
+
NUM2INT8(estbytes, &estbytes8);
|
260
|
+
ret = ifx_lo_specset_estbytes(slob->spec, &estbytes8);
|
261
|
+
if (ret == -1)
|
262
|
+
rb_raise(rb_eRuntimeError, "Could not set estbytes");
|
263
|
+
}
|
264
|
+
if (RTEST(extsz)) {
|
265
|
+
ret = ifx_lo_specset_extsz(slob->spec, FIX2LONG(extsz));
|
266
|
+
if (ret == -1)
|
267
|
+
rb_raise(rb_eRuntimeError, "Could not set extsz to %d", FIX2LONG(extsz));
|
268
|
+
}
|
269
|
+
if (RTEST(createflags)) {
|
270
|
+
ret = ifx_lo_specset_flags(slob->spec, FIX2LONG(createflags));
|
271
|
+
if (ret == -1)
|
272
|
+
rb_raise(rb_eRuntimeError, "Could not set crate-time flags to 0x%X", FIX2LONG(createflags));
|
273
|
+
}
|
274
|
+
if (RTEST(maxbytes)) {
|
275
|
+
ifx_int8_t maxbytes8;
|
276
|
+
|
277
|
+
NUM2INT8(maxbytes, (&maxbytes8));
|
278
|
+
ret = ifx_lo_specset_maxbytes(slob->spec, &maxbytes8);
|
279
|
+
if (ret == -1)
|
280
|
+
rb_raise(rb_eRuntimeError, "Could not set maxbytes");
|
281
|
+
}
|
282
|
+
slob->fd = ifx_lo_create(slob->spec, RTEST(openflags)? FIX2LONG(openflags): LO_RDWR, &slob->lo, &error);
|
283
|
+
if (slob->fd == -1) {
|
284
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d\n", error);
|
285
|
+
}
|
286
|
+
return self;
|
287
|
+
}
|
288
|
+
|
289
|
+
/*
|
290
|
+
* call-seq:
|
291
|
+
* slob.open(access = Slob::RDONLY) => slob
|
292
|
+
*
|
293
|
+
* Opens the Smart Large Object in <i>access</i> mode.
|
294
|
+
*
|
295
|
+
* access modes:
|
296
|
+
*
|
297
|
+
* Slob::RDONLY:: Read only
|
298
|
+
* Slob::DIRTY_READ:: Read uncommitted data
|
299
|
+
* Slob::WRONLY:: Write only
|
300
|
+
* Slob::APPEND:: Append data to the end, if combined with RDRW or WRONLY; read only otherwise
|
301
|
+
* Slob::RDRW:: Read/Write
|
302
|
+
* Slob::BUFFER:: Use standard database server buffer pool
|
303
|
+
* Slob::NOBUFFER:: Use private buffer from the session pool of the database server
|
304
|
+
* Slob::LOCKALL:: Lock the entire Smart Large Object
|
305
|
+
* Slob::LOCKRANGE:: Lock a range of bytes
|
306
|
+
*
|
307
|
+
* Returns __self__.
|
308
|
+
*/
|
309
|
+
static VALUE
|
310
|
+
slob_open(int argc, VALUE *argv, VALUE self)
|
311
|
+
{
|
312
|
+
VALUE access;
|
313
|
+
slob_t *slob;
|
314
|
+
mint error;
|
315
|
+
/*
|
316
|
+
* EXEC SQL begin declare section;
|
317
|
+
*/
|
318
|
+
#line 279 "informix.ec"
|
319
|
+
#line 280 "informix.ec"
|
320
|
+
char *did;
|
321
|
+
/*
|
322
|
+
* EXEC SQL end declare section;
|
323
|
+
*/
|
324
|
+
#line 281 "informix.ec"
|
325
|
+
|
326
|
+
|
327
|
+
Data_Get_Struct(self, slob_t, slob);
|
328
|
+
|
329
|
+
if (slob->fd != -1) /* Already open */
|
330
|
+
return self;
|
331
|
+
|
332
|
+
did = slob->database_id;
|
333
|
+
if (currentdid != did) {
|
334
|
+
/*
|
335
|
+
* EXEC SQL set connection :did;
|
336
|
+
*/
|
337
|
+
#line 290 "informix.ec"
|
338
|
+
{
|
339
|
+
#line 290 "informix.ec"
|
340
|
+
sqli_connect_set(0, did, 0);
|
341
|
+
#line 290 "informix.ec"
|
342
|
+
}
|
343
|
+
if (SQLCODE < 0)
|
344
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
345
|
+
currentdid = did;
|
346
|
+
}
|
347
|
+
|
348
|
+
rb_scan_args(argc, argv, "01", &access);
|
349
|
+
|
350
|
+
slob->fd = ifx_lo_open(&slob->lo, NIL_P(access)? LO_RDONLY: FIX2INT(access), &error);
|
351
|
+
|
352
|
+
if (slob->fd == -1)
|
353
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", error);
|
354
|
+
|
355
|
+
return self;
|
356
|
+
}
|
357
|
+
|
358
|
+
/*
|
359
|
+
* call-seq:
|
360
|
+
* slob.close => slob
|
361
|
+
*
|
362
|
+
* Closes the Smart Large Object and returns __self__.
|
363
|
+
*/
|
364
|
+
static VALUE
|
365
|
+
slob_close(VALUE self)
|
366
|
+
{
|
367
|
+
slob_t *slob;
|
368
|
+
|
369
|
+
Data_Get_Struct(self, slob_t, slob);
|
370
|
+
if (slob->fd != -1) {
|
371
|
+
/*
|
372
|
+
* EXEC SQL begin declare section;
|
373
|
+
*/
|
374
|
+
#line 319 "informix.ec"
|
375
|
+
#line 320 "informix.ec"
|
376
|
+
char *did;
|
377
|
+
/*
|
378
|
+
* EXEC SQL end declare section;
|
379
|
+
*/
|
380
|
+
#line 321 "informix.ec"
|
381
|
+
|
382
|
+
|
383
|
+
did = slob->database_id;
|
384
|
+
if (currentdid != did) {
|
385
|
+
/*
|
386
|
+
* EXEC SQL set connection :did;
|
387
|
+
*/
|
388
|
+
#line 325 "informix.ec"
|
389
|
+
{
|
390
|
+
#line 325 "informix.ec"
|
391
|
+
sqli_connect_set(0, did, 0);
|
392
|
+
#line 325 "informix.ec"
|
393
|
+
}
|
394
|
+
if (SQLCODE < 0)
|
395
|
+
return self;
|
396
|
+
currentdid = did;
|
397
|
+
}
|
398
|
+
|
399
|
+
ifx_lo_close(slob->fd);
|
400
|
+
slob->fd = -1;
|
401
|
+
}
|
402
|
+
|
403
|
+
return self;
|
404
|
+
}
|
405
|
+
|
406
|
+
/*
|
407
|
+
* call-seq:
|
408
|
+
* slob.read(nbytes) => string
|
409
|
+
*
|
410
|
+
* Reads at most <i>nbytes</i> bytes from the Smart Large Object.
|
411
|
+
*
|
412
|
+
* Returns the bytes read as a String object.
|
413
|
+
*/
|
414
|
+
static VALUE
|
415
|
+
slob_read(VALUE self, VALUE nbytes)
|
416
|
+
{
|
417
|
+
slob_t *slob;
|
418
|
+
mint error, ret;
|
419
|
+
char *buffer;
|
420
|
+
long c_nbytes;
|
421
|
+
VALUE str;
|
422
|
+
/*
|
423
|
+
* EXEC SQL begin declare section;
|
424
|
+
*/
|
425
|
+
#line 354 "informix.ec"
|
426
|
+
#line 355 "informix.ec"
|
427
|
+
char *did;
|
428
|
+
/*
|
429
|
+
* EXEC SQL end declare section;
|
430
|
+
*/
|
431
|
+
#line 356 "informix.ec"
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
Data_Get_Struct(self, slob_t, slob);
|
436
|
+
|
437
|
+
if (slob->fd == -1)
|
438
|
+
rb_raise(rb_eRuntimeError, "Open the Slob object before reading");
|
439
|
+
|
440
|
+
did = slob->database_id;
|
441
|
+
if (currentdid != did) {
|
442
|
+
/*
|
443
|
+
* EXEC SQL set connection :did;
|
444
|
+
*/
|
445
|
+
#line 366 "informix.ec"
|
446
|
+
{
|
447
|
+
#line 366 "informix.ec"
|
448
|
+
sqli_connect_set(0, did, 0);
|
449
|
+
#line 366 "informix.ec"
|
450
|
+
}
|
451
|
+
if (SQLCODE < 0)
|
452
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
453
|
+
currentdid = did;
|
454
|
+
}
|
455
|
+
|
456
|
+
c_nbytes = FIX2LONG(nbytes);
|
457
|
+
buffer = ALLOC_N(char, c_nbytes);
|
458
|
+
ret = ifx_lo_read(slob->fd, buffer, c_nbytes, &error);
|
459
|
+
|
460
|
+
if (ret == -1)
|
461
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d\n", error);
|
462
|
+
|
463
|
+
str = rb_str_new(buffer, ret);
|
464
|
+
xfree(buffer);
|
465
|
+
|
466
|
+
return str;
|
467
|
+
}
|
468
|
+
|
469
|
+
/*
|
470
|
+
* call-seq:
|
471
|
+
* slob.write(data) => fixnum or bignum
|
472
|
+
*
|
473
|
+
* Writes <i>data</i> to the Smart Large Object.
|
474
|
+
*
|
475
|
+
* Returns the number of bytes written.
|
476
|
+
*/
|
477
|
+
static VALUE
|
478
|
+
slob_write(VALUE self, VALUE data)
|
479
|
+
{
|
480
|
+
slob_t *slob;
|
481
|
+
mint error, ret;
|
482
|
+
char *buffer;
|
483
|
+
long nbytes;
|
484
|
+
VALUE str;
|
485
|
+
/*
|
486
|
+
* EXEC SQL begin declare section;
|
487
|
+
*/
|
488
|
+
#line 401 "informix.ec"
|
489
|
+
#line 402 "informix.ec"
|
490
|
+
char *did;
|
491
|
+
/*
|
492
|
+
* EXEC SQL end declare section;
|
493
|
+
*/
|
494
|
+
#line 403 "informix.ec"
|
495
|
+
|
496
|
+
|
497
|
+
Data_Get_Struct(self, slob_t, slob);
|
498
|
+
|
499
|
+
if (slob->fd == -1)
|
500
|
+
rb_raise(rb_eRuntimeError, "Open the Slob object before writing");
|
501
|
+
|
502
|
+
did = slob->database_id;
|
503
|
+
if (currentdid != did) {
|
504
|
+
/*
|
505
|
+
* EXEC SQL set connection :did;
|
506
|
+
*/
|
507
|
+
#line 412 "informix.ec"
|
508
|
+
{
|
509
|
+
#line 412 "informix.ec"
|
510
|
+
sqli_connect_set(0, did, 0);
|
511
|
+
#line 412 "informix.ec"
|
512
|
+
}
|
513
|
+
if (SQLCODE < 0)
|
514
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
515
|
+
currentdid = did;
|
516
|
+
}
|
517
|
+
|
518
|
+
str = StringValue(data);
|
519
|
+
buffer = RSTRING(str)->ptr;
|
520
|
+
nbytes = RSTRING(str)->len;
|
521
|
+
|
522
|
+
ret = ifx_lo_write(slob->fd, buffer, nbytes, &error);
|
523
|
+
|
524
|
+
if (ret == -1)
|
525
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", error);
|
526
|
+
|
527
|
+
return LONG2NUM(ret);
|
528
|
+
}
|
529
|
+
|
530
|
+
/*
|
531
|
+
* call-seq:
|
532
|
+
* slob.seek(offset, whence) => fixnum or bignum
|
533
|
+
*
|
534
|
+
* Sets the file position for the next read or write
|
535
|
+
* operation on the open Smart Large Object.
|
536
|
+
*
|
537
|
+
*
|
538
|
+
* <i>offset</i> offset from the starting seek position
|
539
|
+
* <i>whence</i> identifies the starting seek position
|
540
|
+
*
|
541
|
+
* Values for <i>whence</i>:
|
542
|
+
*
|
543
|
+
* Slob::SEEK_SET:: The start of the Smart Large Object
|
544
|
+
* Slob::SEEK_CUR:: The current seek position in the Smart Large Object
|
545
|
+
* Slob::SEEK_END:: The end of the Smart Large Object
|
546
|
+
*
|
547
|
+
* Returns the new position.
|
548
|
+
*/
|
549
|
+
static VALUE
|
550
|
+
slob_seek(VALUE self, VALUE offset, VALUE whence)
|
551
|
+
{
|
552
|
+
slob_t *slob;
|
553
|
+
mint ret;
|
554
|
+
VALUE seek_pos;
|
555
|
+
ifx_int8_t offset8, seek_pos8;
|
556
|
+
/*
|
557
|
+
* EXEC SQL begin declare section;
|
558
|
+
*/
|
559
|
+
#line 456 "informix.ec"
|
560
|
+
#line 457 "informix.ec"
|
561
|
+
char *did;
|
562
|
+
/*
|
563
|
+
* EXEC SQL end declare section;
|
564
|
+
*/
|
565
|
+
#line 458 "informix.ec"
|
566
|
+
|
567
|
+
|
568
|
+
Data_Get_Struct(self, slob_t, slob);
|
569
|
+
|
570
|
+
if (slob->fd == -1)
|
571
|
+
rb_raise(rb_eRuntimeError, "Open the Slob object first");
|
572
|
+
|
573
|
+
did = slob->database_id;
|
574
|
+
if (currentdid != did) {
|
575
|
+
/*
|
576
|
+
* EXEC SQL set connection :did;
|
577
|
+
*/
|
578
|
+
#line 467 "informix.ec"
|
579
|
+
{
|
580
|
+
#line 467 "informix.ec"
|
581
|
+
sqli_connect_set(0, did, 0);
|
582
|
+
#line 467 "informix.ec"
|
583
|
+
}
|
584
|
+
if (SQLCODE < 0)
|
585
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
586
|
+
currentdid = did;
|
587
|
+
}
|
588
|
+
|
589
|
+
NUM2INT8(offset, &offset8);
|
590
|
+
ret = ifx_lo_seek(slob->fd, &offset8, FIX2INT(whence), &seek_pos8);
|
591
|
+
if (ret < 0)
|
592
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", ret);
|
593
|
+
|
594
|
+
INT82NUM(&seek_pos8, seek_pos);
|
595
|
+
|
596
|
+
return seek_pos;
|
597
|
+
}
|
598
|
+
|
599
|
+
/*
|
600
|
+
* call-seq:
|
601
|
+
* slob.tell => fixnum or bignum
|
602
|
+
*
|
603
|
+
* Returns the current file or seek position for an
|
604
|
+
* open Smart Large Object
|
605
|
+
*/
|
606
|
+
static VALUE
|
607
|
+
slob_tell(VALUE self)
|
608
|
+
{
|
609
|
+
slob_t *slob;
|
610
|
+
mint ret;
|
611
|
+
VALUE seek_pos;
|
612
|
+
ifx_int8_t seek_pos8;
|
613
|
+
/*
|
614
|
+
* EXEC SQL begin declare section;
|
615
|
+
*/
|
616
|
+
#line 497 "informix.ec"
|
617
|
+
#line 498 "informix.ec"
|
618
|
+
char *did;
|
619
|
+
/*
|
620
|
+
* EXEC SQL end declare section;
|
621
|
+
*/
|
622
|
+
#line 499 "informix.ec"
|
623
|
+
|
624
|
+
|
625
|
+
Data_Get_Struct(self, slob_t, slob);
|
626
|
+
|
627
|
+
if (slob->fd == -1)
|
628
|
+
rb_raise(rb_eRuntimeError, "Open the Slob object first");
|
629
|
+
|
630
|
+
did = slob->database_id;
|
631
|
+
if (currentdid != did) {
|
632
|
+
/*
|
633
|
+
* EXEC SQL set connection :did;
|
634
|
+
*/
|
635
|
+
#line 508 "informix.ec"
|
636
|
+
{
|
637
|
+
#line 508 "informix.ec"
|
638
|
+
sqli_connect_set(0, did, 0);
|
639
|
+
#line 508 "informix.ec"
|
640
|
+
}
|
641
|
+
if (SQLCODE < 0)
|
642
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
643
|
+
currentdid = did;
|
644
|
+
}
|
645
|
+
|
646
|
+
ret = ifx_lo_tell(slob->fd, &seek_pos8);
|
647
|
+
if (ret < 0)
|
648
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", ret);
|
649
|
+
|
650
|
+
INT82NUM(&seek_pos8, seek_pos);
|
651
|
+
|
652
|
+
return seek_pos;
|
653
|
+
}
|
654
|
+
|
655
|
+
/*
|
656
|
+
* call-seq:
|
657
|
+
* slob.truncate(offset) => slob
|
658
|
+
*
|
659
|
+
* Truncates a Smart Large Object at a specified byte position.
|
660
|
+
*
|
661
|
+
* Returns __self__.
|
662
|
+
*/
|
663
|
+
static VALUE
|
664
|
+
slob_truncate(VALUE self, VALUE offset)
|
665
|
+
{
|
666
|
+
slob_t *slob;
|
667
|
+
mint ret;
|
668
|
+
ifx_int8_t offset8;
|
669
|
+
/*
|
670
|
+
* EXEC SQL begin declare section;
|
671
|
+
*/
|
672
|
+
#line 537 "informix.ec"
|
673
|
+
#line 538 "informix.ec"
|
674
|
+
char *did;
|
675
|
+
/*
|
676
|
+
* EXEC SQL end declare section;
|
677
|
+
*/
|
678
|
+
#line 539 "informix.ec"
|
679
|
+
|
680
|
+
|
681
|
+
Data_Get_Struct(self, slob_t, slob);
|
682
|
+
|
683
|
+
if (slob->fd == -1)
|
684
|
+
rb_raise(rb_eRuntimeError, "Open the Slob object first");
|
685
|
+
|
686
|
+
did = slob->database_id;
|
687
|
+
if (currentdid != did) {
|
688
|
+
/*
|
689
|
+
* EXEC SQL set connection :did;
|
690
|
+
*/
|
691
|
+
#line 548 "informix.ec"
|
692
|
+
{
|
693
|
+
#line 548 "informix.ec"
|
694
|
+
sqli_connect_set(0, did, 0);
|
695
|
+
#line 548 "informix.ec"
|
696
|
+
}
|
697
|
+
if (SQLCODE < 0)
|
698
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
699
|
+
currentdid = did;
|
700
|
+
}
|
701
|
+
|
702
|
+
NUM2INT8(offset, &offset8);
|
703
|
+
ret = ifx_lo_truncate(slob->fd, &offset8);
|
704
|
+
if (ret < 0)
|
705
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", ret);
|
706
|
+
|
707
|
+
return self;
|
708
|
+
}
|
709
|
+
|
710
|
+
/* Helper functions ------------------------------------------------------- */
|
711
|
+
|
712
|
+
/*
|
713
|
+
* Counts the number of markers '?' in the query
|
714
|
+
*/
|
715
|
+
static int count_markers(const char *query)
|
716
|
+
{
|
717
|
+
register char c, quote = 0;
|
718
|
+
register int count = 0;
|
719
|
+
|
720
|
+
while((c = *query++)) {
|
721
|
+
if (quote && c != quote)
|
722
|
+
;
|
723
|
+
else if (quote == c) {
|
724
|
+
quote = 0;
|
725
|
+
}
|
726
|
+
else if (c == '\'' || c == '"') {
|
727
|
+
quote = c;
|
728
|
+
}
|
729
|
+
else if (c == '?') {
|
730
|
+
++count;
|
731
|
+
}
|
732
|
+
}
|
733
|
+
return count;
|
734
|
+
}
|
735
|
+
|
736
|
+
/*
|
737
|
+
* Allocates memory for the indicators array and slots for the input
|
738
|
+
* parameters, if any. Freed by free_input_slots.
|
739
|
+
*/
|
740
|
+
static void
|
741
|
+
alloc_input_slots(cursor_t *c, const char *query)
|
742
|
+
{
|
743
|
+
register int n;
|
744
|
+
|
745
|
+
n = count_markers(query);
|
746
|
+
c->daInput.sqld = n;
|
747
|
+
if (n) {
|
748
|
+
c->daInput.sqlvar = ALLOC_N(struct sqlvar_struct, n);
|
749
|
+
memset(c->daInput.sqlvar, 0, n*sizeof(struct sqlvar_struct));
|
750
|
+
c->indInput = ALLOC_N(short, n);
|
751
|
+
while(n--)
|
752
|
+
c->daInput.sqlvar[n].sqlind = &c->indInput[n];
|
753
|
+
}
|
754
|
+
else {
|
755
|
+
c->daInput.sqlvar = NULL;
|
756
|
+
c->indInput = NULL;
|
757
|
+
}
|
758
|
+
}
|
759
|
+
|
760
|
+
/*
|
761
|
+
* Allocates memory for the output data slots and its indicators array.
|
762
|
+
* Freed by free_output_slots.
|
763
|
+
*/
|
764
|
+
static void
|
765
|
+
alloc_output_slots(cursor_t *c)
|
766
|
+
{
|
767
|
+
register int i, count;
|
768
|
+
register short *ind;
|
769
|
+
struct sqlvar_struct *var;
|
770
|
+
register char *buffer;
|
771
|
+
|
772
|
+
c->field_names = rb_ary_new2(c->daOutput->sqld);
|
773
|
+
|
774
|
+
ind = c->indOutput = ALLOC_N(short, c->daOutput->sqld);
|
775
|
+
|
776
|
+
var = c->daOutput->sqlvar;
|
777
|
+
for (i = count = 0; i < c->daOutput->sqld; i++, ind++, var++) {
|
778
|
+
var->sqlind = ind;
|
779
|
+
rb_ary_store(c->field_names, i, rb_str_new2(var->sqlname));
|
780
|
+
if (ISSMARTBLOB(var->sqltype, var->sqlxid)) {
|
781
|
+
var->sqldata = (char *)ALLOC(ifx_lo_t);
|
782
|
+
continue;
|
783
|
+
}
|
784
|
+
var->sqllen = rtypmsize(var->sqltype, var->sqllen);
|
785
|
+
count = rtypalign(count, var->sqltype) + var->sqllen;
|
786
|
+
}
|
787
|
+
|
788
|
+
buffer = c->bfOutput = ALLOC_N(char, count);
|
789
|
+
memset(buffer, 0, count);
|
790
|
+
|
791
|
+
var = c->daOutput->sqlvar;
|
792
|
+
for (i = count = 0; i < c->daOutput->sqld; i++, var++) {
|
793
|
+
if (var->sqldata)
|
794
|
+
continue;
|
795
|
+
count = rtypalign(count, var->sqltype);
|
796
|
+
var->sqldata = buffer + count;
|
797
|
+
count += var->sqllen;
|
798
|
+
if (ISBYTESTYPE(var->sqltype) || ISTEXTTYPE(var->sqltype)) {
|
799
|
+
loc_t *p;
|
800
|
+
p = (loc_t *)var->sqldata;
|
801
|
+
byfill((char *)p, sizeof(loc_t), 0);
|
802
|
+
p->loc_loctype = LOCMEMORY;
|
803
|
+
p->loc_bufsize = -1;
|
804
|
+
}
|
805
|
+
if (var->sqltype == SQLDTIME) {
|
806
|
+
var->sqllen = 0;
|
807
|
+
}
|
808
|
+
}
|
809
|
+
}
|
810
|
+
|
811
|
+
/*
|
812
|
+
* Frees the allocated memory of the input parameters, but not the slots
|
813
|
+
* nor the indicators array. Allocated by bind_input_params.
|
814
|
+
*/
|
815
|
+
static void
|
816
|
+
clean_input_slots(cursor_t *c)
|
817
|
+
{
|
818
|
+
register int count;
|
819
|
+
register struct sqlvar_struct *var;
|
820
|
+
|
821
|
+
if (c->daInput.sqlvar == NULL)
|
822
|
+
return;
|
823
|
+
var = c->daInput.sqlvar;
|
824
|
+
count = c->daInput.sqld;
|
825
|
+
while(count--) {
|
826
|
+
if (var->sqldata != NULL) {
|
827
|
+
if (var->sqltype == CLOCATORTYPE) {
|
828
|
+
loc_t *p = (loc_t *)var->sqldata;
|
829
|
+
if (p->loc_buffer != NULL) {
|
830
|
+
xfree(p->loc_buffer);
|
831
|
+
}
|
832
|
+
}
|
833
|
+
xfree(var->sqldata);
|
834
|
+
var->sqldata = NULL;
|
835
|
+
var++;
|
836
|
+
}
|
837
|
+
}
|
838
|
+
}
|
839
|
+
|
840
|
+
/*
|
841
|
+
* Frees the memory for the input parameters, their slots, and the indicators
|
842
|
+
* array. Allocated by alloc_input_slots and bind_input_params.
|
843
|
+
*/
|
844
|
+
static void
|
845
|
+
free_input_slots(cursor_t *c)
|
846
|
+
{
|
847
|
+
clean_input_slots(c);
|
848
|
+
if (c->daInput.sqlvar) {
|
849
|
+
xfree(c->daInput.sqlvar);
|
850
|
+
c->daInput.sqlvar = NULL;
|
851
|
+
c->daInput.sqld = 0;
|
852
|
+
}
|
853
|
+
if (c->indInput) {
|
854
|
+
xfree(c->indInput);
|
855
|
+
c->indInput = NULL;
|
856
|
+
}
|
857
|
+
}
|
858
|
+
|
859
|
+
/*
|
860
|
+
* Frees the memory for the output parameters, their slots, and the indicators
|
861
|
+
* array. Allocated by alloc_output_slots.
|
862
|
+
*/
|
863
|
+
static void
|
864
|
+
free_output_slots(cursor_t *c)
|
865
|
+
{
|
866
|
+
if (c->daOutput != NULL) {
|
867
|
+
struct sqlvar_struct *var = c->daOutput->sqlvar;
|
868
|
+
if (var) {
|
869
|
+
register int i;
|
870
|
+
for (i = 0; i < c->daOutput->sqld; i++, var++) {
|
871
|
+
if (ISBLOBTYPE(var->sqltype)) {
|
872
|
+
loc_t *p = (loc_t *) var->sqldata;
|
873
|
+
if(p -> loc_buffer)
|
874
|
+
xfree(p->loc_buffer);
|
875
|
+
}
|
876
|
+
if (ISSMARTBLOB(var->sqltype, var->sqlxid))
|
877
|
+
xfree(var->sqldata);
|
878
|
+
}
|
879
|
+
}
|
880
|
+
xfree(c->daOutput);
|
881
|
+
c->daOutput = NULL;
|
882
|
+
}
|
883
|
+
if (c->indOutput != NULL) {
|
884
|
+
xfree(c->indOutput);
|
885
|
+
c->indOutput = NULL;
|
886
|
+
}
|
887
|
+
if (c->bfOutput != NULL) {
|
888
|
+
xfree(c->bfOutput);
|
889
|
+
c->bfOutput = NULL;
|
890
|
+
}
|
891
|
+
}
|
892
|
+
|
893
|
+
/*
|
894
|
+
* Gets an array of Ruby objects as input parameters and place them in input
|
895
|
+
* slots, converting data types and allocating memory as needed.
|
896
|
+
*/
|
897
|
+
static void
|
898
|
+
bind_input_params(cursor_t *c, VALUE *argv)
|
899
|
+
{
|
900
|
+
VALUE data, klass;
|
901
|
+
register int i;
|
902
|
+
register struct sqlvar_struct *var;
|
903
|
+
|
904
|
+
var = c->daInput.sqlvar;
|
905
|
+
for (i = 0; i < c->daInput.sqld; i++, var++) {
|
906
|
+
data = argv[i];
|
907
|
+
|
908
|
+
switch(TYPE(data)) {
|
909
|
+
case T_NIL:
|
910
|
+
var->sqltype = CSTRINGTYPE;
|
911
|
+
var->sqldata = NULL;
|
912
|
+
var->sqllen = 0;
|
913
|
+
*var->sqlind = -1;
|
914
|
+
break;
|
915
|
+
case T_FIXNUM:
|
916
|
+
var->sqldata = (char *)ALLOC(long);
|
917
|
+
*((long *)var->sqldata) = FIX2LONG(data);
|
918
|
+
var->sqltype = CLONGTYPE;
|
919
|
+
var->sqllen = sizeof(long);
|
920
|
+
*var->sqlind = 0;
|
921
|
+
break;
|
922
|
+
case T_FLOAT:
|
923
|
+
var->sqldata = (char *)ALLOC(double);
|
924
|
+
*((double *)var->sqldata) = NUM2DBL(data);
|
925
|
+
var->sqltype = CDOUBLETYPE;
|
926
|
+
var->sqllen = sizeof(double);
|
927
|
+
*var->sqlind = 0;
|
928
|
+
break;
|
929
|
+
case T_TRUE:
|
930
|
+
case T_FALSE:
|
931
|
+
var->sqldata = ALLOC(char);
|
932
|
+
*var->sqldata = TYPE(data) == T_TRUE? 't': 'f';
|
933
|
+
var->sqltype = CCHARTYPE;
|
934
|
+
var->sqllen = sizeof(char);
|
935
|
+
*var->sqlind = 0;
|
936
|
+
break;
|
937
|
+
default:
|
938
|
+
klass = rb_obj_class(data);
|
939
|
+
if (klass == rb_cDate) {
|
940
|
+
int2 mdy[3];
|
941
|
+
int4 date;
|
942
|
+
|
943
|
+
mdy[0] = FIX2INT(rb_funcall(data, s_month, 0));
|
944
|
+
mdy[1] = FIX2INT(rb_funcall(data, s_day, 0));
|
945
|
+
mdy[2] = FIX2INT(rb_funcall(data, s_year, 0));
|
946
|
+
rmdyjul(mdy, &date);
|
947
|
+
|
948
|
+
var->sqldata = (char *)ALLOC(int4);
|
949
|
+
*((int4 *)var->sqldata) = date;
|
950
|
+
var->sqltype = CDATETYPE;
|
951
|
+
var->sqllen = sizeof(int4);
|
952
|
+
*var->sqlind = 0;
|
953
|
+
break;
|
954
|
+
}
|
955
|
+
if (klass == rb_cTime) {
|
956
|
+
char buffer[30];
|
957
|
+
short year, month, day, hour, minute, second;
|
958
|
+
int usec;
|
959
|
+
dtime_t *dt;
|
960
|
+
|
961
|
+
year = FIX2INT(rb_funcall(data, s_year, 0));
|
962
|
+
month = FIX2INT(rb_funcall(data, s_month, 0));
|
963
|
+
day = FIX2INT(rb_funcall(data, s_day, 0));
|
964
|
+
hour = FIX2INT(rb_funcall(data, s_hour, 0));
|
965
|
+
minute = FIX2INT(rb_funcall(data, s_min, 0));
|
966
|
+
second = FIX2INT(rb_funcall(data, s_sec, 0));
|
967
|
+
usec = FIX2INT(rb_funcall(data, s_usec, 0));
|
968
|
+
|
969
|
+
dt = ALLOC(dtime_t);
|
970
|
+
|
971
|
+
dt->dt_qual = TU_DTENCODE(TU_YEAR, TU_F5);
|
972
|
+
snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d.%d",
|
973
|
+
year, month, day, hour, minute, second, usec/10);
|
974
|
+
dtcvasc(buffer, dt);
|
975
|
+
|
976
|
+
var->sqldata = (char *)dt;
|
977
|
+
var->sqltype = CDTIMETYPE;
|
978
|
+
var->sqllen = sizeof(dtime_t);
|
979
|
+
*var->sqlind = 0;
|
980
|
+
break;
|
981
|
+
}
|
982
|
+
if (klass == rb_cSlob) {
|
983
|
+
slob_t *slob;
|
984
|
+
|
985
|
+
Data_Get_Struct(data, slob_t, slob);
|
986
|
+
|
987
|
+
var->sqldata = (char *)ALLOC(ifx_lo_t);
|
988
|
+
memcpy(var->sqldata, &slob->lo, sizeof(slob->lo));
|
989
|
+
var->sqltype = SQLUDTFIXED;
|
990
|
+
var->sqlxid = slob->type;
|
991
|
+
var->sqllen = sizeof(ifx_lo_t);
|
992
|
+
*var->sqlind = 0;
|
993
|
+
break;
|
994
|
+
}
|
995
|
+
if (rb_respond_to(data, s_read)) {
|
996
|
+
char *str;
|
997
|
+
loc_t *loc;
|
998
|
+
long len;
|
999
|
+
|
1000
|
+
data = rb_funcall(data, s_read, 0);
|
1001
|
+
data = StringValue(data);
|
1002
|
+
str = RSTRING(data)->ptr;
|
1003
|
+
len = RSTRING(data)->len;
|
1004
|
+
|
1005
|
+
loc = (loc_t *)ALLOC(loc_t);
|
1006
|
+
byfill((char *)loc, sizeof(loc_t), 0);
|
1007
|
+
loc->loc_loctype = LOCMEMORY;
|
1008
|
+
loc->loc_buffer = (char *)ALLOC_N(char, len);
|
1009
|
+
memcpy(loc->loc_buffer, str, len);
|
1010
|
+
loc->loc_bufsize = loc->loc_size = len;
|
1011
|
+
|
1012
|
+
var->sqldata = (char *)loc;
|
1013
|
+
var->sqltype = CLOCATORTYPE;
|
1014
|
+
var->sqllen = sizeof(loc_t);
|
1015
|
+
*var->sqlind = 0;
|
1016
|
+
break;
|
1017
|
+
}
|
1018
|
+
{
|
1019
|
+
VALUE str;
|
1020
|
+
str = rb_check_string_type(data);
|
1021
|
+
if (NIL_P(str)) {
|
1022
|
+
data = rb_obj_as_string(data);
|
1023
|
+
}
|
1024
|
+
else {
|
1025
|
+
data = str;
|
1026
|
+
}
|
1027
|
+
}
|
1028
|
+
case T_STRING: {
|
1029
|
+
char *str;
|
1030
|
+
long len;
|
1031
|
+
|
1032
|
+
str = RSTRING(data)->ptr;
|
1033
|
+
len = RSTRING(data)->len;
|
1034
|
+
var->sqldata = ALLOC_N(char, len + 1);
|
1035
|
+
memcpy(var->sqldata, str, len);
|
1036
|
+
var->sqldata[len] = 0;
|
1037
|
+
var->sqltype = CSTRINGTYPE;
|
1038
|
+
var->sqllen = len;
|
1039
|
+
*var->sqlind = 0;
|
1040
|
+
break;
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
}
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
/*
|
1047
|
+
* Returns an array or a hash of Ruby objects containing the record fetched.
|
1048
|
+
*/
|
1049
|
+
static VALUE
|
1050
|
+
make_result(cursor_t *c, VALUE record)
|
1051
|
+
{
|
1052
|
+
VALUE item;
|
1053
|
+
register int i;
|
1054
|
+
register struct sqlvar_struct *var;
|
1055
|
+
|
1056
|
+
var = c->daOutput->sqlvar;
|
1057
|
+
for (i = 0; i < c->daOutput->sqld; i++, var++) {
|
1058
|
+
if (*var->sqlind == -1) {
|
1059
|
+
item = Qnil;
|
1060
|
+
} else {
|
1061
|
+
switch(var->sqltype) {
|
1062
|
+
case SQLCHAR:
|
1063
|
+
case SQLVCHAR:
|
1064
|
+
case SQLNCHAR:
|
1065
|
+
case SQLNVCHAR:
|
1066
|
+
item = rb_str_new2(var->sqldata);
|
1067
|
+
break;
|
1068
|
+
case SQLSMINT:
|
1069
|
+
item = INT2FIX(*(int2 *)var->sqldata);
|
1070
|
+
break;
|
1071
|
+
case SQLINT:
|
1072
|
+
case SQLSERIAL:
|
1073
|
+
item = INT2NUM(*(int4 *)var->sqldata);
|
1074
|
+
break;
|
1075
|
+
case SQLINT8:
|
1076
|
+
case SQLSERIAL8:
|
1077
|
+
INT82NUM((ifx_int8_t *)var->sqldata, item);
|
1078
|
+
break;
|
1079
|
+
case SQLSMFLOAT:
|
1080
|
+
item = rb_float_new(*(float *)var->sqldata);
|
1081
|
+
break;
|
1082
|
+
case SQLFLOAT:
|
1083
|
+
item = rb_float_new(*(double *)var->sqldata);
|
1084
|
+
break;
|
1085
|
+
case SQLDATE: {
|
1086
|
+
VALUE year, month, day;
|
1087
|
+
int2 mdy[3];
|
1088
|
+
|
1089
|
+
rjulmdy(*(int4 *)var->sqldata, mdy);
|
1090
|
+
year = INT2FIX(mdy[2]);
|
1091
|
+
month = INT2FIX(mdy[0]);
|
1092
|
+
day = INT2FIX(mdy[1]);
|
1093
|
+
item = rb_funcall(rb_cDate, s_new, 3, year, month, day);
|
1094
|
+
break;
|
1095
|
+
}
|
1096
|
+
case SQLDTIME: {
|
1097
|
+
register short qual;
|
1098
|
+
short year, month, day, hour, minute, second;
|
1099
|
+
int usec;
|
1100
|
+
dtime_t *dt;
|
1101
|
+
register char *dgts;
|
1102
|
+
|
1103
|
+
month = day = 1;
|
1104
|
+
year = hour = minute = second = usec = 0;
|
1105
|
+
dt = (dtime_t *)var->sqldata;
|
1106
|
+
dgts = dt->dt_dec.dec_dgts;
|
1107
|
+
|
1108
|
+
qual = TU_START(dt->dt_qual);
|
1109
|
+
for (; qual <= TU_END(dt->dt_qual); qual++) {
|
1110
|
+
switch(qual) {
|
1111
|
+
case TU_YEAR:
|
1112
|
+
year = 100**dgts++;
|
1113
|
+
year += *dgts++;
|
1114
|
+
break;
|
1115
|
+
case TU_MONTH:
|
1116
|
+
month = *dgts++;
|
1117
|
+
break;
|
1118
|
+
case TU_DAY:
|
1119
|
+
day = *dgts++;
|
1120
|
+
break;
|
1121
|
+
case TU_HOUR:
|
1122
|
+
hour = *dgts++;
|
1123
|
+
break;
|
1124
|
+
case TU_MINUTE:
|
1125
|
+
minute = *dgts++;
|
1126
|
+
break;
|
1127
|
+
case TU_SECOND:
|
1128
|
+
second = *dgts++;
|
1129
|
+
break;
|
1130
|
+
case TU_F1:
|
1131
|
+
usec = 10000**dgts++;
|
1132
|
+
break;
|
1133
|
+
case TU_F3:
|
1134
|
+
usec += 100**dgts++;
|
1135
|
+
break;
|
1136
|
+
case TU_F5:
|
1137
|
+
usec += *dgts++;
|
1138
|
+
break;
|
1139
|
+
}
|
1140
|
+
}
|
1141
|
+
|
1142
|
+
item = rb_funcall(rb_cTime, s_utc, 7,
|
1143
|
+
INT2FIX(year), INT2FIX(month), INT2FIX(day),
|
1144
|
+
INT2FIX(hour), INT2FIX(minute), INT2FIX(second),
|
1145
|
+
INT2FIX(usec));
|
1146
|
+
|
1147
|
+
/* Clean the buffer for DATETIME columns because
|
1148
|
+
* ESQL/C leaves the previous content when a
|
1149
|
+
* a time field is zero.
|
1150
|
+
*/
|
1151
|
+
memset(dt, 0, sizeof(dtime_t));
|
1152
|
+
break;
|
1153
|
+
}
|
1154
|
+
case SQLDECIMAL:
|
1155
|
+
case SQLMONEY: {
|
1156
|
+
double dblValue;
|
1157
|
+
dectodbl((dec_t *)var->sqldata, &dblValue);
|
1158
|
+
item = rb_float_new(dblValue);
|
1159
|
+
break;
|
1160
|
+
}
|
1161
|
+
case SQLBOOL:
|
1162
|
+
item = var->sqldata[0]? Qtrue: Qfalse;
|
1163
|
+
break;
|
1164
|
+
case SQLBYTES:
|
1165
|
+
case SQLTEXT: {
|
1166
|
+
loc_t *loc;
|
1167
|
+
loc = (loc_t *)var->sqldata;
|
1168
|
+
item = rb_str_new(loc->loc_buffer, loc->loc_size);
|
1169
|
+
break;
|
1170
|
+
}
|
1171
|
+
case SQLUDTFIXED:
|
1172
|
+
if (ISSMARTBLOB(var->sqltype, var->sqlxid)) {
|
1173
|
+
slob_t *slob;
|
1174
|
+
|
1175
|
+
item = slob_alloc(rb_cSlob);
|
1176
|
+
Data_Get_Struct(item, slob_t, slob);
|
1177
|
+
memcpy(&slob->lo, var->sqldata, sizeof(ifx_lo_t));
|
1178
|
+
slob->type = var->sqlxid;
|
1179
|
+
break;
|
1180
|
+
}
|
1181
|
+
case SQLSET:
|
1182
|
+
case SQLMULTISET:
|
1183
|
+
case SQLLIST:
|
1184
|
+
case SQLROW:
|
1185
|
+
case SQLCOLLECTION:
|
1186
|
+
case SQLROWREF:
|
1187
|
+
case SQLUDTVAR:
|
1188
|
+
case SQLREFSER8:
|
1189
|
+
case SQLLVARCHAR:
|
1190
|
+
case SQLSENDRECV:
|
1191
|
+
case SQLIMPEXP:
|
1192
|
+
case SQLIMPEXPBIN:
|
1193
|
+
case SQLUNKNOWN:
|
1194
|
+
default:
|
1195
|
+
item = Qnil;
|
1196
|
+
break;
|
1197
|
+
}
|
1198
|
+
}
|
1199
|
+
if (BUILTIN_TYPE(record) == T_ARRAY) {
|
1200
|
+
rb_ary_store(record, i, item);
|
1201
|
+
}
|
1202
|
+
else {
|
1203
|
+
rb_hash_aset(record, RARRAY(c->field_names)->ptr[i], item);
|
1204
|
+
}
|
1205
|
+
}
|
1206
|
+
return record;
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
/* module Informix -------------------------------------------------------- */
|
1210
|
+
|
1211
|
+
/*
|
1212
|
+
* call-seq:
|
1213
|
+
* Informix.connect(dbname, user = nil, password = nil) => database
|
1214
|
+
*
|
1215
|
+
* Returns a <code>Database</code> object connected to <i>dbname</i> as
|
1216
|
+
* <i>user</i> with <i>password</i>. If these are not given, connects to
|
1217
|
+
* <i>dbname</i> as the current user.
|
1218
|
+
*/
|
1219
|
+
static VALUE
|
1220
|
+
informix_connect(int argc, VALUE *argv, VALUE self)
|
1221
|
+
{
|
1222
|
+
return rb_class_new_instance(argc, argv, rb_cDatabase);
|
1223
|
+
}
|
1224
|
+
|
1225
|
+
|
1226
|
+
/* class Database --------------------------------------------------------- */
|
1227
|
+
|
1228
|
+
static void
|
1229
|
+
database_free(void *p)
|
1230
|
+
{
|
1231
|
+
/*
|
1232
|
+
* EXEC SQL begin declare section;
|
1233
|
+
*/
|
1234
|
+
#line 1083 "informix.ec"
|
1235
|
+
#line 1084 "informix.ec"
|
1236
|
+
char *did;
|
1237
|
+
/*
|
1238
|
+
* EXEC SQL end declare section;
|
1239
|
+
*/
|
1240
|
+
#line 1085 "informix.ec"
|
1241
|
+
|
1242
|
+
|
1243
|
+
did = p;
|
1244
|
+
/*
|
1245
|
+
* EXEC SQL disconnect :did;
|
1246
|
+
*/
|
1247
|
+
#line 1088 "informix.ec"
|
1248
|
+
{
|
1249
|
+
#line 1088 "informix.ec"
|
1250
|
+
sqli_connect_close(0, did, 0, 0);
|
1251
|
+
#line 1088 "informix.ec"
|
1252
|
+
}
|
1253
|
+
if (currentdid == did)
|
1254
|
+
currentdid = NULL;
|
1255
|
+
xfree(p);
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
static VALUE
|
1259
|
+
database_alloc(VALUE klass)
|
1260
|
+
{
|
1261
|
+
char *did;
|
1262
|
+
|
1263
|
+
did = ALLOC_N(char, IDSIZE);
|
1264
|
+
did[0] = 0;
|
1265
|
+
return Data_Wrap_Struct(klass, 0, database_free, did);
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
/*
|
1269
|
+
* call-seq:
|
1270
|
+
* Database.new(dbname, user = nil, password = nil) => database
|
1271
|
+
*
|
1272
|
+
* Returns a <code>Database</code> object connected to <i>dbname</i> as
|
1273
|
+
* <i>user</i> with <i>password</i>. If these are not given, connects to
|
1274
|
+
* <i>dbname</i> as the current user.
|
1275
|
+
*/
|
1276
|
+
static VALUE
|
1277
|
+
database_initialize(int argc, VALUE *argv, VALUE self)
|
1278
|
+
{
|
1279
|
+
VALUE arg[3];
|
1280
|
+
|
1281
|
+
/*
|
1282
|
+
* EXEC SQL begin declare section;
|
1283
|
+
*/
|
1284
|
+
#line 1117 "informix.ec"
|
1285
|
+
#line 1118 "informix.ec"
|
1286
|
+
char *dbname, *user = NULL, *pass = NULL, *did;
|
1287
|
+
/*
|
1288
|
+
* EXEC SQL end declare section;
|
1289
|
+
*/
|
1290
|
+
#line 1119 "informix.ec"
|
1291
|
+
|
1292
|
+
|
1293
|
+
rb_scan_args(argc, argv, "12", &arg[0], &arg[1], &arg[2]);
|
1294
|
+
|
1295
|
+
if (NIL_P(arg[0]))
|
1296
|
+
rb_raise(rb_eRuntimeError, "A database name must be specified");
|
1297
|
+
|
1298
|
+
Data_Get_Struct(self, char, did);
|
1299
|
+
|
1300
|
+
dbname = StringValueCStr(arg[0]);
|
1301
|
+
snprintf(did, IDSIZE, "DB%lX", self);
|
1302
|
+
|
1303
|
+
if (!NIL_P(arg[1]))
|
1304
|
+
user = StringValueCStr(arg[1]);
|
1305
|
+
|
1306
|
+
if (!NIL_P(arg[2]))
|
1307
|
+
pass = StringValueCStr(arg[2]);
|
1308
|
+
|
1309
|
+
if (user && pass)
|
1310
|
+
/*
|
1311
|
+
* EXEC SQL connect to :dbname as :did user :user
|
1312
|
+
* using :pass with concurrent transaction;
|
1313
|
+
*/
|
1314
|
+
#line 1138 "informix.ec"
|
1315
|
+
{
|
1316
|
+
#line 1139 "informix.ec"
|
1317
|
+
ifx_conn_t *_sqiconn;
|
1318
|
+
_sqiconn = (ifx_conn_t *)ifx_alloc_conn_user(user, pass);
|
1319
|
+
sqli_connect_open(ESQLINTVERSION, 0, dbname, did, _sqiconn, 1);
|
1320
|
+
ifx_free_conn_user(&_sqiconn);
|
1321
|
+
#line 1139 "informix.ec"
|
1322
|
+
}
|
1323
|
+
else
|
1324
|
+
/*
|
1325
|
+
* EXEC SQL connect to :dbname as :did with concurrent transaction;
|
1326
|
+
*/
|
1327
|
+
#line 1141 "informix.ec"
|
1328
|
+
{
|
1329
|
+
#line 1141 "informix.ec"
|
1330
|
+
sqli_connect_open(ESQLINTVERSION, 0, dbname, did, (ifx_conn_t *)0, 1);
|
1331
|
+
#line 1141 "informix.ec"
|
1332
|
+
}
|
1333
|
+
|
1334
|
+
if (SQLCODE < 0)
|
1335
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1336
|
+
|
1337
|
+
currentdid = did;
|
1338
|
+
|
1339
|
+
return self;
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
/*
|
1343
|
+
* call-seq:
|
1344
|
+
* db.close => db
|
1345
|
+
*
|
1346
|
+
* Disconnects <i>db</i> and returns __self__
|
1347
|
+
*/
|
1348
|
+
static VALUE
|
1349
|
+
database_close(VALUE self)
|
1350
|
+
{
|
1351
|
+
/*
|
1352
|
+
* EXEC SQL begin declare section;
|
1353
|
+
*/
|
1354
|
+
#line 1160 "informix.ec"
|
1355
|
+
#line 1161 "informix.ec"
|
1356
|
+
char *did;
|
1357
|
+
/*
|
1358
|
+
* EXEC SQL end declare section;
|
1359
|
+
*/
|
1360
|
+
#line 1162 "informix.ec"
|
1361
|
+
|
1362
|
+
|
1363
|
+
Data_Get_Struct(self, char, did);
|
1364
|
+
/*
|
1365
|
+
* EXEC SQL disconnect :did;
|
1366
|
+
*/
|
1367
|
+
#line 1165 "informix.ec"
|
1368
|
+
{
|
1369
|
+
#line 1165 "informix.ec"
|
1370
|
+
sqli_connect_close(0, did, 0, 0);
|
1371
|
+
#line 1165 "informix.ec"
|
1372
|
+
}
|
1373
|
+
if (did == currentdid)
|
1374
|
+
currentdid = NULL;
|
1375
|
+
|
1376
|
+
return self;
|
1377
|
+
}
|
1378
|
+
|
1379
|
+
/*
|
1380
|
+
* call-seq:
|
1381
|
+
* db.immediate(query) => fixnum
|
1382
|
+
*
|
1383
|
+
* Executes <i>query</i> and returns the number of rows affected.
|
1384
|
+
* <i>query</i> must not return rows. Executes efficiently any
|
1385
|
+
* non-parameterized or DQL statement.
|
1386
|
+
*/
|
1387
|
+
|
1388
|
+
static VALUE
|
1389
|
+
database_immediate(VALUE self, VALUE arg)
|
1390
|
+
{
|
1391
|
+
/*
|
1392
|
+
* EXEC SQL begin declare section;
|
1393
|
+
*/
|
1394
|
+
#line 1184 "informix.ec"
|
1395
|
+
#line 1185 "informix.ec"
|
1396
|
+
char *query, *did;
|
1397
|
+
/*
|
1398
|
+
* EXEC SQL end declare section;
|
1399
|
+
*/
|
1400
|
+
#line 1186 "informix.ec"
|
1401
|
+
|
1402
|
+
|
1403
|
+
Data_Get_Struct(self, char, did);
|
1404
|
+
|
1405
|
+
if (currentdid != did) {
|
1406
|
+
/*
|
1407
|
+
* EXEC SQL set connection :did;
|
1408
|
+
*/
|
1409
|
+
#line 1191 "informix.ec"
|
1410
|
+
{
|
1411
|
+
#line 1191 "informix.ec"
|
1412
|
+
sqli_connect_set(0, did, 0);
|
1413
|
+
#line 1191 "informix.ec"
|
1414
|
+
}
|
1415
|
+
if (SQLCODE < 0)
|
1416
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1417
|
+
currentdid = did;
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
query = StringValueCStr(arg);
|
1421
|
+
/*
|
1422
|
+
* EXEC SQL execute immediate :query;
|
1423
|
+
*/
|
1424
|
+
#line 1198 "informix.ec"
|
1425
|
+
{
|
1426
|
+
#line 1198 "informix.ec"
|
1427
|
+
sqli_exec_immed(query);
|
1428
|
+
#line 1198 "informix.ec"
|
1429
|
+
}
|
1430
|
+
if (SQLCODE < 0)
|
1431
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1432
|
+
|
1433
|
+
return INT2FIX(sqlca.sqlerrd[2]);
|
1434
|
+
}
|
1435
|
+
|
1436
|
+
/*
|
1437
|
+
* call-seq:
|
1438
|
+
* db.rollback => db
|
1439
|
+
*
|
1440
|
+
* Rolls back a transaction and returns __self__.
|
1441
|
+
*/
|
1442
|
+
static VALUE
|
1443
|
+
database_rollback(VALUE self)
|
1444
|
+
{
|
1445
|
+
/*
|
1446
|
+
* EXEC SQL begin declare section;
|
1447
|
+
*/
|
1448
|
+
#line 1214 "informix.ec"
|
1449
|
+
#line 1215 "informix.ec"
|
1450
|
+
char *did;
|
1451
|
+
/*
|
1452
|
+
* EXEC SQL end declare section;
|
1453
|
+
*/
|
1454
|
+
#line 1216 "informix.ec"
|
1455
|
+
|
1456
|
+
|
1457
|
+
Data_Get_Struct(self, char, did);
|
1458
|
+
|
1459
|
+
if (currentdid != did) {
|
1460
|
+
/*
|
1461
|
+
* EXEC SQL set connection :did;
|
1462
|
+
*/
|
1463
|
+
#line 1221 "informix.ec"
|
1464
|
+
{
|
1465
|
+
#line 1221 "informix.ec"
|
1466
|
+
sqli_connect_set(0, did, 0);
|
1467
|
+
#line 1221 "informix.ec"
|
1468
|
+
}
|
1469
|
+
if (SQLCODE < 0)
|
1470
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1471
|
+
currentdid = did;
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
/*
|
1475
|
+
* EXEC SQL rollback;
|
1476
|
+
*/
|
1477
|
+
#line 1227 "informix.ec"
|
1478
|
+
{
|
1479
|
+
#line 1227 "informix.ec"
|
1480
|
+
sqli_trans_rollback();
|
1481
|
+
#line 1227 "informix.ec"
|
1482
|
+
}
|
1483
|
+
return self;
|
1484
|
+
}
|
1485
|
+
|
1486
|
+
/*
|
1487
|
+
* call-seq:
|
1488
|
+
* db.commit => db
|
1489
|
+
*
|
1490
|
+
* Commits a transaction and returns __self__.
|
1491
|
+
*/
|
1492
|
+
static VALUE
|
1493
|
+
database_commit(VALUE self)
|
1494
|
+
{
|
1495
|
+
/*
|
1496
|
+
* EXEC SQL begin declare section;
|
1497
|
+
*/
|
1498
|
+
#line 1240 "informix.ec"
|
1499
|
+
#line 1241 "informix.ec"
|
1500
|
+
char *did;
|
1501
|
+
/*
|
1502
|
+
* EXEC SQL end declare section;
|
1503
|
+
*/
|
1504
|
+
#line 1242 "informix.ec"
|
1505
|
+
|
1506
|
+
|
1507
|
+
Data_Get_Struct(self, char, did);
|
1508
|
+
|
1509
|
+
if (currentdid != did) {
|
1510
|
+
/*
|
1511
|
+
* EXEC SQL set connection :did;
|
1512
|
+
*/
|
1513
|
+
#line 1247 "informix.ec"
|
1514
|
+
{
|
1515
|
+
#line 1247 "informix.ec"
|
1516
|
+
sqli_connect_set(0, did, 0);
|
1517
|
+
#line 1247 "informix.ec"
|
1518
|
+
}
|
1519
|
+
if (SQLCODE < 0)
|
1520
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1521
|
+
currentdid = did;
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
/*
|
1525
|
+
* EXEC SQL commit;
|
1526
|
+
*/
|
1527
|
+
#line 1253 "informix.ec"
|
1528
|
+
{
|
1529
|
+
#line 1253 "informix.ec"
|
1530
|
+
sqli_trans_commit();
|
1531
|
+
#line 1253 "informix.ec"
|
1532
|
+
}
|
1533
|
+
return self;
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
static VALUE
|
1537
|
+
database_transfail(VALUE self)
|
1538
|
+
{
|
1539
|
+
database_rollback(self);
|
1540
|
+
return Qundef;
|
1541
|
+
}
|
1542
|
+
|
1543
|
+
/*
|
1544
|
+
* call-seq:
|
1545
|
+
* db.transaction {|db| block } => db
|
1546
|
+
*
|
1547
|
+
* Opens a transaction and executes <i>block</i>, passing __self__ as parameter.
|
1548
|
+
* If an exception is raised, the transaction is rolled back. It is commited
|
1549
|
+
* otherwise.
|
1550
|
+
*
|
1551
|
+
* Returns __self__.
|
1552
|
+
*/
|
1553
|
+
static VALUE
|
1554
|
+
database_transaction(VALUE self)
|
1555
|
+
{
|
1556
|
+
VALUE ret;
|
1557
|
+
/*
|
1558
|
+
* EXEC SQL begin declare section;
|
1559
|
+
*/
|
1560
|
+
#line 1278 "informix.ec"
|
1561
|
+
#line 1279 "informix.ec"
|
1562
|
+
char *did;
|
1563
|
+
/*
|
1564
|
+
* EXEC SQL end declare section;
|
1565
|
+
*/
|
1566
|
+
#line 1280 "informix.ec"
|
1567
|
+
|
1568
|
+
|
1569
|
+
Data_Get_Struct(self, char, did);
|
1570
|
+
|
1571
|
+
if (currentdid != did) {
|
1572
|
+
/*
|
1573
|
+
* EXEC SQL set connection :did;
|
1574
|
+
*/
|
1575
|
+
#line 1285 "informix.ec"
|
1576
|
+
{
|
1577
|
+
#line 1285 "informix.ec"
|
1578
|
+
sqli_connect_set(0, did, 0);
|
1579
|
+
#line 1285 "informix.ec"
|
1580
|
+
}
|
1581
|
+
if (SQLCODE < 0)
|
1582
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1583
|
+
currentdid = did;
|
1584
|
+
}
|
1585
|
+
|
1586
|
+
/*
|
1587
|
+
* EXEC SQL commit;
|
1588
|
+
*/
|
1589
|
+
#line 1291 "informix.ec"
|
1590
|
+
{
|
1591
|
+
#line 1291 "informix.ec"
|
1592
|
+
sqli_trans_commit();
|
1593
|
+
#line 1291 "informix.ec"
|
1594
|
+
}
|
1595
|
+
|
1596
|
+
/*
|
1597
|
+
* EXEC SQL begin work;
|
1598
|
+
*/
|
1599
|
+
#line 1293 "informix.ec"
|
1600
|
+
{
|
1601
|
+
#line 1293 "informix.ec"
|
1602
|
+
sqli_trans_begin2((mint)1);
|
1603
|
+
#line 1293 "informix.ec"
|
1604
|
+
}
|
1605
|
+
ret = rb_rescue(rb_yield, self, database_transfail, self);
|
1606
|
+
if (ret == Qundef)
|
1607
|
+
rb_raise(rb_eRuntimeError, "Transaction rolled back");
|
1608
|
+
/*
|
1609
|
+
* EXEC SQL commit;
|
1610
|
+
*/
|
1611
|
+
#line 1297 "informix.ec"
|
1612
|
+
{
|
1613
|
+
#line 1297 "informix.ec"
|
1614
|
+
sqli_trans_commit();
|
1615
|
+
#line 1297 "informix.ec"
|
1616
|
+
}
|
1617
|
+
return self;
|
1618
|
+
}
|
1619
|
+
|
1620
|
+
/*
|
1621
|
+
* call-seq:
|
1622
|
+
* db.prepare(query) => statement
|
1623
|
+
*
|
1624
|
+
* Returns a <code>Statement</code> object based on <i>query</i>.
|
1625
|
+
* <i>query</i> may contain '?' placeholders for input parameters;
|
1626
|
+
* it must not be a query returning more than one row
|
1627
|
+
* (use <code>Database#cursor</code> instead.)
|
1628
|
+
*/
|
1629
|
+
static VALUE
|
1630
|
+
database_prepare(VALUE self, VALUE query)
|
1631
|
+
{
|
1632
|
+
VALUE argv[2];
|
1633
|
+
|
1634
|
+
argv[0] = self; argv[1] = query;
|
1635
|
+
return rb_class_new_instance(2, argv, rb_cStatement);
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
/*
|
1639
|
+
* call-seq:
|
1640
|
+
* db.cursor(query, options = nil) => cursor
|
1641
|
+
*
|
1642
|
+
* Returns a <code>Cursor</code> object based on <i>query</i>.
|
1643
|
+
* <i>query</i> may contain '?' placeholders for input parameters.
|
1644
|
+
*
|
1645
|
+
* <i>options</i> must be a hash with the following possible keys:
|
1646
|
+
*
|
1647
|
+
* :scroll => true or false
|
1648
|
+
* :hold => true or false
|
1649
|
+
*
|
1650
|
+
*/
|
1651
|
+
static VALUE
|
1652
|
+
database_cursor(int argc, VALUE *argv, VALUE self)
|
1653
|
+
{
|
1654
|
+
VALUE arg[3];
|
1655
|
+
|
1656
|
+
arg[0] = self;
|
1657
|
+
rb_scan_args(argc, argv, "11", &arg[1], &arg[2]);
|
1658
|
+
return rb_class_new_instance(3, arg, rb_cCursor);
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
/*
|
1662
|
+
* call-seq:
|
1663
|
+
* db.columns(tablename) => array
|
1664
|
+
*
|
1665
|
+
* Returns an array with information for every column of the given table.
|
1666
|
+
*/
|
1667
|
+
static VALUE
|
1668
|
+
database_columns(VALUE self, VALUE tablename)
|
1669
|
+
{
|
1670
|
+
VALUE v, column, result;
|
1671
|
+
char *stype;
|
1672
|
+
static char *stypes[] = {
|
1673
|
+
"CHAR", "SMALLINT", "INTEGER", "FLOAT", "SMALLFLOAT", "DECIMAL",
|
1674
|
+
"SERIAL", "DATE", "MONEY", "NULL", "DATETIME", "BYTE",
|
1675
|
+
"TEXT", "VARCHAR", "INTERVAL", "NCHAR", "NVARCHAR", "INT8",
|
1676
|
+
"SERIAL8", "SET", "MULTISET", "LIST", "UNNAMED ROW", "NAMED ROW",
|
1677
|
+
"VARIABLE-LENGTH OPAQUE TYPE"
|
1678
|
+
};
|
1679
|
+
|
1680
|
+
static char *qualifiers[] = {
|
1681
|
+
"YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND"
|
1682
|
+
};
|
1683
|
+
|
1684
|
+
/*
|
1685
|
+
* EXEC SQL begin declare section;
|
1686
|
+
*/
|
1687
|
+
#line 1365 "informix.ec"
|
1688
|
+
#line 1366 "informix.ec"
|
1689
|
+
char *did;
|
1690
|
+
char *tabname;
|
1691
|
+
int tabid, xid;
|
1692
|
+
char colname[129];
|
1693
|
+
short coltype, collength;
|
1694
|
+
char deftype[2];
|
1695
|
+
char defvalue[257];
|
1696
|
+
/*
|
1697
|
+
* EXEC SQL end declare section;
|
1698
|
+
*/
|
1699
|
+
#line 1373 "informix.ec"
|
1700
|
+
|
1701
|
+
|
1702
|
+
Data_Get_Struct(self, char, did);
|
1703
|
+
|
1704
|
+
if (currentdid != did) {
|
1705
|
+
/*
|
1706
|
+
* EXEC SQL set connection :did;
|
1707
|
+
*/
|
1708
|
+
#line 1378 "informix.ec"
|
1709
|
+
{
|
1710
|
+
#line 1378 "informix.ec"
|
1711
|
+
sqli_connect_set(0, did, 0);
|
1712
|
+
#line 1378 "informix.ec"
|
1713
|
+
}
|
1714
|
+
if (SQLCODE < 0)
|
1715
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1716
|
+
currentdid = did;
|
1717
|
+
}
|
1718
|
+
|
1719
|
+
tabname = StringValueCStr(tablename);
|
1720
|
+
|
1721
|
+
/*
|
1722
|
+
* EXEC SQL select tabid into :tabid from systables where tabname = :tabname;
|
1723
|
+
*/
|
1724
|
+
#line 1386 "informix.ec"
|
1725
|
+
{
|
1726
|
+
#line 1386 "informix.ec"
|
1727
|
+
static const char *sqlcmdtxt[] =
|
1728
|
+
#line 1386 "informix.ec"
|
1729
|
+
{
|
1730
|
+
#line 1386 "informix.ec"
|
1731
|
+
"select tabid from systables where tabname = ?",
|
1732
|
+
0
|
1733
|
+
};
|
1734
|
+
#line 1386 "informix.ec"
|
1735
|
+
static ifx_cursor_t _SQ0 = {0};
|
1736
|
+
static ifx_sqlvar_t _sqibind[] =
|
1737
|
+
{
|
1738
|
+
{ 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1739
|
+
#line 1386 "informix.ec"
|
1740
|
+
};
|
1741
|
+
static ifx_sqlvar_t _sqobind[] =
|
1742
|
+
{
|
1743
|
+
{ 102, sizeof(tabid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1744
|
+
#line 1386 "informix.ec"
|
1745
|
+
};
|
1746
|
+
#line 1386 "informix.ec"
|
1747
|
+
_sqibind[0].sqldata = tabname;
|
1748
|
+
#line 1386 "informix.ec"
|
1749
|
+
_sqobind[0].sqldata = (char *) &tabid;
|
1750
|
+
#line 1386 "informix.ec"
|
1751
|
+
sqli_slct(ESQLINTVERSION, &_SQ0,sqlcmdtxt,1,_sqibind,1,_sqobind,0,(ifx_literal_t *)0,(ifx_namelist_t *)0,0);
|
1752
|
+
#line 1386 "informix.ec"
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
if (SQLCODE == SQLNOTFOUND)
|
1756
|
+
rb_raise(rb_eRuntimeError, "Table '%s' doesn't exist", tabname);
|
1757
|
+
|
1758
|
+
result = rb_ary_new();
|
1759
|
+
|
1760
|
+
/*
|
1761
|
+
* EXEC SQL declare cur cursor for
|
1762
|
+
* select colname, coltype, collength, extended_id, type, default, c.colno
|
1763
|
+
* from syscolumns c, outer sysdefaults d
|
1764
|
+
* where c.tabid = :tabid and c.tabid = d.tabid and c.colno = d.colno
|
1765
|
+
* order by c.colno;
|
1766
|
+
*/
|
1767
|
+
#line 1393 "informix.ec"
|
1768
|
+
{
|
1769
|
+
#line 1397 "informix.ec"
|
1770
|
+
static const char *sqlcmdtxt[] =
|
1771
|
+
#line 1397 "informix.ec"
|
1772
|
+
{
|
1773
|
+
#line 1397 "informix.ec"
|
1774
|
+
"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",
|
1775
|
+
0
|
1776
|
+
};
|
1777
|
+
#line 1397 "informix.ec"
|
1778
|
+
static ifx_sqlvar_t _sqibind[] =
|
1779
|
+
{
|
1780
|
+
{ 102, sizeof(tabid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1781
|
+
#line 1397 "informix.ec"
|
1782
|
+
};
|
1783
|
+
static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
|
1784
|
+
#line 1397 "informix.ec"
|
1785
|
+
_sqibind[0].sqldata = (char *) &tabid;
|
1786
|
+
#line 1397 "informix.ec"
|
1787
|
+
sqli_curs_decl_stat(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 512), _Cn1, sqlcmdtxt, &_SD0, (ifx_sqlda_t *)0, 0, (ifx_literal_t *)0, (ifx_namelist_t *)0, 2, 0, 0);
|
1788
|
+
#line 1397 "informix.ec"
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
if (SQLCODE < 0)
|
1792
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1793
|
+
|
1794
|
+
/*
|
1795
|
+
* EXEC SQL open cur;
|
1796
|
+
*/
|
1797
|
+
#line 1402 "informix.ec"
|
1798
|
+
{
|
1799
|
+
#line 1402 "informix.ec"
|
1800
|
+
sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0, 0);
|
1801
|
+
#line 1402 "informix.ec"
|
1802
|
+
}
|
1803
|
+
if (SQLCODE < 0)
|
1804
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1805
|
+
|
1806
|
+
for(;;) {
|
1807
|
+
/*
|
1808
|
+
* EXEC SQL fetch cur into :colname, :coltype, :collength, :xid,
|
1809
|
+
* :deftype, :defvalue;
|
1810
|
+
*/
|
1811
|
+
#line 1407 "informix.ec"
|
1812
|
+
{
|
1813
|
+
#line 1408 "informix.ec"
|
1814
|
+
static ifx_sqlvar_t _sqobind[] =
|
1815
|
+
{
|
1816
|
+
{ 114, 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1817
|
+
{ 101, sizeof(coltype), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1818
|
+
{ 101, sizeof(collength), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1819
|
+
{ 102, sizeof(xid), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1820
|
+
{ 100, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1821
|
+
{ 114, 257, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
1822
|
+
#line 1408 "informix.ec"
|
1823
|
+
};
|
1824
|
+
static ifx_sqlda_t _SD0 = { 6, _sqobind, {0}, 6, 0 };
|
1825
|
+
static _FetchSpec _FS1 = { 0, 1, 0 };
|
1826
|
+
#line 1408 "informix.ec"
|
1827
|
+
_sqobind[0].sqldata = colname;
|
1828
|
+
#line 1408 "informix.ec"
|
1829
|
+
_sqobind[1].sqldata = (char *) &coltype;
|
1830
|
+
#line 1408 "informix.ec"
|
1831
|
+
_sqobind[2].sqldata = (char *) &collength;
|
1832
|
+
#line 1408 "informix.ec"
|
1833
|
+
_sqobind[3].sqldata = (char *) &xid;
|
1834
|
+
#line 1408 "informix.ec"
|
1835
|
+
_sqobind[4].sqldata = deftype;
|
1836
|
+
#line 1408 "informix.ec"
|
1837
|
+
_sqobind[5].sqldata = defvalue;
|
1838
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768), (ifx_sqlda_t *)0, &_SD0, (char *)0, &_FS1);
|
1839
|
+
#line 1408 "informix.ec"
|
1840
|
+
}
|
1841
|
+
if (SQLCODE < 0)
|
1842
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
1843
|
+
|
1844
|
+
if (SQLCODE == SQLNOTFOUND)
|
1845
|
+
break;
|
1846
|
+
|
1847
|
+
column = rb_hash_new();
|
1848
|
+
rb_hash_aset(column, sym_name, rb_str_new2(colname));
|
1849
|
+
rb_hash_aset(column, sym_type, INT2FIX(coltype));
|
1850
|
+
rb_hash_aset(column, sym_nullable, coltype&0x100? Qfalse: Qtrue);
|
1851
|
+
rb_hash_aset(column, sym_xid, INT2FIX(xid));
|
1852
|
+
|
1853
|
+
if ((coltype&0xFF) < 23) {
|
1854
|
+
stype = coltype == 4118? stypes[23]: stypes[coltype&0xFF];
|
1855
|
+
}
|
1856
|
+
else {
|
1857
|
+
stype = stypes[24];
|
1858
|
+
}
|
1859
|
+
rb_hash_aset(column, sym_stype, rb_str_new2(stype));
|
1860
|
+
rb_hash_aset(column, sym_length, INT2FIX(collength));
|
1861
|
+
|
1862
|
+
switch(coltype&0xFF) {
|
1863
|
+
case SQLVCHAR:
|
1864
|
+
case SQLNVCHAR:
|
1865
|
+
case SQLMONEY:
|
1866
|
+
case SQLDECIMAL:
|
1867
|
+
rb_hash_aset(column, sym_precision, INT2FIX(collength >> 8));
|
1868
|
+
rb_hash_aset(column, sym_scale, INT2FIX(collength&0xFF));
|
1869
|
+
break;
|
1870
|
+
case SQLDATE:
|
1871
|
+
case SQLDTIME:
|
1872
|
+
case SQLINTERVAL:
|
1873
|
+
rb_hash_aset(column, sym_length, INT2FIX(collength >> 8));
|
1874
|
+
rb_hash_aset(column, sym_precision, INT2FIX((collength&0xF0) >> 4));
|
1875
|
+
rb_hash_aset(column, sym_scale, INT2FIX(collength&0xF));
|
1876
|
+
break;
|
1877
|
+
default:
|
1878
|
+
rb_hash_aset(column, sym_precision, INT2FIX(0));
|
1879
|
+
rb_hash_aset(column, sym_scale, INT2FIX(0));
|
1880
|
+
}
|
1881
|
+
|
1882
|
+
if (!deftype[0]) {
|
1883
|
+
v = Qnil;
|
1884
|
+
}
|
1885
|
+
else {
|
1886
|
+
switch(deftype[0]) {
|
1887
|
+
case 'C': {
|
1888
|
+
char current[28];
|
1889
|
+
snprintf(current, sizeof(current), "CURRENT %s TO %s",
|
1890
|
+
qualifiers[(collength&0xF0) >> 5],
|
1891
|
+
qualifiers[(collength&0xF)>>1]);
|
1892
|
+
v = rb_str_new2(current);
|
1893
|
+
break;
|
1894
|
+
}
|
1895
|
+
case 'L':
|
1896
|
+
switch (coltype & 0xFF) {
|
1897
|
+
case SQLCHAR:
|
1898
|
+
case SQLNCHAR:
|
1899
|
+
case SQLVCHAR:
|
1900
|
+
case SQLNVCHAR:
|
1901
|
+
v = rb_str_new2(defvalue);
|
1902
|
+
break;
|
1903
|
+
default: {
|
1904
|
+
char *s = defvalue;
|
1905
|
+
while(*s++ != ' ');
|
1906
|
+
if ((coltype&0xFF) == SQLFLOAT ||
|
1907
|
+
(coltype&0xFF) == SQLSMFLOAT ||
|
1908
|
+
(coltype&0xFF) == SQLMONEY ||
|
1909
|
+
(coltype&0xFF) == SQLDECIMAL)
|
1910
|
+
v = rb_float_new(atof(s));
|
1911
|
+
else
|
1912
|
+
v = LONG2FIX(atol(s));
|
1913
|
+
}
|
1914
|
+
}
|
1915
|
+
break;
|
1916
|
+
case 'N':
|
1917
|
+
v = rb_str_new2("NULL");
|
1918
|
+
break;
|
1919
|
+
case 'T':
|
1920
|
+
v = rb_str_new2("today");
|
1921
|
+
break;
|
1922
|
+
case 'U':
|
1923
|
+
v = rb_str_new2("user");
|
1924
|
+
break;
|
1925
|
+
case 'S':
|
1926
|
+
default: /* XXX */
|
1927
|
+
v = Qnil;
|
1928
|
+
}
|
1929
|
+
}
|
1930
|
+
rb_hash_aset(column, sym_default, v);
|
1931
|
+
rb_ary_push(result, column);
|
1932
|
+
}
|
1933
|
+
|
1934
|
+
/*
|
1935
|
+
* EXEC SQL close cur;
|
1936
|
+
*/
|
1937
|
+
#line 1502 "informix.ec"
|
1938
|
+
{
|
1939
|
+
#line 1502 "informix.ec"
|
1940
|
+
sqli_curs_close(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768));
|
1941
|
+
#line 1502 "informix.ec"
|
1942
|
+
}
|
1943
|
+
/*
|
1944
|
+
* EXEC SQL free cur;
|
1945
|
+
*/
|
1946
|
+
#line 1503 "informix.ec"
|
1947
|
+
{
|
1948
|
+
#line 1503 "informix.ec"
|
1949
|
+
sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 770));
|
1950
|
+
#line 1503 "informix.ec"
|
1951
|
+
}
|
1952
|
+
|
1953
|
+
return result;
|
1954
|
+
}
|
1955
|
+
|
1956
|
+
/* class Statement ------------------------------------------------------- */
|
1957
|
+
|
1958
|
+
static void
|
1959
|
+
statement_mark(cursor_t *c)
|
1960
|
+
{
|
1961
|
+
rb_gc_mark(c->db);
|
1962
|
+
if (c->array)
|
1963
|
+
rb_gc_mark(c->array);
|
1964
|
+
if (c->hash)
|
1965
|
+
rb_gc_mark(c->hash);
|
1966
|
+
if (c->field_names)
|
1967
|
+
rb_gc_mark(c->field_names);
|
1968
|
+
}
|
1969
|
+
|
1970
|
+
static void
|
1971
|
+
statement_free(void *p)
|
1972
|
+
{
|
1973
|
+
/*
|
1974
|
+
* EXEC SQL begin declare section;
|
1975
|
+
*/
|
1976
|
+
#line 1525 "informix.ec"
|
1977
|
+
#line 1526 "informix.ec"
|
1978
|
+
char *sid, *did;
|
1979
|
+
/*
|
1980
|
+
* EXEC SQL end declare section;
|
1981
|
+
*/
|
1982
|
+
#line 1527 "informix.ec"
|
1983
|
+
|
1984
|
+
|
1985
|
+
free_input_slots(p);
|
1986
|
+
free_output_slots(p);
|
1987
|
+
|
1988
|
+
did = ((cursor_t *)p)->database_id;
|
1989
|
+
if (currentdid != did) {
|
1990
|
+
/*
|
1991
|
+
* EXEC SQL set connection :did;
|
1992
|
+
*/
|
1993
|
+
#line 1534 "informix.ec"
|
1994
|
+
{
|
1995
|
+
#line 1534 "informix.ec"
|
1996
|
+
sqli_connect_set(0, did, 0);
|
1997
|
+
#line 1534 "informix.ec"
|
1998
|
+
}
|
1999
|
+
if (SQLCODE < 0)
|
2000
|
+
goto exit;
|
2001
|
+
currentdid = did;
|
2002
|
+
}
|
2003
|
+
|
2004
|
+
sid = ((cursor_t *)p)->stmt_id;
|
2005
|
+
/*
|
2006
|
+
* EXEC SQL free :sid;
|
2007
|
+
*/
|
2008
|
+
#line 1541 "informix.ec"
|
2009
|
+
{
|
2010
|
+
#line 1541 "informix.ec"
|
2011
|
+
sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
|
2012
|
+
#line 1541 "informix.ec"
|
2013
|
+
}
|
2014
|
+
|
2015
|
+
exit:
|
2016
|
+
xfree(p);
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
static VALUE
|
2020
|
+
statement_alloc(VALUE klass)
|
2021
|
+
{
|
2022
|
+
cursor_t *c;
|
2023
|
+
|
2024
|
+
c = ALLOC(cursor_t);
|
2025
|
+
memset(c, 0, sizeof(cursor_t));
|
2026
|
+
return Data_Wrap_Struct(klass, statement_mark, statement_free, c);
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
/*
|
2030
|
+
* call-seq:
|
2031
|
+
* Statement.new(database, query) => statement
|
2032
|
+
*
|
2033
|
+
* Prepares <i>query</i> in the context of <i>database</i> and returns
|
2034
|
+
* a <code>Statement</code> object.
|
2035
|
+
*/
|
2036
|
+
static VALUE
|
2037
|
+
statement_initialize(VALUE self, VALUE db, VALUE query)
|
2038
|
+
{
|
2039
|
+
struct sqlda *output;
|
2040
|
+
cursor_t *c;
|
2041
|
+
/*
|
2042
|
+
* EXEC SQL begin declare section;
|
2043
|
+
*/
|
2044
|
+
#line 1569 "informix.ec"
|
2045
|
+
#line 1570 "informix.ec"
|
2046
|
+
char *c_query, *sid, *did;
|
2047
|
+
/*
|
2048
|
+
* EXEC SQL end declare section;
|
2049
|
+
*/
|
2050
|
+
#line 1571 "informix.ec"
|
2051
|
+
|
2052
|
+
|
2053
|
+
Data_Get_Struct(db, char, did);
|
2054
|
+
if (currentdid != did) {
|
2055
|
+
/*
|
2056
|
+
* EXEC SQL set connection :did;
|
2057
|
+
*/
|
2058
|
+
#line 1575 "informix.ec"
|
2059
|
+
{
|
2060
|
+
#line 1575 "informix.ec"
|
2061
|
+
sqli_connect_set(0, did, 0);
|
2062
|
+
#line 1575 "informix.ec"
|
2063
|
+
}
|
2064
|
+
if (SQLCODE < 0)
|
2065
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2066
|
+
currentdid = did;
|
2067
|
+
}
|
2068
|
+
|
2069
|
+
Data_Get_Struct(self, cursor_t, c);
|
2070
|
+
c->db = db;
|
2071
|
+
c->database_id = did;
|
2072
|
+
output = c->daOutput;
|
2073
|
+
snprintf(c->stmt_id, sizeof(c->stmt_id), "STMT%lX", self);
|
2074
|
+
sid = c->stmt_id;
|
2075
|
+
c_query = StringValueCStr(query);
|
2076
|
+
|
2077
|
+
/*
|
2078
|
+
* EXEC SQL prepare :sid from :c_query;
|
2079
|
+
*/
|
2080
|
+
#line 1589 "informix.ec"
|
2081
|
+
{
|
2082
|
+
#line 1589 "informix.ec"
|
2083
|
+
sqli_prep(ESQLINTVERSION, sid, c_query,(ifx_literal_t *)0, (ifx_namelist_t *)0, -1, 0, 0 );
|
2084
|
+
#line 1589 "informix.ec"
|
2085
|
+
}
|
2086
|
+
if (SQLCODE < 0)
|
2087
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2088
|
+
|
2089
|
+
alloc_input_slots(c, c_query);
|
2090
|
+
/*
|
2091
|
+
* EXEC SQL describe :sid into output;
|
2092
|
+
*/
|
2093
|
+
#line 1594 "informix.ec"
|
2094
|
+
{
|
2095
|
+
#line 1594 "informix.ec"
|
2096
|
+
sqli_describe_stmt(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), &output, 0);
|
2097
|
+
#line 1594 "informix.ec"
|
2098
|
+
}
|
2099
|
+
c->daOutput = output;
|
2100
|
+
|
2101
|
+
c->is_select = (SQLCODE == 0 || SQLCODE == SQ_EXECPROC);
|
2102
|
+
|
2103
|
+
if (c->is_select)
|
2104
|
+
alloc_output_slots(c);
|
2105
|
+
else {
|
2106
|
+
xfree(c->daOutput);
|
2107
|
+
c->daOutput = NULL;
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
return self;
|
2111
|
+
}
|
2112
|
+
|
2113
|
+
|
2114
|
+
/*
|
2115
|
+
* call-seq:
|
2116
|
+
* stmt[*params] => fixnum or hash
|
2117
|
+
*
|
2118
|
+
* Executes the previously prepared statement, binding <i>params</i> as
|
2119
|
+
* input parameters.
|
2120
|
+
*
|
2121
|
+
* Returns the record retrieved, in the case of a singleton select, or the
|
2122
|
+
* number of rows affected, in the case of any other statement.
|
2123
|
+
*/
|
2124
|
+
static VALUE
|
2125
|
+
statement_call(int argc, VALUE *argv, VALUE self)
|
2126
|
+
{
|
2127
|
+
struct sqlda *input, *output;
|
2128
|
+
cursor_t *c;
|
2129
|
+
/*
|
2130
|
+
* EXEC SQL begin declare section;
|
2131
|
+
*/
|
2132
|
+
#line 1625 "informix.ec"
|
2133
|
+
#line 1626 "informix.ec"
|
2134
|
+
char *sid, *did;
|
2135
|
+
/*
|
2136
|
+
* EXEC SQL end declare section;
|
2137
|
+
*/
|
2138
|
+
#line 1627 "informix.ec"
|
2139
|
+
|
2140
|
+
|
2141
|
+
Data_Get_Struct(self, cursor_t, c);
|
2142
|
+
|
2143
|
+
did = c->database_id;
|
2144
|
+
if (currentdid != did) {
|
2145
|
+
/*
|
2146
|
+
* EXEC SQL set connection :did;
|
2147
|
+
*/
|
2148
|
+
#line 1633 "informix.ec"
|
2149
|
+
{
|
2150
|
+
#line 1633 "informix.ec"
|
2151
|
+
sqli_connect_set(0, did, 0);
|
2152
|
+
#line 1633 "informix.ec"
|
2153
|
+
}
|
2154
|
+
if (SQLCODE < 0)
|
2155
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2156
|
+
currentdid = did;
|
2157
|
+
}
|
2158
|
+
|
2159
|
+
output = c->daOutput;
|
2160
|
+
input = &c->daInput;
|
2161
|
+
sid = c->stmt_id;
|
2162
|
+
|
2163
|
+
if (argc != input->sqld)
|
2164
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
2165
|
+
argc, input->sqld);
|
2166
|
+
|
2167
|
+
if (c->is_select) {
|
2168
|
+
if (argc) {
|
2169
|
+
bind_input_params(c, argv);
|
2170
|
+
/*
|
2171
|
+
* EXEC SQL execute :sid into descriptor output
|
2172
|
+
* using descriptor input;
|
2173
|
+
*/
|
2174
|
+
#line 1650 "informix.ec"
|
2175
|
+
{
|
2176
|
+
#line 1651 "informix.ec"
|
2177
|
+
sqli_exec(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), input, (char *)0, (struct value *)0, output, (char *)0, (struct value *)0, 0);
|
2178
|
+
#line 1651 "informix.ec"
|
2179
|
+
}
|
2180
|
+
clean_input_slots(c);
|
2181
|
+
}
|
2182
|
+
else
|
2183
|
+
/*
|
2184
|
+
* EXEC SQL execute :sid into descriptor output;
|
2185
|
+
*/
|
2186
|
+
#line 1655 "informix.ec"
|
2187
|
+
{
|
2188
|
+
#line 1655 "informix.ec"
|
2189
|
+
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);
|
2190
|
+
#line 1655 "informix.ec"
|
2191
|
+
}
|
2192
|
+
|
2193
|
+
if (SQLCODE < 0)
|
2194
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2195
|
+
|
2196
|
+
if (SQLCODE == SQLNOTFOUND)
|
2197
|
+
return Qnil;
|
2198
|
+
return make_result(c, rb_hash_new());
|
2199
|
+
}
|
2200
|
+
else {
|
2201
|
+
if (argc) {
|
2202
|
+
bind_input_params(c, argv);
|
2203
|
+
/*
|
2204
|
+
* EXEC SQL execute :sid using descriptor input;
|
2205
|
+
*/
|
2206
|
+
#line 1667 "informix.ec"
|
2207
|
+
{
|
2208
|
+
#line 1667 "informix.ec"
|
2209
|
+
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);
|
2210
|
+
#line 1667 "informix.ec"
|
2211
|
+
}
|
2212
|
+
clean_input_slots(c);
|
2213
|
+
}
|
2214
|
+
else
|
2215
|
+
/*
|
2216
|
+
* EXEC SQL execute :sid;
|
2217
|
+
*/
|
2218
|
+
#line 1671 "informix.ec"
|
2219
|
+
{
|
2220
|
+
#line 1671 "informix.ec"
|
2221
|
+
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);
|
2222
|
+
#line 1671 "informix.ec"
|
2223
|
+
}
|
2224
|
+
}
|
2225
|
+
if (SQLCODE < 0)
|
2226
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2227
|
+
|
2228
|
+
return INT2FIX(sqlca.sqlerrd[2]);
|
2229
|
+
}
|
2230
|
+
|
2231
|
+
/*
|
2232
|
+
* call-seq:
|
2233
|
+
* stmt.drop
|
2234
|
+
*
|
2235
|
+
* Frees the statement and the memory associated with it.
|
2236
|
+
*/
|
2237
|
+
static VALUE
|
2238
|
+
statement_drop(VALUE self)
|
2239
|
+
{
|
2240
|
+
cursor_t *c;
|
2241
|
+
/*
|
2242
|
+
* EXEC SQL begin declare section;
|
2243
|
+
*/
|
2244
|
+
#line 1689 "informix.ec"
|
2245
|
+
#line 1690 "informix.ec"
|
2246
|
+
char *sid, *did;
|
2247
|
+
/*
|
2248
|
+
* EXEC SQL end declare section;
|
2249
|
+
*/
|
2250
|
+
#line 1691 "informix.ec"
|
2251
|
+
|
2252
|
+
|
2253
|
+
Data_Get_Struct(self, cursor_t, c);
|
2254
|
+
free_input_slots(c);
|
2255
|
+
free_output_slots(c);
|
2256
|
+
|
2257
|
+
did = c->database_id;
|
2258
|
+
if (currentdid != did) {
|
2259
|
+
/*
|
2260
|
+
* EXEC SQL set connection :did;
|
2261
|
+
*/
|
2262
|
+
#line 1699 "informix.ec"
|
2263
|
+
{
|
2264
|
+
#line 1699 "informix.ec"
|
2265
|
+
sqli_connect_set(0, did, 0);
|
2266
|
+
#line 1699 "informix.ec"
|
2267
|
+
}
|
2268
|
+
if (SQLCODE < 0)
|
2269
|
+
return Qnil;
|
2270
|
+
currentdid = did;
|
2271
|
+
}
|
2272
|
+
sid = c->stmt_id;
|
2273
|
+
/*
|
2274
|
+
* EXEC SQL free :sid;
|
2275
|
+
*/
|
2276
|
+
#line 1705 "informix.ec"
|
2277
|
+
{
|
2278
|
+
#line 1705 "informix.ec"
|
2279
|
+
sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
|
2280
|
+
#line 1705 "informix.ec"
|
2281
|
+
}
|
2282
|
+
|
2283
|
+
return Qnil;
|
2284
|
+
}
|
2285
|
+
|
2286
|
+
|
2287
|
+
/* module SequentialCursor ----------------------------------------------- */
|
2288
|
+
|
2289
|
+
/* Decides whether to use an Array or a Hash, and instantiate a new
|
2290
|
+
* object or reuse an existing one.
|
2291
|
+
*/
|
2292
|
+
#define RECORD(c, type, bang, record) do {\
|
2293
|
+
if (type == T_ARRAY) {\
|
2294
|
+
if (bang) {\
|
2295
|
+
if (!c->array)\
|
2296
|
+
c->array = rb_ary_new2(c->daOutput->sqld);\
|
2297
|
+
record = c->array;\
|
2298
|
+
}\
|
2299
|
+
else\
|
2300
|
+
record = rb_ary_new2(c->daOutput->sqld);\
|
2301
|
+
}\
|
2302
|
+
else {\
|
2303
|
+
if (bang) {\
|
2304
|
+
if (!c->hash)\
|
2305
|
+
c->hash = rb_hash_new();\
|
2306
|
+
record = c->hash;\
|
2307
|
+
}\
|
2308
|
+
else\
|
2309
|
+
record = rb_hash_new();\
|
2310
|
+
}\
|
2311
|
+
}while(0)
|
2312
|
+
|
2313
|
+
/*
|
2314
|
+
* Base function for fetch* methods, except *_many
|
2315
|
+
*/
|
2316
|
+
static VALUE
|
2317
|
+
fetch(VALUE self, VALUE type, int bang)
|
2318
|
+
{
|
2319
|
+
/*
|
2320
|
+
* EXEC SQL begin declare section;
|
2321
|
+
*/
|
2322
|
+
#line 1743 "informix.ec"
|
2323
|
+
#line 1744 "informix.ec"
|
2324
|
+
char *cid, *did;
|
2325
|
+
/*
|
2326
|
+
* EXEC SQL end declare section;
|
2327
|
+
*/
|
2328
|
+
#line 1745 "informix.ec"
|
2329
|
+
|
2330
|
+
cursor_t *c;
|
2331
|
+
struct sqlda *output;
|
2332
|
+
VALUE record;
|
2333
|
+
|
2334
|
+
Data_Get_Struct(self, cursor_t, c);
|
2335
|
+
if (!c->is_open)
|
2336
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2337
|
+
|
2338
|
+
did = c->database_id;
|
2339
|
+
if (currentdid != did) {
|
2340
|
+
/*
|
2341
|
+
* EXEC SQL set connection :did;
|
2342
|
+
*/
|
2343
|
+
#line 1756 "informix.ec"
|
2344
|
+
{
|
2345
|
+
#line 1756 "informix.ec"
|
2346
|
+
sqli_connect_set(0, did, 0);
|
2347
|
+
#line 1756 "informix.ec"
|
2348
|
+
}
|
2349
|
+
if (SQLCODE < 0)
|
2350
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2351
|
+
currentdid = did;
|
2352
|
+
}
|
2353
|
+
|
2354
|
+
output = c->daOutput;
|
2355
|
+
cid = c->cursor_id;
|
2356
|
+
|
2357
|
+
/*
|
2358
|
+
* EXEC SQL fetch :cid using descriptor output;
|
2359
|
+
*/
|
2360
|
+
#line 1765 "informix.ec"
|
2361
|
+
{
|
2362
|
+
#line 1765 "informix.ec"
|
2363
|
+
static _FetchSpec _FS0 = { 0, 1, 0 };
|
2364
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
|
2365
|
+
#line 1765 "informix.ec"
|
2366
|
+
}
|
2367
|
+
if (SQLCODE < 0)
|
2368
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2369
|
+
|
2370
|
+
if (SQLCODE == SQLNOTFOUND)
|
2371
|
+
return Qnil;
|
2372
|
+
|
2373
|
+
RECORD(c, type, bang, record);
|
2374
|
+
return make_result(c, record);
|
2375
|
+
}
|
2376
|
+
|
2377
|
+
/*
|
2378
|
+
* call-seq:
|
2379
|
+
* cursor.fetch => array or nil
|
2380
|
+
*
|
2381
|
+
* Fetches the next record.
|
2382
|
+
*
|
2383
|
+
* Returns the record fetched as an array, or nil if there are no
|
2384
|
+
* records left.
|
2385
|
+
*/
|
2386
|
+
static VALUE
|
2387
|
+
seqcur_fetch(VALUE self)
|
2388
|
+
{
|
2389
|
+
return fetch(self, T_ARRAY, 0);
|
2390
|
+
}
|
2391
|
+
|
2392
|
+
/*
|
2393
|
+
* call-seq:
|
2394
|
+
* cursor.fetch! => array or nil
|
2395
|
+
*
|
2396
|
+
* Fetches the next record, storing it in the same Array object every time
|
2397
|
+
* it is called.
|
2398
|
+
*
|
2399
|
+
* Returns the record fetched as an array, or nil if there are no
|
2400
|
+
* records left.
|
2401
|
+
*/
|
2402
|
+
static VALUE
|
2403
|
+
seqcur_fetch_bang(VALUE self)
|
2404
|
+
{
|
2405
|
+
return fetch(self, T_ARRAY, 1);
|
2406
|
+
}
|
2407
|
+
|
2408
|
+
/*
|
2409
|
+
* call-seq:
|
2410
|
+
* cursor.fetch_hash => hash or nil
|
2411
|
+
*
|
2412
|
+
* Fetches the next record.
|
2413
|
+
*
|
2414
|
+
* Returns the record fetched as a hash, or nil if there are no
|
2415
|
+
* records left.
|
2416
|
+
*/
|
2417
|
+
static VALUE
|
2418
|
+
seqcur_fetch_hash(VALUE self)
|
2419
|
+
{
|
2420
|
+
return fetch(self, T_HASH, 0);
|
2421
|
+
}
|
2422
|
+
|
2423
|
+
/*
|
2424
|
+
* call-seq:
|
2425
|
+
* cursor.fetch_hash! => hash or nil
|
2426
|
+
*
|
2427
|
+
* Fetches the next record, storing it in the same Hash object every time
|
2428
|
+
* it is called.
|
2429
|
+
*
|
2430
|
+
* Returns the record fetched as a hash, or nil if there are no
|
2431
|
+
* records left.
|
2432
|
+
*/
|
2433
|
+
static VALUE
|
2434
|
+
seqcur_fetch_hash_bang(VALUE self)
|
2435
|
+
{
|
2436
|
+
return fetch(self, T_HASH, 1);
|
2437
|
+
}
|
2438
|
+
|
2439
|
+
/*
|
2440
|
+
* Base function for fetch*_many, fetch*_all and each_by methods
|
2441
|
+
*/
|
2442
|
+
static VALUE
|
2443
|
+
fetch_many(VALUE self, VALUE n, VALUE type)
|
2444
|
+
{
|
2445
|
+
/*
|
2446
|
+
* EXEC SQL begin declare section;
|
2447
|
+
*/
|
2448
|
+
#line 1844 "informix.ec"
|
2449
|
+
#line 1845 "informix.ec"
|
2450
|
+
char *cid, *did;
|
2451
|
+
/*
|
2452
|
+
* EXEC SQL end declare section;
|
2453
|
+
*/
|
2454
|
+
#line 1846 "informix.ec"
|
2455
|
+
|
2456
|
+
cursor_t *c;
|
2457
|
+
struct sqlda *output;
|
2458
|
+
VALUE record, records;
|
2459
|
+
register long i, max;
|
2460
|
+
register int all = n == Qnil;
|
2461
|
+
|
2462
|
+
Data_Get_Struct(self, cursor_t, c);
|
2463
|
+
if (!c->is_open)
|
2464
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2465
|
+
|
2466
|
+
did = c->database_id;
|
2467
|
+
if (currentdid != did) {
|
2468
|
+
/*
|
2469
|
+
* EXEC SQL set connection :did;
|
2470
|
+
*/
|
2471
|
+
#line 1859 "informix.ec"
|
2472
|
+
{
|
2473
|
+
#line 1859 "informix.ec"
|
2474
|
+
sqli_connect_set(0, did, 0);
|
2475
|
+
#line 1859 "informix.ec"
|
2476
|
+
}
|
2477
|
+
if (SQLCODE < 0)
|
2478
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2479
|
+
currentdid = did;
|
2480
|
+
}
|
2481
|
+
|
2482
|
+
output = c->daOutput;
|
2483
|
+
cid = c->cursor_id;
|
2484
|
+
|
2485
|
+
if (!all) {
|
2486
|
+
max = FIX2LONG(n);
|
2487
|
+
records = rb_ary_new2(max);
|
2488
|
+
}
|
2489
|
+
else {
|
2490
|
+
records = rb_ary_new();
|
2491
|
+
}
|
2492
|
+
|
2493
|
+
for(i = 0; all || i < max; i++) {
|
2494
|
+
/*
|
2495
|
+
* EXEC SQL fetch :cid using descriptor output;
|
2496
|
+
*/
|
2497
|
+
#line 1877 "informix.ec"
|
2498
|
+
{
|
2499
|
+
#line 1877 "informix.ec"
|
2500
|
+
static _FetchSpec _FS0 = { 0, 1, 0 };
|
2501
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
|
2502
|
+
#line 1877 "informix.ec"
|
2503
|
+
}
|
2504
|
+
if (SQLCODE < 0)
|
2505
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2506
|
+
|
2507
|
+
if (SQLCODE == SQLNOTFOUND)
|
2508
|
+
break;
|
2509
|
+
|
2510
|
+
if (type == T_ARRAY)
|
2511
|
+
record = rb_ary_new2(c->daOutput->sqld);
|
2512
|
+
else
|
2513
|
+
record = rb_hash_new();
|
2514
|
+
rb_ary_store(records, i, make_result(c, record));
|
2515
|
+
}
|
2516
|
+
|
2517
|
+
return records;
|
2518
|
+
}
|
2519
|
+
|
2520
|
+
/*
|
2521
|
+
* call-seq:
|
2522
|
+
* cursor.fetch_many(n) => array
|
2523
|
+
*
|
2524
|
+
* Reads at most <i>n</i> records.
|
2525
|
+
*
|
2526
|
+
* Returns the records read as an array of arrays
|
2527
|
+
*/
|
2528
|
+
static VALUE
|
2529
|
+
seqcur_fetch_many(VALUE self, VALUE n)
|
2530
|
+
{
|
2531
|
+
return fetch_many(self, n, T_ARRAY);
|
2532
|
+
}
|
2533
|
+
|
2534
|
+
/*
|
2535
|
+
* call-seq:
|
2536
|
+
* cursor.fetch_hash_many(n) => array
|
2537
|
+
*
|
2538
|
+
* Reads at most <i>n</i> records.
|
2539
|
+
* Returns the records read as an array of hashes.
|
2540
|
+
*/
|
2541
|
+
static VALUE
|
2542
|
+
seqcur_fetch_hash_many(VALUE self, VALUE n)
|
2543
|
+
{
|
2544
|
+
return fetch_many(self, n, T_HASH);
|
2545
|
+
}
|
2546
|
+
|
2547
|
+
/*
|
2548
|
+
* call-seq:
|
2549
|
+
* cursor.fetch_all => array
|
2550
|
+
*
|
2551
|
+
* Returns all the records left as an array of arrays
|
2552
|
+
*/
|
2553
|
+
static VALUE
|
2554
|
+
seqcur_fetch_all(VALUE self)
|
2555
|
+
{
|
2556
|
+
return fetch_many(self, Qnil, T_ARRAY);
|
2557
|
+
}
|
2558
|
+
|
2559
|
+
/*
|
2560
|
+
* call-seq:
|
2561
|
+
* cursor.fetch_hash_all => array
|
2562
|
+
*
|
2563
|
+
* Returns all the records left as an array of hashes
|
2564
|
+
*/
|
2565
|
+
static VALUE
|
2566
|
+
seqcur_fetch_hash_all(VALUE self)
|
2567
|
+
{
|
2568
|
+
return fetch_many(self, Qnil, T_HASH);
|
2569
|
+
}
|
2570
|
+
|
2571
|
+
/*
|
2572
|
+
* Base function for each* methods, except each*_by
|
2573
|
+
*/
|
2574
|
+
static VALUE
|
2575
|
+
each(VALUE self, VALUE type, int bang)
|
2576
|
+
{
|
2577
|
+
cursor_t *c;
|
2578
|
+
/*
|
2579
|
+
* EXEC SQL begin declare section;
|
2580
|
+
*/
|
2581
|
+
#line 1952 "informix.ec"
|
2582
|
+
#line 1953 "informix.ec"
|
2583
|
+
char *cid, *did;
|
2584
|
+
/*
|
2585
|
+
* EXEC SQL end declare section;
|
2586
|
+
*/
|
2587
|
+
#line 1954 "informix.ec"
|
2588
|
+
|
2589
|
+
struct sqlda *output;
|
2590
|
+
VALUE record;
|
2591
|
+
|
2592
|
+
Data_Get_Struct(self, cursor_t, c);
|
2593
|
+
if (!c->is_open)
|
2594
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2595
|
+
|
2596
|
+
did = c->database_id;
|
2597
|
+
if (currentdid != did) {
|
2598
|
+
/*
|
2599
|
+
* EXEC SQL set connection :did;
|
2600
|
+
*/
|
2601
|
+
#line 1964 "informix.ec"
|
2602
|
+
{
|
2603
|
+
#line 1964 "informix.ec"
|
2604
|
+
sqli_connect_set(0, did, 0);
|
2605
|
+
#line 1964 "informix.ec"
|
2606
|
+
}
|
2607
|
+
if (SQLCODE < 0)
|
2608
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2609
|
+
currentdid = did;
|
2610
|
+
}
|
2611
|
+
|
2612
|
+
output = c->daOutput;
|
2613
|
+
cid = c->cursor_id;
|
2614
|
+
|
2615
|
+
for(;;) {
|
2616
|
+
/*
|
2617
|
+
* EXEC SQL fetch :cid using descriptor output;
|
2618
|
+
*/
|
2619
|
+
#line 1974 "informix.ec"
|
2620
|
+
{
|
2621
|
+
#line 1974 "informix.ec"
|
2622
|
+
static _FetchSpec _FS0 = { 0, 1, 0 };
|
2623
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
|
2624
|
+
#line 1974 "informix.ec"
|
2625
|
+
}
|
2626
|
+
if (SQLCODE < 0)
|
2627
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2628
|
+
|
2629
|
+
if (SQLCODE == SQLNOTFOUND)
|
2630
|
+
return self;
|
2631
|
+
RECORD(c, type, bang, record);
|
2632
|
+
rb_yield(make_result(c, record));
|
2633
|
+
}
|
2634
|
+
}
|
2635
|
+
|
2636
|
+
/*
|
2637
|
+
* Base function for each*_by methods
|
2638
|
+
*/
|
2639
|
+
static VALUE
|
2640
|
+
each_by(VALUE self, VALUE n, VALUE type)
|
2641
|
+
{
|
2642
|
+
VALUE records;
|
2643
|
+
|
2644
|
+
for(;;) {
|
2645
|
+
records = fetch_many(self, n, type);
|
2646
|
+
if (RARRAY(records)->len == 0)
|
2647
|
+
return self;
|
2648
|
+
rb_yield(records);
|
2649
|
+
}
|
2650
|
+
}
|
2651
|
+
|
2652
|
+
/*
|
2653
|
+
* call-seq:
|
2654
|
+
* cursor.each {|record| block } => cursor
|
2655
|
+
*
|
2656
|
+
* Iterates over the remaining records, passing each <i>record</i> to the
|
2657
|
+
* <i>block</i> as an array.
|
2658
|
+
*
|
2659
|
+
* Returns __self__.
|
2660
|
+
*/
|
2661
|
+
static VALUE
|
2662
|
+
seqcur_each(VALUE self)
|
2663
|
+
{
|
2664
|
+
return each(self, T_ARRAY, 0);
|
2665
|
+
}
|
2666
|
+
|
2667
|
+
/*
|
2668
|
+
* call-seq:
|
2669
|
+
* cursor.each! {|record| block } => cursor
|
2670
|
+
*
|
2671
|
+
* Iterates over the remaining records, passing each <i>record</i> to the
|
2672
|
+
* <i>block</i> as an array. No new Array objects are created for each record.
|
2673
|
+
* The same Array object is reused in each call.
|
2674
|
+
*
|
2675
|
+
* Returns __self__.
|
2676
|
+
*/
|
2677
|
+
static VALUE
|
2678
|
+
seqcur_each_bang(VALUE self)
|
2679
|
+
{
|
2680
|
+
return each(self, T_ARRAY, 1);
|
2681
|
+
}
|
2682
|
+
|
2683
|
+
/*
|
2684
|
+
* call-seq:
|
2685
|
+
* cursor.each_hash {|record| block } => cursor
|
2686
|
+
*
|
2687
|
+
* Iterates over the remaining records, passing each <i>record</i> to the
|
2688
|
+
* <i>block</i> as a hash.
|
2689
|
+
*
|
2690
|
+
* Returns __self__.
|
2691
|
+
*/
|
2692
|
+
static VALUE
|
2693
|
+
seqcur_each_hash(VALUE self)
|
2694
|
+
{
|
2695
|
+
return each(self, T_HASH, 0);
|
2696
|
+
}
|
2697
|
+
|
2698
|
+
/*
|
2699
|
+
* call-seq:
|
2700
|
+
* cursor.each_hash! {|record| block } => cursor
|
2701
|
+
*
|
2702
|
+
* Iterates over the remaining records, passing each <i>record</i> to the
|
2703
|
+
* <i>block</i> as a hash. No new Hash objects are created for each record.
|
2704
|
+
* The same Hash object is reused in each call.
|
2705
|
+
*
|
2706
|
+
* Returns __self__.
|
2707
|
+
*/
|
2708
|
+
static VALUE
|
2709
|
+
seqcur_each_hash_bang(VALUE self)
|
2710
|
+
{
|
2711
|
+
return each(self, T_HASH, 1);
|
2712
|
+
}
|
2713
|
+
|
2714
|
+
/*
|
2715
|
+
* call-seq:
|
2716
|
+
* cursor.each_by(n) {|records| block } => cursor
|
2717
|
+
*
|
2718
|
+
* Iterates over the remaining records, passing at most <i>n</i> <i>records</i>
|
2719
|
+
* to the <i>block</i> as arrays.
|
2720
|
+
*
|
2721
|
+
* Returns __self__.
|
2722
|
+
*/
|
2723
|
+
static VALUE
|
2724
|
+
seqcur_each_by(VALUE self, VALUE n)
|
2725
|
+
{
|
2726
|
+
return each_by(self, n, T_ARRAY);
|
2727
|
+
}
|
2728
|
+
|
2729
|
+
/*
|
2730
|
+
* call-seq:
|
2731
|
+
* cursor.each_hash_by(n) {|records| block } => cursor
|
2732
|
+
*
|
2733
|
+
* Iterates over the remaining records, passing at most <i>n</i> <i>records</i>
|
2734
|
+
* to the <i>block</i> as hashes.
|
2735
|
+
*
|
2736
|
+
* Returns __self__.
|
2737
|
+
*/
|
2738
|
+
static VALUE
|
2739
|
+
seqcur_each_hash_by(VALUE self, VALUE n)
|
2740
|
+
{
|
2741
|
+
return each_by(self, n, T_HASH);
|
2742
|
+
}
|
2743
|
+
|
2744
|
+
/* module InsertCursor --------------------------------------------------- */
|
2745
|
+
|
2746
|
+
/*
|
2747
|
+
* call-seq:
|
2748
|
+
* cursor.put(*params)
|
2749
|
+
*
|
2750
|
+
* Binds <i>params</i> as input parameters and executes the insert statement.
|
2751
|
+
* The records are not written immediatly to disk, unless the insert buffer
|
2752
|
+
* is full, the <code>flush</code> method is called, the cursor is closed or
|
2753
|
+
* the transaction is commited.
|
2754
|
+
*/
|
2755
|
+
static VALUE
|
2756
|
+
inscur_put(int argc, VALUE *argv, VALUE self)
|
2757
|
+
{
|
2758
|
+
struct sqlda *input;
|
2759
|
+
cursor_t *c;
|
2760
|
+
/*
|
2761
|
+
* EXEC SQL begin declare section;
|
2762
|
+
*/
|
2763
|
+
#line 2109 "informix.ec"
|
2764
|
+
#line 2110 "informix.ec"
|
2765
|
+
char *cid, *did;
|
2766
|
+
/*
|
2767
|
+
* EXEC SQL end declare section;
|
2768
|
+
*/
|
2769
|
+
#line 2111 "informix.ec"
|
2770
|
+
|
2771
|
+
|
2772
|
+
Data_Get_Struct(self, cursor_t, c);
|
2773
|
+
if (!c->is_open)
|
2774
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2775
|
+
|
2776
|
+
did = c->database_id;
|
2777
|
+
if (currentdid != did) {
|
2778
|
+
/*
|
2779
|
+
* EXEC SQL set connection :did;
|
2780
|
+
*/
|
2781
|
+
#line 2119 "informix.ec"
|
2782
|
+
{
|
2783
|
+
#line 2119 "informix.ec"
|
2784
|
+
sqli_connect_set(0, did, 0);
|
2785
|
+
#line 2119 "informix.ec"
|
2786
|
+
}
|
2787
|
+
if (SQLCODE < 0)
|
2788
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2789
|
+
currentdid = did;
|
2790
|
+
}
|
2791
|
+
|
2792
|
+
input = &c->daInput;
|
2793
|
+
cid = c->cursor_id;
|
2794
|
+
|
2795
|
+
bind_input_params(c, argv);
|
2796
|
+
if (argc != input->sqld)
|
2797
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
2798
|
+
argc, input->sqld);
|
2799
|
+
|
2800
|
+
/*
|
2801
|
+
* EXEC SQL put :cid using descriptor input;
|
2802
|
+
*/
|
2803
|
+
#line 2133 "informix.ec"
|
2804
|
+
{
|
2805
|
+
#line 2133 "informix.ec"
|
2806
|
+
sqli_curs_put(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), input, (char *)0);
|
2807
|
+
#line 2133 "informix.ec"
|
2808
|
+
}
|
2809
|
+
clean_input_slots(c);
|
2810
|
+
if (SQLCODE < 0)
|
2811
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2812
|
+
|
2813
|
+
/* XXX 2-448, Guide to SQL: Sytax*/
|
2814
|
+
return INT2FIX(sqlca.sqlerrd[2]);
|
2815
|
+
}
|
2816
|
+
|
2817
|
+
/*
|
2818
|
+
* call-seq:
|
2819
|
+
* cursor.flush => cursor
|
2820
|
+
*
|
2821
|
+
* Flushes the insert buffer, writing data to disk.
|
2822
|
+
*
|
2823
|
+
* Returns __self__.
|
2824
|
+
*/
|
2825
|
+
static VALUE
|
2826
|
+
inscur_flush(VALUE self)
|
2827
|
+
{
|
2828
|
+
cursor_t *c;
|
2829
|
+
/*
|
2830
|
+
* EXEC SQL begin declare section;
|
2831
|
+
*/
|
2832
|
+
#line 2154 "informix.ec"
|
2833
|
+
#line 2155 "informix.ec"
|
2834
|
+
char *cid, *did;
|
2835
|
+
/*
|
2836
|
+
* EXEC SQL end declare section;
|
2837
|
+
*/
|
2838
|
+
#line 2156 "informix.ec"
|
2839
|
+
|
2840
|
+
|
2841
|
+
Data_Get_Struct(self, cursor_t, c);
|
2842
|
+
if (!c->is_open)
|
2843
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2844
|
+
|
2845
|
+
did = c->database_id;
|
2846
|
+
if (currentdid != did) {
|
2847
|
+
/*
|
2848
|
+
* EXEC SQL set connection :did;
|
2849
|
+
*/
|
2850
|
+
#line 2164 "informix.ec"
|
2851
|
+
{
|
2852
|
+
#line 2164 "informix.ec"
|
2853
|
+
sqli_connect_set(0, did, 0);
|
2854
|
+
#line 2164 "informix.ec"
|
2855
|
+
}
|
2856
|
+
if (SQLCODE < 0)
|
2857
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2858
|
+
currentdid = did;
|
2859
|
+
}
|
2860
|
+
|
2861
|
+
cid = c->cursor_id;
|
2862
|
+
/*
|
2863
|
+
* EXEC SQL flush :cid;
|
2864
|
+
*/
|
2865
|
+
#line 2171 "informix.ec"
|
2866
|
+
{
|
2867
|
+
#line 2171 "informix.ec"
|
2868
|
+
sqli_curs_flush(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256));
|
2869
|
+
#line 2171 "informix.ec"
|
2870
|
+
}
|
2871
|
+
return self;
|
2872
|
+
}
|
2873
|
+
|
2874
|
+
/* module ScrollCursor --------------------------------------------------- */
|
2875
|
+
|
2876
|
+
/*
|
2877
|
+
* Provides the Array-like functionality for scroll cursors when using the
|
2878
|
+
* cursor[index] syntax
|
2879
|
+
*/
|
2880
|
+
static VALUE
|
2881
|
+
scrollcur_entry(VALUE self, VALUE index, VALUE type, int bang)
|
2882
|
+
{
|
2883
|
+
cursor_t *c;
|
2884
|
+
struct sqlda *output;
|
2885
|
+
VALUE record;
|
2886
|
+
/*
|
2887
|
+
* EXEC SQL begin declare section;
|
2888
|
+
*/
|
2889
|
+
#line 2187 "informix.ec"
|
2890
|
+
#line 2188 "informix.ec"
|
2891
|
+
char *cid, *did;
|
2892
|
+
long pos;
|
2893
|
+
/*
|
2894
|
+
* EXEC SQL end declare section;
|
2895
|
+
*/
|
2896
|
+
#line 2190 "informix.ec"
|
2897
|
+
|
2898
|
+
|
2899
|
+
Data_Get_Struct(self, cursor_t, c);
|
2900
|
+
if (!c->is_open)
|
2901
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
2902
|
+
|
2903
|
+
did = c->database_id;
|
2904
|
+
if (currentdid != did) {
|
2905
|
+
/*
|
2906
|
+
* EXEC SQL set connection :did;
|
2907
|
+
*/
|
2908
|
+
#line 2198 "informix.ec"
|
2909
|
+
{
|
2910
|
+
#line 2198 "informix.ec"
|
2911
|
+
sqli_connect_set(0, did, 0);
|
2912
|
+
#line 2198 "informix.ec"
|
2913
|
+
}
|
2914
|
+
if (SQLCODE < 0)
|
2915
|
+
return Qnil;
|
2916
|
+
currentdid = did;
|
2917
|
+
}
|
2918
|
+
|
2919
|
+
output = c->daOutput;
|
2920
|
+
cid = c->cursor_id;
|
2921
|
+
|
2922
|
+
if (NIL_P(index))
|
2923
|
+
/*
|
2924
|
+
* EXEC SQL fetch current :cid using descriptor output;
|
2925
|
+
*/
|
2926
|
+
#line 2208 "informix.ec"
|
2927
|
+
{
|
2928
|
+
#line 2208 "informix.ec"
|
2929
|
+
static _FetchSpec _FS0 = { 0, 5, 0 };
|
2930
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, output, (char *)0, &_FS0);
|
2931
|
+
#line 2208 "informix.ec"
|
2932
|
+
}
|
2933
|
+
else if ((pos = NUM2LONG(index) + 1) > 0)
|
2934
|
+
/*
|
2935
|
+
* EXEC SQL fetch absolute :pos :cid using descriptor output;
|
2936
|
+
*/
|
2937
|
+
#line 2210 "informix.ec"
|
2938
|
+
{
|
2939
|
+
#line 2210 "informix.ec"
|
2940
|
+
static ifx_sqlvar_t _sqibind[] =
|
2941
|
+
{
|
2942
|
+
{ 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
2943
|
+
#line 2210 "informix.ec"
|
2944
|
+
};
|
2945
|
+
static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
|
2946
|
+
static _FetchSpec _FS1 = { 0, 6, 0 };
|
2947
|
+
#line 2210 "informix.ec"
|
2948
|
+
_sqibind[0].sqldata = (char *) &pos;
|
2949
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
|
2950
|
+
#line 2210 "informix.ec"
|
2951
|
+
}
|
2952
|
+
else {
|
2953
|
+
/*
|
2954
|
+
* EXEC SQL fetch last :cid;
|
2955
|
+
*/
|
2956
|
+
#line 2212 "informix.ec"
|
2957
|
+
{
|
2958
|
+
#line 2212 "informix.ec"
|
2959
|
+
static _FetchSpec _FS0 = { 0, 4, 0 };
|
2960
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (ifx_sqlda_t *)0, (char *)0, &_FS0);
|
2961
|
+
#line 2212 "informix.ec"
|
2962
|
+
}
|
2963
|
+
/*
|
2964
|
+
* EXEC SQL fetch relative :pos :cid using descriptor output;
|
2965
|
+
*/
|
2966
|
+
#line 2213 "informix.ec"
|
2967
|
+
{
|
2968
|
+
#line 2213 "informix.ec"
|
2969
|
+
static ifx_sqlvar_t _sqibind[] =
|
2970
|
+
{
|
2971
|
+
{ 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
2972
|
+
#line 2213 "informix.ec"
|
2973
|
+
};
|
2974
|
+
static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
|
2975
|
+
static _FetchSpec _FS1 = { 0, 7, 0 };
|
2976
|
+
#line 2213 "informix.ec"
|
2977
|
+
_sqibind[0].sqldata = (char *) &pos;
|
2978
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
|
2979
|
+
#line 2213 "informix.ec"
|
2980
|
+
}
|
2981
|
+
}
|
2982
|
+
|
2983
|
+
if (SQLCODE == SQLNOTFOUND)
|
2984
|
+
return Qnil;
|
2985
|
+
|
2986
|
+
if (SQLCODE < 0)
|
2987
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
2988
|
+
|
2989
|
+
RECORD(c, type, bang, record);
|
2990
|
+
return make_result(c, record);
|
2991
|
+
}
|
2992
|
+
|
2993
|
+
/*
|
2994
|
+
* Provides the Array-like functionality for scroll cursors when using the
|
2995
|
+
* cursor[start, length] syntax
|
2996
|
+
*/
|
2997
|
+
static VALUE
|
2998
|
+
scrollcur_subseq(VALUE self, VALUE start, VALUE length, VALUE type)
|
2999
|
+
{
|
3000
|
+
cursor_t *c;
|
3001
|
+
struct sqlda *output;
|
3002
|
+
VALUE first, records;
|
3003
|
+
/*
|
3004
|
+
* EXEC SQL begin declare section;
|
3005
|
+
*/
|
3006
|
+
#line 2236 "informix.ec"
|
3007
|
+
#line 2237 "informix.ec"
|
3008
|
+
char *cid, *did;
|
3009
|
+
long pos;
|
3010
|
+
/*
|
3011
|
+
* EXEC SQL end declare section;
|
3012
|
+
*/
|
3013
|
+
#line 2239 "informix.ec"
|
3014
|
+
|
3015
|
+
|
3016
|
+
first = scrollcur_entry(self, start, type, 0);
|
3017
|
+
if (NIL_P(first))
|
3018
|
+
return Qnil;
|
3019
|
+
|
3020
|
+
pos = NUM2LONG(length) - 1;
|
3021
|
+
|
3022
|
+
if (pos > 0) {
|
3023
|
+
length = LONG2NUM(pos);
|
3024
|
+
records = fetch_many(self, length, type);
|
3025
|
+
}
|
3026
|
+
else
|
3027
|
+
records = rb_ary_new();
|
3028
|
+
|
3029
|
+
rb_ary_unshift(records, first);
|
3030
|
+
|
3031
|
+
return records;
|
3032
|
+
}
|
3033
|
+
|
3034
|
+
/*
|
3035
|
+
* Base function for slice and slice_hash methods
|
3036
|
+
*/
|
3037
|
+
static VALUE
|
3038
|
+
slice(int argc, VALUE *argv, VALUE self, VALUE type)
|
3039
|
+
{
|
3040
|
+
if (argc == 2) {
|
3041
|
+
if (NUM2LONG(argv[1]) <= 0)
|
3042
|
+
rb_raise(rb_eArgError, "length must be positive");
|
3043
|
+
return scrollcur_subseq(self, argv[0], argv[1], type);
|
3044
|
+
}
|
3045
|
+
if (argc != 1)
|
3046
|
+
rb_scan_args(argc, argv, "11", 0, 0);
|
3047
|
+
|
3048
|
+
return scrollcur_entry(self, argv[0], type, 0);
|
3049
|
+
}
|
3050
|
+
|
3051
|
+
/*
|
3052
|
+
* call-seq:
|
3053
|
+
* cursor[index] => array or nil
|
3054
|
+
* cursor[start, length] => array or nil
|
3055
|
+
* cursor.slice(index) => array or nil
|
3056
|
+
* cursor.slice(start, length) => array or nil
|
3057
|
+
*
|
3058
|
+
* Returns the record at _index_, or returns a subarray starting at _start_
|
3059
|
+
* and continuing for _length_ records. Negative indices count backward from
|
3060
|
+
* the end of the cursor (-1 is the last element). Returns nil if the
|
3061
|
+
* (starting) index is out of range.
|
3062
|
+
*
|
3063
|
+
* <b>Warning</b>: if the (starting) index is negative and out of range, the
|
3064
|
+
* position in the cursor is set to the last record. Otherwise the current
|
3065
|
+
* position in the cursor is preserved.
|
3066
|
+
*/
|
3067
|
+
static VALUE
|
3068
|
+
scrollcur_slice(int argc, VALUE *argv, VALUE self)
|
3069
|
+
{
|
3070
|
+
return slice(argc, argv, self, T_ARRAY);
|
3071
|
+
}
|
3072
|
+
|
3073
|
+
/*
|
3074
|
+
* call-seq:
|
3075
|
+
* cursor.slice!(index) => array or nil
|
3076
|
+
*
|
3077
|
+
* Returns the record at _index_. Negative indices count backward from
|
3078
|
+
* the end of the cursor (-1 is the last element). Returns nil if the index
|
3079
|
+
* is out of range.
|
3080
|
+
*
|
3081
|
+
* Stores the record fetched always in the same Array object.
|
3082
|
+
*
|
3083
|
+
* <b>Warning</b>: if the index is negative and out of range, the
|
3084
|
+
* position in the cursor is set to the last record. Otherwise the current
|
3085
|
+
* position in the cursor is preserved.
|
3086
|
+
*/
|
3087
|
+
static VALUE
|
3088
|
+
scrollcur_slice_bang(VALUE self, VALUE index)
|
3089
|
+
{
|
3090
|
+
return scrollcur_entry(self, index, T_ARRAY, 1);
|
3091
|
+
}
|
3092
|
+
|
3093
|
+
/*
|
3094
|
+
* call-seq:
|
3095
|
+
* cursor.slice_hash(index) => hash or nil
|
3096
|
+
* cursor.slice_hash(start, length) => array or nil
|
3097
|
+
*
|
3098
|
+
* Returns the record at _index_, or returns a subarray starting at _start_
|
3099
|
+
* and continuing for _length_ records. Negative indices count backward from
|
3100
|
+
* the end of the cursor (-1 is the last element). Returns nil if the
|
3101
|
+
* (starting) index is out of range.
|
3102
|
+
*
|
3103
|
+
* <b>Warning</b>: if the (starting) index is negative and out of range, the
|
3104
|
+
* position in the cursor is set to the last record. Otherwise the current
|
3105
|
+
* position in the cursor is preserved.
|
3106
|
+
*/
|
3107
|
+
static VALUE
|
3108
|
+
scrollcur_slice_hash(int argc, VALUE *argv, VALUE self)
|
3109
|
+
{
|
3110
|
+
return slice(argc, argv, self, T_HASH);
|
3111
|
+
}
|
3112
|
+
|
3113
|
+
/*
|
3114
|
+
* call-seq:
|
3115
|
+
* cursor.slice_hash!(index) => hash or nil
|
3116
|
+
*
|
3117
|
+
* Returns the record at _index_. Negative indices count backward from
|
3118
|
+
* the end of the cursor (-1 is the last element). Returns nil if the index
|
3119
|
+
* is out of range.
|
3120
|
+
*
|
3121
|
+
* Stores the record fetched always in the same Hash object.
|
3122
|
+
*
|
3123
|
+
* <b>Warning</b>: if the index is negative and out of range, the
|
3124
|
+
* position in the cursor is set to the last record. Otherwise the current
|
3125
|
+
* position in the cursor is preserved.
|
3126
|
+
*/
|
3127
|
+
static VALUE
|
3128
|
+
scrollcur_slice_hash_bang(VALUE self, VALUE index)
|
3129
|
+
{
|
3130
|
+
return scrollcur_entry(self, index, T_HASH, 1);
|
3131
|
+
}
|
3132
|
+
|
3133
|
+
/*
|
3134
|
+
* Base function for prev* and next* methods
|
3135
|
+
*/
|
3136
|
+
static VALUE
|
3137
|
+
scrollcur_rel(int argc, VALUE *argv, VALUE self, int dir, VALUE type, int bang)
|
3138
|
+
{
|
3139
|
+
cursor_t *c;
|
3140
|
+
struct sqlda *output;
|
3141
|
+
VALUE offset, record;
|
3142
|
+
/*
|
3143
|
+
* EXEC SQL begin declare section;
|
3144
|
+
*/
|
3145
|
+
#line 2367 "informix.ec"
|
3146
|
+
#line 2368 "informix.ec"
|
3147
|
+
char *cid, *did;
|
3148
|
+
long pos;
|
3149
|
+
/*
|
3150
|
+
* EXEC SQL end declare section;
|
3151
|
+
*/
|
3152
|
+
#line 2370 "informix.ec"
|
3153
|
+
|
3154
|
+
|
3155
|
+
Data_Get_Struct(self, cursor_t, c);
|
3156
|
+
if (!c->is_open)
|
3157
|
+
rb_raise(rb_eRuntimeError, "Open the cursor object first");
|
3158
|
+
|
3159
|
+
did = c->database_id;
|
3160
|
+
if (currentdid != did) {
|
3161
|
+
/*
|
3162
|
+
* EXEC SQL set connection :did;
|
3163
|
+
*/
|
3164
|
+
#line 2378 "informix.ec"
|
3165
|
+
{
|
3166
|
+
#line 2378 "informix.ec"
|
3167
|
+
sqli_connect_set(0, did, 0);
|
3168
|
+
#line 2378 "informix.ec"
|
3169
|
+
}
|
3170
|
+
if (SQLCODE < 0)
|
3171
|
+
return Qnil;
|
3172
|
+
currentdid = did;
|
3173
|
+
}
|
3174
|
+
|
3175
|
+
rb_scan_args(argc, argv, "01", &offset);
|
3176
|
+
pos = dir*(NIL_P(offset)? 1: NUM2LONG(offset));
|
3177
|
+
|
3178
|
+
output = c->daOutput;
|
3179
|
+
cid = c->cursor_id;
|
3180
|
+
/*
|
3181
|
+
* EXEC SQL fetch relative :pos :cid using descriptor output;
|
3182
|
+
*/
|
3183
|
+
#line 2389 "informix.ec"
|
3184
|
+
{
|
3185
|
+
#line 2389 "informix.ec"
|
3186
|
+
static ifx_sqlvar_t _sqibind[] =
|
3187
|
+
{
|
3188
|
+
{ 103, sizeof(pos), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
3189
|
+
#line 2389 "informix.ec"
|
3190
|
+
};
|
3191
|
+
static ifx_sqlda_t _SD0 = { 1, _sqibind, {0}, 1, 0 };
|
3192
|
+
static _FetchSpec _FS1 = { 0, 7, 0 };
|
3193
|
+
#line 2389 "informix.ec"
|
3194
|
+
_sqibind[0].sqldata = (char *) &pos;
|
3195
|
+
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), &_SD0, output, (char *)0, &_FS1);
|
3196
|
+
#line 2389 "informix.ec"
|
3197
|
+
}
|
3198
|
+
|
3199
|
+
if (SQLCODE == SQLNOTFOUND)
|
3200
|
+
return Qnil;
|
3201
|
+
|
3202
|
+
if (SQLCODE < 0)
|
3203
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3204
|
+
|
3205
|
+
RECORD(c, type, bang, record);
|
3206
|
+
return make_result(c, record);
|
3207
|
+
}
|
3208
|
+
|
3209
|
+
/* call-seq:
|
3210
|
+
* cursor.prev(offset = 1) => array or nil
|
3211
|
+
*
|
3212
|
+
* Returns the previous _offset_ th record. Negative indices count
|
3213
|
+
* forward from the current position. Returns nil if the _offset_ is out of
|
3214
|
+
* range.
|
3215
|
+
*/
|
3216
|
+
static VALUE
|
3217
|
+
scrollcur_prev(int argc, VALUE *argv, VALUE self)
|
3218
|
+
{
|
3219
|
+
return scrollcur_rel(argc, argv, self, -1, T_ARRAY, 0);
|
3220
|
+
}
|
3221
|
+
|
3222
|
+
/* call-seq:
|
3223
|
+
* cursor.prev!(offset = 1) => array or nil
|
3224
|
+
*
|
3225
|
+
* Returns the previous _offset_ th record. Negative indices count
|
3226
|
+
* forward from the current position. Returns nil if the _offset_ is out of
|
3227
|
+
* range.
|
3228
|
+
*
|
3229
|
+
* Stores the record fetched always in the same Array object.
|
3230
|
+
*/
|
3231
|
+
static VALUE
|
3232
|
+
scrollcur_prev_bang(int argc, VALUE *argv, VALUE self)
|
3233
|
+
{
|
3234
|
+
return scrollcur_rel(argc, argv, self, -1, T_ARRAY, 1);
|
3235
|
+
}
|
3236
|
+
|
3237
|
+
/* call-seq:
|
3238
|
+
* cursor.prev_hash(offset = 1) => hash or nil
|
3239
|
+
*
|
3240
|
+
* Returns the previous _offset_ th record. Negative indices count
|
3241
|
+
* forward from the current position. Returns nil if the _offset_ is out of
|
3242
|
+
* range.
|
3243
|
+
*/
|
3244
|
+
static VALUE
|
3245
|
+
scrollcur_prev_hash(int argc, VALUE *argv, VALUE self)
|
3246
|
+
{
|
3247
|
+
return scrollcur_rel(argc, argv, self, -1, T_HASH, 0);
|
3248
|
+
}
|
3249
|
+
|
3250
|
+
/* call-seq:
|
3251
|
+
* cursor.prev_hash!(offset = 1) => hash or nil
|
3252
|
+
*
|
3253
|
+
* Returns the previous _offset_ th record. Negative indices count
|
3254
|
+
* forward from the current position. Returns nil if the _offset_ is out of
|
3255
|
+
* range.
|
3256
|
+
*
|
3257
|
+
* Stores the record fetched always in the same Hash object.
|
3258
|
+
*/
|
3259
|
+
static VALUE
|
3260
|
+
scrollcur_prev_hash_bang(int argc, VALUE *argv, VALUE self)
|
3261
|
+
{
|
3262
|
+
return scrollcur_rel(argc, argv, self, -1, T_HASH, 1);
|
3263
|
+
}
|
3264
|
+
|
3265
|
+
/* call-seq:
|
3266
|
+
* cursor.next(offset = 1) => array or nil
|
3267
|
+
*
|
3268
|
+
* Returns the next _offset_ th record. Negative indices count
|
3269
|
+
* backward from the current position. Returns nil if the _offset_ is out of
|
3270
|
+
* range.
|
3271
|
+
*/
|
3272
|
+
static VALUE
|
3273
|
+
scrollcur_next(int argc, VALUE *argv, VALUE self)
|
3274
|
+
{
|
3275
|
+
return scrollcur_rel(argc, argv, self, 1, T_ARRAY, 0);
|
3276
|
+
}
|
3277
|
+
|
3278
|
+
/* call-seq:
|
3279
|
+
* cursor.next!(offset = 1) => array or nil
|
3280
|
+
*
|
3281
|
+
* Returns the next _offset_ th record. Negative indices count
|
3282
|
+
* backward from the current position. Returns nil if the _offset_ is out of
|
3283
|
+
* range.
|
3284
|
+
*
|
3285
|
+
* Stores the record fetched always in the same Array object.
|
3286
|
+
*/
|
3287
|
+
static VALUE
|
3288
|
+
scrollcur_next_bang(int argc, VALUE *argv, VALUE self)
|
3289
|
+
{
|
3290
|
+
return scrollcur_rel(argc, argv, self, 1, T_ARRAY, 1);
|
3291
|
+
}
|
3292
|
+
|
3293
|
+
/* call-seq:
|
3294
|
+
* cursor.next_hash(offset = 1) => hash or nil
|
3295
|
+
*
|
3296
|
+
* Returns the next _offset_ th record. Negative indices count
|
3297
|
+
* backward from the current position. Returns nil if the _offset_ is out of
|
3298
|
+
* range.
|
3299
|
+
*/
|
3300
|
+
static VALUE
|
3301
|
+
scrollcur_next_hash(int argc, VALUE *argv, VALUE self)
|
3302
|
+
{
|
3303
|
+
return scrollcur_rel(argc, argv, self, 1, T_HASH, 0);
|
3304
|
+
}
|
3305
|
+
|
3306
|
+
/* call-seq:
|
3307
|
+
* cursor.next_hash!(offset = 1) => hash or nil
|
3308
|
+
*
|
3309
|
+
* Returns the next _offset_ th record. Negative indices count
|
3310
|
+
* backward from the current position. Returns nil if the _offset_ is out of
|
3311
|
+
* range.
|
3312
|
+
*
|
3313
|
+
* Stores the record fetched always in the same Hash object.
|
3314
|
+
*/
|
3315
|
+
static VALUE
|
3316
|
+
scrollcur_next_hash_bang(int argc, VALUE *argv, VALUE self)
|
3317
|
+
{
|
3318
|
+
return scrollcur_rel(argc, argv, self, 1, T_HASH, 1);
|
3319
|
+
}
|
3320
|
+
|
3321
|
+
/*
|
3322
|
+
* call-seq:
|
3323
|
+
* cursor.first => array or nil
|
3324
|
+
*
|
3325
|
+
* Returns the first record of the cursor. If the cursor is empty,
|
3326
|
+
* returns nil.
|
3327
|
+
*/
|
3328
|
+
static VALUE
|
3329
|
+
scrollcur_first(VALUE self)
|
3330
|
+
{
|
3331
|
+
return scrollcur_entry(self, INT2FIX(0), T_ARRAY, 0);
|
3332
|
+
}
|
3333
|
+
|
3334
|
+
/*
|
3335
|
+
* call-seq:
|
3336
|
+
* cursor.first! => array or nil
|
3337
|
+
*
|
3338
|
+
* Returns the first record of the cursor. If the cursor is empty,
|
3339
|
+
* returns nil.
|
3340
|
+
*
|
3341
|
+
* Stores the record fetched always in the same Array object.
|
3342
|
+
*/
|
3343
|
+
static VALUE
|
3344
|
+
scrollcur_first_bang(VALUE self)
|
3345
|
+
{
|
3346
|
+
return scrollcur_entry(self, INT2FIX(0), T_ARRAY, 1);
|
3347
|
+
}
|
3348
|
+
|
3349
|
+
/*
|
3350
|
+
* call-seq:
|
3351
|
+
* cursor.first_hash => hash or nil
|
3352
|
+
*
|
3353
|
+
* Returns the first record of the cursor. If the cursor is empty,
|
3354
|
+
* returns nil.
|
3355
|
+
*/
|
3356
|
+
static VALUE
|
3357
|
+
scrollcur_first_hash(VALUE self)
|
3358
|
+
{
|
3359
|
+
return scrollcur_entry(self, INT2FIX(0), T_HASH, 0);
|
3360
|
+
}
|
3361
|
+
|
3362
|
+
/*
|
3363
|
+
* call-seq:
|
3364
|
+
* cursor.first_hash! => hash or nil
|
3365
|
+
*
|
3366
|
+
* Returns the first record of the cursor. If the cursor is empty,
|
3367
|
+
* returns nil.
|
3368
|
+
*
|
3369
|
+
* Stores the record fetched always in the same Hash object.
|
3370
|
+
*/
|
3371
|
+
static VALUE
|
3372
|
+
scrollcur_first_hash_bang(VALUE self)
|
3373
|
+
{
|
3374
|
+
return scrollcur_entry(self, INT2FIX(0), T_HASH, 1);
|
3375
|
+
}
|
3376
|
+
|
3377
|
+
/*
|
3378
|
+
* call-seq:
|
3379
|
+
* cursor.last => array or nil
|
3380
|
+
*
|
3381
|
+
* Returns the last record of the cursor. If the cursor is empty,
|
3382
|
+
* returns nil.
|
3383
|
+
*/
|
3384
|
+
static VALUE
|
3385
|
+
scrollcur_last(VALUE self)
|
3386
|
+
{
|
3387
|
+
return scrollcur_entry(self, INT2FIX(-1), T_ARRAY, 0);
|
3388
|
+
}
|
3389
|
+
|
3390
|
+
/*
|
3391
|
+
* call-seq:
|
3392
|
+
* cursor.last! => array or nil
|
3393
|
+
*
|
3394
|
+
* Returns the last record of the cursor. If the cursor is empty,
|
3395
|
+
* returns nil.
|
3396
|
+
*
|
3397
|
+
* Stores the record fetched always in the same Array object.
|
3398
|
+
*/
|
3399
|
+
static VALUE
|
3400
|
+
scrollcur_last_bang(VALUE self)
|
3401
|
+
{
|
3402
|
+
return scrollcur_entry(self, INT2FIX(-1), T_ARRAY, 1);
|
3403
|
+
}
|
3404
|
+
|
3405
|
+
/*
|
3406
|
+
* call-seq:
|
3407
|
+
* cursor.last_hash => hash or nil
|
3408
|
+
*
|
3409
|
+
* Returns the last record of the cursor. If the cursor is empty,
|
3410
|
+
* returns nil.
|
3411
|
+
*/
|
3412
|
+
static VALUE
|
3413
|
+
scrollcur_last_hash(VALUE self)
|
3414
|
+
{
|
3415
|
+
return scrollcur_entry(self, INT2FIX(-1), T_HASH, 0);
|
3416
|
+
}
|
3417
|
+
|
3418
|
+
/*
|
3419
|
+
* call-seq:
|
3420
|
+
* cursor.last_hash! => hash or nil
|
3421
|
+
*
|
3422
|
+
* Returns the last record of the cursor. If the cursor is empty,
|
3423
|
+
* returns nil.
|
3424
|
+
*
|
3425
|
+
* Stores the record fetched always in the same Hash object.
|
3426
|
+
*/
|
3427
|
+
static VALUE
|
3428
|
+
scrollcur_last_hash_bang(VALUE self)
|
3429
|
+
{
|
3430
|
+
return scrollcur_entry(self, INT2FIX(-1), T_HASH, 1);
|
3431
|
+
}
|
3432
|
+
|
3433
|
+
/*
|
3434
|
+
* call-seq:
|
3435
|
+
* cursor.current => array or nil
|
3436
|
+
*
|
3437
|
+
* Returns the current record of the cursor. If the cursor is empty,
|
3438
|
+
* returns nil.
|
3439
|
+
*/
|
3440
|
+
static VALUE
|
3441
|
+
scrollcur_current(VALUE self)
|
3442
|
+
{
|
3443
|
+
return scrollcur_entry(self, Qnil, T_ARRAY, 0);
|
3444
|
+
}
|
3445
|
+
|
3446
|
+
/*
|
3447
|
+
* call-seq:
|
3448
|
+
* cursor.current! => array or nil
|
3449
|
+
*
|
3450
|
+
* Returns the current record of the cursor. If the cursor is empty,
|
3451
|
+
* returns nil.
|
3452
|
+
*
|
3453
|
+
* Stores the record fetched always in the same Array object.
|
3454
|
+
*/
|
3455
|
+
static VALUE
|
3456
|
+
scrollcur_current_bang(VALUE self)
|
3457
|
+
{
|
3458
|
+
return scrollcur_entry(self, Qnil, T_ARRAY, 1);
|
3459
|
+
}
|
3460
|
+
|
3461
|
+
/*
|
3462
|
+
* call-seq:
|
3463
|
+
* cursor.current_hash => hash or nil
|
3464
|
+
*
|
3465
|
+
* Returns the current record of the cursor. If the cursor is empty,
|
3466
|
+
* returns nil.
|
3467
|
+
*/
|
3468
|
+
static VALUE
|
3469
|
+
scrollcur_current_hash(VALUE self)
|
3470
|
+
{
|
3471
|
+
return scrollcur_entry(self, Qnil, T_HASH, 0);
|
3472
|
+
}
|
3473
|
+
|
3474
|
+
/*
|
3475
|
+
* call-seq:
|
3476
|
+
* cursor.current_hash! => hash or nil
|
3477
|
+
*
|
3478
|
+
* Returns the current record of the cursor. If the cursor is empty,
|
3479
|
+
* returns nil.
|
3480
|
+
*
|
3481
|
+
* Stores the record fetched always in the same Hash object.
|
3482
|
+
*/
|
3483
|
+
static VALUE
|
3484
|
+
scrollcur_current_hash_bang(VALUE self)
|
3485
|
+
{
|
3486
|
+
return scrollcur_entry(self, Qnil, T_HASH, 1);
|
3487
|
+
}
|
3488
|
+
|
3489
|
+
/* class Cursor ---------------------------------------------------------- */
|
3490
|
+
static void
|
3491
|
+
cursor_close_or_free(cursor_t *c, short op)
|
3492
|
+
{
|
3493
|
+
/*
|
3494
|
+
* EXEC SQL begin declare section;
|
3495
|
+
*/
|
3496
|
+
#line 2685 "informix.ec"
|
3497
|
+
#line 2686 "informix.ec"
|
3498
|
+
char *cid, *sid, *did;
|
3499
|
+
/*
|
3500
|
+
* EXEC SQL end declare section;
|
3501
|
+
*/
|
3502
|
+
#line 2687 "informix.ec"
|
3503
|
+
|
3504
|
+
|
3505
|
+
if (op == 1 && !c->is_open)
|
3506
|
+
return;
|
3507
|
+
|
3508
|
+
c->is_open = 0;
|
3509
|
+
if (op == 1)
|
3510
|
+
clean_input_slots(c);
|
3511
|
+
else {
|
3512
|
+
free_input_slots(c);
|
3513
|
+
free_output_slots(c);
|
3514
|
+
}
|
3515
|
+
|
3516
|
+
did = c->database_id;
|
3517
|
+
if (currentdid != did) {
|
3518
|
+
/*
|
3519
|
+
* EXEC SQL set connection :did;
|
3520
|
+
*/
|
3521
|
+
#line 2702 "informix.ec"
|
3522
|
+
{
|
3523
|
+
#line 2702 "informix.ec"
|
3524
|
+
sqli_connect_set(0, did, 0);
|
3525
|
+
#line 2702 "informix.ec"
|
3526
|
+
}
|
3527
|
+
if (SQLCODE < 0)
|
3528
|
+
return;
|
3529
|
+
currentdid = did;
|
3530
|
+
}
|
3531
|
+
|
3532
|
+
cid = c->cursor_id;
|
3533
|
+
/*
|
3534
|
+
* EXEC SQL close :cid;
|
3535
|
+
*/
|
3536
|
+
#line 2709 "informix.ec"
|
3537
|
+
{
|
3538
|
+
#line 2709 "informix.ec"
|
3539
|
+
sqli_curs_close(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256));
|
3540
|
+
#line 2709 "informix.ec"
|
3541
|
+
}
|
3542
|
+
|
3543
|
+
if (op == 2) {
|
3544
|
+
sid = c->stmt_id;
|
3545
|
+
/*
|
3546
|
+
* EXEC SQL free :cid;
|
3547
|
+
*/
|
3548
|
+
#line 2713 "informix.ec"
|
3549
|
+
{
|
3550
|
+
#line 2713 "informix.ec"
|
3551
|
+
sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 258));
|
3552
|
+
#line 2713 "informix.ec"
|
3553
|
+
}
|
3554
|
+
/*
|
3555
|
+
* EXEC SQL free :sid;
|
3556
|
+
*/
|
3557
|
+
#line 2713 "informix.ec"
|
3558
|
+
{
|
3559
|
+
#line 2713 "informix.ec"
|
3560
|
+
sqli_curs_free(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 258));
|
3561
|
+
#line 2713 "informix.ec"
|
3562
|
+
}
|
3563
|
+
}
|
3564
|
+
}
|
3565
|
+
|
3566
|
+
static void
|
3567
|
+
cursor_mark(cursor_t *c)
|
3568
|
+
{
|
3569
|
+
rb_gc_mark(c->db);
|
3570
|
+
if (c->array)
|
3571
|
+
rb_gc_mark(c->array);
|
3572
|
+
if (c->hash)
|
3573
|
+
rb_gc_mark(c->hash);
|
3574
|
+
if (c->field_names)
|
3575
|
+
rb_gc_mark(c->field_names);
|
3576
|
+
}
|
3577
|
+
|
3578
|
+
static void
|
3579
|
+
cursor_free(void *p)
|
3580
|
+
{
|
3581
|
+
cursor_close_or_free(p, 2);
|
3582
|
+
xfree(p);
|
3583
|
+
}
|
3584
|
+
|
3585
|
+
static VALUE
|
3586
|
+
cursor_alloc(VALUE klass)
|
3587
|
+
{
|
3588
|
+
cursor_t *c;
|
3589
|
+
|
3590
|
+
c = ALLOC(cursor_t);
|
3591
|
+
memset(c, 0, sizeof(cursor_t));
|
3592
|
+
return Data_Wrap_Struct(klass, cursor_mark, cursor_free, c);
|
3593
|
+
}
|
3594
|
+
|
3595
|
+
/*
|
3596
|
+
* call-seq:
|
3597
|
+
* Cursor.new(database, query, options) => cursor
|
3598
|
+
*
|
3599
|
+
* Prepares <i>query</i> in the context of <i>database</i> with <i>options</i>
|
3600
|
+
* and returns a <code>Cursor</code> object.
|
3601
|
+
*
|
3602
|
+
* <i>options</i> can be nil or a hash with the following possible keys:
|
3603
|
+
*
|
3604
|
+
* :scroll => true or false
|
3605
|
+
* :hold => true or false
|
3606
|
+
*/
|
3607
|
+
static VALUE
|
3608
|
+
cursor_initialize(VALUE self, VALUE db, VALUE query, VALUE options)
|
3609
|
+
{
|
3610
|
+
VALUE scroll, hold;
|
3611
|
+
struct sqlda *output;
|
3612
|
+
cursor_t *c;
|
3613
|
+
/*
|
3614
|
+
* EXEC SQL begin declare section;
|
3615
|
+
*/
|
3616
|
+
#line 2764 "informix.ec"
|
3617
|
+
#line 2765 "informix.ec"
|
3618
|
+
char *c_query;
|
3619
|
+
char *cid, *sid, *did;
|
3620
|
+
/*
|
3621
|
+
* EXEC SQL end declare section;
|
3622
|
+
*/
|
3623
|
+
#line 2767 "informix.ec"
|
3624
|
+
|
3625
|
+
|
3626
|
+
Data_Get_Struct(db, char, did);
|
3627
|
+
|
3628
|
+
if (currentdid != did) {
|
3629
|
+
/*
|
3630
|
+
* EXEC SQL set connection :did;
|
3631
|
+
*/
|
3632
|
+
#line 2772 "informix.ec"
|
3633
|
+
{
|
3634
|
+
#line 2772 "informix.ec"
|
3635
|
+
sqli_connect_set(0, did, 0);
|
3636
|
+
#line 2772 "informix.ec"
|
3637
|
+
}
|
3638
|
+
if (SQLCODE < 0)
|
3639
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3640
|
+
currentdid = did;
|
3641
|
+
}
|
3642
|
+
|
3643
|
+
Data_Get_Struct(self, cursor_t, c);
|
3644
|
+
c->db = db;
|
3645
|
+
c->database_id = did;
|
3646
|
+
scroll = hold = Qfalse;
|
3647
|
+
snprintf(c->cursor_id, sizeof(c->cursor_id), "CUR%lX", self);
|
3648
|
+
snprintf(c->stmt_id, sizeof(c->stmt_id), "STMT%lX", self);
|
3649
|
+
cid = c->cursor_id; sid = c->stmt_id;
|
3650
|
+
c_query = StringValueCStr(query);
|
3651
|
+
|
3652
|
+
if (RTEST(options)) {
|
3653
|
+
scroll = rb_hash_aref(options, sym_scroll);
|
3654
|
+
hold = rb_hash_aref(options, sym_hold);
|
3655
|
+
}
|
3656
|
+
|
3657
|
+
/*
|
3658
|
+
* EXEC SQL prepare :sid from :c_query;
|
3659
|
+
*/
|
3660
|
+
#line 2792 "informix.ec"
|
3661
|
+
{
|
3662
|
+
#line 2792 "informix.ec"
|
3663
|
+
sqli_prep(ESQLINTVERSION, sid, c_query,(ifx_literal_t *)0, (ifx_namelist_t *)0, -1, 0, 0 );
|
3664
|
+
#line 2792 "informix.ec"
|
3665
|
+
}
|
3666
|
+
if (SQLCODE < 0)
|
3667
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3668
|
+
|
3669
|
+
if (RTEST(scroll) && RTEST(hold))
|
3670
|
+
/*
|
3671
|
+
* EXEC SQL declare :cid scroll cursor with hold for :sid;
|
3672
|
+
*/
|
3673
|
+
#line 2797 "informix.ec"
|
3674
|
+
{
|
3675
|
+
#line 2797 "informix.ec"
|
3676
|
+
sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 4128, 0);
|
3677
|
+
#line 2797 "informix.ec"
|
3678
|
+
}
|
3679
|
+
else if (RTEST(hold))
|
3680
|
+
/*
|
3681
|
+
* EXEC SQL declare :cid cursor with hold for :sid;
|
3682
|
+
*/
|
3683
|
+
#line 2799 "informix.ec"
|
3684
|
+
{
|
3685
|
+
#line 2799 "informix.ec"
|
3686
|
+
sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 4096, 0);
|
3687
|
+
#line 2799 "informix.ec"
|
3688
|
+
}
|
3689
|
+
else if (RTEST(scroll))
|
3690
|
+
/*
|
3691
|
+
* EXEC SQL declare :cid scroll cursor for :sid;
|
3692
|
+
*/
|
3693
|
+
#line 2801 "informix.ec"
|
3694
|
+
{
|
3695
|
+
#line 2801 "informix.ec"
|
3696
|
+
sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 32, 0);
|
3697
|
+
#line 2801 "informix.ec"
|
3698
|
+
}
|
3699
|
+
else
|
3700
|
+
/*
|
3701
|
+
* EXEC SQL declare :cid cursor for :sid;
|
3702
|
+
*/
|
3703
|
+
#line 2803 "informix.ec"
|
3704
|
+
{
|
3705
|
+
#line 2803 "informix.ec"
|
3706
|
+
sqli_curs_decl_dynm(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 0), cid, sqli_curs_locate(ESQLINTVERSION, sid, 1), 0, 0);
|
3707
|
+
#line 2803 "informix.ec"
|
3708
|
+
}
|
3709
|
+
|
3710
|
+
if (SQLCODE < 0)
|
3711
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3712
|
+
|
3713
|
+
alloc_input_slots(c, c_query);
|
3714
|
+
/*
|
3715
|
+
* EXEC SQL describe :sid into output;
|
3716
|
+
*/
|
3717
|
+
#line 2809 "informix.ec"
|
3718
|
+
{
|
3719
|
+
#line 2809 "informix.ec"
|
3720
|
+
sqli_describe_stmt(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, sid, 257), &output, 0);
|
3721
|
+
#line 2809 "informix.ec"
|
3722
|
+
}
|
3723
|
+
c->daOutput = output;
|
3724
|
+
|
3725
|
+
c->is_select = (SQLCODE == 0 || SQLCODE == SQ_EXECPROC);
|
3726
|
+
|
3727
|
+
if (c->is_select) {
|
3728
|
+
alloc_output_slots(c);
|
3729
|
+
rb_extend_object(self, rb_mSequentialCursor);
|
3730
|
+
if (scroll)
|
3731
|
+
rb_extend_object(self, rb_mScrollCursor);
|
3732
|
+
}
|
3733
|
+
else {
|
3734
|
+
xfree(c->daOutput);
|
3735
|
+
c->daOutput = NULL;
|
3736
|
+
rb_extend_object(self, rb_mInsertCursor);
|
3737
|
+
}
|
3738
|
+
return self;
|
3739
|
+
}
|
3740
|
+
|
3741
|
+
/*
|
3742
|
+
* call-seq:
|
3743
|
+
* cursor.id => string
|
3744
|
+
*
|
3745
|
+
* Returns the cursor ID
|
3746
|
+
*/
|
3747
|
+
static VALUE
|
3748
|
+
cursor_id(VALUE self)
|
3749
|
+
{
|
3750
|
+
cursor_t *c;
|
3751
|
+
|
3752
|
+
Data_Get_Struct(self, cursor_t, c);
|
3753
|
+
return rb_str_new2(c->cursor_id);
|
3754
|
+
}
|
3755
|
+
|
3756
|
+
/*
|
3757
|
+
* call-seq:
|
3758
|
+
* cursor.open(*params) => cursor
|
3759
|
+
*
|
3760
|
+
* Executes the previously prepared select statement, binding <i>params</i> as
|
3761
|
+
* input parameters.
|
3762
|
+
*
|
3763
|
+
* Returns __self__.
|
3764
|
+
*/
|
3765
|
+
static VALUE
|
3766
|
+
cursor_open(int argc, VALUE *argv, VALUE self)
|
3767
|
+
{
|
3768
|
+
struct sqlda *input;
|
3769
|
+
cursor_t *c;
|
3770
|
+
/*
|
3771
|
+
* EXEC SQL begin declare section;
|
3772
|
+
*/
|
3773
|
+
#line 2857 "informix.ec"
|
3774
|
+
#line 2858 "informix.ec"
|
3775
|
+
char *cid, *did;
|
3776
|
+
/*
|
3777
|
+
* EXEC SQL end declare section;
|
3778
|
+
*/
|
3779
|
+
#line 2859 "informix.ec"
|
3780
|
+
|
3781
|
+
|
3782
|
+
Data_Get_Struct(self, cursor_t, c);
|
3783
|
+
|
3784
|
+
if (c->is_open)
|
3785
|
+
return self;
|
3786
|
+
|
3787
|
+
did = c->database_id;
|
3788
|
+
if (currentdid != did) {
|
3789
|
+
/*
|
3790
|
+
* EXEC SQL set connection :did;
|
3791
|
+
*/
|
3792
|
+
#line 2868 "informix.ec"
|
3793
|
+
{
|
3794
|
+
#line 2868 "informix.ec"
|
3795
|
+
sqli_connect_set(0, did, 0);
|
3796
|
+
#line 2868 "informix.ec"
|
3797
|
+
}
|
3798
|
+
if (SQLCODE < 0)
|
3799
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3800
|
+
currentdid = did;
|
3801
|
+
}
|
3802
|
+
|
3803
|
+
input = &c->daInput;
|
3804
|
+
cid = c->cursor_id;
|
3805
|
+
|
3806
|
+
if (c->is_select) {
|
3807
|
+
if (argc != input->sqld) {
|
3808
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
|
3809
|
+
argc, input->sqld);
|
3810
|
+
}
|
3811
|
+
if (argc) {
|
3812
|
+
bind_input_params(c, argv);
|
3813
|
+
/*
|
3814
|
+
* EXEC SQL open :cid using descriptor input
|
3815
|
+
* with reoptimization;
|
3816
|
+
*/
|
3817
|
+
#line 2884 "informix.ec"
|
3818
|
+
{
|
3819
|
+
#line 2885 "informix.ec"
|
3820
|
+
sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), input, (char *)0, (struct value *)0, 1, 1);
|
3821
|
+
#line 2885 "informix.ec"
|
3822
|
+
}
|
3823
|
+
clean_input_slots(c);
|
3824
|
+
}
|
3825
|
+
else
|
3826
|
+
/*
|
3827
|
+
* EXEC SQL open :cid with reoptimization;
|
3828
|
+
*/
|
3829
|
+
#line 2889 "informix.ec"
|
3830
|
+
{
|
3831
|
+
#line 2889 "informix.ec"
|
3832
|
+
sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0, 1);
|
3833
|
+
#line 2889 "informix.ec"
|
3834
|
+
}
|
3835
|
+
}
|
3836
|
+
else
|
3837
|
+
/*
|
3838
|
+
* EXEC SQL open :cid;
|
3839
|
+
*/
|
3840
|
+
#line 2892 "informix.ec"
|
3841
|
+
{
|
3842
|
+
#line 2892 "informix.ec"
|
3843
|
+
sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, cid, 256), (ifx_sqlda_t *)0, (char *)0, (struct value *)0, 0, 0);
|
3844
|
+
#line 2892 "informix.ec"
|
3845
|
+
}
|
3846
|
+
|
3847
|
+
if (SQLCODE < 0)
|
3848
|
+
rb_raise(rb_eRuntimeError, "Informix Error: %d", SQLCODE);
|
3849
|
+
|
3850
|
+
c->is_open = 1;
|
3851
|
+
return self;
|
3852
|
+
}
|
3853
|
+
|
3854
|
+
/*
|
3855
|
+
* call-seq:
|
3856
|
+
* cursor.close => cursor
|
3857
|
+
*
|
3858
|
+
* Closes the cursor and returns __self__.
|
3859
|
+
*/
|
3860
|
+
static VALUE
|
3861
|
+
cursor_close(VALUE self)
|
3862
|
+
{
|
3863
|
+
cursor_t *c;
|
3864
|
+
|
3865
|
+
Data_Get_Struct(self, cursor_t, c);
|
3866
|
+
cursor_close_or_free(c, 1);
|
3867
|
+
return self;
|
3868
|
+
}
|
3869
|
+
|
3870
|
+
/*
|
3871
|
+
* call-seq:
|
3872
|
+
* cursor.drop => nil
|
3873
|
+
*
|
3874
|
+
* Closes the cursor and frees the memory associated with it. The cursor
|
3875
|
+
* cannot be opened again.
|
3876
|
+
*/
|
3877
|
+
static VALUE
|
3878
|
+
cursor_drop(VALUE self)
|
3879
|
+
{
|
3880
|
+
cursor_t *c;
|
3881
|
+
|
3882
|
+
Data_Get_Struct(self, cursor_t, c);
|
3883
|
+
cursor_close_or_free(c, 2);
|
3884
|
+
|
3885
|
+
return Qnil;
|
3886
|
+
}
|
3887
|
+
|
3888
|
+
/* Entry point ------------------------------------------------------------ */
|
3889
|
+
|
3890
|
+
void Init_informix(void)
|
3891
|
+
{
|
3892
|
+
/* module Informix ---------------------------------------------------- */
|
3893
|
+
rb_mInformix = rb_define_module("Informix");
|
3894
|
+
rb_mScrollCursor = rb_define_module_under(rb_mInformix, "ScrollCursor");
|
3895
|
+
rb_mInsertCursor = rb_define_module_under(rb_mInformix, "InsertCursor");
|
3896
|
+
rb_define_module_function(rb_mInformix, "connect", informix_connect, -1);
|
3897
|
+
|
3898
|
+
/* class Slob --------------------------------------------------------- */
|
3899
|
+
rb_cSlob = rb_define_class_under(rb_mInformix, "Slob", rb_cObject);
|
3900
|
+
rb_define_alloc_func(rb_cSlob, slob_alloc);
|
3901
|
+
rb_define_method(rb_cSlob, "initialize", slob_initialize, -1);
|
3902
|
+
rb_define_method(rb_cSlob, "open", slob_open, -1);
|
3903
|
+
rb_define_method(rb_cSlob, "close", slob_close, 0);
|
3904
|
+
rb_define_method(rb_cSlob, "read", slob_read, 1);
|
3905
|
+
rb_define_method(rb_cSlob, "write", slob_write, 1);
|
3906
|
+
rb_define_method(rb_cSlob, "seek", slob_seek, 2);
|
3907
|
+
rb_define_method(rb_cSlob, "tell", slob_tell, 0);
|
3908
|
+
rb_define_method(rb_cSlob, "truncate", slob_truncate, 1);
|
3909
|
+
|
3910
|
+
rb_define_const(rb_cSlob, "CLOB", INT2FIX(XID_CLOB));
|
3911
|
+
rb_define_const(rb_cSlob, "BLOB", INT2FIX(XID_BLOB));
|
3912
|
+
|
3913
|
+
#define DEF_SLOB_CONST(k) rb_define_const(rb_cSlob, #k, INT2FIX(LO_##k))
|
3914
|
+
|
3915
|
+
DEF_SLOB_CONST(RDONLY);
|
3916
|
+
DEF_SLOB_CONST(DIRTY_READ);
|
3917
|
+
DEF_SLOB_CONST(WRONLY);
|
3918
|
+
DEF_SLOB_CONST(APPEND);
|
3919
|
+
DEF_SLOB_CONST(RDWR);
|
3920
|
+
DEF_SLOB_CONST(BUFFER);
|
3921
|
+
DEF_SLOB_CONST(NOBUFFER);
|
3922
|
+
DEF_SLOB_CONST(LOCKALL);
|
3923
|
+
DEF_SLOB_CONST(LOCKRANGE);
|
3924
|
+
DEF_SLOB_CONST(SEEK_SET);
|
3925
|
+
DEF_SLOB_CONST(SEEK_CUR);
|
3926
|
+
DEF_SLOB_CONST(SEEK_END);
|
3927
|
+
|
3928
|
+
/* class Database ----------------------------------------------------- */
|
3929
|
+
rb_cDatabase = rb_define_class_under(rb_mInformix, "Database", rb_cObject);
|
3930
|
+
rb_define_alloc_func(rb_cDatabase, database_alloc);
|
3931
|
+
rb_define_method(rb_cDatabase, "initialize", database_initialize, -1);
|
3932
|
+
rb_define_alias(rb_cDatabase, "open", "initialize");
|
3933
|
+
rb_define_method(rb_cDatabase, "close", database_close, 0);
|
3934
|
+
rb_define_method(rb_cDatabase, "immediate", database_immediate, 1);
|
3935
|
+
rb_define_alias(rb_cDatabase, "do", "immediate");
|
3936
|
+
rb_define_method(rb_cDatabase, "rollback", database_rollback, 0);
|
3937
|
+
rb_define_method(rb_cDatabase, "commit", database_commit, 0);
|
3938
|
+
rb_define_method(rb_cDatabase, "transaction", database_transaction, 0);
|
3939
|
+
rb_define_method(rb_cDatabase, "prepare", database_prepare, 1);
|
3940
|
+
rb_define_method(rb_cDatabase, "columns", database_columns, 1);
|
3941
|
+
rb_define_method(rb_cDatabase, "cursor", database_cursor, -1);
|
3942
|
+
|
3943
|
+
/* class Statement ---------------------------------------------------- */
|
3944
|
+
rb_cStatement = rb_define_class_under(rb_mInformix, "Statement", rb_cObject);
|
3945
|
+
rb_define_alloc_func(rb_cStatement, statement_alloc);
|
3946
|
+
rb_define_method(rb_cStatement, "initialize", statement_initialize, 2);
|
3947
|
+
rb_define_method(rb_cStatement, "[]", statement_call, -1);
|
3948
|
+
rb_define_alias(rb_cStatement, "call", "[]");
|
3949
|
+
rb_define_alias(rb_cStatement, "execute", "[]");
|
3950
|
+
rb_define_method(rb_cStatement, "drop", statement_drop, 0);
|
3951
|
+
|
3952
|
+
/* module SequentialCursor -------------------------------------------- */
|
3953
|
+
rb_mSequentialCursor = rb_define_module_under(rb_mInformix, "SequentialCursor");
|
3954
|
+
rb_define_method(rb_mSequentialCursor, "fetch", seqcur_fetch, 0);
|
3955
|
+
rb_define_method(rb_mSequentialCursor, "fetch!", seqcur_fetch_bang, 0);
|
3956
|
+
rb_define_method(rb_mSequentialCursor, "fetch_hash", seqcur_fetch_hash, 0);
|
3957
|
+
rb_define_method(rb_mSequentialCursor, "fetch_hash!", seqcur_fetch_hash_bang, 0);
|
3958
|
+
rb_define_method(rb_mSequentialCursor, "fetch_many", seqcur_fetch_many, 1);
|
3959
|
+
rb_define_method(rb_mSequentialCursor, "fetch_hash_many", seqcur_fetch_hash_many, 1);
|
3960
|
+
rb_define_method(rb_mSequentialCursor, "fetch_all", seqcur_fetch_all, 0);
|
3961
|
+
rb_define_method(rb_mSequentialCursor, "fetch_hash_all", seqcur_fetch_hash_all, 0);
|
3962
|
+
rb_define_method(rb_mSequentialCursor, "each", seqcur_each, 0);
|
3963
|
+
rb_define_method(rb_mSequentialCursor, "each!", seqcur_each_bang, 0);
|
3964
|
+
rb_define_method(rb_mSequentialCursor, "each_hash", seqcur_each_hash, 0);
|
3965
|
+
rb_define_method(rb_mSequentialCursor, "each_hash!", seqcur_each_hash_bang, 0);
|
3966
|
+
rb_define_method(rb_mSequentialCursor, "each_by", seqcur_each_by, 1);
|
3967
|
+
rb_define_method(rb_mSequentialCursor, "each_hash_by", seqcur_each_hash_by, 1);
|
3968
|
+
|
3969
|
+
/* InsertCursor ------------------------------------------------------- */
|
3970
|
+
rb_define_method(rb_mInsertCursor, "put", inscur_put, -1);
|
3971
|
+
rb_define_method(rb_mInsertCursor, "flush", inscur_flush, 0);
|
3972
|
+
|
3973
|
+
/* ScrollCursor ------------------------------------------------------- */
|
3974
|
+
rb_define_method(rb_mScrollCursor, "[]", scrollcur_slice, -1);
|
3975
|
+
rb_define_alias(rb_mScrollCursor, "slice", "[]");
|
3976
|
+
rb_define_method(rb_mScrollCursor, "slice!", scrollcur_slice_bang, 1);
|
3977
|
+
rb_define_method(rb_mScrollCursor, "slice_hash", scrollcur_slice_hash, -1);
|
3978
|
+
rb_define_method(rb_mScrollCursor, "slice_hash!", scrollcur_slice_hash_bang, 1);
|
3979
|
+
rb_define_method(rb_mScrollCursor, "prev", scrollcur_prev, -1);
|
3980
|
+
rb_define_method(rb_mScrollCursor, "prev!", scrollcur_prev_bang, -1);
|
3981
|
+
rb_define_method(rb_mScrollCursor, "prev_hash", scrollcur_prev_hash, -1);
|
3982
|
+
rb_define_method(rb_mScrollCursor, "prev_hash!", scrollcur_prev_hash_bang, -1);
|
3983
|
+
rb_define_method(rb_mScrollCursor, "next", scrollcur_next, -1);
|
3984
|
+
rb_define_method(rb_mScrollCursor, "next!", scrollcur_next_bang, -1);
|
3985
|
+
rb_define_method(rb_mScrollCursor, "next_hash", scrollcur_next_hash, -1);
|
3986
|
+
rb_define_method(rb_mScrollCursor, "next_hash!", scrollcur_next_hash_bang, -1);
|
3987
|
+
rb_define_method(rb_mScrollCursor, "first", scrollcur_first, 0);
|
3988
|
+
rb_define_method(rb_mScrollCursor, "first!", scrollcur_first_bang, 0);
|
3989
|
+
rb_define_method(rb_mScrollCursor, "first_hash", scrollcur_first_hash, 0);
|
3990
|
+
rb_define_method(rb_mScrollCursor, "first_hash!", scrollcur_first_hash_bang, 0);
|
3991
|
+
rb_define_method(rb_mScrollCursor, "last", scrollcur_last, 0);
|
3992
|
+
rb_define_method(rb_mScrollCursor, "last!", scrollcur_last_bang, 0);
|
3993
|
+
rb_define_method(rb_mScrollCursor, "last_hash", scrollcur_last_hash, 0);
|
3994
|
+
rb_define_method(rb_mScrollCursor, "last_hash!", scrollcur_last_hash_bang, 0);
|
3995
|
+
rb_define_method(rb_mScrollCursor, "current", scrollcur_current, 0);
|
3996
|
+
rb_define_method(rb_mScrollCursor, "current!", scrollcur_current_bang, 0);
|
3997
|
+
rb_define_method(rb_mScrollCursor, "current_hash", scrollcur_current_hash, 0);
|
3998
|
+
rb_define_method(rb_mScrollCursor, "current_hash!", scrollcur_current_hash_bang, 0);
|
3999
|
+
|
4000
|
+
/* class Cursor ------------------------------------------------------- */
|
4001
|
+
rb_cCursor = rb_define_class_under(rb_mInformix, "Cursor", rb_cObject);
|
4002
|
+
rb_define_alloc_func(rb_cCursor, cursor_alloc);
|
4003
|
+
rb_define_method(rb_cCursor, "initialize", cursor_initialize, 3);
|
4004
|
+
rb_define_method(rb_cCursor, "id", cursor_id, 0);
|
4005
|
+
rb_define_method(rb_cCursor, "open", cursor_open, -1);
|
4006
|
+
rb_define_method(rb_cCursor, "close", cursor_close, 0);
|
4007
|
+
rb_define_method(rb_cCursor, "drop", cursor_drop, 0);
|
4008
|
+
|
4009
|
+
/* Global constants --------------------------------------------------- */
|
4010
|
+
rb_require("date");
|
4011
|
+
rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
4012
|
+
|
4013
|
+
/* Global symbols ----------------------------------------------------- */
|
4014
|
+
s_read = rb_intern("read");
|
4015
|
+
s_new = rb_intern("new");
|
4016
|
+
s_utc = rb_intern("utc");
|
4017
|
+
s_day = rb_intern("day");
|
4018
|
+
s_month = rb_intern("month");
|
4019
|
+
s_year = rb_intern("year");
|
4020
|
+
s_hour = rb_intern("hour");
|
4021
|
+
s_min = rb_intern("min");
|
4022
|
+
s_sec = rb_intern("sec");
|
4023
|
+
s_usec = rb_intern("usec");
|
4024
|
+
s_to_s = rb_intern("to_s");
|
4025
|
+
s_to_i = rb_intern("to_i");
|
4026
|
+
|
4027
|
+
sym_name = ID2SYM(rb_intern("name"));
|
4028
|
+
sym_type = ID2SYM(rb_intern("type"));
|
4029
|
+
sym_nullable = ID2SYM(rb_intern("nullable"));
|
4030
|
+
sym_stype = ID2SYM(rb_intern("stype"));
|
4031
|
+
sym_length = ID2SYM(rb_intern("length"));
|
4032
|
+
sym_precision = ID2SYM(rb_intern("precision"));
|
4033
|
+
sym_scale = ID2SYM(rb_intern("scale"));
|
4034
|
+
sym_default = ID2SYM(rb_intern("default"));
|
4035
|
+
sym_xid = ID2SYM(rb_intern("xid"));
|
4036
|
+
|
4037
|
+
sym_scroll = ID2SYM(rb_intern("scroll"));
|
4038
|
+
sym_hold = ID2SYM(rb_intern("hold"));
|
4039
|
+
|
4040
|
+
sym_col_info = ID2SYM(rb_intern("col_info"));
|
4041
|
+
sym_sbspace = ID2SYM(rb_intern("sbspace"));
|
4042
|
+
sym_estbytes = ID2SYM(rb_intern("estbytes"));
|
4043
|
+
sym_extsz = ID2SYM(rb_intern("extsz"));
|
4044
|
+
sym_createflags = ID2SYM(rb_intern("createflags"));
|
4045
|
+
sym_openflags = ID2SYM(rb_intern("openflags"));
|
4046
|
+
}
|
4047
|
+
|
4048
|
+
#line 3093 "informix.ec"
|