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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b4a853f294d878decdf635afbfe2ef4029fe994ec710172038ec2a9ac664980
4
- data.tar.gz: 278a68ac45dda9070d30fd08d98ca9bb93ea6c8e5b378d7ebe7f085620797c77
3
+ metadata.gz: e88eaeeb85de88eed3c83b12481b9682a1de4327ee433098a46932866884c1d3
4
+ data.tar.gz: eac737d3b6281392099675b6d3bcd25d6493d836d66204fa7de229583c2a3be8
5
5
  SHA512:
6
- metadata.gz: ae6b7f73423e5001d80f0fc027fe0f2c557ac4961c1868e642087c50b8147bf2fca8b3431f8bec2603c33d762c533be57bb742d1ea5983481b4c3045ca348e73
7
- data.tar.gz: c6628d1b1ce3b9c2d0f6f553370f705f649d643c25ec1a524415fb5f3c871a9c93f80834698d6df8b82b04012917baaf3ada442bea585ddce3692bcc7af40870
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
- before_install: gem install bundler -v 1.16.2
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mini_sql (0.1.1)
4
+ mini_sql (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
@@ -1,6 +1,7 @@
1
1
  require_relative "mini_sql/version"
2
2
  require_relative "mini_sql/connection"
3
3
  require_relative "mini_sql/deserializer_cache"
4
+ require_relative "mini_sql/builder"
4
5
 
5
6
  module MiniSql
6
7
  autoload :Coders, "mini_sql/coders"
@@ -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
+
@@ -5,5 +5,10 @@ module MiniSql
5
5
  string.to_f
6
6
  end
7
7
  end
8
+ class IPAddrCoder < PG::SimpleDecoder
9
+ def decode(string, tuple = nil, field = nil)
10
+ IPAddr.new(string)
11
+ end
12
+ end
8
13
  end
9
14
  end
@@ -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
- params.each do |k, v|
61
- sql.gsub!(":#{k.to_s}", "$#{param_array.length + 1}")
62
- param_array << v
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]
@@ -1,3 +1,3 @@
1
1
  module MiniSql
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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.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-15 00:00:00.000000000 Z
11
+ date: 2018-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler