rebel 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rebel/sql.rb +137 -37
  3. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa3b3e1d946d65b40349085c1f02503587f2f3fd
4
- data.tar.gz: e7923044d3c6f76a81eda0001941bb978adf85f5
3
+ metadata.gz: 10809e6c0a432430cd14bff789a33f4e931d8d19
4
+ data.tar.gz: f09ec1c343f3202fdec996cbea89cc8b5c88eccc
5
5
  SHA512:
6
- metadata.gz: 5992df606d5eba47645c9301729488d4114f1d4278542d7476521675aaed788427d7a6f4e9673a32bd88f1238a06ee3bfa7ea9f14d6136d7a49805846cae8516
7
- data.tar.gz: d44f06d4f085bee06d81b3db9a609a34dfdba2e6d191c003e316eca27bc154c8c7ffaa57c962f28b6e1ed46177ad04344fc5aa5cf72c5e6f2620849c7fc193b4
6
+ metadata.gz: bb6c20a31bac4c52a5b2dba793608c53544b5abe713540b733e614009747a4f7e216e6bf998aee9b56985d4becc7c3b9552f35f93241c9cd50b462696a2a8c5a
7
+ data.tar.gz: dac1d09cbbc44bc324441295848757be87f77b48e362eda69417d15c770e8ceb8dd9a359bead9072c2d2173cc0a7d45320da7cbc4cc9888c43013c7c0acebeef
@@ -51,6 +51,24 @@ module Rebel::SQL
51
51
  end
52
52
 
53
53
  class Raw < String
54
+ def wants_parens!
55
+ @wants_parens = true
56
+ self
57
+ end
58
+
59
+ def wants_parens?
60
+ @wants_parens = false unless instance_variable_defined?(:@wants_parens)
61
+ @wants_parens
62
+ end
63
+
64
+ def parens
65
+ Raw.new("(#{self})")
66
+ end
67
+
68
+ def parens?
69
+ wants_parens? ? parens : self
70
+ end
71
+
54
72
  def as(n)
55
73
  Raw.new(self + " AS #{Rebel::SQL.name(n)}")
56
74
  end
@@ -59,48 +77,117 @@ module Rebel::SQL
59
77
  n ? as(n) : self
60
78
  end
61
79
 
62
- def on(clause)
63
- Raw.new(self + " ON #{Rebel::SQL.and_clause(clause)}")
80
+ def on(*clause)
81
+ Raw.new(self + " ON #{Rebel::SQL.and_clause(*clause)}")
82
+ end
83
+
84
+ def on?(*clause)
85
+ clause.any? ? on(clause) : self
86
+ end
87
+
88
+ def and(*clause)
89
+ Raw.new("#{self.parens?} AND #{Rebel::SQL.and_clause(*clause)}")
64
90
  end
65
91
 
66
- def on?(clause)
67
- clause ? on(clause) : self
92
+ def or(*clause)
93
+ Raw.new("#{self} OR #{Rebel::SQL.and_clause(*clause)}").wants_parens!
94
+ end
95
+
96
+ def eq(n)
97
+ case n
98
+ when nil
99
+ Raw.new("#{self} IS NULL")
100
+ else
101
+ Raw.new("#{self} = #{Rebel::SQL.name_or_value(n)}")
102
+ end
103
+ end
104
+ alias == eq
105
+ alias is eq
106
+
107
+ def ne(n)
108
+ case n
109
+ when nil
110
+ Raw.new("#{self} IS NOT NULL")
111
+ else
112
+ Raw.new("#{self} != #{Rebel::SQL.name_or_value(n)}")
113
+ end
114
+ end
115
+ alias != ne
116
+
117
+ def lt(n)
118
+ Raw.new("#{self} < #{Rebel::SQL.name_or_value(n)}")
119
+ end
120
+ alias < lt
121
+
122
+ def gt(n)
123
+ Raw.new("#{self} > #{Rebel::SQL.name_or_value(n)}")
124
+ end
125
+ alias > gt
126
+
127
+ def le(n)
128
+ Raw.new("#{self} <= #{Rebel::SQL.name_or_value(n)}")
129
+ end
130
+ alias <= le
131
+
132
+ def ge(n)
133
+ Raw.new("#{self} >= #{Rebel::SQL.name_or_value(n)}")
134
+ end
135
+ alias >= ge
136
+
137
+ def in(*v)
138
+ Raw.new("#{self} IN (#{Rebel::SQL.values(*v)})")
68
139
  end
