grn_mini 0.3.0 → 0.4.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.
data/lib/grn_mini/hash.rb CHANGED
@@ -1,49 +1,14 @@
1
- require 'grn_mini/util'
2
- require 'groonga'
3
- require 'tmpdir'
1
+ require 'grn_mini/table'
4
2
 
5
3
  module GrnMini
6
- class Hash
7
- attr_accessor :grn
8
- include Enumerable
9
-
10
- def self.tmpdb
11
- Dir.mktmpdir do |dir|
12
- # p dir
13
- yield self.new(File.join(dir, "tmp.db"))
14
- end
15
- end
16
-
17
- def initialize(path)
18
- unless File.exist?(path)
19
- Groonga::Database.create(path: path)
20
- else
21
- Groonga::Database.open(path)
22
- end
23
-
24
- @grn = Groonga["Hash"] || Groonga::Hash.create(name: "Hash", persistent: true)
25
- @terms = Groonga["Terms"] || Groonga::PatriciaTrie.create(name: "Terms", key_normalize: true, default_tokenizer: "TokenBigramSplitSymbolAlphaDigit")
4
+ class Hash < Table
5
+ def initialize(name = "Hash")
6
+ super(name,
7
+ Groonga[name] || Groonga::Hash.create(name: name, persistent: true))
26
8
  end
27
9
 
28
10
  def add(key, values)
29
- if @grn.empty?
30
- values.each do |key, value|
31
- column = key.to_s
32
-
33
- # @todo Need define_index_column ?
34
- if value.is_a?(Time)
35
- @grn.define_column(column, "Time")
36
- elsif value.is_a?(Float)
37
- @grn.define_column(column, "Float")
38
- elsif value.is_a?(Numeric)
39
- @grn.define_column(column, "Int32")
40
- else
41
- @grn.define_column(column, "ShortText")
42
- @terms.define_index_column("array_#{column}", @grn, source: "Hash.#{column}", with_position: true)
43
- end
44
- end
45
- end
46
-
11
+ setup_columns(values) unless @setup_columns_once
47
12
  @grn.add(key, values)
48
13
  end
49
14
 
@@ -55,41 +20,13 @@ module GrnMini
55
20
  add(key, value)
56
21
  end
57
22
 
58
- def select(query, options = {default_column: "text"})
59
- @grn.select(query, options)
60
- end
61
-
62
- def size
63
- @grn.size
64
- end
65
-
66
- alias length size
67
-
68
- def empty?
69
- size == 0
70
- end
71
-
72
- def each
73
- @grn.each do |record|
74
- yield record
75
- end
76
- end
77
-
78
23
  def delete(id = nil, &block)
79
24
  if block_given?
80
25
  @grn.delete(&block)
81
26
  else
82
- raise IdIsGreaterThanZero if id == 0
83
27
  @grn.delete(id)
84
28
  end
85
29
  end
86
30
 
87
- def sort(keys, options = {})
88
- @grn.sort(keys, options)
89
- end
90
-
91
- def group(key, options = {})
92
- @grn.group(key, options)
93
- end
94
31
  end
95
32
  end
