mongoose 0.2.0 → 0.2.5
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/README +13 -10
- data/bin/mongoose_export.rb +17 -0
- data/bin/mongoose_import.rb +17 -0
- data/changes.txt +24 -0
- data/example/simple_examples.rb +63 -26
- data/lib/mongoose.rb +43 -3
- data/lib/mongoose/column.rb +147 -64
- data/lib/mongoose/error.rb +9 -0
- data/lib/mongoose/query.rb +52 -0
- data/lib/mongoose/table.rb +318 -97
- data/lib/mongoose/util.rb +21 -8
- data/test/tc_relations.rb +28 -1
- data/test/tc_table.rb +145 -25
- metadata +9 -4
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Mongoose 0.2.
|
1
|
+
= Mongoose 0.2.5
|
2
2
|
|
3
3
|
A database management system written in Ruby. It has an ActiveRecord-like
|
4
4
|
interface, uses Skiplists for its indexing, and Marshal for its data
|
@@ -15,6 +15,8 @@ provided much of the inspiration for the query language. Also, Ezra has
|
|
15
15
|
graciously taken the time to give me pointers on how to make Mongoose's query
|
16
16
|
language and api better.
|
17
17
|
|
18
|
+
Thanks to everyone who has given me feedback so far on Mongoose.
|
19
|
+
|
18
20
|
Thanks to everyone who gave me feedback on KirbyBase. I have tried to put all
|
19
21
|
the lessons learned from developing that library to good use here.
|
20
22
|
|
@@ -64,7 +66,7 @@ db.create_table(:plane) do |tbl|
|
|
64
66
|
tbl.add_column(:range, :integer)
|
65
67
|
end
|
66
68
|
|
67
|
-
# Add a record.
|
69
|
+
# Add a record. You can also use #create.
|
68
70
|
rec = Plane.new
|
69
71
|
rec.name = 'P-51'
|
70
72
|
rec.country = 'USA'
|
@@ -75,18 +77,18 @@ rec.save
|
|
75
77
|
# Various ways to find a record; should be familiar to ActiveRecord users.
|
76
78
|
Plane.find(1) # Find record with id equal 1.
|
77
79
|
|
78
|
-
Plane.find { speed > 350 } # Find all planes with speed > 350.
|
80
|
+
Plane.find { |plane| plane.speed > 350 } # Find all planes with speed > 350.
|
79
81
|
|
80
82
|
Plane.find # Find all records.
|
81
83
|
|
82
|
-
Plane.find(:first) { country == 'USA' } # Find first plane from USA.
|
84
|
+
Plane.find(:first) { |plane| plane.country == 'USA' } # Find first plane from USA.
|
83
85
|
|
84
|
-
Plane.find do
|
85
|
-
any do
|
86
|
-
country == 'USA'
|
87
|
-
country == 'Great Britain'
|
86
|
+
Plane.find do |plane| # Find all planes from either USA or
|
87
|
+
plane.any do # Great Britain with speed > 400.
|
88
|
+
plane.country == 'USA'
|
89
|
+
plane.country == 'Great Britain'
|
88
90
|
end
|
89
|
-
speed > 400
|
91
|
+
plane.speed > 400
|
90
92
|
end
|
91
93
|
|
92
94
|
# Delete a record.
|
@@ -101,7 +103,8 @@ db.close
|
|
101
103
|
* README - this file
|
102
104
|
* install.rb - install script
|
103
105
|
* changes.txt - history of changes.
|
104
|
-
* lib directory - dbms module
|
106
|
+
* lib directory - dbms module
|
107
|
+
* bin directory - import, export scripts
|
105
108
|
* test directory - unit tests
|
106
109
|
* examples directory - many example scripts demonstrating features.
|
107
110
|
* images directory - images used in manual.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
require_gem 'Mongoose'
|
4
|
+
rescue LoadError
|
5
|
+
require 'mongoose'
|
6
|
+
end
|
7
|
+
|
8
|
+
raise "Must supply class name to export!" unless ARGV.size > 0
|
9
|
+
|
10
|
+
class_name = ARGV[0]
|
11
|
+
filename = 1
|
12
|
+
filename = ARGV[1] if ARGV.size > 1
|
13
|
+
|
14
|
+
Object.const_set(ARGV[0], Class.new(Mongoose::Table))
|
15
|
+
|
16
|
+
db = Mongoose::Database.new
|
17
|
+
Object.const_get(class_name).export(filename)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
require_gem 'Mongoose'
|
4
|
+
rescue LoadError
|
5
|
+
require 'mongoose'
|
6
|
+
end
|
7
|
+
|
8
|
+
raise "Must supply class name to import!" unless ARGV.size > 0
|
9
|
+
|
10
|
+
class_name = ARGV[0]
|
11
|
+
filename = 0
|
12
|
+
filename = ARGV[1] if ARGV.size > 1
|
13
|
+
|
14
|
+
Object.const_set(ARGV[0], Class.new(Mongoose::Table))
|
15
|
+
|
16
|
+
db = Mongoose::Database.new
|
17
|
+
Object.const_get(class_name).import(filename)
|
data/changes.txt
CHANGED
@@ -23,3 +23,27 @@
|
|
23
23
|
eliminated the string eval. Thanks Logan!
|
24
24
|
* Included a new example from Daniel Sheppard that shows how to integrate
|
25
25
|
ActiveRecord validations into Mongoose.
|
26
|
+
|
27
|
+
2006-07-25:: Version 0.2.5
|
28
|
+
* Logan Capaldo submitted a patch to the Util module to make pluralization
|
29
|
+
a lot smarter. He also added method Table.plural_form. And he updated the
|
30
|
+
test cases to test these changes. Thanks Logan!
|
31
|
+
* Refactored the query engine code. Thanks to Logan Capaldo for code and ideas
|
32
|
+
to get me going.
|
33
|
+
* John Long brought up a great point about losing access to instance variables
|
34
|
+
from the calling object, using the present scheme of #instance_eval(&block)
|
35
|
+
in Table.find. Therefore, I am going back to requiring that the table class
|
36
|
+
be passed as a block parameter and that column names be qualified by the
|
37
|
+
table's class name.
|
38
|
+
* Added Table.import, Table.export methods.
|
39
|
+
* Added Table.destroy, Table.destroy_all, Table.content_columns, Table.exists?
|
40
|
+
methods.
|
41
|
+
* Major cleanup of Table.find. First, I have split the functionality up into
|
42
|
+
separate methods. Second, I believe I have got all of the basic options
|
43
|
+
working: :first, :all, one id, mulitple ids, :order, :limit, :offset.
|
44
|
+
* Added dynamic attribute-base finder methods, i.e. Plane.find_by_country and
|
45
|
+
Plane.find_all_by_country.
|
46
|
+
* Fixed Plane.initialize so that it does the right thing, i.e. if you pass it a
|
47
|
+
hash, it will create a new record initialized to those values.
|
48
|
+
* Added Table#update_attributes method.
|
49
|
+
* Added Table#delete , Table#delete_all methods.
|
data/example/simple_examples.rb
CHANGED
@@ -12,6 +12,7 @@ unless ARGV[0] == 'keep-data'
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
# Create the table class.
|
15
16
|
class Plane < Mongoose::Table
|
16
17
|
validates_presence_of :name, :speed
|
17
18
|
end
|
@@ -30,12 +31,13 @@ unless ARGV[0] == 'keep-data'
|
|
30
31
|
|
31
32
|
# Add records.
|
32
33
|
Plane.create :name => 'P-51', :country => 'USA', :speed => 402, :range => 1205
|
33
|
-
Plane.create :name => 'Spitfire', :country => 'Great Britain', :speed =>
|
34
|
+
Plane.create :name => 'Spitfire', :country => 'Great Britain', :speed => 351,
|
34
35
|
:range => 454
|
35
36
|
Plane.create :name => 'ME-109', :country => 'Germany', :speed => 354,
|
36
37
|
:range => 501
|
37
38
|
|
38
|
-
# Forgot value for speed, which is a required field.
|
39
|
+
# Forgot value for speed, which is a required field. Notice
|
40
|
+
# validates_presence_of in the class definition above.
|
39
41
|
begin
|
40
42
|
Plane.create :name => 'P-39', :country => 'USA', :range => 701
|
41
43
|
rescue RuntimeError => e
|
@@ -49,52 +51,87 @@ puts "\n\nFind P-51 record by ID"
|
|
49
51
|
p_51 = Plane.find(1)
|
50
52
|
p p_51
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
p_51.save
|
56
|
-
end
|
54
|
+
# Change speed on P-51 record and save.
|
55
|
+
p_51.speed = 405
|
56
|
+
p_51.save
|
57
57
|
|
58
58
|
puts "\n\nFind all records with speed greater than 350 mph"
|
59
|
-
result = Plane.find { speed > 350 }
|
59
|
+
result = Plane.find { |plane| plane.speed > 350 }
|
60
60
|
p result
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
|
63
|
+
puts "\n\nFind all US planes with speed greater than 350 mph"
|
64
|
+
result = Plane.find { |plane| plane.country == 'USA' and plane.speed > 350 }
|
64
65
|
p result
|
65
66
|
|
66
67
|
puts "\n\nFind all British planes with speed greater than 300 mph"
|
67
|
-
result = Plane.find do
|
68
|
-
country == 'Great Britain' and speed > 300
|
68
|
+
result = Plane.find do |plane|
|
69
|
+
plane.country == 'Great Britain' and plane.speed > 300
|
69
70
|
end
|
70
71
|
p result
|
71
72
|
|
72
73
|
puts "\n\nFind all Allied planes"
|
73
|
-
result = Plane.find do
|
74
|
-
any do
|
75
|
-
country == 'USA'
|
76
|
-
country == 'Great Britain'
|
74
|
+
result = Plane.find do |plane|
|
75
|
+
plane.any do
|
76
|
+
plane.country == 'USA'
|
77
|
+
plane.country == 'Great Britain'
|
77
78
|
end
|
78
79
|
end
|
79
80
|
p result
|
80
81
|
|
81
|
-
puts "\n\nFind all Allied planes with speed greater than
|
82
|
-
result = Plane.find do
|
83
|
-
any do
|
84
|
-
country == 'USA'
|
85
|
-
country == 'Great Britain'
|
82
|
+
puts "\n\nFind all Allied planes with speed greater than 350 mph"
|
83
|
+
result = Plane.find do |plane|
|
84
|
+
plane.any do
|
85
|
+
plane.country == 'USA'
|
86
|
+
plane.country == 'Great Britain'
|
86
87
|
end
|
87
|
-
speed >
|
88
|
+
plane.speed > 350
|
88
89
|
end
|
89
90
|
p result
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
puts "\n\nFind all Allied planes with speed between 300 and 350 mph"
|
93
|
+
result = Plane.find do |plane|
|
94
|
+
plane.any do
|
95
|
+
plane.country == 'USA'
|
96
|
+
plane.country == 'Great Britain'
|
97
|
+
end
|
98
|
+
plane.speed.between(300, 350)
|
99
|
+
end
|
100
|
+
p result
|
95
101
|
|
96
102
|
puts "\n\nFind all records in table."
|
97
103
|
result = Plane.find
|
98
104
|
p result
|
99
105
|
|
106
|
+
puts "\n\nFind by dynamic finder method."
|
107
|
+
result = Plane.find_by_name('ME-109')
|
108
|
+
p result
|
109
|
+
|
110
|
+
puts "\n\nSort result set by name."
|
111
|
+
result = Plane.find(:all, :order => :name)
|
112
|
+
p result
|
113
|
+
|
114
|
+
puts "\n\nSort by country, then name."
|
115
|
+
result = Plane.find(:order => [:country, :name])
|
116
|
+
p result
|
117
|
+
|
118
|
+
puts "\n\nSort by speed descending."
|
119
|
+
result = Plane.find(:order => -:speed)
|
120
|
+
p result
|
121
|
+
|
122
|
+
puts "\n\nLimit number of records returned."
|
123
|
+
result = Plane.find(:order => :name, :limit => 2)
|
124
|
+
p result
|
125
|
+
|
126
|
+
puts "\n\nSpecify offset."
|
127
|
+
result = Plane.find(:order => :name, :offset => 3)
|
128
|
+
p result
|
129
|
+
|
130
|
+
# Delete Spitfire record.
|
131
|
+
spitfire = Plane.find(:first) { |plane| plane.name == 'Spitfire' }
|
132
|
+
spitfire.destroy if spitfire
|
133
|
+
|
134
|
+
puts "\n\nShow only content columns."
|
135
|
+
Plane.content_columns.each { |c| puts c.name }
|
136
|
+
|
100
137
|
db.close
|
data/lib/mongoose.rb
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'pp'
|
3
|
+
require 'forwardable'
|
4
|
+
require 'time'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'faster_csv'
|
9
|
+
rescue LoadError
|
10
|
+
require 'csv'
|
11
|
+
end
|
12
|
+
|
2
13
|
require 'mongoose/database'
|
3
14
|
require 'mongoose/table'
|
4
15
|
require 'mongoose/column'
|
5
16
|
require 'mongoose/skiplist'
|
6
17
|
require 'mongoose/linear_search'
|
18
|
+
require 'mongoose/query'
|
7
19
|
require 'mongoose/util'
|
20
|
+
require 'mongoose/error'
|
8
21
|
|
9
22
|
#
|
10
23
|
# :main:Mongoose
|
@@ -22,7 +35,7 @@ require 'mongoose/util'
|
|
22
35
|
#
|
23
36
|
module Mongoose
|
24
37
|
|
25
|
-
VERSION = '0.2.
|
38
|
+
VERSION = '0.2.5'
|
26
39
|
DATA_TYPES = [:string, :integer, :float, :time, :date, :datetime, :boolean]
|
27
40
|
TBL_EXT = '.mgt'
|
28
41
|
TBL_HDR_EXT = '.mgh'
|
@@ -30,14 +43,41 @@ TBL_IDX_EXT = '.mgi'
|
|
30
43
|
|
31
44
|
end
|
32
45
|
|
33
|
-
|
46
|
+
|
47
|
+
#-------------------------------------------------------------------------------
|
34
48
|
# Object
|
35
|
-
|
49
|
+
#-------------------------------------------------------------------------------
|
36
50
|
class Object
|
37
51
|
def full_const_get(name)
|
38
52
|
list = name.split("::")
|
39
53
|
obj = Object
|
40
54
|
list.each {|x| obj = obj.const_get(x) }
|
41
55
|
obj
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
#-------------------------------------------------------------------------------
|
61
|
+
# Symbol
|
62
|
+
#-------------------------------------------------------------------------------
|
63
|
+
class Symbol
|
64
|
+
#-----------------------------------------------------------------------------
|
65
|
+
# -@
|
66
|
+
#-----------------------------------------------------------------------------
|
67
|
+
#
|
68
|
+
# This allows you to put a minus sign in front of a field name in order
|
69
|
+
# to specify descending sort order.
|
70
|
+
def -@
|
71
|
+
("-"+self.to_s).to_sym
|
72
|
+
end
|
73
|
+
|
74
|
+
#-----------------------------------------------------------------------------
|
75
|
+
# +@
|
76
|
+
#-----------------------------------------------------------------------------
|
77
|
+
#
|
78
|
+
# This allows you to put a plus sign in front of a field name in order
|
79
|
+
# to specify ascending sort order.
|
80
|
+
def +@
|
81
|
+
("+"+self.to_s).to_sym
|
42
82
|
end
|
43
83
|
end
|
data/lib/mongoose/column.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
|
3
1
|
module Mongoose
|
4
2
|
|
5
3
|
#-------------------------------------------------------------------------------
|
@@ -11,14 +9,32 @@ class BaseColumn
|
|
11
9
|
|
12
10
|
private_class_method :new
|
13
11
|
|
12
|
+
extend Forwardable
|
13
|
+
def_delegator(:@idx, :>, :>)
|
14
|
+
def_delegator(:@idx, :>=, :>=)
|
15
|
+
def_delegator(:@idx, :==, :==)
|
16
|
+
def_delegator(:@idx, :<, :<)
|
17
|
+
def_delegator(:@idx, :<=, :<=)
|
18
|
+
def_delegator(:@idx, :between, :between)
|
19
|
+
def_delegator(:@idx, :one_of, :one_of)
|
20
|
+
|
21
|
+
#-----------------------------------------------------------------------
|
22
|
+
# BaseColumn.valid_data_type?
|
23
|
+
#-----------------------------------------------------------------------
|
14
24
|
def self.valid_data_type?(data_type)
|
15
25
|
DATA_TYPES.include?(data_type)
|
16
26
|
end
|
17
27
|
|
28
|
+
#-----------------------------------------------------------------------
|
29
|
+
# BaseColumn.create_table
|
30
|
+
#-----------------------------------------------------------------------
|
18
31
|
def self.create(tbl_class, name, col_def)
|
19
32
|
return new(tbl_class, name, col_def)
|
20
33
|
end
|
21
34
|
|
35
|
+
#-----------------------------------------------------------------------
|
36
|
+
# initialize
|
37
|
+
#-----------------------------------------------------------------------
|
22
38
|
def initialize(tbl_class, name, col_def)
|
23
39
|
@tbl_class = tbl_class
|
24
40
|
@name = name
|
@@ -27,17 +43,47 @@ class BaseColumn
|
|
27
43
|
@required = false
|
28
44
|
end
|
29
45
|
|
46
|
+
#-----------------------------------------------------------------------
|
47
|
+
# indexed?
|
48
|
+
#-----------------------------------------------------------------------
|
30
49
|
def indexed?
|
31
50
|
@indexed
|
32
51
|
end
|
33
52
|
|
53
|
+
#-----------------------------------------------------------------------
|
54
|
+
# required?
|
55
|
+
#-----------------------------------------------------------------------
|
34
56
|
def required?
|
35
57
|
@required
|
36
58
|
end
|
37
59
|
|
60
|
+
#-----------------------------------------------------------------------
|
61
|
+
# close
|
62
|
+
#-----------------------------------------------------------------------
|
38
63
|
def close
|
39
64
|
end
|
40
65
|
|
66
|
+
#-----------------------------------------------------------------------
|
67
|
+
# convert_to_native
|
68
|
+
#-----------------------------------------------------------------------
|
69
|
+
def convert_to_native(value)
|
70
|
+
case @data_type
|
71
|
+
when :string
|
72
|
+
value.to_s
|
73
|
+
when :integer
|
74
|
+
value.to_i
|
75
|
+
when :float
|
76
|
+
value.to_f
|
77
|
+
when :time
|
78
|
+
Time.parse(value)
|
79
|
+
when :date
|
80
|
+
Date.parse(value)
|
81
|
+
when :datetime
|
82
|
+
DateTime.parse(value)
|
83
|
+
when :boolean
|
84
|
+
true if [true, 'true', 1].include?(value)
|
85
|
+
end
|
86
|
+
end
|
41
87
|
end
|
42
88
|
|
43
89
|
|
@@ -45,38 +91,13 @@ end
|
|
45
91
|
# Column class
|
46
92
|
#-------------------------------------------------------------------------------
|
47
93
|
class Column < BaseColumn
|
94
|
+
#-----------------------------------------------------------------------
|
95
|
+
# initialize
|
96
|
+
#-----------------------------------------------------------------------
|
48
97
|
def initialize(tbl_class, name, col_def)
|
49
98
|
super
|
50
99
|
@idx = LinearSearch.new(self)
|
51
100
|
end
|
52
|
-
|
53
|
-
def >(other)
|
54
|
-
@tbl_class.query << [@idx, :>, other]
|
55
|
-
end
|
56
|
-
|
57
|
-
def >=(other)
|
58
|
-
@tbl_class.query << [@idx, :>=, other]
|
59
|
-
end
|
60
|
-
|
61
|
-
def <(other)
|
62
|
-
@tbl_class.query << [@idx, :<, other]
|
63
|
-
end
|
64
|
-
|
65
|
-
def <=(other)
|
66
|
-
@tbl_class.query << [@idx, :<=, other]
|
67
|
-
end
|
68
|
-
|
69
|
-
def ==(other)
|
70
|
-
@tbl_class.query << [@idx, :==, other]
|
71
|
-
end
|
72
|
-
|
73
|
-
def between(*other)
|
74
|
-
@tbl_class.query << [@idx, :between, other]
|
75
|
-
end
|
76
|
-
|
77
|
-
def one_of(*other)
|
78
|
-
@tbl_class.query << [@idx, :one_of, other]
|
79
|
-
end
|
80
101
|
end
|
81
102
|
|
82
103
|
|
@@ -145,51 +166,31 @@ end
|
|
145
166
|
# SkipListIndexColumn class
|
146
167
|
#-------------------------------------------------------------------------------
|
147
168
|
class SkipListIndexColumn < IndexedColumn
|
169
|
+
#-----------------------------------------------------------------------
|
170
|
+
# initialize
|
171
|
+
#-----------------------------------------------------------------------
|
148
172
|
def initialize(tbl_class, name, col_def)
|
149
173
|
@idx = SkipList.new(self)
|
150
174
|
super
|
151
175
|
end
|
152
176
|
|
177
|
+
#-----------------------------------------------------------------------
|
178
|
+
# clear_index
|
179
|
+
#-----------------------------------------------------------------------
|
153
180
|
def clear_index
|
154
181
|
@idx = SkipList.new(self)
|
155
182
|
end
|
156
183
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
def >=(other)
|
162
|
-
@tbl_class.query << [@idx, :>=, other]
|
163
|
-
end
|
164
|
-
|
165
|
-
def <(other)
|
166
|
-
@tbl_class.query << [@idx, :<, other]
|
167
|
-
end
|
168
|
-
|
169
|
-
def <=(other)
|
170
|
-
@tbl_class.query << [@idx, :<=, other]
|
171
|
-
end
|
172
|
-
|
173
|
-
def ==(other)
|
174
|
-
@tbl_class.query << [@idx, :==, other]
|
175
|
-
end
|
176
|
-
|
177
|
-
def search(other)
|
178
|
-
@tbl_class.query << [@idx, :search, other]
|
179
|
-
end
|
180
|
-
|
181
|
-
def between(*other)
|
182
|
-
@tbl_class.query << [@idx, :between, other]
|
183
|
-
end
|
184
|
-
|
185
|
-
def one_of(*other)
|
186
|
-
@tbl_class.query << [@idx, :one_of, other]
|
187
|
-
end
|
188
|
-
|
184
|
+
#-----------------------------------------------------------------------
|
185
|
+
# rebuild_index_file
|
186
|
+
#-----------------------------------------------------------------------
|
189
187
|
def rebuild_index_file
|
190
188
|
with_index_file('w') { |fptr| fptr.write(Marshal.dump(@idx.dump_to_hash)) }
|
191
189
|
end
|
192
190
|
|
191
|
+
#-----------------------------------------------------------------------
|
192
|
+
# rebuild_index_from_table
|
193
|
+
#-----------------------------------------------------------------------
|
193
194
|
def rebuild_index_from_table
|
194
195
|
clear_index
|
195
196
|
i = @tbl_class.columns.index(self)
|
@@ -199,15 +200,24 @@ class SkipListIndexColumn < IndexedColumn
|
|
199
200
|
end
|
200
201
|
end
|
201
202
|
|
203
|
+
#-----------------------------------------------------------------------
|
204
|
+
# rebuild_index_from_index_file
|
205
|
+
#-----------------------------------------------------------------------
|
202
206
|
def rebuild_index_from_index_file
|
203
207
|
clear_index
|
204
208
|
with_index_file { |fptr| @idx.load_from_hash(Marshal.load(fptr)) }
|
205
209
|
end
|
206
210
|
|
211
|
+
#-----------------------------------------------------------------------
|
212
|
+
# add_index_rec
|
213
|
+
#-----------------------------------------------------------------------
|
207
214
|
def add_index_rec(key, value)
|
208
215
|
@idx.store(key, value)
|
209
216
|
end
|
210
217
|
|
218
|
+
#-----------------------------------------------------------------------
|
219
|
+
# remove_index_rec
|
220
|
+
#-----------------------------------------------------------------------
|
211
221
|
def remove_index_rec(key, value)
|
212
222
|
@idx.remove(key, value)
|
213
223
|
end
|
@@ -218,38 +228,111 @@ end
|
|
218
228
|
# IDColumn class
|
219
229
|
#-------------------------------------------------------------------------------
|
220
230
|
class IDColumn < IndexedColumn
|
221
|
-
|
222
|
-
|
231
|
+
def_delegator(:@idx, :==, :[])
|
223
232
|
def_delegator(:@idx, :[], :[])
|
224
233
|
def_delegator(:@idx, :keys, :keys)
|
225
234
|
|
235
|
+
#-----------------------------------------------------------------------
|
236
|
+
# initialize
|
237
|
+
#-----------------------------------------------------------------------
|
226
238
|
def initialize(tbl_class, name, col_def)
|
227
239
|
@idx = {}
|
228
240
|
super
|
229
241
|
end
|
230
242
|
|
243
|
+
#-----------------------------------------------------------------------
|
244
|
+
# clear_index
|
245
|
+
#-----------------------------------------------------------------------
|
231
246
|
def clear_index
|
232
247
|
@idx = {}
|
233
248
|
end
|
234
249
|
|
250
|
+
#-----------------------------------------------------------------------
|
251
|
+
# >
|
252
|
+
#-----------------------------------------------------------------------
|
253
|
+
def >(other)
|
254
|
+
return @idx.keys.select { |k| k > other }
|
255
|
+
end
|
256
|
+
|
257
|
+
#-----------------------------------------------------------------------
|
258
|
+
# >=
|
259
|
+
#-----------------------------------------------------------------------
|
260
|
+
def >=(other)
|
261
|
+
return @idx.keys.select { |k| k >= other }
|
262
|
+
end
|
263
|
+
|
264
|
+
#-----------------------------------------------------------------------
|
265
|
+
# <
|
266
|
+
#-----------------------------------------------------------------------
|
267
|
+
def <(other)
|
268
|
+
return @idx.keys.select { |k| k < other }
|
269
|
+
end
|
270
|
+
|
271
|
+
#-----------------------------------------------------------------------
|
272
|
+
# <=
|
273
|
+
#-----------------------------------------------------------------------
|
274
|
+
def <=(other)
|
275
|
+
return @idx.keys.select { |k| k <= other }
|
276
|
+
end
|
277
|
+
|
278
|
+
#-----------------------------------------------------------------------
|
279
|
+
# between
|
280
|
+
#-----------------------------------------------------------------------
|
281
|
+
def between(search_start, search_end, start_inclusive=false,
|
282
|
+
end_inclusive=false)
|
283
|
+
return @idx.keys.select do |k|
|
284
|
+
if k == search_start and start_inclusive
|
285
|
+
true
|
286
|
+
elsif k > search_start and k < search_end
|
287
|
+
true
|
288
|
+
elsif k == search_end and end_inclusive
|
289
|
+
true
|
290
|
+
else
|
291
|
+
false
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
#-----------------------------------------------------------------------
|
297
|
+
# one_of
|
298
|
+
#-----------------------------------------------------------------------
|
299
|
+
def one_of(*other)
|
300
|
+
return @idx.keys.select { |k| other.include?(k) }
|
301
|
+
end
|
302
|
+
|
303
|
+
#-----------------------------------------------------------------------
|
304
|
+
# rebuild_index_file
|
305
|
+
#-----------------------------------------------------------------------
|
235
306
|
def rebuild_index_file
|
236
307
|
with_index_file('w') { |fptr| fptr.write(Marshal.dump(@idx)) }
|
237
308
|
end
|
238
309
|
|
310
|
+
#-----------------------------------------------------------------------
|
311
|
+
# rebuild_index_from_table
|
312
|
+
#-----------------------------------------------------------------------
|
239
313
|
def rebuild_index_from_table
|
240
314
|
clear_index
|
241
315
|
@tbl_class.get_all_recs { |rec, fpos| add_index_rec(rec[0], fpos) }
|
242
316
|
end
|
243
317
|
|
318
|
+
#-----------------------------------------------------------------------
|
319
|
+
# rebuild_index_from_index_file
|
320
|
+
#-----------------------------------------------------------------------
|
244
321
|
def rebuild_index_from_index_file
|
245
322
|
clear_index
|
246
323
|
with_index_file { |fptr| @idx = Marshal.load(fptr) }
|
247
324
|
end
|
248
325
|
|
326
|
+
#-----------------------------------------------------------------------
|
327
|
+
# add_index_rec
|
328
|
+
#-----------------------------------------------------------------------
|
249
329
|
def add_index_rec(id, fpos)
|
250
330
|
@idx[id] = fpos
|
251
331
|
end
|
252
332
|
|
333
|
+
#-----------------------------------------------------------------------
|
334
|
+
# remove_index_rec
|
335
|
+
#-----------------------------------------------------------------------
|
253
336
|
def remove_index_rec(id)
|
254
337
|
@idx.delete(id)
|
255
338
|
end
|