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