yesql 0.1.6 → 0.2.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: 8f432f23ac16148c7439ec096a55c142c9985c537d06ef5ded891fb3178d3bbf
4
- data.tar.gz: b5d82c03933a0401d4b24a3fd48f00ea3864adfb8566db7f73c518714784cc54
3
+ metadata.gz: d4cad8cd91b4afba6c7a8722f9f0dfd6092552d2f4ce735c6880425241122b43
4
+ data.tar.gz: b8be652b46ee03e081ec2d8bc3bcc2321e26e2b7fcd55dcbf2a2bb288ddac139
5
5
  SHA512:
6
- metadata.gz: '084397cf83aa10faf2d724a0be1c11548e36dd515932c4552498c130a96efb044ca5f498aa30d4ec9c002ea1f36c4ec3699bcd4e6e2db2313b0b56fab9da2ae5'
7
- data.tar.gz: 70a91ebc63c23cd5c653351e728fc9c93207fd2583b1b72629d63717ba8e105c86318b016110f3040fd681b176da4d80db2807c40b4859ac3192c1a160901572
6
+ metadata.gz: 4dc794c44484b4fcc8815fa866023c6cf5d2f4b82d4f2c45c6de7e86082eaa3ba838c55e750e3f2fd53b0312b4be699c7ddc900400c8445c377fd7c6d1139190
7
+ data.tar.gz: 88b860a5ce91655366f9d73336b522678a8f709938881e1ff150a13565b57cd12b65c753531ecfb886528d162405c36ca9036c1c3cba52a62aa2e3e3993e76fb
data/.gitignore CHANGED
@@ -2,3 +2,6 @@ spec/minimalpg/log/*
2
2
  spec/minimalmysql/log/*
3
3
  spec/minimalpg/db/*
4
4
  spec/minimalmysql/db/*
5
+
6
+ *.un~
7
+ *.swp
data/.rubocop.yml CHANGED
@@ -1,8 +1,20 @@
1
1
  require: rubocop-rspec
2
2
 
3
+ Metrics/BlockLength:
4
+ Exclude:
5
+ - spec/**/*_spec.rb
6
+ - spec/spec_helper.rb
7
+ - spec/yesql/shared/*
8
+
3
9
  RSpec/FilePath:
4
10
  Exclude:
5
11
  - spec/**/*_spec.rb
6
12
 
7
13
  RSpec/NestedGroups:
8
14
  Enabled: False
15
+
16
+ RSpec/ExampleLength:
17
+ Enabled: False
18
+
19
+ RSpec/BeforeAfterAll:
20
+ Enabled: False
data/Gemfile CHANGED
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source 'https://rubygems.org'
3
+ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
7
  group :docs do
8
- gem 'yard'
8
+ gem "yard"
9
9
  end
data/Gemfile.lock CHANGED
@@ -1,159 +1,55 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- yesql (0.1.5)
5
- rails (>= 5.0)
4
+ yesql (0.2.2)
5
+ activerecord (>= 4.0.0.beta1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- actioncable (6.0.3.4)
11
- actionpack (= 6.0.3.4)
12
- nio4r (~> 2.0)
13
- websocket-driver (>= 0.6.1)
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)
20
- mail (>= 2.7.1)
21
- actionmailer (6.0.3.4)
22
- actionpack (= 6.0.3.4)
23
- actionview (= 6.0.3.4)
24
- activejob (= 6.0.3.4)
25
- mail (~> 2.5, >= 2.5.4)
26
- rails-dom-testing (~> 2.0)
27
- actionpack (6.0.3.4)
28
- actionview (= 6.0.3.4)
29
- activesupport (= 6.0.3.4)
30
- rack (~> 2.0, >= 2.0.8)
31
- rack-test (>= 0.6.3)
32
- rails-dom-testing (~> 2.0)
33
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
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)
39
- nokogiri (>= 1.8.5)
40
- actionview (6.0.3.4)
41
- activesupport (= 6.0.3.4)
42
- builder (~> 3.1)
43
- erubi (~> 1.4)
44
- rails-dom-testing (~> 2.0)
45
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
46
- activejob (6.0.3.4)
47
- activesupport (= 6.0.3.4)
48
- globalid (>= 0.3.6)
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)
58
- marcel (~> 0.3.1)
59
- activesupport (6.0.3.4)
10
+ activemodel (6.1.3.1)
11
+ activesupport (= 6.1.3.1)
12
+ activerecord (6.1.3.1)
13
+ activemodel (= 6.1.3.1)
14
+ activesupport (= 6.1.3.1)
15
+ activesupport (6.1.3.1)
60
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
61
- i18n (>= 0.7, < 2)
62
- minitest (~> 5.1)
63
- tzinfo (~> 1.1)
64
- zeitwerk (~> 2.2, >= 2.2.2)
65
- builder (3.2.4)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
66
21
  coderay (1.1.3)
