activerecord-jdbc-adapter 5.0.pre1 → 51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -100,9 +100,9 @@ public class MySQLModule {
|
|
100
100
|
|
101
101
|
final Ruby runtime = context.getRuntime();
|
102
102
|
final RubyString quoted = runtime.newString(quotedBytes);
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
|
104
|
+
quoted.associateEncoding(UTF8Encoding.INSTANCE);
|
105
|
+
|
106
106
|
return quoted;
|
107
107
|
}
|
108
108
|
|
@@ -26,7 +26,6 @@
|
|
26
26
|
package arjdbc.mysql;
|
27
27
|
|
28
28
|
import arjdbc.jdbc.RubyJdbcConnection;
|
29
|
-
import arjdbc.jdbc.Callable;
|
30
29
|
|
31
30
|
import java.lang.reflect.Field;
|
32
31
|
import java.lang.reflect.InvocationTargetException;
|
@@ -43,17 +42,18 @@ import java.util.TimeZone;
|
|
43
42
|
import java.util.regex.Matcher;
|
44
43
|
import java.util.regex.Pattern;
|
45
44
|
|
45
|
+
import org.joda.time.DateTime;
|
46
46
|
import org.jruby.Ruby;
|
47
|
-
import org.jruby.RubyArray;
|
48
47
|
import org.jruby.RubyClass;
|
49
|
-
import org.jruby.RubyFloat;
|
50
48
|
import org.jruby.RubyInteger;
|
51
|
-
import org.jruby.RubyModule;
|
52
49
|
import org.jruby.RubyString;
|
50
|
+
import org.jruby.RubyTime;
|
51
|
+
import org.jruby.anno.JRubyMethod;
|
53
52
|
import org.jruby.exceptions.RaiseException;
|
54
53
|
import org.jruby.runtime.ObjectAllocator;
|
55
54
|
import org.jruby.runtime.ThreadContext;
|
56
55
|
import org.jruby.runtime.builtin.IRubyObject;
|
56
|
+
import org.jruby.util.TypeConverter;
|
57
57
|
|
58
58
|
/**
|
59
59
|
*
|
@@ -79,25 +79,20 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
79
79
|
return clazz;
|
80
80
|
}
|
81
81
|
|
82
|
-
@
|
83
|
-
|
84
|
-
|
85
|
-
return
|
82
|
+
@JRubyMethod
|
83
|
+
public IRubyObject query(final ThreadContext context, final IRubyObject sql) throws SQLException {
|
84
|
+
final String query = sql.convertToString().getUnicodeValue(); // sql
|
85
|
+
return executeUpdate(context, query, false);
|
86
86
|
}
|
87
87
|
|
88
88
|
@Override
|
89
|
-
protected
|
90
|
-
|
91
|
-
final Ruby runtime = context.getRuntime();
|
92
|
-
final IRubyObject key = mapGeneratedKeys(runtime, connection, statement);
|
93
|
-
return ( key == null || key.isNil() ) ? runtime.newFixnum( statement.getUpdateCount() ) : key;
|
89
|
+
protected boolean doExecute(final Statement statement, final String query) throws SQLException {
|
90
|
+
return statement.execute(query, Statement.RETURN_GENERATED_KEYS);
|
94
91
|
}
|
95
92
|
|
96
93
|
@Override
|
97
|
-
protected IRubyObject jdbcToRuby(
|
98
|
-
final
|
99
|
-
final int column, final int type, final ResultSet resultSet)
|
100
|
-
throws SQLException {
|
94
|
+
protected IRubyObject jdbcToRuby(final ThreadContext context, final Ruby runtime,
|
95
|
+
final int column, final int type, final ResultSet resultSet) throws SQLException {
|
101
96
|
if ( type == Types.BIT ) {
|
102
97
|
final int value = resultSet.getInt(column);
|
103
98
|
return resultSet.wasNull() ? runtime.getNil() : runtime.newFixnum(value);
|
@@ -106,53 +101,50 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
106
101
|
}
|
107
102
|
|
108
103
|
@Override // can not use statement.setTimestamp( int, Timestamp, Calendar )
|
109
|
-
protected void setTimestampParameter(
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
else {
|
115
|
-
value = getTimeInDefaultTimeZone(context, value);
|
116
|
-
if ( value instanceof RubyString ) { // yyyy-[m]m-[d]d hh:mm:ss[.f...]
|
117
|
-
final Timestamp timestamp = Timestamp.valueOf( value.toString() );
|
118
|
-
statement.setTimestamp( index, timestamp ); // assume local time-zone
|
119
|
-
}
|
120
|
-
else { // Time or DateTime ( ActiveSupport::TimeWithZone.to_time )
|
121
|
-
final double time = adjustTimeFromDefaultZone(value);
|
122
|
-
final RubyFloat timeValue = context.getRuntime().newFloat( time );
|
123
|
-
statement.setTimestamp( index, convertToTimestamp(timeValue) );
|
124
|
-
}
|
125
|
-
}
|
104
|
+
protected void setTimestampParameter(ThreadContext context, Connection connection, PreparedStatement statement,
|
105
|
+
int index, IRubyObject value, IRubyObject column, int type) throws SQLException {
|
106
|
+
value = callMethod(context, "time_in_default_timezone", value);
|
107
|
+
TypeConverter.checkType(context, value, context.runtime.getTime());
|
108
|
+
setTimestamp(statement, index, (RubyTime) value, type);
|
126
109
|
}
|
127
110
|
|
128
|
-
@Override
|
129
|
-
protected void setTimeParameter(
|
130
|
-
|
131
|
-
|
132
|
-
final IRubyObject column, final int type) throws SQLException {
|
133
|
-
if ( value.isNil() ) statement.setNull(index, Types.TIME);
|
134
|
-
else {
|
135
|
-
value = getTimeInDefaultTimeZone(context, value);
|
136
|
-
if ( value instanceof RubyString ) {
|
137
|
-
final Time time = Time.valueOf( value.toString() );
|
138
|
-
statement.setTime( index, time ); // assume local time-zone
|
139
|
-
}
|
140
|
-
else { // Time or DateTime ( ActiveSupport::TimeWithZone.to_time )
|
141
|
-
final double timeValue = adjustTimeFromDefaultZone(value);
|
142
|
-
final Time time = new Time(( (long) timeValue ) * 1000); // millis
|
143
|
-
// java.sql.Time is expected to be only up to second precision
|
144
|
-
statement.setTime( index, time );
|
145
|
-
}
|
146
|
-
}
|
111
|
+
@Override
|
112
|
+
protected void setTimeParameter(ThreadContext context, Connection connection, PreparedStatement statement,
|
113
|
+
int index, IRubyObject value, IRubyObject column, int type) throws SQLException {
|
114
|
+
setTimestampParameter(context, connection, statement, index, value, column, type);
|
147
115
|
}
|
148
116
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
117
|
+
// FIXME: we should detect adapter and not do this timezone offset calculation is it is jdbc version 6+.
|
118
|
+
private void setTimestamp(PreparedStatement statement, int index, RubyTime value, int type) throws SQLException {
|
119
|
+
DateTime dateTime = value.getDateTime();
|
120
|
+
int offset = TimeZone.getDefault().getOffset(dateTime.getMillis()); // JDBC <6.x ignores time zone info (we adjust manually).
|
121
|
+
Timestamp timestamp = new Timestamp(dateTime.getMillis() - offset);
|
122
|
+
|
123
|
+
// 1942-11-30T01:02:03.123_456
|
124
|
+
if (type != Types.DATE && value.getNSec() >= 0) timestamp.setNanos((int) (timestamp.getNanos() + value.getNSec()));
|
125
|
+
|
126
|
+
statement.setTimestamp(index, timestamp);
|
127
|
+
}
|
128
|
+
|
129
|
+
// FIXME: I think we can unify this back to main adapter code since previous conflict involved not using
|
130
|
+
// the raw string return type and not the extra formatting logic.
|
131
|
+
@Override
|
132
|
+
protected IRubyObject timeToRuby(ThreadContext context, Ruby runtime, ResultSet resultSet, int column) throws SQLException {
|
133
|
+
Time value = resultSet.getTime(column);
|
134
|
+
|
135
|
+
if (value == null) return resultSet.wasNull() ? runtime.getNil() : runtime.newString();
|
136
|
+
|
137
|
+
String strValue = value.toString();
|
138
|
+
|
139
|
+
// If time is column type but that time had a precision which included
|
140
|
+
// nanoseconds we used timestamp to save the data. Since this is conditional
|
141
|
+
// we grab data a second time as a timestamp to look for nsecs.
|
142
|
+
Timestamp nsecTimeHack = resultSet.getTimestamp(column);
|
143
|
+
if (nsecTimeHack.getNanos() != 0) {
|
144
|
+
strValue = String.format("%s.%09d", strValue, nsecTimeHack.getNanos());
|
145
|
+
}
|
146
|
+
|
147
|
+
return RubyString.newUnicodeString(runtime,strValue);
|
156
148
|
}
|
157
149
|
|
158
150
|
@Override
|
@@ -192,80 +184,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
192
184
|
}
|
193
185
|
|
194
186
|
@Override
|
195
|
-
protected
|
196
|
-
return withConnection(context, new Callable<IRubyObject>() {
|
197
|
-
public IRubyObject call(final Connection connection) throws SQLException {
|
198
|
-
final Ruby runtime = context.getRuntime();
|
199
|
-
final RubyModule indexDefinition = getIndexDefinition(runtime);
|
200
|
-
final String jdbcTableName = caseConvertIdentifierForJdbc(connection, tableName);
|
201
|
-
final String jdbcSchemaName = caseConvertIdentifierForJdbc(connection, schemaName);
|
202
|
-
final IRubyObject rubyTableName = RubyString.newUnicodeString(
|
203
|
-
runtime, caseConvertIdentifierForJdbc(connection, tableName)
|
204
|
-
);
|
205
|
-
|
206
|
-
StringBuilder query = new StringBuilder("SHOW KEYS FROM ");
|
207
|
-
if (jdbcSchemaName != null) {
|
208
|
-
query.append(jdbcSchemaName).append(".");
|
209
|
-
}
|
210
|
-
query.append(jdbcTableName);
|
211
|
-
query.append(" WHERE key_name != 'PRIMARY'");
|
212
|
-
|
213
|
-
final RubyArray indexes = runtime.newArray(8);
|
214
|
-
PreparedStatement statement = null;
|
215
|
-
ResultSet keySet = null;
|
216
|
-
|
217
|
-
try {
|
218
|
-
statement = connection.prepareStatement(query.toString());
|
219
|
-
keySet = statement.executeQuery();
|
220
|
-
|
221
|
-
String currentKeyName = null;
|
222
|
-
|
223
|
-
while ( keySet.next() ) {
|
224
|
-
final String keyName = caseConvertIdentifierForRails(connection, keySet.getString("key_name"));
|
225
|
-
|
226
|
-
if ( ! keyName.equals(currentKeyName) ) {
|
227
|
-
currentKeyName = keyName;
|
228
|
-
|
229
|
-
final boolean nonUnique = keySet.getBoolean("non_unique");
|
230
|
-
|
231
|
-
IRubyObject[] args = new IRubyObject[] {
|
232
|
-
rubyTableName, // table_name
|
233
|
-
RubyString.newUnicodeString(runtime, keyName), // index_name
|
234
|
-
runtime.newBoolean( ! nonUnique ), // unique
|
235
|
-
runtime.newArray(), // [] for column names, we'll add to that in just a bit
|
236
|
-
runtime.newArray() // lengths
|
237
|
-
};
|
238
|
-
|
239
|
-
indexes.append( indexDefinition.callMethod(context, "new", args) ); // IndexDefinition.new
|
240
|
-
}
|
241
|
-
|
242
|
-
IRubyObject lastIndexDef = indexes.isEmpty() ? null : indexes.entry(-1);
|
243
|
-
if ( lastIndexDef != null ) {
|
244
|
-
final String columnName = caseConvertIdentifierForRails(connection, keySet.getString("column_name"));
|
245
|
-
final int length = keySet.getInt("sub_part");
|
246
|
-
final boolean nullLength = keySet.wasNull();
|
247
|
-
|
248
|
-
lastIndexDef.callMethod(context, "columns").callMethod(context,
|
249
|
-
"<<", RubyString.newUnicodeString(runtime, columnName));
|
250
|
-
lastIndexDef.callMethod(context, "lengths").callMethod(context,
|
251
|
-
"<<", nullLength ? runtime.getNil() : runtime.newFixnum(length));
|
252
|
-
}
|
253
|
-
}
|
254
|
-
|
255
|
-
return indexes;
|
256
|
-
}
|
257
|
-
finally {
|
258
|
-
close(keySet);
|
259
|
-
close(statement);
|
260
|
-
}
|
261
|
-
}
|
262
|
-
});
|
263
|
-
}
|
264
|
-
|
265
|
-
@Override
|
266
|
-
protected String caseConvertIdentifierForRails(final Connection connection, final String value)
|
267
|
-
throws SQLException {
|
268
|
-
if ( value == null ) return null;
|
187
|
+
protected String caseConvertIdentifierForRails(Connection connection, String value) throws SQLException {
|
269
188
|
return value; // MySQL does not storesUpperCaseIdentifiers() :
|
270
189
|
}
|
271
190
|
|