yesql 0.2.1 → 0.2.2

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 +7 -0
  3. data/.rubocop.yml +20 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +63 -0
  6. data/Rakefile +3 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/lib/yesql.rb +15 -17
  10. data/lib/yesql/bindings/extract.rb +17 -11
  11. data/lib/yesql/bindings/extractor.rb +18 -20
  12. data/lib/yesql/bindings/transformed.rb +7 -5
  13. data/lib/yesql/bindings/utils.rb +6 -7
  14. data/lib/yesql/common/adapter.rb +11 -4
  15. data/lib/yesql/config/configuration.rb +3 -1
  16. data/lib/yesql/errors/file_path_does_not_exist_error.rb +17 -22
  17. data/lib/yesql/errors/no_bindings_provided_error.rb +18 -17
  18. data/lib/yesql/errors/output_argument_error.rb +4 -13
  19. data/lib/yesql/params/output.rb +12 -4
  20. data/lib/yesql/query/performer.rb +8 -4
  21. data/lib/yesql/query/result.rb +11 -5
  22. data/lib/yesql/query/transform_result.rb +19 -8
  23. data/lib/yesql/statement.rb +16 -10
  24. data/lib/yesql/utils/read.rb +8 -11
  25. data/lib/yesql/version.rb +1 -1
  26. data/yesql.gemspec +28 -0
  27. metadata +9 -54
  28. data/lib/.rbnext/2.3/yesql/errors/file_path_does_not_exist_error.rb +0 -40
  29. data/lib/.rbnext/2.3/yesql/errors/no_bindings_provided_error.rb +0 -38
  30. data/lib/.rbnext/2.3/yesql/errors/output_argument_error.rb +0 -31
  31. data/lib/.rbnext/2.3/yesql/query/transform_result.rb +0 -48
  32. data/lib/.rbnext/2.7/yesql/bindings/extract.rb +0 -71
  33. data/lib/.rbnext/2.7/yesql/bindings/extractor.rb +0 -38
  34. data/lib/.rbnext/2.7/yesql/bindings/transformed.rb +0 -58
  35. data/lib/.rbnext/2.7/yesql/bindings/utils.rb +0 -16
  36. data/lib/.rbnext/2.7/yesql/errors/file_path_does_not_exist_error.rb +0 -43
  37. data/lib/.rbnext/2.7/yesql/errors/no_bindings_provided_error.rb +0 -41
  38. data/lib/.rbnext/2.7/yesql/query/transform_result.rb +0 -48
  39. data/lib/.rbnext/2.7/yesql/statement.rb +0 -44
  40. data/lib/.rbnext/2.7/yesql/utils/read.rb +0 -20
  41. data/lib/.rbnext/3.0/yesql/bindings/extract.rb +0 -71
  42. data/lib/.rbnext/3.0/yesql/bindings/transformed.rb +0 -58
  43. data/lib/.rbnext/3.0/yesql/common/adapter.rb +0 -18
  44. data/lib/.rbnext/3.0/yesql/config/configuration.rb +0 -32
  45. data/lib/.rbnext/3.0/yesql/errors/file_path_does_not_exist_error.rb +0 -43
  46. data/lib/.rbnext/3.0/yesql/errors/no_bindings_provided_error.rb +0 -41
  47. data/lib/.rbnext/3.0/yesql/params/output.rb +0 -26
  48. data/lib/.rbnext/3.0/yesql/query/performer.rb +0 -44
  49. data/lib/.rbnext/3.0/yesql/query/result.rb +0 -41
  50. data/lib/.rbnext/3.0/yesql/query/transform_result.rb +0 -48
  51. data/lib/.rbnext/3.0/yesql/statement.rb +0 -44
  52. data/lib/.rbnext/3.0/yesql/utils/read.rb +0 -20
