github-ds 0.2.7 → 0.2.8

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
  SHA1:
3
- metadata.gz: b7df77cb6809937119fa2de6b8c56fc949df2562
4
- data.tar.gz: 315a6384a50871cc13fc1b3b275eac7e243d3786
3
+ metadata.gz: e72707c0bbfc8fcf2e846d4e16e6735b8b457728
4
+ data.tar.gz: 11e5d2059aafe9dc81e7cd343c0a1b7218ca23e6
5
5
  SHA512:
6
- metadata.gz: 6505957502604a32bc5c37e9d45b6002ba824c2085f1d26b85937b4e32f15d9a90464763ab88c64fc96b5c7b54f54578d60c8f16b9b7428af005936872fa5493
7
- data.tar.gz: 68168285e35c21a1fb101ca89c4ca9cd00d3bb2e2bef4fc3c62b9ccc260282ff370e2be1ba918059830a921dca2fe554cee9c197ebd4835cf2470a069b7c5a08
6
+ metadata.gz: a9f34c95c26ee3edd98d27acefa2d1ea8ca6c1197c36f1616c0dbc387e2f76c4a16c497024565a85de00138031ec8955ab40bd61c6545e3a6ef0e28f4ef1bfbe
7
+ data.tar.gz: 38586c9b89eaefa299d45e94ed9beb03cbc21b230c301aada2db21aeab27ff8a851cce41ddfc7f7cec0cfd56193e66a1ff62588f57d930ef3089cecbf3c2634f
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.8
4
+
5
+ Fixes
6
+
7
+ * GitHub::SQL.transaction now takes options and passes them to ActiveRecord::Base.transaction.
8
+ * Moved default time zone enforcement to sanitize from add. Makes it possible to use interpolate or sanitize and have correct time zone enforcement.
9
+
10
+ Additions
11
+
12
+ * Added GitHub::SQL#transaction instance method to match the class level one.
13
+
3
14
  ## 0.2.7
4
15
 
5
16
  Fixes
@@ -1,5 +1,5 @@
1
1
  module GitHub
2
2
  module DS
3
- VERSION = "0.2.7"
3
+ VERSION = "0.2.8"
4
4
  end
5
5
  end
@@ -31,47 +31,12 @@ module GitHub
31
31
  # GitHub::SQL::ROWS(array_of_arrays).
32
32
  #
33
33
  class SQL
34
-
35
- # Internal: a SQL literal value.
36
- class Literal
37
- # Public: the string value of this literal
38
- attr_reader :value
39
-
40
- def initialize(value)
41
- @value = value.to_s.dup.freeze
42
- end
43
-
44
- def inspect
45
- "<#{self.class.name} #{value}>"
46
- end
47
-
48
- def bytesize
49
- value.bytesize
50
- end
51
- end
52
-
53
- # Internal: a list of arrays of values for insertion into SQL.
54
- class Rows
55
- # Public: the Array of row values
56
- attr_reader :values
57
-
58
- def initialize(values)
59
- unless values.all? { |v| v.is_a? Array }
60
- raise ArgumentError, "cannot instantiate SQL rows with anything but arrays"
61
- end
62
- @values = values.dup.freeze
63
- end
64
-
65
- def inspect
66
- "<#{self.class.name} #{values.inspect}>"
67
- end
68
- end
69
-
70
- # Public: Run inside a transaction
71
- def self.transaction
72
- ActiveRecord::Base.connection.transaction do
73
- yield
74
- end
34
+ # Public: Run inside a transaction. Class version of this method only works
35
+ # if only one connection is in use. If passing connections to
36
+ # GitHub::SQL#initialize or overriding connection then you'll need to use
37
+ # the instance version.
38
+ def self.transaction(options = {}, &block)
39
+ ActiveRecord::Base.connection.transaction(options, &block)
75
40
  end
76
41
 
77
42
  # Public: Instantiate a literal SQL value.
@@ -103,27 +68,55 @@ module GitHub
103
68
  Rows.new(rows)
104
69
  end
105
70
 
