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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -0
- data/.standard.yml +1 -0
- data/.travis.yml +60 -12
- data/CHANGELOG +39 -0
- data/Gemfile +12 -1
- data/LICENSE +3 -1
- data/README.md +47 -6
- data/Rakefile +7 -1
- data/lib/upsert.rb +54 -11
- 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 +11 -5
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc_PgConnection.rb +33 -0
- data/lib/upsert/connection/PG_Connection.rb +10 -1
- data/lib/upsert/connection/jdbc.rb +20 -1
- data/lib/upsert/connection/postgresql.rb +2 -3
- data/lib/upsert/merge_function.rb +5 -4
- data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc_PgConnection.rb +27 -0
- data/lib/upsert/merge_function/PG_Connection.rb +11 -42
- data/lib/upsert/merge_function/postgresql.rb +215 -1
- data/lib/upsert/merge_function/sqlite3.rb +10 -0
- data/lib/upsert/version.rb +1 -1
- data/spec/active_record_upsert_spec.rb +10 -0
- data/spec/correctness_spec.rb +34 -5
- data/spec/database_functions_spec.rb +16 -9
- data/spec/database_spec.rb +7 -0
- data/spec/hstore_spec.rb +56 -55
- data/spec/jruby_spec.rb +9 -0
- data/spec/logger_spec.rb +8 -6
- data/spec/postgresql_spec.rb +94 -0
- data/spec/reserved_words_spec.rb +21 -17
- data/spec/sequel_spec.rb +26 -7
- data/spec/spec_helper.rb +251 -92
- data/spec/speed_spec.rb +3 -32
- data/spec/threaded_spec.rb +35 -12
- data/spec/type_safety_spec.rb +2 -1
- data/travis/install_postgres.sh +18 -0
- data/travis/run_docker_db.sh +20 -0
- data/travis/tune_mysql.sh +7 -0
- data/upsert-java.gemspec +13 -0
- data/upsert.gemspec +9 -57
- data/upsert.gemspec.common +107 -0
- metadata +53 -40
- data/lib/upsert/connection/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -15
- data/lib/upsert/merge_function/Java_OrgPostgresqlJdbc4_Jdbc4Connection.rb +0 -39
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,15 +1,63 @@
|
|
1
|
+
dist: xenial
|
1
2
|
language: ruby
|
2
|
-
|
3
|
-
|
4
|
-
|
3
|
+
cache: bundler
|
4
|
+
services:
|
5
|
+
- docker
|
5
6
|
rvm:
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
-
- 2.
|
9
|
-
-
|
10
|
-
-
|
11
|
-
- 1.
|
12
|
-
-
|
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
|
-
|
15
|
-
-
|
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
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
|
-
(
|
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
|
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
@@ -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 ||
|
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 (
|
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
|
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,
|
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
|
-
|
219
|
-
|
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
|
-
|
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
|
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,
|
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,
|
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
|
|