groonga-client 0.4.3 → 0.5.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: 3dd4add841527a3ebe6c5e9a0e9cc83bb618a973
4
- data.tar.gz: 3946ccfce7f6e1aa7e3105760fa0a305885ca629
3
+ metadata.gz: 6f33db5326ba66ef34f99764539597e287337df5
4
+ data.tar.gz: ba050f7b65edc1889f843cef883e1784b29c1b8a
5
5
  SHA512:
6
- metadata.gz: 7a131ca1ab2cb04af14a5bb43e83dbac2f793e040c777354125bad17399453cdf26ef17390e931ce60b241b3cb3806131589cdd2fe836ec683ebb696ccf1ebe9
7
- data.tar.gz: '080dec40f5d1b28a4b55c3d6e30e7c48261a6f0db3bffccdd7c55b755f2e59ac77bdb8dd909d4f1a53f901cf4d0f36c5eb1d0278c3d2872902a1cda7c7daa182'
6
+ metadata.gz: a7869a7e5ac081ed34339ae21665ff97802ed473eb765cb7ef388420319ee5396ab95bde8162a37e0fc434a989aa0a3daa9808d9072b239f34d7704875230afb
7
+ data.tar.gz: 44ffaaa3ec83082d908db61985675827684cb8e850317a9363ddebecf1fe84cc1cd52eb96ed7dd27f299fbe90ddd7aefcf0c2efe763a1a67de8c3c7a7f4bce92
data/doc/text/news.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # NEWS
2
2
 
3
+ ## 0.5.0 - 2017-05-08
4
+
5
+ ### Improvements
6
+
7
+ * `Groonga::Client::Request::Select::Filter#between`: Added a
8
+ convenience method to add a popular filter condition. You can
9
+ use this method by
10
+ `filter.between(:age, 19, "include", 32, "include")`.
11
+
12
+ * `Groonga::Client::Request::Select::Filter#geo_in_circle`:
13
+ Added a convenience method to add a popular filter condition.
14
+ You can use this method by
15
+ `filter.geo_in_circle(:location, "100x100", 300, "rectangle")`.
16
+
17
+ * `Groonga::Client::Request::Select::Filter#geo_in_rectangle`:
18
+ Added a convenience method to add a popular filter condition.
19
+ You can use this method by
20
+ `filter.geo_in_rectangle(:location, "0x100", "100x0")`.
21
+
22
+ * `Groonga::Client::Request::Select#filter`: Changed how to handle
23
+ `Symbol` to identifier in Groonga script syntax expression from
24
+ string literal in Groonga script syntax expression. It's a
25
+ backward incompatible change. Some methods keep compatibility as
26
+ much as possible but some methods may break compatibility
27
+ unexpectedly. If you find any incompatibility what you think
28
+ unexpected, please report to us.
29
+
30
+ ### Fixes
31
+
32
+ * `groonga-client`: Fixed a bug that `load --values` input causes an
33
+ error.
34
+
3
35
  ## 0.4.3 - 2017-04-21
4
36
 
5
37
  ### Improvements
@@ -185,8 +217,8 @@
185
217
 
186
218
  * Supported command version 3.
187
219
 
