ruby-oci8 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }