From a296838bd2832f2a7095a60059936f6f3336ae11 Mon Sep 17 00:00:00 2001 From: Abdullah Barrak Date: Sun, 28 Jan 2018 12:07:10 +0300 Subject: [PATCH 1/2] add support of providing raw sql query instead of context relation --- .gitignore | 4 ++++ lib/postgres-copy/acts_as_copy_target.rb | 5 +++-- spec/copy_to_spec.rb | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 38df41b..ce3cd4a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,7 @@ pkg ## PROJECT::SPECIFIC .project + +# RVM files +.ruby-version +.ruby-gemset diff --git a/lib/postgres-copy/acts_as_copy_target.rb b/lib/postgres-copy/acts_as_copy_target.rb index c1320b1..fc75d58 100644 --- a/lib/postgres-copy/acts_as_copy_target.rb +++ b/lib/postgres-copy/acts_as_copy_target.rb @@ -16,12 +16,13 @@ def copy_to path = nil, options = {} else "DELIMITER '#{options[:delimiter]}' CSV #{options[:header] ? 'HEADER' : ''}" end + options_query = options.delete(:query) || self.all.to_sql if path raise "You have to choose between exporting to a file or receiving the lines inside a block" if block_given? - connection.execute "COPY (#{self.all.to_sql}) TO '#{sanitize_sql(path)}' WITH #{options_string}" + connection.execute "COPY (#{options_query}) TO '#{sanitize_sql(path)}' WITH #{options_string}" else - connection.raw_connection.copy_data "COPY (#{self.all.to_sql}) TO STDOUT WITH #{options_string}" do + connection.raw_connection.copy_data "COPY (#{options_query}) TO STDOUT WITH #{options_string}" do while line = connection.raw_connection.get_copy_data do yield(line) if block_given? end diff --git a/spec/copy_to_spec.rb b/spec/copy_to_spec.rb index 2a11021..a3ebfb9 100644 --- a/spec/copy_to_spec.rb +++ b/spec/copy_to_spec.rb @@ -5,7 +5,7 @@ ActiveRecord::Base.connection.execute %{ TRUNCATE TABLE test_models; SELECT setval('test_models_id_seq', 1, false); -} + } TestModel.create :data => 'test data 1' end @@ -79,5 +79,11 @@ end end.should raise_error end + + it "accepts custom sql query to run instead on the current relation" do + TestModel.copy_to '/tmp/export.csv', query: 'SELECT count(*) as "Total" FROM test_models' + content = File.open('/tmp/export.csv', 'r').read + expect(content).to eq("Total\n1\n") + end end end From 3a5cd81f77b9ff976c6381d6e405b6e94f4a4161 Mon Sep 17 00:00:00 2001 From: Abdullah Barrak Date: Sun, 28 Jan 2018 12:13:02 +0300 Subject: [PATCH 2/2] docs: add documentations for new query option --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index a8373c9..1090996 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,18 @@ Which will generate the following SQL command: COPY (SELECT name FROM "users" WHERE "users"."id" IN (1, 2, 3)) TO '/tmp/users.csv' WITH DELIMITER ',' CSV HEADER ``` +Alternatively, you can supply customized raw SQL query to copy_to instead of scoped relation: + +```ruby +User.copy_to("/tmp/users.csv", query: 'SELECT count(*) as Total FROM users') +``` + +Which will generate the following SQL command: + +```sql +COPY (SELECT count(*) as Total FROM users) TO '/tmp/users.csv' WITH DELIMITER ',' CSV HEADER +``` + The COPY command also supports exporting the data in binary format. ```ruby