@@ -0,0 +1,91 @@
1
+ require 'grn_mini/util'
2
+ require 'groonga'
3
+
4
+ module GrnMini
5
+ class NotSupportColumnType < RuntimeError; end
6
+
7
+ class Table
8
+ attr_accessor :grn
9
+ include Enumerable
10
+
11
+ def initialize(name, grn)
12
+ @name = name
13
+ @grn = grn
14
+ @terms = Groonga["Terms"] || Groonga::PatriciaTrie.create(name: "Terms", key_normalize: true, default_tokenizer: "TokenBigramSplitSymbolAlphaDigit")
15
+ @setup_columns_once = false
16
+ end
17
+
18
+ def setup_columns(hash)
19
+ hash.each do |key, value|
20
+ column = key.to_s
21
+
22
+ if value.is_a?(String)
23
+ @grn.define_column(column, value_type(value))
24
+ @terms.define_index_column("#{@name}_#{column}", @grn, source: "#{@name}.#{column}", with_position: true)
25
+ elsif value.is_a?(::Array)
26
+ @grn.define_column(column, value_type(value), type: :vector)
27
+
28
+ elem = value.first
29
+
30
+ if elem.is_a?(GrnMini::Table)
31
+ elem.grn.define_index_column("index_#{column}", @grn, source: "#{@grn.name}.#{column}")
32
+ elsif elem.is_a?(Groonga::Table)
33
+ elem.define_index_column("index_#{column}", @grn, source: "#{@grn.name}.#{column}")
34
+ end
35
+ else
36
+ @grn.define_column(column, value_type(value))
37
+ end
38
+ end
39
+
40
+ @setup_columns_once = true
41
+ end
42
+
43
+ def value_type(value)
44
+ if value.is_a?(TrueClass) || value.is_a?(FalseClass)
45
+ "Bool"
46
+ elsif value.is_a?(Integer)
47
+ "Int32"
48
+ elsif value.is_a?(Float)
49
+ "Float"
50
+ elsif value.is_a?(Time)
51
+ "Time"
52
+ elsif value.is_a?(String)
53
+ "ShortText"
54
+ elsif value.is_a?(GrnMini::Table)
55
+ value.grn.name
56
+ elsif value.is_a?(Groonga::Table)
57
+ value.name
58
+ elsif value.is_a?(::Array)
59
+ value_type(value.first)
60
+ else
61
+ raise NotSupportColumnType, value
62
+ end
63
+ end
64
+
65
+ def select(*args, &block)
66
+ @grn.select(*args, &block)
67
+ end
68
+
69
+ def size
70
+ @grn.size
71
+ end
72
+
73
+ def empty?
74
+ size == 0
75
+ end
76
+
77
+ def each
78
+ @grn.each do |record|
79
+ yield record
80
+ end
81
+ end
82
+
83
+ def sort(keys, options = {})
84
+ @grn.sort(keys, options)
85
+ end
86
+
87
+ def group(key, options = {})
88
+ @grn.group(key, options)
89
+ end
90
+ end
91
+ end
@@ -1,3 +1,3 @@
1
1
  module GrnMini
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -2,13 +2,15 @@ require 'minitest_helper'
2
2
 
3
3
  class TestGrnMiniArray < MiniTest::Unit::TestCase
4
4
  def test_initialize
5
- Dir.mktmpdir do |dir|
6
- array = GrnMini::Array.new(File.join(dir, "test.db"))
5
+ GrnMini::tmpdb do
6
+ array = GrnMini::Array.new
7
7
  end
8
8
  end
9
9
 
10
10
  def test_add
11
- GrnMini::Array.tmpdb do |array|
11
+ GrnMini::tmpdb do
12
+ array = GrnMini::Array.new
13
+
12
14
  array.add(text:"aaa", number:1)
13
15
  assert_equal 1, array.size
14
16
 
@@ -19,12 +21,14 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
19
21
  end
20
22
 
21
23
  def test_select
22
- GrnMini::Array.tmpdb do |array|
24
+ GrnMini::tmpdb do
25
+ array = GrnMini::Array.new
26
+
23
27
  array << {text:"aaa", number:1}
24
28
  array << {text:"bbb", number:2}
25
29
  array << {text:"ccc", number:3}
26
30
 
27
- results = array.select("bb")
31
+ results = array.select("text:@bb")
28
32
 
29
33
  assert_equal 1, results.size
30
34
  assert_equal "bbb", results.first.text
@@ -32,13 +36,15 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
32
36
  end
33
37
 
34
38
  def test_select2
35
- GrnMini::Array.tmpdb do |array|
39
+ GrnMini::tmpdb do
40
+ array = GrnMini::Array.new
41
+
36
42
  array << {text:"aaa", number:1}
37
43
  array << {text:"bbb", number:2}
38
44
  array << {text:"bbb", number:20}
39
45
  array << {text:"ccc", number:3}
40
46
 
41
- results = array.select("bb number:<10")
47
+ results = array.select("text:@bb number:<10")
42
48
 
43
49
  assert_equal 1, results.size
44
50
  assert_equal 2, results.first.key.id
@@ -48,19 +54,21 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
48
54
  end
