activerecord-jdbc-adapter 0.7.2 → 0.8

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.
@@ -1,3 +1,17 @@
1
+ == 0.8
2
+
3
+ - NOTE: This release is only compatible with JRuby 1.1RC3 or later.
4
+ - Because of recent API changes in trunk in preparation for JRuby 1.1, this release is not
5
+ backward compatible with previous JRuby releases. Hence the version bump.
6
+ - Internal: convert Java methods to be defined with annotations
7
+ - Fix problem with reserved words coming back pre-quoted from #indexes in postgres
8
+ - JRUBY-2205: Fix N^2 allocation of bytelists for mysql quoting (taw)
9
+ - Attempt a fix for Rubyforge 18059
10
+ - Upgrade derby to 10.3.2.1
11
+ - Fix db:create etc. in the case where JDBC is loaded in Rails' preinitializer.rb
12
+ - Fix db:drop to actually work
13
+ - Fix for Rubyforge #11567 (Matt Williams)
14
+
1
15
  == 0.7.2
2
16
 
3
17
  - JRUBY-1905: add_column for derby, hsqldb, and postgresql (Stephen Bannasch)
@@ -1,5 +1,5 @@
1
- Copyright (c) 2006-2007 Nick Sieger <nick@nicksieger.com>
2
- Copyright (c) 2006-2007 Ola Bini <ola@ologix.com>
1
+ Copyright (c) 2006-2008 Nick Sieger <nick@nicksieger.com>
2
+ Copyright (c) 2006-2008 Ola Bini <ola.bini@gmail.com>
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -2,7 +2,7 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
- LICENSE
5
+ LICENSE.txt
6
6
  lib/active_record/connection_adapters/derby_adapter.rb
7
7
  lib/active_record/connection_adapters/h2_adapter.rb
8
8
  lib/active_record/connection_adapters/hsqldb_adapter.rb
@@ -60,11 +60,14 @@ test/models/add_not_null_column_to_table.rb
60
60
  test/models/auto_id.rb
61
61
  test/models/data_types.rb
62
62
  test/models/entry.rb
63
+ test/models/reserved_word.rb
63
64
  test/mysql_multibyte_test.rb
64
65
  test/mysql_simple_test.rb
65
66
  test/oracle_simple_test.rb
67
+ test/postgres_reserved_test.rb
66
68
  test/postgres_simple_test.rb
67
69
  test/simple.rb
70
+ lib/jdbc_adapter/jdbc.rake
68
71
  src/java/jdbc_adapter/JdbcAdapterInternalService.java
69
72
  src/java/jdbc_adapter/JdbcConnectionFactory.java
70
73
  src/java/jdbc_adapter/JdbcDerbySpec.java
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ task :java_compile do
20
20
  pkg_classes = File.join(*%w(pkg classes))
21
21
  jar_name = File.join(*%w(lib jdbc_adapter jdbc_adapter_internal.jar))
22
22
  mkdir_p pkg_classes
23
- sh "javac -target 1.4 -source 1.4 -d pkg/classes #{java_classpath_arg} #{FileList['src/java/**/*.java'].join(' ')}"
23
+ sh "javac -target 1.5 -source 1.5 -d pkg/classes #{java_classpath_arg} #{FileList['src/java/**/*.java'].join(' ')}"
24
24
  sh "jar cf #{jar_name} -C #{pkg_classes} ."
25
25
  end
26
26
  file "lib/jdbc_adapter/jdbc_adapter_internal.jar" => :java_compile
@@ -87,7 +87,7 @@ end
87
87
 
88
88
 
89
89
  MANIFEST = FileList["History.txt", "Manifest.txt", "README.txt",
90
- "Rakefile", "LICENSE", "lib/**/*.rb", "lib/jdbc_adapter/jdbc_adapter_internal.jar", "test/**/*.rb",
90
+ "Rakefile", "LICENSE.txt", "lib/**/*.rb", "lib/jdbc_adapter/jdbc_adapter_internal.jar", "test/**/*.rb",
91
91
  "lib/**/*.rake", "src/**/*.java"]
92
92
 
93
93
  file "Manifest.txt" => :manifest
@@ -342,19 +342,19 @@ module ActiveRecord
342
342
  next unless index_name
343
343
  index_name.downcase!
344
344
  column_name = resultset.get_string(Jdbc::IndexMetaData::COLUMN_NAME).downcase
345
-
345
+
346
346
  next if primary_keys.include? column_name
347
-
347
+
348
348
  # We are working on a new index
349
349
  if current_index != index_name
350
350
  current_index = index_name
351
351
  table_name = resultset.get_string(Jdbc::IndexMetaData::TABLE_NAME).downcase
352
352
  non_unique = resultset.get_boolean(Jdbc::IndexMetaData::NON_UNIQUE)
353
-
353
+
354
354
  # empty list for column names, we'll add to that in just a bit
355
355
  indexes << IndexDefinition.new(table_name, index_name, !non_unique, [])
356
356
  end
357
-
357
+
358
358
  # One or more columns can be associated with an index
359
359
  indexes.last.columns << column_name
360
360
  end
@@ -404,7 +404,19 @@ module ActiveRecord
404
404
 
405
405
  end
406
406
 
407
+ module ShadowCoreMethods
408
+ def alias_chained_method(meth, feature, target)
409
+ if instance_methods.include?("#{meth}_without_#{feature}")
410
+ alias_method "#{meth}_without_#{feature}".to_sym, target
411
+ else
412
+ alias_method meth, target
413
+ end
414
+ end
415
+ end
416
+
407
417
  class JdbcAdapter < AbstractAdapter
418
+ extend ShadowCoreMethods
419
+
408
420
  attr_reader :config
409
421
 