67
- concurrent-ruby (1.1.7)
68
- crass (1.0.6)
22
+ concurrent-ruby (1.1.8)
69
23
  diff-lcs (1.4.4)
70
- erubi (1.9.0)
71
- globalid (0.4.2)
72
- activesupport (>= 4.2.0)
73
- i18n (1.8.5)
24
+ i18n (1.8.10)
74
25
  concurrent-ruby (~> 1.0)
75
- loofah (2.7.0)
76
- crass (~> 1.0.2)
77
- nokogiri (>= 1.5.9)
78
- mail (2.7.1)
79
- mini_mime (>= 0.1.1)
80
- marcel (0.3.3)
81
- mimemagic (~> 0.3.2)
82
26
  method_source (1.0.0)
83
- mimemagic (0.3.5)
84
- mini_mime (1.0.2)
85
- mini_portile2 (2.4.0)
86
- minitest (5.14.2)
27
+ minitest (5.14.4)
87
28
  mysql2 (0.5.3)
88
- nio4r (2.5.4)
89
- nokogiri (1.10.10)
90
- mini_portile2 (~> 2.4.0)
91
29
  pg (1.2.3)
92
30
  pry (0.13.1)
93
31
  coderay (~> 1.1)
94
32
  method_source (~> 1.0)
95
- rack (2.2.3)
96
- rack-test (1.1.0)
97
- rack (>= 1.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)
110
- bundler (>= 1.3.0)
111
- railties (= 6.0.3.4)
112
- sprockets-rails (>= 2.0.0)
113
- rails-dom-testing (2.0.3)
114
- activesupport (>= 4.2.0)
115
- nokogiri (>= 1.6)
116
- rails-html-sanitizer (1.3.0)
117
- loofah (~> 2.3)
118
- railties (6.0.3.4)
119
- actionpack (= 6.0.3.4)
120
- activesupport (= 6.0.3.4)
121
- method_source
122
- rake (>= 0.8.7)
123
- thor (>= 0.20.3, < 2.0)
124
- rake (13.0.1)
125
33
  rspec (3.9.0)
126
34
  rspec-core (~> 3.9.0)
127
35
  rspec-expectations (~> 3.9.0)
128
36
  rspec-mocks (~> 3.9.0)
129
- rspec-core (3.9.2)
37
+ rspec-core (3.9.3)
130
38
  rspec-support (~> 3.9.3)
131
- rspec-expectations (3.9.2)
39
+ rspec-expectations (3.9.4)
132
40
  diff-lcs (>= 1.2.0, < 2.0)
133
41
  rspec-support (~> 3.9.0)
134
42
  rspec-mocks (3.9.1)
135
43
  diff-lcs (>= 1.2.0, < 2.0)
136
44
  rspec-support (~> 3.9.0)
137
- rspec-support (3.9.3)
138
- sprockets (4.0.2)
45
+ rspec-support (3.9.4)
46
+ tzinfo (2.0.4)
139
47
  concurrent-ruby (~> 1.0)
140
- rack (> 1, < 3)
141
- sprockets-rails (3.2.2)
142
- actionpack (>= 4.0)
143
- activesupport (>= 4.0)
144
- sprockets (>= 3.0.0)
145
- thor (1.0.1)
146
- thread_safe (0.3.6)
147
- tzinfo (1.2.7)
148
- thread_safe (~> 0.1)
149
- websocket-driver (0.7.3)
150
- websocket-extensions (>= 0.1.0)
151
- websocket-extensions (0.1.5)
152
- yard (0.9.25)
153
- zeitwerk (2.4.0)
48
+ yard (0.9.26)
49
+ zeitwerk (2.4.2)
154
50
 