49
55
 
50
56
  def test_size
51
- GrnMini::Array.tmpdb do |array|
57
+ GrnMini::tmpdb do
58
+ array = GrnMini::Array.new
59
+
52
60
  assert_equal 0, array.size
53
- assert_equal 0, array.length
54
61
 
55
62
  array << {text:"aaa", number:1}
56
63
  array << {text:"bbb", number:2}
57
64
  assert_equal 2, array.size
58
- assert_equal 2, array.length
59
65
  end
60
66
  end
61
67
 
62
68
  def test_empty?
63
- GrnMini::Array.tmpdb do |array|
69
+ GrnMini::tmpdb do
70
+ array = GrnMini::Array.new
71
+
64
72
  assert_equal true, array.empty?
65
73
 
66
74
  array << {text:"aaa", number:1}
@@ -69,7 +77,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
69
77
  end
70
78
 
71
79
  def test_each
72
- GrnMini::Array.tmpdb do |array|
80
+ GrnMini::tmpdb do
81
+ array = GrnMini::Array.new
82
+
73
83
  array << {text:"aaa", number:1}
74
84
  array << {text:"bbb", number:2}
75
85
  array << {text:"ccc", number:3}
@@ -91,7 +101,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
91
101
  end
92
102
 
93
103
  def test_read_by_id
94
- GrnMini::Array.tmpdb do |array|
104
+ GrnMini::tmpdb do
105
+ array = GrnMini::Array.new
106
+
95
107
  array << {text:"aaa", number:1}
96
108
  array << {text:"bbb", number:2}
97
109
  array << {text:"ccc", number:3}
@@ -111,7 +123,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
111
123
  end
112
124
 
113
125
  def test_write_by_id
114
- GrnMini::Array.tmpdb do |array|
126
+ GrnMini::tmpdb do
127
+ array = GrnMini::Array.new
128
+
115
129
  array << {text:"aaa", number:1}
116
130
  array << {text:"bbb", number:2}
117
131
  array << {text:"ccc", number:3}
@@ -128,7 +142,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
128
142
  end
129
143
 
130
144
  def test_delete_by_id
131
- GrnMini::Array.tmpdb do |array|
145
+ GrnMini::tmpdb do
146
+ array = GrnMini::Array.new
147
+
132
148
  array << {text:"aaa", number:1}
133
149
  array << {text:"bbb", number:2}
134
150
  array << {text:"ccc", number:3}
@@ -163,7 +179,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
163
179
  end
164
180
 
165
181
  def test_delete_by_block
166
- GrnMini::Array.tmpdb do |array|
182
+ GrnMini::tmpdb do
183
+ array = GrnMini::Array.new
184
+
167
185
  array << {text:"bbb", number:2}
168
186
  array << {text:"ccc", number:3}
169
187
  array << {text:"aaa", number:1}
@@ -179,7 +197,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
179
197
  end
180
198
 
181
199
  def test_float_column
182
- GrnMini::Array.tmpdb do |array|
200
+ GrnMini::tmpdb do
201
+ array = GrnMini::Array.new
202
+
183
203
  array << {text:"aaaa", float: 1.5}
184
204
  array << {text:"bbbb", float: 2.5}
185
205
  array << {text:"cccc", float: 3.5}
@@ -192,7 +212,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
192
212
  end
193
213
 
194
214
  def test_time_column
195
- GrnMini::Array.tmpdb do |array|
215
+ GrnMini::tmpdb do
216
+ array = GrnMini::Array.new
217
+
196
218
  array << {text:"aaaa", timestamp: Time.new(2013)} # 2013-01-01
197
219
  array << {text:"bbbb", timestamp: Time.new(2014)} # 2014-01-01
198
220
  array << {text:"cccc", timestamp: Time.new(2015)} # 2015-01-01
@@ -205,8 +227,29 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
205
227
  end
206
228
  end
207
229
 
