activerecord-jdbc-adapter 1.1.3 → 1.2.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.
Files changed (68) hide show
  1. data/.gitignore +22 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +42 -0
  4. data/History.txt +10 -3
  5. data/{README.txt → README.rdoc} +30 -14
  6. data/Rakefile +49 -0
  7. data/activerecord-jdbc-adapter.gemspec +23 -0
  8. data/bench/bench_attributes.rb +13 -0
  9. data/bench/bench_attributes_new.rb +14 -0
  10. data/bench/bench_create.rb +12 -0
  11. data/bench/bench_find_all.rb +12 -0
  12. data/bench/bench_find_all_mt.rb +25 -0
  13. data/bench/bench_model.rb +85 -0
  14. data/bench/bench_new.rb +12 -0
  15. data/bench/bench_new_valid.rb +12 -0
  16. data/bench/bench_valid.rb +13 -0
  17. data/lib/activerecord-jdbc-adapter.rb +1 -1
  18. data/lib/arel/visitors/derby.rb +5 -1
  19. data/lib/arjdbc.rb +12 -17
  20. data/lib/arjdbc/db2/adapter.rb +91 -4
  21. data/lib/arjdbc/derby/adapter.rb +8 -8
  22. data/lib/arjdbc/derby/connection_methods.rb +1 -0
  23. data/lib/arjdbc/firebird/adapter.rb +4 -4
  24. data/lib/arjdbc/h2/adapter.rb +3 -2
  25. data/lib/arjdbc/h2/connection_methods.rb +1 -0
  26. data/lib/arjdbc/hsqldb/adapter.rb +5 -2
  27. data/lib/arjdbc/hsqldb/connection_methods.rb +1 -0
  28. data/lib/arjdbc/informix/adapter.rb +2 -2
  29. data/lib/arjdbc/informix/connection_methods.rb +1 -0
  30. data/lib/arjdbc/jdbc/adapter.rb +92 -22
  31. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  32. data/lib/arjdbc/mimer/adapter.rb +4 -4
  33. data/lib/arjdbc/mssql/adapter.rb +10 -8
  34. data/lib/arjdbc/mssql/connection_methods.rb +1 -0
  35. data/lib/arjdbc/mssql/limit_helpers.rb +7 -4
  36. data/lib/arjdbc/mysql/adapter.rb +30 -6
  37. data/lib/arjdbc/mysql/connection_methods.rb +1 -0
  38. data/lib/arjdbc/oracle/adapter.rb +15 -12
  39. data/lib/arjdbc/oracle/connection_methods.rb +1 -0
  40. data/lib/arjdbc/postgresql/adapter.rb +35 -16
  41. data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
  42. data/lib/arjdbc/sqlite3/adapter.rb +13 -10
  43. data/lib/arjdbc/sqlite3/connection_methods.rb +1 -0
  44. data/lib/arjdbc/version.rb +1 -1
  45. data/lib/generators/jdbc/USAGE +10 -0
  46. data/pom.xml +57 -0
  47. data/rakelib/rails.rake +1 -1
  48. data/rakelib/test.rake +20 -6
  49. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4 -1
  50. data/src/java/arjdbc/jdbc/SQLBlock.java +1 -1
  51. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +74 -0
  52. data/test/abstract_db_create.rb +8 -1
  53. data/test/activerecord/jall.sh +7 -0
  54. data/test/activerecord/jtest.sh +3 -0
  55. data/test/jdbc_common.rb +6 -4
  56. data/test/models/data_types.rb +1 -1
  57. data/test/models/string_id.rb +2 -0
  58. data/test/models/thing.rb +16 -0
  59. data/test/mysql_index_length_test.rb +58 -0
  60. data/test/mysql_info_test.rb +3 -3
  61. data/test/postgres_db_create_test.rb +1 -1
  62. data/test/simple.rb +11 -3
  63. data/test/sqlite3_simple_test.rb +16 -2
  64. metadata +167 -108
  65. data/.gemtest +0 -0
  66. data/Manifest.txt +0 -187
  67. data/rakelib/package.rake +0 -92
  68. data/test/pick_rails_version.rb +0 -3
