yesql 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|