69
140
  end
70
141
 
142
+ @identifier_quote = '"'
143
+ @string_quote = "'"
144
+ @escaped_string_quote = "''"
145
+
71
146
  class << self
147
+ def identifier_quote=(str)
148
+ @identifier_quote = str
149
+ end
150
+
151
+ def string_quote=(str)
152
+ @string_quote = str
153
+ end
154
+
155
+ def escaped_string_quote=(str)
156
+ @escaped_string_quote = str
157
+ end
158
+
72
159
  def raw(str)
73
160
  Raw.new(str)
74
161
  end
75
162
 
76
163
  def create_table(table_name, desc)
77
164
  <<-SQL
78
- CREATE TABLE #{Rebel::SQL.name(table_name)} (
79
- #{Rebel::SQL.list(desc.map { |k, v| "#{Rebel::SQL.name(k)} #{v}" })}
165
+ CREATE TABLE #{name(table_name)} (
166
+ #{list(desc.map { |k, v| "#{name(k)} #{v}" })}
80
167
  );
81
168
  SQL
82
169
  end
83
170
 
84
171
  def drop_table(table_name)
85
172
  <<-SQL
86
- DROP TABLE #{Rebel::SQL.name(table_name)};
173
+ DROP TABLE #{name(table_name)};
87
174
  SQL
88
175
  end
89
176
 
90
177
  def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil)
91
178
  <<-SQL
92
179
  SELECT #{names(*fields)} FROM #{name(from)}
93
- #{Rebel::SQL.inner?(inner)}
94
- #{Rebel::SQL.left?(left)}
95
- #{Rebel::SQL.right?(right)}
96
- #{Rebel::SQL.where?(where)};
180
+ #{inner?(inner)}
181
+ #{left?(left)}
182
+ #{right?(right)}
183
+ #{where?(where)};
97
184
  SQL
98
185
  end
99
186
 
100
187
  def insert_into(table_name, *rows)
101
188
  <<-SQL
102
- INSERT INTO #{Rebel::SQL.name(table_name)} (#{Rebel::SQL.names(*rows.first.keys)})
103
- VALUES #{Rebel::SQL.list(rows.map { |r| "(#{Rebel::SQL.values(*r.values)})" })};
189
+ INSERT INTO #{name(table_name)} (#{names(*rows.first.keys)})
190
+ VALUES #{list(rows.map { |r| "(#{values(*r.values)})" })};
104
191
  SQL
105
192
  end
106
193
 
@@ -108,33 +195,38 @@ module Rebel::SQL
108
195
  raise ArgumentError if set.nil?
109
196
 
110
197
  <<-SQL
111
- UPDATE #{Rebel::SQL.name(table_name)}
112
- SET #{Rebel::SQL.assign_clause(set)}
113
- #{Rebel::SQL.inner?(inner)}
114
- #{Rebel::SQL.left?(left)}
115
- #{Rebel::SQL.right?(right)}
116
- #{Rebel::SQL.where?(where)};
198
+ UPDATE #{name(table_name)}
199
+ SET #{assign_clause(set)}
200
+ #{inner?(inner)}
201
+ #{left?(left)}
202
+ #{right?(right)}
203
+ #{where?(where)};
117
204
  SQL
118
205
  end
119
206
 
120
207
  def delete_from(table_name, where: nil, inner: nil, left: nil, right: nil)
121
208
  <<-SQL
122
- DELETE FROM #{Rebel::SQL.name(table_name)}
123
- #{Rebel::SQL.inner?(inner)}
124
- #{Rebel::SQL.left?(left)}
125
- #{Rebel::SQL.right?(right)}
126
- #{Rebel::SQL.where?(where)};
209
+ DELETE FROM #{name(table_name)}
210
+ #{inner?(inner)}
211
+ #{left?(left)}
212
+ #{right?(right)}
213
+ #{where?(where)};
127
214
  SQL
128
215
  end
