activerecord-jdbc-adapter 1.1.3 → 1.2.0

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