user_query 0.1.0

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.
Files changed (69) hide show
  1. data/ChangeLog +4 -0
  2. data/README +45 -0
  3. data/Rakefile +359 -0
  4. data/Releases +6 -0
  5. data/TODO +0 -0
  6. data/examples/userqueryex/HOWTO.txt +5 -0
  7. data/examples/userqueryex/README +183 -0
  8. data/examples/userqueryex/Rakefile +10 -0
  9. data/examples/userqueryex/WHAT.txt +16 -0
  10. data/examples/userqueryex/app/controllers/application.rb +4 -0
  11. data/examples/userqueryex/app/controllers/entries_controller.rb +68 -0
  12. data/examples/userqueryex/app/helpers/application_helper.rb +3 -0
  13. data/examples/userqueryex/app/helpers/entries_helper.rb +2 -0
  14. data/examples/userqueryex/app/models/entry.rb +8 -0
  15. data/examples/userqueryex/app/views/entries/_form.rhtml +20 -0
  16. data/examples/userqueryex/app/views/entries/edit.rhtml +9 -0
  17. data/examples/userqueryex/app/views/entries/list.rhtml +75 -0
  18. data/examples/userqueryex/app/views/entries/new.rhtml +8 -0
  19. data/examples/userqueryex/app/views/entries/show.rhtml +8 -0
  20. data/examples/userqueryex/app/views/layouts/entries.rhtml +13 -0
  21. data/examples/userqueryex/config/boot.rb +44 -0
  22. data/examples/userqueryex/config/database.yml +36 -0
  23. data/examples/userqueryex/config/environment.rb +54 -0
  24. data/examples/userqueryex/config/environments/development.rb +21 -0
  25. data/examples/userqueryex/config/environments/production.rb +18 -0
  26. data/examples/userqueryex/config/environments/test.rb +19 -0
  27. data/examples/userqueryex/config/routes.rb +22 -0
  28. data/examples/userqueryex/db/migrate/001_entry_migration.rb +16 -0
  29. data/examples/userqueryex/db/schema.rb +15 -0
  30. data/examples/userqueryex/doc/README_FOR_APP +2 -0
  31. data/examples/userqueryex/public/404.html +8 -0
  32. data/examples/userqueryex/public/500.html +8 -0
  33. data/examples/userqueryex/public/dispatch.cgi +10 -0
  34. data/examples/userqueryex/public/dispatch.fcgi +24 -0
  35. data/examples/userqueryex/public/dispatch.rb +10 -0
  36. data/examples/userqueryex/public/favicon.ico +0 -0
  37. data/examples/userqueryex/public/images/rails.png +0 -0
  38. data/examples/userqueryex/public/javascripts/application.js +2 -0
  39. data/examples/userqueryex/public/javascripts/controls.js +815 -0
  40. data/examples/userqueryex/public/javascripts/dragdrop.js +913 -0
  41. data/examples/userqueryex/public/javascripts/effects.js +958 -0
  42. data/examples/userqueryex/public/javascripts/prototype.js +2006 -0
  43. data/examples/userqueryex/public/robots.txt +1 -0
  44. data/examples/userqueryex/public/stylesheets/scaffold.css +74 -0
  45. data/examples/userqueryex/script/about +3 -0
  46. data/examples/userqueryex/script/breakpointer +3 -0
  47. data/examples/userqueryex/script/console +3 -0
  48. data/examples/userqueryex/script/destroy +3 -0
  49. data/examples/userqueryex/script/generate +3 -0
  50. data/examples/userqueryex/script/performance/benchmarker +3 -0
  51. data/examples/userqueryex/script/performance/profiler +3 -0
  52. data/examples/userqueryex/script/plugin +3 -0
  53. data/examples/userqueryex/script/process/reaper +3 -0
  54. data/examples/userqueryex/script/process/spawner +3 -0
  55. data/examples/userqueryex/script/runner +3 -0
  56. data/examples/userqueryex/script/server +3 -0
  57. data/examples/userqueryex/test/fixtures/entries.yml +5 -0
  58. data/examples/userqueryex/test/functional/entries_controller_test.rb +88 -0
  59. data/examples/userqueryex/test/test_helper.rb +28 -0
  60. data/examples/userqueryex/test/unit/entry_test.rb +10 -0
  61. data/lib/user_query.rb +10 -0
  62. data/lib/user_query/generator.rb +219 -0
  63. data/lib/user_query/parameters.rb +93 -0
  64. data/lib/user_query/parser.rb +762 -0
  65. data/lib/user_query/schema.rb +159 -0
  66. data/lib/user_query/user_query_version.rb +6 -0
  67. data/test/parser_test.rb +539 -0
  68. data/test/schema_test.rb +142 -0
  69. metadata +148 -0