106
- # Public: prepackaged literal values.
107
- NULL = Literal.new "NULL"
108
- NOW = Literal.new "NOW()"
71
+ # Public: Create and execute a new SQL query, ignoring results.
72
+ #
73
+ # sql - A SQL string. See GitHub::SQL#add for details.
74
+ # bindings - Optional bind values. See GitHub::SQL#add for details.
75
+ #
76
+ # Returns self.
77
+ def self.run(sql, bindings = {})
78
+ new(sql, bindings).run
79
+ end
109
80
 
110
- # Public: A superclass for errors.
111
- class Error < RuntimeError
81
+ # Public: Create and execute a new SQL query, returning its hash_result rows.
82
+ #
83
+ # sql - A SQL string. See GitHub::SQL#add for details.
84
+ # bindings - Optional bind values. See GitHub::SQL#add for details.
85
+ #
86
+ # Returns an Array of result hashes.
87
+ def self.hash_results(sql, bindings = {})
88
+ new(sql, bindings).hash_results
112
89
  end
113
90
 
114
- # Public: Raised when a bound ":keyword" value isn't available.
115
- class BadBind < Error
116
- def initialize(keyword)
117
- super "There's no bind value for #{keyword.inspect}"
118
- end
91
+ # Public: Create and execute a new SQL query, returning its result rows.
92
+ #
93
+ # sql - A SQL string. See GitHub::SQL#add for details.
94
+ # bindings - Optional bind values. See GitHub::SQL#add for details.
95
+ #
96
+ # Returns an Array of result arrays.
97
+ def self.results(sql, bindings = {})
98
+ new(sql, bindings).results
119
99
  end
120
100
 
121
- # Public: Raised when a bound value can't be sanitized.
122
- class BadValue < Error
123
- def initialize(value, description = nil)
124
- description ||= "a #{value.class.name}"
125
- super "Can't sanitize #{description}: #{value.inspect}"
126
- end
101
+ # Public: Create and execute a new SQL query, returning the value of the
102
+ # first column of the first result row.
103
+ #
104
+ # sql - A SQL string. See GitHub::SQL#add for details.
105
+ # bindings - Optional bind values. See GitHub::SQL#add for details.
106
+ #
107
+ # Returns a value or nil.
108
+ def self.value(sql, bindings = {})
109
+ new(sql, bindings).value
110
+ end
111
+
112
+ # Public: Create and execute a new SQL query, returning its values.
113
+ #
114
+ # sql - A SQL string. See GitHub::SQL#add for details.
115
+ # bindings - Optional bind values. See GitHub::SQL#add for details.
116
+ #
117
+ # Returns an Array of values.
118
+ def self.values(sql, bindings = {})
119
+ new(sql, bindings).values
127
120
  end
128
121
 
129
122
  # Internal: A Symbol-Keyed Hash of bind values.
@@ -151,10 +144,10 @@ module GitHub
151
144
 
152
145
  @last_insert_id = nil
153
146
  @affected_rows = nil
154
- @binds = binds ? binds.dup : {}
155
- @query = ""
156
- @connection = @binds.delete :connection
157
- @force_tz = @binds.delete :force_timezone
147
+ @binds = binds ? binds.dup : {}
148
+ @query = ""
149
+ @connection = @binds.delete :connection
150
+ @force_timezone = @binds.delete :force_timezone
158
151
 
159
152
  add query
160
153
  end
@@ -173,19 +166,9 @@ module GitHub
173
166
  return self if sql.nil? || sql.empty?
174
167
 
175
168
  query << " " unless query.empty?
169
+ query << interpolate(sql.strip, extras)
176
170
 
177
- begin
178
- if @force_tz
179
- zone = ActiveRecord::Base.default_timezone
180
- ActiveRecord::Base.default_timezone = @force_tz
181
- end
182
-
183
- query << interpolate(sql.strip, extras)
184
-
185
- self
186
- ensure
187
- ActiveRecord::Base.default_timezone = zone if @force_tz
188
- end
171
+ self
189
172
  end
190
173
 
191
174
  # Public: Add a chunk of SQL to the query, unless query generated so far is empty.
@@ -204,11 +187,6 @@ module GitHub
204
187
  add sql, extras