230
+ def test_bool_column
231
+ GrnMini::tmpdb do
232
+ array = GrnMini::Array.new
233
+
234
+ array << {bool: true}
235
+ array << {bool: false}
236
+ array << {bool: false}
237
+
238
+ assert_equal true, array[1].bool
239
+ assert_equal false, array[2].bool
240
+
241
+ results = array.select { |r| r.bool == true }
242
+ assert_equal 1, results.size
243
+
244
+ results = array.select { |r| r.bool == false }
245
+ assert_equal 2, results.size
246
+ end
247
+ end
248
+
208
249
  def test_record_attributes
209
- GrnMini::Array.tmpdb do |array|
250
+ GrnMini::tmpdb do
251
+ array = GrnMini::Array.new
252
+
210
253
  array << {text:"aaaa", int: 1}
211
254
  array << {text:"bbbb", int: 2}
212
255
  array << {text:"cccc", int: 3}
@@ -218,7 +261,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
218
261
  end
219
262
 
220
263
  def test_assign_long_text_to_short_text
221
- GrnMini::Array.tmpdb do |array|
264
+ GrnMini::tmpdb do
265
+ array = GrnMini::Array.new
266
+
222
267
  array << {filename:"a.txt"}
223
268
  array << {filename:"a"*4095 + ".txt" } # Over 4095 byte (ShortText limit)
224
269
 
@@ -228,7 +273,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
228
273
  end
229
274
 
230
275
  def test_grn_object
231
- GrnMini::Array.tmpdb do |array|
276
+ GrnMini::tmpdb do
277
+ array = GrnMini::Array.new
278
+
232
279
  array << {text: "aaaa", filename:"a.txt", int: 1, float: 1.5, time: Time.at(2001)}
233
280
 
234
281
  raw = array.grn
@@ -251,7 +298,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
251
298
  end
252
299
 
253
300
  def test_sort
254
- GrnMini::Array.tmpdb do |array|
301
+ GrnMini::tmpdb do
302
+ array = GrnMini::Array.new
303
+
255
304
  array << {name:"Tanaka", age: 11, height: 162.5}
256
305
  array << {name:"Suzuki", age: 31, height: 170.0}
257
306
  array << {name:"Hayashi", age: 21, height: 175.4}
@@ -275,7 +324,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
275
324
  end
276
325
 
277
326
  def test_group_from_array
278
- GrnMini::Array.tmpdb do |array|
327
+ GrnMini::tmpdb do
328
+ array = GrnMini::Array.new
329
+
279
330
  array << {text:"aaaa.txt", suffix:"txt", type:1}
280
331
  array << {text:"aaaa.doc", suffix:"doc", type:2}
281
332
  array << {text:"aabb.txt", suffix:"txt", type:2}
@@ -289,13 +340,15 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
289
340
  end
290
341
 
291
342
  def test_group_from_selection_results
292
- GrnMini::Array.tmpdb do |array|
343
+ GrnMini::tmpdb do
344
+ array = GrnMini::Array.new
345
+
293
346
  array << {text:"aaaa", suffix:"txt"}
294
347
  array << {text:"aaaa", suffix:"doc"}
295
348
  array << {text:"aaaa", suffix:"txt"}
296
349
  array << {text:"cccc", suffix:"txt"}
297
350
 
298
- results = array.select("aa")
351
+ results = array.select("text:@aa")
299
352
  groups = GrnMini::Util::group_with_sort(results, "suffix")
300
353
 
301
354
  assert_equal 2, groups.size
@@ -305,7 +358,9 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
305
358
  end
306
359
 
307
360
  def test_text_snippet_from_selection_results
308
- GrnMini::Array.tmpdb do |array|
361
+ GrnMini::tmpdb do
362
+ array = GrnMini::Array.new
363
+
309
364
  array << {text: <<EOF, filename: "aaa.txt"}
310
365
  [1] This is a pen pep pea pek pet.
311
366
  ------------------------------
@@ -320,7 +375,7 @@ class TestGrnMiniArray < MiniTest::Unit::TestCase
320
375
  ------------------------------
321
376
  EOF
322
377
 
323
- results = array.select("This pen")
378
+ results = array.select("This pen", default_column: "text")
324
379
  snippet = GrnMini::Util::text_snippet_from_selection_results(results)
325
380
 
326
381
  record = results.first
@@ -332,14 +387,16 @@ EOF
332
387
  end
