simple-sql 0.5.27 → 0.5.32
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/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/Makefile +3 -3
- data/VERSION +1 -1
- data/config/database.yml +2 -1
- data/lib/simple/sql.rb +1 -0
- data/lib/simple/sql/connection/scope.rb +1 -0
- data/lib/simple/sql/connection/scope/order.rb +16 -2
- data/lib/simple/sql/connection/scope/pagination.rb +4 -2
- data/lib/simple/sql/helpers/encoder.rb +19 -3
- data/lib/simple/sql/helpers/immutable.rb +4 -146
- data/lib/simple/sql/helpers/row_converter.rb +2 -1
- data/lib/simple/sql/monkey_patches.rb +49 -0
- data/lib/simple/sql/version.rb +1 -0
- data/simple-sql.gemspec +1 -0
- data/spec/simple/sql/conversion_spec.rb +10 -7
- data/spec/simple/sql/each_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/001_database.rb +4 -0
- metadata +22 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb4af8eb0802b84e83370417d134ff18f82c812dbd9a053853739d9570f92a95
|
4
|
+
data.tar.gz: 0b023420320187d12f32cb6e1a4a093775a5bd2849015443768b0177392729fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 996461571d090b5cf7589dfc6f1d12925b11b54d047fc2ec2395bbb6a2d75e583a7f82d0cc92985982891d3254e3e26a83260f6a38be5bee0eac5872effb4609
|
7
|
+
data.tar.gz: 57decbf1a834422bdfc2987056c3fa37f04988de7059ed8c6eb8aa64ffc16c445a19f1dc9e91f880eac8a2ea7e8772dcfb8b1aeaf43b57ca7f13d4662ceaf177
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7
|
data/Gemfile
CHANGED
data/Makefile
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
tests: test4 test5 test6
|
2
2
|
|
3
3
|
test4:
|
4
|
-
SIMPLE_SQL_ACTIVERECORD_SPECS="
|
4
|
+
SIMPLE_SQL_ACTIVERECORD_SPECS="> 4,< 5" bundle
|
5
5
|
rspec
|
6
6
|
|
7
7
|
test5:
|
8
|
-
SIMPLE_SQL_ACTIVERECORD_SPECS="
|
8
|
+
SIMPLE_SQL_ACTIVERECORD_SPECS="> 5,< 6" bundle update activerecord
|
9
9
|
rspec
|
10
10
|
|
11
11
|
test6:
|
12
|
-
SIMPLE_SQL_ACTIVERECORD_SPECS="
|
12
|
+
SIMPLE_SQL_ACTIVERECORD_SPECS="> 6,< 7" bundle update activerecord
|
13
13
|
rspec
|
14
14
|
|
15
15
|
stats:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.32
|
data/config/database.yml
CHANGED
data/lib/simple/sql.rb
CHANGED
@@ -84,6 +84,7 @@ class Simple::SQL::Connection::Scope
|
|
84
84
|
dupe.instance_variable_set :@page, @page
|
85
85
|
dupe.instance_variable_set :@order_by_fragment, @order_by_fragment
|
86
86
|
dupe.instance_variable_set :@limit, @limit
|
87
|
+
dupe.instance_variable_set :@offset, @offset
|
87
88
|
dupe
|
88
89
|
end
|
89
90
|
|
@@ -3,8 +3,16 @@ class Simple::SQL::Connection::Scope
|
|
3
3
|
duplicate.send(:order_by!, sql_fragment)
|
4
4
|
end
|
5
5
|
|
6
|
-
def limit(
|
7
|
-
|
6
|
+
def limit(limit)
|
7
|
+
raise ArgumentError, "limit must be >= 0" unless limit >= 0
|
8
|
+
|
9
|
+
duplicate.send(:limit!, limit)
|
10
|
+
end
|
11
|
+
|
12
|
+
def offset(offset)
|
13
|
+
raise ArgumentError, "offset must be >= 0" unless offset >= 0
|
14
|
+
|
15
|
+
duplicate.send(:offset!, offset)
|
8
16
|
end
|
9
17
|
|
10
18
|
private
|
@@ -21,10 +29,16 @@ class Simple::SQL::Connection::Scope
|
|
21
29
|
self
|
22
30
|
end
|
23
31
|
|
32
|
+
def offset!(offset)
|
33
|
+
@offset = offset
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
24
37
|
# called from to_sql
|
25
38
|
def apply_order_and_limit(sql)
|
26
39
|
sql = "#{sql} ORDER BY #{@order_by_fragment}" if @order_by_fragment
|
27
40
|
sql = "#{sql} LIMIT #{@limit}" if @limit
|
41
|
+
sql = "#{sql} OFFSET #{@offset}" if @offset
|
28
42
|
|
29
43
|
sql
|
30
44
|
end
|
@@ -3,6 +3,9 @@
|
|
3
3
|
class Simple::SQL::Connection::Scope
|
4
4
|
# Set pagination
|
5
5
|
def paginate(per:, page:)
|
6
|
+
raise ArgumentError, "per must be > 0" unless per > 0
|
7
|
+
raise ArgumentError, "page must be > 0" unless page > 0
|
8
|
+
|
6
9
|
duplicate.send(:paginate!, per: per, page: page)
|
7
10
|
end
|
8
11
|
|
@@ -23,8 +26,7 @@ class Simple::SQL::Connection::Scope
|
|
23
26
|
def apply_pagination(sql, pagination:)
|
24
27
|
return sql unless pagination == :auto && @per && @page
|
25
28
|
|
26
|
-
raise ArgumentError, "
|
27
|
-
raise ArgumentError, "page must be > 0" unless @page > 0
|
29
|
+
raise ArgumentError, "You cannot mix 'paginate' and 'offset'/'limit'" if @offset || @limit
|
28
30
|
|
29
31
|
"#{sql} LIMIT #{@per} OFFSET #{(@page - 1) * @per}"
|
30
32
|
end
|
@@ -8,11 +8,27 @@ module Simple::SQL::Helpers::Encoder
|
|
8
8
|
|
9
9
|
def encode_arg(connection, arg)
|
10
10
|
return arg unless arg.is_a?(Array)
|
11
|
+
return "{}" if arg.empty?
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
encoded_ary = encode_array(connection, arg)
|
14
|
+
"{" + encoded_ary.join(",") + "}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def encode_array(connection, ary)
|
18
|
+
case ary.first
|
19
|
+
when String
|
20
|
+
ary.map do |str|
|
21
|
+
str = connection.escape(str)
|
22
|
+
|
23
|
+
# These fixes have been discovered during tests. see spec/simple/sql/conversion_spec.rb
|
24
|
+
str = str.gsub("\"", "\\\"")
|
25
|
+
str = str.gsub("''", "'")
|
26
|
+
"\"#{str}\""
|
27
|
+
end
|
28
|
+
when Integer
|
29
|
+
ary
|
14
30
|
else
|
15
|
-
"
|
31
|
+
raise ArgumentError, "Don't know how to encode array of #{ary.first.class}"
|
16
32
|
end
|
17
33
|
end
|
18
34
|
end
|
@@ -1,152 +1,10 @@
|
|
1
|
+
require "simple-immutable"
|
2
|
+
|
1
3
|
module Simple
|
2
4
|
module SQL
|
3
5
|
module Helpers
|
6
|
+
# for backwards compatibility
|
7
|
+
Immutable = ::Simple::Immutable
|
4
8
|
end
|
5
9
|
end
|
6
10
|
end
|
7
|
-
|
8
|
-
class Simple::SQL::Helpers::Immutable
|
9
|
-
SELF = self
|
10
|
-
|
11
|
-
# turns an object, which can be a hash or array of hashes, arrays, and scalars
|
12
|
-
# into an object which you can use to access with dot methods.
|
13
|
-
def self.create(object, max_depth = 5)
|
14
|
-
case object
|
15
|
-
when Array
|
16
|
-
raise ArgumentError, "Object nested too deep (or inner loop?)" if max_depth < 0
|
17
|
-
|
18
|
-
object.map { |obj| create obj, max_depth - 1 }
|
19
|
-
when Hash
|
20
|
-
new(object)
|
21
|
-
else
|
22
|
-
object
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def initialize(hsh)
|
29
|
-
@hsh = hsh
|
30
|
-
end
|
31
|
-
|
32
|
-
def method_missing(sym, *args, &block)
|
33
|
-
if args.empty? && !block
|
34
|
-
begin
|
35
|
-
value = @hsh.fetch(sym.to_sym) { @hsh.fetch(sym.to_s) }
|
36
|
-
return SELF.create(value)
|
37
|
-
rescue KeyError
|
38
|
-
# STDERR.puts "Missing attribute #{sym} for Immutable w/#{@hsh.inspect}"
|
39
|
-
nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
super
|
44
|
-
end
|
45
|
-
|
46
|
-
public
|
47
|
-
|
48
|
-
def respond_to_missing?(method_name, include_private = false)
|
49
|
-
@hsh.key?(method_name.to_sym) ||
|
50
|
-
@hsh.key?(method_name.to_s) ||
|
51
|
-
super
|
52
|
-
end
|
53
|
-
|
54
|
-
def inspect
|
55
|
-
"<Immutable: #{@hsh.inspect}>"
|
56
|
-
end
|
57
|
-
|
58
|
-
def respond_to?(sym)
|
59
|
-
super || @hsh.key?(sym.to_s) || @hsh.key?(sym.to_sym)
|
60
|
-
end
|
61
|
-
|
62
|
-
def ==(other)
|
63
|
-
@hsh == other
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
if $PROGRAM_NAME == __FILE__
|
68
|
-
|
69
|
-
# rubocop:disable Metrics/AbcSize
|
70
|
-
|
71
|
-
require "test-unit"
|
72
|
-
|
73
|
-
class Simple::SQL::Helpers::Immutable::TestCase < Test::Unit::TestCase
|
74
|
-
Immutable = ::Simple::SQL::Helpers::Immutable
|
75
|
-
|
76
|
-
def hsh
|
77
|
-
{
|
78
|
-
a: "a-value",
|
79
|
-
"b": "b-value",
|
80
|
-
"child": {
|
81
|
-
name: "childname",
|
82
|
-
grandchild: {
|
83
|
-
name: "grandchildname"
|
84
|
-
}
|
85
|
-
},
|
86
|
-
"children": [
|
87
|
-
"anna",
|
88
|
-
"arthur",
|
89
|
-
{
|
90
|
-
action: {
|
91
|
-
keep_your_mouth_shut: true
|
92
|
-
}
|
93
|
-
}
|
94
|
-
]
|
95
|
-
}
|
96
|
-
end
|
97
|
-
|
98
|
-
def immutable
|
99
|
-
Immutable.create hsh
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_hash_access
|
103
|
-
assert_equal "a-value", immutable.a
|
104
|
-
assert_equal "b-value", immutable.b
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_comparison
|
108
|
-
immutable = Immutable.create hsh
|
109
|
-
|
110
|
-
assert_equal immutable, hsh
|
111
|
-
assert_not_equal({}, immutable)
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_child_access
|
115
|
-
child = immutable.child
|
116
|
-
assert_kind_of(Immutable, child)
|
117
|
-
assert_equal "childname", immutable.child.name
|
118
|
-
assert_equal "grandchildname", immutable.child.grandchild.name
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_array_access
|
122
|
-
assert_kind_of(Array, immutable.children)
|
123
|
-
assert_equal 3, immutable.children.length
|
124
|
-
assert_equal "anna", immutable.children[0]
|
125
|
-
|
126
|
-
assert_kind_of(Immutable, immutable.children[2])
|
127
|
-
assert_equal true, immutable.children[2].action.keep_your_mouth_shut
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_base_class
|
131
|
-
assert_nothing_raised do
|
132
|
-
immutable.object_id
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def test_missing_keys
|
137
|
-
assert_raise(NoMethodError) do
|
138
|
-
immutable.foo
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_skip_when_args_or_block
|
143
|
-
assert_raise(NoMethodError) do
|
144
|
-
immutable.a(1, 2, 3)
|
145
|
-
end
|
146
|
-
assert_raise(NoMethodError) do
|
147
|
-
immutable.a { :dummy }
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative "./immutable"
|
2
|
+
require "simple/immutable"
|
2
3
|
|
3
4
|
module Simple::SQL::Helpers::RowConverter
|
4
5
|
SELF = self
|
@@ -57,7 +58,7 @@ module Simple::SQL::Helpers::RowConverter
|
|
57
58
|
end
|
58
59
|
|
59
60
|
class ImmutableConverter < TypeConverter #:nodoc:
|
60
|
-
Immutable = ::Simple::
|
61
|
+
Immutable = ::Simple::Immutable
|
61
62
|
|
62
63
|
def build_row_in_target_type(hsh)
|
63
64
|
Immutable.create hsh
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# This file contains some monkey patches
|
2
|
+
|
3
|
+
module Simple::SQL::MonkeyPatches
|
4
|
+
def self.warn(msg)
|
5
|
+
@@warned ||= {}
|
6
|
+
return if @@warned[msg]
|
7
|
+
|
8
|
+
@@warned[msg] = true
|
9
|
+
|
10
|
+
STDERR.puts "== monkeypatch warning: #{msg}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
case ActiveRecord.gem_version.to_s
|
15
|
+
when /^4/
|
16
|
+
:nop
|
17
|
+
when /^5.2/
|
18
|
+
unless defined?(ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper)
|
19
|
+
raise "Make sure to properly require active-record first"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Rails5 introduced a Reaper which starts a Thread which checks for unused connections. However,
|
23
|
+
# these threads are never cleaned up. This monkey patch disables the creation of those threads
|
24
|
+
# in the first place, consequently preventing leakage of threads.
|
25
|
+
#
|
26
|
+
# see see https://github.com/rails/rails/issues/33600 and related commits and issues.
|
27
|
+
class ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper
|
28
|
+
def run
|
29
|
+
return unless frequency && frequency > 0
|
30
|
+
Simple::SQL::MonkeyPatches.warn "simple-sql disables reapers for all connection pools, see https://github.com/rails/rails/issues/33600"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
when /^6/
|
35
|
+
unless defined?(ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper)
|
36
|
+
raise "Make sure to properly require active-record first"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Rails6 fixes the issue w/reapers leaking threads; by properly cleaning up these threads
|
40
|
+
# (or so one hopes after looking at connection_pool.rb). However, in the interest of simple-sql
|
41
|
+
# being more or less ActiveRecord agnostic we disable reaping here as well. (Also, that code
|
42
|
+
# looks pretty complex to me).
|
43
|
+
class ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper
|
44
|
+
def run
|
45
|
+
return unless frequency && frequency > 0
|
46
|
+
Simple::SQL::MonkeyPatches.warn "simple-sql disables reapers for all connection pools, see https://github.com/rails/rails/issues/33600"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/simple/sql/version.rb
CHANGED
data/simple-sql.gemspec
CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_dependency 'expectation', '~> 1'
|
29
29
|
|
30
30
|
gem.add_dependency 'digest-crc', '~> 0'
|
31
|
+
gem.add_dependency 'simple-immutable', '~> 1.0'
|
31
32
|
|
32
33
|
# during tests we check the SIMPLE_SQL_ACTIVERECORD_SPECS environment setting.
|
33
34
|
# Run make tests to run all tests
|
@@ -23,6 +23,7 @@ describe "Simple::SQL conversions" do
|
|
23
23
|
expects "foo,\"bar}", "SELECT $1::varchar", "foo,\"bar}"
|
24
24
|
expects ["one", "two", "3.5", "foo,\"bar}"], "SELECT ARRAY['one', 'two', '3.5', 'foo,\"bar}']"
|
25
25
|
expects ["foo", "foo,bar}"], "SELECT $1::varchar[]", ["foo", "foo,bar}"]
|
26
|
+
expects "foo'bar", 'SELECT $1', "foo'bar"
|
26
27
|
end
|
27
28
|
|
28
29
|
it "parses JSON as expected" do
|
@@ -42,13 +43,15 @@ describe "Simple::SQL conversions" do
|
|
42
43
|
it "converts hstore" do
|
43
44
|
expects({ a: "1", b: "3" }, "SELECT 'a=>1,b=>3'::hstore")
|
44
45
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "arra conversions" do
|
49
|
+
it "works with strings" do
|
50
|
+
expects [ "foo", "bar" ], 'SELECT $1::varchar[]', [ "foo", "bar" ]
|
51
|
+
|
52
|
+
# test escaping
|
53
|
+
expects [ "foo", "foo'bar\"baz" ], 'SELECT $1::varchar[]', [ "foo", "foo'bar\"baz" ]
|
54
|
+
expects [ ], 'SELECT $1::varchar[]', []
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
@@ -61,7 +61,7 @@ describe "Simple::SQL.each" do
|
|
61
61
|
|
62
62
|
expect(received.first.id).to eq(1)
|
63
63
|
expect(received[1].dupe).to eq(2)
|
64
|
-
expect(received.map(&:class).uniq).to eq([Simple::
|
64
|
+
expect(received.map(&:class).uniq).to eq([Simple::Immutable])
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# connect to the database and setup the schema
|
2
2
|
require "active_record"
|
3
|
+
|
4
|
+
# it is important to require simple-sql here to activate monkey patches
|
5
|
+
require "simple-sql"
|
6
|
+
|
3
7
|
require "yaml"
|
4
8
|
abc = YAML.load_file("config/database.yml")
|
5
9
|
ActiveRecord::Base.establish_connection(abc["test"])
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.32
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
8
8
|
- mediapeers GmbH
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg_array_parser
|
@@ -73,6 +73,20 @@ dependencies:
|
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: simple-immutable
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
76
90
|
- !ruby/object:Gem::Dependency
|
77
91
|
name: activerecord
|
78
92
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,6 +185,7 @@ extra_rdoc_files: []
|
|
171
185
|
files:
|
172
186
|
- ".gitignore"
|
173
187
|
- ".rubocop.yml"
|
188
|
+
- ".ruby-version"
|
174
189
|
- ".tm_properties"
|
175
190
|
- Gemfile
|
176
191
|
- Makefile
|
@@ -212,6 +227,7 @@ files:
|
|
212
227
|
- lib/simple/sql/helpers/immutable.rb
|
213
228
|
- lib/simple/sql/helpers/row_converter.rb
|
214
229
|
- lib/simple/sql/logging.rb
|
230
|
+
- lib/simple/sql/monkey_patches.rb
|
215
231
|
- lib/simple/sql/result.rb
|
216
232
|
- lib/simple/sql/result/association_loader.rb
|
217
233
|
- lib/simple/sql/result/records.rb
|
@@ -256,7 +272,7 @@ files:
|
|
256
272
|
homepage: http://github.com/radiospiel/simple-sql
|
257
273
|
licenses: []
|
258
274
|
metadata: {}
|
259
|
-
post_install_message:
|
275
|
+
post_install_message:
|
260
276
|
rdoc_options: []
|
261
277
|
require_paths:
|
262
278
|
- lib
|
@@ -271,8 +287,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
271
287
|
- !ruby/object:Gem::Version
|
272
288
|
version: '0'
|
273
289
|
requirements: []
|
274
|
-
rubygems_version: 3.
|
275
|
-
signing_key:
|
290
|
+
rubygems_version: 3.1.4
|
291
|
+
signing_key:
|
276
292
|
specification_version: 4
|
277
293
|
summary: SQL with a simple interface
|
278
294
|
test_files:
|