129
216
 
130
217
  def truncate(table_name)
131
218
  <<-SQL
132
- TRUNCATE #{Rebel::SQL.name(table_name)};
219
+ TRUNCATE #{name(table_name)};
133
220
  SQL
134
221
  end
135
222
 
136
223
  ## Functions
137
224
 
225
+ def function(name, *args)
226
+ raw("#{name}(#{names_or_values(*args)})")
227
+ end
228
+ alias fn function
229
+
138
230
  def count(*n)
139
231
  raw("COUNT(#{names(*n)})")
140
232
  end
@@ -165,7 +257,7 @@ module Rebel::SQL
165
257
  return name if name.is_a?(Raw)
166
258
  return raw('*') if name == '*'
167
259
 
168
- name.to_s.split('.').map { |e| "\"#{e}\"" }.join('.')
260
+ raw(name.to_s.split('.').map { |e| "#{@identifier_quote}#{e}#{@identifier_quote}" }.join('.'))
169
261
  end
170
262
 
171
263
  def names(*names)
@@ -176,11 +268,17 @@ module Rebel::SQL
176
268
  items.join(', ')
177
269
  end
178
270
 
271
+ def escape_str(str)
272
+ str.tr(@string_quote, @escaped_string_quote)
273
+ end
274
+
179
275
  def value(v)
180
276
  case v
181
277
  when Raw then v
182
- when String then raw "'#{v.tr("'", "''")}'"
278
+ when String then raw "'#{escape_str(v)}'"
183
279
  when Integer then raw v.to_s
280
+ when TrueClass, FalseClass then raw(v ? 'TRUE' : 'FALSE')
281
+ when Date, Time, DateTime then value(v.iso8601)
184
282
  when nil then raw 'NULL'
185
283
  else raise NotImplementedError, v.inspect
186
284
  end
@@ -194,6 +292,10 @@ module Rebel::SQL
194
292
  item.is_a?(Symbol) ? name(item) : value(item)
195
293
  end
196
294
 
295
+ def names_or_values(*items)
296
+ list(items.map { |v| name_or_value(v) })
297
+ end
298
+
197
299
  def equal(l, r)
198
300
  "#{name_or_value(l)} = #{name_or_value(r)}"
199
301
  end
@@ -205,28 +307,26 @@ module Rebel::SQL
205
307
  def clause_term(left, right)
206
308
  case right
207
309
  when Array
208
- "#{name(left)} IN (#{values(*right)})"
310
+ name(left).in(*right)
209
311
  else
210
- "#{name(left)} = #{name_or_value(right)}"
312
+ name(left).eq(name_or_value(right))
211
313
  end
212
314
  end
213
315
 
214
- def and_clause(clause)
215
- return clause if clause.is_a?(Raw) || clause.is_a?(String)
216
-
316
+ def and_clause(*clause)
217
317
  clause.map do |e|
218
318
  case e
319
+ when Hash then and_clause(*e.to_a)
219
320
  when Array then clause_term(e[0], e[1])
220
- when Raw, String then e
321
+ when Raw then e.parens?
322
+ when String then e
221
323
  else raise NotImplementedError, e.class
222
324
  end
223
325
  end.join(' AND ')
224
326
  end
225
327
 
226
- def where?(clause)
227
- return "WHERE #{clause}" if clause.is_a?(Raw) || clause.is_a?(String)
228
-
229
- clause && clause.any? ? "WHERE #{Rebel::SQL.and_clause(clause)}" : nil
328
+ def where?(*clause)
329
+ clause.any? ? "WHERE #{and_clause(*clause)}" : nil
230
330
  end
231
331
 
232
332
  def inner?(join)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rebel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loic Nageleisen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-01 00:00:00.000000000 Z
11
+ date: 2017-03-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: SQL-flavoured Ruby, or is it the other way around?
14
14
  email: loic.nageleisen@gmail.com
@@ -38,7 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
38
38
  version: '0'
39
39
  requirements: []
40
40
  rubyforge_project:
41
- rubygems_version: 2.6.10
41
+ rubygems_version: 2.5.2
42
42
  signing_key:
43
43
  specification_version: 4
44
44
  summary: Fight against the Object tyranny