@@ -13,6 +13,7 @@ class ActiveRecord::Base
13
13
  config[:url] ||= "jdbc:sqlite:#{database}"
14
14
  config[:driver] ||= "org.sqlite.JDBC"
15
15
  config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter
16
+ config[:adapter_spec] = ::ArJdbc::SQLite3
16
17
  jdbc_connection(config)
17
18
  end
18
19
 
@@ -1,6 +1,6 @@
1
1
  module ArJdbc
2
2
  module Version
3
- VERSION = "1.1.3"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
6
6
  # Compatibility with older versions of ar-jdbc for other extensions out there
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Creates stubs that ensure activerecord-jdbc is bootstrapped in
3
+ your Rails application.
4
+
5
+ Example:
6
+ ./script/generate jdbc
7
+
8
+ This will create:
9
+ config/initializers/jdbc.rb
10
+ lib/tasks/jdbc.rake
data/pom.xml ADDED
@@ -0,0 +1,57 @@
1
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3
+ <modelVersion>4.0.0</modelVersion>
4
+ <groupId>org.jruby.activerecord-jdbc</groupId>
5
+ <artifactId>activerecord-jdbc</artifactId>
6
+ <packaging>jar</packaging>
7
+ <version>1.0.0</version>
8
+ <name>activerecord-jdbc</name>
9
+ <description>
10
+ This POM for activerecord-jdbc is just for bootstrapping IDEs. You
11
+ can't use it to build the project at the moment.
12
+ </description>
13
+ <url>http://activerecord-jdbc.kenai.com/</url>
14
+
15
+ <issueManagement>
16
+ <system>JIRA</system>
17
+ <url>http://kenai.com/jira/browse/ACTIVERECORD_JDBC</url>
18
+ </issueManagement>
19
+
20
+ <scm>
21
+ <connection>scm:git:git://github.com/nicksieger/activerecord-jdbc-adapter.git</connection>
22
+ <developerConnection>scm:git:git@github.com:nicksieger/activerecord-jdbc-adapter.git</developerConnection>
23
+ <url>http://github.com/nicksieger/activerecord-jdbc-adapter</url>
24
+ </scm>
25
+
26
+ <licenses>
27
+ <license>
28
+ <name>BSD</name>
29
+ <url>http://www.opensource.org/licenses/bsd-license.php</url>
30
+ <distribution>repo</distribution>
31
+ </license>
32
+ </licenses>
33
+
34
+ <dependencies>
35
+ <dependency>
36
+ <groupId>org.jruby</groupId>
37
+ <artifactId>jruby-complete</artifactId>
38
+ <version>1.5.3</version>
39
+ </dependency>
40
+ </dependencies>
41
+
42
+ <build>
43
+ <outputDirectory>pkg/classes</outputDirectory>
44
+ <sourceDirectory>src/java</sourceDirectory>
45
+ <plugins>
46
+ <plugin>
47
+ <groupId>org.apache.maven.plugins</groupId>
48
+ <artifactId>maven-compiler-plugin</artifactId>
49
+ <configuration>
50
+ <source>1.5</source>
51
+ <target>1.5</target>
52
+ </configuration>
53
+ </plugin>
54
+ </plugins>
55
+ </build>
56
+
57
+ </project>
data/rakelib/rails.rake CHANGED
@@ -33,7 +33,7 @@ namespace :rails do
33
33
  raise "need location of RAILS source code" unless activerecord
34
34
  activerecord = File.join(activerecord, 'activerecord') unless activerecord =~ /activerecord$/
35
35
  ar_jdbc = File.expand_path(File.dirname(__FILE__) + '/..')
