simple-sql 0.2.10 → 0.3.0
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/Gemfile.lock +1 -1
- data/lib/simple/sql.rb +7 -6
- data/lib/simple/sql/duplicate.rb +26 -74
- data/lib/simple/sql/version.rb +1 -1
- data/spec/simple/sql_duplicate_spec.rb +5 -5
- data/spec/simple/sql_insert_spec.rb +5 -0
- data/spec/support/001_database.rb +0 -9
- data/spec/support/factories/user_factory.rb +2 -8
- data/spec/support/model/user.rb +0 -3
- metadata +2 -4
- data/spec/simple/sql_duplicate_unique_spec.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c57a6e1295b2ce84040e5e0f8167aa83d367e0cf
|
4
|
+
data.tar.gz: 10527d7193cc63784a21ce703427f6e111fc9e39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9254b98c19843789d4ec814047316caefe96a020c3393d686ba5dcc4faac2aafcab638d01f1a04dce4286e676674a55fc7d5668d965a3452c68e80330e836ff
|
7
|
+
data.tar.gz: 3e662b58ff18e2608f3005d8f53c55e445dce91d8cd02011dcde2292d461e264b93bf0cabc7b54d12ec6df9ad84e11ade46bff5021f5e20c3d5c041a5a85d8d0
|
data/Gemfile.lock
CHANGED
data/lib/simple/sql.rb
CHANGED
@@ -25,12 +25,13 @@ module Simple
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def default_logger
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
if defined?(ActiveRecord)
|
29
|
+
ActiveRecord::Base.logger
|
30
|
+
else
|
31
|
+
logger = Logger.new(STDERR)
|
32
|
+
logger.level = Logger::INFO
|
33
|
+
logger
|
34
|
+
end
|
34
35
|
end
|
35
36
|
|
36
37
|
# execute one or more sql statements. This method does not allow to pass in
|
data/lib/simple/sql/duplicate.rb
CHANGED
@@ -1,89 +1,41 @@
|
|
1
|
-
# rubocop:disable
|
1
|
+
# rubocop:disable Metrics/MethodLength
|
2
|
+
# rubocop:disable Metrics/AbcSize
|
2
3
|
|
3
4
|
module Simple
|
4
5
|
module SQL
|
5
|
-
|
6
|
-
end
|
7
|
-
|
8
|
-
def fragment(str)
|
9
|
-
Fragment.new(str)
|
10
|
-
end
|
11
|
-
|
12
|
-
#
|
13
|
-
# Creates duplicates of record in a table.
|
14
|
-
#
|
15
|
-
# This method handles timestamp columns (these will be set to the current
|
16
|
-
# time) and primary keys (will be set to NULL.) You can pass in overrides
|
17
|
-
# as a third argument for specific columns.
|
18
|
-
#
|
19
|
-
# Parameters:
|
20
|
-
#
|
21
|
-
# - ids: (Integer, Array<Integer>) primary key ids
|
22
|
-
# - overrides: Hash[column_names => SQL::Fragment]
|
23
|
-
#
|
24
|
-
def duplicate(table, ids, overrides = {})
|
6
|
+
def duplicate(table, ids, except: [])
|
25
7
|
ids = Array(ids)
|
26
8
|
return [] if ids.empty?
|
27
9
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
class Duplicator
|
32
|
-
attr_reader :table_name, :custom_overrides
|
33
|
-
|
34
|
-
def initialize(table_name, overrides)
|
35
|
-
@table_name = table_name
|
36
|
-
@custom_overrides = validated_overrides(overrides)
|
37
|
-
end
|
38
|
-
|
39
|
-
def call(ids)
|
40
|
-
Simple::SQL.all query, ids
|
41
|
-
rescue PG::UndefinedColumn => e
|
42
|
-
raise ArgumentError, e.message
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
# This stringify all keys of the overrides hash, and verifies that
|
48
|
-
# all values in there are SQL::Fragments
|
49
|
-
def validated_overrides(overrides)
|
50
|
-
overrides.inject({}) do |hsh, (key, value)|
|
51
|
-
raise ArgumentError, "Unknown value #{value.inspect}" unless value.is_a?(Fragment)
|
52
|
-
hsh.update key.to_s => value.to_sql
|
53
|
-
end
|
54
|
-
end
|
10
|
+
timestamp_columns = Reflection.timestamp_columns(table)
|
11
|
+
primary_key_columns = Reflection.primary_key_columns(table)
|
55
12
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
13
|
+
# duplicate all columns in the table that need to be SELECTed.
|
14
|
+
#
|
15
|
+
columns_to_dupe = Reflection.columns(table)
|
61
16
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
17
|
+
# Primary keys will not be selected from the table, they should be set
|
18
|
+
# automatically by the database, via a DEFAULT role on the column.
|
19
|
+
columns_to_dupe -= primary_key_columns
|
67
20
|
|
68
|
-
#
|
69
|
-
|
70
|
-
|
21
|
+
# timestamp_columns will not be selected from the table, they will be
|
22
|
+
# set to now() explicitely.
|
23
|
+
columns_to_dupe -= timestamp_columns
|
71
24
|
|
72
|
-
|
73
|
-
|
74
|
-
|
25
|
+
# If some other columns must be excluded they have to be added in the
|
26
|
+
# except: keyword argument. This is helpful for UNIQUE columns, but
|
27
|
+
# a column which is supposed to be UNIQUE and NOT NULL can not be dealt
|
28
|
+
# with.
|
29
|
+
columns_to_dupe -= except.map(&:to_s)
|
75
30
|
|
76
|
-
|
77
|
-
|
78
|
-
|
31
|
+
# build query
|
32
|
+
select_columns = columns_to_dupe + timestamp_columns
|
33
|
+
select_values = columns_to_dupe + timestamp_columns.map { |col| "now() AS #{col}" }
|
79
34
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
WHERE id = ANY($1) RETURNING id
|
85
|
-
SQL
|
86
|
-
end
|
35
|
+
Simple::SQL.all <<~SQL, ids
|
36
|
+
INSERT INTO #{table}(#{select_columns.join(', ')})
|
37
|
+
SELECT #{select_values.join(', ')} FROM #{table} WHERE id = ANY($1) RETURNING id
|
38
|
+
SQL
|
87
39
|
end
|
88
40
|
end
|
89
41
|
end
|
data/lib/simple/sql/version.rb
CHANGED
@@ -10,24 +10,24 @@ describe "Simple::SQL.duplicate" do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it "does not fail on a non-existing user" do
|
13
|
-
dupe_ids = SQL.duplicate "users",
|
13
|
+
dupe_ids = SQL.duplicate "users", source_ids.first
|
14
14
|
|
15
|
-
expect(dupe_ids.length).to eq(
|
16
|
-
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(
|
15
|
+
expect(dupe_ids.length).to eq(1)
|
16
|
+
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(3)
|
17
17
|
end
|
18
18
|
|
19
19
|
it "duplicates a single user" do
|
20
20
|
dupe_ids = SQL.duplicate "users", source_ids.first
|
21
21
|
|
22
22
|
expect(dupe_ids.length).to eq(1)
|
23
|
-
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(
|
23
|
+
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(3)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "duplicates many users" do
|
27
27
|
dupe_ids = SQL.duplicate "users", (source_ids + [ -10 ])
|
28
28
|
|
29
29
|
expect(dupe_ids.length).to eq(2)
|
30
|
-
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(
|
30
|
+
expect(SQL.ask("SELECT COUNT(*) FROM users")).to eq(4)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "updates the timestamp columns" do
|
@@ -15,6 +15,11 @@ describe "Simple::SQL.insert" do
|
|
15
15
|
expect(user.first_name).to eq("foo")
|
16
16
|
expect(user.last_name).to eq("bar")
|
17
17
|
expect(user.created_at).to be_a(Time)
|
18
|
+
|
19
|
+
#
|
20
|
+
# r = SQL.record("SELECT COUNT(*) AS count FROM users")
|
21
|
+
# r = SQL.record("SELECT COUNT(*) AS count FROM users")
|
22
|
+
# expect(r).to eq({count: 2})
|
18
23
|
end
|
19
24
|
end
|
20
25
|
|
@@ -35,13 +35,4 @@ ActiveRecord::Schema.define do
|
|
35
35
|
|
36
36
|
t.timestamps null: true
|
37
37
|
end
|
38
|
-
|
39
|
-
create_table :unique_users, force: true do |t|
|
40
|
-
t.string :first_name
|
41
|
-
t.string :last_name
|
42
|
-
end
|
43
|
-
|
44
|
-
execute <<-SQL
|
45
|
-
CREATE UNIQUE INDEX unique_users_ix1 ON unique_users(first_name, last_name)
|
46
|
-
SQL
|
47
38
|
end
|
@@ -1,14 +1,8 @@
|
|
1
1
|
FactoryGirl.define do
|
2
2
|
factory :user do
|
3
3
|
role_id 123
|
4
|
-
|
5
|
-
|
6
|
-
sequence :last_name do |n| "Last #{n}" end
|
4
|
+
first_name "Uni"
|
5
|
+
last_name "Corn"
|
7
6
|
access_level "viewable"
|
8
7
|
end
|
9
|
-
|
10
|
-
factory :unique_user do
|
11
|
-
sequence :first_name do |n| "First #{n}" end
|
12
|
-
sequence :last_name do |n| "Last #{n}" end
|
13
|
-
end
|
14
8
|
end
|
data/spec/support/model/user.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-02-
|
12
|
+
date: 2018-02-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg_array_parser
|
@@ -198,7 +198,6 @@ files:
|
|
198
198
|
- spec/simple/sql_config_spec.rb
|
199
199
|
- spec/simple/sql_conversion_spec.rb
|
200
200
|
- spec/simple/sql_duplicate_spec.rb
|
201
|
-
- spec/simple/sql_duplicate_unique_spec.rb
|
202
201
|
- spec/simple/sql_insert_spec.rb
|
203
202
|
- spec/simple/sql_record_spec.rb
|
204
203
|
- spec/simple/sql_reflection_spec.rb
|
@@ -239,7 +238,6 @@ test_files:
|
|
239
238
|
- spec/simple/sql_config_spec.rb
|
240
239
|
- spec/simple/sql_conversion_spec.rb
|
241
240
|
- spec/simple/sql_duplicate_spec.rb
|
242
|
-
- spec/simple/sql_duplicate_unique_spec.rb
|
243
241
|
- spec/simple/sql_insert_spec.rb
|
244
242
|
- spec/simple/sql_record_spec.rb
|
245
243
|
- spec/simple/sql_reflection_spec.rb
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "Simple::SQL.duplicate/unique indices" do
|
4
|
-
let!(:unique_users) { 1.upto(USER_COUNT).map { create(:unique_user) } }
|
5
|
-
|
6
|
-
let!(:source_ids) { SQL.all("SELECT id FROM unique_users") }
|
7
|
-
|
8
|
-
it "cannot duplicate unique_user" do
|
9
|
-
expect {
|
10
|
-
SQL.duplicate "unique_users", source_ids
|
11
|
-
}.to raise_error(PG::UniqueViolation)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "raises an ArgumentError when called with unknown columns" do
|
15
|
-
expect {
|
16
|
-
SQL.duplicate "unique_users", source_ids, foo: SQL.fragment("baz")
|
17
|
-
}.to raise_error(ArgumentError)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "raises an ArgumentError when called with invalid overrides" do
|
21
|
-
expect {
|
22
|
-
SQL.duplicate "unique_users", source_ids, first_name: "I am invalid"
|
23
|
-
}.to raise_error(ArgumentError)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "duplicates unique_users" do
|
27
|
-
overrides = {
|
28
|
-
first_name: SQL.fragment("first_name || '.' || id"),
|
29
|
-
last_name: SQL.fragment("last_name || '.' || id")
|
30
|
-
}
|
31
|
-
|
32
|
-
dupe_ids = SQL.duplicate "unique_users", source_ids, overrides
|
33
|
-
|
34
|
-
expect(dupe_ids.length).to eq(2)
|
35
|
-
expect(SQL.ask("SELECT COUNT(*) FROM unique_users")).to eq(4)
|
36
|
-
end
|
37
|
-
end
|