205
188
  end
206
189
 
207
- # Public: The number of affected rows for this connection.
208
- def affected_rows
209
- @affected_rows || connection.raw_connection.affected_rows
210
- end
211
-
212
190
  # Public: Add additional bind values to be interpolated each time SQL
213
191
  # is added to the query.
214
192
  #
@@ -220,44 +198,6 @@ module GitHub
220
198
  self
221
199
  end
222
200
 
223
- # Internal: The object we use to execute SQL and retrieve results. Defaults
224
- # to AR::B.connection, but can be overridden with a ":connection" key when
225
- # initializing a new instance.
226
- def connection
227
- @connection || ActiveRecord::Base.connection
228
- end
229
-
230
- # Public: the number of rows found by the query.
231
- #
232
- # Returns FOUND_ROWS() if a SELECT query included SQL_CALC_FOUND_ROWS.
233
- # Raises if SQL_CALC_FOUND_ROWS was not present in the query.
234
- def found_rows
235
- raise "no SQL_CALC_FOUND_ROWS clause present" unless defined? @found_rows
236
- @found_rows
237
- end
238
-
239
- # Internal: Replace ":keywords" with sanitized values from binds or extras.
240
- def interpolate(sql, extras = nil)
241
- sql.gsub(/:[a-z][a-z0-9_]*/) do |raw|
242
- sym = raw[1..-1].intern # O.o gensym
243
-
244
- if extras && extras.include?(sym)
245
- val = extras[sym]
246
- elsif binds.include?(sym)
247
- val = binds[sym]
248
- end
249
-
250
- raise BadBind.new raw if val.nil?
251
-
252
- sanitize val
253
- end
254
- end
255
-
256
- # Public: The last inserted ID for this connection.
257
- def last_insert_id
258
- @last_insert_id || connection.raw_connection.last_insert_id
259
- end
260
-
261
201
  # Public: Map each row to an instance of an ActiveRecord::Base subclass.
262
202
  def models(klass)
263
203
  return @models if defined? @models
@@ -279,12 +219,7 @@ module GitHub
279
219
  return @results if defined? @results
280
220
  return [] if frozen?
281
221
 
282
- begin
283
- if @force_tz
284
- zone = ActiveRecord::Base.default_timezone
285
- ActiveRecord::Base.default_timezone = @force_tz
286
- end
287
-
222
+ enforce_timezone do
288
223
  case query
289
224
  when /\ADELETE/i
290
225
  @affected_rows = connection.delete(query, "#{self.class.name} Delete")
@@ -310,11 +245,23 @@ module GitHub
310
245
  freeze
311
246
 
312
247
  @results
313
- ensure
314
- ActiveRecord::Base.default_timezone = zone if @force_tz
315
248
  end
316
249
  end
317
250
 
251
+ # Public: Execute, ignoring results. This is useful when the results of a
252
+ # query aren't important, often INSERTs, UPDATEs, or DELETEs.
253
+ #
254
+ # sql - An optional SQL string. See GitHub::SQL#add for details.
255
+ # extras - Optional bind values. See GitHub::SQL#add for details.
256
+ #
257
+ # Returns self.
258
+ def run(sql = nil, extras = nil)
259
+ add sql, extras if !sql.nil?
260
+ results
261
+
262
+ self
263
+ end
264
+
318
265
  # Public: If the query is a SELECT, return an array of hashes instead of an array of arrays.
319
266
  def hash_results
320
267
  results
@@ -326,18 +273,47 @@ module GitHub
326
273
  results.first
327
274
  end
328
275
 
329
- # Public: Execute, ignoring results. This is useful when the results of a
330
- # query aren't important, often INSERTs, UPDATEs, or DELETEs.
331
- #
332
- # sql - An optional SQL string. See GitHub::SQL#add for details.
333
- # extras - Optional bind values. See GitHub::SQL#add for details.
276
+ # Public: Get the first column of the first row of results.
277
+ def value
278
+ row && row.first
279
+ end
280
+
281
+ # Public: Is there a value?
282
+ def value?
283
+ !value.nil?
284
+ end
285
+
286
+ # Public: Get first column of every row of results.
334
287
  #
