rufus-tokyo 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +8 -0
- data/CREDITS.txt +14 -1
- data/README.txt +35 -7
- data/lib/rufus/tokyo.rb +2 -245
- data/lib/rufus/tokyo/base.rb +123 -0
- data/lib/rufus/tokyo/cabinet.rb +3 -0
- data/lib/rufus/tokyo/cabinet/abstract.rb +237 -0
- data/lib/rufus/tokyo/cabinet/lib.rb +179 -0
- data/lib/rufus/tokyo/cabinet/table.rb +528 -0
- data/lib/rufus/tokyo/cabinet/util.rb +322 -0
- data/lib/rufus/tokyo/dystopia/lib.rb +71 -0
- data/lib/rufus/tokyo/dystopia/words.rb +87 -0
- data/lib/rufus/tokyo/hmethods.rb +109 -0
- data/test/{cabinet_0_test.rb → cabinet/abstract_0_test.rb} +23 -15
- data/test/cabinet/abstract_1_test.rb +69 -0
- data/test/cabinet/api_0_test.rb +26 -0
- data/test/cabinet/hmethods_test.rb +52 -0
- data/test/cabinet/table_0_test.rb +63 -0
- data/test/cabinet/table_1_test.rb +153 -0
- data/test/cabinet/test.rb +9 -0
- data/test/cabinet/util_list_test.rb +86 -0
- data/test/cabinet/util_map_test.rb +69 -0
- data/test/dystopia/test.rb +9 -0
- data/test/dystopia/words_0_test.rb +22 -0
- data/test/mem1.rb +44 -0
- data/test/test.rb +5 -2
- data/test/test_base.rb +2 -0
- metadata +28 -3
@@ -0,0 +1,109 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
|
25
|
+
#
|
26
|
+
# "made in Japan"
|
27
|
+
#
|
28
|
+
# jmettraux@gmail.com
|
29
|
+
#
|
30
|
+
|
31
|
+
|
32
|
+
module Rufus
|
33
|
+
module Tokyo
|
34
|
+
|
35
|
+
#
|
36
|
+
# A mixin for Cabinet and Map, gathers all the hash-like methods
|
37
|
+
#
|
38
|
+
module HashMethods
|
39
|
+
|
40
|
+
#
|
41
|
+
# The [] methods
|
42
|
+
#
|
43
|
+
# (assumes there's an underlying get(k) method)
|
44
|
+
#
|
45
|
+
def [] (k)
|
46
|
+
val = get(k)
|
47
|
+
return val unless val.nil?
|
48
|
+
return nil unless @default_proc
|
49
|
+
@default_proc.call(self, k)
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# Returns an array of all the values
|
54
|
+
#
|
55
|
+
def values
|
56
|
+
collect { |k, v| v }
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Our classical 'each'
|
61
|
+
#
|
62
|
+
def each
|
63
|
+
keys.each { |k| yield(k, self[k]) }
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Turns this instance into a Ruby hash
|
68
|
+
#
|
69
|
+
def to_h
|
70
|
+
self.inject({}) { |h, (k, v)| h[k] = v; h }
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Turns this instance into an array of [ key, value ]
|
75
|
+
#
|
76
|
+
def to_a
|
77
|
+
self.collect { |e| e }
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# Returns a new Ruby hash which is a merge of this Map and the given hash
|
82
|
+
#
|
83
|
+
def merge (h)
|
84
|
+
self.to_h.merge(h)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Merges the entries in the given hash into this map
|
89
|
+
#
|
90
|
+
def merge! (h)
|
91
|
+
h.each { |k, v| self[k] = v }
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def default (key=nil)
|
96
|
+
val = self[key]
|
97
|
+
val.nil? ? @default_proc.call(self, key) : val
|
98
|
+
end
|
99
|
+
|
100
|
+
def default= (val)
|
101
|
+
@default_proc = lambda { |h, k| val }
|
102
|
+
end
|
103
|
+
|
104
|
+
attr_reader :default_proc
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
@@ -5,11 +5,9 @@
|
|
5
5
|
# Fri Jan 23 08:31:01 JST 2009
|
6
6
|
#
|
7
7
|
|
8
|
-
require File.dirname(__FILE__) + '
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
9
|
|
10
|
-
require '
|
11
|
-
|
12
|
-
require 'rufus/tokyo'
|
10
|
+
require 'rufus/tokyo/cabinet'
|
13
11
|
|
14
12
|
|
15
13
|
class CabinetZero < Test::Unit::TestCase
|
@@ -25,11 +23,6 @@ class CabinetZero < Test::Unit::TestCase
|
|
25
23
|
@db
|
26
24
|
end
|
27
25
|
|
28
|
-
def test_lib
|
29
|
-
|
30
|
-
assert_not_nil Rufus::Tokyo.lib
|
31
|
-
end
|
32
|
-
|
33
26
|
def test_basic_workflow
|
34
27
|
|
35
28
|
db['pillow'] = 'Shonagon'
|
@@ -43,18 +36,16 @@ class CabinetZero < Test::Unit::TestCase
|
|
43
36
|
|
44
37
|
def test_clear
|
45
38
|
|
46
|
-
db = Rufus::Tokyo::Cabinet.new('test_data.tch')
|
47
|
-
db.clear
|
48
|
-
|
49
39
|
40.times { |i| db[i.to_s] = i.to_s }
|
50
40
|
assert_equal 40, db.size
|
41
|
+
|
42
|
+
db.clear
|
43
|
+
|
44
|
+
assert_equal 0, db.size
|
51
45
|
end
|
52
46
|
|
53
47
|
def test_keys_and_values
|
54
48
|
|
55
|
-
db = Rufus::Tokyo::Cabinet.new('test_data.tch')
|
56
|
-
db.clear
|
57
|
-
|
58
49
|
keys = %w{ alpha bravo charly delta echo foxtrott }
|
59
50
|
|
60
51
|
keys.each_with_index { |k, i| db[k] = i.to_s }
|
@@ -63,5 +54,22 @@ class CabinetZero < Test::Unit::TestCase
|
|
63
54
|
assert_equal %w{ 0 1 2 3 4 5 }, db.values
|
64
55
|
end
|
65
56
|
|
57
|
+
def test_merge
|
58
|
+
|
59
|
+
db['a'] = 'A'
|
60
|
+
|
61
|
+
assert_equal(
|
62
|
+
{ 'a' => 'A', 'b' => 'B', 'c' => 'C' },
|
63
|
+
db.merge({ 'b' => 'B', 'c' => 'C' }))
|
64
|
+
|
65
|
+
assert_equal 1, db.size
|
66
|
+
|
67
|
+
db.merge!({ 'b' => 'B', 'c' => 'C' })
|
68
|
+
|
69
|
+
assert_equal(3, db.size)
|
70
|
+
|
71
|
+
assert_equal({ 'a' => 'A', 'b' => 'B', 'c' => 'C' }, db.to_h)
|
72
|
+
end
|
73
|
+
|
66
74
|
end
|
67
75
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-tokyo
|
4
|
+
#
|
5
|
+
# Sun Jan 25 12:26:48 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
|
+
|
10
|
+
require 'fileutils'
|
11
|
+
require 'rufus/tokyo/cabinet'
|
12
|
+
|
13
|
+
|
14
|
+
class CabinetOne < Test::Unit::TestCase
|
15
|
+
|
16
|
+
def test_copy
|
17
|
+
|
18
|
+
cab = Rufus::Tokyo::Cabinet.new('test_source.tch')
|
19
|
+
5000.times { |i| cab["key #{i}"] = "val #{i}" }
|
20
|
+
2500.times { |i| cab.delete("key #{i}") }
|
21
|
+
assert_equal 2500, cab.size
|
22
|
+
cab.copy('test_target.tch')
|
23
|
+
cab.close
|
24
|
+
|
25
|
+
cab = Rufus::Tokyo::Cabinet.new('test_target.tch')
|
26
|
+
assert_equal 2500, cab.size
|
27
|
+
cab.close
|
28
|
+
|
29
|
+
FileUtils.rm('test_source.tch')
|
30
|
+
FileUtils.rm('test_target.tch')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_compact_copy
|
34
|
+
|
35
|
+
cab = Rufus::Tokyo::Cabinet.new('test_source.tch')
|
36
|
+
100.times { |i| cab["key #{i}"] = "val #{i}" }
|
37
|
+
50.times { |i| cab.delete("key #{i}") }
|
38
|
+
assert_equal 50, cab.size
|
39
|
+
cab.compact_copy('test_target.tch')
|
40
|
+
cab.close
|
41
|
+
|
42
|
+
cab = Rufus::Tokyo::Cabinet.new('test_target.tch')
|
43
|
+
assert_equal 50, cab.size
|
44
|
+
cab.close
|
45
|
+
|
46
|
+
fs0 = File.size('test_source.tch')
|
47
|
+
fs1 = File.size('test_target.tch')
|
48
|
+
assert (fs0 > fs1)
|
49
|
+
|
50
|
+
FileUtils.rm('test_source.tch')
|
51
|
+
FileUtils.rm('test_target.tch')
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_default
|
55
|
+
|
56
|
+
db = Rufus::Tokyo::Cabinet.new('test_data.tch', :default => 'wrong')
|
57
|
+
db.clear
|
58
|
+
|
59
|
+
db['a'] = 'A'
|
60
|
+
|
61
|
+
assert_equal 'A', db['a']
|
62
|
+
assert_equal 'wrong', db['b']
|
63
|
+
|
64
|
+
assert_equal 1, db.size
|
65
|
+
|
66
|
+
db.close
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-tokyo
|
4
|
+
#
|
5
|
+
# Mon Jan 26 15:10:03 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
|
+
|
10
|
+
require 'rufus/tokyo/base'
|
11
|
+
|
12
|
+
|
13
|
+
class ApiZero < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_compute_open_mode
|
16
|
+
|
17
|
+
o = Object.new
|
18
|
+
o.extend(Rufus::Tokyo::TokyoContainerMixin)
|
19
|
+
|
20
|
+
assert_equal 0, o.compute_open_mode({})
|
21
|
+
assert_equal 16, o.compute_open_mode(:no_lock => true)
|
22
|
+
assert_equal 17, o.compute_open_mode([:no_lock, :reader])
|
23
|
+
assert_equal 20, o.compute_open_mode([:no_lock, :create])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-tokyo
|
4
|
+
#
|
5
|
+
# Thu Jan 29 11:19:25 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
|
+
|
10
|
+
require 'rufus/tokyo/hmethods'
|
11
|
+
|
12
|
+
|
13
|
+
class HmethodsTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
class MyHash
|
16
|
+
attr_accessor :default_proc
|
17
|
+
def get (k)
|
18
|
+
k.to_i % 2 == 0 ? k : nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@h = MyHash.new
|
24
|
+
@h.extend(Rufus::Tokyo::HashMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_myhash
|
28
|
+
|
29
|
+
assert_equal nil, @h[1]
|
30
|
+
assert_equal 2, @h[2]
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_default
|
34
|
+
|
35
|
+
@h.default = :default
|
36
|
+
|
37
|
+
assert_equal :default, @h.default
|
38
|
+
|
39
|
+
assert_equal :default, @h[1]
|
40
|
+
assert_equal 2, @h[2]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_default_proc
|
44
|
+
|
45
|
+
@h.default_proc = lambda { |h, k| k * 2 }
|
46
|
+
|
47
|
+
assert_equal 2, @h[1]
|
48
|
+
assert_equal 2, @h[2]
|
49
|
+
assert_equal 6, @h[3]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-tokyo
|
4
|
+
#
|
5
|
+
# Mon Jan 26 15:10:03 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
|
+
|
10
|
+
require 'rufus/tokyo/cabinet/table'
|
11
|
+
|
12
|
+
|
13
|
+
class TableZero < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_open_missing
|
16
|
+
|
17
|
+
e = assert_raises Rufus::Tokyo::TokyoError do
|
18
|
+
Rufus::Tokyo::Table.new('missing.tdb')
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_equal '(err 3) file not found', e.message
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_tabbed_put
|
25
|
+
|
26
|
+
t = Rufus::Tokyo::Table.new('test_new.tdb', :create, :write)
|
27
|
+
t.clear
|
28
|
+
|
29
|
+
assert_equal 0, t.size
|
30
|
+
|
31
|
+
assert t.genuid > 0, 'unique id is 0, bad'
|
32
|
+
assert t.generate_unique_id > 0, 'unique id is 0, bad'
|
33
|
+
|
34
|
+
t.tabbed_put('toto', 'name', 'toto', 'age', '3')
|
35
|
+
t.tabbed_put('fred', 'name', 'fred', 'age', '4')
|
36
|
+
|
37
|
+
assert_equal 2, t.size
|
38
|
+
|
39
|
+
t.close
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_put
|
43
|
+
|
44
|
+
t = Rufus::Tokyo::Table.new('test_new.tdb', :create, :write)
|
45
|
+
t.clear
|
46
|
+
|
47
|
+
t['pk0'] = [ 'name', 'alfred', 'age', '22']
|
48
|
+
t['pk1'] = { 'name' => 'jim', 'age' => '23' }
|
49
|
+
|
50
|
+
assert_equal 2, t.size
|
51
|
+
|
52
|
+
assert_equal({ 'name' => 'jim', 'age' => '23' }, t['pk1'])
|
53
|
+
|
54
|
+
t.delete('pk0')
|
55
|
+
|
56
|
+
assert_equal 1, t.size
|
57
|
+
|
58
|
+
assert_nil t['pk0']
|
59
|
+
|
60
|
+
t.close
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Testing rufus-tokyo
|
4
|
+
#
|
5
|
+
# Mon Jan 26 15:10:03 JST 2009
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.dirname(__FILE__) + '/../test_base'
|
9
|
+
|
10
|
+
require 'rufus/tokyo/cabinet/table'
|
11
|
+
|
12
|
+
|
13
|
+
class TableOne < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@tdb = Rufus::Tokyo::Table.new('test_new.tdb', :create, :write)
|
17
|
+
@tdb.clear
|
18
|
+
@tdb['pk0'] = { 'name' => 'jim', 'age' => '25', 'lang' => 'ja,en' }
|
19
|
+
@tdb['pk1'] = { 'name' => 'jeff', 'age' => '32', 'lang' => 'en,es' }
|
20
|
+
@tdb['pk2'] = { 'name' => 'jack', 'age' => '44', 'lang' => 'en' }
|
21
|
+
@tdb['pk3'] = { 'name' => 'jake', 'age' => '45', 'lang' => 'en,li' }
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
@tdb.close
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_prepare_query
|
29
|
+
|
30
|
+
q = @tdb.prepare_query { |q|
|
31
|
+
q.add 'lang', :includes, 'en'
|
32
|
+
}
|
33
|
+
rs = q.run
|
34
|
+
|
35
|
+
assert_equal 4, rs.size
|
36
|
+
|
37
|
+
rs.close
|
38
|
+
|
39
|
+
q.limit 2
|
40
|
+
|
41
|
+
rs = q.run
|
42
|
+
|
43
|
+
assert_equal 2, rs.size
|
44
|
+
|
45
|
+
q.close
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_limit
|
49
|
+
|
50
|
+
rs = @tdb.do_query { |q|
|
51
|
+
q.add 'lang', :includes, 'en'
|
52
|
+
q.order_by 'name', :desc
|
53
|
+
q.limit 2 # set_max
|
54
|
+
}
|
55
|
+
|
56
|
+
assert_equal 2, rs.size
|
57
|
+
|
58
|
+
assert_equal(
|
59
|
+
[
|
60
|
+
{:pk => 'pk0', "name"=>"jim", "lang"=>"ja,en", "age"=>"25"},
|
61
|
+
{:pk => 'pk1', "name"=>"jeff", "lang"=>"en,es", "age"=>"32"}
|
62
|
+
],
|
63
|
+
rs.to_a)
|
64
|
+
|
65
|
+
rs.free
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_order_strasc
|
69
|
+
|
70
|
+
assert_equal(
|
71
|
+
[
|
72
|
+
{:pk => 'pk2', "name"=>"jack", "lang"=>"en", "age"=>"44"},
|
73
|
+
{:pk => 'pk3', "name"=>"jake", "lang"=>"en,li", "age"=>"45"},
|
74
|
+
{:pk => 'pk1', "name"=>"jeff", "lang"=>"en,es", "age"=>"32"},
|
75
|
+
{:pk => 'pk0', "name"=>"jim", "lang"=>"ja,en", "age"=>"25"}
|
76
|
+
],
|
77
|
+
@tdb.query { |q|
|
78
|
+
q.add 'lang', :includes, 'en'
|
79
|
+
q.order_by 'name', :asc
|
80
|
+
})
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_order_numasc
|
84
|
+
|
85
|
+
assert_equal(
|
86
|
+
[
|
87
|
+
{:pk => 'pk0', "name"=>"jim", "lang"=>"ja,en", "age"=>"25"},
|
88
|
+
{:pk => 'pk1', "name"=>"jeff", "lang"=>"en,es", "age"=>"32"},
|
89
|
+
{:pk => 'pk2', "name"=>"jack", "lang"=>"en", "age"=>"44"},
|
90
|
+
{:pk => 'pk3', "name"=>"jake", "lang"=>"en,li", "age"=>"45"}
|
91
|
+
],
|
92
|
+
a = @tdb.query { |q|
|
93
|
+
q.add 'lang', :includes, 'en'
|
94
|
+
q.order_by 'age', :numasc
|
95
|
+
})
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_matches
|
99
|
+
|
100
|
+
assert_equal(
|
101
|
+
[
|
102
|
+
{:pk => 'pk2', "name"=>"jack", "lang"=>"en", "age"=>"44"},
|
103
|
+
{:pk => 'pk3', "name"=>"jake", "lang"=>"en,li", "age"=>"45"}
|
104
|
+
],
|
105
|
+
a = @tdb.query { |q|
|
106
|
+
q.add 'name', :matches, '^j.+k'
|
107
|
+
})
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_no_pk
|
111
|
+
|
112
|
+
assert_equal(
|
113
|
+
[
|
114
|
+
{"name"=>"jack", "lang"=>"en", "age"=>"44"},
|
115
|
+
{"name"=>"jake", "lang"=>"en,li", "age"=>"45"}
|
116
|
+
],
|
117
|
+
a = @tdb.query { |q|
|
118
|
+
q.add 'name', :matches, '^j.+k'
|
119
|
+
q.no_pk
|
120
|
+
})
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_pk_only
|
124
|
+
|
125
|
+
assert_equal(
|
126
|
+
[ 'pk2', 'pk3' ],
|
127
|
+
a = @tdb.query { |q|
|
128
|
+
q.add 'name', :matches, '^j.+k'
|
129
|
+
q.pk_only
|
130
|
+
})
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_condition_numerical_gt
|
134
|
+
|
135
|
+
assert_equal(
|
136
|
+
[ 'pk2', 'pk3' ],
|
137
|
+
a = @tdb.query { |q|
|
138
|
+
q.add 'age', :gt, '40'
|
139
|
+
q.pk_only
|
140
|
+
})
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_condition_negate
|
144
|
+
|
145
|
+
assert_equal(
|
146
|
+
[ 'pk0', 'pk1' ],
|
147
|
+
a = @tdb.query { |q|
|
148
|
+
q.add 'age', :gt, '40', false
|
149
|
+
q.pk_only
|
150
|
+
})
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|