ruby-oci8 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/ChangeLog +569 -0
  2. data/Makefile +51 -0
  3. data/NEWS +322 -0
  4. data/README +415 -0
  5. data/VERSION +1 -0
  6. data/dist-files +70 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/MANIFEST +22 -0
  13. data/ext/oci8/attr.c +415 -0
  14. data/ext/oci8/bind.c +194 -0
  15. data/ext/oci8/const.c +165 -0
  16. data/ext/oci8/define.c +53 -0
  17. data/ext/oci8/describe.c +81 -0
  18. data/ext/oci8/descriptor.c +39 -0
  19. data/ext/oci8/env.c +276 -0
  20. data/ext/oci8/error.c +234 -0
  21. data/ext/oci8/extconf.rb +118 -0
  22. data/ext/oci8/handle.c +262 -0
  23. data/ext/oci8/lob.c +386 -0
  24. data/ext/oci8/oci8.c +137 -0
  25. data/ext/oci8/oci8.h +345 -0
  26. data/ext/oci8/ocinumber.c +117 -0
  27. data/ext/oci8/oraconf.rb +1026 -0
  28. data/ext/oci8/oradate.c +426 -0
  29. data/ext/oci8/oranumber.c +445 -0
  30. data/ext/oci8/param.c +37 -0
  31. data/ext/oci8/post-config.rb +5 -0
  32. data/ext/oci8/server.c +182 -0
  33. data/ext/oci8/session.c +99 -0
  34. data/ext/oci8/stmt.c +624 -0
  35. data/ext/oci8/svcctx.c +229 -0
  36. data/lib/DBD/OCI8/OCI8.rb +549 -0
  37. data/lib/oci8.rb.in +1605 -0
  38. data/metaconfig +142 -0
  39. data/pre-distclean.rb +7 -0
  40. data/ruby-oci8.gemspec +54 -0
  41. data/ruby-oci8.spec +62 -0
  42. data/setup.rb +1331 -0
  43. data/support/README +4 -0
  44. data/support/runit/assert.rb +281 -0
  45. data/support/runit/cui/testrunner.rb +101 -0
  46. data/support/runit/error.rb +4 -0
  47. data/support/runit/method_mappable.rb +20 -0
  48. data/support/runit/robserver.rb +25 -0
  49. data/support/runit/setuppable.rb +15 -0
  50. data/support/runit/teardownable.rb +16 -0
  51. data/support/runit/testcase.rb +113 -0
  52. data/support/runit/testfailure.rb +25 -0
  53. data/support/runit/testresult.rb +121 -0
  54. data/support/runit/testsuite.rb +43 -0
  55. data/support/runit/version.rb +3 -0
  56. data/test/README +4 -0
  57. data/test/config.rb +129 -0
  58. data/test/test_all.rb +43 -0
  59. data/test/test_bind_raw.rb +53 -0
  60. data/test/test_bind_time.rb +191 -0
  61. data/test/test_break.rb +81 -0
  62. data/test/test_clob.rb +101 -0
  63. data/test/test_connstr.rb +80 -0
  64. data/test/test_dbi.rb +317 -0
  65. data/test/test_dbi_clob.rb +56 -0
  66. data/test/test_describe.rb +137 -0
  67. data/test/test_metadata.rb +243 -0
  68. data/test/test_oci8.rb +273 -0
  69. data/test/test_oradate.rb +263 -0
  70. data/test/test_oranumber.rb +149 -0
  71. metadata +118 -0
