postgres_upsert 3.1.0-java → 3.2.0-java
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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +13 -4
- data/Rakefile +4 -16
- data/bin/bundle +3 -0
- data/bin/rails +4 -0
- data/bin/rake +4 -0
- data/bin/setup +29 -0
- data/config/application.rb +26 -0
- data/config/boot.rb +3 -0
- data/config/database.yml +22 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +41 -0
- data/config/environments/production.rb +79 -0
- data/config/environments/test.rb +42 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +56 -0
- data/config/secrets.yml +22 -0
- data/config.ru +4 -0
- data/db/migrate/20150214192135_create_test_tables.rb +19 -0
- data/db/schema.rb +28 -0
- data/db/seeds.rb +7 -0
- data/lib/postgres_upsert/active_record.rb +1 -1
- data/lib/postgres_upsert/writer.rb +41 -65
- data/postgres_upsert.gemspec +2 -2
- data/spec/pg_upsert_binary_spec.rb +0 -6
- data/spec/pg_upsert_csv_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -33
- metadata +28 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a166fc5c6a14c11742339c30f2a5adac836d894
|
4
|
+
data.tar.gz: 88a1acf92267cd88e13f155af23d1d52ceadd2a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f95b444a3d883d52e32272ee8af8f1763f1f13c8328f8c98f0bf196ba8eac79443a5ba1b0af53410111c827f86428cdb8cd1900397c07d318daf6c1b7a4f852
|
7
|
+
data.tar.gz: 18406dd2ba138d0e6acbe858af96e179f40b063d5ff463f2b22831cfae7495ff99dce22bf8d1031ddaabfc4a68dc2b3b3f9065dbf8e23c59a3af7e7c462098fd
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
postgres_upsert (3.
|
4
|
+
postgres_upsert (3.1.0-java)
|
5
5
|
activerecord (>= 3.0.0)
|
6
6
|
activerecord-jdbcpostgresql-adapter
|
7
7
|
rails (>= 3.0.0)
|
@@ -106,16 +106,25 @@ GEM
|
|
106
106
|
rake (>= 0.8.7)
|
107
107
|
thor (>= 0.18.1, < 2.0)
|
108
108
|
rake (10.4.2)
|
109
|
-
rdoc (4.2.0)
|
110
|
-
json (~> 1.4)
|
111
109
|
rspec (2.99.0)
|
112
110
|
rspec-core (~> 2.99.0)
|
113
111
|
rspec-expectations (~> 2.99.0)
|
114
112
|
rspec-mocks (~> 2.99.0)
|
113
|
+
rspec-collection_matchers (1.1.2)
|
114
|
+
rspec-expectations (>= 2.99.0.beta1)
|
115
115
|
rspec-core (2.99.2)
|
116
116
|
rspec-expectations (2.99.2)
|
117
117
|
diff-lcs (>= 1.1.3, < 2.0)
|
118
118
|
rspec-mocks (2.99.3)
|
119
|
+
rspec-rails (2.99.0)
|
120
|
+
actionpack (>= 3.0)
|
121
|
+
activemodel (>= 3.0)
|
122
|
+
activesupport (>= 3.0)
|
123
|
+
railties (>= 3.0)
|
124
|
+
rspec-collection_matchers
|
125
|
+
rspec-core (~> 2.99.0)
|
126
|
+
rspec-expectations (~> 2.99.0)
|
127
|
+
rspec-mocks (~> 2.99.0)
|
119
128
|
sequel (4.19.0)
|
120
129
|
slop (3.6.0)
|
121
130
|
spoon (0.0.4)
|
@@ -142,5 +151,5 @@ DEPENDENCIES
|
|
142
151
|
bundler
|
143
152
|
postgres_upsert!
|
144
153
|
pry-rails
|
145
|
-
rdoc
|
146
154
|
rspec (~> 2.12)
|
155
|
+
rspec-rails (~> 2.0)
|
data/Rakefile
CHANGED
@@ -1,18 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
require 'bundler/gem_tasks'
|
4
|
-
require 'rubygems'
|
5
|
-
require 'rspec/core/rake_task'
|
6
|
-
require 'rdoc/task'
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
7
3
|
|
8
|
-
|
4
|
+
require File.expand_path('../config/application', __FILE__)
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
Rake::RDocTask.new do |rdoc|
|
13
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
14
|
-
rdoc.rdoc_dir = 'rdoc'
|
15
|
-
rdoc.title = "postgres_upsert #{version}"
|
16
|
-
rdoc.rdoc_files.include('README*')
|
17
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
18
|
-
end
|
6
|
+
Rails.application.load_tasks
|
data/bin/bundle
ADDED
data/bin/rails
ADDED
data/bin/rake
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
# path to your application root.
|
5
|
+
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
|
6
|
+
|
7
|
+
Dir.chdir APP_ROOT do
|
8
|
+
# This script is a starting point to setup your application.
|
9
|
+
# Add necessary setup steps to this file:
|
10
|
+
|
11
|
+
puts "== Installing dependencies =="
|
12
|
+
system "gem install bundler --conservative"
|
13
|
+
system "bundle check || bundle install"
|
14
|
+
|
15
|
+
# puts "\n== Copying sample files =="
|
16
|
+
# unless File.exist?("config/database.yml")
|
17
|
+
# system "cp config/database.yml.sample config/database.yml"
|
18
|
+
# end
|
19
|
+
|
20
|
+
puts "\n== Preparing database =="
|
21
|
+
system "bin/rake db:setup"
|
22
|
+
|
23
|
+
puts "\n== Removing old logs and tempfiles =="
|
24
|
+
system "rm -f log/*"
|
25
|
+
system "rm -rf tmp/cache"
|
26
|
+
|
27
|
+
puts "\n== Restarting application server =="
|
28
|
+
system "touch tmp/restart.txt"
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require 'rails/all'
|
4
|
+
|
5
|
+
# Require the gems listed in Gemfile, including any gems
|
6
|
+
# you've limited to :test, :development, or :production.
|
7
|
+
Bundler.require(*Rails.groups)
|
8
|
+
|
9
|
+
module PostgresUpsert
|
10
|
+
class Application < Rails::Application
|
11
|
+
# Settings in config/environments/* take precedence over those specified here.
|
12
|
+
# Application configuration should go into files in config/initializers
|
13
|
+
# -- all .rb files in that directory are automatically loaded.
|
14
|
+
|
15
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
16
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
17
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
18
|
+
|
19
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
20
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
21
|
+
# config.i18n.default_locale = :de
|
22
|
+
|
23
|
+
# Do not swallow errors in after_commit/after_rollback callbacks.
|
24
|
+
config.active_record.raise_in_transactional_callbacks = true
|
25
|
+
end
|
26
|
+
end
|
data/config/boot.rb
ADDED
data/config/database.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# SQLite version 3.x
|
2
|
+
# gem 'activerecord-jdbcsqlite3-adapter'
|
3
|
+
#
|
4
|
+
# Configure Using Gemfile
|
5
|
+
# gem 'activerecord-jdbcsqlite3-adapter'
|
6
|
+
#
|
7
|
+
default: &default
|
8
|
+
adapter: postgresql
|
9
|
+
host: localhost
|
10
|
+
port: 5432
|
11
|
+
pool: 5
|
12
|
+
|
13
|
+
development:
|
14
|
+
<<: *default
|
15
|
+
database: ar_pg_copy_dev
|
16
|
+
|
17
|
+
# Warning: The database defined as "test" will be erased and
|
18
|
+
# re-generated from your development database when you run "rake".
|
19
|
+
# Do not set this db to the same as development or production.
|
20
|
+
test:
|
21
|
+
<<: *default
|
22
|
+
database: ar_pg_copy_test
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
+
|
4
|
+
# In the development environment your application's code is reloaded on
|
5
|
+
# every request. This slows down response time but is perfect for development
|
6
|
+
# since you don't have to restart the web server when you make code changes.
|
7
|
+
config.cache_classes = false
|
8
|
+
|
9
|
+
# Do not eager load code on boot.
|
10
|
+
config.eager_load = false
|
11
|
+
|
12
|
+
# Show full error reports and disable caching.
|
13
|
+
config.consider_all_requests_local = true
|
14
|
+
config.action_controller.perform_caching = false
|
15
|
+
|
16
|
+
# Don't care if the mailer can't send.
|
17
|
+
config.action_mailer.raise_delivery_errors = false
|
18
|
+
|
19
|
+
# Print deprecation notices to the Rails logger.
|
20
|
+
config.active_support.deprecation = :log
|
21
|
+
|
22
|
+
# Raise an error on page load if there are pending migrations.
|
23
|
+
config.active_record.migration_error = :page_load
|
24
|
+
|
25
|
+
# Debug mode disables concatenation and preprocessing of assets.
|
26
|
+
# This option may cause significant delays in view rendering with a large
|
27
|
+
# number of complex assets.
|
28
|
+
config.assets.debug = true
|
29
|
+
|
30
|
+
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
31
|
+
# yet still be able to expire them through the digest params.
|
32
|
+
config.assets.digest = true
|
33
|
+
|
34
|
+
# Adds additional error checking when serving assets at runtime.
|
35
|
+
# Checks for improperly declared sprockets dependencies.
|
36
|
+
# Raises helpful error messages.
|
37
|
+
config.assets.raise_runtime_errors = true
|
38
|
+
|
39
|
+
# Raises error for missing translations
|
40
|
+
# config.action_view.raise_on_missing_translations = true
|
41
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
+
|
4
|
+
# Code is not reloaded between requests.
|
5
|
+
config.cache_classes = true
|
6
|
+
|
7
|
+
# Eager load code on boot. This eager loads most of Rails and
|
8
|
+
# your application in memory, allowing both threaded web servers
|
9
|
+
# and those relying on copy on write to perform better.
|
10
|
+
# Rake tasks automatically ignore this option for performance.
|
11
|
+
config.eager_load = true
|
12
|
+
|
13
|
+
# Full error reports are disabled and caching is turned on.
|
14
|
+
config.consider_all_requests_local = false
|
15
|
+
config.action_controller.perform_caching = true
|
16
|
+
|
17
|
+
# Enable Rack::Cache to put a simple HTTP cache in front of your application
|
18
|
+
# Add `rack-cache` to your Gemfile before enabling this.
|
19
|
+
# For large-scale production use, consider using a caching reverse proxy like
|
20
|
+
# NGINX, varnish or squid.
|
21
|
+
# config.action_dispatch.rack_cache = true
|
22
|
+
|
23
|
+
# Disable serving static files from the `/public` folder by default since
|
24
|
+
# Apache or NGINX already handles this.
|
25
|
+
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
26
|
+
|
27
|
+
# Compress JavaScripts and CSS.
|
28
|
+
config.assets.js_compressor = :uglifier
|
29
|
+
# config.assets.css_compressor = :sass
|
30
|
+
|
31
|
+
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
32
|
+
config.assets.compile = false
|
33
|
+
|
34
|
+
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
35
|
+
# yet still be able to expire them through the digest params.
|
36
|
+
config.assets.digest = true
|
37
|
+
|
38
|
+
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
39
|
+
|
40
|
+
# Specifies the header that your server uses for sending files.
|
41
|
+
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
42
|
+
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
43
|
+
|
44
|
+
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
45
|
+
# config.force_ssl = true
|
46
|
+
|
47
|
+
# Use the lowest log level to ensure availability of diagnostic information
|
48
|
+
# when problems arise.
|
49
|
+
config.log_level = :debug
|
50
|
+
|
51
|
+
# Prepend all log lines with the following tags.
|
52
|
+
# config.log_tags = [ :subdomain, :uuid ]
|
53
|
+
|
54
|
+
# Use a different logger for distributed setups.
|
55
|
+
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
56
|
+
|
57
|
+
# Use a different cache store in production.
|
58
|
+
# config.cache_store = :mem_cache_store
|
59
|
+
|
60
|
+
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
61
|
+
# config.action_controller.asset_host = 'http://assets.example.com'
|
62
|
+
|
63
|
+
# Ignore bad email addresses and do not raise email delivery errors.
|
64
|
+
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
65
|
+
# config.action_mailer.raise_delivery_errors = false
|
66
|
+
|
67
|
+
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
68
|
+
# the I18n.default_locale when a translation cannot be found).
|
69
|
+
config.i18n.fallbacks = true
|
70
|
+
|
71
|
+
# Send deprecation notices to registered listeners.
|
72
|
+
config.active_support.deprecation = :notify
|
73
|
+
|
74
|
+
# Use default logging formatter so that PID and timestamp are not suppressed.
|
75
|
+
config.log_formatter = ::Logger::Formatter.new
|
76
|
+
|
77
|
+
# Do not dump schema after migrations.
|
78
|
+
config.active_record.dump_schema_after_migration = false
|
79
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
+
|
4
|
+
# The test environment is used exclusively to run your application's
|
5
|
+
# test suite. You never need to work with it otherwise. Remember that
|
6
|
+
# your test database is "scratch space" for the test suite and is wiped
|
7
|
+
# and recreated between test runs. Don't rely on the data there!
|
8
|
+
config.cache_classes = true
|
9
|
+
|
10
|
+
# Do not eager load code on boot. This avoids loading your whole application
|
11
|
+
# just for the purpose of running a single test. If you are using a tool that
|
12
|
+
# preloads Rails for running tests, you may have to set it to true.
|
13
|
+
config.eager_load = false
|
14
|
+
|
15
|
+
# Configure static file server for tests with Cache-Control for performance.
|
16
|
+
config.serve_static_files = true
|
17
|
+
config.static_cache_control = 'public, max-age=3600'
|
18
|
+
|
19
|
+
# Show full error reports and disable caching.
|
20
|
+
config.consider_all_requests_local = true
|
21
|
+
config.action_controller.perform_caching = false
|
22
|
+
|
23
|
+
# Raise exceptions instead of rendering exception templates.
|
24
|
+
config.action_dispatch.show_exceptions = false
|
25
|
+
|
26
|
+
# Disable request forgery protection in test environment.
|
27
|
+
config.action_controller.allow_forgery_protection = false
|
28
|
+
|
29
|
+
# Tell Action Mailer not to deliver emails to the real world.
|
30
|
+
# The :test delivery method accumulates sent emails in the
|
31
|
+
# ActionMailer::Base.deliveries array.
|
32
|
+
config.action_mailer.delivery_method = :test
|
33
|
+
|
34
|
+
# Randomize the order test cases are executed.
|
35
|
+
config.active_support.test_order = :random
|
36
|
+
|
37
|
+
# Print deprecation notices to the stderr.
|
38
|
+
config.active_support.deprecation = :stderr
|
39
|
+
|
40
|
+
# Raises error for missing translations
|
41
|
+
# config.action_view.raise_on_missing_translations = true
|
42
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
3
|
+
# than English, add the necessary files in this directory.
|
4
|
+
#
|
5
|
+
# To use the locales, use `I18n.t`:
|
6
|
+
#
|
7
|
+
# I18n.t 'hello'
|
8
|
+
#
|
9
|
+
# In views, this is aliased to just `t`:
|
10
|
+
#
|
11
|
+
# <%= t('hello') %>
|
12
|
+
#
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
14
|
+
#
|
15
|
+
# I18n.locale = :es
|
16
|
+
#
|
17
|
+
# This would use the information in config/locales/es.yml.
|
18
|
+
#
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
21
|
+
|
22
|
+
en:
|
23
|
+
hello: "Hello world"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
# The priority is based upon order of creation: first created -> highest priority.
|
3
|
+
# See how all your routes lay out with "rake routes".
|
4
|
+
|
5
|
+
# You can have the root of your site routed with "root"
|
6
|
+
# root 'welcome#index'
|
7
|
+
|
8
|
+
# Example of regular route:
|
9
|
+
# get 'products/:id' => 'catalog#view'
|
10
|
+
|
11
|
+
# Example of named route that can be invoked with purchase_url(id: product.id)
|
12
|
+
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
13
|
+
|
14
|
+
# Example resource route (maps HTTP verbs to controller actions automatically):
|
15
|
+
# resources :products
|
16
|
+
|
17
|
+
# Example resource route with options:
|
18
|
+
# resources :products do
|
19
|
+
# member do
|
20
|
+
# get 'short'
|
21
|
+
# post 'toggle'
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# collection do
|
25
|
+
# get 'sold'
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
|
29
|
+
# Example resource route with sub-resources:
|
30
|
+
# resources :products do
|
31
|
+
# resources :comments, :sales
|
32
|
+
# resource :seller
|
33
|
+
# end
|
34
|
+
|
35
|
+
# Example resource route with more complex sub-resources:
|
36
|
+
# resources :products do
|
37
|
+
# resources :comments
|
38
|
+
# resources :sales do
|
39
|
+
# get 'recent', on: :collection
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
|
43
|
+
# Example resource route with concerns:
|
44
|
+
# concern :toggleable do
|
45
|
+
# post 'toggle'
|
46
|
+
# end
|
47
|
+
# resources :posts, concerns: :toggleable
|
48
|
+
# resources :photos, concerns: :toggleable
|
49
|
+
|
50
|
+
# Example resource route within a namespace:
|
51
|
+
# namespace :admin do
|
52
|
+
# # Directs /admin/products/* to Admin::ProductsController
|
53
|
+
# # (app/controllers/admin/products_controller.rb)
|
54
|
+
# resources :products
|
55
|
+
# end
|
56
|
+
end
|
data/config/secrets.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
8
|
+
# You can use `rake secret` to generate a secure secret key.
|
9
|
+
|
10
|
+
# Make sure the secrets in this file are kept private
|
11
|
+
# if you're sharing your code publicly.
|
12
|
+
|
13
|
+
development:
|
14
|
+
secret_key_base: 8264e1ad58136b3cc4d88529894ff4372de655b520b09ecb244ccf9a4777eb8cfe29dae848a56a04b3cdc0e4dae9152efd630943c3447ab048b04cc4149e8427
|
15
|
+
|
16
|
+
test:
|
17
|
+
secret_key_base: 5ee4bb64e4cd7b273a957d7ab0049c7f120103728f8702ba03007a828e95ce0816c2b8f13e7b4b3381950ed6e8981a464f268c1f43d96b0b365b591254368737
|
18
|
+
|
19
|
+
# Do not keep production secrets in the repository,
|
20
|
+
# instead read values from the environment.
|
21
|
+
production:
|
22
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
data/config.ru
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateTestTables < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :test_models do |t|
|
4
|
+
t.string :data
|
5
|
+
t.timestamps
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :three_columns do |t|
|
9
|
+
t.string :data
|
10
|
+
t.string :extra
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :reserved_word_models do |t|
|
15
|
+
t.string :select
|
16
|
+
t.string :group
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/db/schema.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended that you check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(version: 20150214192135) do
|
15
|
+
|
16
|
+
# These are extensions that must be enabled in order to support this database
|
17
|
+
enable_extension "plpgsql"
|
18
|
+
|
19
|
+
# Could not dump table "reserved_word_models" because of following NoMethodError
|
20
|
+
# undefined method `[]' for nil:NilClass
|
21
|
+
|
22
|
+
# Could not dump table "test_models" because of following NoMethodError
|
23
|
+
# undefined method `[]' for nil:NilClass
|
24
|
+
|
25
|
+
# Could not dump table "three_columns" because of following NoMethodError
|
26
|
+
# undefined method `[]' for nil:NilClass
|
27
|
+
|
28
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# This file should contain all the record creation needed to seed the database with its default values.
|
2
|
+
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
3
|
+
#
|
4
|
+
# Examples:
|
5
|
+
#
|
6
|
+
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
7
|
+
# Mayor.create(name: 'Emanuel', city: cities.first)
|
@@ -7,7 +7,7 @@ module ActiveRecord
|
|
7
7
|
# * You can map fields from the file to different fields in the table using a map in the options hash
|
8
8
|
# * For further details on usage take a look at the README.md
|
9
9
|
def self.pg_upsert path_or_io, options = {}
|
10
|
-
PostgresUpsert::Writer.new(
|
10
|
+
PostgresUpsert::Writer.new(self, path_or_io, options).write
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -1,17 +1,15 @@
|
|
1
|
-
require 'sequel'
|
2
|
-
|
3
1
|
|
4
2
|
module PostgresUpsert
|
5
3
|
|
6
4
|
class Writer
|
7
5
|
|
8
|
-
def initialize(
|
9
|
-
@
|
6
|
+
def initialize(klass, source, options = {})
|
7
|
+
@klass = klass
|
10
8
|
@options = options.reverse_merge({
|
11
9
|
:delimiter => ",",
|
12
10
|
:format => :csv,
|
13
11
|
:header => true,
|
14
|
-
:key_column => primary_key,
|
12
|
+
:key_column => @klass.primary_key,
|
15
13
|
:update_only => false})
|
16
14
|
@source = source.instance_of?(String) ? File.open(source, 'r') : source
|
17
15
|
@columns_list = get_columns
|
@@ -19,6 +17,8 @@ module PostgresUpsert
|
|
19
17
|
end
|
20
18
|
|
21
19
|
def write
|
20
|
+
import org.postgresql.copy.CopyManager
|
21
|
+
|
22
22
|
if @columns_list.empty?
|
23
23
|
raise "Either the :columns option or :header => true are required"
|
24
24
|
end
|
@@ -28,55 +28,27 @@ module PostgresUpsert
|
|
28
28
|
copy_table = @temp_table_name
|
29
29
|
|
30
30
|
columns_string = columns_string_for_copy
|
31
|
+
|
32
|
+
ActiveRecord::Base.connection_pool.with_connection do |conn|
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
-
base_connection.synchronize do |connection|
|
35
|
-
create_temp_table(connection)
|
36
|
-
copy_manager = org.postgresql.copy.CopyManager.new(connection)
|
34
|
+
create_temp_table(conn)
|
35
|
+
copy_manager = CopyManager.new(conn.raw_connection.connection)
|
37
36
|
stream = copy_manager.copy_in("COPY #{copy_table} #{columns_string} FROM STDIN WITH #{csv_options}")
|
37
|
+
|
38
38
|
while line = read_input_line do
|
39
39
|
next if line.strip.size == 0
|
40
40
|
line = line.to_java_bytes
|
41
41
|
stream.write_to_copy(line, 0, line.length)
|
42
42
|
end
|
43
43
|
stream.end_copy
|
44
|
-
upsert_from_temp_table(
|
45
|
-
drop_temp_table(
|
44
|
+
upsert_from_temp_table(conn)
|
45
|
+
drop_temp_table(conn)
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
def primary_key
|
53
|
-
@primary_key ||= begin
|
54
|
-
query = <<-sql
|
55
|
-
SELECT
|
56
|
-
pg_attribute.attname,
|
57
|
-
format_type(pg_attribute.atttypid, pg_attribute.atttypmod)
|
58
|
-
FROM pg_index, pg_class, pg_attribute
|
59
|
-
WHERE
|
60
|
-
pg_class.oid = '#{@table_name}'::regclass AND
|
61
|
-
indrelid = pg_class.oid AND
|
62
|
-
pg_attribute.attrelid = pg_class.oid AND
|
63
|
-
pg_attribute.attnum = any(pg_index.indkey)
|
64
|
-
AND indisprimary
|
65
|
-
sql
|
66
|
-
|
67
|
-
pg_result = ActiveRecord::Base.connection.execute query
|
68
|
-
pg_result.each{ |row| return row['attname'] }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def column_names
|
73
|
-
@column_names ||= begin
|
74
|
-
query = "SELECT * FROM information_schema.columns WHERE TABLE_NAME = '#{@table_name}'"
|
75
|
-
pg_result = ActiveRecord::Base.connection.execute query
|
76
|
-
pg_result.map{ |row| row['column_name'] }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
52
|
def get_columns
|
81
53
|
columns_list = @options[:columns] || []
|
82
54
|
if @options[:format] != :binary && @options[:header]
|
@@ -97,23 +69,23 @@ module PostgresUpsert
|
|
97
69
|
|
98
70
|
def columns_string_for_select
|
99
71
|
columns = @columns_list.clone
|
100
|
-
columns << "created_at" if column_names.include?("created_at")
|
101
|
-
columns << "updated_at" if column_names.include?("updated_at")
|
72
|
+
columns << "created_at" if @klass.column_names.include?("created_at")
|
73
|
+
columns << "updated_at" if @klass.column_names.include?("updated_at")
|
102
74
|
str = get_columns_string(columns)
|
103
75
|
end
|
104
76
|
|
105
77
|
def columns_string_for_insert
|
106
78
|
columns = @columns_list.clone
|
107
|
-
columns << "created_at" if column_names.include?("created_at")
|
108
|
-
columns << "updated_at" if column_names.include?("updated_at")
|
79
|
+
columns << "created_at" if @klass.column_names.include?("created_at")
|
80
|
+
columns << "updated_at" if @klass.column_names.include?("updated_at")
|
109
81
|
str = get_columns_string(columns)
|
110
82
|
end
|
111
83
|
|
112
84
|
def select_string_for_insert
|
113
85
|
columns = @columns_list.clone
|
114
86
|
str = get_columns_string(columns)
|
115
|
-
str << ",'#{DateTime.now.utc}'" if column_names.include?("created_at")
|
116
|
-
str << ",'#{DateTime.now.utc}'" if column_names.include?("updated_at")
|
87
|
+
str << ",'#{DateTime.now.utc}'" if @klass.column_names.include?("created_at")
|
88
|
+
str << ",'#{DateTime.now.utc}'" if @klass.column_names.include?("updated_at")
|
117
89
|
str
|
118
90
|
end
|
119
91
|
|
@@ -128,12 +100,16 @@ module PostgresUpsert
|
|
128
100
|
columns.size > 0 ? "\"#{columns.join('","')}\"" : ""
|
129
101
|
end
|
130
102
|
|
131
|
-
def
|
132
|
-
|
103
|
+
def get_table_name
|
104
|
+
if @options[:table]
|
105
|
+
connection.quote_table_name(@options[:table])
|
106
|
+
else
|
107
|
+
@klass.quoted_table_name
|
108
|
+
end
|
133
109
|
end
|
134
110
|
|
135
111
|
def generate_temp_table_name
|
136
|
-
@temp_table_name = "#{@table_name}_temp_#{rand(1000)}"
|
112
|
+
@temp_table_name = "#{@klass.table_name}_temp_#{rand(1000)}"
|
137
113
|
end
|
138
114
|
|
139
115
|
def read_input_line
|
@@ -148,14 +124,14 @@ module PostgresUpsert
|
|
148
124
|
end
|
149
125
|
end
|
150
126
|
|
151
|
-
def upsert_from_temp_table(
|
152
|
-
update_from_temp_table(
|
153
|
-
insert_from_temp_table(
|
127
|
+
def upsert_from_temp_table(conn)
|
128
|
+
update_from_temp_table(conn)
|
129
|
+
insert_from_temp_table(conn) unless @options[:update_only]
|
154
130
|
end
|
155
131
|
|
156
|
-
def update_from_temp_table(
|
157
|
-
|
158
|
-
UPDATE #{
|
132
|
+
def update_from_temp_table(conn)
|
133
|
+
conn.execute <<-SQL
|
134
|
+
UPDATE #{get_table_name} AS d
|
159
135
|
#{update_set_clause}
|
160
136
|
FROM #{@temp_table_name} as t
|
161
137
|
WHERE t.#{@options[:key_column]} = d.#{@options[:key_column]}
|
@@ -167,38 +143,38 @@ module PostgresUpsert
|
|
167
143
|
command = @columns_list.map do |col|
|
168
144
|
"\"#{col}\" = t.\"#{col}\""
|
169
145
|
end
|
170
|
-
command << "\"updated_at\" = '#{DateTime.now.utc}'" if column_names.include?("updated_at")
|
146
|
+
command << "\"updated_at\" = '#{DateTime.now.utc}'" if @klass.column_names.include?("updated_at")
|
171
147
|
"SET #{command.join(',')}"
|
172
148
|
end
|
173
149
|
|
174
|
-
def insert_from_temp_table(
|
150
|
+
def insert_from_temp_table(conn)
|
175
151
|
columns_string = columns_string_for_insert
|
176
152
|
select_string = select_string_for_insert
|
177
|
-
|
178
|
-
INSERT INTO #{
|
153
|
+
conn.execute <<-SQL
|
154
|
+
INSERT INTO #{get_table_name} (#{columns_string})
|
179
155
|
SELECT #{select_string}
|
180
156
|
FROM #{@temp_table_name} as t
|
181
157
|
WHERE NOT EXISTS
|
182
158
|
(SELECT 1
|
183
|
-
FROM #{
|
159
|
+
FROM #{get_table_name} as d
|
184
160
|
WHERE d.#{@options[:key_column]} = t.#{@options[:key_column]})
|
185
161
|
AND t.#{@options[:key_column]} IS NOT NULL;
|
186
162
|
SQL
|
187
163
|
end
|
188
164
|
|
189
|
-
def create_temp_table(
|
165
|
+
def create_temp_table(conn)
|
190
166
|
columns_string = select_string_for_create
|
191
|
-
|
167
|
+
conn.execute <<-SQL
|
192
168
|
SET client_min_messages=WARNING;
|
193
169
|
DROP TABLE IF EXISTS #{@temp_table_name};
|
194
170
|
|
195
171
|
CREATE TEMP TABLE #{@temp_table_name}
|
196
|
-
AS SELECT #{columns_string} FROM #{
|
172
|
+
AS SELECT #{columns_string} FROM #{get_table_name} WHERE 0 = 1;
|
197
173
|
SQL
|
198
174
|
end
|
199
175
|
|
200
|
-
def drop_temp_table(
|
201
|
-
|
176
|
+
def drop_temp_table(conn)
|
177
|
+
conn.execute <<-SQL
|
202
178
|
DROP TABLE #{@temp_table_name}
|
203
179
|
SQL
|
204
180
|
end
|
data/postgres_upsert.gemspec
CHANGED
@@ -5,7 +5,7 @@ $:.unshift lib unless $:.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "postgres_upsert"
|
8
|
-
s.version = "3.
|
8
|
+
s.version = "3.2.0"
|
9
9
|
|
10
10
|
s.platform = 'java'
|
11
11
|
s.authors = ["Steve Mitchell"]
|
@@ -27,8 +27,8 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_dependency "activerecord", '>= 3.0.0'
|
28
28
|
s.add_dependency "rails", '>= 3.0.0'
|
29
29
|
s.add_development_dependency "bundler"
|
30
|
-
s.add_development_dependency "rdoc"
|
31
30
|
s.add_development_dependency "pry-rails"
|
32
31
|
s.add_development_dependency "rspec", "~> 2.12"
|
32
|
+
s.add_development_dependency "rspec-rails", "~> 2.0"
|
33
33
|
end
|
34
34
|
|
@@ -1,12 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "pg_upsert from file with binary data" do
|
4
|
-
before(:each) do
|
5
|
-
ActiveRecord::Base.connection.execute %{
|
6
|
-
TRUNCATE TABLE test_models;
|
7
|
-
SELECT setval('test_models_id_seq', 1, false);
|
8
|
-
}
|
9
|
-
end
|
10
4
|
|
11
5
|
before do
|
12
6
|
DateTime.stub(:now).and_return (DateTime.parse("2012-01-01").utc)
|
data/spec/pg_upsert_csv_spec.rb
CHANGED
@@ -180,7 +180,7 @@ describe "pg_upsert from file with CSV format" do
|
|
180
180
|
ThreeColumn.pg_upsert(file, :key_column => "data")
|
181
181
|
expect(
|
182
182
|
ThreeColumn.last.attributes
|
183
|
-
).to include("
|
183
|
+
).to include("data" => "old stuff", "extra" => "ABC: Always Be Changing.")
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,43 +1,15 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
require File.expand_path("../../config/environment", __FILE__)
|
2
3
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
4
|
require 'fixtures/test_model'
|
4
5
|
require 'fixtures/three_column'
|
5
6
|
require 'fixtures/reserved_word_model'
|
6
7
|
require 'rspec'
|
8
|
+
require 'rspec/rails'
|
7
9
|
require 'rspec/autorun'
|
8
10
|
|
9
11
|
RSpec.configure do |config|
|
10
|
-
config.
|
11
|
-
|
12
|
-
|
13
|
-
begin
|
14
|
-
ActiveRecord::Base.establish_connection(
|
15
|
-
:adapter => "postgresql",
|
16
|
-
:host => "localhost",
|
17
|
-
:port => 5432,
|
18
|
-
:database => "ar_pg_copy_test"
|
19
|
-
)
|
20
|
-
ActiveRecord::Base.connection.execute %{
|
21
|
-
SET client_min_messages TO warning;
|
22
|
-
DROP TABLE IF EXISTS test_models;
|
23
|
-
DROP TABLE IF EXISTS three_columns;
|
24
|
-
DROP TABLE IF EXISTS reserved_word_models;
|
25
|
-
CREATE TABLE test_models (id serial PRIMARY KEY, data text, created_at timestamp with time zone, updated_at timestamp with time zone );
|
26
|
-
CREATE TABLE three_columns (id serial PRIMARY KEY, data text, extra text, created_at timestamp with time zone, updated_at timestamp with time zone );
|
27
|
-
CREATE TABLE reserved_word_models (id serial PRIMARY KEY, "select" text, "group" text);
|
28
|
-
}
|
29
|
-
rescue Exception => e
|
30
|
-
puts "Exception: #{e}"
|
31
|
-
ActiveRecord::Base.establish_connection(
|
32
|
-
:adapter => "postgresql",
|
33
|
-
:host => "localhost",
|
34
|
-
:port => 5432,
|
35
|
-
:database => "postgres"
|
36
|
-
)
|
37
|
-
ActiveRecord::Base.connection.execute "DROP DATABASE IF EXISTS ar_pg_copy_test"
|
38
|
-
ActiveRecord::Base.connection.execute "CREATE DATABASE ar_pg_copy_test;"
|
39
|
-
retry
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
12
|
+
#config.use_transactional_fixtures = false
|
13
|
+
config.expose_current_running_example_as :example
|
14
|
+
config.infer_spec_type_from_file_location!
|
43
15
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: postgres_upsert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Steve Mitchell
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
prerelease: false
|
82
82
|
type: :development
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: pry-rails
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '>='
|
@@ -95,31 +95,31 @@ dependencies:
|
|
95
95
|
prerelease: false
|
96
96
|
type: :development
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rspec
|
99
99
|
version_requirements: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '2.12'
|
104
104
|
requirement: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
|
-
- -
|
106
|
+
- - ~>
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version: '
|
108
|
+
version: '2.12'
|
109
109
|
prerelease: false
|
110
110
|
type: :development
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name: rspec
|
112
|
+
name: rspec-rails
|
113
113
|
version_requirements: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '2.
|
117
|
+
version: '2.0'
|
118
118
|
requirement: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
120
|
- - ~>
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: '2.
|
122
|
+
version: '2.0'
|
123
123
|
prerelease: false
|
124
124
|
type: :development
|
125
125
|
description: Uses Postgres's powerful COPY command to upsert large sets of data into ActiveRecord tables
|
@@ -135,6 +135,24 @@ files:
|
|
135
135
|
- README.md
|
136
136
|
- Rakefile
|
137
137
|
- VERSION
|
138
|
+
- bin/bundle
|
139
|
+
- bin/rails
|
140
|
+
- bin/rake
|
141
|
+
- bin/setup
|
142
|
+
- config.ru
|
143
|
+
- config/application.rb
|
144
|
+
- config/boot.rb
|
145
|
+
- config/database.yml
|
146
|
+
- config/environment.rb
|
147
|
+
- config/environments/development.rb
|
148
|
+
- config/environments/production.rb
|
149
|
+
- config/environments/test.rb
|
150
|
+
- config/locales/en.yml
|
151
|
+
- config/routes.rb
|
152
|
+
- config/secrets.yml
|
153
|
+
- db/migrate/20150214192135_create_test_tables.rb
|
154
|
+
- db/schema.rb
|
155
|
+
- db/seeds.rb
|
138
156
|
- lib/postgres_upsert.rb
|
139
157
|
- lib/postgres_upsert/active_record.rb
|
140
158
|
- lib/postgres_upsert/writer.rb
|