sql_query_executor 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3687167aeee2a4c5247df316603b0395d041b26b
4
- data.tar.gz: f2709f263731b76b601a6a158c36fb64a00d1932
3
+ metadata.gz: c42f0a76b148c57bbe10c04654bbd6380cab657b
4
+ data.tar.gz: c653b58ffc9a847922c2b8b1e3d88463b9b46e84
5
5
  SHA512:
6
- metadata.gz: 97c5d6546a812e34a7b6fc4246f55e92b454f59f1f3b58dae49dba2aca0d24d22145002b8feb81d8e548fc0720efe8b52168ee07d430d4a94dd52f13c0c336fd
7
- data.tar.gz: 4644918b41c5aec118c84a26a5cca0a4d6a8bfbe102ef009a171854a1bebd86ca2aeda6f7194f6cce10c606824a2a7c8d3b317e61b4e40e6173646a4bac42705
6
+ metadata.gz: 48ef44419b5509ff76af6e617370350dbb7167892f0f85283d1cbd465b8349bff384319aced176870d8fbc4e42fa38ca83e8a5dc2568e2739d9170e150cd218a
7
+ data.tar.gz: 2000259b6d0931d496a8757c0f4619f185609f64d741a99d44d7451cc4a41f094a06bd2fe81334bf5cc73ec807ce79d1aedfc51e0fa07f15bb032f1ac5165089
@@ -18,7 +18,6 @@ module SqlQueryExecutor #:nodoc:
18
18
  # Recursive method that divides the query in sub queries, executes each part individually
19
19
  # and finally relates its results as specified in the query.
20
20
  def where(*query)
21
- raise ArgumentError.new("must pass at least one argument") if query.empty?
22
21
  query = query.first if query.respond_to?(:size) && query.size == 1
23
22
 
24
23
  message = check_query(query)
@@ -42,6 +41,8 @@ module SqlQueryExecutor #:nodoc:
42
41
  end
43
42
 
44
43
  def check_query(query)
44
+ return "must pass at least one argument" if query.empty?
45
+
45
46
  if query.is_a?(Array) && !query.first.is_a?(String)
46
47
  "First element from array must be a String. eg: [\"name = ?\", \"John\"]"
47
48
  end
@@ -10,13 +10,17 @@ module SqlQueryExecutor
10
10
  @value = get_value
11
11
  end
12
12
 
13
+ def selector
14
+ { @field => @value }
15
+ end
16
+
13
17
  protected
14
18
  def get_field
15
19
  @array.first
16
20
  end
17
21
 
18
22
  def get_value
19
- value = @array.last.gsub(::SqlQueryExecutor::Query::Base::STRING_SPACE, ' ')
23
+ value = @array.last.gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' ')
20
24
 
21
25
  convert_value(value)
22
26
  end
@@ -18,6 +18,10 @@ module SqlQueryExecutor
18
18
  end
19
19
  end
20
20
 
21
+ def selector
22
+ { @field => { "$gte" => @value.first, "$lte" => @value.last }}
23
+ end
24
+
21
25
  private
22
26
  def get_value
23
27
  value = []
@@ -3,6 +3,15 @@ require 'sql_query_executor/operators/base'
3
3
  module SqlQueryExecutor
4
4
  module Operators
5
5
  class Default < SqlQueryExecutor::Operators::Base
6
+ SELECTORS = {
7
+ "==" => nil,
8
+ ">" => "$gt",
9
+ "<" => "$lt",
10
+ ">=" => "$gte",
11
+ "<=" => "$lte",
12
+ "!=" => "$ne"
13
+ }
14
+
6
15
  def initialize(query, collection)
7
16
  super
8
17
  convert_operator
@@ -16,6 +25,12 @@ module SqlQueryExecutor
16
25
  end
17
26
  end
18
27
 
28
+ def selector
29
+ operator = SELECTORS[@operator]
30
+
31
+ { @field.to_sym => operator ? {operator => @value} : @value}
32
+ end
33
+
19
34
  private
20
35
  def convert_operator
21
36
  @operator = @operator == "=" ? "==" : @operator
@@ -11,6 +11,10 @@ module SqlQueryExecutor
11
11
  end
12
12
  end
13
13
 
14
+ def selector
15
+ { @field => { "$in" => @value }}
16
+ end
17
+
14
18
  private
15
19
  def get_value
16
20
  value = super
@@ -3,8 +3,6 @@ require 'sql_query_executor/query/query_normalizer'
3
3
  module SqlQueryExecutor
4
4
  module Query
5
5
  class Base
6
- attr_reader :query
7
-
8
6
  STRING_SPACE = "$SS$"
9
7
  QUERY_SPACE = "$QS$"
10
8
  TEMP_SPACE = "$TS$"
@@ -18,100 +16,12 @@ module SqlQueryExecutor
18
16
  @query.execute!
19
17
  end
20
18
 
