grn_mini 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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