activerecord-jdbc-adapter 0.6 → 0.7
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/History.txt +46 -27
- data/Manifest.txt +7 -4
- data/Rakefile +6 -5
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +93 -108
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_derby.rb +1 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +1 -1
- data/lib/jdbc_adapter/jdbc_mysql.rb +55 -13
- data/lib/jdbc_adapter/version.rb +1 -1
- data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +1113 -0
- data/src/java/jdbc_adapter/JdbcConnectionFactory.java +36 -0
- data/src/java/{JDBCDerbySpec.java → jdbc_adapter/JdbcDerbySpec.java} +95 -91
- data/src/java/{JDBCMySQLSpec.java → jdbc_adapter/JdbcMySQLSpec.java} +24 -27
- data/src/java/jdbc_adapter/SQLBlock.java +18 -0
- data/test/has_many_through.rb +72 -0
- data/test/jdbc_common.rb +1 -0
- data/test/mysql_simple_test.rb +4 -0
- data/test/simple.rb +36 -1
- metadata +9 -6
- data/lib/jdbc_adapter_internal.jar +0 -0
- data/src/java/JdbcAdapterInternalService.java +0 -953
data/test/jdbc_common.rb
CHANGED
data/test/mysql_simple_test.rb
CHANGED
data/test/simple.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
ActiveRecord::Schema.verbose = false
|
2
|
+
|
1
3
|
module MigrationSetup
|
2
4
|
def setup
|
3
5
|
CreateEntries.up
|
@@ -110,9 +112,42 @@ module SimpleTestMethods
|
|
110
112
|
|
111
113
|
def test_invalid
|
112
114
|
e = Entry.new(:title => @title, :content => @content, :rating => ' ')
|
113
|
-
|
115
|
+
assert e.valid?
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_reconnect
|
119
|
+
assert_equal 1, Entry.count
|
120
|
+
@connection.reconnect!
|
121
|
+
assert_equal 1, Entry.count
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_connection_valid
|
125
|
+
assert_raises(ActiveRecord::ActiveRecordError) do
|
126
|
+
@connection.raw_connection.with_connection_retry_guard do |c|
|
127
|
+
begin
|
128
|
+
stmt = c.createStatement
|
129
|
+
stmt.execute "bogus sql"
|
130
|
+
ensure
|
131
|
+
stmt.close rescue nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
114
135
|
end
|
115
136
|
|
137
|
+
def test_disconnect
|
138
|
+
assert_equal 1, Entry.count
|
139
|
+
ActiveRecord::Base.clear_active_connections!
|
140
|
+
assert !ActiveRecord::Base.connected?
|
141
|
+
assert_equal 1, Entry.count
|
142
|
+
assert ActiveRecord::Base.connected?
|
143
|
+
end
|
144
|
+
|
145
|
+
class Animal < ActiveRecord::Base; end
|
146
|
+
def test_fetching_columns_for_nonexistent_table_should_raise
|
147
|
+
assert_raises(ActiveRecord::ActiveRecordError) do
|
148
|
+
Animal.columns
|
149
|
+
end
|
150
|
+
end
|
116
151
|
end
|
117
152
|
|
118
153
|
module MultibyteTestMethods
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: activerecord-jdbc-adapter
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2007-12-
|
6
|
+
version: "0.7"
|
7
|
+
date: 2007-12-15 00:00:00 -06:00
|
8
8
|
summary: JDBC adapter for ActiveRecord, for use within JRuby on Rails.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- lib/jdbc_adapter/missing_functionality_helper.rb
|
56
56
|
- lib/jdbc_adapter/version.rb
|
57
57
|
- lib/jdbc_adapter.rb
|
58
|
-
- lib/jdbc_adapter_internal.jar
|
58
|
+
- lib/jdbc_adapter/jdbc_adapter_internal.jar
|
59
59
|
- test/activerecord/connection_adapters/type_conversion_test.rb
|
60
60
|
- test/activerecord/connections/native_jdbc_mysql/connection.rb
|
61
61
|
- test/db/derby.rb
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- test/derby_simple_test.rb
|
71
71
|
- test/generic_jdbc_connection_test.rb
|
72
72
|
- test/h2_simple_test.rb
|
73
|
+
- test/has_many_through.rb
|
73
74
|
- test/hsqldb_simple_test.rb
|
74
75
|
- test/jdbc_adapter/jdbc_db2_test.rb
|
75
76
|
- test/jdbc_common.rb
|
@@ -90,9 +91,11 @@ files:
|
|
90
91
|
- test/postgres_simple_test.rb
|
91
92
|
- test/simple.rb
|
92
93
|
- lib/tasks/jdbc_databases.rake
|
93
|
-
- src/java/JdbcAdapterInternalService.java
|
94
|
-
- src/java/
|
95
|
-
- src/java/
|
94
|
+
- src/java/jdbc_adapter/JdbcAdapterInternalService.java
|
95
|
+
- src/java/jdbc_adapter/JdbcConnectionFactory.java
|
96
|
+
- src/java/jdbc_adapter/JdbcDerbySpec.java
|
97
|
+
- src/java/jdbc_adapter/JdbcMySQLSpec.java
|
98
|
+
- src/java/jdbc_adapter/SQLBlock.java
|
96
99
|
test_files: []
|
97
100
|
|
98
101
|
rdoc_options:
|
Binary file
|
@@ -1,953 +0,0 @@
|
|
1
|
-
/***** BEGIN LICENSE BLOCK *****
|
2
|
-
* Version: CPL 1.0/GPL 2.0/LGPL 2.1
|
3
|
-
*
|
4
|
-
* The contents of this file are subject to the Common Public
|
5
|
-
* License Version 1.0 (the "License"); you may not use this file
|
6
|
-
* except in compliance with the License. You may obtain a copy of
|
7
|
-
* the License at http://www.eclipse.org/legal/cpl-v10.html
|
8
|
-
*
|
9
|
-
* Software distributed under the License is distributed on an "AS
|
10
|
-
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
11
|
-
* implied. See the License for the specific language governing
|
12
|
-
* rights and limitations under the License.
|
13
|
-
*
|
14
|
-
* Copyright (C) 2007 Ola Bini <ola@ologix.com>
|
15
|
-
*
|
16
|
-
* Alternatively, the contents of this file may be used under the terms of
|
17
|
-
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
18
|
-
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
19
|
-
* in which case the provisions of the GPL or the LGPL are applicable instead
|
20
|
-
* of those above. If you wish to allow use of your version of this file only
|
21
|
-
* under the terms of either the GPL or the LGPL, and not to allow others to
|
22
|
-
* use your version of this file under the terms of the CPL, indicate your
|
23
|
-
* decision by deleting the provisions above and replace them with the notice
|
24
|
-
* and other provisions required by the GPL or the LGPL. If you do not delete
|
25
|
-
* the provisions above, a recipient may use your version of this file under
|
26
|
-
* the terms of any one of the CPL, the GPL or the LGPL.
|
27
|
-
***** END LICENSE BLOCK *****/
|
28
|
-
import java.io.IOException;
|
29
|
-
import java.io.Reader;
|
30
|
-
import java.io.InputStream;
|
31
|
-
import java.io.ByteArrayInputStream;
|
32
|
-
import java.io.StringReader;
|
33
|
-
|
34
|
-
import java.sql.Connection;
|
35
|
-
import java.sql.DatabaseMetaData;
|
36
|
-
import java.sql.PreparedStatement;
|
37
|
-
import java.sql.ResultSetMetaData;
|
38
|
-
import java.sql.ResultSet;
|
39
|
-
import java.sql.SQLException;
|
40
|
-
import java.sql.Statement;
|
41
|
-
import java.sql.PreparedStatement;
|
42
|
-
import java.sql.Timestamp;
|
43
|
-
import java.sql.Types;
|
44
|
-
|
45
|
-
import java.text.DateFormat;
|
46
|
-
import java.text.SimpleDateFormat;
|
47
|
-
|
48
|
-
import java.util.ArrayList;
|
49
|
-
import java.util.Calendar;
|
50
|
-
import java.util.Date;
|
51
|
-
import java.util.List;
|
52
|
-
import java.util.Map;
|
53
|
-
import java.util.Iterator;
|
54
|
-
import java.util.HashMap;
|
55
|
-
|
56
|
-
import org.jruby.Ruby;
|
57
|
-
import org.jruby.RubyArray;
|
58
|
-
import org.jruby.RubyBigDecimal;
|
59
|
-
import org.jruby.RubyClass;
|
60
|
-
import org.jruby.RubyHash;
|
61
|
-
import org.jruby.RubyModule;
|
62
|
-
import org.jruby.RubyNumeric;
|
63
|
-
import org.jruby.RubyObject;
|
64
|
-
import org.jruby.RubyString;
|
65
|
-
import org.jruby.RubySymbol;
|
66
|
-
import org.jruby.RubyTime;
|
67
|
-
import org.jruby.javasupport.JavaObject;
|
68
|
-
import org.jruby.runtime.Arity;
|
69
|
-
import org.jruby.runtime.Block;
|
70
|
-
import org.jruby.runtime.CallbackFactory;
|
71
|
-
import org.jruby.runtime.ThreadContext;
|
72
|
-
import org.jruby.runtime.builtin.IRubyObject;
|
73
|
-
import org.jruby.runtime.load.BasicLibraryService;
|
74
|
-
import org.jruby.util.ByteList;
|
75
|
-
|
76
|
-
public class JdbcAdapterInternalService implements BasicLibraryService {
|
77
|
-
public boolean basicLoad(final Ruby runtime) throws IOException {
|
78
|
-
RubyClass cJdbcConn = ((RubyModule)(runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).
|
79
|
-
defineClassUnder("JdbcConnection",runtime.getObject(),runtime.getObject().getAllocator());
|
80
|
-
|
81
|
-
CallbackFactory cf = runtime.callbackFactory(JdbcAdapterInternalService.class);
|
82
|
-
cJdbcConn.defineMethod("unmarshal_result",cf.getSingletonMethod("unmarshal_result", IRubyObject.class));
|
83
|
-
cJdbcConn.defineFastMethod("set_connection",cf.getFastSingletonMethod("set_connection", IRubyObject.class));
|
84
|
-
cJdbcConn.defineFastMethod("execute_update",cf.getFastSingletonMethod("execute_update", IRubyObject.class));
|
85
|
-
cJdbcConn.defineFastMethod("execute_query",cf.getFastOptSingletonMethod("execute_query"));
|
86
|
-
cJdbcConn.defineFastMethod("execute_insert",cf.getFastSingletonMethod("execute_insert", IRubyObject.class));
|
87
|
-
cJdbcConn.defineFastMethod("execute_id_insert",cf.getFastSingletonMethod("execute_id_insert", IRubyObject.class, IRubyObject.class));
|
88
|
-
cJdbcConn.defineFastMethod("primary_keys",cf.getFastSingletonMethod("primary_keys", IRubyObject.class));
|
89
|
-
cJdbcConn.defineFastMethod("set_native_database_types",cf.getFastSingletonMethod("set_native_database_types"));
|
90
|
-
cJdbcConn.defineFastMethod("native_database_types",cf.getFastSingletonMethod("native_database_types"));
|
91
|
-
cJdbcConn.defineFastMethod("begin",cf.getFastSingletonMethod("begin"));
|
92
|
-
cJdbcConn.defineFastMethod("commit",cf.getFastSingletonMethod("commit"));
|
93
|
-
cJdbcConn.defineFastMethod("rollback",cf.getFastSingletonMethod("rollback"));
|
94
|
-
cJdbcConn.defineFastMethod("database_name",cf.getFastSingletonMethod("database_name"));
|
95
|
-
cJdbcConn.defineFastMethod("columns",cf.getFastOptSingletonMethod("columns_internal"));
|
96
|
-
cJdbcConn.defineFastMethod("columns_internal",cf.getFastOptSingletonMethod("columns_internal"));
|
97
|
-
cJdbcConn.defineFastMethod("tables",cf.getFastOptSingletonMethod("tables"));
|
98
|
-
|
99
|
-
cJdbcConn.defineFastMethod("insert_bind",cf.getFastOptSingletonMethod("insert_bind"));
|
100
|
-
cJdbcConn.defineFastMethod("update_bind",cf.getFastOptSingletonMethod("update_bind"));
|
101
|
-
|
102
|
-
cJdbcConn.defineFastMethod("write_large_object",cf.getFastOptSingletonMethod("write_large_object"));
|
103
|
-
|
104
|
-
cJdbcConn.getMetaClass().defineFastMethod("insert?",cf.getFastSingletonMethod("insert_p", IRubyObject.class));
|
105
|
-
cJdbcConn.getMetaClass().defineFastMethod("select?",cf.getFastSingletonMethod("select_p", IRubyObject.class));
|
106
|
-
|
107
|
-
RubyModule jdbcSpec = runtime.getOrCreateModule("JdbcSpec");
|
108
|
-
JDBCMySQLSpec.load(runtime, jdbcSpec);
|
109
|
-
JDBCDerbySpec.load(runtime, jdbcSpec);
|
110
|
-
|
111
|
-
return true;
|
112
|
-
}
|
113
|
-
|
114
|
-
private static int whitespace(int p, final int pend, ByteList bl) {
|
115
|
-
while(p < pend) {
|
116
|
-
switch(bl.bytes[p]) {
|
117
|
-
case ' ':
|
118
|
-
case '\n':
|
119
|
-
case '\r':
|
120
|
-
case '\t':
|
121
|
-
p++;
|
122
|
-
break;
|
123
|
-
default:
|
124
|
-
return p;
|
125
|
-
}
|
126
|
-
}
|
127
|
-
return p;
|
128
|
-
}
|
129
|
-
|
130
|
-
public static IRubyObject insert_p(IRubyObject recv, IRubyObject _sql) {
|
131
|
-
ByteList bl = _sql.convertToString().getByteList();
|
132
|
-
|
133
|
-
int p = bl.begin;
|
134
|
-
int pend = p + bl.realSize;
|
135
|
-
|
136
|
-
p = whitespace(p, pend, bl);
|
137
|
-
|
138
|
-
if(pend - p >= 6) {
|
139
|
-
switch(bl.bytes[p++]) {
|
140
|
-
case 'i':
|
141
|
-
case 'I':
|
142
|
-
switch(bl.bytes[p++]) {
|
143
|
-
case 'n':
|
144
|
-
case 'N':
|
145
|
-
switch(bl.bytes[p++]) {
|
146
|
-
case 's':
|
147
|
-
case 'S':
|
148
|
-
switch(bl.bytes[p++]) {
|
149
|
-
case 'e':
|
150
|
-
case 'E':
|
151
|
-
switch(bl.bytes[p++]) {
|
152
|
-
case 'r':
|
153
|
-
case 'R':
|
154
|
-
switch(bl.bytes[p++]) {
|
155
|
-
case 't':
|
156
|
-
case 'T':
|
157
|
-
return recv.getRuntime().getTrue();
|
158
|
-
}
|
159
|
-
}
|
160
|
-
}
|
161
|
-
}
|
162
|
-
}
|
163
|
-
}
|
164
|
-
}
|
165
|
-
return recv.getRuntime().getFalse();
|
166
|
-
}
|
167
|
-
|
168
|
-
public static IRubyObject select_p(IRubyObject recv, IRubyObject _sql) {
|
169
|
-
ByteList bl = _sql.convertToString().getByteList();
|
170
|
-
|
171
|
-
int p = bl.begin;
|
172
|
-
int pend = p + bl.realSize;
|
173
|
-
|
174
|
-
p = whitespace(p, pend, bl);
|
175
|
-
|
176
|
-
if(pend - p >= 6) {
|
177
|
-
if(bl.bytes[p] == '(') {
|
178
|
-
p++;
|
179
|
-
p = whitespace(p, pend, bl);
|
180
|
-
}
|
181
|
-
if(pend - p >= 6) {
|
182
|
-
switch(bl.bytes[p++]) {
|
183
|
-
case 's':
|
184
|
-
case 'S':
|
185
|
-
switch(bl.bytes[p++]) {
|
186
|
-
case 'e':
|
187
|
-
case 'E':
|
188
|
-
switch(bl.bytes[p++]) {
|
189
|
-
case 'l':
|
190
|
-
case 'L':
|
191
|
-
switch(bl.bytes[p++]) {
|
192
|
-
case 'e':
|
193
|
-
case 'E':
|
194
|
-
switch(bl.bytes[p++]) {
|
195
|
-
case 'c':
|
196
|
-
case 'C':
|
197
|
-
switch(bl.bytes[p++]) {
|
198
|
-
case 't':
|
199
|
-
case 'T':
|
200
|
-
return recv.getRuntime().getTrue();
|
201
|
-
}
|
202
|
-
}
|
203
|
-
}
|
204
|
-
}
|
205
|
-
case 'h':
|
206
|
-
case 'H':
|
207
|
-
switch(bl.bytes[p++]) {
|
208
|
-
case 'o':
|
209
|
-
case 'O':
|
210
|
-
switch(bl.bytes[p++]) {
|
211
|
-
case 'w':
|
212
|
-
case 'W':
|
213
|
-
return recv.getRuntime().getTrue();
|
214
|
-
}
|
215
|
-
}
|
216
|
-
}
|
217
|
-
}
|
218
|
-
}
|
219
|
-
}
|
220
|
-
return recv.getRuntime().getFalse();
|
221
|
-
}
|
222
|
-
|
223
|
-
private static ResultSet intoResultSet(IRubyObject inp) {
|
224
|
-
return (ResultSet)((inp instanceof JavaObject ? ((JavaObject)inp) : (((JavaObject)(inp.getInstanceVariable("@java_object"))))).getValue());
|
225
|
-
}
|
226
|
-
|
227
|
-
public static IRubyObject set_connection(IRubyObject recv, IRubyObject conn) {
|
228
|
-
Connection c = (Connection)recv.dataGetStruct();
|
229
|
-
if(c != null) {
|
230
|
-
try {
|
231
|
-
c.close();
|
232
|
-
} catch(Exception e) {}
|
233
|
-
}
|
234
|
-
recv.setInstanceVariable("@connection",conn);
|
235
|
-
c = (Connection)(((JavaObject)conn.getInstanceVariable("@java_object")).getValue());
|
236
|
-
recv.dataWrapStruct(c);
|
237
|
-
return recv;
|
238
|
-
}
|
239
|
-
|
240
|
-
public static IRubyObject tables(IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
|
241
|
-
Ruby runtime = recv.getRuntime();
|
242
|
-
String catalog = null, schemapat = null, tablepat = null;
|
243
|
-
String[] types = new String[]{"TABLE"};
|
244
|
-
if (args != null) {
|
245
|
-
if (args.length > 0) {
|
246
|
-
catalog = convertToStringOrNull(args[0]);
|
247
|
-
}
|
248
|
-
if (args.length > 1) {
|
249
|
-
schemapat = convertToStringOrNull(args[1]);
|
250
|
-
}
|
251
|
-
if (args.length > 2) {
|
252
|
-
tablepat = convertToStringOrNull(args[2]);
|
253
|
-
}
|
254
|
-
if (args.length > 3) {
|
255
|
-
IRubyObject typearr = args[3];
|
256
|
-
if (typearr instanceof RubyArray) {
|
257
|
-
IRubyObject[] arr = ((RubyArray) typearr).toJavaArray();
|
258
|
-
types = new String[arr.length];
|
259
|
-
for (int i = 0; i < types.length; i++) {
|
260
|
-
types[i] = arr[i].toString();
|
261
|
-
}
|
262
|
-
} else {
|
263
|
-
types = new String[] {types.toString()};
|
264
|
-
}
|
265
|
-
}
|
266
|
-
}
|
267
|
-
while (true) {
|
268
|
-
Connection c = (Connection) recv.dataGetStruct();
|
269
|
-
ResultSet rs = null;
|
270
|
-
try {
|
271
|
-
DatabaseMetaData metadata = c.getMetaData();
|
272
|
-
String clzName = metadata.getClass().getName().toLowerCase();
|
273
|
-
boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
|
274
|
-
|
275
|
-
if(schemapat == null && isOracle) {
|
276
|
-
ResultSet schemas = metadata.getSchemas();
|
277
|
-
String username = metadata.getUserName();
|
278
|
-
while(schemas.next()) {
|
279
|
-
if(schemas.getString(1).equalsIgnoreCase(username)) {
|
280
|
-
schemapat = schemas.getString(1);
|
281
|
-
break;
|
282
|
-
}
|
283
|
-
}
|
284
|
-
schemas.close();
|
285
|
-
}
|
286
|
-
rs = metadata.getTables(catalog, schemapat, tablepat, types);
|
287
|
-
List arr = new ArrayList();
|
288
|
-
while (rs.next()) {
|
289
|
-
String name = rs.getString(3).toLowerCase();
|
290
|
-
if(!isOracle || !name.startsWith("bin$")) { //Handle stupid Oracle 10g RecycleBin feature
|
291
|
-
arr.add(runtime.newString(name));
|
292
|
-
}
|
293
|
-
}
|
294
|
-
return runtime.newArray(arr);
|
295
|
-
} catch (SQLException e) {
|
296
|
-
if(c.isClosed()) {
|
297
|
-
recv = recv.callMethod(recv.getRuntime().getCurrentContext(),"reconnect!");
|
298
|
-
if(!((Connection)recv.dataGetStruct()).isClosed()) {
|
299
|
-
continue;
|
300
|
-
}
|
301
|
-
}
|
302
|
-
throw wrap(recv, e);
|
303
|
-
} finally {
|
304
|
-
try {
|
305
|
-
rs.close();
|
306
|
-
} catch(Exception e) {}
|
307
|
-
}
|
308
|
-
|
309
|
-
}
|
310
|
-
}
|
311
|
-
|
312
|
-
public static IRubyObject native_database_types(IRubyObject recv) {
|
313
|
-
return recv.getInstanceVariable("@tps");
|
314
|
-
}
|
315
|
-
|
316
|
-
public static IRubyObject set_native_database_types(IRubyObject recv) throws SQLException, IOException {
|
317
|
-
Ruby runtime = recv.getRuntime();
|
318
|
-
ThreadContext ctx = runtime.getCurrentContext();
|
319
|
-
IRubyObject types = unmarshal_result_downcase(recv, ((Connection)recv.dataGetStruct()).getMetaData().getTypeInfo());
|
320
|
-
recv.setInstanceVariable("@native_types",
|
321
|
-
((RubyModule)(runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).
|
322
|
-
getConstant("JdbcTypeConverter").callMethod(ctx,"new", types).
|
323
|
-
callMethod(ctx, "choose_best_types"));
|
324
|
-
return runtime.getNil();
|
325
|
-
}
|
326
|
-
|
327
|
-
public static IRubyObject database_name(IRubyObject recv) throws SQLException {
|
328
|
-
String name = ((Connection)recv.dataGetStruct()).getCatalog();
|
329
|
-
if(null == name) {
|
330
|
-
name = ((Connection)recv.dataGetStruct()).getMetaData().getUserName();
|
331
|
-
if(null == name) {
|
332
|
-
name = "db1";
|
333
|
-
}
|
334
|
-
}
|
335
|
-
return recv.getRuntime().newString(name);
|
336
|
-
}
|
337
|
-
|
338
|
-
public static IRubyObject begin(IRubyObject recv) throws SQLException {
|
339
|
-
((Connection)recv.dataGetStruct()).setAutoCommit(false);
|
340
|
-
return recv.getRuntime().getNil();
|
341
|
-
}
|
342
|
-
|
343
|
-
public static IRubyObject commit(IRubyObject recv) throws SQLException {
|
344
|
-
try {
|
345
|
-
((Connection)recv.dataGetStruct()).commit();
|
346
|
-
return recv.getRuntime().getNil();
|
347
|
-
} finally {
|
348
|
-
((Connection)recv.dataGetStruct()).setAutoCommit(true);
|
349
|
-
}
|
350
|
-
}
|
351
|
-
|
352
|
-
public static IRubyObject rollback(IRubyObject recv) throws SQLException {
|
353
|
-
try {
|
354
|
-
((Connection)recv.dataGetStruct()).rollback();
|
355
|
-
return recv.getRuntime().getNil();
|
356
|
-
} finally {
|
357
|
-
((Connection)recv.dataGetStruct()).setAutoCommit(true);
|
358
|
-
}
|
359
|
-
}
|
360
|
-
|
361
|
-
public static IRubyObject columns_internal(IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
|
362
|
-
String table_name = args[0].convertToString().getUnicodeValue();
|
363
|
-
int tries = 10;
|
364
|
-
while(true) {
|
365
|
-
Connection c = (Connection)recv.dataGetStruct();
|
366
|
-
try {
|
367
|
-
DatabaseMetaData metadata = c.getMetaData();
|
368
|
-
String clzName = metadata.getClass().getName().toLowerCase();
|
369
|
-
boolean isDerby = clzName.indexOf("derby") != -1;
|
370
|
-
boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
|
371
|
-
String schemaName = null;
|
372
|
-
if(args.length>2) {
|
373
|
-
schemaName = args[2].toString();
|
374
|
-
}
|
375
|
-
if(metadata.storesUpperCaseIdentifiers()) {
|
376
|
-
table_name = table_name.toUpperCase();
|
377
|
-
} else if(metadata.storesLowerCaseIdentifiers()) {
|
378
|
-
table_name = table_name.toLowerCase();
|
379
|
-
}
|
380
|
-
if(schemaName == null && (isDerby || isOracle)) {
|
381
|
-
ResultSet schemas = metadata.getSchemas();
|
382
|
-
String username = metadata.getUserName();
|
383
|
-
while(schemas.next()) {
|
384
|
-
if(schemas.getString(1).equalsIgnoreCase(username)) {
|
385
|
-
schemaName = schemas.getString(1);
|
386
|
-
break;
|
387
|
-
}
|
388
|
-
}
|
389
|
-
schemas.close();
|
390
|
-
}
|
391
|
-
|
392
|
-
ResultSet results = metadata.getColumns(c.getCatalog(),schemaName,table_name,null);
|
393
|
-
return unmarshal_columns(recv, metadata, results);
|
394
|
-
} catch(SQLException e) {
|
395
|
-
if(c.isClosed()) {
|
396
|
-
recv = recv.callMethod(recv.getRuntime().getCurrentContext(),"reconnect!");
|
397
|
-
if(!((Connection)recv.dataGetStruct()).isClosed() && --tries > 0) {
|
398
|
-
continue;
|
399
|
-
}
|
400
|
-
}
|
401
|
-
throw wrap(recv, e);
|
402
|
-
}
|
403
|
-
}
|
404
|
-
}
|
405
|
-
|
406
|
-
private static final java.util.regex.Pattern HAS_SMALL = java.util.regex.Pattern.compile("[a-z]");
|
407
|
-
private static final java.util.regex.Pattern HAS_LARGE = java.util.regex.Pattern.compile("[A-Z]");
|
408
|
-
private static IRubyObject unmarshal_columns(IRubyObject recv, DatabaseMetaData metadata, ResultSet rs) throws SQLException, IOException {
|
409
|
-
try {
|
410
|
-
List columns = new ArrayList();
|
411
|
-
String clzName = metadata.getClass().getName().toLowerCase();
|
412
|
-
boolean isDerby = clzName.indexOf("derby") != -1;
|
413
|
-
boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
|
414
|
-
Ruby runtime = recv.getRuntime();
|
415
|
-
ThreadContext ctx = runtime.getCurrentContext();
|
416
|
-
|
417
|
-
RubyHash tps = ((RubyHash)(recv.callMethod(ctx, "adapter").callMethod(ctx,"native_database_types")));
|
418
|
-
|
419
|
-
IRubyObject jdbcCol = ((RubyModule)(runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).getConstant("JdbcColumn");
|
420
|
-
|
421
|
-
while(rs.next()) {
|
422
|
-
String column_name = rs.getString(4);
|
423
|
-
if(metadata.storesUpperCaseIdentifiers() && !HAS_SMALL.matcher(column_name).find()) {
|
424
|
-
column_name = column_name.toLowerCase();
|
425
|
-
}
|
426
|
-
|
427
|
-
String prec = rs.getString(7);
|
428
|
-
String scal = rs.getString(9);
|
429
|
-
int precision = -1;
|
430
|
-
int scale = -1;
|
431
|
-
if(prec != null) {
|
432
|
-
precision = Integer.parseInt(prec);
|
433
|
-
if(scal != null) {
|
434
|
-
scale = Integer.parseInt(scal);
|
435
|
-
}
|
436
|
-
}
|
437
|
-
String type = rs.getString(6);
|
438
|
-
if(prec != null && precision > 0) {
|
439
|
-
type += "(" + precision;
|
440
|
-
if(scal != null && scale > 0) {
|
441
|
-
type += "," + scale;
|
442
|
-
}
|
443
|
-
type += ")";
|
444
|
-
}
|
445
|
-
String def = rs.getString(13);
|
446
|
-
IRubyObject _def;
|
447
|
-
if(def == null || (isOracle && def.toLowerCase().trim().equals("null"))) {
|
448
|
-
_def = runtime.getNil();
|
449
|
-
} else {
|
450
|
-
if(isOracle) {
|
451
|
-
def = def.trim();
|
452
|
-
}
|
453
|
-
if((isDerby || isOracle) && def.length() > 0 && def.charAt(0) == '\'') {
|
454
|
-
def = def.substring(1, def.length()-1);
|
455
|
-
}
|
456
|
-
_def = runtime.newString(def);
|
457
|
-
}
|
458
|
-
IRubyObject c = jdbcCol.callMethod(ctx,"new", new IRubyObject[]{recv.getInstanceVariable("@config"), runtime.newString(column_name),
|
459
|
-
_def, runtime.newString(type),
|
460
|
-
runtime.newBoolean(!rs.getString(18).trim().equals("NO"))});
|
461
|
-
columns.add(c);
|
462
|
-
|
463
|
-
IRubyObject tp = (IRubyObject)tps.fastARef(c.callMethod(ctx,"type"));
|
464
|
-
if(tp != null && !tp.isNil() && tp.callMethod(ctx,"[]",runtime.newSymbol("limit")).isNil()) {
|
465
|
-
c.callMethod(ctx,"limit=", runtime.getNil());
|
466
|
-
if(!c.callMethod(ctx,"type").equals(runtime.newSymbol("decimal"))) {
|
467
|
-
c.callMethod(ctx,"precision=", runtime.getNil());
|
468
|
-
}
|
469
|
-
}
|
470
|
-
}
|
471
|
-
return runtime.newArray(columns);
|
472
|
-
} finally {
|
473
|
-
try {
|
474
|
-
rs.close();
|
475
|
-
} catch(Exception e) {}
|
476
|
-
}
|
477
|
-
}
|
478
|
-
|
479
|
-
public static IRubyObject primary_keys(IRubyObject recv, IRubyObject _table_name) throws SQLException {
|
480
|
-
Connection c = (Connection)recv.dataGetStruct();
|
481
|
-
DatabaseMetaData metadata = c.getMetaData();
|
482
|
-
String table_name = _table_name.toString();
|
483
|
-
if(metadata.storesUpperCaseIdentifiers()) {
|
484
|
-
table_name = table_name.toUpperCase();
|
485
|
-
} else if(metadata.storesLowerCaseIdentifiers()) {
|
486
|
-
table_name = table_name.toLowerCase();
|
487
|
-
}
|
488
|
-
ResultSet result_set = metadata.getPrimaryKeys(null,null,table_name);
|
489
|
-
List keyNames = new ArrayList();
|
490
|
-
Ruby runtime = recv.getRuntime();
|
491
|
-
while(result_set.next()) {
|
492
|
-
String s1 = result_set.getString(4);
|
493
|
-
if(metadata.storesUpperCaseIdentifiers() && !HAS_SMALL.matcher(s1).find()) {
|
494
|
-
s1 = s1.toLowerCase();
|
495
|
-
}
|
496
|
-
keyNames.add(runtime.newString(s1));
|
497
|
-
}
|
498
|
-
|
499
|
-
try {
|
500
|
-
result_set.close();
|
501
|
-
} catch(Exception e) {}
|
502
|
-
|
503
|
-
return runtime.newArray(keyNames);
|
504
|
-
}
|
505
|
-
|
506
|
-
public static IRubyObject execute_id_insert(IRubyObject recv, IRubyObject sql, IRubyObject id) throws SQLException {
|
507
|
-
Connection c = (Connection)recv.dataGetStruct();
|
508
|
-
PreparedStatement ps = c.prepareStatement(sql.convertToString().getUnicodeValue());
|
509
|
-
try {
|
510
|
-
ps.setLong(1,RubyNumeric.fix2long(id));
|
511
|
-
ps.executeUpdate();
|
512
|
-
} finally {
|
513
|
-
ps.close();
|
514
|
-
}
|
515
|
-
return id;
|
516
|
-
}
|
517
|
-
|
518
|
-
private static RuntimeException wrap(IRubyObject recv, Throwable exception) {
|
519
|
-
return recv.getRuntime().newArgumentError(exception.getMessage());
|
520
|
-
}
|
521
|
-
|
522
|
-
public static IRubyObject execute_update(IRubyObject recv, IRubyObject sql) throws SQLException {
|
523
|
-
int tries = 10;
|
524
|
-
while(true) {
|
525
|
-
Connection c = (Connection)recv.dataGetStruct();
|
526
|
-
Statement stmt = null;
|
527
|
-
try {
|
528
|
-
stmt = c.createStatement();
|
529
|
-
return recv.getRuntime().newFixnum(stmt.executeUpdate(sql.convertToString().getUnicodeValue()));
|
530
|
-
} catch(SQLException e) {
|
531
|
-
if(c.isClosed()) {
|
532
|
-
recv = recv.callMethod(recv.getRuntime().getCurrentContext(),"reconnect!");
|
533
|
-
if(!((Connection)recv.dataGetStruct()).isClosed() && --tries > 0) {
|
534
|
-
continue;
|
535
|
-
}
|
536
|
-
}
|
537
|
-
|
538
|
-
throw wrap(recv, e);
|
539
|
-
} finally {
|
540
|
-
if(null != stmt) {
|
541
|
-
try {
|
542
|
-
stmt.close();
|
543
|
-
} catch(Exception e) {}
|
544
|
-
}
|
545
|
-
}
|
546
|
-
}
|
547
|
-
}
|
548
|
-
|
549
|
-
public static IRubyObject execute_query(IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
|
550
|
-
IRubyObject sql = args[0];
|
551
|
-
int maxrows = 0;
|
552
|
-
if(args.length > 1) {
|
553
|
-
maxrows = RubyNumeric.fix2int(args[1]);
|
554
|
-
}
|
555
|
-
int tries = 10;
|
556
|
-
while(true) {
|
557
|
-
Connection c = (Connection)recv.dataGetStruct();
|
558
|
-
Statement stmt = null;
|
559
|
-
try {
|
560
|
-
stmt = c.createStatement();
|
561
|
-
stmt.setMaxRows(maxrows);
|
562
|
-
return unmarshal_result(recv, stmt.executeQuery(sql.convertToString().getUnicodeValue()));
|
563
|
-
} catch(SQLException e) {
|
564
|
-
if(c.isClosed()) {
|
565
|
-
recv = recv.callMethod(recv.getRuntime().getCurrentContext(),"reconnect!");
|
566
|
-
if(!((Connection)recv.dataGetStruct()).isClosed() && --tries > 0) {
|
567
|
-
continue;
|
568
|
-
}
|
569
|
-
}
|
570
|
-
throw wrap(recv, e);
|
571
|
-
} finally {
|
572
|
-
if(null != stmt) {
|
573
|
-
try {
|
574
|
-
stmt.close();
|
575
|
-
} catch(Exception e) {}
|
576
|
-
}
|
577
|
-
}
|
578
|
-
}
|
579
|
-
}
|
580
|
-
|
581
|
-
public static IRubyObject execute_insert(IRubyObject recv, IRubyObject sql) throws SQLException {
|
582
|
-
int tries = 10;
|
583
|
-
while(true) {
|
584
|
-
Connection c = (Connection)recv.dataGetStruct();
|
585
|
-
Statement stmt = null;
|
586
|
-
try {
|
587
|
-
stmt = c.createStatement();
|
588
|
-
stmt.executeUpdate(sql.convertToString().getUnicodeValue(), Statement.RETURN_GENERATED_KEYS);
|
589
|
-
return unmarshal_id_result(recv.getRuntime(), stmt.getGeneratedKeys());
|
590
|
-
} catch(SQLException e) {
|
591
|
-
if(c.isClosed()) {
|
592
|
-
recv = recv.callMethod(recv.getRuntime().getCurrentContext(),"reconnect!");
|
593
|
-
if(!((Connection)recv.dataGetStruct()).isClosed() && --tries > 0) {
|
594
|
-
continue;
|
595
|
-
}
|
596
|
-
}
|
597
|
-
throw wrap(recv, e);
|
598
|
-
} finally {
|
599
|
-
if(null != stmt) {
|
600
|
-
try {
|
601
|
-
stmt.close();
|
602
|
-
} catch(Exception e) {}
|
603
|
-
}
|
604
|
-
}
|
605
|
-
}
|
606
|
-
}
|
607
|
-
|
608
|
-
public static IRubyObject unmarshal_result_downcase(IRubyObject recv, ResultSet rs) throws SQLException, IOException {
|
609
|
-
List results = new ArrayList();
|
610
|
-
Ruby runtime = recv.getRuntime();
|
611
|
-
try {
|
612
|
-
ResultSetMetaData metadata = rs.getMetaData();
|
613
|
-
int col_count = metadata.getColumnCount();
|
614
|
-
IRubyObject[] col_names = new IRubyObject[col_count];
|
615
|
-
int[] col_types = new int[col_count];
|
616
|
-
int[] col_scale = new int[col_count];
|
617
|
-
|
618
|
-
for(int i=0;i<col_count;i++) {
|
619
|
-
col_names[i] = runtime.newString(metadata.getColumnName(i+1).toLowerCase());
|
620
|
-
col_types[i] = metadata.getColumnType(i+1);
|
621
|
-
col_scale[i] = metadata.getScale(i+1);
|
622
|
-
}
|
623
|
-
|
624
|
-
while(rs.next()) {
|
625
|
-
RubyHash row = RubyHash.newHash(runtime);
|
626
|
-
for(int i=0;i<col_count;i++) {
|
627
|
-
row.aset(col_names[i], jdbc_to_ruby(runtime, i+1, col_types[i], col_scale[i], rs));
|
628
|
-
}
|
629
|
-
results.add(row);
|
630
|
-
}
|
631
|
-
} finally {
|
632
|
-
try {
|
633
|
-
rs.close();
|
634
|
-
} catch(Exception e) {}
|
635
|
-
}
|
636
|
-
|
637
|
-
return runtime.newArray(results);
|
638
|
-
}
|
639
|
-
|
640
|
-
public static IRubyObject unmarshal_result(IRubyObject recv, ResultSet rs) throws SQLException, IOException {
|
641
|
-
Ruby runtime = recv.getRuntime();
|
642
|
-
List results = new ArrayList();
|
643
|
-
try {
|
644
|
-
ResultSetMetaData metadata = rs.getMetaData();
|
645
|
-
boolean storesUpper = rs.getStatement().getConnection().getMetaData().storesUpperCaseIdentifiers();
|
646
|
-
int col_count = metadata.getColumnCount();
|
647
|
-
IRubyObject[] col_names = new IRubyObject[col_count];
|
648
|
-
int[] col_types = new int[col_count];
|
649
|
-
int[] col_scale = new int[col_count];
|
650
|
-
|
651
|
-
for(int i=0;i<col_count;i++) {
|
652
|
-
String s1 = metadata.getColumnName(i+1);
|
653
|
-
if(storesUpper && !HAS_SMALL.matcher(s1).find()) {
|
654
|
-
s1 = s1.toLowerCase();
|
655
|
-
}
|
656
|
-
col_names[i] = runtime.newString(s1);
|
657
|
-
col_types[i] = metadata.getColumnType(i+1);
|
658
|
-
col_scale[i] = metadata.getScale(i+1);
|
659
|
-
}
|
660
|
-
|
661
|
-
while(rs.next()) {
|
662
|
-
RubyHash row = RubyHash.newHash(runtime);
|
663
|
-
for(int i=0;i<col_count;i++) {
|
664
|
-
row.aset(col_names[i], jdbc_to_ruby(runtime, i+1, col_types[i], col_scale[i], rs));
|
665
|
-
}
|
666
|
-
results.add(row);
|
667
|
-
}
|
668
|
-
} finally {
|
669
|
-
try {
|
670
|
-
rs.close();
|
671
|
-
} catch(Exception e) {}
|
672
|
-
}
|
673
|
-
return runtime.newArray(results);
|
674
|
-
}
|
675
|
-
|
676
|
-
public static IRubyObject unmarshal_result(IRubyObject recv, IRubyObject resultset, Block row_filter) throws SQLException, IOException {
|
677
|
-
Ruby runtime = recv.getRuntime();
|
678
|
-
ResultSet rs = intoResultSet(resultset);
|
679
|
-
List results = new ArrayList();
|
680
|
-
try {
|
681
|
-
ResultSetMetaData metadata = rs.getMetaData();
|
682
|
-
int col_count = metadata.getColumnCount();
|
683
|
-
IRubyObject[] col_names = new IRubyObject[col_count];
|
684
|
-
int[] col_types = new int[col_count];
|
685
|
-
int[] col_scale = new int[col_count];
|
686
|
-
|
687
|
-
for(int i=0;i<col_count;i++) {
|
688
|
-
col_names[i] = runtime.newString(metadata.getColumnName(i+1));
|
689
|
-
col_types[i] = metadata.getColumnType(i+1);
|
690
|
-
col_scale[i] = metadata.getScale(i+1);
|
691
|
-
}
|
692
|
-
|
693
|
-
if(row_filter.isGiven()) {
|
694
|
-
while(rs.next()) {
|
695
|
-
if(row_filter.yield(runtime.getCurrentContext(),resultset).isTrue()) {
|
696
|
-
RubyHash row = RubyHash.newHash(runtime);
|
697
|
-
for(int i=0;i<col_count;i++) {
|
698
|
-
row.aset(col_names[i], jdbc_to_ruby(runtime, i+1, col_types[i], col_scale[i], rs));
|
699
|
-
}
|
700
|
-
results.add(row);
|
701
|
-
}
|
702
|
-
}
|
703
|
-
} else {
|
704
|
-
while(rs.next()) {
|
705
|
-
RubyHash row = RubyHash.newHash(runtime);
|
706
|
-
for(int i=0;i<col_count;i++) {
|
707
|
-
row.aset(col_names[i], jdbc_to_ruby(runtime, i+1, col_types[i], col_scale[i], rs));
|
708
|
-
}
|
709
|
-
results.add(row);
|
710
|
-
}
|
711
|
-
}
|
712
|
-
|
713
|
-
} finally {
|
714
|
-
try {
|
715
|
-
rs.close();
|
716
|
-
} catch(Exception e) {}
|
717
|
-
}
|
718
|
-
|
719
|
-
return runtime.newArray(results);
|
720
|
-
}
|
721
|
-
|
722
|
-
private static IRubyObject jdbc_to_ruby(Ruby runtime, int row, int type, int scale, ResultSet rs) throws SQLException, IOException {
|
723
|
-
int n;
|
724
|
-
switch(type) {
|
725
|
-
case Types.BINARY:
|
726
|
-
case Types.BLOB:
|
727
|
-
case Types.LONGVARBINARY:
|
728
|
-
case Types.VARBINARY:
|
729
|
-
InputStream is = rs.getBinaryStream(row);
|
730
|
-
if(is == null || rs.wasNull()) {
|
731
|
-
return runtime.getNil();
|
732
|
-
}
|
733
|
-
ByteList str = new ByteList(2048);
|
734
|
-
byte[] buf = new byte[2048];
|
735
|
-
while((n = is.read(buf)) != -1) {
|
736
|
-
str.append(buf, 0, n);
|
737
|
-
}
|
738
|
-
is.close();
|
739
|
-
return runtime.newString(str);
|
740
|
-
case Types.LONGVARCHAR:
|
741
|
-
case Types.CLOB:
|
742
|
-
Reader rss = rs.getCharacterStream(row);
|
743
|
-
if(rss == null || rs.wasNull()) {
|
744
|
-
return runtime.getNil();
|
745
|
-
}
|
746
|
-
StringBuffer str2 = new StringBuffer(2048);
|
747
|
-
char[] cuf = new char[2048];
|
748
|
-
while((n = rss.read(cuf)) != -1) {
|
749
|
-
str2.append(cuf, 0, n);
|
750
|
-
}
|
751
|
-
rss.close();
|
752
|
-
return RubyString.newUnicodeString(runtime, str2.toString());
|
753
|
-
case Types.TIMESTAMP:
|
754
|
-
Timestamp time = rs.getTimestamp(row);
|
755
|
-
if (time == null || rs.wasNull()) {
|
756
|
-
return runtime.getNil();
|
757
|
-
}
|
758
|
-
String sttr = time.toString();
|
759
|
-
if(sttr.endsWith(" 00:00:00.0")) {
|
760
|
-
sttr = sttr.substring(0, sttr.length()-(" 00:00:00.0".length()));
|
761
|
-
}
|
762
|
-
return RubyString.newUnicodeString(runtime, sttr);
|
763
|
-
default:
|
764
|
-
String vs = rs.getString(row);
|
765
|
-
if(vs == null || rs.wasNull()) {
|
766
|
-
return runtime.getNil();
|
767
|
-
}
|
768
|
-
|
769
|
-
return RubyString.newUnicodeString(runtime, vs);
|
770
|
-
}
|
771
|
-
}
|
772
|
-
|
773
|
-
public static IRubyObject unmarshal_id_result(Ruby runtime, ResultSet rs) throws SQLException {
|
774
|
-
try {
|
775
|
-
if(rs.next()) {
|
776
|
-
if(rs.getMetaData().getColumnCount() > 0) {
|
777
|
-
return runtime.newFixnum(rs.getLong(1));
|
778
|
-
}
|
779
|
-
}
|
780
|
-
return runtime.getNil();
|
781
|
-
} finally {
|
782
|
-
try {
|
783
|
-
rs.close();
|
784
|
-
} catch(Exception e) {}
|
785
|
-
}
|
786
|
-
}
|
787
|
-
|
788
|
-
private static String convertToStringOrNull(IRubyObject obj) {
|
789
|
-
if (obj.isNil()) {
|
790
|
-
return null;
|
791
|
-
}
|
792
|
-
return obj.toString();
|
793
|
-
}
|
794
|
-
|
795
|
-
private static int getTypeValueFor(Ruby runtime, IRubyObject type) throws SQLException {
|
796
|
-
if(!(type instanceof RubySymbol)) {
|
797
|
-
type = type.callMethod(runtime.getCurrentContext(),"type");
|
798
|
-
}
|
799
|
-
if(type == runtime.newSymbol("string")) {
|
800
|
-
return Types.VARCHAR;
|
801
|
-
} else if(type == runtime.newSymbol("text")) {
|
802
|
-
return Types.CLOB;
|
803
|
-
} else if(type == runtime.newSymbol("integer")) {
|
804
|
-
return Types.INTEGER;
|
805
|
-
} else if(type == runtime.newSymbol("decimal")) {
|
806
|
-
return Types.DECIMAL;
|
807
|
-
} else if(type == runtime.newSymbol("float")) {
|
808
|
-
return Types.FLOAT;
|
809
|
-
} else if(type == runtime.newSymbol("datetime")) {
|
810
|
-
return Types.TIMESTAMP;
|
811
|
-
} else if(type == runtime.newSymbol("timestamp")) {
|
812
|
-
return Types.TIMESTAMP;
|
813
|
-
} else if(type == runtime.newSymbol("time")) {
|
814
|
-
return Types.TIME;
|
815
|
-
} else if(type == runtime.newSymbol("date")) {
|
816
|
-
return Types.DATE;
|
817
|
-
} else if(type == runtime.newSymbol("binary")) {
|
818
|
-
return Types.BLOB;
|
819
|
-
} else if(type == runtime.newSymbol("boolean")) {
|
820
|
-
return Types.BOOLEAN;
|
821
|
-
} else {
|
822
|
-
return -1;
|
823
|
-
}
|
824
|
-
}
|
825
|
-
|
826
|
-
private final static DateFormat FORMAT = new SimpleDateFormat("%y-%M-%d %H:%m:%s");
|
827
|
-
|
828
|
-
private static void setValue(PreparedStatement ps, int index, Ruby runtime, IRubyObject value, IRubyObject type) throws SQLException {
|
829
|
-
final int tp = getTypeValueFor(runtime, type);
|
830
|
-
if(value.isNil()) {
|
831
|
-
ps.setNull(index, tp);
|
832
|
-
return;
|
833
|
-
}
|
834
|
-
|
835
|
-
switch(tp) {
|
836
|
-
case Types.VARCHAR:
|
837
|
-
case Types.CLOB:
|
838
|
-
ps.setString(index, RubyString.objAsString(value).toString());
|
839
|
-
break;
|
840
|
-
case Types.INTEGER:
|
841
|
-
ps.setLong(index, RubyNumeric.fix2long(value));
|
842
|
-
break;
|
843
|
-
case Types.FLOAT:
|
844
|
-
ps.setDouble(index, ((RubyNumeric)value).getDoubleValue());
|
845
|
-
break;
|
846
|
-
case Types.TIMESTAMP:
|
847
|
-
case Types.TIME:
|
848
|
-
case Types.DATE:
|
849
|
-
if(!(value instanceof RubyTime)) {
|
850
|
-
try {
|
851
|
-
Date dd = FORMAT.parse(RubyString.objAsString(value).toString());
|
852
|
-
ps.setTimestamp(index, new java.sql.Timestamp(dd.getTime()), Calendar.getInstance());
|
853
|
-
} catch(Exception e) {
|
854
|
-
ps.setString(index, RubyString.objAsString(value).toString());
|
855
|
-
}
|
856
|
-
} else {
|
857
|
-
RubyTime rubyTime = (RubyTime) value;
|
858
|
-
java.util.Date date = rubyTime.getJavaDate();
|
859
|
-
long millis = date.getTime();
|
860
|
-
long micros = rubyTime.microseconds() - millis / 1000;
|
861
|
-
java.sql.Timestamp ts = new java.sql.Timestamp(millis);
|
862
|
-
java.util.Calendar cal = Calendar.getInstance();
|
863
|
-
cal.setTime(date);
|
864
|
-
ts.setNanos((int)(micros * 1000));
|
865
|
-
ps.setTimestamp(index, ts, cal);
|
866
|
-
}
|
867
|
-
break;
|
868
|
-
case Types.BOOLEAN:
|
869
|
-
ps.setBoolean(index, value.isTrue());
|
870
|
-
break;
|
871
|
-
default: throw new RuntimeException("type " + type + " not supported in _bind yet");
|
872
|
-
}
|
873
|
-
}
|
874
|
-
|
875
|
-
private static void setValuesOnPS(PreparedStatement ps, Ruby runtime, IRubyObject values, IRubyObject types) throws SQLException {
|
876
|
-
RubyArray vals = (RubyArray)values;
|
877
|
-
RubyArray tps = (RubyArray)types;
|
878
|
-
|
879
|
-
for(int i=0, j=vals.getLength(); i<j; i++) {
|
880
|
-
setValue(ps, i+1, runtime, vals.eltInternal(i), tps.eltInternal(i));
|
881
|
-
}
|
882
|
-
}
|
883
|
-
|
884
|
-
/*
|
885
|
-
* sql, values, types, name = nil, pk = nil, id_value = nil, sequence_name = nil
|
886
|
-
*/
|
887
|
-
public static IRubyObject insert_bind(IRubyObject recv, IRubyObject[] args) throws SQLException {
|
888
|
-
Ruby runtime = recv.getRuntime();
|
889
|
-
Arity.checkArgumentCount(runtime, args, 3, 7);
|
890
|
-
Connection c = (Connection)recv.dataGetStruct();
|
891
|
-
PreparedStatement ps = null;
|
892
|
-
try {
|
893
|
-
ps = c.prepareStatement(RubyString.objAsString(args[0]).toString(), Statement.RETURN_GENERATED_KEYS);
|
894
|
-
setValuesOnPS(ps, runtime, args[1], args[2]);
|
895
|
-
ps.executeUpdate();
|
896
|
-
return unmarshal_id_result(runtime, ps.getGeneratedKeys());
|
897
|
-
} finally {
|
898
|
-
try {
|
899
|
-
ps.close();
|
900
|
-
} catch(Exception e) {}
|
901
|
-
}
|
902
|
-
}
|
903
|
-
|
904
|
-
/*
|
905
|
-
* sql, values, types, name = nil
|
906
|
-
*/
|
907
|
-
public static IRubyObject update_bind(IRubyObject recv, IRubyObject[] args) throws SQLException {
|
908
|
-
Ruby runtime = recv.getRuntime();
|
909
|
-
Arity.checkArgumentCount(runtime, args, 3, 4);
|
910
|
-
Connection c = (Connection)recv.dataGetStruct();
|
911
|
-
PreparedStatement ps = null;
|
912
|
-
try {
|
913
|
-
ps = c.prepareStatement(RubyString.objAsString(args[0]).toString());
|
914
|
-
setValuesOnPS(ps, runtime, args[1], args[2]);
|
915
|
-
ps.executeUpdate();
|
916
|
-
} finally {
|
917
|
-
try {
|
918
|
-
ps.close();
|
919
|
-
} catch(Exception e) {}
|
920
|
-
}
|
921
|
-
return runtime.getNil();
|
922
|
-
}
|
923
|
-
|
924
|
-
|
925
|
-
private final static String LOB_UPDATE = "UPDATE ? WHERE ";
|
926
|
-
|
927
|
-
/*
|
928
|
-
* (is binary?, colname, tablename, primary key, id, value)
|
929
|
-
*/
|
930
|
-
public static IRubyObject write_large_object(IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
|
931
|
-
Ruby runtime = recv.getRuntime();
|
932
|
-
Arity.checkArgumentCount(runtime, args, 6, 6);
|
933
|
-
Connection c = (Connection)recv.dataGetStruct();
|
934
|
-
String sql = "UPDATE " + args[2].toString() + " SET " + args[1].toString() + " = ? WHERE " + args[3] + "=" + args[4];
|
935
|
-
PreparedStatement ps = null;
|
936
|
-
try {
|
937
|
-
ByteList outp = RubyString.objAsString(args[5]).getByteList();
|
938
|
-
ps = c.prepareStatement(sql);
|
939
|
-
if(args[0].isTrue()) { // binary
|
940
|
-
ps.setBinaryStream(1,new ByteArrayInputStream(outp.bytes, outp.begin, outp.realSize), outp.realSize);
|
941
|
-
} else { // clob
|
942
|
-
String ss = outp.toString();
|
943
|
-
ps.setCharacterStream(1,new StringReader(ss), ss.length());
|
944
|
-
}
|
945
|
-
ps.executeUpdate();
|
946
|
-
} finally {
|
947
|
-
try {
|
948
|
-
ps.close();
|
949
|
-
} catch(Exception e) {}
|
950
|
-
}
|
951
|
-
return runtime.getNil();
|
952
|
-
}
|
953
|
-
}
|