@@ -0,0 +1,37 @@
1
+ /*
2
+ param.c - part of ruby-oci8
3
+
4
+ Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
5
+
6
+ =begin
7
+ == OCIParam
8
+ super class: ((<OCIDescriptor>))
9
+ =end
10
+ */
11
+ #include "oci8.h"
12
+
13
+ void Init_oci8_param(void)
14
+ {
15
+ rb_define_method(cOCIParam, "paramGet", oci8_param_get, 1);
16
+ }
17
+
18
+ VALUE oci8_param_get(VALUE self, VALUE pos)
19
+ {
20
+ oci8_handle_t *h;
21
+ OCIParam *parmhp = NULL;
22
+ oci8_handle_t *parmh;
23
+ VALUE obj;
24
+ sword rv;
25
+
26
+ Get_Handle(self, h);
27
+ Check_Type(pos, T_FIXNUM);
28
+ rv = OCIParamGet(h->hp, h->type, h->errhp, (dvoid *)&parmhp, FIX2INT(pos));
29
+ if (rv != OCI_SUCCESS) {
30
+ oci8_raise(h->errhp, rv, NULL);
31
+ }
32
+ parmh = oci8_make_handle(OCI_DTYPE_PARAM, parmhp, h->errhp, h, 0);
33
+ parmh->u.param.is_implicit = (h->type == OCI_HTYPE_STMT) ? 1 : 0;
34
+
35
+ obj = parmh->self;
36
+ return obj;
37
+ }
@@ -0,0 +1,5 @@
1
+ File.foreach("#{curr_objdir}/extconf.h") do |line|
2
+ if /^#define OCI8_CLIENT_VERSION "(...)"/ =~ line
3
+ set_config('oracle_version', $1)
4
+ end
5
+ end
@@ -0,0 +1,182 @@
1
+ /*
2
+ server.c - part of ruby-oci8
3
+
4
+ Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
5
+
6
+ =begin
7
+ == OCIServer
8
+ If you use ((<OCIEnv#logon>)), you have no need to use this handle directly.
9
+ Because ((<OCIEnv#logon>)) create this handle implicitly and set it to ((<OCISvcCtx>)).
10
+
11
+ super class: ((<OCIHandle>))
12
+
13
+ correspond native OCI datatype: ((|OCIServer|))
14
+ =end
15
+ */
16
+ #include "oci8.h"
17
+
18
+ /*
19
+ =begin
20
+ --- OCIServer#attach(dbname [, mode])
21
+ attach to the database.
22
+ :dbname
23
+ the name of database.
24
+ :mode
25
+ ((|OCI_DEFAULT|)) or ((|OCI_CPOOL|))(Oracle 9i). Default value is ((|OCI_DEFAULT|)).
26
+
27
+ This ruby module doesn't support the connection pooling provided by OCI,
28
+ so ((|OCI_CPOOL|)) is invalid value for now.
29
+
30
+ correspond native OCI function: ((|OCIServerAttach|))
31
+ =end
32
+ */
33
+ static VALUE oci8_server_attach(int argc, VALUE *argv, VALUE self)
34
+ {
35
+ VALUE vdbname, vmode;
36
+ oci8_handle_t *h;
37
+ oci8_string_t d;
38
+ ub4 mode;
39
+ sword rv;
40
+
41
+ rb_scan_args(argc, argv, "11", &vdbname, &vmode);
42
+ Get_Handle(self, h); /* 0 */
43
+ Get_String(vdbname, d); /* 1 */
44
+ Get_Int_With_Default(argc, 2, vmode, mode, OCI_DEFAULT); /* 2 */
45
+
46
+ rv = OCIServerAttach(h->hp, h->errhp, d.ptr, d.len, mode);
47
+ if (rv != OCI_SUCCESS)
48
+ oci8_raise(h->errhp, rv, NULL);
49
+ return self;
50
+ }
51
+
52
+ /*
53
+ =begin
54
+ --- OCIServer#detach([mode])
55
+ detach from the database.
56
+
57
+ :mode
58
+ ((|OCI_DEFAULT|)) only valid. Default value is ((|OCI_DEFAULT|)).
59
+
60
+ correspond native OCI function: ((|OCIServerDetach|))
61
+ =end
62
+ */
63
+ static VALUE oci8_server_detach(int argc, VALUE *argv, VALUE self)
64
+ {
65
+ VALUE vmode;
66
+ oci8_handle_t *h;
67
+ ub4 mode;
68
+ sword rv;
69
+
70
+
71
+ rb_scan_args(argc, argv, "01", &vmode);
72
+ Get_Handle(self, h); /* 0 */
73
+ Get_Int_With_Default(argc, 1, vmode, mode, OCI_DEFAULT); /* 1 */
74
+
75
+ rv = OCIServerDetach(h->hp, h->errhp, mode);
76
+ if (rv != OCI_SUCCESS)
77
+ oci8_raise(h->errhp, rv, NULL);
78
+ return self;
79
+ }
80
+
81
+
82
+
83
+ void Init_oci8_server(void)
84
+ {
85
+ rb_define_method(cOCIServer, "attach", oci8_server_attach, -1);
86
+ rb_define_method(cOCIServer, "detach", oci8_server_detach, -1);
87
+ rb_define_method(cOCIServer, "version", oci8_server_version, 0);
88
+ #ifdef HAVE_OCISERVERRELEASE
89
+ rb_define_method(cOCIServer, "release", oci8_server_release, 0);
90
+ #endif
91
+ rb_define_method(cOCIServer, "break", oci8_break, 0);
92
+ #ifdef HAVE_OCIRESET
93
+ rb_define_method(cOCIServer, "reset", oci8_reset, 0);
94
+ #endif
95
+ }
96
+
97
+ /*
98
+ =begin
99
+ --- OCIServer#version()
100
+ get server version.
101
+
102
+ :return value
103
+ string of server version. For example
104
+ Oracle8 Release 8.0.5.0.0 - Production
105
+ PL/SQL Release 8.0.5.0.0 - Production
106
+
107
+ correspond native OCI function: ((|OCIServerVersion|))
108
+ =end
109
+ */
110
+ VALUE oci8_server_version(VALUE self)
111
+ {
112
+ oci8_handle_t *h;
113
+ OraText buf[1024];
114
+ sword rv;
115
+
116
+ Get_Handle(self, h); /* 0 */
117
+ rv = OCIServerVersion(h->hp, h->errhp, buf, sizeof(buf), h->type);
118
+ if (rv != OCI_SUCCESS)
119
+ oci8_raise(h->errhp, rv, NULL);
120
+ return rb_str_new2(TO_CHARPTR(buf));
121
+ }
122
+
123
+ /*
124
+ =begin
125
+ --- OCIServer#release()
126
+ get server version number and string
127
+
128
+ :return value
129
+ array of number and string. For example
130
+
131
+ version_number, version_str = srv.release()
132
+ version_number is 0x8005000.
133
+ version_str is
134
+ Oracle8 Release 8.0.5.0.0 - Production
135
+ PL/SQL Release 8.0.5.0.0 - Production
136
+
137
+ correspond native OCI function: ((|OCIServerVersion|))
138
+
139
+ Oracle 9i or later?
140
+ =end
141
+ */
142
+ #ifdef HAVE_OCISERVERRELEASE
143
+ VALUE oci8_server_release(VALUE self)
144
+ {
145
+ oci8_handle_t *h;
146
+ OraText buf[1024];
147
+ ub4 version = 0;
148
+ sword rv;
149
+
150
+ Get_Handle(self, h); /* 0 */
151
+ rv = OCIServerRelease(h->hp, h->errhp, buf, sizeof(buf), h->type, &version);
152
+ if (rv != OCI_SUCCESS)
153
+ oci8_raise(h->errhp, rv, NULL);
154
+ return rb_ary_new3(2, INT2FIX(version), rb_str_new2(buf));
155
+ }
156
+ #endif
157
+
158
+ VALUE oci8_break(VALUE self)
159
+ {
160
+ oci8_handle_t *h;
161
+ sword rv;
162
+
163
+ Get_Handle(self, h); /* 0 */
164
+ rv = OCIBreak(h->hp, h->errhp);
165
+ if (rv != OCI_SUCCESS)
166
+ oci8_raise(h->errhp, rv, NULL);
167
+ return self;
168
+ }
169
+
170
+ #ifdef HAVE_OCIRESET
171
+ VALUE oci8_reset(VALUE self)
172
+ {
173
+ oci8_handle_t *h;
174
+ sword rv;
175
+
176
+ Get_Handle(self, h); /* 0 */
177
+ rv = OCIReset(h->hp, h->errhp);
178
+ if (rv != OCI_SUCCESS)
179
+ oci8_raise(h->errhp, rv, NULL);
180
+ return self;
181
+ }
182
+ #endif
@@ -0,0 +1,99 @@
1
+ /*
2
+ session.c - part of ruby-oci8
3
+
4
+ Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
5
+
6
+ =begin
7
+ == OCISession
8
+ If you use ((<OCIEnv#logon>)), you have no need to use this handle directly.
9
+ Because ((<OCIEnv#logon>)) create this handle implicitly and set it to ((<OCISvcCtx>)).
10
+
11
+ super class: ((<OCIHandle>))
12
+
13
+ correspond native OCI datatype: ((|OCISession|))
14
+ =end
15
+ */
16
+ #include "oci8.h"
17
+
18
+ /*
19
+ =begin
20
+ --- OCISession#begin(svc [, credt [, mode]])
21
+ start user session under the specified server context.
22
+ :svc
23
+ ((<OCISvcCtx>)).
24
+ :credt
25
+ ((|OCI_CRED_RDBMS|)) or ((|OCI_CRED_EXT|)).
26
+ Default value is ((|OCI_CRED_RDBMS|)).
27
+
28
+ If you use ((|OCI_CRED_RDBMS|)), set ((<OCI_ATTR_USERNAME>))
29
+ and ((<OCI_ATTR_PASSWORD>)) in advance.
30
+
31
+ :mode
32
+ ((|OCI_DEFAULT|)), ((|OCI_MIGRATE|)), ((|OCI_SYSDBA|)), ((|OCI_SYSOPER|)),
33
+ (((|OCI_SYSDBA|)) | ((|OCI_PRELIM_AUTH|))), or (((|OCI_SYSOPER|)) | ((|OCI_PRELIM_AUTH|))).
34
+ Default value is ((|OCI_DEFAULT|)).
35
+
36
+ If you need SYSDBA or SYSOPER privilege, use
37
+ ((|OCI_SYSDBA|)) or ((|OCI_SYSOPER|)) respectively.
38
+
39
+ correspond native OCI function: ((|OCISessionBegin|))
40
+ =end
41
+ */
42
+ static VALUE oci8_session_begin(int argc, VALUE *argv, VALUE self)
43
+ {
44
+ VALUE vsvc, vcredt, vmode;
45
+ oci8_handle_t *h;
46
+ oci8_handle_t *svch;
47
+ ub4 credt;
48
+ ub4 mode;
49
+ sword rv;
50
+
51
+ rb_scan_args(argc, argv, "12", &vsvc, &vcredt, &vmode);
52
+ Get_Handle(self, h); /* 0 */
53
+ Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
54
+ Get_Int_With_Default(argc, 2, vcredt, credt, OCI_NTV_SYNTAX); /* 2 */
55
+ Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */
56
+
57
+ rv = OCISessionBegin(svch->hp, h->errhp, h->hp, credt, mode);
58
+ if (rv != OCI_SUCCESS)
59
+ oci8_raise(h->errhp, rv, NULL);
60
+ return self;
61
+ }
62
+
63
+ /*
64
+ =begin
65
+ --- OCISession#end(svc [, vmode])
66
+ terminate user Authentication Context
67
+
68
+ :svc
69
+ ((<OCISvcCtx>)).
70
+ :mode
71
+ ((|OCI_DEFAULT|)) only valid. Defalt value is ((|OCI_DEFAULT|)).
72
+
73
+ correspond native OCI function: ((|OCISessionEnd|))
74
+ =end
75
+ */
76
+ static VALUE oci8_session_end(int argc, VALUE *argv, VALUE self)
77
+ {
78
+ VALUE vsvc, vmode;
79
+ oci8_handle_t *h;
80
+ oci8_handle_t *svch;
81
+ ub4 mode;
82
+ sword rv;
83
+
84
+ rb_scan_args(argc, argv, "11", &vsvc, &vmode);
85
+ Get_Handle(self, h); /* 0 */
86
+ Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
87
+ Get_Int_With_Default(argc, 2, vmode, mode, OCI_DEFAULT); /* 2 */
88
+
89
+ rv = OCISessionEnd(svch->hp, h->errhp, h->hp, mode);
90
+ if (rv != OCI_SUCCESS)
91
+ oci8_raise(h->errhp, rv, NULL);
92
+ return self;
93
+ }
94
+
95
+ void Init_oci8_session(void)
96
+ {
97
+ rb_define_method(cOCISession, "begin", oci8_session_begin, -1);
98
+ rb_define_method(cOCISession, "end", oci8_session_end, -1);
99
+ }
@@ -0,0 +1,624 @@
1
+ /*
2
+ stmt.c - part of ruby-oci8
3
+ implement the methods of OCIStmt.
4
+
5
+ Copyright (C) 2002-2006 KUBO Takehiro <kubo@jiubao.org>
6
+
7
+ =begin
8
+ == OCIStmt
9
+ Statemet handle identify a SQL or PL/SQL statement and its associated attributes.
10
+
11
+ Information about SQL or PL/SQL's input/output variables is managed by the
12
+ ((<bind handle|OCIBind>)). Fetched data of select statement is managed by the
13
+ ((<define handle|OCIDefine>)).
14
+
15
+ super class: ((<OCIHandle>))
16
+
17
+ correspond native OCI datatype: ((|OCIStmt|))
18
+ =end
19
+ */
20
+ #include "oci8.h"
21
+
22
+ static ID id_alloc;
23
+
24
+ static void check_bind_type(ub4 type, oci8_handle_t *stmth, VALUE vtype, VALUE vlength, oci8_bind_handle_t **bhp, ub2 *dty)
25
+ {
26
+ enum oci8_bind_type bind_type;
27
+ oci8_bind_handle_t *bh;
28
+ sb4 value_sz;
29
+ VALUE klass = Qnil;
30
+
31
+ if (TYPE(vtype) == T_FIXNUM) {
32
+ switch (FIX2INT(vtype)) {
33
+ case SQLT_CHR: /* OCI_TYPECODE_VARCHAR */
34
+ bind_type = BIND_STRING;
35
+ *dty = SQLT_LVC;
36
+ if (NIL_P(vlength))
37
+ rb_raise(rb_eArgError, "the length of String is not specified.");
38
+ value_sz = NUM2INT(vlength) + 4;
39
+ if (value_sz < 5)
40
+ value_sz = 5; /* at least 5 bytes */
41
+ break;
42
+ case SQLT_LVB: /* OCI_TYPECODE_RAW */
43
+ case SQLT_BIN: /* OCI_TYPECODE_UNSIGNED8 */
44
+ bind_type = BIND_STRING;
45
+ *dty = SQLT_LVB;
46
+ if (NIL_P(vlength))
47
+ rb_raise(rb_eArgError, "the length of String is not specified.");
48
+ value_sz = NUM2INT(vlength) + 4;
49
+ if (value_sz < 5)
50
+ value_sz = 5; /* at least 5 bytes */
51
+ break;
52
+ case SQLT_DAT:
53
+ bind_type = BIND_ORA_DATE;
54
+ *dty = SQLT_DAT;
55
+ value_sz = sizeof(ora_date_t);
56
+ break;
57
+ case SQLT_CLOB: /* OCI_TYPECODE_CLOB */
58
+ case SQLT_BLOB: /* OCI_TYPECODE_BLOB */
59
+ bind_type = BIND_HANDLE;
60
+ *dty = FIX2INT(vtype);
61
+ value_sz = sizeof(bh->value.handle);
62
+ klass = cOCILobLocator;
63
+ break;
64
+ case SQLT_BFILE:
65
+ case SQLT_CFILE:
66
+ bind_type = BIND_HANDLE;
67
+ *dty = FIX2INT(vtype);
68
+ value_sz = sizeof(bh->value.handle);
69
+ klass = cOCIFileLocator;
70
+ break;
71
+ case SQLT_RDD:
72
+ bind_type = BIND_HANDLE;
73
+ *dty = SQLT_RDD;
74
+ value_sz = sizeof(bh->value.handle);
75
+ klass = cOCIRowid;
76
+ break;
77
+ case SQLT_RSET:
78
+ bind_type = BIND_HANDLE;
79
+ *dty = SQLT_RSET;
80
+ value_sz = sizeof(bh->value.handle);
81
+ klass = cOCIStmt;
82
+ break;
83
+ #ifdef SQLT_IBDOUBLE
84
+ case SQLT_IBDOUBLE:
85
+ bind_type = BIND_FLOAT;
86
+ *dty = SQLT_BDOUBLE;
87
+ value_sz = sizeof(double);
88
+ break;
89
+ #endif
90
+ default:
91
+ rb_raise(rb_eArgError, "Not supported type (%d)", FIX2INT(vtype));
92
+ }
93
+ } else if (vtype == rb_cFixnum) {
94
+ bind_type = BIND_FIXNUM;
95
+ *dty = SQLT_INT;
96
+ value_sz = sizeof(long);
97
+ } else if (vtype == rb_cInteger || vtype == rb_cBignum) {
98
+ bind_type = BIND_INTEGER_VIA_ORA_NUMBER;
99
+ *dty = SQLT_NUM;
100
+ value_sz = sizeof(ora_number_t);
101
+ } else if (vtype == rb_cTime) {
102
+ bind_type = BIND_TIME_VIA_ORA_DATE;
103
+ *dty = SQLT_DAT;
104
+ value_sz = sizeof(ora_date_t);
105
+ } else if (vtype == rb_cString) {
106
+ bind_type = BIND_STRING;
107
+ *dty = SQLT_LVC;
108
+ if (NIL_P(vlength))
109
+ rb_raise(rb_eArgError, "the length of String is not specified.");
110
+ value_sz = NUM2INT(vlength) + 4;
111
+ if (value_sz < 5)
112
+ value_sz = 5; /* at least 5 bytes */
113
+ } else if (vtype == rb_cFloat) {
114
+ bind_type = BIND_FLOAT;
115
+ *dty = SQLT_FLT;
116
+ value_sz = sizeof(double);
117
+ } else if (vtype == cOraDate) {
118
+ bind_type = BIND_ORA_DATE;
119
+ *dty = SQLT_DAT;
120
+ value_sz = sizeof(ora_date_t);
121
+ } else if (vtype == cOraNumber) {
122
+ bind_type = BIND_ORA_NUMBER;
123
+ *dty = SQLT_NUM;
124
+ value_sz = sizeof(ora_number_t);
125
+ } else {
126
+ if (SYMBOL_P(vtype)) {
127
+ rb_raise(rb_eArgError, "Not supported type (:%s)", rb_id2name(SYM2ID(vtype)));
128
+ } else {
129
+ rb_raise(rb_eArgError, "Not supported type (%s)", rb_class2name(vtype));
130
+ }
131
+ }
132
+ bh = (oci8_bind_handle_t *)oci8_make_handle(type, NULL, NULL, stmth, value_sz);
133
+ bh->bind_type = bind_type;
134
+ if (bind_type == BIND_HANDLE) {
135
+ if (NIL_P(vlength)) {
136
+ oci8_handle_t *envh;
137
+ for (envh = stmth; envh->type != OCI_HTYPE_ENV; envh = envh->parent);
138
+ vlength = rb_funcall(envh->self, id_alloc, 1, klass);
139
+ }
140
+ bh->value.handle.klass = klass;
141
+ oci8_set_value(bh, vlength);
142
+ }
143
+ *bhp = bh;
144
+ }
145
+
146
+ static VALUE oci8_each_value(VALUE hash)
147
+ {
148
+ return rb_funcall(hash, rb_intern("each_value"), 0);
149
+ }
150
+
151
+ /*
152
+ =begin
153
+ --- OCIStmt#prepare(stmt [, language [, mode]])
154
+ set and prepare SQL statement.
155
+
156
+ :stmt
157
+ SQL or PL/SQL statement
158
+ :language
159
+ ((|OCI_NTV_SYNTAX|)), ((|OCI_V7_SYNTAX|)), or ((|OCI_V8_SYNTAX|)).
160
+ Default value is ((|OCI_NTV_SYNTAX|))
161
+ :mode
162
+ ((|OCI_DEFAULT|)) or ((|OCI_NO_SHARING|)). Default value is ((|OCI_DEFAULT|)).
163
+
164
+ ((|OCI_NO_SHARING|)) disables ((<Shared Data Mode>)) for this statement.
165
+
166
+ correspond native OCI function: ((|OCIStmtPrepare|))
167
+ =end
168
+ */
169
+ static VALUE oci8_stmt_prepare(int argc, VALUE *argv, VALUE self)
170
+ {
171
+ VALUE vsql, vlanguage, vmode;
172
+ oci8_handle_t *h;
173
+ oci8_string_t s;
174
+ ub4 language;
175
+ ub4 mode;
176
+ sword rv;
177
+ VALUE ary;
178
+ VALUE hash;
179
+ int i;
180
+
181
+ rb_scan_args(argc, argv, "12", &vsql, &vlanguage, &vmode);
182
+ Get_Handle(self, h); /* 0 */
183
+ Get_String(vsql, s); /* 1 */
184
+ Get_Int_With_Default(argc, 2, vlanguage, language, OCI_NTV_SYNTAX); /* 2 */
185
+ Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */
186
+
187
+ /* when a new statement is prepared, OCI implicitly free the previous
188
+ * statement's define and bind handles.
189
+ * But ruby's object don't know it. So free these handles in advance.
190
+ */
191
+ /* free define handles */
192
+ ary = rb_ivar_get(self, oci8_id_define_array);
193
+ if (ary != Qnil) {
194
+ for (i = 0;i < RARRAY_LEN(ary);i++) {
195
+ if (RARRAY_PTR(ary)[i] != Qnil)
196
+ oci8_handle_free(RARRAY_PTR(ary)[i]);
197
+ }
198
+ rb_ivar_set(self, oci8_id_define_array, Qnil);
199
+ }
200
+ /* free bind handles */
201
+ hash = rb_ivar_get(self, oci8_id_bind_hash);
202
+ if (hash != Qnil) {
203
+ rb_iterate(oci8_each_value, hash, oci8_handle_free, Qnil);
204
+ rb_ivar_set(self, oci8_id_bind_hash, Qnil);
205
+ }
206
+
207
+ rv = OCIStmtPrepare(h->hp, h->errhp, s.ptr, s.len, language, mode);
208
+ if (IS_OCI_ERROR(rv)) {
209
+ oci8_raise(h->errhp, rv, h->hp);
210
+ }
211
+ return self;
212
+ }
213
+
214
+ /*
215
+ =begin
216
+ --- OCIStmt#defineByPos(position, type [, length [, mode]])
217
+ define the datatype of fetched column.
218
+ You must define all column's datatype, before you fetch data.
219
+
220
+ :position
221
+ the position of the column. It starts from 1.
222
+ :type
223
+ the type of column.
224
+ ((|String|)), ((|Fixnum|)), ((|Integer|)), ((|Float|)), ((|Time|)),
225
+ ((<OraDate>)), ((<OraNumber>)), or ((|OCI_TYPECODE_RAW|))
226
+ :length
227
+ When the 2nd argument is
228
+ * ((|String|)) or ((|OCI_TYPECODE_RAW|)),
229
+ the max length of fetched data.
230
+ * otherwise,
231
+ its value is ignored.
232
+ :mode
233
+ ((|OCI_DEFAULT|)), or ((|OCI_DYNAMIC_FETCH|)). But now available value is
234
+ ((|OCI_DEFAULT|)) only. Default value is ((|OCI_DEFAULT|))
235
+ :return value
236
+ newly created ((<define handle|OCIDefine>))
237
+
238
+ correspond native OCI function: ((|OCIDefineByPos|))
239
+ =end
240
+ */
241
+ static VALUE oci8_define_by_pos(int argc, VALUE *argv, VALUE self)
242
+ {
243
+ VALUE vposition;
244
+ VALUE vtype;
245
+ VALUE vlength;
246
+ VALUE vmode;
247
+ oci8_handle_t *h;
248
+ ub4 position;
249
+ oci8_bind_handle_t *bh;
250
+ ub2 dty;
251
+ ub4 mode;
252
+ dvoid *indp;
253
+ ub2 *rlenp;
254
+ dvoid *valuep;
255
+ OCIDefine *dfnhp = NULL;
256
+ sword status;
257
+ VALUE ary;
258
+ VALUE obj;
259
+
260
+ rb_scan_args(argc, argv, "22", &vposition, &vtype, &vlength, &vmode);
261
+ Get_Handle(self, h); /* 0 */
262
+ position = NUM2INT(vposition); /* 1 */
263
+ check_bind_type(OCI_HTYPE_DEFINE, h, vtype, vlength, &bh, &dty); /* 2, 3 */
264
+ Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */
265
+
266
+ if (mode & OCI_DYNAMIC_FETCH) {
267
+ indp = NULL;
268
+ rlenp = NULL;
269
+ } else {
270
+ indp = &(bh->ind);
271
+ rlenp = (bh->bind_type == BIND_STRING) ? NULL : &bh->rlen;
272
+ }
273
+ valuep = &bh->value;
274
+ status = OCIDefineByPos(h->hp, &dfnhp, h->errhp, position, valuep, bh->value_sz, dty, indp, rlenp, 0, mode);
275
+ if (status != OCI_SUCCESS) {
276
+ oci8_unlink((oci8_handle_t *)bh);
277
+ bh->type = 0;
278
+ oci8_raise(h->errhp, status, h->hp);
279
+ }
280
+ bh->type = OCI_HTYPE_DEFINE;
281
+ bh->hp = dfnhp;
282
+ bh->errhp = h->errhp;
283
+ obj = bh->self;
284
+ ary = rb_ivar_get(self, oci8_id_define_array);
285
+ if (ary == Qnil) {
286
+ ary = rb_ary_new();
287
+ rb_ivar_set(self, oci8_id_define_array, ary);
288
+ }
289
+ rb_ary_store(ary, position - 1, obj);
290
+ return obj;
291
+ }
292
+
293
+ /*
294
+ =begin
295
+ --- OCIStmt#bindByPos(position, type [, length [, mode]])
296
+ define the datatype of the bind variable by posision.
297
+
298
+ :position
299
+ the position of the bind variable.
300
+ :type
301
+ the type of the bind variable.
302
+ ((|String|)), ((|Fixnum|)), ((|Integer|)), ((|Float|)), ((|Time|)),
303
+ ((<OraDate>)), ((<OraNumber>)), or ((|OCI_TYPECODE_RAW|))
304
+ :length
305
+ When the 2nd argument is
306
+ * ((|String|)) or ((|OCI_TYPECODE_RAW|)),
307
+ the max length of fetched data.
308
+ * otherwise,
309
+ its value is ignored.
310
+ :mode
311
+ ((|OCI_DEFAULT|)), or ((|OCI_DATA_AT_EXEC|)). But now available value is
312
+ ((|OCI_DEFAULT|)) only. Default value is ((|OCI_DEFAULT|))
313
+ :return value
314
+ newly created ((<bind handle|OCIBind>))
315
+
316
+ correspond native OCI function: ((|OCIBindByPos|))
317
+ =end
318
+ */
319
+ static VALUE oci8_bind_by_pos(int argc, VALUE *argv, VALUE self)
320
+ {
321
+ VALUE vposition;
322
+ VALUE vtype;
323
+ VALUE vlength;
324
+ VALUE vmode;
325
+ oci8_handle_t *h;
326
+ ub4 position;
327
+ oci8_bind_handle_t *bh;
328
+ ub2 dty;
329
+ ub4 mode;
330
+ dvoid *indp;
331
+ ub2 *rlenp;
332
+ dvoid *valuep;
333
+ OCIBind *bindhp = NULL;
334
+ sword status;
335
+ VALUE hash;
336
+ VALUE obj;
337
+
338
+ rb_scan_args(argc, argv, "22", &vposition, &vtype, &vlength, &vmode);
339
+ Get_Handle(self, h); /* 0 */
340
+ position = NUM2INT(vposition); /* 1 */
341
+ check_bind_type(OCI_HTYPE_BIND, h, vtype, vlength, &bh, &dty); /* 2, 3 */
342
+ Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */
343
+
344
+ if (mode & OCI_DATA_AT_EXEC) {
345
+ indp = NULL;
346
+ rlenp = NULL;
347
+ } else {
348
+ indp = &(bh->ind);
349
+ rlenp = (bh->bind_type == BIND_STRING) ? NULL : &bh->rlen;
350
+ }
351
+ valuep = &bh->value;
352
+ status = OCIBindByPos(h->hp, &bindhp, h->errhp, position, valuep, bh->value_sz, dty, indp, rlenp, 0, 0, 0, mode);
353
+ if (status != OCI_SUCCESS) {
354
+ oci8_unlink((oci8_handle_t *)bh);
355
+ bh->type = 0;
356
+ oci8_raise(h->errhp, status, h->hp);
357
+ }
358
+ bh->type = OCI_HTYPE_BIND;
359
+ bh->hp = bindhp;
360
+ bh->errhp = h->errhp;
361
+ obj = bh->self;
362
+ hash = rb_ivar_get(self, oci8_id_bind_hash);
363
+ if (hash == Qnil) {
364
+ hash = rb_hash_new();
365
+ rb_ivar_set(self, oci8_id_bind_hash, hash);
366
+ }
367
+ rb_hash_aset(hash, vposition, obj);
368
+ return obj;
369
+ }
370
+
371
+ /*
372
+ =begin
373
+ --- OCIStmt#bindByName(name, type [, length [, mode]])
374
+ define the datatype of the bind variable by name.
375
+
376
+ :name
377
+ the name of the bind variable including colon.
378
+ :type
379
+ the type of the bind variable.
380
+ ((|String|)), ((|Fixnum|)), ((|Integer|)), ((|Float|)), ((|Time|)),
381
+ ((<OraDate>)), ((<OraNumber>)), or ((|OCI_TYPECODE_RAW|))
382
+ :length
383
+ When the 2nd argument is
384
+ * ((|String|)) or ((|OCI_TYPECODE_RAW|)),
385
+ the max length of fetched data.
386
+ * otherwise,
387
+ its value is ignored.
388
+ :mode
389
+ ((|OCI_DEFAULT|)), or ((|OCI_DATA_AT_EXEC|)). But now available value is
390
+ ((|OCI_DEFAULT|)) only. Default value is ((|OCI_DEFAULT|))
391
+ :return value
392
+ newly created ((<bind handle|OCIBind>))
393
+
394
+ for example
395
+ stmt = env.alloc(OCIStmt)
396
+ stmt.prepare("SELECT * FROM EMP
397
+ WHERE ename = :ENAME
398
+ AND sal > :SAL
399
+ AND hiredate >= :HIREDATE")
400
+ b_ename = stmt.bindByName(":ENAME", String, 10)
401
+ b_sal = stmt.bindByName(":SAL", Fixnum)
402
+ b_hiredate = stmt.bindByName(":HIREDATE", OraDate)
403
+
404
+ correspond native OCI function: ((|OCIBindByName|))
405
+ =end
406
+ */
407
+ static VALUE oci8_bind_by_name(int argc, VALUE *argv, VALUE self)
408
+ {
409
+ VALUE vplaceholder;
410
+ VALUE vtype;
411
+ VALUE vlength;
412
+ VALUE vmode;
413
+ oci8_handle_t *h;
414
+ oci8_string_t placeholder;
415
+ oci8_bind_handle_t *bh;
416
+ ub2 dty;
417
+ ub4 mode;
418
+ dvoid *indp;
419
+ ub2 *rlenp;
420
+ dvoid *valuep;
421
+ OCIBind *bindhp = NULL;
422
+ sword status;
423
+ VALUE hash;
424
+ VALUE obj;
425
+
426
+ rb_scan_args(argc, argv, "22", &vplaceholder, &vtype, &vlength, &vmode);
427
+ Get_Handle(self, h); /* 0 */
428
+ Get_String(vplaceholder, placeholder); /* 1 */
429
+ check_bind_type(OCI_HTYPE_BIND, h, vtype, vlength, &bh, &dty); /* 2, 3 */
430
+ Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */
431
+
432
+ if (mode & OCI_DATA_AT_EXEC) {
433
+ indp = NULL;
434
+ rlenp = NULL;
435
+ } else {
436
+ indp = &(bh->ind);
437
+ rlenp = (bh->bind_type == BIND_STRING) ? NULL : &bh->rlen;
438
+ }
439
+ valuep = &bh->value;
440
+ status = OCIBindByName(h->hp, &bindhp, h->errhp, placeholder.ptr, placeholder.len, valuep, bh->value_sz, dty, indp, rlenp, 0, 0, 0, mode);
441
+ if (status != OCI_SUCCESS) {
442
+ oci8_unlink((oci8_handle_t *)bh);
443
+ bh->type = 0;
444
+ oci8_raise(h->errhp, status, h->hp);
445
+ }
446
+ bh->type = OCI_HTYPE_BIND;
447
+ bh->hp = bindhp;
448
+ bh->errhp = h->errhp;
449
+ obj = bh->self;
450
+ hash = rb_ivar_get(self, oci8_id_bind_hash);
451
+ if (hash == Qnil) {
452
+ hash = rb_hash_new();
453
+ rb_ivar_set(self, oci8_id_bind_hash, hash);
454
+ }
455
+ rb_hash_aset(hash, vplaceholder, obj);
456
+ return obj;
457
+ }
458
+
459
+ /*
460
+ =begin
461
+ --- OCIStmt#execute(svc [, iters [, mode]])
462
+ execute statement at the ((<service context handle|OCISvcCtx>)).
463
+
464
+ :svc
465
+ ((<service context handle|OCISvcCtx>))
466
+ :iters
467
+ the number of iterations to execute.
468
+
469
+ For select statement, if there are columns which is not defined
470
+ by ((<OCIStmt#defineByPos>)) and this value is positive, it
471
+ raises exception. If zero, no exception. In any case you must define
472
+ all columns before you call ((<OCIStmt#fetch>)).
473
+
474
+ For non-select statement, use positive value.
475
+
476
+ Default value is 0 for select statement, 1 for non-select statement.
477
+
478
+ note: Current implemantation doesn't support array fetch and batch mode, so
479
+ valid value is 0 or 1.
480
+ :mode
481
+ ((|OCI_DEFAULT|)), ((|OCI_BATCH_ERRORS|)), ((|OCI_COMMIT_ON_SUCCESS|)),
482
+ ((|OCI_DESCRIBE_ONLY|)), ((|OCI_EXACT_FETCH|)), ((|OCI_PARSE_ONLY|)),
483
+ any combinations of previous values, or ((|OCI_STMT_SCROLLABLE_READONLY|)).
484
+ Default value is ((|OCI_DEFAULT|)).
485
+
486
+ ((|OCI_BATCH_ERRORS|)) and ((|OCI_STMT_SCROLLABLE_READONLY|)) are not
487
+ supported by current implementation.
488
+
489
+ correspond native OCI function: ((|OCIStmtExecute|))
490
+ =end
491
+ */
492
+ static VALUE oci8_stmt_execute(int argc, VALUE *argv, VALUE self)
493
+ {
494
+ VALUE vsvc;
495
+ VALUE viters;
496
+ VALUE vmode;
497
+ oci8_handle_t *h;
498
+ oci8_handle_t *svch;
499
+ ub4 mode;
500
+ ub4 iters;
501
+ ub2 stmt_type;
502
+ sword rv;
503
+
504
+ rb_scan_args(argc, argv, "12", &vsvc, &viters, &vmode);
505
+ Get_Handle(self, h); /* 0 */
506
+ Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
507
+ if (argc >= 2) {
508
+ iters = NUM2UINT(viters); /* 2 */
509
+ } else {
510
+ rv = OCIAttrGet(h->hp, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, h->errhp);
511
+ if (rv != OCI_SUCCESS) {
512
+ oci8_raise(h->errhp, rv, h->hp);
513
+ }
514
+ if (stmt_type == OCI_STMT_SELECT) {
515
+ /* for select statement, default value 0. */
516
+ iters = 0;
517
+ } else {
518
+ /* for non-select statement, default value 0. */
519
+ iters = 1;
520
+ }
521
+ }
522
+ Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */
523
+
524
+ if (iters > 1) {
525
+ rb_raise(rb_eArgError, "current implementation doesn't support array fatch or batch mode");
526
+ }
527
+
528
+ rv = OCIStmtExecute(svch->hp, h->hp, h->errhp, iters, 0, NULL, NULL, mode);
529
+ if (rv == OCI_ERROR) {
530
+ sb4 errcode;
531
+ OCIErrorGet(h->errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
532
+ if (errcode == 1000) {
533
+ /* run GC to close unreferred cursors when ORA-01000 (maximum open cursors exceeded). */
534
+ rb_gc();
535
+ rv = OCIStmtExecute(svch->hp, h->hp, h->errhp, iters, 0, NULL, NULL, mode);
536
+ }
537
+ }
538
+ if (IS_OCI_ERROR(rv)) {
539
+ oci8_raise(h->errhp, rv, h->hp);
540
+ }
541
+ return self;
542
+ }
543
+
544
+ /*
545
+ =begin
546
+ --- OCIStmt#fetch([nrows [, orientation [, mode]]])
547
+ fetch data from select statement.
548
+ fetched data are stored to previously defined ((<define handle|OCIDefine>)).
549
+
550
+ :nrows
551
+ number of rows to fetch. If zero, cancel the cursor.
552
+ The default value is 1.
553
+
554
+ Because array fetch is not supported, valid value is 0 or 1.
555
+
556
+ :orientation
557
+ orientation to fetch. ((|OCI_FETCH_NEXT|)) only valid.
558
+ The default value is ((|OCI_FETCH_NEXT|)).
559
+
560
+ :mode
561
+ ((|OCI_DEFULT|)) only valid.
562
+ The default value is ((|OCI_DEFAULT|)).
563
+
564
+ :return value
565
+ array of define handles, which are defined previously,
566
+ or nil when end of data.
567
+
568
+ correspond native OCI function: ((|OCIStmtFetch|))
569
+ =end
570
+ */
571
+ static VALUE oci8_stmt_fetch(int argc, VALUE *argv, VALUE self)
572
+ {
573
+ VALUE vnrows;
574
+ VALUE vorientation;
575
+ VALUE vmode;
576
+ oci8_handle_t *h;
577
+ ub4 nrows;
578
+ ub2 orientation;
579
+ ub4 mode;
580
+ sword rv;
581
+
582
+ rb_scan_args(argc, argv, "03", &vnrows, &vorientation, &vmode);
583
+ Get_Handle(self, h); /* 0 */
584
+ Get_Int_With_Default(argc, 1, vnrows, nrows, 1); /* 1 */
585
+ Get_Int_With_Default(argc, 2, vorientation, orientation, OCI_FETCH_NEXT); /* 2 */
586
+ Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */
587
+
588
+ rv = OCIStmtFetch(h->hp, h->errhp, nrows, orientation, mode);
589
+ if (rv == OCI_NO_DATA) {
590
+ return Qnil;
591
+ }
592
+ if (IS_OCI_ERROR(rv)) {
593
+ oci8_raise(h->errhp, rv, h->hp);
594
+ }
595
+ return rb_ivar_get(self, oci8_id_define_array);
596
+ }
597
+
598
+ /*
599
+ implemented in param.c
600
+ =begin
601
+ --- OCIStmt#paramGet(position)
602
+ get column information of executed select statement.
603
+ See ((<Select a table whose column types are unknown.>))
604
+
605
+ :posision
606
+ the position of the column to get parameter. It starts from 1.
607
+ :return value
608
+ newly created ((<read-only parameter descriptor|OCIParam>))
609
+
610
+ correspond native OCI function: ((|OCIParamGet|))
611
+ =end
612
+ */
613
+
614
+ void Init_oci8_stmt(void)
615
+ {
616
+ id_alloc = rb_intern("alloc");
617
+ rb_define_method(cOCIStmt, "prepare", oci8_stmt_prepare, -1);
618
+ rb_define_method(cOCIStmt, "defineByPos", oci8_define_by_pos, -1);
619
+ rb_define_method(cOCIStmt, "bindByPos", oci8_bind_by_pos, -1);
620
+ rb_define_method(cOCIStmt, "bindByName", oci8_bind_by_name, -1);
621
+ rb_define_method(cOCIStmt, "execute", oci8_stmt_execute, -1);
622
+ rb_define_method(cOCIStmt, "fetch", oci8_stmt_fetch, -1);
623
+ rb_define_method(cOCIStmt, "paramGet", oci8_param_get, 1);
624
+ }