activerecord-jdbc-adapter 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|