36
- rubylib = "#{ar_jdbc}/lib:#{ar_jdbc}/drivers/#{_driver(driver)}/lib:#{ar_jdbc}/adapters/#{_adapter(driver)}/lib"
36
+ rubylib = "#{ar_jdbc}/lib:#{ar_jdbc}/jdbc-#{_driver(driver)}/lib:#{ar_jdbc}/activerecord-jdbc#{_adapter(driver)}-adapter/lib"
37
37
  Dir.chdir(activerecord) do
38
38
  rake "RUBYLIB=#{rubylib}", "#{_target(driver)}"
39
39
  end
data/rakelib/test.rake CHANGED
@@ -12,6 +12,13 @@ else
12
12
  task :test => [:test_mysql]
13
13
  end
14
14
 
15
+ def set_compat_version(task)
16
+ task.ruby_opts << '-v'
17
+ if defined?(JRUBY_VERSION)
18
+ task.ruby_opts << "--#{RUBY_VERSION[/^(\d+\.\d+)/, 1]}"
19
+ end
20
+ end
21
+
15
22
  def declare_test_task_for(adapter, options = {})
16
23
  driver = options[:driver] || adapter
17
24
  Rake::TestTask.new("test_#{adapter}") do |t|
@@ -21,10 +28,11 @@ def declare_test_task_for(adapter, options = {})
21
28
  end
22
29
  t.test_files = files
23
30
  t.libs = []
31
+ set_compat_version(t)
24
32
  if defined?(JRUBY_VERSION)
25
33
  t.ruby_opts << "-rjdbc/#{driver}"
26
- t.libs << "lib" << "drivers/#{driver}/lib"
27
- t.libs.push *FileList["adapters/#{adapter}*/lib"]
34
+ t.libs << "lib" << "jdbc-#{driver}/lib"
35
+ t.libs.push *FileList["activerecord-jdbc#{adapter}*/lib"]
28
36
  end
29
37
  t.libs << "test"
30
38
  t.verbose = true
@@ -41,12 +49,14 @@ declare_test_task_for :sqlite3
41
49
 
42
50
  Rake::TestTask.new(:test_jdbc) do |t|
43
51
  t.test_files = FileList['test/generic_jdbc_connection_test.rb']
44
- t.libs << 'test' << 'drivers/mysql/lib'
52
+ t.libs << 'test' << 'jdbc-mysql/lib'
53
+ set_compat_version(t)
45
54
  end
46
55
 
47
56
  Rake::TestTask.new(:test_jndi) do |t|
48
57
  t.test_files = FileList['test/jndi*_test.rb']
49
- t.libs << 'test' << 'drivers/derby/lib'
58
+ t.libs << 'test' << 'jdbc-derby/lib'
59
+ set_compat_version(t)
50
60
  end
51
61
 
52
62
  task :test_postgresql => [:test_postgres]
@@ -59,6 +69,7 @@ task :test_pgsql => [:test_postgres]
59
69
  t.libs = []
60
70
  t.libs << 'lib' if defined?(JRUBY_VERSION)
61
71
  t.libs << 'test'
72
+ set_compat_version(t)
62
73
  end
63
74
  end
64
75
 
@@ -66,16 +77,19 @@ end
66
77
  Rake::TestTask.new(:test_jdbc_adapters) do | t |
67
78
  t.test_files = FileList[ 'test/jdbc_adapter/jdbc_sybase_test.rb' ]
68
79
  t.libs << 'test'
80
+ set_compat_version(t)
69
81
  end
70
82
 
71
83
  # Ensure that the jTDS driver is in your classpath before launching rake
72
84
  Rake::TestTask.new(:test_sybase_jtds) do |t|
73
85
  t.test_files = FileList['test/sybase_jtds_simple_test.rb']
74
- t.libs << 'test'
86
+ t.libs << 'test'
87
+ set_compat_version(t)
75
88
  end
76
89
 
77
90
  # Ensure that the jConnect driver is in your classpath before launching rake
78
91
  Rake::TestTask.new(:test_sybase_jconnect) do |t|
79
92
  t.test_files = FileList['test/sybase_jconnect_simple_test.rb']
