mini_sql 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|