335
- # Returns self.
336
- def run(sql = nil, extras = nil)
337
- add sql, extras if !sql.nil?
338
- results
288
+ # Returns an Array or nil.
289
+ def values
290
+ results.map(&:first)
291
+ end
339
292
 
340
- self
293
+ # Public: Run inside a transaction for the connection.
294
+ def transaction(options = {}, &block)
295
+ connection.transaction(options, &block)
296
+ end
297
+
298
+ # Internal: The object we use to execute SQL and retrieve results. Defaults
299
+ # to AR::B.connection, but can be overridden with a ":connection" key when
300
+ # initializing a new instance.
301
+ def connection
302
+ @connection || ActiveRecord::Base.connection
303
+ end
304
+
305
+ # Public: The number of affected rows for this connection.
306
+ def affected_rows
307
+ @affected_rows || connection.raw_connection.affected_rows
308
+ end
309
+
310
+ # Public: the number of rows found by the query.
311
+ #
312
+ # Returns FOUND_ROWS() if a SELECT query included SQL_CALC_FOUND_ROWS.
313
+ # Raises if SQL_CALC_FOUND_ROWS was not present in the query.
314
+ def found_rows
315
+ raise "no SQL_CALC_FOUND_ROWS clause present" unless defined? @found_rows
316
+ @found_rows
341
317
  end
342
318
 
343
319
  # Internal: when a SQL_CALC_FOUND_ROWS clause is present in a SELECT query,
@@ -349,55 +325,26 @@ module GitHub
349
325
  end
350
326
  end
351
327
 
352
- # Public: Create and execute a new SQL query, ignoring results.
353
- #
354
- # sql - A SQL string. See GitHub::SQL#add for details.
355
- # bindings - Optional bind values. See GitHub::SQL#add for details.
356
- #
357
- # Returns self.
358
- def self.run(sql, bindings = {})
359
- new(sql, bindings).run
328
+ # Public: The last inserted ID for this connection.
329
+ def last_insert_id
330
+ @last_insert_id || connection.raw_connection.last_insert_id
360
331
  end
361
332
 
362
- # Public: Create and execute a new SQL query, returning its hash_result rows.
363
- #
364
- # sql - A SQL string. See GitHub::SQL#add for details.
365
- # bindings - Optional bind values. See GitHub::SQL#add for details.
366
- #
367
- # Returns an Array of result hashes.
368
- def self.hash_results(sql, bindings = {})
369
- new(sql, bindings).hash_results
370
- end
333
+ # Internal: Replace ":keywords" with sanitized values from binds or extras.
334
+ def interpolate(sql, extras = nil)
335
+ sql.gsub(/:[a-z][a-z0-9_]*/) do |raw|
336
+ sym = raw[1..-1].intern # O.o gensym
371
337
 
372
- # Public: Create and execute a new SQL query, returning its result rows.
373
- #
374
- # sql - A SQL string. See GitHub::SQL#add for details.
375
- # bindings - Optional bind values. See GitHub::SQL#add for details.
376
- #
377
- # Returns an Array of result arrays.
378
- def self.results(sql, bindings = {})
379
- new(sql, bindings).results
380
- end
338
+ if extras && extras.include?(sym)
339
+ val = extras[sym]
340
+ elsif binds.include?(sym)
341
+ val = binds[sym]
342
+ end
381
343
 
382
- # Public: Create and execute a new SQL query, returning the value of the
383
- # first column of the first result row.
384
- #
385
- # sql - A SQL string. See GitHub::SQL#add for details.
386
- # bindings - Optional bind values. See GitHub::SQL#add for details.
387
- #
388
- # Returns a value or nil.
389
- def self.value(sql, bindings = {})
390
- new(sql, bindings).value
391
- end
344
+ raise BadBind.new raw if val.nil?
392
345
 
393
- # Public: Create and execute a new SQL query, returning its values.
394
- #
395
- # sql - A SQL string. See GitHub::SQL#add for details.
396
- # bindings - Optional bind values. See GitHub::SQL#add for details.
397
- #
398
- # Returns an Array of values.
399
- def self.values(sql, bindings = {})
400
- new(sql, bindings).values
346
+ sanitize val
347
+ end
401
348
  end
