upsert 2.1.0 → 2.9.10

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 (47) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -0
  3. data/.standard.yml +1 -0
  4. data/.travis.yml +60 -12
  5. data/CHANGELOG +39 -0
  6. data/Gemfile +12 -1
  7. data/LICENSE +3 -1
  8. data/README.md +47 -6
  9. data/Rakefile +7 -1
  10. data/lib/upsert.rb +54 -11
  11. data/lib/upsert/column_definition/mysql.rb +2 -2
  12. data/lib/upsert/column_definition/postgresql.rb +9 -8
  13. data/lib/upsert/column_definition/sqlite3.rb +3 -3
  14. data/lib/upsert/connection/Java_ComMysqlJdbc_JDBC4Connection.rb +11 -5
  15. data/lib/upsert/connection/Java_OrgPostgresqlJdbc_PgConnection.rb +33 -0
  16. data/lib/upsert/connection/PG_Connection.rb +10 -1
  17. data/lib/upsert/connection/jdbc.rb +20 -1
  18. data/lib/upsert/connection/postgresql.rb +2 -3
  19. data/lib/upsert/merge_function.rb +5 -4
  20. data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc_PgConnection.rb +27 -0
  21. data/lib/upsert/merge_function/PG_Connection.rb +11 -42
  22. data/lib/upsert/merge_function/postgresql.rb +215 -1
  23. data/lib/upsert/merge_function/sqlite3.rb +10 -0
  24. data/lib/upsert/version.rb +1 -1
  25. data/spec/active_record_upsert_spec.rb +10 -0
  26. data/spec/correctness_spec.rb +34 -5
  27. data/spec/database_functions_spec.rb +16 -9
  28. data/spec/database_spec.rb +7 -0
  29. data/spec/hstore_spec.rb +56 -55
  30. data/spec/jruby_spec.rb +9 -0
  31. data/spec/logger_spec.rb +8 -6
  32. data/spec/postgresql_spec.rb +94 -0
  33. data/spec/reserved_words_spec.rb +21 -17
  34. data/spec/sequel_spec.rb +26 -7
  35. data/spec/spec_helper.rb +251 -92
  36. data/spec/speed_spec.rb +3 -32
  37. data/spec/threaded_spec.rb +35 -12
  38. data/spec/type_safety_spec.rb +2 -1
  39. data/travis/install_postgres.sh +18 -0
  40. data/travis/run_docker_db.sh +20 -0
  41. data/travis/tune_mysql.sh +7 -0
  42. data/upsert-java.gemspec +13 -0
  43. data/upsert.gemspec +9 -57
  44. data/upsert.gemspec.common +107 -0
  45. metadata +53 -40
  46. data/lib/upsert/connection/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -15
  47. data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8a8d49c15022e8faa065c2f060349210b28998b9
4
- data.tar.gz: 3814d296ef548257347af887ca39a04b801ceb91
2
+ SHA256:
3
+ metadata.gz: 5d3ee917c4d930fdfb8be20d6838b49f88142ffb35122ed9c84724ceb498df16
4
+ data.tar.gz: f8186de9b5a77c3b5dd58ac23b14a7280a27f8a37d2dd3e0305f9dd725846ae4
5
5
  SHA512:
6
- metadata.gz: e3a2553e8a0d143bb90592d1dc7f5a4ccd9224386fdce394dceef2ad2f46e186a853e61560ef1d6ea93f52b5bb7e948659c62398c60cc6c5d8c5887bdd9c6d0f
7
- data.tar.gz: 864fcc5434d104ae1c4d5e8d68a8e8546217612be2d710b01a8ecfbd5e25435f2181a8c59afd7f6224b388762276f93256be6c7cec4ea5e18e994129ba1b396d
6
+ metadata.gz: 9e874aed50b2fd6d15e9591764f2d16656d0e1a22d44474fb2c279cd2bb508098b81aa2482a1605c0dfcbb7ec356eae65d8a70b1d1763f709f8c9694b78c8862
7
+ data.tar.gz: a7f35d0e6b5c423b5676c740d9285e7a32134486edc811d184bd35c4f6c97f20024a4db8847fbfd9adecd6a9e8731993e5047528d12fb19387809e306b8067a5
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.5
data/.standard.yml ADDED
@@ -0,0 +1 @@
1
+ ruby_version: 2.2.4
data/.travis.yml CHANGED
@@ -1,15 +1,63 @@
1
+ dist: xenial
1
2
  language: ruby
