sqlite3_extend_function 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -0
  3. data/.rubocop.yml +36 -0
  4. data/CHANGELOG.md +17 -0
  5. data/Gemfile +10 -0
  6. data/README.md +32 -3
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/lib/sqlite3_extend_function.rb +7 -9
  10. data/lib/sqlite3_extend_function/function.rb +20 -555
  11. data/lib/sqlite3_extend_function/functions.rb +17 -0
  12. data/lib/sqlite3_extend_function/functions/acos.rb +19 -0
  13. data/lib/sqlite3_extend_function/functions/ascii.rb +20 -0
  14. data/lib/sqlite3_extend_function/functions/asin.rb +19 -0
  15. data/lib/sqlite3_extend_function/functions/atan.rb +19 -0
  16. data/lib/sqlite3_extend_function/functions/atan2.rb +20 -0
  17. data/lib/sqlite3_extend_function/functions/bit_length.rb +21 -0
  18. data/lib/sqlite3_extend_function/functions/btrim.rb +21 -0
  19. data/lib/sqlite3_extend_function/functions/cbrt.rb +22 -0
  20. data/lib/sqlite3_extend_function/functions/ceil.rb +21 -0
  21. data/lib/sqlite3_extend_function/functions/char_length.rb +20 -0
  22. data/lib/sqlite3_extend_function/functions/chr.rb +20 -0
  23. data/lib/sqlite3_extend_function/functions/concat.rb +20 -0
  24. data/lib/sqlite3_extend_function/functions/concat_ws.rb +21 -0
  25. data/lib/sqlite3_extend_function/functions/cos.rb +19 -0
  26. data/lib/sqlite3_extend_function/functions/cot.rb +19 -0
  27. data/lib/sqlite3_extend_function/functions/decode.rb +29 -0
  28. data/lib/sqlite3_extend_function/functions/degrees.rb +19 -0
  29. data/lib/sqlite3_extend_function/functions/div.rb +20 -0
  30. data/lib/sqlite3_extend_function/functions/encode.rb +29 -0
  31. data/lib/sqlite3_extend_function/functions/exp.rb +22 -0
  32. data/lib/sqlite3_extend_function/functions/floor.rb +19 -0
  33. data/lib/sqlite3_extend_function/functions/format.rb +17 -0
  34. data/lib/sqlite3_extend_function/functions/initcap.rb +24 -0
  35. data/lib/sqlite3_extend_function/functions/ln.rb +22 -0
  36. data/lib/sqlite3_extend_function/functions/log.rb +24 -0
  37. data/lib/sqlite3_extend_function/functions/md5.rb +20 -0
  38. data/lib/sqlite3_extend_function/functions/mod.rb +21 -0
  39. data/lib/sqlite3_extend_function/functions/now.rb +15 -0
  40. data/lib/sqlite3_extend_function/functions/octet_length.rb +20 -0
  41. data/lib/sqlite3_extend_function/functions/pi.rb +15 -0
  42. data/lib/sqlite3_extend_function/functions/power.rb +23 -0
  43. data/lib/sqlite3_extend_function/functions/radians.rb +22 -0
  44. data/lib/sqlite3_extend_function/functions/sign.rb +22 -0
  45. data/lib/sqlite3_extend_function/functions/sin.rb +19 -0
  46. data/lib/sqlite3_extend_function/functions/sqrt.rb +22 -0
  47. data/lib/sqlite3_extend_function/functions/tan.rb +19 -0
  48. data/lib/sqlite3_extend_function/functions/trunc.rb +25 -0
  49. data/lib/sqlite3_extend_function/functions/width_bucket.rb +27 -0
  50. data/lib/sqlite3_extend_function/version.rb +1 -1
  51. data/sqlite3_extend_function.gemspec +25 -0
  52. metadata +52 -62
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b370727ad3e7fe4e4dbce17de3372fb15fff6c2193f2400563c1a7a1e9e6fc88
4
- data.tar.gz: d66b7180e476b6154ff201b82424df92f0e28572643e7de869ddd842a9707159
3
+ metadata.gz: 80bfa77fec9b09e2cf91f422d457b75f4d4a29f477a34b677ce33252b8a4c02a
4
+ data.tar.gz: e4bd09974e3c5353c622a3adbdf8b6c3f03040ff1128db0e495569bb769e6a29
5
5
  SHA512:
6
- metadata.gz: b52dc19acdd7720c481acdc73ba8390aaad68f79181f0d9ce4f0fff87bd6c4b512e01bd2faa7141461b6efc4b9909a3b306ff0544c3b233c8b833c5183750940
7
- data.tar.gz: d2f10a203913bbdcf6bf7d1c85e48b0be609cf158ae08209dbe6016561e28653350092f2d7b487a486c05680133b52c847b60073a5b3dd89550518ec26cf633c
6
+ metadata.gz: 01a2867fe5fc9ae7b005eec2ab1310938338fb323fb2336f2f11155a3af60cb79b3ef5215e85e2303c478d31e3b15416a2bba0d5fe51cc9bebe87c0593d718d1
7
+ data.tar.gz: ffd1a7a02b6db7e1e4fede1c2dc33676d496af8e5b278a45f1eaea5758edd240117bfbec9b35f65721f340366df366e43bc42472417545c04f95946549c5ce8e
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /vendor
10
+ .DS_Store
11
+ Gemfile.lock
12
+ .rspec
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
@@ -0,0 +1,36 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ NewCops: enable
4
+ Lint/DuplicateBranch:
5
+ Enabled: true
6
+ Lint/DuplicateRegexpCharacterClassElement:
7
+ Enabled: true
8
+ Lint/EmptyBlock:
9
+ Enabled: true
10
+ Lint/EmptyClass:
11
+ Enabled: true
12
+ Lint/NoReturnInBeginEndBlocks:
13
+ Enabled: true
14
+ Lint/ToEnumArguments:
15
+ Enabled: true
16
+ Lint/UnmodifiedReduceAccumulator:
17
+ Enabled: true
18
+ Naming/MethodParameterName:
19
+ Enabled: false
20
+ Metrics/BlockLength:
21
+ Exclude:
22
+ - spec/**/*
23
+ Style/ArgumentsForwarding:
24
+ Enabled: true
25
+ Style/CollectionCompact:
26
+ Enabled: true
27
+ Style/DocumentDynamicEvalDefinition:
28
+ Enabled: true
29
+ Style/NegatedIfElseCondition:
30
+ Enabled: true
31
+ Style/NilLambda:
32
+ Enabled: true
33
+ Style/RedundantArgument:
34
+ Enabled: true
35
+ Style/SwapValues:
36
+ Enabled: true
@@ -0,0 +1,17 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.3.0 / 2020-12-20
4
+ ### Modified
5
+ - Added specification to add extend function
6
+ - Remove SQLite3 from dependency
7
+ - Abolished automatic include of extend function
8
+ - Ruby version changed to 2.4 or higher
9
+
10
+ ## 0.2.0 / 2019-12-05
11
+ ### Modified
12
+ - Remove ActiveRecord from dependency
13
+ - Add function
14
+
15
+ ## 0.1.0 / 2019-12-03
16
+ ### Modified
17
+ - Create ceil and floor functions
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in qlite3_extend_function.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+ gem 'rspec', '~> 3.10'
10
+ gem 'sqlite3', '~> 1.4'
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SQLite3ExtendFunction
2
2
 
3
- Add some user-defined function to SQL when using SQLie3.
3
+ Add some user-defined function to SQL when using SQLite3.
4
4
 
5
5
  ## Functions
6
6
 
@@ -47,8 +47,9 @@ The following PostgreSQL functions are supported.
47
47
 