402
349
 
403
350
  # Internal: Make `value` database-safe. Ish.
@@ -426,7 +373,9 @@ module GitHub
426
373
  connection.quote value.name
427
374
 
428
375
  when DateTime, Time, Date
429
- connection.quote value.to_s(:db)
376
+ enforce_timezone do
377
+ connection.quote value.to_s(:db)
378
+ end
430
379
 
431
380
  when true
432
381
  connection.quoted_true
@@ -442,21 +391,24 @@ module GitHub
442
391
  end
443
392
  end
444
393
 
445
- # Public: Get the first column of the first row of results.
446
- def value
447
- row && row.first
448
- end
394
+ private
449
395
 
450
- # Public: Is there a value?
451
- def value?
452
- !value.nil?
453
- end
396
+ # Private: Forces ActiveRecord's default timezone for duration of block.
397
+ def enforce_timezone(&block)
398
+ begin
399
+ if @force_timezone
400
+ zone = ActiveRecord::Base.default_timezone
401
+ ActiveRecord::Base.default_timezone = @force_timezone
402
+ end
454
403
 
455
- # Public: Get first column of every row of results.
456
- #
457
- # Returns an Array or nil.
458
- def values
459
- results.map(&:first)
404
+ yield if block_given?
405
+ ensure
406
+ ActiveRecord::Base.default_timezone = zone if @force_timezone
407
+ end
460
408
  end
461
409
  end
462
410
  end
411
+
412
+ require "github/sql/literal"
413
+ require "github/sql/rows"
414
+ require "github/sql/errors"
@@ -0,0 +1,22 @@
1
+ module GitHub
2
+ class SQL
3
+ # Public: A superclass for errors.
4
+ class Error < RuntimeError
5
+ end
6
+
7
+ # Public: Raised when a bound ":keyword" value isn't available.
8
+ class BadBind < Error
9
+ def initialize(keyword)
10
+ super "There's no bind value for #{keyword.inspect}"
11
+ end
12
+ end
13
+
14
+ # Public: Raised when a bound value can't be sanitized.
15
+ class BadValue < Error
16
+ def initialize(value, description = nil)
17
+ description ||= "a #{value.class.name}"
18
+ super "Can't sanitize #{description}: #{value.inspect}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module GitHub
2
+ class SQL
3
+ # Internal: a SQL literal value.
4
+ class Literal
5
+ # Public: the string value of this literal
6
+ attr_reader :value
7
+
8
+ def initialize(value)
9
+ @value = value.to_s.dup.freeze
10
+ end
11
+
12
+ def inspect
13
+ "<#{self.class.name} #{value}>"
14
+ end
15
+
16
+ def bytesize
17
+ value.bytesize
18
+ end
19
+ end
20
+
21
+ # Public: prepackaged literal values.
22
+ NULL = Literal.new "NULL"
23
+ NOW = Literal.new "NOW()"
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ module GitHub
2
+ class SQL
3
+ # Internal: a list of arrays of values for insertion into SQL.
4
+ class Rows
5
+ # Public: the Array of row values
6
+ attr_reader :values
7
+
8
+ def initialize(values)
9
+ unless values.all? { |v| v.is_a? Array }
10
+ raise ArgumentError, "cannot instantiate SQL rows with anything but arrays"
11
+ end
12
+ @values = values.dup.freeze
13
+ end
14
+
15
+ def inspect
16
+ "<#{self.class.name} #{values.inspect}>"
17
+ end
18
+ end
19
+ end
20
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github-ds
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-09-28 00:00:00.000000000 Z
12
+ date: 2017-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -162,6 +162,9 @@ files:
162
162
  - lib/github/kv.rb
163
163
  - lib/github/result.rb
164
164
  - lib/github/sql.rb
165
+ - lib/github/sql/errors.rb
166
+ - lib/github/sql/literal.rb
167
+ - lib/github/sql/rows.rb
165
168
  - script/bootstrap
166
169
  - script/console
167
170
  - script/install