2
- global:
3
- - USERNAME=travis
4
- PASSWORD=
3
+ cache: bundler
4
+ services:
5
+ - docker
5
6
  rvm:
6
- - 2.2.0
7
- - 2.1.0
8
- - 2.0.0
9
- - 1.9.3
10
- - 1.9.2
11
- - 1.8.7
12
- - rbx-2
7
+ - 2.6
8
+ - 2.5
9
+ - 2.4
10
+ - 2.3
11
+ - 2.2
12
+ - jruby-9.1.14.0
13
+ - jruby-9.1.17.0
14
+ - jruby-9.2.7.0
13
15
  env:
14
- - DB=postgresql
15
- - DB=mysql
16
+ global:
17
+ - USERNAME=travis
18
+ - PASSWORD=
19
+ - DB_USER=upsert_test
20
+ - DB_PASSWORD=upsert_test
21
+ - DB_NAME=upsert_test
22
+ matrix:
23
+ - DB=postgresql DB_VERSION=postgres:9.4
24
+ - DB=postgresql DB_VERSION=postgres:9.5
25
+ - DB=postgresql DB_VERSION=postgres:9.6
26
+ - DB=postgresql DB_VERSION=postgres:10
27
+ - DB=postgresql DB_VERSION=postgres:11
28
+ - DB=postgresql DB_VERSION=postgres:12
29
+ - DB=postgresql DB_VERSION=postgres:9.4 UNIQUE_CONSTRAINT=true
30
+ - DB=postgresql DB_VERSION=postgres:9.5 UNIQUE_CONSTRAINT=true
31
+ - DB=postgresql DB_VERSION=postgres:9.6 UNIQUE_CONSTRAINT=true
32
+ - DB=postgresql DB_VERSION=postgres:10 UNIQUE_CONSTRAINT=true
33
+ - DB=postgresql DB_VERSION=postgres:11 UNIQUE_CONSTRAINT=true
34
+ - DB=postgresql DB_VERSION=postgres:12 UNIQUE_CONSTRAINT=true
35
+ - DB=mysql DB_VERSION=mysql:5.6
36
+ - DB=mysql DB_VERSION=mysql:5.7
37
+ - DB=mysql DB_VERSION=mysql:8
38
+ matrix:
39
+ exclude:
40
+ - rvm: 2.6
41
+ env: DB=postgresql DB_VERSION=postgres:9.4
42
+ - rvm: 2.6
43
+ env: DB=postgresql DB_VERSION=postgres:9.5
44
+ - rvm: 2.6
45
+ env: DB=postgresql DB_VERSION=postgres:9.4 UNIQUE_CONSTRAINT=true
46
+ - rvm: 2.6
47
+ env: DB=postgresql DB_VERSION=postgres:9.5 UNIQUE_CONSTRAINT=true
48
+ - rvm: jruby-9.2.7
49
+ env: DB=postgresql DB_VERSION=postgres:9.4
50
+ - rvm: jruby-9.2.7
51
+ env: DB=postgresql DB_VERSION=postgres:9.5
52
+ - rvm: jruby-9.2.7
53
+ env: DB=postgresql DB_VERSION=postgres:9.4 UNIQUE_CONSTRAINT=true
54
+ - rvm: jruby-9.2.7
55
+ env: DB=postgresql DB_VERSION=postgres:9.5 UNIQUE_CONSTRAINT=true
56
+ allow_failures:
57
+ - env: DB=postgresql DB_VERSION=postgres:12
58
+ - env: DB=postgresql DB_VERSION=postgres:12 UNIQUE_CONSTRAINT=true
59
+ before_install:
60
+ - ./travis/run_docker_db.sh
61
+ - bundle --version
62
+ - gem --version
63
+ script: ./travis/run_specs.sh
data/CHANGELOG CHANGED
@@ -1,3 +1,42 @@
1
+ -- no version -- / 2019-06-05
2
+
3
+ * Enhancements
4
+
5
+ * Bump development Ruby version to 2.5 since Ruby 2.2 is no longer supported.
6
+ This should not affect usage of the gem, only local development for people
7
+ working *on* the gem. Ruby 2.2 is also not dropped from Upsert compatibility
8
+ at this time but you should consider upgrading to newer Ruby versions anyway.
9
+
10
+ 2.2.1 / 2017-04-20
11
+
12
+ * Bug fixes
13
+
14
+ * Fix unique constraint detection on pg >9.5.5 (@pnomolos https://github.com/seamusabshere/upsert/pull/99)
15
+ * Fix Ruby 1.9 tests
16
+
17
+ 2.2.0 / 2017-04-14
18
+
19
+ * Enhancements
20
+
21
+ * Use native "upsert" on Postgres 9.5+! (thanks to @pnomolos https://github.com/seamusabshere/upsert/pull/79)
22
+ * More modern CI tests
23
+
24
+ 2.1.2 / 2016-02-25
25
+
26
+ * Enhancements
27
+
28
+ * Test on Ruby 2.3 - thanks @Ch4s3 https://github.com/seamusabshere/upsert/pull/70
29
+
30
+ * Bug fixes
31
+
32
+ * Stop using Thread.exclusive - thanks @hpetru https://github.com/seamusabshere/upsert/pull/67
33
+
34
+ 2.1.1 / 2016-02-12
35
+
36
+ * Enhancements
37
+
38
+ * Assume function exists to avoid huge amounts of recreation
39
+
1
40
  2.1.0 / 2015-03-13
2
41
 
3
42
  * Bug fixes
data/Gemfile CHANGED
@@ -2,4 +2,15 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in upsert.gemspec
4
4
 
5
- gemspec
5
+ gemspec name: RUBY_PLATFORM == "java" ? "upsert-java" : "upsert"
6
+
7
+ case RUBY_PLATFORM
8
+ when "java"
9
+ gem "ffi", platforms: :jruby
10
+ else
11
+ gem "ffi"
12
+ end
13
+
14
+ group "test" do
15
+ gem "testmetrics_rspec"
16
+ end
data/LICENSE CHANGED
@@ -1,4 +1,6 @@
1
- Copyright (c) 2013 Seamus Abshere
1
+ Copyright (c) 2013-2019 Seamus Abshere
2
+ Copyright (c) 2017-2019 Philip Schalm
3
+ Portions Copyright (c) 2019 The JRuby Team
2
4
 
3
5
  MIT License
4
6
 
data/README.md CHANGED
@@ -23,7 +23,7 @@ You pass a __selector__ that uniquely identifies a row, whether it exists or not
23
23
  Syntax inspired by [mongo-ruby-driver's update method](http://api.mongodb.org/ruby/1.6.4/Mongo/Collection.html#update-instance_method).
24
24
 
25
25
  ### Basic
26
-
26
+
27
27
  ```ruby
28
28
  connection = Mysql2::Client.new([...])
29
29
  table_name = :pets
@@ -57,6 +57,14 @@ end
57
57
 
58
58
  Batch mode is tested to be about 80% faster on PostgreSQL, MySQL, and SQLite3 than other ways to emulate upsert (see the tests, which fail if they are not faster).
59
59
 
60
+ ### Native Postgres upsert
61
+
62
+ `INSERT ... ON CONFLICT DO UPDATE` is used when Postgres 9.5+ is detected and *unique constraint are in place.*
63
+
64
+ **Note: ** You must have a **unique constraint** on the column(s) you're using as a selector. A unique index won't work. See https://github.com/seamusabshere/upsert/issues/98#issuecomment-295341405 for more information and some ways to check.
65
+
66
+ If you don't have unique constraints, it will fall back to the classic Upsert gem user-defined function, which does not require a constraint.
67
+
60
68
  ### ActiveRecord helper method
61
69
 
62
70
  ```ruby
@@ -115,7 +123,10 @@ See below for details about what SQL MERGE trick (emulation of upsert) is used,
115
123
 
116
124
  ### Rails / ActiveRecord
117
125
 
118
- (assuming that one of the other three supported drivers is being used under the covers)
126
+ (Assuming that one of the other three supported drivers is being used under the covers).
127
+
128
+ * add "upsert" to your Gemfile and
129
+ * run bundle install
119
130
 
120
131
  ```ruby
121
132
  Upsert.new Pet.connection, Pet.table_name
@@ -167,7 +178,7 @@ BEGIN
167
178
  DECLARE done BOOLEAN;
168
179
  REPEAT
169
180
  BEGIN
170
- -- If there is a unique key constraint error then
181
+ -- If there is a unique key constraint error then
171
182
  -- someone made a concurrent insert. Reset the sentinel
172
183
  -- and try again.
173
184
  DECLARE ER_DUP_UNIQUE CONDITION FOR 23000;
@@ -175,7 +186,7 @@ BEGIN
175
186
  DECLARE CONTINUE HANDLER FOR ER_DUP_UNIQUE BEGIN
176
187
  SET done = FALSE;
177
188
  END;
178
-
189
+
179
190
  DECLARE CONTINUE HANDLER FOR ER_INTEG BEGIN
180
191
  SET done = TRUE;
181
192
  END;
@@ -185,7 +196,7 @@ BEGIN
185
196
  -- Race condition here. If a concurrent INSERT is made after
186
197
  -- the SELECT but before the INSERT below we'll get a duplicate
187
198
  -- key error. But the handler above will take care of that.
188
- IF @count > 0 THEN
199
+ IF @count > 0 THEN
189
200
  -- UPDATE table_name SET b = b_SET WHERE a = a_SEL;
190
201
  UPDATE `pets` SET `name` = `name_set`, `tag_number` = `tag_number_set` WHERE `name` = `name_sel` AND `tag_number` = `tag_number_sel`;
191
202
  ELSE
@@ -224,6 +235,15 @@ require 'pg_hstore'
224
235
  upsert.row({:name => 'Bill'}, :mydata => {:a => 1, :b => 2})
225
236
  ```
226
237
 
238
+ #### PostgreSQL notes
239
+
240
+ - Upsert doesn't do any type casting, so if you attempt to do something like the following:
241
+ `upsert.row({ :name => 'A Name' }, :tag_number => 'bob')`
242
+ you'll get an error which reads something like:
243
+ `invalid input syntax for integer: "bob"`
244
+
245
+
246
+
227
247
  #### Speed
228
248
 
229
249
  From the tests (updated 9/21/12):
@@ -361,10 +381,31 @@ If you're using MySQL, make sure server/connection timezone is UTC. If you're us
361
381
 
362
382
  In general, run some upserts and make sure datetimes get persisted like you expect.
363
383
 
384
+ ### Clearning all library-generated functions
385
+
386
+ Place the following in to a rake task (so you don't globally redefine the `NAME_PREFIX` constant)
387
+
388
+ ```ruby
389
+ Upsert::MergeFunction::NAME_PREFIX = "upsert"
390
+
391
+ # ActiveRecord
392
+ Upsert.clear_database_functions(ActiveRecord::Base.connection)
393
+
394
+ # Sequel
395
+ DB.synchronize do |conn|
396
+ Upsert.clear_database_functions(conn)
397
+ end
398
+ ```
399
+
364
400
  ### Doesn't work with transactional fixtures
365
401
 
366
402
  Per https://github.com/seamusabshere/upsert/issues/23 you might have issues if you try to use transactional fixtures and this library.
367
403
 
404
+ ##
405
+ Testmetrics - https://www.testmetrics.app/seamusabshere/upsert
406
+
368
407
  ## Copyright
369
408
 
370
- Copyright 2014 Seamus Abshere
409
+ Copyright 2013-2019 Seamus Abshere
410
+ Copyright 2017-2019 Philip Schalm
411
+ Portions Copyright (c) 2019 The JRuby Team
data/Rakefile CHANGED
@@ -1,5 +1,11 @@
1
1
  #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
2
+ require "bundler/gem_helper"
3
+ case RUBY_PLATFORM
4
+ when "java"
5
+ Bundler::GemHelper.install_tasks name: "upsert-java"
6
+ else
7
+ Bundler::GemHelper.install_tasks name: "upsert"
8
+ end
3
9
  require "rspec/core/rake_task"
4
10
 
5
11
  RSpec::Core::RakeTask.new(:spec) do |t|
data/lib/upsert.rb CHANGED
@@ -14,11 +14,12 @@ class Upsert
14
14
  # What logger to use.
15
15
  # @return [#info,#warn,#debug]
16
16
  attr_writer :logger
17
-
17
+ MUTEX_FOR_PERFORM = Mutex.new
18
+
18
19
  # The current logger
19
20
  # @return [#info,#warn,#debug]
20
21
  def logger
21
- @logger || Thread.exclusive do
22
+ @logger || MUTEX_FOR_PERFORM.synchronize do
22
23
  @logger ||= if defined?(::Rails) and (rails_logger = ::Rails.logger)
23
24
  rails_logger
24
25
  elsif defined?(::ActiveRecord) and ::ActiveRecord.const_defined?(:Base) and (ar_logger = ::ActiveRecord::Base.logger)
@@ -36,6 +37,31 @@ class Upsert
36
37
  end
37
38
  end
38
39
 
40
+ def mutex_for_row(upsert, row)
41
+ retrieve_mutex(upsert.table_name, row.selector.keys)
42
+ end
43
+
44
+ def mutex_for_function(upsert, row)
45
+ retrieve_mutex(upsert.table_name, row.selector.keys, row.setter.keys)
46
+ end
47
+
48
+ # TODO: Rewrite this to use the thread_safe gem, perhaps?
49
+ def retrieve_mutex(*args)
50
+ # ||= isn't an atomic operation
51
+ MUTEX_FOR_PERFORM.synchronize do
52
+ @mutex_cache ||= {}
53
+ end
54
+
55
+ @mutex_cache.fetch(args.flatten.join('::')) do |k|
56
+ MUTEX_FOR_PERFORM.synchronize do
57
+ # We still need the ||= because this block could have
58
+ # theoretically been entered simultaneously by two threads
59
+ # but the actual assignment is protected by the mutex
60
+ @mutex_cache[k] ||= Mutex.new
61
+ end
62
+ end
63
+ end
64
+
39
65
  # @param [Mysql2::Client,Sqlite3::Database,PG::Connection,#metal] connection A supported database connection.
40
66
  #
41
67
  # Clear any database functions that may have been created.
@@ -182,9 +208,9 @@ class Upsert
182
208
  # @param [Mysql2::Client,Sqlite3::Database,PG::Connection,#metal] connection A supported database connection.
183
209
  # @param [String,Symbol] table_name The name of the table into which you will be upserting.
184
210
  # @param [Hash] options
185
- # @option options [TrueClass,FalseClass] :assume_function_exists (false) Assume the function has already been defined correctly by another process.
211
+ # @option options [TrueClass,FalseClass] :assume_function_exists (true) Assume the function has already been defined correctly by another process.
186
212
  def initialize(connection, table_name, options = {})
187
- @table_name = table_name.to_s
213
+ @table_name = self.class.normalize_table_name(table_name)
188
214
  metal = Upsert.metal connection
189
215
  @flavor = Upsert.flavor metal
190
216
  @adapter = Upsert.adapter metal
@@ -195,7 +221,10 @@ class Upsert
195
221
  @connection = Connection.const_get(adapter).new self, metal
196
222
  @merge_function_class = MergeFunction.const_get adapter
197
223
  @merge_function_cache = {}
198
- @assume_function_exists = options.fetch :assume_function_exists, false
224
+ @assume_function_exists = options.fetch :assume_function_exists, @flavor != "Postgresql"
225
+
226
+ @merge_function_mutex = Mutex.new
227
+ @row_mutex = Mutex.new
199
228
  end
200
229
 
201
230
  # Upsert a row given a selector and a setter.
@@ -215,27 +244,41 @@ class Upsert
215
244
  # upsert.row({:name => 'Pierre'}, :breed => 'tabby')
216
245
  def row(selector, setter = {}, options = nil)
217
246
  row_object = Row.new(selector, setter, options)
218
- merge_function(row_object).execute(row_object)
219
- nil
247
+ self.class.mutex_for_row(self, row_object).synchronize do
248
+ merge_function(row_object).execute(row_object)
249
+ nil
250
+ end
220
251
  end
221
252
 
222
253
  # @private
223
254
  def clear_database_functions
224
255
  merge_function_class.clear connection
225
256
  end
226
-
257
+
227
258
  def merge_function(row)
228
259
  cache_key = [row.selector.keys, row.setter.keys]
229
- @merge_function_cache[cache_key] ||= merge_function_class.new(self, row.selector.keys, row.setter.keys, assume_function_exists?)
260
+ self.class.mutex_for_function(self, row).synchronize do
261
+ @merge_function_cache[cache_key] ||=
262
+ merge_function_class.new(self, row.selector.keys, row.setter.keys, assume_function_exists?)
263
+ end
230
264
  end
231
265
 
232
266
  # @private
233
267
  def quoted_table_name
234
- @quoted_table_name ||= connection.quote_ident table_name
268
+ @quoted_table_name ||= table_name.map { |t| connection.quote_ident(t) }.join(".")
235
269
  end
236
270
 
237
271
  # @private
238
272
  def column_definitions
239
- @column_definitions ||= ColumnDefinition.const_get(flavor).all connection, table_name
273
+ @column_definitions ||= ColumnDefinition.const_get(flavor).all connection, quoted_table_name
274
+ end
275
+
276
+ # @private
277
+ def self.normalize_table_name(table_name)
278
+ if defined?(Sequel) && table_name.is_a?(::Sequel::SQL::QualifiedIdentifier)
279
+ [table_name.table, table_name.column]
280
+ else
281
+ [*table_name].map(&:to_s)
282
+ end
240
283
  end
241
284
  end
@@ -3,8 +3,8 @@ class Upsert
3
3
  # @private
4
4
  class Mysql < ColumnDefinition
5
5
  class << self
6
- def all(connection, table_name)
7
- connection.execute("SHOW COLUMNS FROM #{connection.quote_ident(table_name)}").map do |row|
6
+ def all(connection, quoted_table_name)
7
+ connection.execute("SHOW COLUMNS FROM #{quoted_table_name}").map do |row|
8
8
  # {"Field"=>"name", "Type"=>"varchar(255)", "Null"=>"NO", "Key"=>"PRI", "Default"=>nil, "Extra"=>""}
9
9
  name = row['Field'] || row['COLUMN_NAME'] || row[:Field] || row[:COLUMN_NAME]
10
10
  type = row['Type'] || row['COLUMN_TYPE'] || row[:Type] || row[:COLUMN_TYPE]
@@ -4,14 +4,14 @@ class Upsert
4
4
  class Postgresql < ColumnDefinition
5
5
  class << self
6
6
  # activerecord-3.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb#column_definitions
7
- def all(connection, table_name)
7
+ def all(connection, quoted_table_name)
8
8
  res = connection.execute <<-EOS
9
- SELECT a.attname AS name, format_type(a.atttypid, a.atttypmod) AS sql_type, d.adsrc AS default
10
- FROM pg_attribute a LEFT JOIN pg_attrdef d
9
+ SELECT a.attname AS name, format_type(a.atttypid, a.atttypmod) AS sql_type, d.adsrc AS default
10
+ FROM pg_attribute a LEFT JOIN pg_attrdef d
11
11
  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
12
- WHERE a.attrelid = '#{connection.quote_ident(table_name)}'::regclass
13
- AND a.attnum > 0 AND NOT a.attisdropped
14
- EOS
12
+ WHERE a.attrelid = '#{quoted_table_name}'::regclass
13
+ AND a.attnum > 0 AND NOT a.attisdropped
14
+ EOS
15
15
  res.map do |row|
16
16
  new connection, row['name'], row['sql_type'], row['default']
17
17
  end.sort_by do |cd|
@@ -19,7 +19,7 @@ EOS
19
19
  end
20
20
  end
21
21
  end
22
-
22
+
23
23
  # NOTE not using this because it can't be indexed
24
24
  # def equality(left, right)
25
25
  # "#{left} IS NOT DISTINCT FROM #{right}"
@@ -40,7 +40,8 @@ EOS
40
40
  if hstore?
41
41
  'text'
42
42
  else
43
- super
43
+ # JDBC uses prepared statements and properly sends date objects (which are otherwise escaped)
44
+ RUBY_PLATFORM == "java" ? sql_type : super
44
45
  end
45
46
  end
46
47