80
- t.libs << 'test'
93
+ t.libs << 'test'
94
+ set_compat_version(t)
81
95
  end
@@ -817,8 +817,11 @@ public class RubyJdbcConnection extends RubyObject {
817
817
  case Types.BLOB:
818
818
  case Types.LONGVARBINARY:
819
819
  case Types.VARBINARY:
820
- case Types.LONGVARCHAR:
821
820
  return streamToRuby(runtime, resultSet, resultSet.getBinaryStream(column));
821
+ case Types.LONGVARCHAR:
822
+ return runtime.is1_9() ?
823
+ readerToRuby(runtime, resultSet, resultSet.getCharacterStream(column)) :
824
+ streamToRuby(runtime, resultSet, resultSet.getBinaryStream(column));
822
825
  case Types.CLOB:
823
826
  return readerToRuby(runtime, resultSet, resultSet.getCharacterStream(column));
824
827
  case Types.TIMESTAMP:
@@ -36,7 +36,7 @@ import java.sql.Statement;
36
36
  * @author nicksieger
37
37
  */
38
38
  public abstract class SQLBlock {
39
- abstract Object call(Connection c) throws SQLException;
39
+ protected abstract Object call(Connection c) throws SQLException;
40
40
 
41
41
  public void close(Statement statement) {
42
42
  RubyJdbcConnection.close(statement);
@@ -26,13 +26,21 @@
26
26
  package arjdbc.mysql;
27
27
 
28
28
  import java.sql.Connection;
29
+ import java.sql.DatabaseMetaData;
30
+ import java.sql.PreparedStatement;
29
31
  import java.sql.SQLException;
30
32
  import java.sql.ResultSet;
31
33
  import java.sql.Statement;
32
34
  import java.sql.Types;
35
+ import java.util.ArrayList;
36
+ import java.util.List;
33
37
 
38
+ import arjdbc.jdbc.SQLBlock;
34
39
  import org.jruby.Ruby;
35
40
  import org.jruby.RubyClass;
41
+ import org.jruby.RubyModule;
42
+ import org.jruby.RubyNil;
43
+ import org.jruby.RubyString;
36
44
  import org.jruby.runtime.ObjectAllocator;
37
45
  import org.jruby.runtime.ThreadContext;
38
46
  import org.jruby.runtime.builtin.IRubyObject;
@@ -84,4 +92,70 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
84
92
  return new MySQLRubyJdbcConnection(runtime, klass);
85
93
  }
86
94
  };
95
+
96
+ @Override
97
+ protected IRubyObject indexes(final ThreadContext context, final String tableNameArg, String name, final String schemaNameArg) {
98
+ return (IRubyObject) withConnectionAndRetry(context, new SQLBlock() {
99
+ @Override
100
+ public Object call(Connection connection) throws SQLException {
101
+ Ruby runtime = context.getRuntime();
102
+ DatabaseMetaData metadata = connection.getMetaData();
103
+ String jdbcTableName = caseConvertIdentifierForJdbc(metadata, tableNameArg);
104
+ String jdbcSchemaName = caseConvertIdentifierForJdbc(metadata, schemaNameArg);
105
+
106
+ StringBuilder buffer = new StringBuilder("SHOW KEYS FROM ");
107
+ if (jdbcSchemaName != null) buffer.append(jdbcSchemaName).append(".");
108
+ buffer.append(jdbcTableName);
109
+ buffer.append(" WHERE key_name != 'PRIMARY'");
110
+ String query = buffer.toString();
111
+
112
+ List<IRubyObject> indexes = new ArrayList<IRubyObject>();
113
+ PreparedStatement stmt = null;
114
+ ResultSet rs = null;
115
+
116
+ try {
117
+ stmt = connection.prepareStatement(query);
118
+ rs = stmt.executeQuery();
119
+
120
+ IRubyObject rubyTableName = RubyString.newUnicodeString(runtime, caseConvertIdentifierForJdbc(metadata, tableNameArg));
121
+ RubyModule indexDefinitionClass = getConnectionAdapters(runtime).getClass("IndexDefinition");
122
+ String currentKeyName = null;
123
+
124
+ while (rs.next()) {
125
+ String keyName = caseConvertIdentifierForRails(metadata, rs.getString("key_name"));
126
+
127
+ if (!keyName.equals(currentKeyName)) {
128
+ currentKeyName = keyName;
129
+
130
+ boolean nonUnique = rs.getBoolean("non_unique");
131
+ IRubyObject indexDefinition = indexDefinitionClass.callMethod(context, "new", new IRubyObject[]{
132
+ rubyTableName,
133
+ RubyString.newUnicodeString(runtime, keyName),
134
+ runtime.newBoolean(!nonUnique),
135
+ runtime.newArray(),
136
+ runtime.newArray()
137
+ });
138
+
139
+ indexes.add(indexDefinition);
140
+ }
141
+
142
+ IRubyObject lastIndex = indexes.get(indexes.size() - 1);
143
+ if (lastIndex != null) {
144
+ String columnName = caseConvertIdentifierForRails(metadata, rs.getString("column_name"));
145
+ int length = rs.getInt("sub_part");
146
+ boolean lengthIsNull = rs.wasNull();
147
+
148
+ lastIndex.callMethod(context, "columns").callMethod(context, "<<", RubyString.newUnicodeString(runtime, columnName));
149
+ lastIndex.callMethod(context, "lengths").callMethod(context, "<<", lengthIsNull ? runtime.getNil() : runtime.newFixnum(length));
150
+ }
151
+ }
152
+
153
+ return runtime.newArray(indexes);
154
+ } finally {
155
+ close(rs);
156
+ close(stmt);
157
+ }
158
+ }
159
+ });
160
+ }
87
161
  }
