upsert 2.2.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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -0
- data/.standard.yml +1 -0
- data/.travis.yml +54 -31
- data/CHANGELOG +16 -0
- data/Gemfile +12 -1
- data/LICENSE +3 -1
- data/README.md +43 -8
- data/Rakefile +7 -1
- data/lib/upsert.rb +49 -7
- data/lib/upsert/column_definition/mysql.rb +2 -2
- data/lib/upsert/column_definition/postgresql.rb +9 -8
- data/lib/upsert/column_definition/sqlite3.rb +3 -3
- data/lib/upsert/connection/Java_ComMysqlJdbc_JDBC4Connection.rb +5 -3
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc_PgConnection.rb +33 -0
- data/lib/upsert/connection/PG_Connection.rb +5 -0
- data/lib/upsert/connection/jdbc.rb +7 -1
- data/lib/upsert/connection/postgresql.rb +2 -3
- data/lib/upsert/merge_function.rb +3 -2
- data/lib/upsert/merge_function/{Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb → Java_OrgPostgresqlJdbc_PgConnection.rb} +2 -2
- data/lib/upsert/merge_function/PG_Connection.rb +2 -2
- data/lib/upsert/merge_function/postgresql.rb +81 -19
- data/lib/upsert/merge_function/sqlite3.rb +10 -0
- data/lib/upsert/version.rb +1 -1
- data/spec/correctness_spec.rb +20 -5
- data/spec/database_functions_spec.rb +6 -2
- data/spec/hstore_spec.rb +53 -38
- data/spec/logger_spec.rb +1 -1
- data/spec/postgresql_spec.rb +81 -3
- data/spec/reserved_words_spec.rb +18 -14
- data/spec/sequel_spec.rb +16 -7
- data/spec/spec_helper.rb +238 -111
- data/spec/speed_spec.rb +3 -33
- data/spec/threaded_spec.rb +35 -12
- data/spec/type_safety_spec.rb +2 -1
- data/travis/run_docker_db.sh +20 -0
- data/upsert-java.gemspec +13 -0
- data/upsert.gemspec +9 -58
- data/upsert.gemspec.common +107 -0
- metadata +39 -46
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5d3ee917c4d930fdfb8be20d6838b49f88142ffb35122ed9c84724ceb498df16
|
4
|
+
data.tar.gz: f8186de9b5a77c3b5dd58ac23b14a7280a27f8a37d2dd3e0305f9dd725846ae4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,40 +1,63 @@
|
|
1
|
-
|
2
|
-
dist: trusty
|
1
|
+
dist: xenial
|
3
2
|
language: ruby
|
4
|
-
|
5
|
-
|
6
|
-
-
|
7
|
-
addons:
|
8
|
-
apt:
|
9
|
-
packages:
|
10
|
-
# https://github.com/travis-ci/docs-travis-ci-com/pull/743
|
11
|
-
- haveged
|
12
|
-
- mysql-server-5.6
|
13
|
-
- mysql-client-core-5.6
|
14
|
-
- mysql-client-5.6
|
3
|
+
cache: bundler
|
4
|
+
services:
|
5
|
+
- docker
|
15
6
|
rvm:
|
7
|
+
- 2.6
|
8
|
+
- 2.5
|
9
|
+
- 2.4
|
16
10
|
- 2.3
|
17
11
|
- 2.2
|
18
|
-
-
|
19
|
-
- 1.
|
20
|
-
-
|
21
|
-
|
22
|
-
|
12
|
+
- jruby-9.1.14.0
|
13
|
+
- jruby-9.1.17.0
|
14
|
+
- jruby-9.2.7.0
|
15
|
+
env:
|
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
|
23
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
|
24
56
|
allow_failures:
|
25
|
-
-
|
26
|
-
env:
|
27
|
-
- DB=postgresql PGVERSION=9.4
|
28
|
-
- DB=postgresql PGVERSION=9.5
|
29
|
-
- DB=postgresql PGVERSION=9.4 UNIQUE_CONSTRAINT=true
|
30
|
-
- DB=postgresql PGVERSION=9.5 UNIQUE_CONSTRAINT=true
|
31
|
-
- DB=mysql DB_USER=root
|
57
|
+
- env: DB=postgresql DB_VERSION=postgres:12
|
58
|
+
- env: DB=postgresql DB_VERSION=postgres:12 UNIQUE_CONSTRAINT=true
|
32
59
|
before_install:
|
33
|
-
-
|
34
|
-
# Right now the build-script is properly installing Postgres version. We will need this to test PG 9.6 and up, though
|
35
|
-
# - if [ "$DB" = 'postgresql' ]; then sudo ./travis/install_postgres.sh; fi
|
36
|
-
- gem update --system
|
37
|
-
- gem update bundler
|
60
|
+
- ./travis/run_docker_db.sh
|
38
61
|
- bundle --version
|
39
62
|
- gem --version
|
40
|
-
script:
|
63
|
+
script: ./travis/run_specs.sh
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
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
|
+
|
1
17
|
2.2.0 / 2017-04-14
|
2
18
|
|
3
19
|
* Enhancements
|
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
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
|
@@ -59,9 +59,11 @@ Batch mode is tested to be about 80% faster on PostgreSQL, MySQL, and SQLite3 th
|
|
59
59
|
|
60
60
|
### Native Postgres upsert
|
61
61
|
|
62
|
-
`INSERT ... ON CONFLICT DO UPDATE` is used when Postgres 9.5+ is detected and *unique
|
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.
|
63
65
|
|
64
|
-
If you don't have unique
|
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.
|
65
67
|
|
66
68
|
### ActiveRecord helper method
|
67
69
|
|
@@ -121,7 +123,10 @@ See below for details about what SQL MERGE trick (emulation of upsert) is used,
|
|
121
123
|
|
122
124
|
### Rails / ActiveRecord
|
123
125
|
|
124
|
-
(
|
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
|
125
130
|
|
126
131
|
```ruby
|
127
132
|
Upsert.new Pet.connection, Pet.table_name
|
@@ -173,7 +178,7 @@ BEGIN
|
|
173
178
|
DECLARE done BOOLEAN;
|
174
179
|
REPEAT
|
175
180
|
BEGIN
|
176
|
-
-- If there is a unique key constraint error then
|
181
|
+
-- If there is a unique key constraint error then
|
177
182
|
-- someone made a concurrent insert. Reset the sentinel
|
178
183
|
-- and try again.
|
179
184
|
DECLARE ER_DUP_UNIQUE CONDITION FOR 23000;
|
@@ -181,7 +186,7 @@ BEGIN
|
|
181
186
|
DECLARE CONTINUE HANDLER FOR ER_DUP_UNIQUE BEGIN
|
182
187
|
SET done = FALSE;
|
183
188
|
END;
|
184
|
-
|
189
|
+
|
185
190
|
DECLARE CONTINUE HANDLER FOR ER_INTEG BEGIN
|
186
191
|
SET done = TRUE;
|
187
192
|
END;
|
@@ -191,7 +196,7 @@ BEGIN
|
|
191
196
|
-- Race condition here. If a concurrent INSERT is made after
|
192
197
|
-- the SELECT but before the INSERT below we'll get a duplicate
|
193
198
|
-- key error. But the handler above will take care of that.
|
194
|
-
IF @count > 0 THEN
|
199
|
+
IF @count > 0 THEN
|
195
200
|
-- UPDATE table_name SET b = b_SET WHERE a = a_SEL;
|
196
201
|
UPDATE `pets` SET `name` = `name_set`, `tag_number` = `tag_number_set` WHERE `name` = `name_sel` AND `tag_number` = `tag_number_sel`;
|
197
202
|
ELSE
|
@@ -230,6 +235,15 @@ require 'pg_hstore'
|
|
230
235
|
upsert.row({:name => 'Bill'}, :mydata => {:a => 1, :b => 2})
|
231
236
|
```
|
232
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
|
+
|
233
247
|
#### Speed
|
234
248
|
|
235
249
|
From the tests (updated 9/21/12):
|
@@ -367,10 +381,31 @@ If you're using MySQL, make sure server/connection timezone is UTC. If you're us
|
|
367
381
|
|
368
382
|
In general, run some upserts and make sure datetimes get persisted like you expect.
|
369
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
|
+
|
370
400
|
### Doesn't work with transactional fixtures
|
371
401
|
|
372
402
|
Per https://github.com/seamusabshere/upsert/issues/23 you might have issues if you try to use transactional fixtures and this library.
|
373
403
|
|
404
|
+
##
|
405
|
+
Testmetrics - https://www.testmetrics.app/seamusabshere/upsert
|
406
|
+
|
374
407
|
## Copyright
|
375
408
|
|
376
|
-
Copyright
|
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/
|
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
@@ -37,6 +37,31 @@ class Upsert
|
|
37
37
|
end
|
38
38
|
end
|
39
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
|
+
|
40
65
|
# @param [Mysql2::Client,Sqlite3::Database,PG::Connection,#metal] connection A supported database connection.
|
41
66
|
#
|
42
67
|
# Clear any database functions that may have been created.
|
@@ -185,7 +210,7 @@ class Upsert
|
|
185
210
|
# @param [Hash] options
|
186
211
|
# @option options [TrueClass,FalseClass] :assume_function_exists (true) Assume the function has already been defined correctly by another process.
|
187
212
|
def initialize(connection, table_name, options = {})
|
188
|
-
@table_name = table_name
|
213
|
+
@table_name = self.class.normalize_table_name(table_name)
|
189
214
|
metal = Upsert.metal connection
|
190
215
|
@flavor = Upsert.flavor metal
|
191
216
|
@adapter = Upsert.adapter metal
|
@@ -196,7 +221,10 @@ class Upsert
|
|
196
221
|
@connection = Connection.const_get(adapter).new self, metal
|
197
222
|
@merge_function_class = MergeFunction.const_get adapter
|
198
223
|
@merge_function_cache = {}
|
199
|
-
@assume_function_exists = options.fetch :assume_function_exists,
|
224
|
+
@assume_function_exists = options.fetch :assume_function_exists, @flavor != "Postgresql"
|
225
|
+
|
226
|
+
@merge_function_mutex = Mutex.new
|
227
|
+
@row_mutex = Mutex.new
|
200
228
|
end
|
201
229
|
|
202
230
|
# Upsert a row given a selector and a setter.
|
@@ -216,8 +244,10 @@ class Upsert
|
|
216
244
|
# upsert.row({:name => 'Pierre'}, :breed => 'tabby')
|
217
245
|
def row(selector, setter = {}, options = nil)
|
218
246
|
row_object = Row.new(selector, setter, options)
|
219
|
-
|
220
|
-
|
247
|
+
self.class.mutex_for_row(self, row_object).synchronize do
|
248
|
+
merge_function(row_object).execute(row_object)
|
249
|
+
nil
|
250
|
+
end
|
221
251
|
end
|
222
252
|
|
223
253
|
# @private
|
@@ -227,16 +257,28 @@ class Upsert
|
|
227
257
|
|
228
258
|
def merge_function(row)
|
229
259
|
cache_key = [row.selector.keys, row.setter.keys]
|
230
|
-
|
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
|
231
264
|
end
|
232
265
|
|
233
266
|
# @private
|
234
267
|
def quoted_table_name
|
235
|
-
@quoted_table_name ||= connection.quote_ident
|
268
|
+
@quoted_table_name ||= table_name.map { |t| connection.quote_ident(t) }.join(".")
|
236
269
|
end
|
237
270
|
|
238
271
|
# @private
|
239
272
|
def column_definitions
|
240
|
-
@column_definitions ||= ColumnDefinition.const_get(flavor).all connection,
|
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
|
241
283
|
end
|
242
284
|
end
|
@@ -3,8 +3,8 @@ class Upsert
|
|
3
3
|
# @private
|
4
4
|
class Mysql < ColumnDefinition
|
5
5
|
class << self
|
6
|
-
def all(connection,
|
7
|
-
connection.execute("SHOW COLUMNS FROM #{
|
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,
|
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 = '#{
|
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
|
-
|
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
|
|
@@ -3,9 +3,9 @@ class Upsert
|
|
3
3
|
# @private
|
4
4
|
class Sqlite3 < ColumnDefinition
|
5
5
|
class << self
|
6
|
-
def all(connection,
|
6
|
+
def all(connection, quoted_table_name)
|
7
7
|
# activerecord-3.2.13/lib/active_record/connection_adapters/sqlite_adapter.rb
|
8
|
-
connection.execute("PRAGMA table_info(#{
|
8
|
+
connection.execute("PRAGMA table_info(#{quoted_table_name})").map do |row|#, 'SCHEMA').to_hash
|
9
9
|
if connection.metal.respond_to?(:results_as_hash) and not connection.metal.results_as_hash
|
10
10
|
row = {'name' => row[1], 'type' => row[2], 'dflt_value' => row[4]}
|
11
11
|
end
|
@@ -25,7 +25,7 @@ class Upsert
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def equality(left, right)
|
30
30
|
"(#{left} IS #{right} OR (#{left} IS NULL AND #{right} IS NULL))"
|
31
31
|
end
|