48
48
  See [PostgreSQL Document](https://www.postgresql.org/docs/12/functions.html)
49
49
 
50
- ```
50
+ ```ruby
51
51
  # check
52
+ SQLite3::Database.include(SQLite3ExtendFunction)
52
53
  db = SQLite3::Database.new(':memory:')
53
54
 
54
55
  db.execute("select ceil(0.1)")[0][0]
@@ -62,7 +63,7 @@ db.execute("select floor(1.1)")[0][0]
62
63
  Add this line to your application's Gemfile:
63
64
 
64
65
  ```ruby
65
- gem 'sqlite3_extend_function', '~> 0.2'
66
+ gem 'sqlite3_extend_function', '~> 0.3'
66
67
 
67
68
  # master branch
68
69
  gem 'sqlite3_extend_function',
@@ -75,5 +76,33 @@ And then execute:
75
76
  $ bundle
76
77
  ```
77
78
 
79
+ ## Enable extend functions
80
+
81
+ ```ruby
82
+ SQLite3::Database.include(SQLite3ExtendFunction)
83
+ ```
84
+
85
+ ## Add extend function
86
+
87
+ Extend function can be added by defining modules such as:
88
+
89
+ ```ruby
90
+ module SQLite3ExtendFunction
91
+ module Functions
92
+ module FunctionName
93
+ class << self
94
+ def call(arg1)
95
+ # ...
96
+ rescue StandardError
97
+ raise SQLite3::SQLException, 'error message'
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ ```
104
+
105
+ Extend function name is "FunctionName" as the snake case.
106
+
78
107
  ## License
79
108
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'sqlite3_extend_function'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -1,27 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sqlite3'
3
+ require 'bigdecimal'
4
+ require 'base64'
5
+ require 'digest/md5'
4
6
  require 'sqlite3_extend_function/version'
5
7
  require 'sqlite3_extend_function/function'
8
+ require 'sqlite3_extend_function/functions'
6
9
 
7
10
  # SQLite3ExtendFunction
8
11
  module SQLite3ExtendFunction
12
+ # @param [Class] base
13
+ # @return [void]
9
14
  def self.included(base)
10
15
  base.class_eval do
11
16
  original_method = instance_method(:initialize)
12
17
  define_method(:initialize) do |*args, &block|
13
18
  result = original_method.bind(self).call(*args)
14
- SQLite3ExtendFunction::Function.singleton_methods.each do |func|
15
- lmd = Function.send(func)
16
- create_function(func.to_s, (lmd.parameters.size - 1), &lmd)
17
- end
18
- # frozen_string_literal: true
19
- # SQLite3ExtendFunction
19
+ Functions.each { |func| create_function(func.name, func.arity, &func.to_proc) }
20
20
  block&.call(self)
21
21
  result
22
22
  end
23
23
  end
24
24
  end
25
25
  end
26
-
27
- SQLite3::Database.include(SQLite3ExtendFunction)
@@ -1,565 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bigdecimal'
4
- require 'base64'
5
- require 'digest/md5'
6
3
  module SQLite3ExtendFunction
7
4
  # SQLite3ExtendFunction::Function
8
- module Function
9
- class << self
10
- # @return [Proc]
11
- def ceil
12
- lambda do |func, dp|
13
- return if dp.nil?
14
-
15
- begin
16
- func.result = Kernel.Float(dp).ceil.to_i
17
- rescue ArgumentError
18
- raise SQLite3::SQLException,
19
- "invalid input syntax for type double precision: \"#{dp}\""
20
- end
21
- end
22
- end
23
-
24
- # @return [Proc]
25
- def floor
26
- lambda do |func, dp|
27
- return if dp.nil?
28
-
29
- begin
30
- func.result = Kernel.Float(dp).floor.to_i
31
- rescue ArgumentError
32
- raise SQLite3::SQLException,
33
- "invalid input syntax for type double precision: \"#{dp}\""
34
- end
35
- end
36
- end
37
-
38
- # cube root
39
- # @return [Proc]
40
- def cbrt
41
- lambda do |func, dp|
42
- return if dp.nil?
43
-
44
- begin
45
- result = Math.cbrt(Kernel.Float(dp))
46
- func.result = result.to_i == result ? result.to_i : result
47
- rescue ArgumentError
48
- raise SQLite3::SQLException,
49
- "invalid input syntax for type double precision: \"#{dp}\""
50
- end
51
- end
52
- end
53
-
54
- # radians to degrees
55
- # @return [Proc]
56
- def degrees
57
- lambda do |func, dp|
58
- return if dp.nil?
59
-
60
- begin
61
- func.result = Kernel.Float(dp) * 180 / Math::PI
62
- rescue ArgumentError
63
- raise SQLite3::SQLException,
64
- "invalid input syntax for type double precision: \"#{dp}\""
65
- end
66
- end
67
- end
68
-
69
- # integer quotient of y/x
70
- # @return [Proc]
71
- def div
72
- lambda do |func, y, x|
73
- return if y.nil? || x.nil?
74
-
75
- begin
76
- func.result = Kernel.Float(y).div(Kernel.Float(x))
77
- rescue ArgumentError
78
- raise SQLite3::SQLException,
79
- 'invalid input syntax for type numeric'
80
- end
81
- end
82
- end
83
-
84
- # exponential
85
- # @return [Proc]
86
- def exp
87
- lambda do |func, dp|
88
- return if dp.nil?
89
-
90
- begin
91
- result = Math.exp(Kernel.Float(dp))
92
- func.result = result.to_i == result ? result.to_i : result
93
- rescue ArgumentError
94
- raise SQLite3::SQLException,
95
- "invalid input syntax for type double precision: \"#{dp}\""
96
- end
97
- end
98
- end
99
-
100
- # natural logarithm
101
- # @return [Proc]
102
- def ln
103
- lambda do |func, dp|
104
- return if dp.nil?
105
-
106
- begin
107
- result = Math.log(Kernel.Float(dp))
108
- func.result = result.to_i == result ? result.to_i : result
109
- rescue ArgumentError
110
- raise SQLite3::SQLException,
111
- 'cannot take logarithm of a negative number'
112
- end
113
- end
114
- end
115
-
116
- # base 10 logarithm
117
- # @return [Proc]
118
- def log
119
- lambda do |func, y, x = nil|
120
- if x.nil?
121
- return if y.nil?
122
-
123
- result = Math.log10(Kernel.Float(y))
124
- func.result = result.to_i == result ? result.to_i : result
125
- else
126
- return if y.nil? || x.nil?
127
-
128
- func.result = Math.log(x, y)
129
- end
130
- rescue ArgumentError
131
- raise SQLite3::SQLException,
132
- 'invalid input syntax for type numeric'
133
- end
134
- end
135
-
136
- # remainder of y/x
137
- # @return [Proc]
138
- def mod
139
- lambda do |func, y, x|
140
- func.result = Kernel.Float(y).modulo(Kernel.Float(x)).to_i
141
- rescue ArgumentError
142
- raise SQLite3::SQLException,
143
- 'Could not choose a best candidate function. You might need to add explicit type casts.'
144
- end
145
- end
146
-
147
- # "π" constant
148
- # @return [Proc]
149
- def pi
150
- lambda do |func|
151
- func.result = Math::PI
152
- end
153
- end
154
-
155
- # a raised to the power of b
156
- # @return [Proc]
157
- def power
158
- lambda do |func, a, b|
159
- return if a.nil? || b.nil?
160
-
161
- begin
162
- result = Kernel.Float(a)**Kernel.Float(b)
163
- func.result = result.to_i == result ? result.to_i : result
164
- rescue ArgumentError
165
- raise SQLite3::SQLException,
166
- 'invalid input syntax for type double precision'
167
- end
168
- end
169
- end
170
-
171
- # degrees to radians
172
- # @return [Proc]
173
- def radians
174
- lambda do |func, dp|
175
- return if dp.nil?
176
-
177
- begin
178
- result = Kernel.Float(dp) * Math::PI / 180
179
- func.result = result.to_i == result ? result.to_i : result
180
- rescue ArgumentError
181
- raise SQLite3::SQLException,
182
- "invalid input syntax for type double precision: \"#{dp}\""
183
- end
184
- end
185
- end
186
-
187
- # sign of the argument (-1, 0, +1)
188
- # @return [Proc]
189
- def sign
190
- lambda do |func, dp|
191
- return if dp.nil?
192
-
193
- begin
194
- value = Kernel.Float(dp)
195
- func.result = if value.zero?
196
- 0
197
- elsif value.positive?
198
- 1
199
- else
200
- -1
201
- end
202
- rescue ArgumentError
203
- raise SQLite3::SQLException,
204
- "invalid input syntax for type double precision: \"#{dp}\""
205
- end
206
- end
207
- end
208
-
209
- # square root
210
- # @return [Proc]
211
- def sqrt
212
- lambda do |func, dp|
213
- return if dp.nil?
214
-
215
- begin
216
- result = Math.sqrt(Kernel.Float(dp))
217
- func.result = result.to_i == result ? result.to_i : result
218
- rescue ArgumentError
219
- raise SQLite3::SQLException,
220
- "invalid input syntax for type double precision: \"#{dp}\""
221
- end
222
- end
223
- end
224
-
225
- # truncate toward zero
226
- # @return [Proc]
227
- def trunc
228
- lambda do |func, dp, s = 0|
229
- return if dp.nil?
230
-
231
- begin
232
- ss = BigDecimal(Kernel.Float(s).to_s)
233
- dec = if ss.zero?
234
- BigDecimal('1.0')
235
- else
236
- BigDecimal((1.0 / (10**ss).to_f).to_s)
237
- end
238
- result = (BigDecimal(Kernel.Float(dp).to_s) / dec).to_i * dec
239
- func.result = result.to_i == result ? result.to_i : result.to_f
240
- rescue ArgumentError
241
- raise SQLite3::SQLException,
242
- 'invalid input syntax for type double precision'
243
- end
244
- end
245
- end
246
-
247
- # return the bucket number to which operand would be assigned input
248
- # a histogram having count equal-width buckets spanning the range b1 to b2;
249
- # returns 0 or count+1 for an input outside the range
250
- # @return [Proc]
251
- def width_bucket
252
- lambda do |func, operand, b1, b2, count|
253
- begin
254
- operand = Kernel.Float(operand)
255
- b1 = Kernel.Float(b1)
256
- b2 = Kernel.Float(b2)
257
- count = Kernel.Float(count)
258
-
259
- raise ArgumentError unless count.positive?
260
- result = (operand / ((b2 - b1) / count)).ceil
261
- result = count + 1 if result > count
262
- result = 0 if result.negative?
263
- func.result = result.to_i
264
- rescue ArgumentError
265
- raise SQLite3::SQLException,
266
- 'ArgumentError'
267
- end
268
- end
269
- end
270
-
271
- # @return [Proc]
272
- def acos
273
- lambda do |func, x|
274
- begin
275
- func.result = Math.acos(Kernel.Float(x))
276
- rescue ArgumentError
277
- raise SQLite3::SQLException,
278
- "invalid input syntax for type double precision: #{x}"
279
- end
280
- end
281
- end
282
-
283
- # @return [Proc]
284
- def asin
285
- lambda do |func, x|
286
- begin
287
- func.result = Math.asin(Kernel.Float(x))
288
- rescue ArgumentError
289
- raise SQLite3::SQLException,
290
- "invalid input syntax for type double precision: #{x}"
291
- end
292
- end
293
- end
294
-
295
- # @return [Proc]
296
- def atan
297
- lambda do |func, x|
298
- begin
299
- func.result = Math.atan(Kernel.Float(x))
300
- rescue ArgumentError
301
- raise SQLite3::SQLException,
302
- "invalid input syntax for type double precision: #{x}"
303
- end
304
- end
305
- end
306
-
307
- # @return [Proc]
308
- def atan2
309
- lambda do |func, y, x|
310
- begin
311
- func.result = Math.atan2(Kernel.Float(y), Kernel.Float(x))
312
- rescue ArgumentError
313
- raise SQLite3::SQLException,
314
- "invalid input syntax for type double precision"
315
- end
316
- end
317
- end
318
-
319
- # @return [Proc]
320
- def cos
321
- lambda do |func, x|
322
- begin
323
- func.result = Math.cos(Kernel.Float(x))
324
- rescue ArgumentError
325
- raise SQLite3::SQLException,
326
- "invalid input syntax for type double precision: #{x}"
327
- end
328
- end
329
- end
330
-
331
- # @return [Proc]
332
- def cot
333
- lambda do |func, x|
334
- begin
335
- func.result = 1 / Math.tan(Kernel.Float(x))
336
- rescue ArgumentError
337
- raise SQLite3::SQLException,
338
- "invalid input syntax for type double precision: #{x}"
339
- end
340
- end
341
- end
342
-
343
- # @return [Proc]
344
- def sin
345
- lambda do |func, x|
346
- begin
347
- func.result = Math.sin(Kernel.Float(x))
348
- rescue ArgumentError
349
- raise SQLite3::SQLException,
350
- "invalid input syntax for type double precision: #{x}"
351
- end
352
- end
353
- end
354
-
355
- # @return [Proc]
356
- def tan
357
- lambda do |func, x|
358
- begin
359
- func.result = Math.tan(Kernel.Float(x))
360
- rescue ArgumentError
361
- raise SQLite3::SQLException,
362
- "invalid input syntax for type double precision: #{x}"
363
- end
364
- end
365
- end
366
-
367
- # Number of bits in string
368
- # @return [Proc]
369
- def bit_length
370
- lambda do |func, str|
371
- begin
372
- func.result = str.bytesize * 8
373
- rescue ArgumentError
374
- raise SQLite3::SQLException,
375
- "No function matches the given name and argument types. You might need to add explicit type casts."
376
- end
377
- end
378
- end
379
-
380
- # Number of characters in string
381
- # @return [Proc]
382
- def char_length
383
- lambda do |func, str|
384
- begin
385
- func.result = str.length
386
- rescue ArgumentError
387
- raise SQLite3::SQLException,
388
- "No function matches the given name and argument types. You might need to add explicit type casts."
389
- end
390
- end
391
- end
392
-
393
- # octet_length
394
- # @return [Proc]
395
- def octet_length
396
- lambda do |func, str|
397
- begin
398
- func.result = str.bytesize
399
- rescue ArgumentError
400
- raise SQLite3::SQLException,
401
- "No function matches the given name and argument types. You might need to add explicit type casts."
402
- end
403
- end
404
- end
405
-
406
- # @return [Proc]
407
- def ascii
408
- lambda do |func, str|
409
- begin
410
- raise ArgumentError if str.is_a? String
411
-
412
- func.result = str.ord
413
- rescue ArgumentError
414
- raise SQLite3::SQLException,
415
- "No function matches the given name and argument types. You might need to add explicit type casts."
416
- end
417
- end
418
- end
419
-
420
- # @return [Proc]
421
- def btrim
422
- lambda do |func, text, chrs = ''|
423
- begin
424
- func.result = text.sub(/\A[#{chrs}]*/, '').sub(/[#{chrs}]*\z/, '')
425
- rescue ArgumentError
426
- raise SQLite3::SQLException,
427
- "No function matches the given name and argument types. You might need to add explicit type casts."
428
- end
429
- end
430
- end
431
-
432
- # @return [Proc]
433
- def chr
434
- lambda do |func, int|
435
- begin
436
- func.result = int.chr
437
- rescue ArgumentError
438
- raise SQLite3::SQLException,
439
- "No function matches the given name and argument types. You might need to add explicit type casts."
440
- end
441
- end
442
- end
443
-
444
- # @return [Proc]
445
- def concat
446
- lambda do |func, *args|
447
- begin
448
- func.result = args.compact.join
449
- rescue ArgumentError
450
- raise SQLite3::SQLException,
451
- "No function matches the given name and argument types. You might need to add explicit type casts."
452
- end
453
- end
454
- end
455
-
456
- # @return [Proc]
457
- def concat_ws
458
- lambda do |func, sep, *args|
459
- begin
460
- func.result = args.compact.join(sep)
461
- rescue ArgumentError
462
- raise SQLite3::SQLException,
463
- "No function matches the given name and argument types. You might need to add explicit type casts."
464
- end
465
- end
466
- end
467
-
468
- # @return [Proc]
469
- def decode
470
- lambda do |func, str, format|
471
- return if data.nil?
472
-
473
- begin
474
- raise ArgumentError if data.is_a? String
475
-
476
- func.result = case format
477
- when 'base64'
478
- Base64.decode64(str)
479
- when 'hex'
480
- str.scan(/.{2}/).map(&:hex).map(&:chr).join
481
- when 'escape'
482
- raise ArgumentError
483
- else
484
- raise ArgumentError
485
- end
486
- rescue ArgumentError
487
- raise SQLite3::SQLException,
488
- "No function matches the given name and argument types. You might need to add explicit type casts."
489
- end
490
- end
491
- end
492
-
493
- # @return [Proc]
494
- def encode
495
- lambda do |func, data, format|
496
- return if data.nil?
497
-
498
- begin
499
- raise ArgumentError if data.is_a? String
500
-
501
- func.result = case format
502
- when 'base64'
503
- Base64.encode64(data)
504
- when 'hex'
505
- data.unpack("C*").map { |c| c.to_s(16) }.join
506
- when 'escape'
507
- raise ArgumentError
508
- else
509
- raise ArgumentError
510
- end
511
- rescue ArgumentError
512
- raise SQLite3::SQLException,
513
- "No function matches the given name and argument types. You might need to add explicit type casts."
514
- end
515
- end
516
- end
517
-
518
- # @return [Proc]
519
- def format
520
- lambda do |func, formartstr, *args|
521
- func.result = formartstr % args
522
- end
523
- end
524
-
525
- # @return [Proc]
526
- def initcap
527
- lambda do |func, str|
528
- return if str.nil?
529
-
530
- begin
531
- regexp = /([a-zA-Z0-9]*|[^a-zA-Z0-9]*)/
532
- func.result = str.split(regexp).map.with_index { |s, i|
533
- i.odd? ? s.downcase.capitalize : s
534
- }.join
535
- rescue
536
- raise SQLite3::SQLException,
537
- "No function matches the given name and argument types. You might need to add explicit type casts."
538
- end
539
- end
540
- end
5
+ class Function
6
+ # @param [Class] mod
7
+ # @return [void]
8
+ def initialize(mod)
9
+ @mod = mod
10
+ end
541
11
 
542
- # @return [Proc]
543
- def md5
544
- lambda do |func, str|
545
- return if str.nil?
12
+ # @return [String]
13
+ def name
14
+ @mod.name.split('::').last
15
+ .gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
16
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
17
+ .tr('-', '_').downcase
18
+ end
546
19
 
547
- begin
548
- func.result = Digest::MD5.hexdigest(str)
549
- rescue
550
- raise SQLite3::SQLException,
551
- "No function matches the given name and argument types. You might need to add explicit type casts."
552
- end
553
- end
554
- end
20
+ # @return [Proc]
21
+ def to_proc
22
+ ->(func, *argv) { func.result = @mod.call(*argv) }
23
+ end
555
24
 
556
- # Current date and time (start of current transaction)
557
- # @return [Proc]
558
- def now
559
- lambda do |func|
560
- func.result = Time.now.strftime('%Y-%m-%d %H:%M:%S.%6N%:z')
561
- end
562
- end
25
+ # @return [Integer]
26
+ def arity
27
+ @mod.method(:call).parameters.size
563
28
  end
564
29
  end
565
30
  end