@@ -8,6 +8,9 @@ module Rails
8
8
  def self.config
9
9
  @config ||= Object.new
10
10
  end
11
+ def self.paths
12
+ @paths ||= Hash.new { [] }
13
+ end
11
14
  end
12
15
  def self.application
13
16
  Rails::Application
@@ -89,8 +92,12 @@ module AbstractDbCreate
89
92
  (class << Rails::Application.config; self ; end).instance_eval do
90
93
  define_method(:database_configuration) { configs }
91
94
  end
95
+ require 'pathname'
92
96
  ar_version = $LOADED_FEATURES.grep(%r{active_record/version}).first
93
- ar_lib_path = $LOAD_PATH.detect {|p| p if File.exist?File.join(p, ar_version)}
97
+ ar_lib_path = $LOAD_PATH.detect do |p|
98
+ Pathname.new(p).absolute? && ar_version.start_with?(p) ||
99
+ File.exist?(File.join(p, ar_version))
100
+ end
94
101
  load "#{ar_lib_path}/active_record/railties/databases.rake"
95
102
  end
96
103
 
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ for test in *_test.rb; do
4
+ ./jtest.sh $test
5
+ done
6
+
7
+ #jruby.sh -I connections/native_jdbc_mysql -e 'Dir.foreach(".") { |file| require file if file =~ /_test.rb$/ }' | tee all.log
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ jruby.sh -I connections/native_jdbc_mysql $1 | tee $1.log
data/test/jdbc_common.rb CHANGED
@@ -3,23 +3,25 @@ def jruby?
3
3
  defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
4
4
  end
5
5
 
6
- require 'rubygems'
7
- require 'pick_rails_version'
8
6
  require 'arjdbc' if jruby?
9
7
  puts "Using activerecord version #{ActiveRecord::VERSION::STRING}"
10
- puts "Specify version with AR_VERSION=={version} or RUBYLIB={path}"
8
+ puts "Specify version with AR_VERSION={version} or RUBYLIB={path}"
11
9
  require 'models/auto_id'
12
10
  require 'models/entry'
13
11
  require 'models/data_types'
14
12
  require 'models/add_not_null_column_to_table'
15
13
  require 'models/validates_uniqueness_of_string'
16
14
  require 'models/string_id'
15
+ require 'models/thing'
17
16
  require 'simple'
18
17
  require 'has_many_through'
19
18
  require 'helper'
20
19
  require 'test/unit'
21
20
 
22
21
  # Comment/uncomment to enable logging to be loaded for any of the database adapters
23
- require 'db/logger' if $DEBUG || ENV['DEBUG']
22
+ if $DEBUG || ENV['DEBUG']
23
+ require 'db/logger'
24
+ require 'ruby-debug'
25
+ end
24
26
 
25
27
 
@@ -16,7 +16,7 @@ class DbTypeMigration < ActiveRecord::Migration
16
16
  t.column :sample_integer_with_limit_2, :integer, :limit => 2
17
17
  t.column :sample_integer_with_limit_8, :integer, :limit => 8
18
18
  t.column :sample_integer_no_limit, :integer
19
- t.column :sample_integer_negative_default, :integer, :default => -1
19
+ t.column :sample_integer_neg_default, :integer, :default => -1
20
20
  t.column :sample_text, :text
21
21
  end
22
22
  end
@@ -12,4 +12,6 @@ end
12
12
 
13
13
  class StringId < ActiveRecord::Base
14
14
  def self.table_name () "string_ids" end
15
+ # Fake out a table without a primary key
16
+ self.primary_key = "id"
15
17
  end
@@ -0,0 +1,16 @@
1
+ class CreateThings < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :things, :id => false do |t|
4
+ t.string :name
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :things
12
+ end
13
+ end
14
+
15
+ class Thing < ActiveRecord::Base
16
+ end
@@ -0,0 +1,58 @@
1
+ require 'jdbc_common'
2
+ require 'db/mysql'
3
+
4
+ class MySQLIndexLengthDBSetup < ActiveRecord::Migration
5
+ def self.up
6
+ execute <<-SQL
7
+ CREATE TABLE index_length_test (
8
+ int_column INT,
9
+ text_column TEXT,
10
+ second_text_column TEXT,
11
+ INDEX ix_int (int_column),
12
+ INDEX ix_length_text (text_column(255))
13
+ )
14
+ SQL
15
+ end
16
+
17
+ def self.down
18
+ drop_table 'index_length_test'
19
+ end
20
+ end
21
+
22
+ class MySQLIndexLengthTest < Test::Unit::TestCase
23
+ def setup
24
+ MySQLIndexLengthDBSetup.up
25
+ @connection = ActiveRecord::Base.connection
26
+ end
27
+
28
+ def teardown
29
+ MySQLIndexLengthDBSetup.down
30
+ end
31
+
32
+ def test_index_length
33
+ index = @connection.indexes('index_length_test').find { |idx| idx.name == 'ix_length_text' }
34
+ assert_not_nil index
35
+ assert_equal "index_length_test", index.table
36
+ assert_equal "ix_length_text", index.name
37
+ assert !index.unique
38
+ assert_equal ["text_column"], index.columns
39
+ assert_equal [255], index.lengths
40
+ end
41
+
42
+ def test_add_index
43
+ @connection.add_index 'index_length_test', ['text_column', 'second_text_column'],
44
+ :name => 'added_index', :length => {'text_column' => 32, 'second_text_column' => 64}
45
+
46
+ index = @connection.indexes('index_length_test').find { |idx| idx.name == 'added_index' }
47
+ assert_not_nil index
48
+ assert_equal ['text_column', 'second_text_column'], index.columns
49
+ assert_equal [32, 64], index.lengths
50
+ end
51
+
52
+ def test_index_without_length
53
+ index = @connection.indexes('index_length_test').find { |idx| idx.name == 'ix_int' }
54
+ assert_not_nil index
55
+ assert_equal ['int_column'], index.columns
56
+ assert_equal [nil], index.lengths
57
+ end
58
+ end