yesql 0.1.1 → 0.1.6
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 +4 -4
- data/.gitignore +4 -0
- data/.rubocop.yml +8 -0
- data/Gemfile.lock +54 -60
- data/README.md +8 -9
- data/lib/yesql.rb +2 -6
- data/lib/yesql/bindings/extract.rb +11 -3
- data/lib/yesql/bindings/transformed.rb +61 -0
- data/lib/yesql/common/adapter.rb +25 -0
- data/lib/yesql/config/configuration.rb +33 -0
- data/lib/yesql/params/output.rb +34 -0
- data/lib/yesql/query/performer.rb +16 -24
- data/lib/yesql/query/result.rb +43 -0
- data/lib/yesql/query/transform_result.rb +54 -0
- data/lib/yesql/version.rb +1 -1
- data/yesql.gemspec +1 -1
- metadata +24 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f432f23ac16148c7439ec096a55c142c9985c537d06ef5ded891fb3178d3bbf
|
|
4
|
+
data.tar.gz: b5d82c03933a0401d4b24a3fd48f00ea3864adfb8566db7f73c518714784cc54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '084397cf83aa10faf2d724a0be1c11548e36dd515932c4552498c130a96efb044ca5f498aa30d4ec9c002ea1f36c4ec3699bcd4e6e2db2313b0b56fab9da2ae5'
|
|
7
|
+
data.tar.gz: 70a91ebc63c23cd5c653351e728fc9c93207fd2583b1b72629d63717ba8e105c86318b016110f3040fd681b176da4d80db2807c40b4859ac3192c1a160901572
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/Gemfile.lock
CHANGED
|
@@ -1,63 +1,62 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
yesql (0.1.
|
|
5
|
-
dry-configurable (~> 0.11.6)
|
|
4
|
+
yesql (0.1.5)
|
|
6
5
|
rails (>= 5.0)
|
|
7
6
|
|
|
8
7
|
GEM
|
|
9
8
|
remote: https://rubygems.org/
|
|
10
9
|
specs:
|
|
11
|
-
actioncable (6.0.3.
|
|
12
|
-
actionpack (= 6.0.3.
|
|
10
|
+
actioncable (6.0.3.4)
|
|
11
|
+
actionpack (= 6.0.3.4)
|
|
13
12
|
nio4r (~> 2.0)
|
|
14
13
|
websocket-driver (>= 0.6.1)
|
|
15
|
-
actionmailbox (6.0.3.
|
|
16
|
-
actionpack (= 6.0.3.
|
|
17
|
-
activejob (= 6.0.3.
|
|
18
|
-
activerecord (= 6.0.3.
|
|
19
|
-
activestorage (= 6.0.3.
|
|
20
|
-
activesupport (= 6.0.3.
|
|
14
|
+
actionmailbox (6.0.3.4)
|
|
15
|
+
actionpack (= 6.0.3.4)
|
|
16
|
+
activejob (= 6.0.3.4)
|
|
17
|
+
activerecord (= 6.0.3.4)
|
|
18
|
+
activestorage (= 6.0.3.4)
|
|
19
|
+
activesupport (= 6.0.3.4)
|
|
21
20
|
mail (>= 2.7.1)
|
|
22
|
-
actionmailer (6.0.3.
|
|
23
|
-
actionpack (= 6.0.3.
|
|
24
|
-
actionview (= 6.0.3.
|
|
25
|
-
activejob (= 6.0.3.
|
|
21
|
+
actionmailer (6.0.3.4)
|
|
22
|
+
actionpack (= 6.0.3.4)
|
|
23
|
+
actionview (= 6.0.3.4)
|
|
24
|
+
activejob (= 6.0.3.4)
|
|
26
25
|
mail (~> 2.5, >= 2.5.4)
|
|
27
26
|
rails-dom-testing (~> 2.0)
|
|
28
|
-
actionpack (6.0.3.
|
|
29
|
-
actionview (= 6.0.3.
|
|
30
|
-
activesupport (= 6.0.3.
|
|
27
|
+
actionpack (6.0.3.4)
|
|
28
|
+
actionview (= 6.0.3.4)
|
|
29
|
+
activesupport (= 6.0.3.4)
|
|
31
30
|
rack (~> 2.0, >= 2.0.8)
|
|
32
31
|
rack-test (>= 0.6.3)
|
|
33
32
|
rails-dom-testing (~> 2.0)
|
|
34
33
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
35
|
-
actiontext (6.0.3.
|
|
36
|
-
actionpack (= 6.0.3.
|
|
37
|
-
activerecord (= 6.0.3.
|
|
38
|
-
activestorage (= 6.0.3.
|
|
39
|
-
activesupport (= 6.0.3.
|
|
34
|
+
actiontext (6.0.3.4)
|
|
35
|
+
actionpack (= 6.0.3.4)
|
|
36
|
+
activerecord (= 6.0.3.4)
|
|
37
|
+
activestorage (= 6.0.3.4)
|
|
38
|
+
activesupport (= 6.0.3.4)
|
|
40
39
|
nokogiri (>= 1.8.5)
|
|
41
|
-
actionview (6.0.3.
|
|
42
|
-
activesupport (= 6.0.3.
|
|
40
|
+
actionview (6.0.3.4)
|
|
41
|
+
activesupport (= 6.0.3.4)
|
|
43
42
|
builder (~> 3.1)
|
|
44
43
|
erubi (~> 1.4)
|
|
45
44
|
rails-dom-testing (~> 2.0)
|
|
46
45
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
47
|
-
activejob (6.0.3.
|
|
48
|
-
activesupport (= 6.0.3.
|
|
46
|
+
activejob (6.0.3.4)
|
|
47
|
+
activesupport (= 6.0.3.4)
|
|
49
48
|
globalid (>= 0.3.6)
|
|
50
|
-
activemodel (6.0.3.
|
|
51
|
-
activesupport (= 6.0.3.
|
|
52
|
-
activerecord (6.0.3.
|
|
53
|
-
activemodel (= 6.0.3.
|
|
54
|
-
activesupport (= 6.0.3.
|
|
55
|
-
activestorage (6.0.3.
|
|
56
|
-
actionpack (= 6.0.3.
|
|
57
|
-
activejob (= 6.0.3.
|
|
58
|
-
activerecord (= 6.0.3.
|
|
49
|
+
activemodel (6.0.3.4)
|
|
50
|
+
activesupport (= 6.0.3.4)
|
|
51
|
+
activerecord (6.0.3.4)
|
|
52
|
+
activemodel (= 6.0.3.4)
|
|
53
|
+
activesupport (= 6.0.3.4)
|
|
54
|
+
activestorage (6.0.3.4)
|
|
55
|
+
actionpack (= 6.0.3.4)
|
|
56
|
+
activejob (= 6.0.3.4)
|
|
57
|
+
activerecord (= 6.0.3.4)
|
|
59
58
|
marcel (~> 0.3.1)
|
|
60
|
-
activesupport (6.0.3.
|
|
59
|
+
activesupport (6.0.3.4)
|
|
61
60
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
62
61
|
i18n (>= 0.7, < 2)
|
|
63
62
|
minitest (~> 5.1)
|
|
@@ -68,13 +67,6 @@ GEM
|
|
|
68
67
|
concurrent-ruby (1.1.7)
|
|
69
68
|
crass (1.0.6)
|
|
70
69
|
diff-lcs (1.4.4)
|
|
71
|
-
dry-configurable (0.11.6)
|
|
72
|
-
concurrent-ruby (~> 1.0)
|
|
73
|
-
dry-core (~> 0.4, >= 0.4.7)
|
|
74
|
-
dry-equalizer (~> 0.2)
|
|
75
|
-
dry-core (0.4.9)
|
|
76
|
-
concurrent-ruby (~> 1.0)
|
|
77
|
-
dry-equalizer (0.3.0)
|
|
78
70
|
erubi (1.9.0)
|
|
79
71
|
globalid (0.4.2)
|
|
80
72
|
activesupport (>= 4.2.0)
|
|
@@ -92,7 +84,8 @@ GEM
|
|
|
92
84
|
mini_mime (1.0.2)
|
|
93
85
|
mini_portile2 (2.4.0)
|
|
94
86
|
minitest (5.14.2)
|
|
95
|
-
|
|
87
|
+
mysql2 (0.5.3)
|
|
88
|
+
nio4r (2.5.4)
|
|
96
89
|
nokogiri (1.10.10)
|
|
97
90
|
mini_portile2 (~> 2.4.0)
|
|
98
91
|
pg (1.2.3)
|
|
@@ -102,29 +95,29 @@ GEM
|
|
|
102
95
|
rack (2.2.3)
|
|
103
96
|
rack-test (1.1.0)
|
|
104
97
|
rack (>= 1.0, < 3)
|
|
105
|
-
rails (6.0.3.
|
|
106
|
-
actioncable (= 6.0.3.
|
|
107
|
-
actionmailbox (= 6.0.3.
|
|
108
|
-
actionmailer (= 6.0.3.
|
|
109
|
-
actionpack (= 6.0.3.
|
|
110
|
-
actiontext (= 6.0.3.
|
|
111
|
-
actionview (= 6.0.3.
|
|
112
|
-
activejob (= 6.0.3.
|
|
113
|
-
activemodel (= 6.0.3.
|
|
114
|
-
activerecord (= 6.0.3.
|
|
115
|
-
activestorage (= 6.0.3.
|
|
116
|
-
activesupport (= 6.0.3.
|
|
98
|
+
rails (6.0.3.4)
|
|
99
|
+
actioncable (= 6.0.3.4)
|
|
100
|
+
actionmailbox (= 6.0.3.4)
|
|
101
|
+
actionmailer (= 6.0.3.4)
|
|
102
|
+
actionpack (= 6.0.3.4)
|
|
103
|
+
actiontext (= 6.0.3.4)
|
|
104
|
+
actionview (= 6.0.3.4)
|
|
105
|
+
activejob (= 6.0.3.4)
|
|
106
|
+
activemodel (= 6.0.3.4)
|
|
107
|
+
activerecord (= 6.0.3.4)
|
|
108
|
+
activestorage (= 6.0.3.4)
|
|
109
|
+
activesupport (= 6.0.3.4)
|
|
117
110
|
bundler (>= 1.3.0)
|
|
118
|
-
railties (= 6.0.3.
|
|
111
|
+
railties (= 6.0.3.4)
|
|
119
112
|
sprockets-rails (>= 2.0.0)
|
|
120
113
|
rails-dom-testing (2.0.3)
|
|
121
114
|
activesupport (>= 4.2.0)
|
|
122
115
|
nokogiri (>= 1.6)
|
|
123
116
|
rails-html-sanitizer (1.3.0)
|
|
124
117
|
loofah (~> 2.3)
|
|
125
|
-
railties (6.0.3.
|
|
126
|
-
actionpack (= 6.0.3.
|
|
127
|
-
activesupport (= 6.0.3.
|
|
118
|
+
railties (6.0.3.4)
|
|
119
|
+
actionpack (= 6.0.3.4)
|
|
120
|
+
activesupport (= 6.0.3.4)
|
|
128
121
|
method_source
|
|
129
122
|
rake (>= 0.8.7)
|
|
130
123
|
thor (>= 0.20.3, < 2.0)
|
|
@@ -163,6 +156,7 @@ PLATFORMS
|
|
|
163
156
|
ruby
|
|
164
157
|
|
|
165
158
|
DEPENDENCIES
|
|
159
|
+
mysql2 (~> 0.5.3)
|
|
166
160
|
pg (>= 0.18)
|
|
167
161
|
pry (~> 0.13.1)
|
|
168
162
|
rspec (~> 3.9.0)
|
data/README.md
CHANGED
|
@@ -70,7 +70,6 @@ YeSQL('top_10_users_in_x_country', { country: 'Cuba', country_id: 1, limit: 6 })
|
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
- If the query doesn't have bindings, but they're provided they're just omitted.
|
|
73
|
-
TODO: update this with link to the error.
|
|
74
73
|
- If the query has bindings, but nothing is provided, it raises a `NotImplementedError` exception.
|
|
75
74
|
|
|
76
75
|
|
|
@@ -145,21 +144,21 @@ YeSQL('users', cache: { expires_in: 1.hour })
|
|
|
145
144
|
|
|
146
145
|
## Configuration
|
|
147
146
|
|
|
148
|
-
For default `YeSQL` looks for the _.sql_ files defined under the `app/yesql/` folder but you can update it to use any folder you need. For that you can create a Ruby file under the `config/initializers/`
|
|
147
|
+
For default `YeSQL` looks for the _.sql_ files defined under the `app/yesql/` folder but you can update it to use any folder you need. For that you can create a Ruby file under the `config/initializers/` with the following content:
|
|
149
148
|
|
|
150
149
|
```ruby
|
|
151
|
-
YeSQL.config.path = 'path'
|
|
150
|
+
::YeSQL.configure { |config| config.path = 'path' }
|
|
152
151
|
```
|
|
153
152
|
|
|
154
153
|
After saving the file and restarting the server the files are going to be read from the given folder.
|
|
155
154
|
|
|
156
|
-
You can check at anytime what's the configuration path by inspecting the YeSQL `config` object:
|
|
155
|
+
You can check at anytime what's the configuration path by inspecting the ::YeSQL `config` object:
|
|
157
156
|
|
|
158
157
|
```ruby
|
|
159
|
-
YeSQL.config
|
|
160
|
-
#
|
|
161
|
-
|
|
162
|
-
# "
|
|
158
|
+
::YeSQL.config
|
|
159
|
+
# => #<YeSQL::Config::Configuration:0x00007feea1aa2ef8 @path="app/yesql">
|
|
160
|
+
::YeSQL.config.path
|
|
161
|
+
# => "app/yesql"
|
|
163
162
|
```
|
|
164
163
|
|
|
165
164
|
|
|
@@ -167,7 +166,7 @@ Yesql.config.path
|
|
|
167
166
|
|
|
168
167
|
- Clone the repository.
|
|
169
168
|
- Install the gem dependencies.
|
|
170
|
-
- Make sure to create
|
|
169
|
+
- Make sure to create both databases used in the dummy Rails applications (mysql, pg) in the spec/ folder.
|
|
171
170
|
- Run the tests.
|
|
172
171
|
|
|
173
172
|
## Contributing
|
data/lib/yesql.rb
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'dry-configurable'
|
|
4
|
-
require 'pry'
|
|
5
3
|
require 'yesql/version'
|
|
4
|
+
require 'yesql/config/configuration'
|
|
6
5
|
require 'yesql/query/performer'
|
|
7
6
|
require 'yesql/errors/cache_expiration_error'
|
|
8
7
|
require 'yesql/errors/file_path_does_not_exist_error'
|
|
@@ -11,15 +10,12 @@ require 'yesql/errors/output_argument_error'
|
|
|
11
10
|
require 'yesql/bindings/binder'
|
|
12
11
|
|
|
13
12
|
module YeSQL
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
include ::YeSQL::Config
|
|
16
14
|
include ::YeSQL::Errors::CacheExpirationError
|
|
17
15
|
include ::YeSQL::Errors::FilePathDoesNotExistError
|
|
18
16
|
include ::YeSQL::Errors::NoBindingsProvidedError
|
|
19
17
|
include ::YeSQL::Errors::OutputArgumentError
|
|
20
18
|
|
|
21
|
-
setting :path, 'app/yesql'
|
|
22
|
-
|
|
23
19
|
BIND_REGEX = /(?<!:):(\w+)(?=\b)/.freeze
|
|
24
20
|
|
|
25
21
|
# rubocop:disable Naming/MethodName
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require 'yesql'
|
|
4
4
|
|
|
5
|
-
module YeSQL
|
|
5
|
+
module ::YeSQL
|
|
6
6
|
module Bindings
|
|
7
7
|
class Extract
|
|
8
|
+
include ::YeSQL::Common::Adapter
|
|
9
|
+
|
|
8
10
|
def initialize(indexed_bindings, hash, index, value)
|
|
9
11
|
@indexed_bindings = indexed_bindings
|
|
10
12
|
@hash = hash
|
|
@@ -19,9 +21,15 @@ module YeSQL
|
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def bind_vars
|
|
22
|
-
|
|
24
|
+
if mysql?
|
|
25
|
+
return '?' unless array?
|
|
26
|
+
|
|
27
|
+
Array.new(value.size, '?').join(', ')
|
|
28
|
+
elsif pg?
|
|
29
|
+
return "$#{last_val}" unless array?
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
value.map.with_index(bind_index) { |_, i| "$#{i}" }.join(', ')
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
|
|
27
35
|
def last_val
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yesql'
|
|
4
|
+
require 'yesql/common/adapter'
|
|
5
|
+
|
|
6
|
+
module ::YeSQL
|
|
7
|
+
module Bindings
|
|
8
|
+
class Transformed
|
|
9
|
+
include ::YeSQL::Common::Adapter
|
|
10
|
+
|
|
11
|
+
def initialize(statement_binds:)
|
|
12
|
+
@statement_binds = statement_binds
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
return mysql_rails5_binds if rails5? && mysql?
|
|
17
|
+
return mysql_binds if !rails5? && mysql?
|
|
18
|
+
|
|
19
|
+
pg_binds
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
attr_reader :statement_binds
|
|
25
|
+
|
|
26
|
+
def rails5?
|
|
27
|
+
::Rails::VERSION::MAJOR == 5
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def mysql_rails5_binds
|
|
31
|
+
statement_binds
|
|
32
|
+
.map(&:first)
|
|
33
|
+
.flatten(1)
|
|
34
|
+
.each_slice(2)
|
|
35
|
+
.flat_map do |first, last|
|
|
36
|
+
next [first, last].map(&:last) if first.is_a?(Array)
|
|
37
|
+
|
|
38
|
+
last
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def mysql_binds
|
|
43
|
+
statement_binds
|
|
44
|
+
.map(&:first)
|
|
45
|
+
.flatten
|
|
46
|
+
.each_slice(2)
|
|
47
|
+
.to_a
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def pg_binds
|
|
51
|
+
statement_binds
|
|
52
|
+
.sort_by { |_, position| position.to_s.tr('$', '').to_i }
|
|
53
|
+
.uniq
|
|
54
|
+
.map(&:first)
|
|
55
|
+
.flatten
|
|
56
|
+
.each_slice(2)
|
|
57
|
+
.to_a
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
module ::YeSQL
|
|
6
|
+
module Common
|
|
7
|
+
module Adapter
|
|
8
|
+
extend Forwardable
|
|
9
|
+
|
|
10
|
+
# `adapter` might be a complex object, but
|
|
11
|
+
# for the sake of brevity it's just a string
|
|
12
|
+
def adapter
|
|
13
|
+
::ActiveRecord::Base.connection.adapter_name
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def mysql?
|
|
17
|
+
adapter == 'Mysql2'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def pg?
|
|
21
|
+
adapter == 'PostgreSQL'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ::YeSQL
|
|
4
|
+
module Config
|
|
5
|
+
class Configuration
|
|
6
|
+
attr_accessor :path
|
|
7
|
+
|
|
8
|
+
DEFAULT_PATH = 'app/yesql'
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@path = DEFAULT_PATH
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def config
|
|
18
|
+
@config ||= ::YeSQL::Configuration.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def configure
|
|
22
|
+
yield config if block_given?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def reset_config
|
|
26
|
+
tap do |conf|
|
|
27
|
+
conf.configure do |configuration|
|
|
28
|
+
configuration.path = ::YeSQL::Configuration::DEFAULT_PATH
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yesql'
|
|
4
|
+
require 'forwardable'
|
|
5
|
+
|
|
6
|
+
module ::YeSQL
|
|
7
|
+
module Params
|
|
8
|
+
class Output
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
def initialize(output)
|
|
12
|
+
@output = output.to_s
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def columns?
|
|
16
|
+
output == 'columns'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def rows?
|
|
20
|
+
output == 'rows'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def hash?
|
|
24
|
+
output == 'hash'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def_delegator(:output, :to_sym)
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
attr_reader :output
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'yesql'
|
|
4
|
-
require 'forwardable'
|
|
5
4
|
require 'yesql/bindings/utils'
|
|
5
|
+
require 'yesql/common/adapter'
|
|
6
|
+
require 'yesql/bindings/transformed'
|
|
7
|
+
require 'yesql/query/result'
|
|
8
|
+
require 'yesql/query/transform_result'
|
|
9
|
+
require 'yesql/params/output'
|
|
6
10
|
|
|
7
11
|
module YeSQL
|
|
8
12
|
module Query
|
|
9
13
|
class Performer
|
|
10
|
-
extend Forwardable
|
|
11
|
-
|
|
12
14
|
include ::YeSQL::Bindings::Utils
|
|
13
15
|
|
|
14
16
|
# rubocop:disable Metrics/ParameterLists
|
|
@@ -21,11 +23,10 @@ module YeSQL
|
|
|
21
23
|
@bind_statement = bind_statement
|
|
22
24
|
@cache = cache
|
|
23
25
|
@cache_key = cache[:key] || file_path
|
|
24
|
-
@connection = ActiveRecord::Base.connection
|
|
25
26
|
@expires_in = cache[:expires_in]
|
|
26
27
|
@file_path = file_path
|
|
27
28
|
@named_bindings = bindings.transform_keys(&:to_sym)
|
|
28
|
-
@output = output
|
|
29
|
+
@output = ::YeSQL::Params::Output.new(output)
|
|
29
30
|
@prepare = prepare
|
|
30
31
|
end
|
|
31
32
|
# rubocop:enable Metrics/ParameterLists
|
|
@@ -41,7 +42,6 @@ module YeSQL
|
|
|
41
42
|
attr_reader :bind_statement,
|
|
42
43
|
:cache,
|
|
43
44
|
:cache_key,
|
|
44
|
-
:connection,
|
|
45
45
|
:expires_in,
|
|
46
46
|
:file_path,
|
|
47
47
|
:named_bindings,
|
|
@@ -49,32 +49,24 @@ module YeSQL
|
|
|
49
49
|
:prepare,
|
|
50
50
|
:rows
|
|
51
51
|
|
|
52
|
-
def_delegator(:query_result, :columns)
|
|
53
|
-
private :columns
|
|
54
|
-
def_delegator(:query_result, :rows)
|
|
55
|
-
private :rows
|
|
56
|
-
|
|
57
52
|
def modified_output
|
|
58
53
|
@modified_output ||=
|
|
59
|
-
|
|
60
|
-
return query_result.public_send(output) if %w[columns rows].include?(output.to_s)
|
|
61
|
-
|
|
62
|
-
columns.map(&:to_sym).tap { |cols| break rows.map { |row| cols.zip(row).to_h } }
|
|
63
|
-
end
|
|
54
|
+
::YeSQL::Query::TransformResult.new(output: output, result: query_result).call
|
|
64
55
|
end
|
|
65
56
|
|
|
66
57
|
def query_result
|
|
67
|
-
@query_result ||=
|
|
58
|
+
@query_result ||= ::YeSQL::Query::Result.new(binds: binds,
|
|
59
|
+
bind_statement: bind_statement,
|
|
60
|
+
file_path: file_path,
|
|
61
|
+
prepare: prepare).call
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def extractor
|
|
65
|
+
::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call
|
|
68
66
|
end
|
|
69
67
|
|
|
70
68
|
def binds
|
|
71
|
-
::YeSQL::Bindings::
|
|
72
|
-
break statement_binds(extractor).sort_by(&:last)
|
|
73
|
-
.map(&:first)
|
|
74
|
-
.flatten
|
|
75
|
-
.each_slice(2)
|
|
76
|
-
.to_a
|
|
77
|
-
end
|
|
69
|
+
::YeSQL::Bindings::Transformed.new(statement_binds: statement_binds(extractor)).call
|
|
78
70
|
end
|
|
79
71
|
end
|
|
80
72
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yesql'
|
|
4
|
+
require 'forwardable'
|
|
5
|
+
require 'yesql/common/adapter'
|
|
6
|
+
|
|
7
|
+
module ::YeSQL
|
|
8
|
+
module Query
|
|
9
|
+
class Result
|
|
10
|
+
extend Forwardable
|
|
11
|
+
|
|
12
|
+
include ::YeSQL::Common::Adapter
|
|
13
|
+
|
|
14
|
+
def initialize(binds:, bind_statement:, file_path:, prepare:)
|
|
15
|
+
@binds = binds
|
|
16
|
+
@bind_statement = bind_statement
|
|
17
|
+
@file_path = file_path
|
|
18
|
+
@prepare_option = prepare
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def call
|
|
22
|
+
return rails5_result if ::Rails::VERSION::MAJOR == 5 && mysql?
|
|
23
|
+
|
|
24
|
+
exec_query(bind_statement, file_path, binds, prepare: prepare_option)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :binds, :bind_statement, :file_path, :prepare_option
|
|
30
|
+
|
|
31
|
+
def_delegators(:connection, :exec_query, :raw_connection)
|
|
32
|
+
def_delegators(:raw_connection, :prepare)
|
|
33
|
+
|
|
34
|
+
def connection
|
|
35
|
+
ActiveRecord::Base.connection
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def rails5_result
|
|
39
|
+
prepare(bind_statement).execute(*binds)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yesql'
|
|
4
|
+
require 'forwardable'
|
|
5
|
+
|
|
6
|
+
module ::YeSQL
|
|
7
|
+
module Query
|
|
8
|
+
class TransformResult
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
def initialize(output:, result:)
|
|
12
|
+
@output = output
|
|
13
|
+
@result = result
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
if ::Rails::VERSION::MAJOR == 5
|
|
18
|
+
return columns if columns?
|
|
19
|
+
return rows_values if rows?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return result.public_send(output.to_sym) if columns? || rows?
|
|
23
|
+
|
|
24
|
+
array_of_symbol_hashes
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :output, :result
|
|
30
|
+
|
|
31
|
+
def_delegators(:result, :rows, :to_a)
|
|
32
|
+
def_delegators(:output, :columns?, :hash?, :rows?)
|
|
33
|
+
|
|
34
|
+
def rows_values
|
|
35
|
+
to_a.map { |e| e.respond_to?(:values) ? e.values : e }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def array_of_symbol_hashes
|
|
39
|
+
to_a.tap { |rows| break hashed_rows(rows) if ::Rails::VERSION::MAJOR == 5 }
|
|
40
|
+
.map { |e| e.respond_to?(:symbolize_keys) ? e.symbolize_keys : e }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def hashed_rows(rows)
|
|
44
|
+
rows.map { |row| columns.zip(row).to_h }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def columns
|
|
48
|
+
return result.fields if result.respond_to?(:fields)
|
|
49
|
+
|
|
50
|
+
result.columns
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/yesql/version.rb
CHANGED
data/yesql.gemspec
CHANGED
|
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
spec.bindir = 'exe'
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
22
22
|
spec.require_paths = ['lib']
|
|
23
|
-
spec.add_dependency 'dry-configurable', '~> 0.11.6'
|
|
24
23
|
spec.add_dependency 'rails', '>= 5.0'
|
|
24
|
+
spec.add_development_dependency 'mysql2', '~> 0.5.3'
|
|
25
25
|
spec.add_development_dependency 'pg', '>= 0.18'
|
|
26
26
|
spec.add_development_dependency 'pry', '~> 0.13.1'
|
|
27
27
|
spec.add_development_dependency 'rspec', '~> 3.9.0'
|
metadata
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yesql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sebastián Palma
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-10-
|
|
11
|
+
date: 2020-10-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: rails
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0
|
|
19
|
+
version: '5.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0
|
|
26
|
+
version: '5.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: mysql2
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
34
|
-
type: :
|
|
33
|
+
version: 0.5.3
|
|
34
|
+
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 0.5.3
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: pg
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -87,6 +87,8 @@ executables: []
|
|
|
87
87
|
extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
|
89
89
|
files:
|
|
90
|
+
- ".gitignore"
|
|
91
|
+
- ".rubocop.yml"
|
|
90
92
|
- Gemfile
|
|
91
93
|
- Gemfile.lock
|
|
92
94
|
- LICENSE.txt
|
|
@@ -98,12 +100,18 @@ files:
|
|
|
98
100
|
- lib/yesql/bindings/binder.rb
|
|
99
101
|
- lib/yesql/bindings/extract.rb
|
|
100
102
|
- lib/yesql/bindings/extractor.rb
|
|
103
|
+
- lib/yesql/bindings/transformed.rb
|
|
101
104
|
- lib/yesql/bindings/utils.rb
|
|
105
|
+
- lib/yesql/common/adapter.rb
|
|
106
|
+
- lib/yesql/config/configuration.rb
|
|
102
107
|
- lib/yesql/errors/cache_expiration_error.rb
|
|
103
108
|
- lib/yesql/errors/file_path_does_not_exist_error.rb
|
|
104
109
|
- lib/yesql/errors/no_bindings_provided_error.rb
|
|
105
110
|
- lib/yesql/errors/output_argument_error.rb
|
|
111
|
+
- lib/yesql/params/output.rb
|
|
106
112
|
- lib/yesql/query/performer.rb
|
|
113
|
+
- lib/yesql/query/result.rb
|
|
114
|
+
- lib/yesql/query/transform_result.rb
|
|
107
115
|
- lib/yesql/utils/read.rb
|
|
108
116
|
- lib/yesql/version.rb
|
|
109
117
|
- yesql.gemspec
|
|
@@ -114,7 +122,7 @@ metadata:
|
|
|
114
122
|
homepage_uri: https://github.com/sebastian-palma/yesql
|
|
115
123
|
source_code_uri: https://github.com/sebastian-palma/yesql
|
|
116
124
|
changelog_uri: https://github.com/sebastian-palma/yesql
|
|
117
|
-
post_install_message:
|
|
125
|
+
post_install_message:
|
|
118
126
|
rdoc_options: []
|
|
119
127
|
require_paths:
|
|
120
128
|
- lib
|
|
@@ -130,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
130
138
|
version: '0'
|
|
131
139
|
requirements: []
|
|
132
140
|
rubygems_version: 3.1.2
|
|
133
|
-
signing_key:
|
|
141
|
+
signing_key:
|
|
134
142
|
specification_version: 4
|
|
135
143
|
summary: Ruby library to use SQL
|
|
136
144
|
test_files: []
|