mini_sql 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +32 -7
- data/bench/topic_perf.rb +63 -20
- data/lib/mini_sql/builder.rb +23 -24
- data/lib/mini_sql/connection.rb +2 -3
- data/lib/mini_sql/version.rb +1 -1
- metadata +2 -3
- data/Gemfile.lock +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fe7bfcf37c73b216a8532cd6b17957733213610c73924e241ba36619ae4ce04
|
4
|
+
data.tar.gz: 21e2f615add1039d3cd6363ce1bdea501dc2b9bc08d17565cb8b6378a508e04e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c8de4d35f5d332dd53925502b3d696782a90862b47e75b28e7402b85f7735c675c64ffd6027e419328396114dd9e1d8fcd62760ceda42e58576f52727da0411
|
7
|
+
data.tar.gz: 23e73177710c4ac500bf2a6d96de4c0b9d191526c9e68cd7fcd29d39a3fd686e39a59ade520bc35f60279b3daf78bd3365b1be06b33642f42ee932946734ed98
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -27,19 +27,40 @@ conn = MiniSql::Connection.new(pg_conn)
|
|
27
27
|
puts conn.exec('update table set column = 1 where id in (1,2)')
|
28
28
|
# returns 2 if 2 rows changed
|
29
29
|
|
30
|
-
conn.query("select 1 id, 'bob' name") do |user|
|
30
|
+
conn.query("select 1 id, 'bob' name").each do |user|
|
31
31
|
puts user.name # bob
|
32
32
|
puts user.id # 1
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
p conn.query_single('select 1 union select 2')
|
36
36
|
# [1,2]
|
37
37
|
|
38
|
+
p conn.query_hash('select 1 as a, 2 as b union select 3, 4')
|
39
|
+
# [{"a" => 1, "b"=> 1},{"a" => 3, "b" => 4}
|
40
|
+
```
|
41
|
+
|
42
|
+
## The query builder
|
43
|
+
|
44
|
+
You can use the simple query builder interface to compose queries.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
builder = conn.build("select * from topics /*where*/ /*limit*/")
|
48
|
+
|
49
|
+
if look_for_something
|
50
|
+
builder.where("title = :title", title: 'something')
|
51
|
+
end
|
52
|
+
|
53
|
+
builder.limit(20)
|
54
|
+
|
55
|
+
builder.query.each do |t|
|
56
|
+
puts t.id
|
57
|
+
puts t.title
|
58
|
+
end
|
38
59
|
```
|
39
60
|
|
40
61
|
## Is it fast?
|
41
62
|
|
42
|
-
Yes, it is very fast
|
63
|
+
Yes, it is very fast. See benchmarks in [the bench directory](https://github.com/discourse/mini_sql/tree/master/bench).
|
43
64
|
|
44
65
|
As a rule it will outperform similar naive PG code while remaining safe.
|
45
66
|
|
@@ -47,14 +68,18 @@ As a rule it will outperform similar naive PG code while remaining safe.
|
|
47
68
|
pg_conn = PG.connect(db_name: 'my_db')
|
48
69
|
|
49
70
|
# this is slower, and less safe
|
50
|
-
pg_conn.async_exec('select * from table')
|
71
|
+
result = pg_conn.async_exec('select * from table')
|
72
|
+
result.each do |r|
|
51
73
|
name = r['name']
|
52
74
|
end
|
75
|
+
# ideally you want to remember to run r.clear here
|
53
76
|
|
54
77
|
# this is faster and safer
|
55
78
|
conn = MiniSql::Connection.new(pg_conn)
|
56
|
-
conn.query('select * from table')
|
57
|
-
|
79
|
+
r = conn.query('select * from table')
|
80
|
+
|
81
|
+
r.each do |row|
|
82
|
+
name = row.name
|
58
83
|
end
|
59
84
|
```
|
60
85
|
|
@@ -79,4 +104,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
79
104
|
|
80
105
|
## Code of Conduct
|
81
106
|
|
82
|
-
Everyone interacting in the MiniSql project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
107
|
+
Everyone interacting in the MiniSql project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/discourse/mini_sql/blob/master/CODE_OF_CONDUCT.md).
|
data/bench/topic_perf.rb
CHANGED
@@ -168,7 +168,28 @@ def sequel_pluck_title_id
|
|
168
168
|
s
|
169
169
|
end
|
170
170
|
|
171
|
-
|
171
|
+
# usage is not really recommended but just to compare to pluck lets have it
|
172
|
+
def mini_sql_title_id_query_single
|
173
|
+
s = +""
|
174
|
+
i = 0
|
175
|
+
r = $mini_sql.query_single(-"select id, title from topics order by id limit 1000")
|
176
|
+
while i < r.length
|
177
|
+
s << r[i].to_s
|
178
|
+
s << r[i+1]
|
179
|
+
i += 2
|
180
|
+
end
|
181
|
+
s
|
182
|
+
end
|
183
|
+
|
184
|
+
results = [
|
185
|
+
ar_title_id,
|
186
|
+
ar_title_id_pluck,
|
187
|
+
pg_title_id,
|
188
|
+
mini_sql_title_id,
|
189
|
+
sequel_pluck_title_id,
|
190
|
+
sequel_select_title_id,
|
191
|
+
mini_sql_title_id_query_single
|
192
|
+
]
|
172
193
|
|
173
194
|
exit(-1) unless results.uniq.length == 1
|
174
195
|
|
@@ -241,12 +262,6 @@ Benchmark.ips do |r|
|
|
241
262
|
n -= 1
|
242
263
|
end
|
243
264
|
end
|
244
|
-
r.report("sequel title id pluck") do |n|
|
245
|
-
while n > 0
|
246
|
-
sequel_pluck_title_id
|
247
|
-
n -= 1
|
248
|
-
end
|
249
|
-
end
|
250
265
|
r.report("pg select title id") do |n|
|
251
266
|
while n > 0
|
252
267
|
pg_title_id
|
@@ -259,30 +274,58 @@ Benchmark.ips do |r|
|
|
259
274
|
n -= 1
|
260
275
|
end
|
261
276
|
end
|
277
|
+
r.report("sequel title id pluck") do |n|
|
278
|
+
while n > 0
|
279
|
+
sequel_pluck_title_id
|
280
|
+
n -= 1
|
281
|
+
end
|
282
|
+
end
|
283
|
+
r.report("mini_sql query_single title id") do |n|
|
284
|
+
while n > 0
|
285
|
+
mini_sql_title_id_query_single
|
286
|
+
n -= 1
|
287
|
+
end
|
288
|
+
end
|
262
289
|
r.compare!
|
263
290
|
end
|
264
291
|
|
265
292
|
|
266
293
|
# Calculating -------------------------------------
|
267
|
-
#
|
294
|
+
# wide topic ar 2.383k (± 4.9%) i/s - 12.005k in 5.050490s
|
295
|
+
# wide topic sequel 3.449k (± 3.2%) i/s - 17.591k in 5.104951s
|
296
|
+
# wide topic pg 7.345k (± 1.2%) i/s - 37.352k in 5.086015s
|
297
|
+
# wide topic mini sql 7.536k (± 1.4%) i/s - 38.220k in 5.072834s
|
298
|
+
#
|
299
|
+
# Comparison:
|
300
|
+
# wide topic mini sql: 7535.8 i/s
|
301
|
+
# wide topic pg: 7345.1 i/s - same-ish: difference falls within error
|
302
|
+
# wide topic sequel: 3449.4 i/s - 2.18x slower
|
303
|
+
# wide topic ar: 2382.9 i/s - 3.16x slower
|
304
|
+
#
|
305
|
+
# Calculating -------------------------------------
|
306
|
+
# ar select title id 131.572 (± 3.8%) i/s - 658.000 in 5.008231s
|
268
307
|
# ar select title id pluck
|
269
|
-
#
|
308
|
+
# 696.233 (± 3.7%) i/s - 3.519k in 5.061335s
|
270
309
|
# sequel title id select
|
271
|
-
#
|
272
|
-
#
|
273
|
-
# 1.183k (± 3.2%) i/s - 5.967k in 5.048635s
|
274
|
-
# pg select title id 1.040k (± 1.4%) i/s - 5.253k in 5.051679s
|
310
|
+
# 916.841 (± 3.7%) i/s - 4.655k in 5.084499s
|
311
|
+
# pg select title id 1.002k (± 4.0%) i/s - 5.044k in 5.040584s
|
275
312
|
# mini_sql select title id
|
276
|
-
# 1.
|
313
|
+
# 1.106k (± 2.4%) i/s - 5.618k in 5.084423s
|
314
|
+
# sequel title id pluck
|
315
|
+
# 1.181k (± 3.5%) i/s - 5.980k in 5.069815s
|
316
|
+
# mini_sql query_single title id
|
317
|
+
# 1.171k (± 3.1%) i/s - 5.880k in 5.025793s
|
277
318
|
#
|
278
319
|
# Comparison:
|
279
|
-
# sequel title id pluck:
|
280
|
-
# mini_sql
|
281
|
-
#
|
282
|
-
#
|
283
|
-
#
|
284
|
-
#
|
320
|
+
# sequel title id pluck: 1181.0 i/s
|
321
|
+
# mini_sql query_single title id: 1171.1 i/s - same-ish: difference falls within error
|
322
|
+
# mini_sql select title id: 1105.6 i/s - 1.07x slower
|
323
|
+
# pg select title id: 1002.2 i/s - 1.18x slower
|
324
|
+
# sequel title id select: 916.8 i/s - 1.29x slower
|
325
|
+
# ar select title id pluck: 696.2 i/s - 1.70x slower
|
326
|
+
# ar select title id: 131.6 i/s - 8.98x slower
|
285
327
|
#
|
328
|
+
|
286
329
|
# to run deep analysis run
|
287
330
|
# MemoryProfiler.report do
|
288
331
|
# ar
|
data/lib/mini_sql/builder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class MiniSql::Builder
|
2
4
|
|
3
5
|
def initialize(connection, template)
|
@@ -8,9 +10,13 @@ class MiniSql::Builder
|
|
8
10
|
end
|
9
11
|
|
10
12
|
[:set, :where2, :where, :order_by, :limit, :left_join, :join, :offset, :select].each do |k|
|
11
|
-
define_method k do |data, args
|
13
|
+
define_method k do |data, *args|
|
12
14
|
@args ||= {}
|
13
|
-
|
15
|
+
if Hash === args
|
16
|
+
@args.merge!(args)
|
17
|
+
elsif args && args.length > 0
|
18
|
+
data = @connection.param_encoder.encode(data, *args)
|
19
|
+
end
|
14
20
|
@sections[k] ||= []
|
15
21
|
@sections[k] << data
|
16
22
|
self
|
@@ -24,21 +30,21 @@ class MiniSql::Builder
|
|
24
30
|
joined = nil
|
25
31
|
case k
|
26
32
|
when :select
|
27
|
-
joined = "SELECT " << v.join(" , ")
|
33
|
+
joined = (+"SELECT ") << v.join(" , ")
|
28
34
|
when :where, :where2
|
29
|
-
joined = "WHERE " << v.map { |c| "(" << c << ")" }.join(" AND ")
|
35
|
+
joined = (+"WHERE ") << v.map { |c| (+"(") << c << ")" }.join(" AND ")
|
30
36
|
when :join
|
31
|
-
joined = v.map { |item| "JOIN " << item }.join("\n")
|
37
|
+
joined = v.map { |item| (+"JOIN ") << item }.join("\n")
|
32
38
|
when :left_join
|
33
|
-
joined = v.map { |item| "LEFT JOIN " << item }.join("\n")
|
39
|
+
joined = v.map { |item| (+"LEFT JOIN ") << item }.join("\n")
|
34
40
|
when :limit
|
35
|
-
joined = "LIMIT " << v.last.to_s
|
41
|
+
joined = (+"LIMIT ") << v.last.to_i.to_s
|
36
42
|
when :offset
|
37
|
-
joined = "OFFSET " << v.last.to_s
|
43
|
+
joined = (+"OFFSET ") << v.last.to_i.to_s
|
38
44
|
when :order_by
|
39
|
-
joined = "ORDER BY " << v.join(" , ")
|
45
|
+
joined = (+"ORDER BY ") << v.join(" , ")
|
40
46
|
when :set
|
41
|
-
joined = "SET " << v.join(" , ")
|
47
|
+
joined = (+"SET ") << v.join(" , ")
|
42
48
|
end
|
43
49
|
|
44
50
|
sql.sub!("/*#{k}*/", joined)
|
@@ -46,20 +52,13 @@ class MiniSql::Builder
|
|
46
52
|
sql
|
47
53
|
end
|
48
54
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
def exec(args = nil)
|
58
|
-
if args
|
59
|
-
@args.merge!(args)
|
60
|
-
end
|
61
|
-
sql = to_sql
|
62
|
-
@connection.exec(sql, @args)
|
55
|
+
[:query, :query_single, :query_hash, :exec].each do |m|
|
56
|
+
class_eval <<~RUBY
|
57
|
+
def #{m}(hash_args = nil)
|
58
|
+
hash_args = @args.merge(hash_args) if hash_args
|
59
|
+
@connection.#{m}(to_sql, hash_args || @args)
|
60
|
+
end
|
61
|
+
RUBY
|
63
62
|
end
|
64
63
|
|
65
64
|
end
|
data/lib/mini_sql/connection.rb
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
module MiniSql
|
4
4
|
class Connection
|
5
|
-
attr_reader :raw_connection
|
6
|
-
attr_reader :type_map
|
5
|
+
attr_reader :raw_connection, :type_map, :param_encoder
|
7
6
|
|
8
7
|
def self.default_deserializer_cache
|
9
8
|
@deserializer_cache ||= DeserializerCache.new
|
@@ -100,7 +99,7 @@ module MiniSql
|
|
100
99
|
|
101
100
|
def run(sql, params)
|
102
101
|
if params && params.length > 0
|
103
|
-
sql =
|
102
|
+
sql = param_encoder.encode(sql, *params)
|
104
103
|
end
|
105
104
|
raw_connection.async_exec(sql)
|
106
105
|
end
|
data/lib/mini_sql/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -119,7 +119,6 @@ files:
|
|
119
119
|
- ".travis.yml"
|
120
120
|
- CODE_OF_CONDUCT.md
|
121
121
|
- Gemfile
|
122
|
-
- Gemfile.lock
|
123
122
|
- Guardfile
|
124
123
|
- LICENSE.txt
|
125
124
|
- README.md
|
data/Gemfile.lock
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
mini_sql (0.1.5)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
activesupport (5.2.0)
|
10
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
|
-
i18n (>= 0.7, < 2)
|
12
|
-
minitest (~> 5.1)
|
13
|
-
tzinfo (~> 1.1)
|
14
|
-
coderay (1.1.2)
|
15
|
-
concurrent-ruby (1.0.5)
|
16
|
-
ffi (1.9.25)
|
17
|
-
formatador (0.2.5)
|
18
|
-
guard (2.14.2)
|
19
|
-
formatador (>= 0.2.4)
|
20
|
-
listen (>= 2.7, < 4.0)
|
21
|
-
lumberjack (>= 1.0.12, < 2.0)
|
22
|
-
nenv (~> 0.1)
|
23
|
-
notiffany (~> 0.0)
|
24
|
-
pry (>= 0.9.12)
|
25
|
-
shellany (~> 0.0)
|
26
|
-
thor (>= 0.18.1)
|
27
|
-
guard-compat (1.2.1)
|
28
|
-
guard-minitest (2.4.6)
|
29
|
-
guard-compat (~> 1.2)
|
30
|
-
minitest (>= 3.0)
|
31
|
-
i18n (1.0.1)
|
32
|
-
concurrent-ruby (~> 1.0)
|
33
|
-
listen (3.1.5)
|
34
|
-
rb-fsevent (~> 0.9, >= 0.9.4)
|
35
|
-
rb-inotify (~> 0.9, >= 0.9.7)
|
36
|
-
ruby_dep (~> 1.2)
|
37
|
-
lumberjack (1.0.13)
|
38
|
-
method_source (0.9.0)
|
39
|
-
minitest (5.11.3)
|
40
|
-
nenv (0.3.0)
|
41
|
-
notiffany (0.1.1)
|
42
|
-
nenv (~> 0.1)
|
43
|
-
shellany (~> 0.0)
|
44
|
-
pg (1.0.0)
|
45
|
-
pry (0.11.3)
|
46
|
-
coderay (~> 1.1.0)
|
47
|
-
method_source (~> 0.9.0)
|
48
|
-
rake (10.5.0)
|
49
|
-
rb-fsevent (0.10.3)
|
50
|
-
rb-inotify (0.9.10)
|
51
|
-
ffi (>= 0.5.0, < 2)
|
52
|
-
ruby_dep (1.5.0)
|
53
|
-
shellany (0.0.1)
|
54
|
-
thor (0.20.0)
|
55
|
-
thread_safe (0.3.6)
|
56
|
-
tzinfo (1.2.5)
|
57
|
-
thread_safe (~> 0.1)
|
58
|
-
|
59
|
-
PLATFORMS
|
60
|
-
ruby
|
61
|
-
|
62
|
-
DEPENDENCIES
|
63
|
-
activesupport (~> 5.2)
|
64
|
-
bundler (~> 1.16)
|
65
|
-
guard (~> 2.14)
|
66
|
-
guard-minitest (~> 2.4)
|
67
|
-
mini_sql!
|
68
|
-
minitest (~> 5.0)
|
69
|
-
pg (~> 1.0.0)
|
70
|
-
rake (~> 10.0)
|
71
|
-
|
72
|
-
BUNDLED WITH
|
73
|
-
1.16.2
|