@@ -1,44 +0,0 @@
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
- include ::YeSQL::Utils::Read
17
- # Give access to the quote method.
18
- include ::ActiveRecord::ConnectionAdapters::Quoting
19
-
20
- def initialize(bindings = {}, file_path)
21
- @bindings = bindings
22
- @file_path = file_path
23
- end
24
-
25
- def bound
26
- to_s.gsub(::YeSQL::BIND_REGEX) { |_1| extract_bind_values(extractor[_1[/(\w+)/].to_sym]) }
27
- end
28
-
29
- def to_s ; @to_s ||= statement(readable: true); end
30
- def view? ; to_s =~ /^create\s.*view\s/i; end
31
-
32
- private
33
-
34
- attr_reader :bindings, :file_path
35
-
36
- def extract_bind_values(match)
37
- return quote(match[:value]) if view?
38
-
39
- match[:bind][:vars]
40
- end
41
-
42
- def extractor ; @extractor ||= ::YeSQL::Bindings::Extractor.new(bindings: bindings).call; end
43
- end
44
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ::YeSQL
4
- module Utils
5
- module Read
6
- def statement(readable: false) ; read_file(found_file, readable); end
7
-
8
- private
9
-
10
- def read_file(file, readable)
11
- return File.readlines(file, chomp: true).join(" ") if readable == true
12
-
13
- File.read(file)
14
- end
15
-
16
- def found_file ; dir_sql_files.find { |_1| _1.include?("#{file_path}.sql") }; end
17
- def dir_sql_files ; Dir["./#{::YeSQL.config.path}/**/*.sql"]; end
18
- end
19
- end
20
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "yesql"
4
- require "yesql/common/adapter"
5
-
6
- module ::YeSQL
7
- module Bindings
8
- class Extract
9
- include ::YeSQL::Common::Adapter
10
-
11
- def initialize(hash, indexed_bindings, index, value)
12
- @hash = hash
13
- @index = index
14
- @indexed_bindings = indexed_bindings
15
- @value = value
16
- end
17
-
18
- def bind_vals
19
- return [nil, value] unless array?
20
-
21
- value.map { [nil, _1] }
22
- end
23
-
24
- def bind_vars
25
- if mysql?
26
- return "?" unless array?
27
-
28
- Array.new(size, "?").join(", ")
29
- elsif pg?
30
- return "$#{last_val}" unless array?
31
-
32
- value.map.with_index(bind_index) { "$#{_2}" }.join(", ")
33
- end
34
- end
35
-
36
- def prev
37
- return if first?
38
-
39
- indexed_bindings[index - 2].first
40
- end
41
-
42
- def last_val ; prev_last_val + current_val_size; end
43
-
44
- private
45
-
46
- attr_reader :hash, :index, :indexed_bindings, :value
47
-
48
- def current_val_size
49
- return size if array?
50
-
51
- 1
52
- end
53
-
54
- def prev_last_val
55
- return 0 if first?
56
-
57
- hash[prev][:last_val]
58
- end
59
-
60
- def bind_index
61
- return 1 if first?
62
-
63
- prev_last_val + 1
64
- end
65
-
66
- def size ; value.size; end
67
- def first? ; index == 1; end
68
- def array? ; value.is_a?(Array); end
69
- end
70
- end
71
- end
@@ -1,58 +0,0 @@
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? ; ::ActiveRecord::VERSION::MAJOR == 5; end
27
-
28
- def mysql_rails5_binds
29
- statement_binds
30
- .flat_map(&:first)
31
- .each_slice(2)
32
- .flat_map do
33
- next [_1, _2].compact.map(&:last) if _1.is_a?(Array)
34
-
35
- _2
36
- end
37
- end
38
-
39
- def mysql_binds
40
- statement_binds
41
- .map(&:first)
42
- .flatten
43
- .each_slice(2)
44
- .to_a
45
- end
46
-
47
- def pg_binds
48
- statement_binds
49
- .sort_by { _2.to_s.tr("$", "").to_i }
50
- .uniq
51
- .map(&:first)
52
- .flatten
53
- .each_slice(2)
54
- .to_a
55
- end
56
- end
57
- end
58
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "forwardable"
4
-
5
- module ::YeSQL
6
- module Common
7
- module Adapter
8
- extend ::Forwardable
9
-
10
- def mysql? ; adapter == "Mysql2"; end
11
- def pg? ; adapter == "PostgreSQL"; end
12
-
13
- private
14
-
15
- def adapter ; ::ActiveRecord::Base.connection.adapter_name; end
16
- end
17
- end
18
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ::YeSQL
4
- module Config
5
- class Configuration
6
- attr_accessor :connection, :path
7
-
8
- DEFAULT_PATH = "app/yesql"
9
-
10
- def initialize
11
- @connection = ""
12
- @path = DEFAULT_PATH
13
- end
14
- end
15
- end
16
-
17
- class << self
18
- def config ; @config ||= ::YeSQL::Configuration.new; end
19
-
20
- def configure
21
- yield config if block_given?
22
- end
23
-
24
- def reset_config
25
- tap do |conf|
26
- conf.configure do |configuration|
27
- configuration.path = ::YeSQL::Configuration::DEFAULT_PATH
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ::YeSQL
4
- module Errors
5
- class FilePathDoesNotExistError
6
- def initialize(file_path)
7
- @file_path = file_path
8
- end
9
-
10
- def validate_file_path_existence
11
- return if file_exists?
12
-
13
- raise(
14
- ::NotImplementedError,
15
- format(
16
- MESSAGE,
17
- available_files: available_files,
18
- file_path: file_path,
19
- path: ::YeSQL.config.path
20
- )
21
- )
22
- end
23
-
24
- private
25
-
26
- attr_reader :file_path
27
-
28
- MESSAGE = <<~MSG
29
-
30
- SQL file "%<file_path>s" does not exist in %<path>s.
31
-
32
- Available SQL files are:
33
-
34
- %<available_files>s
35
- MSG
36
- private_constant :MESSAGE
37
-
38
- def file_exists? ; path_files.any? { _1.include?("#{file_path}.sql") }; end
39
- def path_files ; @path_files ||= Dir["#{::YeSQL.config.path}/**/*.sql"]; end
40
- def available_files ; path_files.map { "- #{_1}\n" }.join; end
41
- end
42
- end
43
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "yesql/utils/read"
4
-
5
- module ::YeSQL
6
- module Errors
7
- class NoBindingsProvidedError
8
- include ::YeSQL::Utils::Read
9
-
10
- def initialize(binds, file_path)
11
- @binds = binds
12
- @file_path = file_path
13
- end
14
-
15
- def validate_statement_bindings
16
- return unless statement_binds.size.positive?
17
- return if expected_binds?
18
-
19
- raise ::ArgumentError, format(MESSAGE, renderable_statement_binds)
20
- end
21
-
22
- private
23
-
24
- attr_reader :binds, :file_path
25
-
26
- MESSAGE = <<~MSG
27
-
28
- YeSQL invoked without bindings.
29
-
30
- Expected bindings are:
31
-
32
- %s
33
- MSG
34
- private_constant :MESSAGE
35
-
36
- def statement_binds ; statement.scan(::YeSQL::BIND_REGEX).tap { break (_1 || []).sort }; end
37
- def renderable_statement_binds ; statement_binds.flatten.map { "- `#{_1}`\n" }.join; end
38
- def expected_binds? ; binds.is_a?(::Hash) && !binds.empty?; end
39
- end
40
- end
41
- end
@@ -1,26 +0,0 @@
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? ; output == "columns"; end
16
- def rows? ; output == "rows"; end
17
- def hash? ; output == "hash"; end
18
-
19
- def_delegator(:output, :to_sym)
20
-
21
- private
22
-
23
- attr_reader :output
24
- end
25
- end
26
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
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"
10
-
11
- module ::YeSQL
12
- module Query
13
- class Performer
14
- include ::YeSQL::Bindings::Utils
15
-
16
- def initialize(bind_statement:, file_path:, bindings: {}, output: :rows, prepare: false)
17
- @bind_statement = bind_statement
18
- @file_path = file_path
19
- @named_bindings = bindings.transform_keys(&:to_sym)
20
- @output = ::YeSQL::Params::Output.new(output)
21
- @prepare = prepare
22
- end
23
-
24
- def call ; ::YeSQL::Query::TransformResult.new(output: output, result: query_result).call; end
25
-
26
- private
27
-
28
- attr_reader :bind_statement, :file_path, :named_bindings, :output, :prepare
29
-
30
- def query_result
31
- @query_result ||= ::YeSQL::Query::Result.new(binds: binds,
32
- bind_statement: bind_statement,
33
- file_path: file_path,
34
- prepare: prepare).call
35
- end
36
-
37
- def binds
38
- ::YeSQL::Bindings::Transformed.new(statement_binds: statement_binds(extractor)).call
39
- end
40
-
41
- def extractor ; ::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call; end
42
- end
43
- end
44
- end
@@ -1,41 +0,0 @@
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(bind_statement:, file_path:, prepare:, binds: [])
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 view_result if view?
23
- return rails5_result if ::ActiveRecord::VERSION::MAJOR == 5 && mysql?
24
-
25
- exec_query(bound, file_path, binds, prepare: prepare_option)
26
- end
27
-
28
- private
29
-
30
- attr_reader :binds, :bind_statement, :file_path, :prepare_option
31
-
32
- def_delegators(:bind_statement, :bound, :to_s, :view?)
33
- def_delegators(:connection, :exec_query, :raw_connection)
34
- def_delegators(:raw_connection, :prepare)
35
-
36
- def view_result ; exec_query(bound); end
37
- def rails5_result ; prepare(bound).execute(*binds); end
38
- def connection ; @connection ||= ActiveRecord::Base.connection; end
39
- end
40
- end
41
- end