155
51
  PLATFORMS
156
- ruby
52
+ x86_64-linux
157
53
 
158
54
  DEPENDENCIES
159
55
  mysql2 (~> 0.5.3)
@@ -164,4 +60,4 @@ DEPENDENCIES
164
60
  yesql!
165
61
 
166
62
  BUNDLED WITH
167
- 2.1.4
63
+ 2.2.3
data/README.md CHANGED
@@ -120,28 +120,6 @@ ActiveRecord::Base.connection.execute('SELECT * FROM pg_prepared_statements').to
120
120
  ```
121
121
 
122
122
 
123
- #### `cache`
124
-
125
- If you need to cache your query, you can use the `cache` option. `cache` must be a Hash containing __at least__ the `expires_in` key with an `ActiveSupport::Duration` object, e.g:
126
-
127
- ```ruby
128
- YeSQL('users', cache: { key: 'users', expires_in: 1.hour })
129
- ```
130
-
131
- That's enough to cache the result of the query for 1 hour with the cache key "users".
132
-
133
- If no `key` key/value is used, then the cache key is the name of the file containing the SQL code, and
134
-
135
- ```ruby
136
- YeSQL('users', cache: { key: 'users', expires_in: 1.hour })
137
- ```
138
-
139
- is the same as
140
-
141
- ```ruby
142
- YeSQL('users', cache: { expires_in: 1.hour })
143
- ```
144
-
145
123
  ## Configuration
146
124
 
147
125
  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:
@@ -173,6 +151,12 @@ You can check at anytime what's the configuration path by inspecting the ::YeSQL
173
151
 
174
152
  Bug reports and pull requests are welcome on GitHub at https://github.com/sebastian-palma/yesql. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/sebastian-palma/yesql/blob/master/CODE_OF_CONDUCT.md).
175
153
 
154
+ ## TODO
155
+
156
+ - [ ] Allow comments in .sql files.
157
+ - [ ] Improve errors.
158
+ - [ ] Auto convert `x IN (xs)` queries to `(x = x' OR x = x'')`.
159
+
176
160
 
177
161
  ## License
178
162
 
data/Rakefile CHANGED
@@ -1 +1,3 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require "standard/rake"
data/lib/yesql.rb CHANGED
@@ -1,47 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql/version'
4
- require 'yesql/config/configuration'
5
- require 'yesql/query/performer'
6
- require 'yesql/errors/cache_expiration_error'
7
- require 'yesql/errors/file_path_does_not_exist_error'
8
- require 'yesql/errors/no_bindings_provided_error'
9
- require 'yesql/errors/output_argument_error'
10
- require 'yesql/bindings/binder'
3
+ require "yesql/statement"
4
+ require "yesql/version"
5
+ require "yesql/config/configuration"
6
+ require "yesql/query/performer"
7
+ require "yesql/errors/file_path_does_not_exist_error"
8
+ require "yesql/errors/no_bindings_provided_error"
9
+ require "yesql/errors/output_argument_error"
11
10
 
12
11
  module YeSQL
13
12
  include ::YeSQL::Config
14
- include ::YeSQL::Errors::CacheExpirationError
15
13
  include ::YeSQL::Errors::FilePathDoesNotExistError
16
14
  include ::YeSQL::Errors::NoBindingsProvidedError
17
15
  include ::YeSQL::Errors::OutputArgumentError
18
16
 
19
- BIND_REGEX = /(?<!:):(\w+)(?=\b)/.freeze
17
+ BIND_REGEX = /(?<!:):(\w+)(?=\b)/
20
18
 
21
- # rubocop:disable Naming/MethodName
22
19
  def YeSQL(file_path, bindings = {}, options = {})
23
20
  output = options[:output] || :rows
24
- cache = options[:cache] || {}
25
21
 
26
- validate(bindings, cache, file_path, output)
27
- execute(bindings, cache, file_path, output, options)
22
+ validate(bindings, file_path, output)
23
+ execute(bindings, file_path, output, options)
28
24
  end
29
- # rubocop:enable Naming/MethodName
30
25
 
31
26
  private
32
27
 
33
- def validate(bindings, cache, file_path, output)
28
+ def validate(bindings, file_path, output)
34
29
  validate_file_path_existence(file_path)
35
30
  validate_statement_bindings(bindings, file_path)
36
31
  validate_output_options(output)
37
- validate_cache_expiration(cache[:expires_in]) unless cache.empty?
38
32
  end
39
33
 
40
- def execute(bindings, cache, file_path, output, options)
34
+ def execute(bindings, file_path, output, options)
41
35
  ::YeSQL::Query::Performer.new(
42
36
  bindings: bindings,
43
- bind_statement: ::YeSQL::Bindings::Binder.bind_statement(file_path, bindings),
44
- cache: cache,
37
+ bind_statement: ::YeSQL::Statement.new(bindings, file_path),
45
38
  file_path: file_path,
46
39
  output: output,
47
40
  prepare: options[:prepare]
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
3
+ require "yesql"
4
+ require "yesql/common/adapter"
4
5
 
5
6
  module ::YeSQL
6
7
  module Bindings
@@ -8,9 +9,9 @@ module ::YeSQL
8
9
  include ::YeSQL::Common::Adapter
9
10
 
10
11
  def initialize(indexed_bindings, hash, index, value)
11
- @indexed_bindings = indexed_bindings
12
12
  @hash = hash
13
13
  @index = index
14
+ @indexed_bindings = indexed_bindings
14
15
  @value = value
15
16
  end
16
17
 
@@ -22,13 +23,13 @@ module ::YeSQL
22
23
 
23
24
  def bind_vars
24
25
  if mysql?
25
- return '?' unless array?
26
+ return "?" unless array?
26
27
 
27
- Array.new(value.size, '?').join(', ')
28
+ Array.new(value.size, "?").join(", ")
28
29
  elsif pg?
29
30
  return "$#{last_val}" unless array?
30
31
 
31
- value.map.with_index(bind_index) { |_, i| "$#{i}" }.join(', ')
32
+ value.map.with_index(bind_index) { |_, i| "$#{i}" }.join(", ")
32
33
  end
33
34
  end
34
35
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql/bindings/extract'
3
+ require "yesql/bindings/extract"
4
4
 
5
5
  module YeSQL
6
6
  module Bindings
@@ -10,7 +10,6 @@ module YeSQL
10
10
  @indexed_bindings = (bindings || {}).to_a
11
11
  end
12
12
 
13
- # rubocop:disable Metrics/MethodLength
14
13
  def call
15
14
  bindings.each_with_object({}).with_index(1) do |((key, value), hash), index|
16
15
  hash[key] =
@@ -28,7 +27,6 @@ module YeSQL
28
27
  end
29
28
  end
30
29
  end
31
- # rubocop:enable Metrics/MethodLength
32
30
 
33
31
  private
34
32
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'yesql/common/adapter'
3
+ require "yesql"
4
+ require "yesql/common/adapter"
5
5
 
6
6
  module ::YeSQL
7
7
  module Bindings
@@ -24,16 +24,15 @@ module ::YeSQL
24
24
  attr_reader :statement_binds
25
25
 
26
26
  def rails5?
27
- ::Rails::VERSION::MAJOR == 5
27
+ ::ActiveRecord::VERSION::MAJOR == 5
28
28
  end
29
29
 
30
30
  def mysql_rails5_binds
31
31
  statement_binds
32
- .map(&:first)
33
- .flatten(1)
32
+ .flat_map(&:first)
34
33
  .each_slice(2)
35
34
  .flat_map do |first, last|
36
- next [first, last].map(&:last) if first.is_a?(Array)
35
+ next [first, last].compact.map(&:last) if first.is_a?(Array)
37
36
 
38
37
  last
39
38
  end
@@ -49,7 +48,7 @@ module ::YeSQL
49
48
 
50
49
  def pg_binds
51
50
  statement_binds
52
- .sort_by { |_, position| position.to_s.tr('$', '').to_i }
51
+ .sort_by { |_, position| position.to_s.tr("$", "").to_i }
53
52
  .uniq
54
53
  .map(&:first)
55
54
  .flatten
@@ -4,10 +4,11 @@ module YeSQL
4
4
  module Bindings
5
5
  module Utils
6
6
  def statement_binds(extractor)
7
- ::YeSQL::Utils::Read.statement(file_path, readable: true)
8
- .scan(::YeSQL::BIND_REGEX).map do |(bind)|
9
- extractor[bind.to_sym][:bind].values_at(:vals, :vars)
10
- end
7
+ ::YeSQL::Utils::Read
8
+ .statement(file_path, readable: true)
9
+ .scan(::YeSQL::BIND_REGEX).map do |(bind)|
10
+ extractor[bind.to_sym][:bind].values_at(:vals, :vars)
11
+ end
11
12
  end
12
13
  end
13
14
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
5
  module ::YeSQL
6
6
  module Common
7
7
  module Adapter
8
- extend Forwardable
8
+ extend ::Forwardable
9
9
 
10
10
  # `adapter` might be a complex object, but
11
11
  # for the sake of brevity it's just a string
@@ -14,11 +14,11 @@ module ::YeSQL
14
14
  end
15
15
 
16
16
  def mysql?
17
- adapter == 'Mysql2'
17
+ adapter == "Mysql2"
18
18
  end
19
19
 
20
20
  def pg?
21
- adapter == 'PostgreSQL'
21
+ adapter == "PostgreSQL"
22
22
  end
23
23
  end
24
24
  end
@@ -3,11 +3,12 @@
3
3
  module ::YeSQL
4
4
  module Config
5
5
  class Configuration
6
- attr_accessor :path
6
+ attr_accessor :connection, :path
7
7
 
8
- DEFAULT_PATH = 'app/yesql'
8
+ DEFAULT_PATH = "app/yesql"
9
9
 
10
10
  def initialize
11
+ @connection = ""
11
12
  @path = DEFAULT_PATH
12
13
  end
13
14
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YeSQL
3
+ require "yesql/utils/read"
4
+
5
+ module ::YeSQL
4
6
  module Errors
5
7
  module NoBindingsProvidedError
6
8
  def validate_statement_bindings(binds, file_path)
7
9
  return unless statement_binds(file_path).size.positive?
8
10
 
9
11
  format(MESSAGE, renderable_statement_binds(file_path)).tap do |message|
10
- raise ArgumentError, message unless binds.is_a?(Hash) && !binds.empty?
12
+ raise ::ArgumentError, message unless binds.is_a?(::Hash) && !binds.empty?
11
13
  end
12
14
  end
13
15
 
@@ -25,7 +27,7 @@ module YeSQL
25
27
 
26
28
  def statement_binds(file_path)
27
29
  ::YeSQL::Utils::Read.statement(file_path)
28
- .scan(::YeSQL::BIND_REGEX).tap do |scanned_binds|
30
+ .scan(::YeSQL::BIND_REGEX).tap do |scanned_binds|
29
31
  break [] if scanned_binds.size.zero?
30
32
 
31
33
  break scanned_binds.sort
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'forwardable'
3
+ require "yesql"
4
+ require "forwardable"
5
5
 
6
6
  module ::YeSQL
7
7
  module Params
@@ -13,15 +13,15 @@ module ::YeSQL
13
13
  end
14
14
 
15
15
  def columns?
16
- output == 'columns'
16
+ output == "columns"
17
17
  end
18
18
 
19
19
  def rows?
20
- output == 'rows'
20
+ output == "rows"
21
21
  end
22
22
 
23
23
  def hash?
24
- output == 'hash'
24
+ output == "hash"
25
25
  end
26
26
 
27
27
  def_delegator(:output, :to_sym)
@@ -1,58 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
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'
3
+ require "yesql"
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"
10
10
 
11
11
  module YeSQL
12
12
  module Query
13
13
  class Performer
14
14
  include ::YeSQL::Bindings::Utils
15
15
 
16
- # rubocop:disable Metrics/ParameterLists
17
- def initialize(bind_statement:,
18
- bindings: {},
19
- cache: {},
20
- file_path:,
21
- output: :rows,
22
- prepare: false)
16
+ def initialize(bind_statement:, file_path:, bindings: {}, output: :rows, prepare: false)
23
17
  @bind_statement = bind_statement
24
- @cache = cache
25
- @cache_key = cache[:key] || file_path
26
- @expires_in = cache[:expires_in]
27
18
  @file_path = file_path
28
19
  @named_bindings = bindings.transform_keys(&:to_sym)
29
20
  @output = ::YeSQL::Params::Output.new(output)
30
21
  @prepare = prepare
31
22
  end
32
- # rubocop:enable Metrics/ParameterLists
33
23
 
34
24
  def call
35
- return modified_output if cache.empty?
36
-
37
- Rails.cache.fetch(cache_key, expires_in: expires_in) { modified_output }
25
+ ::YeSQL::Query::TransformResult.new(output: output, result: query_result).call
38
26
  end
39
27
 
40
28
  private
41
29
 
42
- attr_reader :bind_statement,
43
- :cache,
44
- :cache_key,
45
- :expires_in,
46
- :file_path,
47
- :named_bindings,
48
- :output,
49
- :prepare,
50
- :rows
51
-
52
- def modified_output
53
- @modified_output ||=
54
- ::YeSQL::Query::TransformResult.new(output: output, result: query_result).call
55
- end
30
+ attr_reader :bind_statement, :file_path, :named_bindings, :output, :prepare, :rows
56
31
 
57
32
  def query_result
58
33
  @query_result ||= ::YeSQL::Query::Result.new(binds: binds,
@@ -61,13 +36,13 @@ module YeSQL
61
36
  prepare: prepare).call
62
37
  end
63
38
 
64
- def extractor
65
- ::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call
66
- end
67
-
68
39
  def binds
69
40
  ::YeSQL::Bindings::Transformed.new(statement_binds: statement_binds(extractor)).call
70
41
  end
42
+
43
+ def extractor
44
+ ::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call
45
+ end
71
46
  end
72
47
  end
73
48
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'forwardable'
5
- require 'yesql/common/adapter'
3
+ require "yesql"
4
+ require "forwardable"
5
+ require "yesql/common/adapter"
6
6
 
7
7
  module ::YeSQL
8
8
  module Query
@@ -11,32 +11,36 @@ module ::YeSQL
11
11
 
12
12
  include ::YeSQL::Common::Adapter
13
13
 
14
- def initialize(binds:, bind_statement:, file_path:, prepare:)
14
+ def initialize(bind_statement:, file_path:, prepare:, binds: [])
15
15
  @binds = binds
16
16
  @bind_statement = bind_statement
17
+ @connection = ActiveRecord::Base.connection
17
18
  @file_path = file_path
18
19
  @prepare_option = prepare
19
20
  end
20
21
 
21
22
  def call
22
- return rails5_result if ::Rails::VERSION::MAJOR == 5 && mysql?
23
+ return view_result if view?
24
+ return rails5_result if ::ActiveRecord::VERSION::MAJOR == 5 && mysql?
23
25
 
24
- exec_query(bind_statement, file_path, binds, prepare: prepare_option)
26
+ exec_query(bound, file_path, binds, prepare: prepare_option)
25
27
  end
26
28
 
27
29
  private
28
30
 
29
- attr_reader :binds, :bind_statement, :file_path, :prepare_option
31
+ attr_reader :binds, :bind_statement, :connection, :file_path, :prepare_option
30
32
 
33
+ def_delegators(:bind_statement, :bound, :to_s, :view?)
31
34
  def_delegators(:connection, :exec_query, :raw_connection)
32
35
  def_delegators(:raw_connection, :prepare)
33
36
 
34
- def connection
35
- ActiveRecord::Base.connection
37
+ def view_result
38
+ exec_query(bound)
36
39
  end
37
40
 
41
+ # TODO: recheck this case
38
42
  def rails5_result
39
- prepare(bind_statement).execute(*binds)
43
+ prepare(bound).execute(*binds)
40
44
  end
41
45
  end
42
46
  end
@@ -1,27 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'forwardable'
3
+ require "yesql"
4
+ require "yesql/common/adapter"
5
+ require "forwardable"
5
6
 
6
7
  module ::YeSQL
7
8
  module Query
8
9
  class TransformResult
9
10
  extend Forwardable
10
11
 
12
+ include ::YeSQL::Common::Adapter
13
+
11
14
  def initialize(output:, result:)
12
15
  @output = output
13
16
  @result = result
14
17
  end
15
18
 
16
19
  def call
17
- if ::Rails::VERSION::MAJOR == 5
20
+ if ::ActiveRecord::VERSION::MAJOR == 5 && mysql?
18
21
  return columns if columns?
19
22
  return rows_values if rows?
23
+ return array_of_symbol_hashes if hash?
20
24
  end
21
25
 
22
26
  return result.public_send(output.to_sym) if columns? || rows?
23
27
 
24
- array_of_symbol_hashes
28
+ to_a.map(&:symbolize_keys)
25
29
  end
26
30
 
27
31
  private
@@ -36,8 +40,9 @@ module ::YeSQL
36
40
  end
37
41
 
38
42
  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 }
43
+ to_a
44
+ .tap { |rows| break hashed_rows(rows) if ::ActiveRecord::VERSION::MAJOR == 5 }
45
+ .map { |e| e.respond_to?(:symbolize_keys) ? e.symbolize_keys : e }
41
46
  end
42
47
 
43
48
  def hashed_rows(rows)
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ require "forwardable"
6
+
7
+ require "yesql/utils/read"
8
+ require "yesql/bindings/extractor"
9
+ require "yesql/common/adapter"
10
+
11
+ module ::YeSQL
12
+ class Statement
13
+ extend ::Forwardable
14
+
15
+ include ::YeSQL::Common::Adapter
16
+ # Give access to the quote method.
17
+ include ::ActiveRecord::ConnectionAdapters::Quoting
18
+
19
+ def initialize(bindings = {}, file_path)
20
+ @bindings = bindings
21
+ @file_path = file_path
22
+ end
23
+
24
+ def bound
25
+ to_s.gsub(::YeSQL::BIND_REGEX) do |match|
26
+ extractor[match[/(\w+)/].to_sym].tap do |extract|
27
+ break quote(extract[:value]) if view?
28
+
29
+ break extract[:bind][:vars]
30
+ end
31
+ end
32
+ end
33
+
34
+ def to_s
35
+ @to_s ||= ::YeSQL::Utils::Read.statement(file_path, readable: true)
36
+ end
37
+
38
+ def view?
39
+ to_s =~ /^create\s.*view\s/i
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :bindings, :file_path
45
+
46
+ def extractor
47
+ ::YeSQL::Bindings::Extractor.new(bindings: bindings).call
48
+ end
49
+ end
50
+ end
@@ -7,7 +7,7 @@ module YeSQL
7
7
  Dir["./#{::YeSQL.config.path}/**/*.sql"]
8
8
  .find { |dir_file_path| dir_file_path.include?("#{file_path}.sql") }
9
9
  .tap do |sql_file_path|
10
- break File.readlines(sql_file_path, chomp: true).join(' ') if readable == true
10
+ break File.readlines(sql_file_path, chomp: true).join(" ") if readable == true
11
11
 
12
12
  break File.read(sql_file_path)
13
13
  end
data/lib/yesql/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YeSQL
4
- VERSION = '0.1.6'
4
+ VERSION = "0.2.2"
5
5
  end
data/yesql.gemspec CHANGED
@@ -1,28 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/yesql/version'
3
+ require_relative "lib/yesql/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'yesql'
6
+ spec.name = "yesql"
7
7
  spec.version = YeSQL::VERSION
8
- spec.authors = ['Sebastián Palma']
9
- spec.email = ['vnhnhm.github@gmail.com']
10
- spec.summary = 'Ruby library to use SQL'
8
+ spec.authors = ["Sebastián Palma"]
9
+ spec.email = ["vnhnhm.github@gmail.com"]
10
+ spec.summary = "Ruby library to use SQL"
11
11
  spec.description = 'SQL "raw" for Rails projects'
12
- spec.homepage = 'https://github.com/sebastian-palma/yesql'
13
- spec.license = 'MIT'
14
- spec.metadata['homepage_uri'] = spec.homepage
15
- spec.metadata['source_code_uri'] = 'https://github.com/sebastian-palma/yesql'
16
- spec.metadata['changelog_uri'] = 'https://github.com/sebastian-palma/yesql'
12
+ spec.homepage = "https://github.com/sebastian-palma/yesql"
13
+ spec.license = "MIT"
14
+ spec.metadata["homepage_uri"] = spec.homepage
15
+ spec.metadata["source_code_uri"] = "https://github.com/sebastian-palma/yesql"
16
+ spec.metadata["changelog_uri"] = "https://github.com/sebastian-palma/yesql"
17
17
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
18
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
19
  end
20
- spec.bindir = 'exe'
20
+ spec.bindir = "exe"
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ['lib']
23
- spec.add_dependency 'rails', '>= 5.0'
24
- spec.add_development_dependency 'mysql2', '~> 0.5.3'
25
- spec.add_development_dependency 'pg', '>= 0.18'
26
- spec.add_development_dependency 'pry', '~> 0.13.1'
27
- spec.add_development_dependency 'rspec', '~> 3.9.0'
22
+ spec.require_paths = ["lib"]
23
+ spec.add_dependency "activerecord", ">= 4.0.0.beta1"
24
+ spec.add_development_dependency "mysql2", "~> 0.5.3"
25
+ spec.add_development_dependency "pg", ">= 0.18"
26
+ spec.add_development_dependency "pry", "~> 0.13.1"
27
+ spec.add_development_dependency "rspec", "~> 3.9.0"
28
28
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yesql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.2
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-26 00:00:00.000000000 Z
11
+ date: 2021-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5.0'
19
+ version: 4.0.0.beta1
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: '5.0'
26
+ version: 4.0.0.beta1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: mysql2
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -97,14 +97,12 @@ files:
97
97
  - bin/console
98
98
  - bin/setup
99
99
  - lib/yesql.rb
100
- - lib/yesql/bindings/binder.rb
101
100
  - lib/yesql/bindings/extract.rb
102
101
  - lib/yesql/bindings/extractor.rb
103
102
  - lib/yesql/bindings/transformed.rb
104
103
  - lib/yesql/bindings/utils.rb
105
104
  - lib/yesql/common/adapter.rb
106
105
  - lib/yesql/config/configuration.rb
107
- - lib/yesql/errors/cache_expiration_error.rb
108
106
  - lib/yesql/errors/file_path_does_not_exist_error.rb
109
107
  - lib/yesql/errors/no_bindings_provided_error.rb
110
108
  - lib/yesql/errors/output_argument_error.rb
@@ -112,6 +110,7 @@ files:
112
110
  - lib/yesql/query/performer.rb
113
111
  - lib/yesql/query/result.rb
114
112
  - lib/yesql/query/transform_result.rb
113
+ - lib/yesql/statement.rb
115
114
  - lib/yesql/utils/read.rb
116
115
  - lib/yesql/version.rb
117
116
  - yesql.gemspec
@@ -122,7 +121,7 @@ metadata:
122
121
  homepage_uri: https://github.com/sebastian-palma/yesql
123
122
  source_code_uri: https://github.com/sebastian-palma/yesql
124
123
  changelog_uri: https://github.com/sebastian-palma/yesql
125
- post_install_message:
124
+ post_install_message:
126
125
  rdoc_options: []
127
126
  require_paths:
128
127
  - lib
@@ -137,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
136
  - !ruby/object:Gem::Version
138
137
  version: '0'
139
138
  requirements: []
140
- rubygems_version: 3.1.2
141
- signing_key:
139
+ rubygems_version: 3.2.3
140
+ signing_key:
142
141
  specification_version: 4
143
142
  summary: Ruby library to use SQL
144
143
  test_files: []
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yesql/utils/read'
4
- require 'yesql/bindings/extractor'
5
-
6
- module YeSQL
7
- module Bindings
8
- class Binder
9
- def self.bind_statement(file_path, bindings)
10
- ::YeSQL::Bindings::Extractor.new(bindings: bindings).call.tap do |extractor|
11
- break ::YeSQL::Utils::Read.statement(file_path, readable: true)
12
- .gsub(::YeSQL::BIND_REGEX) do |match|
13
- extractor[match[/(\w+)/].to_sym][:bind][:vars]
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YeSQL
4
- module Errors
5
- module CacheExpirationError
6
- def validate_cache_expiration(expires_in)
7
- raise ArgumentError, MESSAGE unless expires_in.is_a?(ActiveSupport::Duration)
8
- end
9
-
10
- MESSAGE = <<~MSG
11
- Missing mandatory `expires_in` option for `cache`.
12
-
13
- Can not cache the result of the query without an expiration date.
14
- MSG
15
- private_constant :MESSAGE
16
- end
17
- end
18
- end