@@ -0,0 +1,159 @@
1
+ # This class defined how query parameters are to be interpreted.
2
+ #
3
+ module UserQuery
4
+
5
+ class Schema
6
+ @active_record_base = false
7
+ begin
8
+ # Kernel.require 'active_record'
9
+ @@active_record_base = ActiveRecord::Base
10
+ rescue Object => err
11
+ @@active_record_base = false
12
+ end
13
+
14
+ @@empty_hash = { }
15
+ @@empty_hash.freeze
16
+
17
+ attr_accessor :verbose
18
+
19
+ def initialize(*opts)
20
+ @opt = Hash[*opts]
21
+
22
+ @verbose = @opt[:verbose]
23
+
24
+ @field_by_name = { }
25
+ @field = [ ]
26
+
27
+ field = @opt[:field]
28
+ field = [ field ] unless field.kind_of?(Array)
29
+ field.each{|x| add_field(x)}
30
+
31
+ # Interpret ActiveRecord::Base subclass
32
+ cls = @opt[:table]
33
+ if is_active_record?(cls)
34
+ columns = cls.columns
35
+ table_name = cls.table_name;
36
+ columns.each do |col|
37
+ field = {
38
+ :table => table_name,
39
+ :name => col.name,
40
+ :type => col.type,
41
+ }
42
+ field = add_field(field)
43
+ # $stderr.puts "AR::Base column #{col.inspect} =>\n #{field.inspect}"
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ def is_active_record?(cls)
50
+ return false unless cls.kind_of?(Class)
51
+ while cls
52
+ if cls == @@active_record_base
53
+ return true;
54
+ end
55
+ cls = cls.superclass
56
+ end
57
+ false
58
+ end
59
+
60
+ private
61
+
62
+ def add_field(field)
63
+ field = { :name => field } unless field.kind_of?(Array) || field.kind_of?(Hash)
64
+ field = { :name => field[0], :type => field[1], :table => field[2] } if field.kind_of?(Array)
65
+
66
+ # Normalize name.
67
+ field[:name] = field[:name].intern if field[:name].respond_to?(:intern);
68
+
69
+ # Normalize table.
70
+ field[:table] ||= @opt[:table]
71
+ field[:table] = sql_table_name(field[:table])
72
+
73
+ return nil if (@field_by_name[field[:table]] ||= {})[field[:name]]
74
+
75
+ # Normalize type
76
+ field[:type] ||= :string
77
+ field[:type] = :string if field[:type] == :text
78
+ field[:type] = :number if field[:type] == :integer
79
+ field[:type] = :datetime if field[:type] == :date
80
+
81
+ # Keep track of by table.column name.
82
+ (@field_by_name[field[:table]] ||= {})[field[:name]] = field;
83
+ @field << field
84
+
85
+ field
86
+ end
87
+
88
+ def sql_table_name(x)
89
+ x && (x.kind_of?(String) ? x : x.table_name)
90
+ end
91
+
92
+ def sql_field_table_name(field)
93
+ sql_table_name(field[:table] || @opt[:table])
94
+ end
95
+
96
+ def sql_expr(field)
97
+ field[:sql_expr] || sql_table_column(sql_field_table_name(field), field[:name].to_s)
98
+ end
99
+
100
+ def sql_table_column(table, column)
101
+ table ? table + '.' + column : column
102
+ end
103
+
104
+ public
105
+
106
+ def sql(parameters, record = nil)
107
+ record ||= parameters if parameters.respond_to?(:errors)
108
+
109
+
110
+ sql = @field.map do |field|
111
+ f_sql = nil
112
+ begin
113
+ name = field[:name]
114
+ type = field[:type]
115
+
116
+ verbose = field[:verbose] || @verbose
117
+
118
+ target = sql_expr(field)
119
+
120
+ parameter = parameters.kind_of?(Hash) ?
121
+ parameters[name] :
122
+ parameters.send(name)
123
+
124
+ query_expr = UserQuery::Parser.
125
+ new(:type => type,
126
+ :verbose => verbose).
127
+ parse(parameter)
128
+
129
+ f_sql = UserQuery::Generator.
130
+ new(:type => type,
131
+ :target => target,
132
+ :verbose => verbose).
133
+ sql(query_expr)
134
+
135
+ if verbose
136
+ $stderr.puts "name = #{name.inspect}"
137
+ $stderr.puts "target = #{target.inspect}"
138
+ $stderr.puts "type = #{type.inspect}"
139
+ $stderr.puts "query = #{parameter.inspect}"
140
+ $stderr.puts "sql = #{f_sql.inspect}"
141
+ end
142
+
143
+ rescue UserQuery::Parser::SyntaxError => err
144
+ record.errors.add(name, err.to_s) if record
145
+ $stderr.puts "\n#{self.class.name}: Error: #{err}" if verbose
146
+ f_sql = nil
147
+ end
148
+
149
+ f_sql
150
+ end.compact.join(' AND ')
151
+
152
+ sql = nil if sql.empty?
153
+
154
+ sql
155
+ end
156
+
157
+ end
158
+
159
+ end # module
@@ -0,0 +1,6 @@
1
+ # DO NOT EDIT
2
+ # This file is auto-generated by build scripts.
3
+ # See: rake update_version
4
+ module UserQuery
5
+ UserQueryVersion = '0.1.0'
6
+ end
@@ -0,0 +1,539 @@
1
+ # $Id$
2
+ # REAL
3
+ #require File.dirname(__FILE__) + '/../test_helper'
4
+
5
+ require 'test/unit'
6
+ require 'user_query'
7
+ #require 'currency' # OPTIONAL
8
+
9
+ module UserQuery
10
+
11
+ class ParserTest < Test::Unit::TestCase
12
+
13
+ @@has_currency = false
14
+ begin
15
+ Kernel.require 'currency' # For :type => :money
16
+ @@has_currency = true
17
+ rescue Object => err
18
+ $stderr.puts "Error loading currency: skipping Currency tests\n#{err}"
19
+ @@has_currency = false
20
+ end
21
+
22
+
23
+ def setup
24
+ super
25
+ end
26
+
27
+ ############################################
28
+ # Simple stuff.
29
+ #
30
+
31
+ def test_create
32
+ assert_not_nil qp = UserQuery::Parser.
33
+ new()
34
+
35
+ qp
36
+ end
37
+
38
+ def test_empty
39
+ qp = test_create
40
+ assert_equal qp << ' ', nil
41
+ end
42
+
43
+ def test_bad_syntax
44
+ qp = test_create
45
+
46
+ assert_raises(UserQuery::Parser::SyntaxError) {qp << '##@!@'}
47
+ end
48
+
49
+ def test_trailing_tokens
50
+ qp = test_create
51
+
52
+ assert_raises(UserQuery::Parser::SyntaxError) {qp << '=Foo bar'}
53
+ end
54
+
55
+ def test_word
56
+ qp = test_create
57
+ assert_equal [:like, [:word, 'hello', 'hello']], qp << 'hello'
58
+
59
+ assert_equal [:like, [:word, 'NOTfoo', 'NOTfoo']], qp << 'NOTfoo'
60
+
61
+ assert_equal [:like, [:word, 'true', 'true']], qp << 'true'
62
+
63
+ assert_equal [:like, [:word, 'FALSE', 'FALSE']], qp << 'FALSE'
64
+ end
65
+
66
+ def test_word_trailing_whitespace
67
+ qp = test_create
68
+ assert_equal [:like, [:word, 'hello', 'hello']], qp << 'hello '
69
+ end
70
+
71
+ def test_string
72
+ qp = test_create
73
+ assert_equal [:like, [:string, "", ""]], qp << ' "" '
74
+ assert_equal [:like, [:string, " ", " "]], qp << ' " " '
75
+ assert_equal [:like, [:string, 'hello world!', 'hello world!']], qp << '"hello world!"'
76
+ end
77
+
78
+ def test_string_escape
79
+ qp = test_create
80
+ # qp.verbose = 1
81
+ assert_equal [:like, [:string, "\\", "\\"]], qp << '"\\\\"'
82
+ assert_equal [:like, [:string, "\"", "\""]], qp << '"\\""'
83
+ assert_equal [:like, [:string, "\"foo\"", "\"foo\""]], qp << '"\\"foo\\""'
84
+ assert_equal [:like, [:string, "he\\llo \"world!", "he\\llo \"world!"]], qp << '"he\\\\llo \"world!"'
85
+ end
86
+
87
+ def test_integer
88
+ qp = test_create
89
+ assert_equal [:eq, [:number, '123', 123]], qp << 123
90
+ assert_equal [:eq, [:number, '123', 123]], qp << '123'
91
+ assert_equal [:eq, [:number, '-123', -123]], qp << '-123'
92
+ assert_equal [:eq, [:number, '-123', -123]], qp << ' -123'
93
+ assert_equal [:eq, [:number, '+1234', 1234]], qp << '+1234'
94
+ end
95
+
96
+ def test_integer_like
97
+ qp = test_create
98
+ assert_equal [:like, [:string, '123', '123']], qp << 'LIKE 123'
99
+ end
100
+
101
+ def test_float
102
+ qp = test_create
103
+ assert_equal [:eq, [:number, '1.23', 1.23]], qp << 1.23
104
+ assert_equal [:eq, [:number, '1.23', 1.23]], qp << '1.23'
105
+ assert_equal [:eq, [:number, '-12.34', -12.34]], qp << '-12.34'
106
+ assert_equal [:eq, [:number, '-0.3', -0.3]], qp << '-0.3'
107
+ assert_equal [:eq, [:number, '+1.2e10', 1.2e10]], qp << '+1.2e10'
108
+ assert_equal [:eq, [:number, '0.25e-8', 0.25e-8]], qp << '0.25e-8'
109
+ end
110
+
111
+ def test_boolean
112
+ qp = test_create
113
+
114
+ qp.type = :boolean
115
+ # qp.verbose = true
116
+ assert_equal [:eq, [:boolean, 'true', true ]], qp << 'true'
117
+ assert_equal [:eq, [:boolean, 'false', false ]], qp << 'false'
118
+ end
119
+
120
+ def test_money
121
+ return true unless @@has_currency
122
+
123
+ qp = test_create
124
+
125
+ qp.type = :money
126
+ # qp.verbose = true
127
+ assert_equal [:eq, [:money, '123', Currency::Money.new('123')]], qp << '123'
128
+ assert_equal [:eq, [:money, '123.00', Currency::Money.new('123')]], qp << '123.00'
129
+ assert_equal [:eq, [:money, '-123.00', Currency::Money.new('-123')]], qp << '-123.00'
130
+ assert_equal [:eq, [:money, '123.45', Currency::Money.new('123.45')]], qp << '123.45'
131
+ assert_equal [:gt, [:money, '1,234.56', Currency::Money.new('1234.56')]], qp << '>1,234.56'
132
+ assert_equal [:eq, [:money, '$123', Currency::Money.new('123')]], qp << '$123'
133
+ assert_equal [:eq, [:money, '$123.00', Currency::Money.new('123')]], qp << '$123.00'
134
+ assert_equal [:eq, [:money, '$-123.00', Currency::Money.new('-123')]], qp << '$-123.00'
135
+ assert_equal [:eq, [:money, '$123.45', Currency::Money.new('123.45')]], qp << '$123.45'
136
+ assert_equal [:gt, [:money, '$1,234.56', Currency::Money.new('1234.56')]], qp << '>$1,234.56'
137
+ end
138
+
139
+ def test_sequence
140
+ qp = test_create
141
+ # qp.verbose = true
142
+ assert_equal [:and, [:like, [:word, 'hello', 'hello']], [:like, [:word, 'world', 'world']]], qp << 'hello world'
143
+ end
144
+
145
+ def test_between
146
+ qp = test_create
147
+ assert_equal [:between, [:number, '1', 1], [:number, '5', 5]], qp << 'BETWEEN 1 AND 5'
148
+ assert_equal [:between, [:number, '2', 2], [:number, '199', 199]], qp << 'BETWEEN 2 ... 199'
149
+
150
+ assert_equal [:between, [:word, 'abraxas', 'abraxas'], [:word, 'zebra', 'zebra']], qp << 'BETWEEN abraxas...zebra'
151
+ end
152
+
153
+ def test_elipsis
154
+ qp = test_create
155
+ assert_equal [:between, [:number, '1', 1], [:number, '19', 19]], qp << '1 ... 19'
156
+ end
157
+
158
+ def test_and
159
+ qp = test_create
160
+ assert_equal [:and,
161
+ [:like, [:word, 'foo', 'foo']],
162
+ [:and,
163
+ [:like, [:word, 'bar', 'bar']],
164
+ [:like, [:word, 'baz', 'baz']]]],
165
+ qp << 'foo AND bar AND baz'
166
+
167
+ qp = test_create
168
+ assert_equal [:and,
169
+ [:like, [:word, 'foo', 'foo']],
170
+ [:and,
171
+ [:like, [:word, 'bar', 'bar']],
172
+ [:not, [:like, [:word, 'baz', 'baz']]]]],
173
+ qp << 'foo AND bar AND !baz'
174
+ end
175
+
176
+ def test_and_or
177
+ qp = test_create
178
+ assert_equal [:or,
179
+ [:and,
180
+ [:like, [:word, 'foo', 'foo']],
181
+ [:like, [:word, 'bar', 'bar']]],
182
+ [:like, [:word, 'baz', 'baz']]],
183
+ qp << 'foo AND bar OR baz'
184
+ end
185
+
186
+ def test_not
187
+ qp = test_create
188
+
189
+ assert_equal [:not,
190
+ [:like, [:word, 'foo', 'foo']]
191
+ ],
192
+ qp << 'NOT foo'
193
+
194
+ #qp.verbose = true
195
+
196
+ assert_equal [:not,
197
+ [:and,
198
+ [:like, [:word, 'foo', 'foo']],
199
+ [:like, [:word, 'bar', 'bar']]
200
+ ]
201
+ ],
202
+ qp << 'NOT (foo AND bar)'
203
+
204
+
205
+ assert_equal [:not,
206
+ [:and,
207
+ [:like, [:word, 'foo', 'foo']],
208
+ [:like, [:word, 'bar', 'bar']]
209
+ ]
210
+ ],
211
+ qp << 'NOT foo bar'
212
+
213
+ end
214
+
215
+ def test_grouping
216
+ qp = test_create
217
+ #qp.verbose = true
218
+
219
+ assert_equal [:or,
220
+ [:and,
221
+ [:like,
222
+ [:word, 'foo', 'foo']
223
+ ],
224
+ [:like,
225
+ [:word, 'bar', 'bar']
226
+ ]],
227
+ [:like,
228
+ [:word, 'baz', 'baz']
229
+ ]],
230
+ qp << '(foo AND bar) OR baz'
231
+
232
+ qp = test_create
233
+ assert_equal [:and,
234
+ [:like,
235
+ [:word, 'foo', 'foo']
236
+ ],
237
+ [:or,
238
+ [:like,
239
+ [:word, 'bar', 'bar']
240
+ ],
241
+ [:like,
242
+ [:word, 'baz', 'baz']
243
+ ]]],
244
+ qp << 'foo AND (bar OR baz)'
245
+ end
246
+
247
+ def test_year
248
+ qp = test_create
249
+ qp.type = :datetime
250
+
251
+ assert_equal [:range, [:year, '2006', 2006], [:year, '2006', 2007]], qp << '2006'
252
+ end
253
+
254
+ def test_month
255
+ qp = test_create
256
+ qp.type = :datetime
257
+
258
+ assert_equal [:range,
259
+ [:month, '4/2006', 2006, 4],
260
+ [:month, '4/2006', 2006, 5]],
261
+ qp << '4/2006'
262
+
263
+ assert_equal [:range,
264
+ [:month, '04/2006', 2006, 4],
265
+ [:month, '04/2006', 2006, 5]],
266
+ qp << '04/2006'
267
+
268
+ assert_equal [:range,
269
+ [:month, '12/2006', 2006, 12],
270
+ [:month, '12/2006', 2007, 1]],
271
+ qp << '12/2006'
272
+ end
273
+
274
+ def test_day
275
+ qp = test_create
276
+ qp.type = :datetime
277
+
278
+ assert_equal [:range,
279
+ [:day, '2/4/2006', 2006, 2, 4],
280
+ [:day, '2/4/2006', 2006, 2, 5]],
281
+ qp << '2/4/2006'
282
+
283
+ assert_equal [:range,
284
+ [:day, '2/04/2006', 2006, 2, 4],
285
+ [:day, '2/04/2006', 2006, 2, 5]],
286
+ qp << '2/04/2006'
287
+
288
+ assert_equal [:range,
289
+ [:day, '02/04/2006', 2006, 2, 4],
290
+ [:day, '02/04/2006', 2006, 2, 5]],
291
+ qp << '02/04/2006'
292
+
293
+ assert_equal [:range,
294
+ [:day, '02/4/2006', 2006, 2, 4],
295
+ [:day, '02/4/2006', 2006, 2, 5]],
296
+ qp << '02/4/2006'
297
+
298
+ assert_equal [:range,
299
+ [:day, '12/4/2006', 2006, 12, 4],
300
+ [:day, '12/4/2006', 2006, 12, 5]],
301
+ qp << '12/4/2006'
302
+
303
+ assert_equal [:range,
304
+ [:day, '12/04/2006', 2006, 12, 4],
305
+ [:day, '12/04/2006', 2006, 12, 5]],
306
+ qp << '12/04/2006'
307
+
308
+ assert_equal [:range,
309
+ [:day, '12/31/2006', 2006, 12, 31],
310
+ [:day, '12/31/2006', 2007, 1, 1]],
311
+ qp << '12/31/2006'
312
+
313
+ qp.this_year = 2006
314
+ assert_equal [:range,
315
+ [:day, '12/31', 2006, 12, 31],
316
+ [:day, '12/31', 2007, 1, 1]],
317
+ qp << '12/31'
318
+ end
319
+
320
+ def test_hour
321
+ qp = test_create
322
+ qp.type = :datetime
323
+
324
+ assert_equal [:range,
325
+ [:hour, '2/4/2006 12am', 2006, 2, 4, 0],
326
+ [:hour, '2/4/2006 12am', 2006, 2, 4, 1]],
327
+ qp << '2/4/2006 12am'
328
+
329
+ assert_equal [:range,
330
+ [:hour, '2/4/2006 5', 2006, 2, 4, 5],
331
+ [:hour, '2/4/2006 5', 2006, 2, 4, 6]],
332
+ qp << '2/4/2006 5'
333
+ assert_equal [:range,
334
+ [:hour, '2/4/2006-5 AM', 2006, 2, 4, 5],
335
+ [:hour, '2/4/2006-5 AM',2006, 2, 4, 6]],
336
+ qp << '2/4/2006-5 AM'
337
+
338
+ assert_equal [:range,
339
+ [:hour, '2/4/2006 12P', 2006, 2, 4, 12],
340
+ [:hour, '2/4/2006 12P', 2006, 2, 4, 13]],
341
+ qp << '2/4/2006 12P'
342
+
343
+ assert_equal [:range,
344
+ [:hour, '2/4/2006-2pm', 2006, 2, 4, 14],
345
+ [:hour, '2/4/2006-2pm', 2006, 2, 4, 15]],
346
+ qp << '2/4/2006-2pm'
347
+
348
+ assert_equal [:range,
349
+ [:hour, '2/4/2006-14', 2006, 2, 4, 14],
350
+ [:hour, '2/4/2006-14', 2006, 2, 4, 15]], qp << '2/4/2006-14'
351
+
352
+ end
353
+
354
+ def test_minute
355
+ qp = test_create
356
+ qp.type = :datetime
357
+
358
+ assert_equal [:range,
359
+ [:minute, '2/4/2006 12:30am', 2006, 2, 4, 0, 30],
360
+ [:minute, '2/4/2006 12:30am', 2006, 2, 4, 0, 31 ]],
361
+ qp << '2/4/2006 12:30am'
362
+
363
+ assert_equal [:range,
364
+ [:minute, '2/4/2006 9:00p', 2006, 2, 4, 21, 00],
365
+ [:minute, '2/4/2006 9:00p', 2006, 2, 4, 21, 01 ]],
366
+ qp << '2/4/2006 9:00p'
367
+
368
+ assert_equal [:range,
369
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 30],
370
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 31 ]],
371
+ qp << '2/4/2006 1430'
372
+
373
+
374
+ end
375
+
376
+ def test_second
377
+ qp = test_create
378
+ qp.type = :datetime
379
+
380
+ assert_equal [:range,
381
+ [:second, '2/4/2006 12:30:00am', 2006, 2, 4, 0, 30, 00 ],
382
+ [:second, '2/4/2006 12:30:00am', 2006, 2, 4, 0, 30, 01 ]],
383
+ qp << '2/4/2006 12:30:00am'
384
+
385
+ assert_equal [:range,
386
+ [:second, '2/4/2006 9:00:05p', 2006, 2, 4, 21, 00, 05 ],
387
+ [:second, '2/4/2006 9:00:05p', 2006, 2, 4, 21, 00, 06 ]],
388
+ qp << '2/4/2006 9:00:05p'
389
+
390
+ assert_equal [:range,
391
+ [:second, '2/4/2006 9:00:59p', 2006, 2, 4, 21, 00, 59 ],
392
+ [:second, '2/4/2006 9:00:59p', 2006, 2, 4, 21, 01, 00 ]],
393
+ qp << '2/4/2006 9:00:59p'
394
+
395
+ assert_equal [:range,
396
+ [:second, '2/4/2006 143033', 2006, 2, 4, 14, 30, 33 ],
397
+ [:second, '2/4/2006 143033', 2006, 2, 4, 14, 30, 34 ]],
398
+ qp << '2/4/2006 143033'
399
+
400
+
401
+ end
402
+
403
+ def test_time_now
404
+ qp = test_create
405
+ qp.type = :datetime
406
+
407
+ qp.now = Time.utc(2006, 2, 4, 0, 30, 15)
408
+ assert_equal [:range,
409
+ [:second, 'now', 2006, 2, 4, 0, 30, 15 ],
410
+ [:second, 'now', 2006, 2, 4, 0, 30, 16 ]],
411
+ qp << 'now'
412
+ end
413
+
414
+ def test_time_today
415
+ qp = test_create
416
+ qp.type = :datetime
417
+
418
+ qp.now = Time.utc(2006, 2, 4, 0, 30, 15)
419
+ assert_equal [:range,
420
+ [:day, 'today', 2006, 2, 4 ],
421
+ [:day, 'today', 2006, 2, 5 ]],
422
+ qp << 'today'
423
+
424
+
425
+ assert_equal [:range,
426
+ [:day, 'tomorrow', 2006, 2, 5 ],
427
+ [:day, 'tomorrow', 2006, 2, 6 ]],
428
+ qp << 'tomorrow'
429
+
430
+ assert_equal [:range,
431
+ [:day, 'yesterday', 2006, 2, 3 ],
432
+ [:day, 'yesterday', 2006, 2, 4 ]],
433
+ qp << 'yesterday'
434
+ end
435
+
436
+
437
+ def test_time_this_year
438
+ qp = test_create
439
+ qp.type = :datetime
440
+
441
+ qp.now = Time.utc(2006, 2, 4, 0, 30, 15)
442
+ assert_equal [:range,
443
+ [:year, 'this year', 2006 ],
444
+ [:year, 'this year', 2007 ]],
445
+ qp << 'this year'
446
+ end
447
+
448
+
449
+ def test_time_today_relative
450
+ qp = test_create
451
+ qp.type = :datetime
452
+
453
+ qp.now = Time.utc(2006, 2, 4, 0, 30, 15)
454
+ assert_equal [:range,
455
+ [:day, 'today+1', 2006, 2, 5 ],
456
+ [:day, 'today+1', 2006, 2, 6 ]],
457
+ qp << 'today+1'
458
+
459
+ qp.now = Time.utc(2006, 2, 4, 0, 30, 15)
460
+ assert_equal [:range,
461
+ [:day, 'today-2', 2006, 2, 2 ],
462
+ [:day, 'today-2', 2006, 2, 3 ]],
463
+ qp << 'today-2'
464
+ end
465
+
466
+
467
+ def test_between_day_and_year
468
+ qp = test_create
469
+ qp.type = :datetime
470
+
471
+ assert_equal [:between, [:day, '2/4/2006', 2006, 2, 4], [:year, '2007', 2007]], qp << 'BETWEEN 2/4/2006 AND 2007'
472
+
473
+ assert_equal [:between, [:day, '2/4/2006', 2006, 2, 4], [:year, '2007', 2007]], qp << '2/4/2006...2007'
474
+ end
475
+
476
+
477
+ def test_bad_between
478
+ qp = test_create
479
+
480
+ assert_raises(UserQuery::Parser::SyntaxError) {qp << 'BETWEEN 1 AND FOO'}
481
+ assert_equal [:between, [:number, '1', 1], [:number, '5', 5]], qp << 'BETWEEN 1 AND 5'
482
+
483
+ assert_equal [:between, [:word, 'BAR', 'BAR'], [:string, 'BAZ', 'BAZ']], qp << 'BETWEEN BAR AND "BAZ"'
484
+
485
+ qp.type = :datetime
486
+ assert_raises(UserQuery::Parser::SyntaxError) {qp << 'BETWEEN 12/31/2006 AND FOO'}
487
+ end
488
+
489
+ def test_eq
490
+ qp = test_create
491
+ assert_equal [:eq, [:number, '45', 45]], qp << '=45'
492
+ assert_equal [:eq, [:number, '123', 123]], qp << '= 123'
493
+
494
+ qp.type = :datetime
495
+ assert_equal [:range,
496
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 30],
497
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 31 ]],
498
+ qp << '= 2/4/2006 1430'
499
+ assert_equal [:range,
500
+ [:hour, '2/4/2006 5', 2006, 2, 4, 5],
501
+ [:hour, '2/4/2006 5', 2006, 2, 4, 6]],
502
+ qp << ' = 2/4/2006 5'
503
+ assert_equal [:range,
504
+ [:month, '12/2006', 2006, 12],
505
+ [:month, '12/2006', 2007, 1]],
506
+ qp << 'EQUAL TO 12/2006'
507
+
508
+ end
509
+
510
+ def test_ne
511
+ qp = test_create
512
+ assert_equal [:ne, [:number, '76', 76]], qp << '!=76'
513
+ assert_equal [:ne, [:number, '34', 34]], qp << '<> 34'
514
+ assert_equal [:ne, [:number, '123', 123]], qp << '<>123'
515
+
516
+ qp.type = :datetime
517
+ assert_equal [:or,
518
+ [:lt,
519
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 30]],
520
+ [:ge,
521
+ [:minute, '2/4/2006 1430', 2006, 2, 4, 14, 31 ]]],
522
+ qp << '<> 2/4/2006 1430'
523
+ end
524
+
525
+ def test_complex_1
526
+ qp = test_create
527
+ # qp.verbose = true
528
+ assert_equal [:and,
529
+ [:lt, [:number, '5', 5]],
530
+ [:gt, [:number, '2', 2]]
531
+ ],
532
+ qp << '<5 AND >2'
533
+ end
534
+
535
+
536
+ end
537
+
538
+ end # module
539
+