groonga-client 0.4.3 → 0.5.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.
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