yesql 0.2.1 → 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 +4 -4
- data/.gitignore +7 -0
- data/.rubocop.yml +20 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +63 -0
- data/Rakefile +3 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/yesql.rb +15 -17
- data/lib/yesql/bindings/extract.rb +17 -11
- data/lib/yesql/bindings/extractor.rb +18 -20
- data/lib/yesql/bindings/transformed.rb +7 -5
- data/lib/yesql/bindings/utils.rb +6 -7
- data/lib/yesql/common/adapter.rb +11 -4
- data/lib/yesql/config/configuration.rb +3 -1
- data/lib/yesql/errors/file_path_does_not_exist_error.rb +17 -22
- data/lib/yesql/errors/no_bindings_provided_error.rb +18 -17
- data/lib/yesql/errors/output_argument_error.rb +4 -13
- data/lib/yesql/params/output.rb +12 -4
- data/lib/yesql/query/performer.rb +8 -4
- data/lib/yesql/query/result.rb +11 -5
- data/lib/yesql/query/transform_result.rb +19 -8
- data/lib/yesql/statement.rb +16 -10
- data/lib/yesql/utils/read.rb +8 -11
- data/lib/yesql/version.rb +1 -1
- data/yesql.gemspec +28 -0
- metadata +9 -54
- data/lib/.rbnext/2.3/yesql/errors/file_path_does_not_exist_error.rb +0 -40
- data/lib/.rbnext/2.3/yesql/errors/no_bindings_provided_error.rb +0 -38
- data/lib/.rbnext/2.3/yesql/errors/output_argument_error.rb +0 -31
- data/lib/.rbnext/2.3/yesql/query/transform_result.rb +0 -48
- data/lib/.rbnext/2.7/yesql/bindings/extract.rb +0 -71
- data/lib/.rbnext/2.7/yesql/bindings/extractor.rb +0 -38
- data/lib/.rbnext/2.7/yesql/bindings/transformed.rb +0 -58
- data/lib/.rbnext/2.7/yesql/bindings/utils.rb +0 -16
- data/lib/.rbnext/2.7/yesql/errors/file_path_does_not_exist_error.rb +0 -43
- data/lib/.rbnext/2.7/yesql/errors/no_bindings_provided_error.rb +0 -41
- data/lib/.rbnext/2.7/yesql/query/transform_result.rb +0 -48
- data/lib/.rbnext/2.7/yesql/statement.rb +0 -44
- data/lib/.rbnext/2.7/yesql/utils/read.rb +0 -20
- data/lib/.rbnext/3.0/yesql/bindings/extract.rb +0 -71
- data/lib/.rbnext/3.0/yesql/bindings/transformed.rb +0 -58
- data/lib/.rbnext/3.0/yesql/common/adapter.rb +0 -18
- data/lib/.rbnext/3.0/yesql/config/configuration.rb +0 -32
- data/lib/.rbnext/3.0/yesql/errors/file_path_does_not_exist_error.rb +0 -43
- data/lib/.rbnext/3.0/yesql/errors/no_bindings_provided_error.rb +0 -41
- data/lib/.rbnext/3.0/yesql/params/output.rb +0 -26
- data/lib/.rbnext/3.0/yesql/query/performer.rb +0 -44
- data/lib/.rbnext/3.0/yesql/query/result.rb +0 -41
- data/lib/.rbnext/3.0/yesql/query/transform_result.rb +0 -48
- data/lib/.rbnext/3.0/yesql/statement.rb +0 -44
- data/lib/.rbnext/3.0/yesql/utils/read.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4cad8cd91b4afba6c7a8722f9f0dfd6092552d2f4ce735c6880425241122b43
|
4
|
+
data.tar.gz: b8be652b46ee03e081ec2d8bc3bcc2321e26e2b7fcd55dcbf2a2bb288ddac139
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4dc794c44484b4fcc8815fa866023c6cf5d2f4b82d4f2c45c6de7e86082eaa3ba838c55e750e3f2fd53b0312b4be699c7ddc900400c8445c377fd7c6d1139190
|
7
|
+
data.tar.gz: 88b860a5ce91655366f9d73336b522678a8f709938881e1ff150a13565b57cd12b65c753531ecfb886528d162405c36ca9036c1c3cba52a62aa2e3e3993e76fb
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
Metrics/BlockLength:
|
4
|
+
Exclude:
|
5
|
+
- spec/**/*_spec.rb
|
6
|
+
- spec/spec_helper.rb
|
7
|
+
- spec/yesql/shared/*
|
8
|
+
|
9
|
+
RSpec/FilePath:
|
10
|
+
Exclude:
|
11
|
+
- spec/**/*_spec.rb
|
12
|
+
|
13
|
+
RSpec/NestedGroups:
|
14
|
+
Enabled: False
|
15
|
+
|
16
|
+
RSpec/ExampleLength:
|
17
|
+
Enabled: False
|
18
|
+
|
19
|
+
RSpec/BeforeAfterAll:
|
20
|
+
Enabled: False
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
yesql (0.2.2)
|
5
|
+
activerecord (>= 4.0.0.beta1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
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)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 1.6, < 2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
tzinfo (~> 2.0)
|
20
|
+
zeitwerk (~> 2.3)
|
21
|
+
coderay (1.1.3)
|
22
|
+
concurrent-ruby (1.1.8)
|
23
|
+
diff-lcs (1.4.4)
|
24
|
+
i18n (1.8.10)
|
25
|
+
concurrent-ruby (~> 1.0)
|
26
|
+
method_source (1.0.0)
|
27
|
+
minitest (5.14.4)
|
28
|
+
mysql2 (0.5.3)
|
29
|
+
pg (1.2.3)
|
30
|
+
pry (0.13.1)
|
31
|
+
coderay (~> 1.1)
|
32
|
+
method_source (~> 1.0)
|
33
|
+
rspec (3.9.0)
|
34
|
+
rspec-core (~> 3.9.0)
|
35
|
+
rspec-expectations (~> 3.9.0)
|
36
|
+
rspec-mocks (~> 3.9.0)
|
37
|
+
rspec-core (3.9.3)
|
38
|
+
rspec-support (~> 3.9.3)
|
39
|
+
rspec-expectations (3.9.4)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.9.0)
|
42
|
+
rspec-mocks (3.9.1)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.9.0)
|
45
|
+
rspec-support (3.9.4)
|
46
|
+
tzinfo (2.0.4)
|
47
|
+
concurrent-ruby (~> 1.0)
|
48
|
+
yard (0.9.26)
|
49
|
+
zeitwerk (2.4.2)
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
x86_64-linux
|
53
|
+
|
54
|
+
DEPENDENCIES
|
55
|
+
mysql2 (~> 0.5.3)
|
56
|
+
pg (>= 0.18)
|
57
|
+
pry (~> 0.13.1)
|
58
|
+
rspec (~> 3.9.0)
|
59
|
+
yard
|
60
|
+
yesql!
|
61
|
+
|
62
|
+
BUNDLED WITH
|
63
|
+
2.2.3
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "yesql"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/yesql.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "backports/2.0"
|
4
|
-
require "ruby-next/language/setup"
|
5
|
-
|
6
|
-
RubyNext::Language.setup_gem_load_path
|
7
|
-
|
8
3
|
require "yesql/statement"
|
9
4
|
require "yesql/version"
|
10
5
|
require "yesql/config/configuration"
|
@@ -13,33 +8,36 @@ require "yesql/errors/file_path_does_not_exist_error"
|
|
13
8
|
require "yesql/errors/no_bindings_provided_error"
|
14
9
|
require "yesql/errors/output_argument_error"
|
15
10
|
|
16
|
-
module
|
11
|
+
module YeSQL
|
17
12
|
include ::YeSQL::Config
|
13
|
+
include ::YeSQL::Errors::FilePathDoesNotExistError
|
14
|
+
include ::YeSQL::Errors::NoBindingsProvidedError
|
15
|
+
include ::YeSQL::Errors::OutputArgumentError
|
18
16
|
|
19
17
|
BIND_REGEX = /(?<!:):(\w+)(?=\b)/
|
20
18
|
|
21
|
-
def YeSQL(file_path,
|
19
|
+
def YeSQL(file_path, bindings = {}, options = {})
|
22
20
|
output = options[:output] || :rows
|
23
21
|
|
24
|
-
validate(
|
25
|
-
execute(
|
22
|
+
validate(bindings, file_path, output)
|
23
|
+
execute(bindings, file_path, output, options)
|
26
24
|
end
|
27
25
|
|
28
26
|
private
|
29
27
|
|
30
|
-
def validate(
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
def validate(bindings, file_path, output)
|
29
|
+
validate_file_path_existence(file_path)
|
30
|
+
validate_statement_bindings(bindings, file_path)
|
31
|
+
validate_output_options(output)
|
34
32
|
end
|
35
33
|
|
36
|
-
def execute(
|
34
|
+
def execute(bindings, file_path, output, options)
|
37
35
|
::YeSQL::Query::Performer.new(
|
38
|
-
bindings:
|
39
|
-
bind_statement: ::YeSQL::Statement.new(
|
36
|
+
bindings: bindings,
|
37
|
+
bind_statement: ::YeSQL::Statement.new(bindings, file_path),
|
40
38
|
file_path: file_path,
|
41
39
|
output: output,
|
42
|
-
prepare: prepare
|
40
|
+
prepare: options[:prepare]
|
43
41
|
).call
|
44
42
|
end
|
45
43
|
end
|
@@ -8,7 +8,7 @@ module ::YeSQL
|
|
8
8
|
class Extract
|
9
9
|
include ::YeSQL::Common::Adapter
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(indexed_bindings, hash, index, value)
|
12
12
|
@hash = hash
|
13
13
|
@index = index
|
14
14
|
@indexed_bindings = indexed_bindings
|
@@ -18,35 +18,37 @@ module ::YeSQL
|
|
18
18
|
def bind_vals
|
19
19
|
return [nil, value] unless array?
|
20
20
|
|
21
|
-
value.map { [nil,
|
21
|
+
value.map { |bind| [nil, bind] }
|
22
22
|
end
|
23
23
|
|
24
24
|
def bind_vars
|
25
25
|
if mysql?
|
26
26
|
return "?" unless array?
|
27
27
|
|
28
|
-
Array.new(size, "?").join(", ")
|
28
|
+
Array.new(value.size, "?").join(", ")
|
29
29
|
elsif pg?
|
30
30
|
return "$#{last_val}" unless array?
|
31
31
|
|
32
|
-
value.map.with_index(bind_index) { "$#{
|
32
|
+
value.map.with_index(bind_index) { |_, i| "$#{i}" }.join(", ")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
def last_val
|
37
|
+
prev_last_val + current_val_size
|
38
|
+
end
|
39
|
+
|
36
40
|
def prev
|
37
41
|
return if first?
|
38
42
|
|
39
43
|
indexed_bindings[index - 2].first
|
40
44
|
end
|
41
45
|
|
42
|
-
def last_val = prev_last_val + current_val_size
|
43
|
-
|
44
46
|
private
|
45
47
|
|
46
48
|
attr_reader :hash, :index, :indexed_bindings, :value
|
47
49
|
|
48
50
|
def current_val_size
|
49
|
-
return size if array?
|
51
|
+
return value.size if array?
|
50
52
|
|
51
53
|
1
|
52
54
|
end
|
@@ -57,15 +59,19 @@ module ::YeSQL
|
|
57
59
|
hash[prev][:last_val]
|
58
60
|
end
|
59
61
|
|
62
|
+
def first?
|
63
|
+
index == 1
|
64
|
+
end
|
65
|
+
|
66
|
+
def array?
|
67
|
+
value.is_a?(Array)
|
68
|
+
end
|
69
|
+
|
60
70
|
def bind_index
|
61
71
|
return 1 if first?
|
62
72
|
|
63
73
|
prev_last_val + 1
|
64
74
|
end
|
65
|
-
|
66
|
-
def size = value.size
|
67
|
-
def first? = index == 1
|
68
|
-
def array? = value.is_a?(Array)
|
69
75
|
end
|
70
76
|
end
|
71
77
|
end
|
@@ -2,37 +2,35 @@
|
|
2
2
|
|
3
3
|
require "yesql/bindings/extract"
|
4
4
|
|
5
|
-
module
|
5
|
+
module YeSQL
|
6
6
|
module Bindings
|
7
7
|
class Extractor
|
8
|
-
def initialize(bindings:
|
8
|
+
def initialize(bindings:)
|
9
9
|
@bindings = bindings
|
10
|
-
@indexed_bindings = bindings.to_a
|
10
|
+
@indexed_bindings = (bindings || {}).to_a
|
11
11
|
end
|
12
12
|
|
13
13
|
def call
|
14
|
-
bindings
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
bindings.each_with_object({}).with_index(1) do |((key, value), hash), index|
|
15
|
+
hash[key] =
|
16
|
+
::YeSQL::Bindings::Extract.new(indexed_bindings, hash, index, value).tap do |extract|
|
17
|
+
break {
|
18
|
+
bind: {
|
19
|
+
vals: extract.bind_vals,
|
20
|
+
vars: extract.bind_vars
|
21
|
+
},
|
22
|
+
last_val: extract.last_val,
|
23
|
+
match: key,
|
24
|
+
prev: extract.prev,
|
25
|
+
value: value
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
19
29
|
end
|
20
30
|
|
21
31
|
private
|
22
32
|
|
23
33
|
attr_reader :bindings, :indexed_bindings
|
24
|
-
|
25
|
-
def binding_extracts(hash, indexed_bindings, index, key, value)
|
26
|
-
::YeSQL::Bindings::Extract.new(hash, indexed_bindings, index, value).tap do
|
27
|
-
break {
|
28
|
-
bind: { vals: _1.bind_vals, vars: _1.bind_vars },
|
29
|
-
last_val: _1.last_val,
|
30
|
-
match: key,
|
31
|
-
prev: _1.prev,
|
32
|
-
value: value
|
33
|
-
}
|
34
|
-
end
|
35
|
-
end
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
@@ -23,16 +23,18 @@ module ::YeSQL
|
|
23
23
|
|
24
24
|
attr_reader :statement_binds
|
25
25
|
|
26
|
-
def rails5?
|
26
|
+
def rails5?
|
27
|
+
::ActiveRecord::VERSION::MAJOR == 5
|
28
|
+
end
|
27
29
|
|
28
30
|
def mysql_rails5_binds
|
29
31
|
statement_binds
|
30
32
|
.flat_map(&:first)
|
31
33
|
.each_slice(2)
|
32
|
-
.flat_map do
|
33
|
-
next [
|
34
|
+
.flat_map do |first, last|
|
35
|
+
next [first, last].compact.map(&:last) if first.is_a?(Array)
|
34
36
|
|
35
|
-
|
37
|
+
last
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -46,7 +48,7 @@ module ::YeSQL
|
|
46
48
|
|
47
49
|
def pg_binds
|
48
50
|
statement_binds
|
49
|
-
.sort_by {
|
51
|
+
.sort_by { |_, position| position.to_s.tr("$", "").to_i }
|
50
52
|
.uniq
|
51
53
|
.map(&:first)
|
52
54
|
.flatten
|
data/lib/yesql/bindings/utils.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module YeSQL
|
4
4
|
module Bindings
|
5
5
|
module Utils
|
6
|
-
include ::YeSQL::Utils::Read
|
7
|
-
|
8
6
|
def statement_binds(extractor)
|
9
|
-
|
10
|
-
.
|
11
|
-
.map(
|
12
|
-
|
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
|
13
12
|
end
|
14
13
|
end
|
15
14
|
end
|
data/lib/yesql/common/adapter.rb
CHANGED
@@ -7,12 +7,19 @@ module ::YeSQL
|
|
7
7
|
module Adapter
|
8
8
|
extend ::Forwardable
|
9
9
|
|
10
|
-
|
11
|
-
|
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
|
12
15
|
|
13
|
-
|
16
|
+
def mysql?
|
17
|
+
adapter == "Mysql2"
|
18
|
+
end
|
14
19
|
|
15
|
-
def
|
20
|
+
def pg?
|
21
|
+
adapter == "PostgreSQL"
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
@@ -1,30 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
3
|
+
module YeSQL
|
4
4
|
module Errors
|
5
|
-
|
6
|
-
def
|
7
|
-
|
8
|
-
end
|
5
|
+
module FilePathDoesNotExistError
|
6
|
+
def validate_file_path_existence(file_path)
|
7
|
+
return if file_exists?(file_path)
|
9
8
|
|
10
|
-
|
11
|
-
|
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
|
-
)
|
9
|
+
raise NotImplementedError, format(MESSAGE, available_files: available_files,
|
10
|
+
file_path: file_path, path: ::YeSQL.config.path)
|
22
11
|
end
|
23
12
|
|
24
13
|
private
|
25
14
|
|
26
|
-
attr_reader :file_path
|
27
|
-
|
28
15
|
MESSAGE = <<~MSG
|
29
16
|
|
30
17
|
SQL file "%<file_path>s" does not exist in %<path>s.
|
@@ -35,9 +22,17 @@ module ::YeSQL
|
|
35
22
|
MSG
|
36
23
|
private_constant :MESSAGE
|
37
24
|
|
38
|
-
def file_exists?
|
39
|
-
|
40
|
-
|
25
|
+
def file_exists?(file_path)
|
26
|
+
path_files.any? { |filename| filename.include?("#{file_path}.sql") }
|
27
|
+
end
|
28
|
+
|
29
|
+
def available_files
|
30
|
+
path_files.map { |file| "- #{file}\n" }.join
|
31
|
+
end
|
32
|
+
|
33
|
+
def path_files
|
34
|
+
@path_files ||= Dir["#{::YeSQL.config.path}/**/*.sql"]
|
35
|
+
end
|
41
36
|
end
|
42
37
|
end
|
43
38
|
end
|