333
388
 
334
389
  def test_html_snippet_from_selection_results
335
- GrnMini::Array.tmpdb do |array|
390
+ GrnMini::tmpdb do
391
+ array = GrnMini::Array.new
392
+
336
393
  array << {text: <<EOF, filename: "aaa.txt"}
337
394
  <html>
338
395
  <div>This is a pen pep pea pek pet.</div>
339
396
  </html>
340
397
  EOF
341
398
 
342
- results = array.select("This pen")
399
+ results = array.select("text:@This text:@pen")
343
400
  snippet = GrnMini::Util::html_snippet_from_selection_results(results)
344
401
 
345
402
  record = results.first
@@ -350,7 +407,9 @@ EOF
350
407
  end
351
408
 
352
409
  def test_paginate
353
- GrnMini::Array.tmpdb do |array|
410
+ GrnMini::tmpdb do
411
+ array = GrnMini::Array.new
412
+
354
413
  array << {text: "aaaa", filename: "1.txt"}
355
414
  array << {text: "aaaa aaaa", filename: "2a.txt"}
356
415
  array << {text: "aaaa aaaa aaaa", filename: "3.txt"}
@@ -358,7 +417,7 @@ EOF
358
417
  array << {text: "aaaa aaaa", filename: "2c.txt"}
359
418
  array << {text: "aaaa aaaa", filename: "2d.txt"}
360
419
 
361
- results = array.select("aaaa")
420
+ results = array.select { |r| r.text =~ "aaaa" }
362
421
 
363
422
  # page1
364
423
  page_entries = results.paginate([["_score", :desc]], :page => 1, :size => 5)
@@ -375,4 +434,175 @@ EOF
375
434
  assert_equal "1.txt", page_entries.first.filename
376
435
  end
377
436
  end
