sqb 1.0.6 → 1.0.7
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 +5 -5
- data/lib/sqb/error.rb +3 -0
- data/lib/sqb/escaping.rb +7 -1
- data/lib/sqb/filtering.rb +66 -64
- data/lib/sqb/update.rb +6 -2
- data/lib/sqb/version.rb +1 -1
- data/lib/sqb/where_dsl.rb +85 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c682c36dc27d41519663b1caf06a97edd9cfdb6c
|
4
|
+
data.tar.gz: 92637092f8f29020c72d40b466b4acfbd43e9060
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd376b13686ee0f7f27621c275cb52100bf9872de3df5cc9805e936f0c591f4ffea321e1076eb4a00b1fdb4a50949cb1c56fa1baa6e2db691f4716606c91f58e
|
7
|
+
data.tar.gz: f1e60e3a689895eb05c5305dc9fb803bb7d088281ce07ceef062222515e6e82151c04e19be92b6bb19ff269f4eff41484622214e1cad2f28d826406387832a8a
|
data/lib/sqb/error.rb
CHANGED
data/lib/sqb/escaping.rb
CHANGED
@@ -30,6 +30,8 @@ module SQB
|
|
30
30
|
'NULL'
|
31
31
|
elsif value.is_a?(Integer)
|
32
32
|
value.to_i
|
33
|
+
elsif value.is_a?(SQB::SafeString)
|
34
|
+
value.to_s
|
33
35
|
else
|
34
36
|
@prepared_arguments << value.to_s
|
35
37
|
'?'
|
@@ -38,7 +40,11 @@ module SQB
|
|
38
40
|
|
39
41
|
def with_table_and_column(input, &block)
|
40
42
|
if input.is_a?(Hash)
|
41
|
-
input.
|
43
|
+
if input.size == 1
|
44
|
+
block.call(input.first[0], input.first[1])
|
45
|
+
else
|
46
|
+
raise QueryError, "Column names provided as a hash must only contain a single item"
|
47
|
+
end
|
42
48
|
else
|
43
49
|
block.call(@table_name, input)
|
44
50
|
end
|
data/lib/sqb/filtering.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sqb/where_dsl'
|
2
|
+
|
1
3
|
module SQB
|
2
4
|
module Filtering
|
3
5
|
|
@@ -5,12 +7,20 @@ module SQB
|
|
5
7
|
#
|
6
8
|
# @param hash [Hash]
|
7
9
|
# @return [Query]
|
8
|
-
def where(hash)
|
9
|
-
if
|
10
|
-
@where_within_or.last
|
10
|
+
def where(hash = nil, &block)
|
11
|
+
if hash
|
12
|
+
if @where_within_or && @where_within_or.last
|
13
|
+
@where_within_or.last << hash
|
14
|
+
else
|
15
|
+
@where ||= []
|
16
|
+
@where << hash_to_sql(hash)
|
17
|
+
end
|
18
|
+
elsif block_given?
|
19
|
+
dsl = WhereDSL.new
|
20
|
+
block.call(dsl)
|
21
|
+
where(dsl.hash)
|
11
22
|
else
|
12
|
-
|
13
|
-
@where << hash_to_sql(hash, @table_name)
|
23
|
+
raise QueryError, "Must provide a hash or a block to `where`"
|
14
24
|
end
|
15
25
|
self
|
16
26
|
end
|
@@ -31,7 +41,7 @@ module SQB
|
|
31
41
|
# executed within the block.
|
32
42
|
if w = @where_within_or.pop
|
33
43
|
@where_within_or_sql << w.map do |w|
|
34
|
-
hash_to_sql(w
|
44
|
+
hash_to_sql(w)
|
35
45
|
end.join(' OR ')
|
36
46
|
end
|
37
47
|
|
@@ -47,71 +57,63 @@ module SQB
|
|
47
57
|
|
48
58
|
private
|
49
59
|
|
50
|
-
def hash_to_sql(hash,
|
60
|
+
def hash_to_sql(hash, joiner = ' AND ')
|
51
61
|
sql = hash.map do |key, value|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
if value.is_a?(Array)
|
60
|
-
escaped_values = value.map { |v| value_escape(v) }.join(', ')
|
61
|
-
if escaped_values.empty?
|
62
|
-
"1=0"
|
63
|
-
else
|
64
|
-
"#{key} IN (#{escaped_values})"
|
65
|
-
end
|
66
|
-
elsif value.is_a?(Hash)
|
67
|
-
sql = []
|
68
|
-
value.each do |operator, value|
|
69
|
-
case operator
|
70
|
-
when :not_equal
|
71
|
-
if value.nil?
|
72
|
-
sql << "#{key} IS NOT NULL"
|
73
|
-
else
|
74
|
-
sql << "#{key} != #{value_escape(value)}"
|
75
|
-
end
|
76
|
-
when :equal
|
77
|
-
if value.nil?
|
78
|
-
sql << "#{key} IS NULL"
|
79
|
-
else
|
80
|
-
sql << "#{key} = #{value_escape(value)}"
|
81
|
-
end
|
82
|
-
when :less_than
|
83
|
-
sql << "#{key} < #{value_escape(value)}"
|
84
|
-
when :greater_than
|
85
|
-
sql << "#{key} > #{value_escape(value)}"
|
86
|
-
when :less_than_or_equal_to
|
87
|
-
sql << "#{key} <= #{value_escape(value)}"
|
88
|
-
when :greater_than_or_equal_to
|
89
|
-
sql << "#{key} >= #{value_escape(value)}"
|
90
|
-
when :in, :not_in
|
91
|
-
escaped_values = value.map { |v| value_escape(v) }.join(', ')
|
92
|
-
if escaped_values.empty?
|
93
|
-
# If there are no values to search from, don't find anything
|
94
|
-
"1=0"
|
95
|
-
else
|
96
|
-
op = operator == :in ? "IN" : "NOT IN"
|
97
|
-
sql << "#{key} #{op} (#{escaped_values})"
|
98
|
-
end
|
99
|
-
when :like
|
100
|
-
sql << "#{key} LIKE #{value_escape(value)}"
|
101
|
-
when :not_like
|
102
|
-
sql << "#{key} NOT LIKE #{value_escape(value)}"
|
103
|
-
else
|
104
|
-
raise InvalidOperatorError, "Invalid operator '#{operator}'"
|
62
|
+
with_table_and_column(key) do |table, column|
|
63
|
+
key = escape_and_join(table, column)
|
64
|
+
if value.is_a?(Array)
|
65
|
+
condition(key, :in, value)
|
66
|
+
elsif value.is_a?(Hash)
|
67
|
+
sql = value.map do |operator, value|
|
68
|
+
condition(key, operator, value)
|
105
69
|
end
|
70
|
+
sql.empty? ? "1=0" : sql.join(joiner)
|
71
|
+
else
|
72
|
+
condition(key, :equal, value)
|
106
73
|
end
|
107
|
-
|
108
|
-
|
74
|
+
end
|
75
|
+
end.join(joiner)
|
76
|
+
"(#{sql})"
|
77
|
+
end
|
78
|
+
|
79
|
+
def condition(key, operator, value)
|
80
|
+
case operator
|
81
|
+
when :equal
|
82
|
+
if value.nil?
|
109
83
|
"#{key} IS NULL"
|
110
84
|
else
|
111
85
|
"#{key} = #{value_escape(value)}"
|
112
86
|
end
|
113
|
-
|
114
|
-
|
87
|
+
when :not_equal
|
88
|
+
if value.nil?
|
89
|
+
"#{key} IS NOT NULL"
|
90
|
+
else
|
91
|
+
"#{key} != #{value_escape(value)}"
|
92
|
+
end
|
93
|
+
when :less_than, :lt
|
94
|
+
"#{key} < #{value_escape(value)}"
|
95
|
+
when :greater_than, :gt
|
96
|
+
"#{key} > #{value_escape(value)}"
|
97
|
+
when :less_than_or_equal_to, :lte
|
98
|
+
"#{key} <= #{value_escape(value)}"
|
99
|
+
when :greater_than_or_equal_to, :gte
|
100
|
+
"#{key} >= #{value_escape(value)}"
|
101
|
+
when :in, :not_in
|
102
|
+
escaped_values = value.map { |v| value_escape(v) }.join(', ')
|
103
|
+
if escaped_values.empty?
|
104
|
+
# If there are no values to search from, don't find anything
|
105
|
+
"1=0"
|
106
|
+
else
|
107
|
+
op = operator == :in ? "IN" : "NOT IN"
|
108
|
+
"#{key} #{op} (#{escaped_values})"
|
109
|
+
end
|
110
|
+
when :like
|
111
|
+
"#{key} LIKE #{value_escape(value)}"
|
112
|
+
when :not_like
|
113
|
+
"#{key} NOT LIKE #{value_escape(value)}"
|
114
|
+
else
|
115
|
+
raise InvalidOperatorError, "Invalid operator '#{operator}'"
|
116
|
+
end
|
115
117
|
end
|
116
118
|
|
117
119
|
end
|
data/lib/sqb/update.rb
CHANGED
@@ -15,7 +15,7 @@ module SQB
|
|
15
15
|
query << "SET"
|
16
16
|
if @sets && !@sets.empty?
|
17
17
|
query << @sets.map do |key, value|
|
18
|
-
"#{escape_and_join(@table_name, key)} = #{
|
18
|
+
"#{escape_and_join(@table_name, key)} = #{value}"
|
19
19
|
end.join(', ')
|
20
20
|
else
|
21
21
|
raise NoValuesError, "No values have been updated. Use `set` to set the values to update."
|
@@ -41,9 +41,13 @@ module SQB
|
|
41
41
|
# @param key [String]
|
42
42
|
# @param value [String, nil]
|
43
43
|
def set(hash)
|
44
|
+
if @where
|
45
|
+
raise QueryError, "Filtering has already been provided. Must filter after setting values."
|
46
|
+
end
|
47
|
+
|
44
48
|
@sets ||= {}
|
45
49
|
hash.each do |key, value|
|
46
|
-
@sets[key] = value
|
50
|
+
@sets[key] = value_escape(value)
|
47
51
|
end
|
48
52
|
self
|
49
53
|
end
|
data/lib/sqb/version.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
module SQB
|
2
|
+
class WhereDSL
|
3
|
+
|
4
|
+
attr_reader :hash
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@hash = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(name, value = nil)
|
11
|
+
if name =~ /(.*)\=\z/
|
12
|
+
attribute_name = $1
|
13
|
+
@hash[attribute_name.to_sym] ||= {}
|
14
|
+
@hash[attribute_name.to_sym][:equal] = value
|
15
|
+
else
|
16
|
+
@hash[name.to_sym] ||= {}
|
17
|
+
attribute = PositiveAttribute.new(name.to_sym, @hash)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Attribute
|
22
|
+
|
23
|
+
def initialize(attribute_name, hash)
|
24
|
+
@attribute_name = attribute_name
|
25
|
+
@hash = hash
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class PositiveAttribute < Attribute
|
31
|
+
def =~(value)
|
32
|
+
@hash[@attribute_name][:like] = value
|
33
|
+
end
|
34
|
+
alias_method :like, :=~
|
35
|
+
|
36
|
+
def <(value)
|
37
|
+
@hash[@attribute_name][:less_than] = value
|
38
|
+
end
|
39
|
+
alias_method :less_than, :<
|
40
|
+
|
41
|
+
def <=(value)
|
42
|
+
@hash[@attribute_name][:less_than_or_equal_to] = value
|
43
|
+
end
|
44
|
+
alias_method :less_than_or_equal_to, :<=
|
45
|
+
|
46
|
+
def >(value)
|
47
|
+
@hash[@attribute_name][:greater_than] = value
|
48
|
+
end
|
49
|
+
alias_method :greater_than, :>
|
50
|
+
|
51
|
+
def >=(value)
|
52
|
+
@hash[@attribute_name][:greater_than_or_equal_to] = value
|
53
|
+
end
|
54
|
+
alias_method :greater_than_or_equal_to, :>=
|
55
|
+
|
56
|
+
def includes(*values)
|
57
|
+
@hash[@attribute_name][:in] = values
|
58
|
+
end
|
59
|
+
alias_method :in, :includes
|
60
|
+
|
61
|
+
def not
|
62
|
+
NegativeAttribute.new(@attribute_name, @hash)
|
63
|
+
end
|
64
|
+
alias_method :does_not, :not
|
65
|
+
|
66
|
+
def not=(value)
|
67
|
+
@hash[@attribute_name][:not_equal] = value
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class NegativeAttribute < Attribute
|
73
|
+
def =~(value)
|
74
|
+
@hash[@attribute_name][:not_like] = value
|
75
|
+
end
|
76
|
+
alias_method :like, :=~
|
77
|
+
|
78
|
+
def includes(*values)
|
79
|
+
@hash[@attribute_name][:not_in] = values
|
80
|
+
end
|
81
|
+
alias_method :in, :includes
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03
|
11
|
+
date: 2018-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A friendly SQL builder for MySQL.
|
14
14
|
email:
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- lib/sqb/select.rb
|
37
37
|
- lib/sqb/update.rb
|
38
38
|
- lib/sqb/version.rb
|
39
|
+
- lib/sqb/where_dsl.rb
|
39
40
|
homepage: https://github.com/adamcooke/sqb
|
40
41
|
licenses:
|
41
42
|
- MIT
|
@@ -56,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
57
|
version: '0'
|
57
58
|
requirements: []
|
58
59
|
rubyforge_project:
|
59
|
-
rubygems_version: 2.
|
60
|
+
rubygems_version: 2.5.2.3
|
60
61
|
signing_key:
|
61
62
|
specification_version: 4
|
62
63
|
summary: This gem provides a friendly DSL for constructing MySQL queries.
|