mini_sql 0.1.1 → 0.1.2
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/.travis.yml +18 -2
- data/Gemfile.lock +1 -1
- data/README.md +28 -0
- data/bench/topic_perf.rb +51 -1
- data/lib/mini_sql.rb +1 -0
- data/lib/mini_sql/builder.rb +65 -0
- data/lib/mini_sql/coders.rb +5 -0
- data/lib/mini_sql/connection.rb +24 -4
- data/lib/mini_sql/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e88eaeeb85de88eed3c83b12481b9682a1de4327ee433098a46932866884c1d3
|
4
|
+
data.tar.gz: eac737d3b6281392099675b6d3bcd25d6493d836d66204fa7de229583c2a3be8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 166faf87640bb2a07fe7d2f4e146274f7229f8c56f61e4160c1296a7f5d9587a5e11be09168abd792807f3bc5a08cec21b835e2ae81dc978c175bec6e155d607
|
7
|
+
data.tar.gz: d43a73fa9abb29de17005b4e361c607509c7a34a82b88e07ad2a344820c3c1efe7bfced0358310c2286d1bf9cc63977c2159c8bbdc3df6233d028a3ca45dadec
|
data/.travis.yml
CHANGED
@@ -1,5 +1,21 @@
|
|
1
|
-
sudo: false
|
2
1
|
language: ruby
|
3
2
|
rvm:
|
4
3
|
- 2.5.1
|
5
|
-
|
4
|
+
- ruby-head
|
5
|
+
|
6
|
+
before_install:
|
7
|
+
- gem install bundler
|
8
|
+
|
9
|
+
cache: bundler
|
10
|
+
sudo: false
|
11
|
+
|
12
|
+
addons:
|
13
|
+
postgresql: 9.6
|
14
|
+
|
15
|
+
install:
|
16
|
+
- createdb test_mini_sql
|
17
|
+
- bundle install
|
18
|
+
|
19
|
+
matrix:
|
20
|
+
allow_failures:
|
21
|
+
- rvm: ruby-head
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -37,6 +37,34 @@ puts conn.query_single('select 1 union select 2')
|
|
37
37
|
|
38
38
|
```
|
39
39
|
|
40
|
+
## Is it fast?
|
41
|
+
|
42
|
+
Yes, it is very fast, see benchmarks [the bench directory](https://github.com/discourse/mini_sql/tree/master/bench)
|
43
|
+
|
44
|
+
As a rule it will outperform similar naive PG code while remaining safe.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
pg_conn = PG.connect(db_name: 'my_db')
|
48
|
+
|
49
|
+
# this is slower, and less safe
|
50
|
+
pg_conn.async_exec('select * from table') do |r|
|
51
|
+
name = r['name']
|
52
|
+
end
|
53
|
+
|
54
|
+
# this is faster and safer
|
55
|
+
conn = MiniSql::Connection.new(pg_conn)
|
56
|
+
conn.query('select * from table') do |r|
|
57
|
+
name = r.name
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
## Safety
|
62
|
+
|
63
|
+
In current version of the PG gem you should be careful to clear results. If you do not you risk memory bloat.
|
64
|
+
See: [Sam's blog post](https://samsaffron.com/archive/2018/06/13/ruby-x27-s-external-malloc-problem).
|
65
|
+
|
66
|
+
MiniSql is careful to always clear results as soon as possible.
|
67
|
+
|
40
68
|
## Development
|
41
69
|
|
42
70
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
data/bench/topic_perf.rb
CHANGED
@@ -34,7 +34,7 @@ SQL
|
|
34
34
|
|
35
35
|
pg.async_exec <<SQL
|
36
36
|
CREATE TABLE topics (
|
37
|
-
id integer NOT NULL,
|
37
|
+
id integer NOT NULL PRIMARY KEY,
|
38
38
|
title character varying NOT NULL,
|
39
39
|
last_posted_at timestamp without time zone,
|
40
40
|
created_at timestamp without time zone NOT NULL,
|
@@ -172,6 +172,56 @@ results = [ar_title_id, ar_title_id_pluck, pg_title_id, mini_sql_title_id, seque
|
|
172
172
|
|
173
173
|
exit(-1) unless results.uniq.length == 1
|
174
174
|
|
175
|
+
|
176
|
+
def wide_topic_ar
|
177
|
+
Topic.first
|
178
|
+
end
|
179
|
+
|
180
|
+
def wide_topic_pg
|
181
|
+
r = $conn.async_exec("select * from topics limit 1")
|
182
|
+
row = r.first
|
183
|
+
r.clear
|
184
|
+
row
|
185
|
+
end
|
186
|
+
|
187
|
+
def wide_topic_sequel
|
188
|
+
TopicSequel.first
|
189
|
+
end
|
190
|
+
|
191
|
+
def wide_topic_mini_sql
|
192
|
+
$conn.query("select * from topics limit 1").first
|
193
|
+
end
|
194
|
+
|
195
|
+
Benchmark.ips do |r|
|
196
|
+
r.report("wide topic ar") do |n|
|
197
|
+
while n > 0
|
198
|
+
wide_topic_ar
|
199
|
+
n -= 1
|
200
|
+
end
|
201
|
+
end
|
202
|
+
r.report("wide topic sequel") do |n|
|
203
|
+
while n > 0
|
204
|
+
wide_topic_sequel
|
205
|
+
n -= 1
|
206
|
+
end
|
207
|
+
end
|
208
|
+
r.report("wide topic pg") do |n|
|
209
|
+
while n > 0
|
210
|
+
wide_topic_pg
|
211
|
+
n -= 1
|
212
|
+
end
|
213
|
+
end
|
214
|
+
r.report("wide topic mini sql") do |n|
|
215
|
+
while n > 0
|
216
|
+
wide_topic_mini_sql
|
217
|
+
n -= 1
|
218
|
+
end
|
219
|
+
end
|
220
|
+
r.compare!
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
|
175
225
|
Benchmark.ips do |r|
|
176
226
|
r.report("ar select title id") do |n|
|
177
227
|
while n > 0
|
data/lib/mini_sql.rb
CHANGED
data/lib/mini_sql/builder.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
class MiniSql::Builder
|
2
|
+
|
3
|
+
def initialize(connection, template)
|
4
|
+
@args = {}
|
5
|
+
@sql = template
|
6
|
+
@sections = {}
|
7
|
+
@connection = connection
|
8
|
+
end
|
9
|
+
|
10
|
+
[:set, :where2, :where, :order_by, :limit, :left_join, :join, :offset, :select].each do |k|
|
11
|
+
define_method k do |data, args = {}|
|
12
|
+
@args.merge!(args)
|
13
|
+
@sections[k] ||= []
|
14
|
+
@sections[k] << data
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_sql
|
20
|
+
sql = @sql.dup
|
21
|
+
|
22
|
+
@sections.each do |k, v|
|
23
|
+
joined = nil
|
24
|
+
case k
|
25
|
+
when :select
|
26
|
+
joined = "SELECT " << v.join(" , ")
|
27
|
+
when :where, :where2
|
28
|
+
joined = "WHERE " << v.map { |c| "(" << c << ")" }.join(" AND ")
|
29
|
+
when :join
|
30
|
+
joined = v.map { |item| "JOIN " << item }.join("\n")
|
31
|
+
when :left_join
|
32
|
+
joined = v.map { |item| "LEFT JOIN " << item }.join("\n")
|
33
|
+
when :limit
|
34
|
+
joined = "LIMIT " << v.last.to_s
|
35
|
+
when :offset
|
36
|
+
joined = "OFFSET " << v.last.to_s
|
37
|
+
when :order_by
|
38
|
+
joined = "ORDER BY " << v.join(" , ")
|
39
|
+
when :set
|
40
|
+
joined = "SET " << v.join(" , ")
|
41
|
+
end
|
42
|
+
|
43
|
+
sql.sub!("/*#{k}*/", joined)
|
44
|
+
end
|
45
|
+
sql
|
46
|
+
end
|
47
|
+
|
48
|
+
def query(args = nil)
|
49
|
+
if args
|
50
|
+
@args.merge!(args)
|
51
|
+
end
|
52
|
+
sql = to_sql
|
53
|
+
@connection.query(sql, args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def exec(args = nil)
|
57
|
+
if args
|
58
|
+
@args.merge!(args)
|
59
|
+
end
|
60
|
+
sql = to_sql
|
61
|
+
@connection.query(sql, args)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
data/lib/mini_sql/coders.rb
CHANGED
data/lib/mini_sql/connection.rb
CHANGED
@@ -10,6 +10,7 @@ module MiniSql
|
|
10
10
|
begin
|
11
11
|
map = PG::BasicTypeMapForResults.new(conn)
|
12
12
|
map.add_coder(MiniSql::Coders::NumericCoder.new(name: "numeric", oid: 1700, format: 0))
|
13
|
+
map.add_coder(MiniSql::Coders::IPAddrCoder.new(name: "inet", oid: 869, format: 0))
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -43,6 +44,10 @@ module MiniSql
|
|
43
44
|
result.clear if result
|
44
45
|
end
|
45
46
|
|
47
|
+
def build(sql)
|
48
|
+
Builder.new(self, sql)
|
49
|
+
end
|
50
|
+
|
46
51
|
private
|
47
52
|
|
48
53
|
def run(sql, params)
|
@@ -55,11 +60,26 @@ module MiniSql
|
|
55
60
|
|
56
61
|
def process_params(sql, params)
|
57
62
|
sql = sql.dup
|
58
|
-
param_array =
|
63
|
+
param_array = nil
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
if Hash === params
|
66
|
+
param_array = []
|
67
|
+
params.each do |k, v|
|
68
|
+
sql.gsub!(":#{k.to_s}", "$#{param_array.length + 1}")
|
69
|
+
param_array << v
|
70
|
+
end
|
71
|
+
elsif Array === params
|
72
|
+
i = 0
|
73
|
+
sql.gsub!("?") do
|
74
|
+
i += 1
|
75
|
+
case params[i-1]
|
76
|
+
when Integer then "$#{i}::bigint"
|
77
|
+
when Float then "$#{i}::float8"
|
78
|
+
when String then "$#{i}::text"
|
79
|
+
else "$#{i}::unknown"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
param_array = params
|
63
83
|
end
|
64
84
|
|
65
85
|
[sql, param_array]
|
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.2
|
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-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|