437
+
438
+ def test_multi_table
439
+ Dir.mktmpdir do |dir|
440
+ GrnMini::create_or_open(File.join(dir, "test.db"))
441
+
442
+ users = GrnMini::Array.new("Users")
443
+ users << {name: "aaa", age: 10}
444
+ users << {name: "bbb", age: 20}
445
+ users << {name: "ccc", age: 30}
446
+
447
+ articles = GrnMini::Array.new("Articles")
448
+ articles << {title: "Hello", text: "hello everyone."}
449
+
450
+ assert Groonga["Users"]
451
+ assert_equal 3, users.size
452
+
453
+ assert Groonga["Articles"]
454
+ assert_equal 1, articles.size
455
+ end
456
+ end
457
+
458
+ def test_multi_table_select
459
+ GrnMini::tmpdb do
460
+ users = GrnMini::Array.new("Users")
461
+ users << {name: "aaa", age: 10, text: ""}
462
+ users << {name: "bbb", age: 20}
463
+ users << {name: "ccc", age: 30}
464
+
465
+ articles = GrnMini::Array.new("Articles")
466
+ articles << {title: "1", text: "111 aaa"}
467
+ articles << {title: "2", text: "222 bbb"}
468
+ articles << {title: "3", text: "333 ccc"}
469
+
470
+ results = users.select("222 OR ccc", default_column: "text")
471
+ assert_equal 0, results.size
472
+
473
+ results = articles.select("222 OR ccc", default_column: "text")
474
+ assert_equal 2, results.size
475
+ assert_equal "2", results.first.title
476
+ end
477
+ end
478
+
479
+ def test_setup_columns
480
+ GrnMini::tmpdb do
481
+ array = GrnMini::Array.new
482
+
483
+ array.setup_columns(
484
+ name: "",
485
+ age: 0,
486
+ )
487
+
488
+ array << {name: "bbb", age: 20 }
489
+ assert_raises(Groonga::NoSuchColumn) { array << {name: "aaa", age: 10, text: ""} }
490
+ assert_equal 2, array.size
491
+ end
492
+ end
493
+
494
+ def test_setup_columns_groonga_table
495
+ GrnMini::tmpdb do
496
+ users = GrnMini::Array.new("Users")
497
+
498
+ users.setup_columns(
499
+ parent: users,
500
+ )
501
+
502
+ users << {}
503
+ users << { parent: users[1] }
504
+ users << { parent: users[2] }
505
+
506
+ # No error ..
507
+ # users << { parent: 123456 }
508
+ # users << { parent: 1.5 }
509
+ # users << { parent: Time.now }
510
+
511
+ assert_equal nil, users[1].parent
512
+ assert_equal users[1], users[2].parent
513
+ assert_equal users[1], users[3].parent.parent
514
+ end
515
+ end
516
+
517
+ def test_setup_columns_vector
518
+ GrnMini::tmpdb do
519
+ array = GrnMini::Array.new
520
+ array.setup_columns(links:[""])
521
+
522
+ array << {}
523
+ assert_equal [], array[1].links
524
+
525
+ # Nothing happens ..
526
+ array[1].links << "http://ongaeshi.me"
527
+ assert_equal 0, array[1].links.size
528
+
529
+ # Use links=
530
+ array[1].links = ["http://ongaeshi.me", "http://yahoo.co.jp"]
531
+ assert_equal 2, array[1].links.size
532
+
533
+ array << { links: ["aaa", "bbb", "ccc"]}
534
+ array << { links: ["AAA"]}
535
+
536
+ # array.each do |record|
537
+ # p record.attributes
538
+ # end
539
+
540
+ assert_equal 3, array.size
541
+ assert_equal 3, array[2].links.size
542
+ end
543
+ end
544
+
545
+ def test_setup_columns_vector2
546
+ GrnMini::tmpdb do
547
+ array = GrnMini::Array.new
548
+ array.setup_columns(strs: [""],
549
+ numbers: [0],
550
+ floats: [0.1],
551
+ times: [Time.new],
552
+ arrays: [array]
553
+ )
554
+
555
+ array.add(strs: ["AAA", "BBB"],
556
+ numbers: [1, 2, 3],
557
+ floats: [0.1, 0.2, 0.3],
558
+ times: [Time.at(0), Time.at(1), Time.at(3)],
559
+ arrays: []
560
+ )
561
+ array.add(arrays: [array[1]])
562
+ array.add(arrays: [array[1], array[2]])
563
+
564
+ # First element is [1..N], Second and subsequent elements is [0..N-1].
565
+ assert_equal 0.2, array[3].arrays[1].arrays[0].floats[1]
566
+ end
567
+ end
568
+
569
+ def test_tweet
570
+ GrnMini::tmpdb do
571
+ users = GrnMini::Array.new("Users")
572
+ tweets = GrnMini::Array.new("Tweets")
573
+
574
+ users.setup_columns(name: "A Name"
575
+ )
576
+ tweets.setup_columns(user: users,
577
+ time: Time.new,
578
+ text: "A Tweet.",
579
+ replies: [tweets]
580
+ )
581
+
582
+ users << { name: "AAA" }
583
+ users << { name: "BBB" }
584
+
585
+ tweets << { user: users[1], time: Time.at(1), text: "AAA Tweet 1" }
586
+ tweets << { user: users[2], time: Time.at(2), text: "BBB Tweet 1" }
587
+ tweets << { user: users[1], time: Time.at(3), text: "AAA Tweet 2" }
588
+ tweets << { user: users[1], time: Time.at(4), text: "Re: BBB Tweet 1" }
589
+ tweets << { user: users[2], time: Time.at(5), text: "Re: Re: BBB Tweet 1" }
590
+ tweets[3].replies = [tweets[4], tweets[5]]
591
+
592
+ # tweets.each do |record|
593
+ # p record.attributes
594
+ # end
595
+
596
+ assert_equal 3, tweets.select("user:1").size
597
+ assert_equal "AAA Tweet 2", tweets.select("user:1 text:@Tweet text:@2").first.text
598
+ assert_equal 2, tweets.select("user:2").size
599
+ end
600
+ end
601
+
602
+ def test_not_support_column_type
603
+ GrnMini::tmpdb do
604
+ array = GrnMini::Array.new
605
+ assert_raises(GrnMini::NotSupportColumnType) { array.setup_columns(error: Hash) }
606
+ end
607
+ end
378
608
  end