410
422
  ADAPTER_TYPES = ::JdbcSpec.constants.map{|c|
@@ -484,14 +496,15 @@ module ActiveRecord
484
496
  @connection.reconnect!
485
497
  @connection
486
498
  end
487
-
499
+
488
500
  def disconnect!
489
501
  @connection.disconnect!
490
502
  end
491
503
 
492
- def select_all(sql, name = nil)
504
+ def jdbc_select_all(sql, name = nil)
493
505
  select(sql, name)
494
506
  end
507
+ alias_chained_method :select_all, :query_cache, :jdbc_select_all
495
508
 
496
509
  def select_rows(sql, name = nil)
497
510
  rows = []
@@ -508,8 +521,7 @@ module ActiveRecord
508
521
  _execute(sql,name)
509
522
  end
510
523
  end
511
-
512
-
524
+
513
525
  # we need to do it this way, to allow Rails stupid tests to always work
514
526
  # even if we define a new execute method. Instead of mixing in a new
515
527
  # execute, an _execute should be mixed in.
@@ -523,18 +535,21 @@ module ActiveRecord
523
535
  end
524
536
  end
525
537
 
526
- def update(sql, name = nil) #:nodoc:
538
+ def jdbc_update(sql, name = nil) #:nodoc:
527
539
  execute(sql, name)
528
540
  end
541
+ alias_chained_method :update, :query_dirty, :jdbc_update
529
542
 
530
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
543
+ def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
531
544
  id = execute(sql, name = nil)
532
545
  id_value || id
533
546
  end
547
+ alias_chained_method :insert, :query_dirty, :jdbc_insert
534
548
 
535
- def columns(table_name, name = nil)
549
+ def jdbc_columns(table_name, name = nil)
536
550
  @connection.columns(table_name.to_s)
537
551
  end
552
+ alias_chained_method :columns, :query_cache, :jdbc_columns
538
553
 
539
554
  def tables
540
555
  @connection.tables
@@ -0,0 +1,78 @@
1
+ def redefine_task(*args, &block)
2
+ task_name = Hash === args.first ? args.first.keys[0] : args.first
3
+ existing_task = Rake.application.lookup task_name
4
+ if existing_task
5
+ class << existing_task; public :instance_variable_set; end
6
+ existing_task.instance_variable_set "@prerequisites", FileList[]
7
+ existing_task.instance_variable_set "@actions", []
8
+ end
9
+ task(*args, &block)
10
+ end
11
+
12
+ namespace :db do
13
+ redefine_task :create => :environment do
14
+ create_database(ActiveRecord::Base.configurations[RAILS_ENV])
15
+ end
16
+
17
+ class << self; alias_method :previous_create_database, :create_database; end
18
+ def create_database(config)
19
+ begin
20
+ ActiveRecord::Base.establish_connection(config)
21
+ ActiveRecord::Base.connection
22
+ rescue
23
+ begin
24
+ url = config['url']
25
+ if url
26
+ if url =~ /^(.*\/)/
27
+ url = $1
28
+ end
29
+ end
30
+
31
+ ActiveRecord::Base.establish_connection(config.merge({'database' => nil, 'url' => url}))
32
+ ActiveRecord::Base.connection.create_database(config['database'])
33
+ ActiveRecord::Base.establish_connection(config)
34
+ rescue
35
+ previous_create_database(config)
36
+ end
37
+ end
38
+ end
39
+
40
+ redefine_task :drop => :environment do
41
+ config = ActiveRecord::Base.configurations[RAILS_ENV]
42
+ begin
43
+ ActiveRecord::Base.establish_connection(config)
44
+ db = ActiveRecord::Base.connection.database_name
45
+ ActiveRecord::Base.connection.drop_database(db)
46
+ rescue
47
+ drop_database(config)
48
+ end
49
+ end
50
+
51
+ namespace :structure do
52
+ redefine_task :dump => :environment do
53
+ abcs = ActiveRecord::Base.configurations
54
+ ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
55
+ File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
56
+ if ActiveRecord::Base.connection.supports_migrations?
57
+ File.open("db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
58
+ end
59
+ end
60
+ end
61
+ namespace :test do
62
+ redefine_task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
63
+ abcs = ActiveRecord::Base.configurations
64
+ ActiveRecord::Base.establish_connection(:test)
65
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') if abcs["test"]["adapter"] =~ /mysql/i
66
+ IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
67
+ ActiveRecord::Base.connection.execute(ddl)
68
+ end
69
+ end
70
+
71
+ redefine_task :purge => :environment do
72
+ abcs = ActiveRecord::Base.configurations
73
+ ActiveRecord::Base.establish_connection(:test)
74
+ db = ActiveRecord::Base.connection.database_name
75
+ ActiveRecord::Base.connection.recreate_database(db)
76
+ end
77
+ end
78
+ end
@@ -157,6 +157,17 @@ module ::JdbcSpec
157
157
  Integer(select_value("SELECT IDENTITY() FROM #{table}"))
158
158
  end
159
159
 
160
+ # Override normal #_execute: See Rubyforge #11567
161
+ def _execute(sql, name = nil)
162
+ if ::ActiveRecord::ConnectionAdapters::JdbcConnection::select?(sql)
163
+ @connection.execute_query(sql)
164
+ elsif ::ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql)
165
+ insert(sql, name)
166
+ else
167
+ @connection.execute_update(sql)
168
+ end
169
+ end
170
+
160
171
  def add_limit_offset!(sql, options) #:nodoc:
161
172
  offset = options[:offset] || 0
162
173
  bef = sql[7..-1]
@@ -6,9 +6,6 @@ module ::JdbcSpec
6
6
 
7
7
  module ActiveRecordExtensions
8
8
  def mysql_connection(config)
9
- if config[:socket]
10
- warn "AR-JDBC MySQL on JRuby does not support sockets"
11
- end
12
9
  config[:port] ||= 3306
13
10
  if config[:url]
14
11
  config[:url] = config[:url]['?'] ? "#{config[:url]}&#{MySQL::URL_OPTIONS}" : "#{config[:url]}?#{MySQL::URL_OPTIONS}"
@@ -147,8 +144,12 @@ module ::JdbcSpec
147
144
  create_database(name)
148
145
  end
149
146
 
150
- def create_database(name) #:nodoc:
151
- execute "CREATE DATABASE `#{name}`"
147
+ def create_database(name, options = {}) #:nodoc:
148
+ if options[:collation]
149
+ execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`"
150
+ else
151
+ execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`"
152
+ end
152
153
  end
153
154
 
154
155
  def drop_database(name) #:nodoc:
@@ -177,7 +177,41 @@ module ::JdbcSpec
177
177
  end
178
178
  @connection.columns_internal(table_name, name, schema_name)
179
179
  end
180
-
180
+
181
+ # From postgresql_adapter.rb
182
+ def indexes(table_name, name = nil)
183
+ result = select_rows(<<-SQL, name)
184
+ SELECT i.relname, d.indisunique, a.attname
185
+ FROM pg_class t, pg_class i, pg_index d, pg_attribute a
186
+ WHERE i.relkind = 'i'
187
+ AND d.indexrelid = i.oid
188
+ AND d.indisprimary = 'f'
189
+ AND t.oid = d.indrelid
190
+ AND t.relname = '#{table_name}'
191
+ AND a.attrelid = t.oid
192
+ AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum
193
+ OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum
194
+ OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum
195
+ OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum
196
+ OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum )
197
+ ORDER BY i.relname
198
+ SQL
199
+
200
+ current_index = nil
201
+ indexes = []
202
+
203
+ result.each do |row|
204
+ if current_index != row[0]
205
+ indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, row[0], row[1] == "t", [])
206
+ current_index = row[0]
207
+ end
208
+
209
+ indexes.last.columns << row[2]
210
+ end
211
+
212
+ indexes
213
+ end
214
+
181
215
  def last_insert_id(table, sequence_name)
182
216
  Integer(select_value("SELECT currval('#{sequence_name}')"))
183
217
  end