188
- * Added {Groonga::Client::Response#return_code}.
189
- {Groonga::Client::Response#status_code} is deprecated. Use
220
+ * Added `Groonga::Client::Response#return_code`.
221
+ `Groonga::Client::Response#status_code` is deprecated. Use
190
222
  `#return_code` instead.
191
223
 
192
224
  * `select` response: Supported vector of `Time`.
@@ -251,10 +283,11 @@
251
283
  [GitHub#7][Patch by Masafumi Yokoyama]
252
284
 
253
285
  * HTTP: Supported HTTPS by passing `:use_tls => true` option to
254
- {Groonga::Client.new}.
286
+ {Groonga::Client#initialize}.
255
287
  [GitHub#8][Patch by KITAITI Makoto]
256
288
 
257
- * Supported URI as server information in {Groonga::Client.new}.
289
+ * Supported URI as server information in
290
+ {Groonga::Client#initialize}.
258
291
 
259
292
  * Required groonga-command 1.2.0 or later.
260
293
 
@@ -413,7 +446,7 @@
413
446
  * select: Supported auto time value conversion.
414
447
  * select: Renamed to {Groonga::Client::Response::Select#n_hits}
415
448
  from #n_records. It is a backward incompatible change.
416
- * Added {Groonga::Client::Connection::Error} as an abstracted error.
449
+ * Added `Groonga::Client::Connection::Error` as an abstracted error.
417
450
  * Required groonga-command 1.0.4 or later.
418
451
 
419
452
  ## 0.0.2 - 2013-07-08
@@ -190,7 +190,7 @@ module Groonga
190
190
 
191
191
  parser.on_load_complete do |command|
192
192
  if command[:values]
193
- run_command(client, command)
193
+ run_command(command)
194
194
  else
195
195
  consume_load_values(command)
196
196
  end
@@ -50,9 +50,9 @@ module Groonga
50
50
  # Adds a script syntax condition. If the request already has
51
51
  # any filter condition, they are combined by AND.
52
52
  #
53
- # @example: Multiple filters
53
+ # @example Multiple filters
54
54
  # request.
55
- # filter("user", "alice").
55
+ # filter(:user, "alice").
56
56
  # # -> --filter 'user == "alice"'
57
57
  # filter("tags @ %{tag}", tag: "Ruby")
58
58
  # # -> --filter '(user == "alice") && (tags @ "Ruby")'
@@ -63,7 +63,7 @@ module Groonga
63
63
  # @overload filter(column_name, value)
64
64
  # Adds a `#{column_name} == #{value}` condition.
65
65
  #
66
- # @param column_name [String, Symbol] The target column name.
66
+ # @param column_name [Symbol] The target column name.
67
67
  #
68
68
  # @param value [Object] The column value. It's escaped
69
69
  # automatically.
@@ -88,31 +88,59 @@ module Groonga
88
88
  # Returns a request object for filter condition. It provides
89
89
  # convenient methods to add a popular filter condition.
90
90
  #
91
- # @example: Use in_values function
91
+ # @example Use in_values function
92
92
  # request.
93
- # filter.in_values("tags", "tag1", "tag2")
93
+ # filter.in_values(:tags, "tag1", "tag2")
94
94
  # # -> --filter 'in_values(tags, "tag1", "tag2")'
95
95
  #
96
+ # @example: Use geo_in_rectangle function
97
+ # request.
98
+ # filter.geo_in_rectangle(:location, "0x100", "100x0")
99
+ # # -> --filter 'geo_in_rectangle(location, "0x100", "100x0")'
100
+ #
101
+ # @example Use geo_in_circle function
102
+ # request.
103
+ # filter.geo_in_circle(:location, "100x100", 300)
104
+ # # -> --filter 'geo_in_circle(location, "100x100", 300, "rectangle")'
105
+ #
106
+ # @example Use between function
107
+ # request.
108
+ # filter.between(:age, 19, "include", 32, "include")
109
+ # # -> --filter 'between(age, 19, "include", 32, "include")'
110
+ #
96
111
  # @return [Groonga::Client::Request::Select::Filter]
97
112
  # The new request object for setting a filter condition.
98
113
  #
99
114
  # @since 0.4.3
100
- def filter(expression_or_column_name=nil, values_or_value=nil)
101
- if expression_or_column_name.nil? and values_or_value.nil?
102
- return Filter.new(self)
103
- end
104
-
105
- if expression_or_column_name.is_a?(Symbol)
106
- parameter = FilterEqualParameter.new(expression_or_column_name,
107
- values_or_value)
108
- elsif values_or_value.nil? or values_or_value.is_a?(::Hash)
109
- parameter = FilterExpressionParameter.new(expression_or_column_name,
110
- values_or_value)
115
+ def filter(*args)
116
+ n_args = args.size
117
+ case n_args
118
+ when 0
119
+ Filter.new(self)
120
+ when 1, 2
121
+ expression_or_column_name, values_or_value = *args
122
+
123
+ if values_or_value.nil? or values_or_value.is_a?(::Hash)
124
+ expression = expression_or_column_name
125
+ values = values_or_value
126
+ else
127
+ expression = "%{column} == %{value}"
128
+ column_name = expression_or_column_name
129
+ column_name = Filter.column_namify(column_name,
130
+ "first",
131
+ "#{self.class}\##{__method__}")
132
+ values = {
133
+ column: column_name,
134
+ value: values_or_value,
135
+ }
136
+ end
137
+ parameter = FilterExpressionParameter.new(expression, values)
138
+ add_parameter(FilterMerger, parameter)
111
139
  else
112
- parameter = FilterEqualParameter.new(expression_or_column_name,
113
- values_or_value)
140
+ message =
141
+ "wrong number of arguments (given #{n_args}, expected 0..2)"
142
+ raise ArgumentError, message
114
143
  end
115
- add_parameter(FilterMerger, parameter)
116
144
  end
117
145
 
118
146
  def output_columns(value)
@@ -176,42 +204,275 @@ module Groonga
176
204
  parameters.key?(:offset) and parameters.key?(:limit)
177
205
  end
178
206
 
179
- # @since 0.4.3
180
207
  class Filter
208
+ class << self
209
+ # @private
210
+ def column_namify(column_name, ith, signature)
211
+ return column_name unless column_name.is_a?(String)
212
+
213
+ message = "column name (the #{ith} argument) of #{signature} "
214
+ message << "should be Symbol: #{column_name.inspect}: "
215
+ message << caller(2, 1)[0]
216
+ warn(message)
217
+ column_name.to_sym
218
+ end
219
+ end
220
+
181
221
  def initialize(request)
182
222
  @request = request
183
223
  end
184
224
 
185
- # Adds a `in_values` condition then return a new `select`
225
+ # Adds a `geo_in_rectangle` condition then return a new `select`
226
+ # request object.
227
+ #
228
+ # @see http://groonga.org/docs/reference/functions/geo_in_rectangle.html
229
+ # geo_in_rectangle function in the Groonga document
230
+ #
231
+ # @overload geo_in_rectangle(column_name, top_left, bottom_right)
232
+ #
233
+ # @example: Basic usage
234
+ # request.
235
+ # filter.geo_in_rectangle(:location, "0x100", "100x0").
236
+ # # -> --filter 'geo_in_rectangle(location, "0x100", "100x0")'
237
+ #
238
+ # @param column_name [Symbol] The column name to be checked.
239
+ #
240
+ # @!macro [new] geo_in_rectangle
241
+ #
242
+ # @param top_left [String] The top left of the condition rectangle.
243
+ # `"#{LONGITUDE}x#{LATITUDE}"` is the point format.
244
+ #
245
+ # @param bottom_right [String] The bottom right of the condition rectangle.
246
+ # `"#{LONGITUDE}x#{LATITUDE}"` is the point format.
247
+ #
248
+ # @return [Groonga::Client::Request::Select]
249
+ # The new request with the given condition.
250
+ #
251
+ # @macro geo_in_rectangle
252
+ #
253
+ # @overload geo_in_rectangle(point, top_left, bottom_right)
254
+ #
255
+ # @example Basic usage
256
+ # request.
257
+ # filter.geo_in_rectangle("50x50", "0x100", "100x0").
258
+ # # -> --filter 'geo_in_rectangle("50x50", "0x100", "100x0")'
259
+ #
260
+ # @param point [String] The point to be checked.
261
+ # `"#{LONGITUDE}x#{LATITUDE}"` is the point format.
262
+ #
263
+ # @macro geo_in_rectangle
264
+ #
265
+ # @since 0.5.0
266
+ def geo_in_rectangle(column_name_or_point,
267
+ top_left, bottom_right)
268
+ expression = "geo_in_rectangle(%{column_name_or_point}"
269
+ expression << ", %{top_left}"
270
+ expression << ", %{bottom_right}"
271
+ expression << ")"
272
+ @request.filter(expression,
273
+ column_name_or_point: column_name_or_point,
274
+ top_left: top_left,
275
+ bottom_right: bottom_right)
276
+ end
277
+
278
+ # Adds a `geo_in_circle` condition then returns a new `select`
279
+ # request object.
280
+ #
281
+ # @see http://groonga.org/docs/reference/functions/geo_in_circle.html
282
+ # geo_in_circle function in the Groonga document
283
+ #
284
+ # @overload geo_in_circle(column_name, center, radius, approximate_type="rectangle")
285
+ #
286
+ # @example Basic usage
287
+ # request.
288
+ # filter.geo_in_circle(:location, "100x100", 300).
289
+ # # -> --filter 'geo_in_circle(location, "100x100", 300, "rectangle")'
290
+ #
291
+ # @param column_name [Symbol] The column name to be checked.
292
+ #
293
+ # @!macro [new] geo_in_circle_common
294
+ #
295
+ # @param center [String] The center point of the condition circle.
296
+ # `"#{LONGITUDE}x#{LATITUDE}"` is the point format.
297
+ #
298
+ # @param radius [Integer] The radius of the condition circle.
299
+ #
300
+ # @param approximate_type
301
+ # ["rectangle", "sphere", "ellipsoid"]
302
+ # ("rectangle")
303
+ #
304
+ # How to approximate geography to compute radius.
305
+ #
306
+ # The default is `"rectangle"`.
307
+ #
308
+ # @return [Groonga::Client::Request::Select]
309
+ # The new request with the given condition.
310
+ #
311
+ # @macro geo_in_circle_common
312
+ #
313
+ # @overload geo_in_circle(point, center, radius, approximate_type="rectangle")
314
+ #
315
+ # @example Basic usage
316
+ # request.
317
+ # filter.geo_in_circle("0x0", "100x100", 300).
318
+ # # -> --filter 'geo_in_circle("0x0", "100x100", 300, "rectangle")'
319
+ #
320
+ # @param point [String] The point to be checked.
321
+ # `"#{LONGITUDE}x#{LATITUDE}"` is the point format.
322
+ #
323
+ # @macro geo_in_circle_common
324
+ #
325
+ #
326
+ # @since 0.5.0
327
+ def geo_in_circle(column_name_or_point,
328
+ center,
329
+ radius_or_point,
330
+ approximate_type="rectangle")
331
+ expression = "geo_in_circle(%{column_name_or_point}"
332
+ expression << ", %{center}"
333
+ expression << ", %{radius_or_point}"
334
+ expression << ", %{approximate_type}"
335
+ expression << ")"
336
+ @request.filter(expression,
337
+ column_name_or_point: column_name_or_point,
338
+ center: center,
339
+ radius_or_point: radius_or_point,
340
+ approximate_type: approximate_type)
341
+ end
342
+
343
+ # Adds a `between` condition then returns a new `select`
344
+ # request object.
345
+ #
346
+ # @see http://groonga.org/docs/reference/functions/between.html
347
+ # between function in the Groonga document
348
+ #
349
+ # @return [Groonga::Client::Request::Select]
350
+ # The new request with the given condition.
351
+ #
352
+ # @overload between(column_name, min, max, min_border: "include", max_border: "include")
353
+ #
354
+ # @example Basic usage
355
+ # request.
356
+ # filter.between(:age, 19, 32)
357
+ # # -> --filter 'between(age, 19, "include", 32, "exclude")'
358
+ #
359
+ # @!macro [new] between_common
360
+ #
361
+ # @param column_name [Symbol] The target column name.
362
+ #
363
+ # @param min [Integer] The minimal value of the
364
+ # condition range.
365
+ #
366
+ # @param max [Integer] The maximum value of the
367
+ # condition range.
368
+ #
369
+ # @param min_border ["include", "exclude"] Whether `min` is
370
+ # included or not. If `"include"` is specified, `min` is
371
+ # included. If `"exclude"` is specified, `min` isn't
372
+ # included.
373
+ #
374
+ # @param max_border ["include", "exclude"] Whether `max` is
375
+ # included or not. If `"include"` is specified, `max` is
376
+ # included. If `"exclude"` is specified, `max` isn't
377
+ # included.
378
+ #
379
+ # @macro between_common
380
+ #
381
+ # @since 0.5.0
382
+ #
383
+ # @overload between(column_name, min, min_border, max, max_border)
384
+ #
385
+ # @example Basic usage
386
+ # request.
387
+ # filter.between(:age, 19, "include", 32, "exclude")
388
+ # # -> --filter 'between(age, 19, "include", 32, "exclude")'
389
+ #
390
+ # @macro between_common
391
+ #
392
+ # @since 0.4.4
393
+ def between(*args)
394
+ n_args = args.size
395
+ case n_args
396
+ when 3
397
+ column_name, min, max = args
398
+ min_border = "include"
399
+ max_border = "include"
400
+ when 4
401
+ column_name, min, max, options = args
402
+ min_border = options[:min_border] || "include"
403
+ max_border = options[:max_border] || "include"
404
+ when 5
405
+ column_name, min, min_border, max, max_border = args
406
+ else
407
+ message =
408
+ "wrong number of arguments (given #{n_args}, expected 3..5)"
409
+ raise ArgumentError, message
410
+ end
411
+
412
+ # TODO: Accept not only column name but also literal as
413
+ # the first argument.
414
+ column_name =
415
+ self.class.column_namify(column_name,
416
+ "first",
417
+ "#{self.class}\##{__method__}")
418
+ expression = "between(%{column_name}"
419
+ expression << ", %{min}"
420
+ expression << ", %{min_border}"
421
+ expression << ", %{max}"
422
+ expression << ", %{max_border}"
423
+ expression << ")"
424
+ @request.filter(expression,
425
+ column_name: column_name,
426
+ min: min,
427
+ min_border: min_border,
428
+ max: max,
429
+ max_border: max_border)
430
+ end
431
+
432
+ # Adds a `in_values` condition then returns a new `select`
186
433
  # request object.
187
434
  #
188
- # @example: Multiple conditions
435
+ # @example Multiple conditions
189
436
  # request.
190
- # filter.in_values("tags", "tag1", "tag2").
437
+ # filter.in_values(:tags, "tag1", "tag2").
191
438
  # # -> --filter 'in_values(tags, "tag1", "tag2")'
192
439
  # filter("user", "alice")
193
440
  # # -> --filter '(in_values(tags, "tag1", "tag2")) && (user == "alice")'
194
441
  #
195
- # @example: Ignore no values case
442
+ # @example Ignore no values case
196
443
  # request.
197
- # filter.in_values("tags")
444
+ # filter.in_values(:tags)
198
445
  # # -> --filter ''
199
446
  #
200
- # @param column_name [String, Symbol] The target column name.
447
+ # @see http://groonga.org/docs/reference/functions/in_values.html
448
+ # `in_values` function in the Groonga document
449
+ #
450
+ # @param column_name [Symbol] The target column name.
201
451
  #
202
452
  # @param values [Object] The column values that cover target
203
453
  # column values.
204
454
  #
205
455
  # @return [Groonga::Client::Request::Select]
206
456
  # The new request with the given condition.
457
+ #
458
+ # @since 0.4.3
207
459
  def in_values(column_name, *values)
208
- parameter = FilterInValuesParameter.new(column_name, *values)
209
- add_parameter(FilterMerger, parameter)
210
- end
211
-
212
- private
213
- def add_parameter(merger, parameter)
214
- @request.__send__(:add_parameter, merger, parameter)
460
+ return @request if values.empty?
461
+
462
+ # TODO: Accept not only column name but also literal as
463
+ # the first argument.
464
+ column_name =
465
+ self.class.column_namify(column_name,
466
+ "first",
467
+ "#{self.class}\##{__method__}")
468
+ expression_values = {column_name: column_name}
469
+ expression = "in_values(%{column_name}"
470
+ values.each_with_index do |value, i|
471
+ expression << ", %{value#{i}}"
472
+ expression_values[:"value#{i}"] = value
473
+ end
474
+ expression << ")"
475
+ @request.filter(expression, expression_values)
215
476
  end
216
477
  end
217
478
 
@@ -385,7 +646,11 @@ module Groonga
385
646
  when String
386
647
  ScriptSyntax.format_string(value)
387
648
  when Symbol
388
- ScriptSyntax.format_string(value.to_s)
649
+ if valid_script_syntax_identifier?(value)
650
+ value.to_s
651
+ else
652
+ ScriptSyntax.format_string(value.to_s)
653
+ end
389
654
  when ::Array
390
655
  escaped_value = "["
391
656
  value.each_with_index do |element, i|
@@ -408,6 +673,13 @@ module Groonga
408
673
  value
409
674
  end
410
675
  end
676
+
677
+ identifier_part = "[a-zA-Z_][a-zA-Z0-9_]*"
678
+ VALID_SCRIPT_SYNTAX_IDENTIFIER_PATTERN =
679
+ /\A#{identifier_part}(?:\.#{identifier_part})*\z/
680
+ def valid_script_syntax_identifier?(value)
681
+ VALID_SCRIPT_SYNTAX_IDENTIFIER_PATTERN === value.to_s
682
+ end
411
683
  end
412
684
 
413
685
  # @private
@@ -457,42 +729,6 @@ module Groonga
457
729
  end
458
730
  end
459
731
 
460
- # @private
461
- class FilterInValuesParameter
462
- include ScriptSyntaxValueEscapable
463
-
464
- def initialize(column_name, *values)
465
- @column_name = column_name
466
- @values = values
467
- end
468
-
469
- def to_parameters
470
- return {} if @values.empty?
471
-
472
- escaped_values = @values.collect do |value|
473
- escape_script_syntax_value(value)
474
- end
475
- {
476
- filter: "in_values(#{@column_name}, #{escaped_values.join(", ")})",
477
- }
478
- end
479
- end
480
-
481
- class FilterEqualParameter
482
- include ScriptSyntaxValueEscapable
483
-
484
- def initialize(column_name, value)
485
- @column_name = column_name
486
- @value = value
487
- end
488
-
489
- def to_parameters
490
- {
491
- filter: "#{@column_name} == #{escape_script_syntax_value(@value)}",
492
- }
493
- end
494
- end
495
-
496
732
  # @private
497
733
  class OutputColumnsParameter < ValuesParameter
498
734
  def initialize(prefix, output_columns)
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Groonga
18
18
  class Client
19
- VERSION = "0.4.3"
19
+ VERSION = "0.5.0"
20
20
  end
21
21
  end
@@ -0,0 +1,318 @@
1
+ # Copyright (C) 2016-2017 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License as published by the Free Software Foundation; either
6
+ # version 2.1 of the License, or (at your option) any later version.
7
+ #
8
+ # This library is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+
17
+ class TestRequestSelectFilter < Test::Unit::TestCase
18
+ setup do
19
+ @request = Groonga::Client::Request::Select.new("posts")
20
+ end
21
+
22
+ def filter(*args)
23
+ @request.filter(*args).to_parameters
24
+ end
25
+
26
+ sub_test_case("expression") do
27
+ def test_nil
28
+ assert_equal({
29
+ :table => "posts",
30
+ },
31
+ filter(nil))
32
+ end
33
+
34
+ def test_string
35
+ assert_equal({
36
+ :table => "posts",
37
+ :filter => "age <= 20",
38
+ },
39
+ filter("age <= 20"))
40
+ end
41
+
42
+ def test_empty_string
43
+ assert_equal({
44
+ :table => "posts",
45
+ },
46
+ filter(""))
47
+ end
48
+ end
49
+
50
+ sub_test_case("values") do
51
+ test("String") do
52
+ filter = <<-'FILTER'.strip
53
+ title == "[\"He\\ llo\"]"
54
+ FILTER
55
+ assert_equal({
56
+ :table => "posts",
57
+ :filter => filter,
58
+ },
59
+ filter("title == %{value}",
60
+ :value => "[\"He\\ llo\"]"))
61
+ end
62
+
63
+ sub_test_case("Symbol") do
64
+ test("valid ID") do
65
+ assert_equal({
66
+ :table => "posts",
67
+ :filter => "title == \"Hello\"",
68
+ },
69
+ filter("%{column} == %{value}",
70
+ :column => :title,
71
+ :value => "Hello"))
72
+ end
73
+
74
+ test("invalid ID") do
75
+ assert_equal({
76
+ :table => "posts",
77
+ :filter => "title == \"Hello World\"",
78
+ },
79
+ filter("title == %{value}",
80
+ :value => :"Hello World"))
81
+ end
82
+ end
83
+
84
+ test("Numeric") do
85
+ assert_equal({
86
+ :table => "posts",
87
+ :filter => "age <= 29",
88
+ },
89
+ filter("age <= %{value}",
90
+ :value => 29))
91
+ end
92
+
93
+ test("true") do
94
+ assert_equal({
95
+ :table => "posts",
96
+ :filter => "published == true",
97
+ },
98
+ filter("published == %{value}",
99
+ :value => true))
100
+ end
101
+
102
+ test("false") do
103
+ assert_equal({
104
+ :table => "posts",
105
+ :filter => "published == false",
106
+ },
107
+ filter("published == %{value}",
108
+ :value => false))
109
+ end
110
+
111
+ test("nil") do
112
+ assert_equal({
113
+ :table => "posts",
114
+ :filter => "function(null)",
115
+ },
116
+ filter("function(%{value})",
117
+ :value => nil))
118
+ end
119
+
120
+ test("Array") do
121
+ assert_equal({
122
+ :table => "posts",
123
+ :filter => "function([\"a\", 29])",
124
+ },
125
+ filter("function(%{arg})", :arg => ["a", 29]))
126
+ end
127
+
128
+ test("Hash") do
129
+ assert_equal({
130
+ :table => "posts",
131
+ :filter => "function({\"string\": \"value\", \"number\": 29})",
132
+ },
133
+ filter("function(%{options})",
134
+ :options => {
135
+ "string" => "value",
136
+ "number" => 29
137
+ }))
138
+ end
139
+ end
140
+
141
+ test("column name") do
142
+ assert_equal({
143
+ :table => "posts",
144
+ :filter => "_key == 29",
145
+ },
146
+ filter(:_key, 29))
147
+ end
148
+
149
+ sub_test_case("value") do
150
+ test("String") do
151
+ filter = <<-'FILTER'.strip
152
+ title == "[\"He\\ llo\"]"
153
+ FILTER
154
+ assert_equal({
155
+ :table => "posts",
156
+ :filter => filter,
157
+ },
158
+ filter(:title, "[\"He\\ llo\"]"))
159
+ end
160
+
161
+ sub_test_case("Symbol") do
162
+ test("valid ID") do
163
+ assert_equal({
164
+ :table => "posts",
165
+ :filter => "title == normalized_title",
166
+ },
167
+ filter(:title, :normalized_title))
168
+ end
169
+
170
+ test("invalid ID") do
171
+ assert_equal({
172
+ :table => "posts",
173
+ :filter => "title == \"Hello World\"",
174
+ },
175
+ filter(:title, :"Hello World"))
176
+ end
177
+ end
178
+
179
+ test("Numeric") do
180
+ assert_equal({
181
+ :table => "posts",
182
+ :filter => "age == 29",
183
+ },
184
+ filter(:age, 29))
185
+ end
186
+
187
+ test("true") do
188
+ assert_equal({
189
+ :table => "posts",
190
+ :filter => "published == true",
191
+ },
192
+ filter(:published, true))
193
+ end
194
+
195
+ test("false") do
196
+ assert_equal({
197
+ :table => "posts",
198
+ :filter => "published == false",
199
+ },
200
+ filter(:published, false))
201
+ end
202
+ end
203
+
204
+ sub_test_case("Filter") do
205
+ sub_test_case("#geo_in_rectangle") do
206
+ def geo_in_rectangle(*args)
207
+ @request.filter.geo_in_rectangle(*args).to_parameters
208
+ end
209
+
210
+ test("column") do
211
+ assert_equal({
212
+ :table => "posts",
213
+ :filter => "geo_in_rectangle(location, \"0x100\", \"100x0\")",
214
+ },
215
+ geo_in_rectangle(:location, "0x100", "100x0"))
216
+ end
217
+
218
+ test("point") do
219
+ assert_equal({
220
+ :table => "posts",
221
+ :filter => "geo_in_rectangle(\"50x50\", \"0x100\", \"100x0\")",
222
+ },
223
+ geo_in_rectangle("50x50", "0x100", "100x0"))
224
+ end
225
+ end
226
+
227
+ sub_test_case("#geo_in_circle") do
228
+ def geo_in_circle(*args)
229
+ @request.filter.geo_in_circle(*args).to_parameters
230
+ end
231
+
232
+ test("column") do
233
+ assert_equal({
234
+ :table => "posts",
235
+ :filter => "geo_in_circle(location, \"140x250\", 300, \"rectangle\")",
236
+ },
237
+ geo_in_circle(:location, "140x250", 300))
238
+ end
239
+
240
+ test("point") do
241
+ assert_equal({
242
+ :table => "posts",
243
+ :filter => "geo_in_circle(\"100x100\", \"140x250\", 300, \"rectangle\")",
244
+ },
245
+ geo_in_circle("100x100", "140x250", 300))
246
+ end
247
+
248
+ test("approximate type") do
249
+ assert_equal({
250
+ :table => "posts",
251
+ :filter => "geo_in_circle(\"100x100\", \"140x250\", 300, \"sphere\")",
252
+ },
253
+ geo_in_circle("100x100", "140x250", 300, "sphere"))
254
+ end
255
+ end
256
+
257
+ sub_test_case("#between") do
258
+ def between(*args)
259
+ @request.filter.between(*args).to_parameters
260
+ end
261
+
262
+ test("min and max") do
263
+ assert_equal({
264
+ :table => "posts",
265
+ :filter => "between(ages, 2, \"include\", 29, \"include\")",
266
+ },
267
+ between(:ages, 2, 29))
268
+ end
269
+
270
+ test("min, max and options") do
271
+ assert_equal({
272
+ :table => "posts",
273
+ :filter => "between(ages, 2, \"exclude\", 29, \"exclude\")",
274
+ },
275
+ between(:ages, 2, 29,
276
+ min_border: "exclude",
277
+ max_border: "exclude"))
278
+ end
279
+
280
+ test("all") do
281
+ assert_equal({
282
+ :table => "posts",
283
+ :filter => "between(ages, 2, \"include\", 29, \"exclude\")",
284
+ },
285
+ between(:ages, 2, "include", 29, "exclude"))
286
+ end
287
+ end
288
+
289
+ sub_test_case("#in_values") do
290
+ def in_values(column_name, *values)
291
+ @request.filter.in_values(column_name, *values).to_parameters
292
+ end
293
+
294
+ test("numbers") do
295
+ assert_equal({
296
+ :table => "posts",
297
+ :filter => "in_values(ages, 2, 29)",
298
+ },
299
+ in_values(:ages, 2, 29))
300
+ end
301
+
302
+ test("strings") do
303
+ assert_equal({
304
+ :table => "posts",
305
+ :filter => "in_values(tags, \"groonga\", \"have \\\"double\\\" quote\")",
306
+ },
307
+ in_values(:tags, "groonga", "have \"double\" quote"))
308
+ end
309
+
310
+ test("no values") do
311
+ assert_equal({
312
+ :table => "posts",
313
+ },
314
+ in_values(:tags))
315
+ end
316
+ end
317
+ end
318
+ end
@@ -19,109 +19,6 @@ class TestRequestSelect < Test::Unit::TestCase
19
19
  @request = Groonga::Client::Request::Select.new("posts")
20
20
  end
21
21
 
22
- sub_test_case("#filter") do
23
- def filter(*args)
24
- @request.filter(*args).to_parameters
25
- end
26
-
27
- test("Numeric") do
28
- assert_equal({
29
- :table => "posts",
30
- :filter => "rate == 5",
31
- },
32
- filter("rate == %{rate}", :rate => 5))
33
- end
34
-
35
- test("true") do
36
- assert_equal({
37
- :table => "posts",
38
- :filter => "published == true",
39
- },
40
- filter("published == %{published}", :published => true))
41
- end
42
-
43
- test("false") do
44
- assert_equal({
45
- :table => "posts",
46
- :filter => "published == false",
47
- },
48
- filter("published == %{published}", :published => false))
49
- end
50
-
51
- test("nil") do
52
- assert_equal({
53
- :table => "posts",
54
- :filter => "function(null)",
55
- },
56
- filter("function(%{arg})", :arg => nil))
57
- end
58
-
59
- test("String") do
60
- assert_equal({
61
- :table => "posts",
62
- :filter => "title == \"Hello\"",
63
- },
64
- filter("title == %{title}", :title => "Hello"))
65
- end
66
-
67
- test("Symbol") do
68
- assert_equal({
69
- :table => "posts",
70
- :filter => "title == \"Hello\"",
71
- },
72
- filter("title == %{title}", :title => :Hello))
73
- end
74
-
75
- test("Array") do
76
- assert_equal({
77
- :table => "posts",
78
- :filter => "function([\"a\", 29])",
79
- },
80
- filter("function(%{arg})", :arg => ["a", 29]))
81
- end
82
-
83
- test("Hash") do
84
- assert_equal({
85
- :table => "posts",
86
- :filter => "function({\"string\": \"value\", \"number\": 29})",
87
- },
88
- filter("function(%{options})",
89
- :options => {
90
- "string" => "value",
91
- "number" => 29
92
- }))
93
- end
94
-
95
- sub_test_case("#in_values") do
96
- def in_values(column_name, *values)
97
- @request.filter.in_values(column_name, *values).to_parameters
98
- end
99
-
100
- test("numbers") do
101
- assert_equal({
102
- :table => "posts",
103
- :filter => "in_values(ages, 2, 29)",
104
- },
105
- in_values("ages", 2, 29))
106
- end
107
-
108
- test("strings") do
109
- assert_equal({
110
- :table => "posts",
111
- :filter => "in_values(tags, \"groonga\", \"have \\\"double\\\" quote\")",
112
- },
113
- in_values("tags", "groonga", "have \"double\" quote"))
114
- end
115
-
116
- test("no values") do
117
- assert_equal({
118
- :table => "posts",
119
- },
120
- in_values("tags"))
121
- end
122
- end
123
- end
124
-
125
22
  sub_test_case("#drilldowns") do
126
23
  def drilldown
127
24
  @request.drilldowns("label")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groonga-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Haruka Yoshihara
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-04-24 00:00:00.000000000 Z
13
+ date: 2017-05-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gqtp
@@ -224,8 +224,7 @@ files:
224
224
  - test/protocol/test-gqtp.rb
225
225
  - test/protocol/test-http.rb
226
226
  - test/request/select/test-backward-compatible-sort-keys-parameter.rb
227
- - test/request/select/test-filter-equal-parameter.rb
228
- - test/request/select/test-filter-expression-parameter.rb
227
+ - test/request/select/test-filter.rb
229
228
  - test/request/select/test-output-columns-parameter.rb
230
229
  - test/request/select/test-sort-keys-parameter.rb
231
230
  - test/request/select/test-values-parameter.rb
@@ -270,38 +269,37 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
269
  version: '0'
271
270
  requirements: []
272
271
  rubyforge_project:
273
- rubygems_version: 2.6.11
272
+ rubygems_version: 2.2.2
274
273
  signing_key:
275
274
  specification_version: 4
276
275
  summary: Groonga-client is a client for Groonga (http://groonga.org/) implemented
277
276
  with pure Ruby. You can use it without Groonga.
278
277
  test_files:
279
- - test/results/test-table-list.rb
280
- - test/results/test-column-list.rb
281
- - test/request/test-generic.rb
282
- - test/request/test-merger.rb
283
- - test/request/test-select.rb
284
- - test/request/select/test-values-parameter.rb
285
- - test/request/select/test-backward-compatible-sort-keys-parameter.rb
286
- - test/request/select/test-output-columns-parameter.rb
287
- - test/request/select/test-filter-equal-parameter.rb
288
- - test/request/select/test-sort-keys-parameter.rb
289
- - test/request/select/test-filter-expression-parameter.rb
290
- - test/response/test-status.rb
278
+ - test/run-test.rb
291
279
  - test/response/test-error.rb
292
- - test/response/test-load.rb
280
+ - test/response/test-select-command-version3.rb
281
+ - test/response/test-select-command-version1.rb
293
282
  - test/response/test-table-create.rb
294
283
  - test/response/helper.rb
284
+ - test/response/test-status.rb
285
+ - test/response/test-column-list.rb
286
+ - test/response/test-schema.rb
295
287
  - test/response/test-table-list.rb
288
+ - test/response/test-load.rb
296
289
  - test/response/test-base.rb
297
290
  - test/response/test-table-remove.rb
298
- - test/response/test-select-command-version3.rb
299
- - test/response/test-column-list.rb
300
- - test/response/test-select-command-version1.rb
301
- - test/response/test-schema.rb
302
- - test/run-test.rb
303
291
  - test/test-script-syntax.rb
304
- - test/protocol/test-gqtp.rb
305
292
  - test/protocol/test-http.rb
293
+ - test/protocol/test-gqtp.rb
294
+ - test/results/test-column-list.rb
295
+ - test/results/test-table-list.rb
306
296
  - test/test-command.rb
297
+ - test/request/select/test-values-parameter.rb
298
+ - test/request/select/test-filter.rb
299
+ - test/request/select/test-output-columns-parameter.rb
300
+ - test/request/select/test-sort-keys-parameter.rb
301
+ - test/request/select/test-backward-compatible-sort-keys-parameter.rb
302
+ - test/request/test-merger.rb
303
+ - test/request/test-generic.rb
304
+ - test/request/test-select.rb
307
305
  - test/test-client.rb
@@ -1,82 +0,0 @@
1
- # Copyright (C) 2016 Kouhei Sutou <kou@clear-code.com>
2
- #
3
- # This library is free software; you can redistribute it and/or
4
- # modify it under the terms of the GNU Lesser General Public
5
- # License as published by the Free Software Foundation; either
6
- # version 2.1 of the License, or (at your option) any later version.
7
- #
8
- # This library is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
- # Lesser General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU Lesser General Public
14
- # License along with this library; if not, write to the Free Software
15
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
-
17
- class TestRequestSelectFilterEqualParmater < Test::Unit::TestCase
18
- def filter_parameter(column_name, value)
19
- Groonga::Client::Request::Select::FilterEqualParameter.new(column_name,
20
- value)
21
- end
22
-
23
- def to_parameters(column_name, value)
24
- filter_parameter(column_name, value).to_parameters
25
- end
26
-
27
- sub_test_case("column name") do
28
- def test_string
29
- assert_equal({
30
- :filter => "_key == 29",
31
- },
32
- to_parameters("_key", 29))
33
- end
34
-
35
- def test_symbol
36
- assert_equal({
37
- :filter => "_key == 29",
38
- },
39
- to_parameters(:_key, 29))
40
- end
41
- end
42
-
43
- sub_test_case("value") do
44
- def test_string
45
- filter = <<-'FILTER'.strip
46
- title == "[\"He\\ llo\"]"
47
- FILTER
48
- assert_equal({
49
- :filter => filter,
50
- },
51
- to_parameters("title", "[\"He\\ llo\"]"))
52
- end
53
-
54
- def test_symbol
55
- assert_equal({
56
- :filter => "title == \"Hello\"",
57
- },
58
- to_parameters("title", :Hello))
59
- end
60
-
61
- def test_number
62
- assert_equal({
63
- :filter => "age == 29",
64
- },
65
- to_parameters("age", 29))
66
- end
67
-
68
- def test_true
69
- assert_equal({
70
- :filter => "published == true",
71
- },
72
- to_parameters("published", true))
73
- end
74
-
75
- def test_false
76
- assert_equal({
77
- :filter => "published == false",
78
- },
79
- to_parameters("published", false))
80
- end
81
- end
82
- end
@@ -1,98 +0,0 @@
1
- # Copyright (C) 2016 Kouhei Sutou <kou@clear-code.com>
2
- #
3
- # This library is free software; you can redistribute it and/or
4
- # modify it under the terms of the GNU Lesser General Public
5
- # License as published by the Free Software Foundation; either
6
- # version 2.1 of the License, or (at your option) any later version.
7
- #
8
- # This library is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
- # Lesser General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU Lesser General Public
14
- # License along with this library; if not, write to the Free Software
15
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
-
17
- class TestRequestSelectFilterExpressionParmater < Test::Unit::TestCase
18
- def filter_parameter(expression, values=nil)
19
- Groonga::Client::Request::Select::FilterExpressionParameter.new(expression,
20
- values)
21
- end
22
-
23
- def to_parameters(expression, values=nil)
24
- filter_parameter(expression, values).to_parameters
25
- end
26
-
27
- sub_test_case("expression") do
28
- def test_nil
29
- assert_equal({},
30
- to_parameters(nil))
31
- end
32
-
33
- def test_string
34
- assert_equal({
35
- :filter => "age <= 20",
36
- },
37
- to_parameters("age <= 20"))
38
- end
39
-
40
- def test_empty_string
41
- assert_equal({},
42
- to_parameters(""))
43
- end
44
- end
45
-
46
- sub_test_case("values") do
47
- def test_string
48
- filter = <<-'FILTER'.strip
49
- title == "[\"He\\ llo\"]"
50
- FILTER
51
- assert_equal({
52
- :filter => filter,
53
- },
54
- to_parameters("title == %{value}",
55
- :value => "[\"He\\ llo\"]"))
56
- end
57
-
58
- def test_symbol
59
- assert_equal({
60
- :filter => "title == \"Hello\"",
61
- },
62
- to_parameters("title == %{value}",
63
- :value => :Hello))
64
- end
65
-
66
- def test_number
67
- assert_equal({
68
- :filter => "age <= 29",
69
- },
70
- to_parameters("age <= %{value}",
71
- :value => 29))
72
- end
73
-
74
- def test_true
75
- assert_equal({
76
- :filter => "published == true",
77
- },
78
- to_parameters("published == %{value}",
79
- :value => true))
80
- end
81
-
82
- def test_false
83
- assert_equal({
84
- :filter => "published == false",
85
- },
86
- to_parameters("published == %{value}",
87
- :value => false))
88
- end
89
-
90
- def test_nil
91
- assert_equal({
92
- :filter => "function(null)",
93
- },
94
- to_parameters("function(%{value})",
95
- :value => nil))
96
- end
97
- end
98
- end