github-ds 0.2.7 → 0.2.8

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