@@ -1,82 +1,10 @@
1
- if defined?(namespace) && RUBY_PLATFORM =~ /java/ && ENV["SKIP_AR_JDBC_RAKE_REDEFINES"].nil?
2
- def redefine_task(*args, &block)
3
- task_name = Hash === args.first ? args.first.keys[0] : args.first
4
- existing_task = Rake.application.lookup task_name
5
- if existing_task
6
- class << existing_task; public :instance_variable_set; end
7
- existing_task.instance_variable_set "@prerequisites", FileList[]
8
- existing_task.instance_variable_set "@actions", []
9
- end
10
- task(*args, &block)
11
- end
12
-
13
- namespace :db do
14
- redefine_task :create => :environment do
15
- create_database(ActiveRecord::Base.configurations[RAILS_ENV])
16
- end
17
-
18
- def create_database(config)
19
- begin
20
- ActiveRecord::Base.establish_connection(config)
21
- ActiveRecord::Base.connection
22
- rescue
23
- begin
24
- url = config['url']
25
- if url
26
- if url =~ /^(.*\/)/
27
- url = $1
28
- end
29
- end
30
-
31
- ActiveRecord::Base.establish_connection(config.merge({'database' => nil, 'url' => url}))
32
- ActiveRecord::Base.connection.create_database(config['database'])
33
- ActiveRecord::Base.establish_connection(config)
34
- rescue
35
- if (config['driver'] || config['adapter']) =~ /postgr/
36
- `createdb "#{config['database']}" -E utf8`
37
- else
38
- warn "couldn't create database #{config['database']}"
39
- end
40
- end
41
- end
42
- end
43
-
44
- redefine_task :drop => :environment do
45
- begin
46
- config = ActiveRecord::Base.configurations[environment_name]
47
- ActiveRecord::Base.establish_connection(config)
48
- db = ActiveRecord::Base.connection.database_name
49
- ActiveRecord::Base.connection.recreate_database(db)
50
- rescue
51
- end
52
- end
53
-
54
- namespace :structure do
55
- redefine_task :dump => :environment do
56
- abcs = ActiveRecord::Base.configurations
57
- ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
58
- File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
59
- if ActiveRecord::Base.connection.supports_migrations?
60
- File.open("db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
61
- end
62
- end
63
- end
64
- namespace :test do
65
- redefine_task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
66
- abcs = ActiveRecord::Base.configurations
67
- ActiveRecord::Base.establish_connection(:test)
68
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') if abcs["test"]["adapter"] =~ /mysql/i
69
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
70
- ActiveRecord::Base.connection.execute(ddl)
71
- end
72
- end
73
-
74
- redefine_task :purge => :environment do
75
- abcs = ActiveRecord::Base.configurations
76
- ActiveRecord::Base.establish_connection(:test)
77
- db = ActiveRecord::Base.connection.database_name
78
- ActiveRecord::Base.connection.recreate_database(db)
79
- end
80
- end
1
+ if defined?(Rake.application) && Rake.application && ENV["SKIP_AR_JDBC_RAKE_REDEFINES"].nil?
2
+ jdbc_rakefile = File.dirname(__FILE__) + "/jdbc.rake"
3
+ if Rake.application.lookup("environment")
4
+ # rails tasks already defined; load the override tasks now
5
+ load jdbc_rakefile
6
+ else
7
+ # rails tasks not loaded yet; load as an import
8
+ Rake.application.add_import(jdbc_rakefile)
81
9
  end
82
10
  end
@@ -1,5 +1,5 @@
1
1
  module JdbcAdapter
2
2
  module Version
3
- VERSION = "0.7.2"
3
+ VERSION = "0.8"
4
4
  end
5
5
  end
@@ -59,14 +59,13 @@ import org.jruby.RubyObjectAdapter;
59
59
  import org.jruby.RubyString;
60
60
  import org.jruby.RubySymbol;
61
61
  import org.jruby.RubyTime;
62
- import org.jruby.
63
- exceptions.RaiseException;
62
+ import org.jruby.anno.JRubyMethod;
63
+ import org.jruby.exceptions.RaiseException;
64
64
  import org.jruby.javasupport.Java;
65
65
  import org.jruby.javasupport.JavaEmbedUtils;
66
66
  import org.jruby.javasupport.JavaObject;
67
67
  import org.jruby.runtime.Arity;
68
68
  import org.jruby.runtime.Block;
69
- import org.jruby.runtime.CallbackFactory;
70
69
  import org.jruby.runtime.ThreadContext;
71
70
  import org.jruby.runtime.builtin.IRubyObject;
72
71
  import org.jruby.runtime.load.BasicLibraryService;
@@ -76,43 +75,14 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
76
75
  private static RubyObjectAdapter rubyApi;
77
76
 
78
77
  public boolean basicLoad(final Ruby runtime) throws IOException {
79
- RubyClass cJdbcConn = ((RubyModule)(runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).
78
+ RubyModule jdbcConnection = ((RubyModule)(runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).
80
79
  defineClassUnder("JdbcConnection",runtime.getObject(),runtime.getObject().getAllocator());
81
-
82
- CallbackFactory cf = runtime.callbackFactory(JdbcAdapterInternalService.class);
83
- cJdbcConn.defineMethod("unmarshal_result",cf.getSingletonMethod("unmarshal_result", IRubyObject.class));
84
- cJdbcConn.defineMethod("with_connection_retry_guard",cf.getSingletonMethod("with_connection_retry_guard"));
85
- cJdbcConn.defineFastMethod("connection",cf.getFastSingletonMethod("connection"));
86
- cJdbcConn.defineFastMethod("reconnect!",cf.getFastSingletonMethod("reconnect"));
87
- cJdbcConn.defineFastMethod("disconnect!",cf.getFastSingletonMethod("disconnect"));
88
- cJdbcConn.defineFastMethod("execute_update",cf.getFastSingletonMethod("execute_update", IRubyObject.class));
89
- cJdbcConn.defineFastMethod("execute_query",cf.getFastOptSingletonMethod("execute_query"));
90
- cJdbcConn.defineFastMethod("execute_insert",cf.getFastSingletonMethod("execute_insert", IRubyObject.class));
91
- cJdbcConn.defineFastMethod("execute_id_insert",cf.getFastSingletonMethod("execute_id_insert", IRubyObject.class, IRubyObject.class));
92
- cJdbcConn.defineFastMethod("primary_keys",cf.getFastSingletonMethod("primary_keys", IRubyObject.class));
93
- cJdbcConn.defineFastMethod("set_native_database_types",cf.getFastSingletonMethod("set_native_database_types"));
94
- cJdbcConn.defineFastMethod("native_database_types",cf.getFastSingletonMethod("native_database_types"));
95
- cJdbcConn.defineFastMethod("begin",cf.getFastSingletonMethod("begin"));
96
- cJdbcConn.defineFastMethod("commit",cf.getFastSingletonMethod("commit"));
97
- cJdbcConn.defineFastMethod("rollback",cf.getFastSingletonMethod("rollback"));
98
- cJdbcConn.defineFastMethod("database_name",cf.getFastSingletonMethod("database_name"));
99
- cJdbcConn.defineFastMethod("columns",cf.getFastOptSingletonMethod("columns_internal"));
100
- cJdbcConn.defineFastMethod("columns_internal",cf.getFastOptSingletonMethod("columns_internal"));
101
- cJdbcConn.defineFastMethod("tables",cf.getFastOptSingletonMethod("tables"));
102
-
103
- cJdbcConn.defineFastMethod("insert_bind",cf.getFastOptSingletonMethod("insert_bind"));
104
- cJdbcConn.defineFastMethod("update_bind",cf.getFastOptSingletonMethod("update_bind"));
105
-
106
- cJdbcConn.defineFastMethod("write_large_object",cf.getFastOptSingletonMethod("write_large_object"));
107
-
108
- cJdbcConn.getMetaClass().defineFastMethod("insert?",cf.getFastSingletonMethod("insert_p", IRubyObject.class));
109
- cJdbcConn.getMetaClass().defineFastMethod("select?",cf.getFastSingletonMethod("select_p", IRubyObject.class));
110
-
80
+ jdbcConnection.defineAnnotatedMethods(JdbcAdapterInternalService.class);
111
81
  RubyModule jdbcSpec = runtime.getOrCreateModule("JdbcSpec");
112
82
 
113
83
  rubyApi = JavaEmbedUtils.newObjectAdapter();
114
- JdbcMySQLSpec.load(runtime, jdbcSpec);
115
- JdbcDerbySpec.load(runtime, jdbcSpec, rubyApi);
84
+ JdbcMySQLSpec.load(jdbcSpec);
85
+ JdbcDerbySpec.load(jdbcSpec, rubyApi);
116
86
  return true;
117
87
  }
118
88
 
@@ -132,6 +102,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
132
102
  return p;
133
103
  }
134
104
 
105
+ @JRubyMethod(name = "insert?", required = 1, meta = true)
135
106
  public static IRubyObject insert_p(IRubyObject recv, IRubyObject _sql) {
136
107
  ByteList bl = rubyApi.convertToRubyString(_sql).getByteList();
137
108
 
@@ -170,6 +141,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
170
141
  return recv.getRuntime().getFalse();
171
142
  }
172
143
 
144
+ @JRubyMethod(name = "select?", required = 1, meta = true)
173
145
  public static IRubyObject select_p(IRubyObject recv, IRubyObject _sql) {
174
146
  ByteList bl = rubyApi.convertToRubyString(_sql).getByteList();
175
147
 
@@ -225,6 +197,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
225
197
  return recv.getRuntime().getFalse();
226
198
  }
227
199
 
200
+ @JRubyMethod(name = "connection")
228
201
  public static IRubyObject connection(IRubyObject recv) {
229
202
  Connection c = getConnection(recv);
230
203
  if (c == null) {
@@ -233,16 +206,19 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
233
206
  return rubyApi.getInstanceVariable(recv, "@connection");
234
207
  }
235
208
 
209
+ @JRubyMethod(name = "disconnect!")
236
210
  public static IRubyObject disconnect(IRubyObject recv) {
237
211
  setConnection(recv, null);
238
212
  return recv;
239
213
  }
240
214
 
215
+ @JRubyMethod(name = "reconnect!")
241
216
  public static IRubyObject reconnect(IRubyObject recv) {
242
217
  setConnection(recv, getConnectionFactory(recv).newConnection());
243
218
  return recv;
244
219
  }
245
220
 
221
+ @JRubyMethod(name = "with_connection_retry_guard", frame = true)
246
222
  public static IRubyObject with_connection_retry_guard(final IRubyObject recv, final Block block) {
247
223
  return withConnectionAndRetry(recv, new SQLBlock() {
248
224
  public IRubyObject call(Connection c) throws SQLException {
@@ -323,6 +299,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
323
299
  };
324
300
  }
325
301
 
302
+ @JRubyMethod(name = "tables", rest = true)
326
303
  public static IRubyObject tables(final IRubyObject recv, IRubyObject[] args) {
327
304
  final Ruby runtime = recv.getRuntime();
328
305
  final String catalog = getCatalog(args);
@@ -371,10 +348,12 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
371
348
  return types;
372
349
  }
373
350
 
351
+ @JRubyMethod(name = "native_database_types")
374
352
  public static IRubyObject native_database_types(IRubyObject recv) {
375
353
  return rubyApi.getInstanceVariable(recv, "@tps");
376
354
  }
377
355
 
356
+ @JRubyMethod(name = "set_native_database_types")
378
357
  public static IRubyObject set_native_database_types(IRubyObject recv) throws SQLException, IOException {
379
358
  Ruby runtime = recv.getRuntime();
380
359
  IRubyObject types = unmarshal_result_downcase(recv, getConnection(recv).getMetaData().getTypeInfo());
@@ -384,6 +363,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
384
363
  return runtime.getNil();
385
364
  }
386
365
 
366
+ @JRubyMethod(name = "database_name")
387
367
  public static IRubyObject database_name(IRubyObject recv) throws SQLException {
388
368
  String name = getConnection(recv).getCatalog();
389
369
  if(null == name) {
@@ -395,11 +375,13 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
395
375
  return recv.getRuntime().newString(name);
396
376
  }
397
377
 
378
+ @JRubyMethod(name = "begin")
398
379
  public static IRubyObject begin(IRubyObject recv) throws SQLException {
399
380
  getConnection(recv).setAutoCommit(false);
400
381
  return recv.getRuntime().getNil();
401
382
  }
402
383
 
384
+ @JRubyMethod(name = "commit")
403
385
  public static IRubyObject commit(IRubyObject recv) throws SQLException {
404
386
  try {
405
387
  getConnection(recv).commit();
@@ -409,6 +391,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
409
391
  }
410
392
  }
411
393
 
394
+ @JRubyMethod(name = "rollback")
412
395
  public static IRubyObject rollback(IRubyObject recv) throws SQLException {
413
396
  try {
414
397
  getConnection(recv).rollback();
@@ -418,6 +401,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
418
401
  }
419
402
  }
420
403
 
404
+ @JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
421
405
  public static IRubyObject columns_internal(final IRubyObject recv, final IRubyObject[] args) throws SQLException, IOException {
422
406
  return withConnectionAndRetry(recv, new SQLBlock() {
423
407
  public IRubyObject call(Connection c) throws SQLException {
@@ -549,6 +533,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
549
533
  }
550
534
  }
551
535
 
536
+ @JRubyMethod(name = "primary_keys", required = 1)
552
537
  public static IRubyObject primary_keys(final IRubyObject recv, final IRubyObject _table_name) throws SQLException {
553
538
  return withConnectionAndRetry(recv, new SQLBlock() {
554
539
  public IRubyObject call(Connection c) throws SQLException {
@@ -580,6 +565,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
580
565
  });
581
566
  }
582
567
 
568
+ @JRubyMethod(name = "execute_id_insert", required = 2)
583
569
  public static IRubyObject execute_id_insert(IRubyObject recv, final IRubyObject sql, final IRubyObject id) throws SQLException {
584
570
  return withConnectionAndRetry(recv, new SQLBlock() {
585
571
  public IRubyObject call(Connection c) throws SQLException {
@@ -595,6 +581,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
595
581
  });
596
582
  }
597
583
 
584
+ @JRubyMethod(name = "execute_update", required = 1)
598
585
  public static IRubyObject execute_update(final IRubyObject recv, final IRubyObject sql) throws SQLException {
599
586
  return withConnectionAndRetry(recv, new SQLBlock() {
600
587
  public IRubyObject call(Connection c) throws SQLException {
@@ -614,6 +601,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
614
601
  });
615
602
  }
616
603
 
604
+ @JRubyMethod(name = "execute_query", rest = true)
617
605
  public static IRubyObject execute_query(final IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
618
606
  final IRubyObject sql = args[0];
619
607
  final int maxrows;
@@ -643,6 +631,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
643
631
  });
644
632
  }
645
633
 
634
+ @JRubyMethod(name = "execute_insert", required = 1)
646
635
  public static IRubyObject execute_insert(final IRubyObject recv, final IRubyObject sql) throws SQLException {
647
636
  return withConnectionAndRetry(recv, new SQLBlock() {
648
637
  public IRubyObject call(Connection c) throws SQLException {
@@ -735,6 +724,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
735
724
  return runtime.newArray(results);
736
725
  }
737
726
 
727
+ @JRubyMethod(name = "unmarshal_result", required = 1)
738
728
  public static IRubyObject unmarshal_result(IRubyObject recv, IRubyObject resultset, Block row_filter) throws SQLException, IOException {
739
729
  Ruby runtime = recv.getRuntime();
740
730
  ResultSet rs = intoResultSet(resultset);
@@ -897,7 +887,8 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
897
887
 
898
888
  private final static DateFormat FORMAT = new SimpleDateFormat("%y-%M-%d %H:%m:%s");
899
889
 
900
- private static void setValue(PreparedStatement ps, int index, Ruby runtime, IRubyObject value, IRubyObject type) throws SQLException {
890
+ private static void setValue(PreparedStatement ps, int index, Ruby runtime, ThreadContext context,
891
+ IRubyObject value, IRubyObject type) throws SQLException {
901
892
  final int tp = getTypeValueFor(runtime, type);
902
893
  if(value.isNil()) {
903
894
  ps.setNull(index, tp);
@@ -907,7 +898,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
907
898
  switch(tp) {
908
899
  case Types.VARCHAR:
909
900
  case Types.CLOB:
910
- ps.setString(index, RubyString.objAsString(value).toString());
901
+ ps.setString(index, RubyString.objAsString(context, value).toString());
911
902
  break;
912
903
  case Types.INTEGER:
913
904
  ps.setLong(index, RubyNumeric.fix2long(value));
@@ -920,10 +911,10 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
920
911
  case Types.DATE:
921
912
  if(!(value instanceof RubyTime)) {
922
913
  try {
923
- Date dd = FORMAT.parse(RubyString.objAsString(value).toString());
914
+ Date dd = FORMAT.parse(RubyString.objAsString(context, value).toString());
924
915
  ps.setTimestamp(index, new java.sql.Timestamp(dd.getTime()), Calendar.getInstance());
925
916
  } catch(Exception e) {
926
- ps.setString(index, RubyString.objAsString(value).toString());
917
+ ps.setString(index, RubyString.objAsString(context, value).toString());
927
918
  }
928
919
  } else {
929
920
  RubyTime rubyTime = (RubyTime) value;
@@ -944,27 +935,28 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
944
935
  }
945
936
  }
946
937
 
947
- private static void setValuesOnPS(PreparedStatement ps, Ruby runtime, IRubyObject values, IRubyObject types) throws SQLException {
938
+ private static void setValuesOnPS(PreparedStatement ps, Ruby runtime, ThreadContext context,
939
+ IRubyObject values, IRubyObject types) throws SQLException {
948
940
  RubyArray vals = (RubyArray)values;
949
941
  RubyArray tps = (RubyArray)types;
950
942
 
951
943
  for(int i=0, j=vals.getLength(); i<j; i++) {
952
- setValue(ps, i+1, runtime, vals.eltInternal(i), tps.eltInternal(i));
944
+ setValue(ps, i+1, runtime, context, vals.eltInternal(i), tps.eltInternal(i));
953
945
  }
954
946
  }
955
947
 
956
948
  /*
957
949
  * sql, values, types, name = nil, pk = nil, id_value = nil, sequence_name = nil
958
950
  */
959
- public static IRubyObject insert_bind(IRubyObject recv, final IRubyObject[] args) throws SQLException {
951
+ @JRubyMethod(name = "insert_bind", required = 3, rest = true)
952
+ public static IRubyObject insert_bind(final ThreadContext context, IRubyObject recv, final IRubyObject[] args) throws SQLException {
960
953
  final Ruby runtime = recv.getRuntime();
961
- Arity.checkArgumentCount(runtime, args, 3, 7);
962
954
  return withConnectionAndRetry(recv, new SQLBlock() {
963
955
  public IRubyObject call(Connection c) throws SQLException {
964
956
  PreparedStatement ps = null;
965
957
  try {
966
958
  ps = c.prepareStatement(rubyApi.convertToRubyString(args[0]).toString(), Statement.RETURN_GENERATED_KEYS);
967
- setValuesOnPS(ps, runtime, args[1], args[2]);
959
+ setValuesOnPS(ps, runtime, context, args[1], args[2]);
968
960
  ps.executeUpdate();
969
961
  return unmarshal_id_result(runtime, ps.getGeneratedKeys());
970
962
  } finally {
@@ -980,7 +972,8 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
980
972
  /*
981
973
  * sql, values, types, name = nil
982
974
  */
983
- public static IRubyObject update_bind(IRubyObject recv, final IRubyObject[] args) throws SQLException {
975
+ @JRubyMethod(name = "update_bind", required = 3, rest = true)
976
+ public static IRubyObject update_bind(final ThreadContext context, IRubyObject recv, final IRubyObject[] args) throws SQLException {
984
977
  final Ruby runtime = recv.getRuntime();
985
978
  Arity.checkArgumentCount(runtime, args, 3, 4);
986
979
  return withConnectionAndRetry(recv, new SQLBlock() {
@@ -988,7 +981,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
988
981
  PreparedStatement ps = null;
989
982
  try {
990
983
  ps = c.prepareStatement(rubyApi.convertToRubyString(args[0]).toString());
991
- setValuesOnPS(ps, runtime, args[1], args[2]);
984
+ setValuesOnPS(ps, runtime, context, args[1], args[2]);
992
985
  ps.executeUpdate();
993
986
  } finally {
994
987
  try {
@@ -1004,10 +997,10 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
1004
997
  /*
1005
998
  * (is binary?, colname, tablename, primary key, id, value)
1006
999
  */
1000
+ @JRubyMethod(name = "write_large_object", required = 6)
1007
1001
  public static IRubyObject write_large_object(IRubyObject recv, final IRubyObject[] args)
1008
1002
  throws SQLException, IOException {
1009
1003
  final Ruby runtime = recv.getRuntime();
1010
- Arity.checkArgumentCount(runtime, args, 6, 6);
1011
1004
  return withConnectionAndRetry(recv, new SQLBlock() {
1012
1005
  public IRubyObject call(Connection c) throws SQLException {
1013
1006
  String sql = "UPDATE " + rubyApi.convertToRubyString(args[2])
@@ -35,83 +35,76 @@ import org.jruby.RubyBigDecimal;
35
35
  import org.jruby.RubyRange;
36
36
  import org.jruby.RubyNumeric;
37
37
 
38
- import org.jruby.runtime.Arity;
39
- import org.jruby.runtime.CallbackFactory;
40
- import org.jruby.runtime.MethodIndex;
41
38
  import org.jruby.runtime.builtin.IRubyObject;
42
39
 
43
40
  import org.jruby.util.ByteList;
44
41
 
45
42
  import java.sql.SQLException;
46
43
  import org.jruby.RubyObjectAdapter;
44
+ import org.jruby.anno.JRubyMethod;
45
+ import org.jruby.runtime.ThreadContext;
47
46
 
48
47
  public class JdbcDerbySpec {
49
48
  private static RubyObjectAdapter rubyApi;
50
- public static void load(Ruby runtime, RubyModule jdbcSpec, RubyObjectAdapter adapter) {
49
+ public static void load(RubyModule jdbcSpec, RubyObjectAdapter adapter) {
51
50
  RubyModule derby = jdbcSpec.defineModuleUnder("Derby");
52
- CallbackFactory cf = runtime.callbackFactory(JdbcDerbySpec.class);
53
- derby.defineFastMethod("quote_string",cf.getFastSingletonMethod("quote_string",IRubyObject.class));
54
- derby.defineFastMethod("quote",cf.getFastOptSingletonMethod("quote"));
55
- derby.defineFastMethod("_execute",cf.getFastOptSingletonMethod("_execute"));
56
- derby.defineFastMethod("add_limit_offset!",cf.getFastSingletonMethod("add_limit_offset", IRubyObject.class, IRubyObject.class));
57
- derby.defineFastMethod("select_all",cf.getFastOptSingletonMethod("select_all"));
58
- derby.defineFastMethod("select_one",cf.getFastOptSingletonMethod("select_one"));
59
- RubyModule col = derby.defineModuleUnder("Column");
60
- col.defineFastMethod("type_cast",cf.getFastSingletonMethod("type_cast", IRubyObject.class));
51
+ derby.defineAnnotatedMethods(JdbcDerbySpec.class);
52
+ RubyModule column = derby.defineModuleUnder("Column");
53
+ column.defineAnnotatedMethods(Column.class);
61
54
  rubyApi = adapter;
62
55
  }
63
56
 
64
- /*
65
- * JdbcSpec::Derby::Column.type_cast(value)
66
- */
67
- public static IRubyObject type_cast(IRubyObject recv, IRubyObject value) {
68
- Ruby runtime = recv.getRuntime();
57
+ public static class Column {
58
+ @JRubyMethod(name = "type_cast", required = 1)
59
+ public static IRubyObject type_cast(IRubyObject recv, IRubyObject value) {
60
+ Ruby runtime = recv.getRuntime();
69
61
 
70
- if (value.isNil() || ((value instanceof RubyString) && value.toString().trim().equalsIgnoreCase("null"))) {
71
- return runtime.getNil();
72
- }
62
+ if (value.isNil() || ((value instanceof RubyString) && value.toString().trim().equalsIgnoreCase("null"))) {
63
+ return runtime.getNil();
64
+ }
73
65
 
74
- String type = rubyApi.getInstanceVariable(recv,"@type").toString();
66
+ String type = rubyApi.getInstanceVariable(recv, "@type").toString();
75
67
 
76
- switch(type.charAt(0)) {
77
- case 's': //string
78
- return value;
79
- case 't': //text, timestamp, time
80
- if(type.equals("text")) {
81
- return value;
82
- } else {
83
- return rubyApi.callMethod(recv, "cast_to_time", value);
84
- }
85
- case 'i': //integer
86
- case 'p': //primary key
87
- if (value.respondsTo("to_i")) {
88
- return rubyApi.callMethod(value, "to_i");
89
- } else {
90
- return runtime.newFixnum(value.isTrue() ? 1 : 0 );
91
- }
92
- case 'd': //decimal, datetime, date
93
- if(type.equals("datetime")) {
94
- return rubyApi.callMethod(recv, "cast_to_date_or_time", value);
95
- } else if(type.equals("date")) {
96
- return rubyApi.callMethod(recv.getMetaClass(), "string_to_date", value);
97
- } else {
98
- return rubyApi.callMethod(recv.getMetaClass(), "value_to_decimal", value);
99
- }
100
- case 'f': //float
101
- return rubyApi.callMethod(value,"to_f");
102
- case 'b': //binary, boolean
103
- if (type.equals("binary")) {
104
- return rubyApi.callMethod(recv, "value_to_binary", value);
105
- } else {
106
- return rubyApi.callMethod(recv.getMetaClass(), "value_to_boolean", value);
68
+ switch (type.charAt(0)) {
69
+ case 's': //string
70
+ return value;
71
+ case 't': //text, timestamp, time
72
+ if (type.equals("text")) {
73
+ return value;
74
+ } else {
75
+ return rubyApi.callMethod(recv, "cast_to_time", value);
76
+ }
77
+ case 'i': //integer
78
+ case 'p': //primary key
79
+ if (value.respondsTo("to_i")) {
80
+ return rubyApi.callMethod(value, "to_i");
81
+ } else {
82
+ return runtime.newFixnum(value.isTrue() ? 1 : 0);
83
+ }
84
+ case 'd': //decimal, datetime, date
85
+ if (type.equals("datetime")) {
86
+ return rubyApi.callMethod(recv, "cast_to_date_or_time", value);
87
+ } else if (type.equals("date")) {
88
+ return rubyApi.callMethod(recv.getMetaClass(), "string_to_date", value);
89
+ } else {
90
+ return rubyApi.callMethod(recv.getMetaClass(), "value_to_decimal", value);
91
+ }
92
+ case 'f': //float
93
+ return rubyApi.callMethod(value, "to_f");
94
+ case 'b': //binary, boolean
95
+ if (type.equals("binary")) {
96
+ return rubyApi.callMethod(recv, "value_to_binary", value);
97
+ } else {
98
+ return rubyApi.callMethod(recv.getMetaClass(), "value_to_boolean", value);
99
+ }
107
100
  }
101
+ return value;
108
102
  }
109
- return value;
110
103
  }
111
104
 
112
- public static IRubyObject quote(IRubyObject recv, IRubyObject[] args) {
105
+ @JRubyMethod(name = "quote", required = 1, optional = 1)
106
+ public static IRubyObject quote(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
113
107
  Ruby runtime = recv.getRuntime();
114
- Arity.checkArgumentCount(runtime, args, 1, 2);
115
108
  IRubyObject value = args[0];
116
109
  if (args.length > 1) {
117
110
  IRubyObject col = args[1];
@@ -128,21 +121,21 @@ public class JdbcDerbySpec {
128
121
  if (only_digits((RubyString)value)) {
129
122
  return value;
130
123
  } else {
131
- return super_quote(recv, runtime, value, col);
124
+ return super_quote(context, recv, runtime, value, col);
132
125
  }
133
126
  }
134
127
  } else if ((value instanceof RubyFloat) || (value instanceof RubyFixnum) || (value instanceof RubyBignum)) {
135
128
  if (type == runtime.newSymbol("string")) {
136
- return quote_string_with_surround(runtime, "'", RubyString.objAsString(value), "'");
129
+ return quote_string_with_surround(runtime, "'", RubyString.objAsString(context, value), "'");
137
130
  }
138
131
  }
139
132
  }
140
- return super_quote(recv, runtime, value, runtime.getNil());
133
+ return super_quote(context, recv, runtime, value, runtime.getNil());
141
134
  }
142
135
 
143
136
  private final static ByteList NULL = new ByteList("NULL".getBytes());
144
137
 
145
- public static IRubyObject super_quote(IRubyObject recv, Ruby runtime, IRubyObject value, IRubyObject col) {
138
+ private static IRubyObject super_quote(ThreadContext context, IRubyObject recv, Ruby runtime, IRubyObject value, IRubyObject col) {
146
139
  if (value.respondsTo("quoted_id")) {
147
140
  return rubyApi.callMethod(value, "quoted_id");
148
141
  }
@@ -151,11 +144,11 @@ public class JdbcDerbySpec {
151
144
  RubyModule multibyteChars = (RubyModule)
152
145
  ((RubyModule) ((RubyModule) runtime.getModule("ActiveSupport")).getConstant("Multibyte")).getConstantAt("Chars");
153
146
  if (value instanceof RubyString || rubyApi.isKindOf(value, multibyteChars)) {
154
- RubyString svalue = RubyString.objAsString(value);
147
+ RubyString svalue = RubyString.objAsString(context, value);
155
148
  if (type == runtime.newSymbol("binary") && col.getType().respondsTo("string_to_binary")) {
156
149
  return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(col.getType(), "string_to_binary", svalue)), "'");
157
150
  } else if (type == runtime.newSymbol("integer") || type == runtime.newSymbol("float")) {
158
- return RubyString.objAsString(((type == runtime.newSymbol("integer")) ?
151
+ return RubyString.objAsString(context, ((type == runtime.newSymbol("integer")) ?
159
152
  rubyApi.callMethod(svalue, "to_i") :
160
153
  rubyApi.callMethod(svalue, "to_f")));
161
154
  } else {
@@ -168,11 +161,11 @@ public class JdbcDerbySpec {
168
161
  (type == runtime.newSymbol(":integer")) ? runtime.newString("1") : rubyApi.callMethod(recv, "quoted_true") :
169
162
  (type == runtime.newSymbol(":integer")) ? runtime.newString("0") : rubyApi.callMethod(recv, "quoted_false"));
170
163
  } else if((value instanceof RubyFloat) || (value instanceof RubyFixnum) || (value instanceof RubyBignum)) {
171
- return RubyString.objAsString(value);
164
+ return RubyString.objAsString(context, value);
172
165
  } else if(value instanceof RubyBigDecimal) {
173
166
  return rubyApi.callMethod(value, "to_s", runtime.newString("F"));
174
167
  } else if (rubyApi.isKindOf(value, runtime.getModule("Date"))) {
175
- return quote_string_with_surround(runtime, "'", RubyString.objAsString(value), "'");
168
+ return quote_string_with_surround(runtime, "'", RubyString.objAsString(context, value), "'");
176
169
  } else if (rubyApi.isKindOf(value, runtime.getModule("Time")) || rubyApi.isKindOf(value, runtime.getModule("DateTime"))) {
177
170
  return quote_string_with_surround(runtime, "'", (RubyString)(rubyApi.callMethod(recv, "quoted_date", value)), "'");
178
171
  } else {
@@ -182,7 +175,7 @@ public class JdbcDerbySpec {
182
175
 
183
176
  private final static ByteList TWO_SINGLE = new ByteList(new byte[]{'\'','\''});
184
177
 
185
- public static IRubyObject quote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
178
+ private static IRubyObject quote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
186
179
  ByteList input = string.getByteList();
187
180
  ByteList output = new ByteList(before.getBytes());
188
181
  for(int i = input.begin; i< input.begin + input.realSize; i++) {
@@ -203,7 +196,7 @@ public class JdbcDerbySpec {
203
196
 
204
197
  private final static byte[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
205
198
 
206
- public static IRubyObject hexquote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
199
+ private static IRubyObject hexquote_string_with_surround(Ruby runtime, String before, RubyString string, String after) {
207
200
  ByteList input = string.getByteList();
208
201
  ByteList output = new ByteList(before.getBytes());
209
202
  for(int i = input.begin; i< input.begin + input.realSize; i++) {
@@ -232,6 +225,7 @@ public class JdbcDerbySpec {
232
225
  return true;
233
226
  }
234
227
 
228
+ @JRubyMethod(name = "quote_string", required = 1)
235
229
  public static IRubyObject quote_string(IRubyObject recv, IRubyObject string) {
236
230
  boolean replacementFound = false;
237
231
  ByteList bl = ((RubyString) string).getByteList();
@@ -259,10 +253,12 @@ public class JdbcDerbySpec {
259
253
  }
260
254
  }
261
255
 
256
+ @JRubyMethod(name = "select_all", rest = true)
262
257
  public static IRubyObject select_all(IRubyObject recv, IRubyObject[] args) {
263
258
  return rubyApi.callMethod(recv, "execute", args);
264
259
  }
265
260
 
261
+ @JRubyMethod(name = "select_one", rest = true)
266
262
  public static IRubyObject select_one(IRubyObject recv, IRubyObject[] args) {
267
263
  IRubyObject limit = rubyApi.getInstanceVariable(recv, "@limit");
268
264
  if (limit == null || limit.isNil()) {
@@ -276,6 +272,7 @@ public class JdbcDerbySpec {
276
272
  }
277
273
  }
278
274
 
275
+ @JRubyMethod(name = "add_limit_offset!", required = 2)
279
276
  public static IRubyObject add_limit_offset(IRubyObject recv, IRubyObject sql, IRubyObject options) {
280
277
  IRubyObject limit = rubyApi.callMethod(options, "[]", recv.getRuntime().newSymbol("limit"));
281
278
  rubyApi.setInstanceVariable(recv, "@limit",limit);
@@ -283,7 +280,8 @@ public class JdbcDerbySpec {
283
280
  return rubyApi.setInstanceVariable(recv, "@offset",offset);
284
281
  }
285
282
 
286
- public static IRubyObject _execute(IRubyObject recv, IRubyObject[] args) throws SQLException, java.io.IOException {
283
+ @JRubyMethod(name = "_execute", required = 1, optional = 1)
284
+ public static IRubyObject _execute(ThreadContext context, IRubyObject recv, IRubyObject[] args) throws SQLException, java.io.IOException {
287
285
  Ruby runtime = recv.getRuntime();
288
286
  try {
289
287
  IRubyObject conn = rubyApi.getInstanceVariable(recv, "@connection");
@@ -302,11 +300,11 @@ public class JdbcDerbySpec {
302
300
  IRubyObject range;
303
301
  IRubyObject max;
304
302
  if (limit == null || limit.isNil() || RubyNumeric.fix2int(limit) == -1) {
305
- range = RubyRange.newRange(runtime, offset, runtime.newFixnum(-1), false);
303
+ range = RubyRange.newRange(runtime, context, offset, runtime.newFixnum(-1), false);
306
304
  max = RubyFixnum.zero(runtime);
307
305
  } else {
308
306
  IRubyObject v1 = rubyApi.callMethod(offset, "+", limit);
309
- range = RubyRange.newRange(runtime, offset, v1, true);
307
+ range = RubyRange.newRange(runtime, context, offset, v1, true);
310
308
  max = rubyApi.callMethod(v1, "+", RubyFixnum.one(runtime));
311
309
  }
312
310
  IRubyObject result = JdbcAdapterInternalService.execute_query(conn, new IRubyObject[]{args[0], max});
@@ -28,16 +28,15 @@ import org.jruby.Ruby;
28
28
  import org.jruby.RubyModule;
29
29
  import org.jruby.RubyString;
30
30
 
31
- import org.jruby.runtime.CallbackFactory;
31
+ import org.jruby.anno.JRubyMethod;
32
32
  import org.jruby.runtime.builtin.IRubyObject;
33
33
 
34
34
  import org.jruby.util.ByteList;
35
35
 
36
36
  public class JdbcMySQLSpec {
37
- public static void load(Ruby runtime, RubyModule jdbcSpec) {
37
+ public static void load(RubyModule jdbcSpec) {
38
38
  RubyModule mysql = jdbcSpec.defineModuleUnder("MySQL");
39
- CallbackFactory cf = runtime.callbackFactory(JdbcMySQLSpec.class);
40
- mysql.defineFastMethod("quote_string",cf.getFastSingletonMethod("quote_string",IRubyObject.class));
39
+ mysql.defineAnnotatedMethods(JdbcMySQLSpec.class);
41
40
  }
42
41
 
43
42
  private final static ByteList ZERO = new ByteList(new byte[]{'\\','0'});
@@ -48,9 +47,11 @@ public class JdbcMySQLSpec {
48
47
  private final static ByteList SINGLE = new ByteList(new byte[]{'\\','\''});
49
48
  private final static ByteList ESCAPE = new ByteList(new byte[]{'\\','\\'});
50
49
 
50
+ @JRubyMethod(name = "quote_string", required = 1)
51
51
  public static IRubyObject quote_string(IRubyObject recv, IRubyObject string) {
52
- boolean replacementFound = false;
53
52
  ByteList bl = ((RubyString) string).getByteList();
53
+ ByteList blNew = new ByteList();
54
+ int startOfExtend = bl.begin;
54
55
 
55
56
  for(int i = bl.begin; i < bl.begin + bl.realSize; i++) {
56
57
  ByteList rep = null;
@@ -64,23 +65,18 @@ public class JdbcMySQLSpec {
64
65
  case '\\': rep = ESCAPE; break;
65
66
  default: continue;
66
67
  }
67
-
68
- // On first replacement allocate a different bytelist so we don't manip original
69
- if(!replacementFound) {
70
- i-= bl.begin;
71
- bl = new ByteList(bl);
72
- replacementFound = true;
73
- }
74
-
75
- bl.replace(i, 1, rep);
76
- i+=1;
68
+ if(i > startOfExtend)
69
+ blNew.append(bl, startOfExtend, i-startOfExtend);
70
+ blNew.append(rep, 0, 2);
71
+ startOfExtend = i+1;
77
72
  }
78
-
79
- if(!replacementFound) {
80
- return string;
73
+ // Nothing changed, can return original
74
+ if (startOfExtend == bl.begin) {
75
+ return string;
81
76
  }
77
+ if (bl.begin + bl.realSize > startOfExtend)
78
+ blNew.append(bl, startOfExtend, bl.begin + bl.realSize - startOfExtend);
82
79
 
83
-
84
- return recv.getRuntime().newStringShared(bl);
80
+ return recv.getRuntime().newStringShared(blNew);
85
81
  }
86
82
  }
@@ -13,6 +13,5 @@ ActiveRecord::Base.logger = logger
13
13
  at_exit {
14
14
  # Clean up derby files
15
15
  require 'fileutils'
16
- Dir.glob('derby-testdb/**/*') {|f| File.delete(f)}
17
16
  FileUtils.rm_rf('derby-testdb')
18
17
  }
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+
4
+ class CreateReservedWords < ActiveRecord::Migration
5
+ def self.up
6
+ create_table "reserved_words", :force => true do |t|
7
+ t.column :position, :integer
8
+ t.column :select, :integer
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table "reserved_words"
14
+ end
15
+ end
16
+
17
+ class ReservedWord < ActiveRecord::Base
18
+ end
@@ -0,0 +1,22 @@
1
+ require 'jdbc_common'
2
+ require 'db/postgres'
3
+ require 'models/reserved_word'
4
+
5
+ class PostgresReservedWordsTest < Test::Unit::TestCase
6
+ def setup
7
+ CreateReservedWords.up
8
+ end
9
+ def teardown
10
+ CreateReservedWords.down
11
+ end
12
+
13
+ def test_quote_reserved_word_column
14
+ columns = ReservedWord.column_names - ["id"]
15
+ ReservedWord.connection.add_index :reserved_words, columns
16
+ indexes = ReservedWord.connection.indexes("reserved_words")
17
+ assert_equal 1, indexes.size
18
+ columns.each do |c|
19
+ assert indexes[0].columns.include?(c), "#{indexes[0].columns.inspect} does not include #{c.inspect}"
20
+ end
21
+ end
22
+ end
@@ -87,7 +87,7 @@ module SimpleTestMethods
87
87
 
88
88
  indexes = @connection.indexes(:entries)
89
89
  assert_equal(1, indexes.size)
90
- assert_equal "entries", indexes.first.table
90
+ assert_equal "entries", indexes.first.table.to_s
91
91
  assert_equal index_name, indexes.first.name
92
92
  assert !indexes.first.unique
93
93
  assert_equal ["updated_on"], indexes.first.columns
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-jdbc-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: "0.8"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sieger, Ola Bini and JRuby contributors
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-02-12 00:00:00 -06:00
12
+ date: 2008-03-19 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,12 +23,13 @@ extra_rdoc_files:
23
23
  - History.txt
24
24
  - Manifest.txt
25
25
  - README.txt
26
+ - LICENSE.txt
26
27
  files:
27
28
  - History.txt
28
29
  - Manifest.txt
29
30
  - README.txt
30
31
  - Rakefile
31
- - LICENSE
32
+ - LICENSE.txt
32
33
  - lib/active_record/connection_adapters/derby_adapter.rb
33
34
  - lib/active_record/connection_adapters/h2_adapter.rb
34
35
  - lib/active_record/connection_adapters/hsqldb_adapter.rb
@@ -86,11 +87,14 @@ files:
86
87
  - test/models/auto_id.rb
87
88
  - test/models/data_types.rb
88
89
  - test/models/entry.rb
90
+ - test/models/reserved_word.rb
89
91
  - test/mysql_multibyte_test.rb
90
92
  - test/mysql_simple_test.rb
91
93
  - test/oracle_simple_test.rb
94
+ - test/postgres_reserved_test.rb
92
95
  - test/postgres_simple_test.rb
93
96
  - test/simple.rb
97
+ - lib/jdbc_adapter/jdbc.rake
94
98
  - src/java/jdbc_adapter/JdbcAdapterInternalService.java
95
99
  - src/java/jdbc_adapter/JdbcConnectionFactory.java
96
100
  - src/java/jdbc_adapter/JdbcDerbySpec.java