21
- private
22
- def clean_query_attribute(query)
23
- return query unless query.is_a?(Array)
24
-
25
- query = query.flatten
26
-
27
- query.size == 1 ? query.first : query
28
- end
29
-
30
- def get_query(query)
31
- query
32
- end
33
-
34
- # Prepares query by replacing all ? by it's real values in #args
35
- def interpolate_query(args)
36
- args.flatten!
37
- return args.first if args.size == 1 && args.first.is_a?(String)
38
-
39
- query = args.first
40
- param = args.delete_at(1)
41
-
42
- param = convert_param(param)
43
-
44
- args[0] = query.sub("?", param.is_a?(Numeric) ? param : "#{param}")
45
-
46
- interpolate_query(args)
47
- end
48
-
49
- # Removes all accents and other non default characters
50
- def sanitize(query)
51
- new_query = replace_on_query(query, /(["|'].*?["|'])/, " ", STRING_SPACE)
52
- new_query = replace_on_query(new_query, /(\(.*?\))/, " ", QUERY_SPACE)
53
-
54
- remove_spaces(prepare_query(new_query))
55
- end
56
-
57
- def replace_on_query(query, regexp, pattern, replacement)
58
- new_query = query ? query.dup : query
59
-
60
- params = new_query.scan(regexp).flatten.compact
61
-
62
- params.each do |param|
63
- new_param = param.dup
64
-
65
- new_param = new_param.gsub(pattern, replacement)
66
-
67
- new_query = new_query.gsub(param, new_param)
68
- end
69
-
70
- new_query
19
+ def to_sql
20
+ @query.to_sql
71
21
  end
72
22
 
73
- def prepare_query(query)
74
- SubQuery::BINDING_OPERATORS.keys.each do |operator|
75
- query.gsub!(" #{operator} ", "#{TEMP_SPACE}#{operator}#{QUERY_SPACE}")
76
- end
77
-
78
- query.gsub(" ", QUERY_SPACE).gsub(TEMP_SPACE, " ")
79
- end
80
-
81
- def remove_spaces(query)
82
- query.gsub!(/\[.*?\]/) { |substr| substr.gsub(' ', '') }
83
- query
84
- end
85
-
86
- # Returns converted #param based on its Class, so it can be used on the query
87
- def convert_param(param)
88
- case param.class.name
89
- when "String"
90
- param = "'#{param}'"
91
- when "Date"
92
- param = "'#{param.strftime("%Y-%m-%d")}'"
93
- when "Time"
94
- param = "'#{param.strftime("%Y-%m-%d %H:%M:%S %z")}'"
95
- else
96
- param = param.to_s
97
- end
98
- end
99
-
100
- def concatenate_hash(query)
101
- return "" unless query.is_a?(Hash)
102
- query_array = []
103
-
104
- query.each do |key, value|
105
- if value.is_a?(Array)
106
- value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
107
- query_array << "#{key} in (#{value.join(',')})"
108
- else
109
- value = value.is_a?(Numeric) ? value : "'#{value}'"
110
- query_array << "#{key} = #{value}"
111
- end
112
- end
113
-
114
- query_array.join(" and ")
23
+ def selector
24
+ @query.selector
115
25
  end
116
26
  end
117
27
  end
@@ -2,7 +2,7 @@ require 'sql_query_executor'
2
2
 
3
3
  module SqlQueryExecutor
4
4
  module Query
5
- class SqlQueryExecutor::Query::QueryNormalizer
5
+ class QueryNormalizer
6
6
  class << self
7
7
  CONVERT_METHODS = {"String" => ["get_query", ""], "Array" => ["interpolate_query", "query.flatten"], "Hash" => ["concatenate_hash", "query"]}
8
8
 
@@ -92,7 +92,7 @@ module SqlQueryExecutor
92
92
  def convert_param(param)
93
93
  case param.class.name
94
94
  when "String"
95
- param = "'#{param}'"
95
+ param = "'#{param}'".gsub("''", "'").gsub('""', '"')
96
96
  when "Date"
97
97
  param = "'#{param.strftime("%Y-%m-%d")}'"
98
98
  when "Time"
@@ -105,14 +105,33 @@ module SqlQueryExecutor
105
105
  def concatenate_hash(query)
106
106
  return "" unless query.is_a?(Hash)
107
107
  query_array = []
108
+ operators = {"$gt" => '>', "$lt" => '<', "$gte" => '>=', "$lte" => '<=', "$ne" => '!=', "$in" => 'in'}
108
109
 
109
110
  query.each do |key, value|
110
111
  if value.is_a?(Array)
111
- value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
112
- query_array << "#{key} in (#{value.join(',')})"
112
+ if [:and, :or].include?(key)
113
+ queries = []
114
+
115
+ value.each do |hash|
116
+ queries << concatenate_hash(hash)
117
+ end
118
+
119
+ query_array << queries.join(" #{key.to_s} ")
120
+ else
121
+ value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
122
+ query_array << "#{key} in (#{value.join(',')})"
123
+ end
113
124
  else
114
- value = value.is_a?(Numeric) ? value : "'#{value}'"
115
- query_array << "#{key} = #{value}"
125
+ operator = '='
126
+
127
+ if value.is_a?(Hash)
128
+ operator = operators[value.keys.first] || operator
129
+
130
+ value = convert_param(value.values.first)
131
+ end
132
+
133
+ value = "#{convert_param(value)}"
134
+ query_array << "#{key} #{operator} #{value}"
116
135
  end
117
136
  end
118
137
 
@@ -37,18 +37,16 @@ module SqlQueryExecutor
37
37
  @operator.execute!(data)
38
38
  end
39
39
 
40
+ def selector
41
+ @operator.selector
42
+ end
43
+
40
44
  private
41
45
  def set_operator
42
46
  operator = OPERATORS[@query.split(' ')[1]]
43
47
 
44
48
  @operator = operator ? operator.new(@query, @collection) : nil
45
49
  end
46
-
47
- def fix_query
48
- @array.delete_at(0)
49
-
50
- @query = @array.join(' ')
51
- end
52
50
  end
53
51
  end
54
52
  end
@@ -4,7 +4,7 @@ module SqlQueryExecutor
4
4
  module Query
5
5
  class SubQuery
6
6
  BINDING_OPERATORS = { "or" => "+", "and" => "&" }
7
- attr_reader :query, :children, :kind
7
+ attr_reader :children, :kind, :binding_operator
8
8
  ADD_CHILDREN_METHODS = { sentence: :add_sentence_children, sub_query: :add_sub_query_children }
9
9
  def initialize(query, collection)
10
10
  @collection = collection
@@ -29,6 +29,25 @@ module SqlQueryExecutor
29
29
  result.sort_by(&:id)
30
30
  end
31
31
 
32
+ def selector
33
+ hash = {}
34
+
35
+ @children.each do |child|
36
+ if child.respond_to?(:binding_operator) && child.binding_operator
37
+ operator = BINDING_OPERATORS.invert[child.binding_operator]
38
+ hash = {operator.to_sym => [hash,child.selector]}
39
+ else
40
+ hash.merge!(child.selector)
41
+ end
42
+ end
43
+
44
+ hash
45
+ end
46
+
47
+ def to_sql
48
+ QueryNormalizer.clean_query(@query)
49
+ end
50
+
32
51
  private
33
52
  def set_binding_operator
34
53
  @binding_operator = nil
@@ -77,31 +96,6 @@ module SqlQueryExecutor
77
96
  array.size <= 5
78
97
  end
79
98
 
80
- def build_sub_query(query)
81
- array = query.split(" ")
82
-
83
- offset = is_binding_operator?(array.first) ? 1 : 0
84
- operator = array[1+offset]
85
-
86
- result = case operator
87
- when "between"
88
- array[0..4+offset]
89
- when "is"
90
- size = array[2+offset] == "not" ? 3 : 2
91
- array[0..size+offset]
92
- when "not"
93
- array[0..3+offset]
94
- else
95
- array[0..2+offset]
96
- end
97
-
98
- result.join(' ')
99
- end
100
-
101
- def is_binding_operator?(operator)
102
- BINDING_OPERATORS.include?(operator)
103
- end
104
-
105
99
  def replace_parentheses(query)
106
100
  count = 1
107
101
  string = ""
@@ -1,3 +1,3 @@
1
1
  module SqlQueryExecutor
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -15,6 +15,42 @@ describe SqlQueryExecutor, "Base" do
15
15
 
16
16
  subject { SqlQueryExecutor::Base.new(@data) }
17
17
 
18
+ describe "initialize" do
19
+ before do
20
+ class Model
21
+ attr_reader :attributes
22
+
23
+ def initialize(attributes)
24
+ @attributes = attributes
25
+ end
26
+
27
+ def id
28
+ @attributes[:id]
29
+ end
30
+ end
31
+
32
+ class Collection
33
+ def initialize(collection)
34
+ @collection = []
35
+
36
+ collection.each do |hash|
37
+ @collection << Model.new(hash)
38
+ end
39
+ end
40
+
41
+ def all
42
+ @collection
43
+ end
44
+ end
45
+ end
46
+
47
+ subject { SqlQueryExecutor::Base.new(Collection.new(@data).all) }
48
+
49
+ it 'initializes with a conforming collection' do
50
+ expect(subject.where(id: 1).first.attributes).to eq (@data.first)
51
+ end
52
+ end
53
+
18
54
  describe ".where" do
19
55
  context "when invalid query is passed" do
20
56
  it "raises an ArgumentError" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sql_query_executor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caio Torres
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-24 00:00:00.000000000 Z
11
+ date: 2014-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec