KirbyBase 2.5.2 → 2.6
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 +2 -8
- data/changes.txt +15 -0
- data/examples/aaa_try_this_first/kbtest.rb +32 -0
- data/examples/indexes_test/index_test.rb +28 -5
- data/examples/record_class_test/record_class_test2.rb +38 -0
- data/examples/yaml_field_test/yaml_field_test.rb +1 -1
- data/kirbybaserubymanual.html +66 -15
- data/lib/kirbybase.rb +185 -93
- data/test/tc_local_db.rb +1 -1
- data/test/tc_local_table.rb +33 -0
- metadata +111 -108
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= KirbyBase 2.
|
1
|
+
= KirbyBase 2.6
|
2
2
|
|
3
3
|
A small, plain-text, dbms written in Ruby. It can be used either embedded
|
4
4
|
or client/server.
|
@@ -31,12 +31,6 @@ See the examples directory for examples of how to use KirbyBase.
|
|
31
31
|
* images directory - images used in manual.
|
32
32
|
|
33
33
|
|
34
|
-
== Warning
|
35
|
-
|
36
|
-
KirbyBase defines #method_missing for NilClass. This might bite you in the
|
37
|
-
butt if you override NilClass.method_missing yourself.
|
38
|
-
|
39
|
-
|
40
34
|
== Author
|
41
35
|
|
42
36
|
Written in 2005 by Jamey Cribbs <mailto:jcribbs@twmi.rr.com>
|
@@ -66,7 +60,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
66
60
|
Please send any bug reports, suggestions, ideas,
|
67
61
|
improvements, to:
|
68
62
|
|
69
|
-
jcribbs@
|
63
|
+
jcribbs@netpromi.com
|
70
64
|
|
71
65
|
== Home Page
|
72
66
|
|
data/changes.txt
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
2006-06-27:: Version 2.6
|
2
|
+
* Removed NilClass#method_missing. I have replaced it with a new class
|
3
|
+
called KBNilClass. Thanks to a host of people for help on this,
|
4
|
+
including: Assaph Mehr, James Edward Gray II, Matthew Desmarais,
|
5
|
+
Logan Capaldo, Trans, John Carter, Dave Burt and anyone else I missed.
|
6
|
+
* Added conditional require logic so that KirbyBase will use FasterCVS if
|
7
|
+
it is available. Thanks to James Edward Gray II for this.
|
8
|
+
* You can now delay index creation in local mode. Thanks to Nicholas Rahn
|
9
|
+
for this.
|
10
|
+
* Added ability to allow for a custom record class with no kb_create or
|
11
|
+
kb_defaults methods. KirbyBase will return each result record as an
|
12
|
+
instance of the custom record class, and will attempt to set attributes
|
13
|
+
with the same names as the table's field names equal to the values of
|
14
|
+
the table record's fields. Thanks to Hal Fulton for this idea.
|
15
|
+
|
1
16
|
2005-12-30:: Version 2.5.2
|
2
17
|
* Changed the behavior of KBTable#insert method. If user specifies nil
|
3
18
|
for a field value and there is a default value for that field, the
|
@@ -83,6 +83,7 @@ plane_tbl.insert('P-39', 'USA', 'Fighter', nil, nil,
|
|
83
83
|
nil, false)
|
84
84
|
plane_tbl.insert('Zero', 'Japan', 'Fighter', 377, 912,
|
85
85
|
Date.new(1937,5,15), true)
|
86
|
+
plane_tbl.insert('B-25', 'USA', '', 320, 1340, Date.new(1940,4,4), true)
|
86
87
|
|
87
88
|
#--------------------- Update Examples -------------------------------------
|
88
89
|
# Four different ways to update existing data in KirbyBase. In all three
|
@@ -195,6 +196,37 @@ puts plane_tbl.select { |r|
|
|
195
196
|
r.country == plane_tbl.select { |x| x.name == 'Zero' }.first.country
|
196
197
|
}
|
197
198
|
|
199
|
+
#-------------------------- Select Example 11 -------------------------------
|
200
|
+
print_divider('Select Example 11')
|
201
|
+
# Select all planes.
|
202
|
+
plane_tbl.select.each { |r| puts r }
|
203
|
+
|
204
|
+
#-------------------------- Select Example 12 -------------------------------
|
205
|
+
print_divider('Select Example 12')
|
206
|
+
# Select all planes with a speed of nil.
|
207
|
+
|
208
|
+
#**************** Note: This example also demonstrates the change from
|
209
|
+
# nil to kb_nil for KirbyBase's internal representation of a nil value. You
|
210
|
+
# should only encounter this different if you have to check for nil in your
|
211
|
+
# query, as this example does. Other than that, everything else should
|
212
|
+
# be transparent, since KirbyBase converts a kb_nil back into a nil when it
|
213
|
+
# returns a query's result set.
|
214
|
+
#***************
|
215
|
+
plane_tbl.select { |r| r.speed.kb_nil? }.each { |r| puts r }
|
216
|
+
|
217
|
+
#-------------------------- Select Example 13 -------------------------------
|
218
|
+
print_divider('Select Example 13')
|
219
|
+
# Same thing, but in a slightly different way.
|
220
|
+
|
221
|
+
#**************** Note: This example also demonstrates the change from
|
222
|
+
# nil to kb_nil for KirbyBase's internal representation of a nil value. You
|
223
|
+
# should only encounter this different if you have to check for nil in your
|
224
|
+
# query, as this example does. Other than that, everything else should
|
225
|
+
# be transparent, since KirbyBase converts a kb_nil back into a nil when it
|
226
|
+
# returns a query's result set.
|
227
|
+
#***************
|
228
|
+
plane_tbl.select { |r| r.speed == kb_nil }.each { |r| puts r }
|
229
|
+
|
198
230
|
#-------------------------- Misc. Methods Examples -------------------------
|
199
231
|
print_divider('Misc. Methods Examples')
|
200
232
|
puts 'Total # of records in table: %d' % plane_tbl.total_recs
|
@@ -37,18 +37,23 @@ address_book_tbl = db.create_table(:address_book,
|
|
37
37
|
:street_address, :String,
|
38
38
|
:city, :String,
|
39
39
|
:phone, :String,
|
40
|
-
:category, {:DataType=>:String, :Index=>2}
|
40
|
+
:category, {:DataType=>:String, :Index=>2},
|
41
|
+
:age, {:DataType=>:Integer, :Index=>3}
|
41
42
|
)
|
42
43
|
|
43
44
|
# Insert some contact info records.
|
44
45
|
address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave', 'Gotham City',
|
45
|
-
'111-111-1111', 'Super Hero')
|
46
|
+
'111-111-1111', 'Super Hero', 39)
|
46
47
|
address_book_tbl.insert('Bugs', 'Bunny', '1234 Rabbit Hole', 'The Forest',
|
47
|
-
'222-222-2222', 'Cartoon Character')
|
48
|
+
'222-222-2222', 'Cartoon Character', 12)
|
48
49
|
address_book_tbl.insert('George', 'Bush', '1600 Pennsylvania Ave',
|
49
|
-
'Washington', '333-333-3333', 'President')
|
50
|
+
'Washington', '333-333-3333', 'President', 2)
|
50
51
|
address_book_tbl.insert('Silver', 'Surfer', '1234 Galaxy Way',
|
51
|
-
'Any City', '444-444-4444', 'Super Hero')
|
52
|
+
'Any City', '444-444-4444', 'Super Hero', 199)
|
53
|
+
address_book_tbl.insert('John', 'Doe', '1234 Robin Lane', 'Detroit',
|
54
|
+
'999-999-9999', nil, 54)
|
55
|
+
address_book_tbl.insert(nil, 'NoFirstName', 'Nowhere Road', 'Notown',
|
56
|
+
'000-000-0000', 'Nothing', nil)
|
52
57
|
|
53
58
|
# Select all super heros without using the index.
|
54
59
|
address_book_tbl.select { |r| r.category == 'Super Hero' }.each { |r|
|
@@ -68,4 +73,22 @@ address_book_tbl.select_by_firstname_lastname_index { |r|
|
|
68
73
|
r.firstname == 'Bugs' and r.lastname == 'Bunny'
|
69
74
|
}.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
|
70
75
|
|
76
|
+
puts;puts
|
77
|
+
# Select the guy with no first name using the firstname+lastname index.
|
78
|
+
address_book_tbl.select_by_firstname_lastname_index { |r|
|
79
|
+
r.lastname == 'NoFirstName'
|
80
|
+
}.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
|
81
|
+
|
82
|
+
puts;puts
|
83
|
+
# Select the guy with no first name using the firstname+lastname index.
|
84
|
+
# This time we will explicitly say firstname should be nil
|
85
|
+
address_book_tbl.select_by_firstname_lastname_index { |r|
|
86
|
+
r.firstname.nil? and r.lastname == 'NoFirstName'
|
87
|
+
}.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
|
88
|
+
|
89
|
+
puts;puts
|
90
|
+
address_book_tbl.select_by_age_index { |r| r.age > 30 }.each { |r|
|
91
|
+
puts '%s %s %d' % [r.firstname, r.lastname, r.age] }
|
92
|
+
|
93
|
+
puts;puts
|
71
94
|
p address_book_tbl.field_indexes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#Test of returning result set composed of instances of user class. This
|
2
|
+
#example differs from the first in that there is no kb_create method, so
|
3
|
+
#KirbyBase will default to create a new instance of the record's custom
|
4
|
+
#class and setting each instance attribute to each field's value.
|
5
|
+
|
6
|
+
require 'kirbybase'
|
7
|
+
|
8
|
+
class Foobar
|
9
|
+
attr_accessor(:recno, :name, :country, :role, :speed, :range,
|
10
|
+
:began_service, :still_flying)
|
11
|
+
end
|
12
|
+
|
13
|
+
# To run local, single-user, uncomment next line.
|
14
|
+
db = KirbyBase.new
|
15
|
+
|
16
|
+
# If table exists, delete it.
|
17
|
+
db.drop_table(:plane) if db.table_exists?(:plane)
|
18
|
+
|
19
|
+
# Create a table. Notice how you set record_class equal to your class.
|
20
|
+
plane_tbl = db.create_table do |t|
|
21
|
+
t.name = :plane
|
22
|
+
t.field_defs = [:name, :String, :country, :String, :role, :String,
|
23
|
+
:speed, :Integer, :range, :Integer, :began_service, :Date,
|
24
|
+
:still_flying, :Boolean]
|
25
|
+
t.encrypt = false
|
26
|
+
t.record_class = Foobar
|
27
|
+
end
|
28
|
+
|
29
|
+
plane_tbl = db.get_table(:plane)
|
30
|
+
|
31
|
+
# Insert a record.
|
32
|
+
plane_tbl.insert('Spitfire','Great Britain','Fighter',333,454,
|
33
|
+
Date.new(1936, 1, 1),true)
|
34
|
+
|
35
|
+
# Notice how select returns instances of Foobar, even there is no
|
36
|
+
# kb_create method.
|
37
|
+
recs = plane_tbl.select
|
38
|
+
p recs.first
|
@@ -25,7 +25,7 @@ pet_tbl.insert('Kirby', 'dog', Date.new(2002, 06, 01),
|
|
25
25
|
pet_tbl.insert('Mojo', 'cat', Date.new(2000, 04, 01),
|
26
26
|
['cute', 'soft', '6', 12.25])
|
27
27
|
pet_tbl.insert('Goldy', 'fish', Date.new(2004, 10, 10),
|
28
|
-
|
28
|
+
[])
|
29
29
|
|
30
30
|
pet_tbl.select.each { |r|
|
31
31
|
puts '%s %s' % [r.name, r.characteristics[1]]
|
data/kirbybaserubymanual.html
CHANGED
@@ -261,8 +261,8 @@ div.exampleblock-content {
|
|
261
261
|
<div id="header">
|
262
262
|
<h1>KirbyBase Manual (Ruby Version)</h1>
|
263
263
|
<span id="author">Jamey Cribbs</span><br />
|
264
|
-
<span id="email"><tt><<a href="mailto:jcribbs@
|
265
|
-
v2.
|
264
|
+
<span id="email"><tt><<a href="mailto:jcribbs@netpromi.com">jcribbs@netpromi.com</a>></tt></span><br />
|
265
|
+
v2.6 June 2006
|
266
266
|
</div>
|
267
267
|
<div id="preamble">
|
268
268
|
<div class="sectionbody">
|
@@ -270,7 +270,7 @@ v2.5.2 December 2005
|
|
270
270
|
<div class="content">
|
271
271
|
<img src="images/kirby1.jpg" alt="images/kirby1.jpg"/>
|
272
272
|
</div>
|
273
|
-
<div class="image-title">Figure: Kirby pictured here in attack mode.</div>
|
273
|
+
<div class="image-title">Figure: Kirby, pictured here in attack mode.</div>
|
274
274
|
</div>
|
275
275
|
</div>
|
276
276
|
</div>
|
@@ -386,6 +386,11 @@ v2.5.2 December 2005
|
|
386
386
|
<a href="#selects-involving-lookups-or-link-manys">Selects involving Lookups or Link_manys</a>
|
387
387
|
</p>
|
388
388
|
</li>
|
389
|
+
<li>
|
390
|
+
<p>
|
391
|
+
<a href="#a-note-about-nil-values">A note about nil values</a>
|
392
|
+
</p>
|
393
|
+
</li>
|
389
394
|
</ol>
|
390
395
|
</li>
|
391
396
|
<li>
|
@@ -708,9 +713,10 @@ MySQL.</p>
|
|
708
713
|
<div class="sidebarblock">
|
709
714
|
<div class="sidebar-content">
|
710
715
|
<div class="sidebar-title">Drop me a line!</div>
|
711
|
-
<p>If you find a use for KirbyBase, please send an email
|
712
|
-
|
713
|
-
|
716
|
+
<p>If you find a use for KirbyBase, please send me an email telling how you
|
717
|
+
use it, whether it is ok for me to mention your application on the
|
718
|
+
"KirbyBase Applications" webpage, and possibly a link to your application's
|
719
|
+
webpage (if you have one).</p>
|
714
720
|
</div></div>
|
715
721
|
</div>
|
716
722
|
<h2><a id="connecting-to-a-database"></a>Connecting to a database</h2>
|
@@ -750,14 +756,14 @@ a different extension, pass this as an argument, like so:</p>
|
|
750
756
|
memo/blob files, you need to pass the location as an argument, like so:</p>
|
751
757
|
<div class="listingblock">
|
752
758
|
<div class="content">
|
753
|
-
<pre><tt>db = KirbyBase.new(:local, nil, './', '.tbl', './memos')</tt></pre>
|
759
|
+
<pre><tt>db = KirbyBase.new(:local, nil, nil, './', '.tbl', './memos')</tt></pre>
|
754
760
|
</div></div>
|
755
761
|
<p>If you don't want KirbyBase to spend time initially creating all of the
|
756
762
|
indexes for the tables in the database, you can pass true as the
|
757
763
|
delay_index_creation argument:</p>
|
758
764
|
<div class="listingblock">
|
759
765
|
<div class="content">
|
760
|
-
<pre><tt>db = KirbyBase.new(:local, nil, './', '.tbl', './', true)</tt></pre>
|
766
|
+
<pre><tt>db = KirbyBase.new(:local, nil, nil, './', '.tbl', './', true)</tt></pre>
|
761
767
|
</div></div>
|
762
768
|
<p>KirbyBase will skip initial index creation and will create a table's
|
763
769
|
indexes when the table is first referenced.</p>
|
@@ -828,8 +834,12 @@ end</tt></pre>
|
|
828
834
|
<p>You can also specify that you want records of the table to be returned to
|
829
835
|
you as instances of a class. To do this, simply define a class before you
|
830
836
|
call #create_table. This class needs to have an accessor for each fieldname
|
831
|
-
in the table
|
832
|
-
|
837
|
+
in the table.</p>
|
838
|
+
<p>If this class has a class method, called #kb_create, KirbyBase, when
|
839
|
+
creating each record of the result set, will call that method and pass it
|
840
|
+
the field values of the result record. #kb_create will need to handle
|
841
|
+
creating an instance of the record class itself.</p>
|
842
|
+
<p>Here is an example of #kb_create in action:</p>
|
833
843
|
<div class="listingblock">
|
834
844
|
<div class="content">
|
835
845
|
<pre><tt>class Foobar
|
@@ -870,6 +880,8 @@ end</tt></pre>
|
|
870
880
|
Foobar, instead of the default, which is instances of Struct. This also
|
871
881
|
works the other way. You can now specify instances of Foobar as input to
|
872
882
|
the #insert, #update and #set methods. More on those methods below.</p>
|
883
|
+
<p>If the custom record class does not respond to #kb_create, KirbyBase will
|
884
|
+
call the class's #new method instead, passing it all of the field values.</p>
|
873
885
|
<div class="sidebarblock">
|
874
886
|
<div class="sidebar-content">
|
875
887
|
<div class="admonitionblock">
|
@@ -1372,6 +1384,35 @@ result.items.each { |item| puts '%d %d' % [item.item_no, item.qty] }</tt></pre>
|
|
1372
1384
|
<p>Notice how the items attribute in the ResultSet is itself a ResultSet
|
1373
1385
|
containing all of the :order_items records that belong to the selected
|
1374
1386
|
order.</p>
|
1387
|
+
<h3><a id="a-note-about-nil-values"></a>A Note About nil Values</h3>
|
1388
|
+
<p>Beginning in version 2.6 of KirbyBase, nil values are no longer stored as
|
1389
|
+
the singleton instance of NilClass in the database. Now, they are stored
|
1390
|
+
as references to the singleton instance, kb_nil, of KBNilClass. KBNilClass
|
1391
|
+
is as similar to NilClass as possible, but since NilClass cannot
|
1392
|
+
be sub-classed, there are a few minor differences.</p>
|
1393
|
+
<p>However, this should all be transparent to you because KirbyBase converts
|
1394
|
+
kb_nil values to Ruby nil values before returning the results of a query.
|
1395
|
+
The only time you will need to be worried about kb_nil is when you need to
|
1396
|
+
explicitly test for a nil value in a query. For example:</p>
|
1397
|
+
<div class="listingblock">
|
1398
|
+
<div class="content">
|
1399
|
+
<pre><tt>plane_tbl.select {|r| r.speed == kb_nil}</tt></pre>
|
1400
|
+
</div></div>
|
1401
|
+
<p>which is the same as:</p>
|
1402
|
+
<div class="listingblock">
|
1403
|
+
<div class="content">
|
1404
|
+
<pre><tt>plane_tbl.select {|r| r.speed.kb_nil?}</tt></pre>
|
1405
|
+
</div></div>
|
1406
|
+
<p>Notice how it is very similar to how you would test for nil?</p>
|
1407
|
+
<p>The only other difference you will now notice, is if you open up a table in
|
1408
|
+
a text editor. Now, nil values are stored as "kb_nil", instead of being
|
1409
|
+
stored as an empty string (i.e. ""). This has the added advantage that
|
1410
|
+
KirbyBase can now distinguish between empty strings and nil values. In the
|
1411
|
+
past, if you saved an empty string as a field value, the next time you
|
1412
|
+
selected that record, KirbyBase would return that field's value as nil.</p>
|
1413
|
+
<p>The main reason for making this change was to eliminate the need to
|
1414
|
+
override NilClass#method_missing, which was cause for concern for some
|
1415
|
+
users.</p>
|
1375
1416
|
</div>
|
1376
1417
|
<h2><a id="kbresultset"></a>KBResultSet</h2>
|
1377
1418
|
<div class="sectionbody">
|
@@ -1677,6 +1718,14 @@ lines:</p>
|
|
1677
1718
|
<div class="content">
|
1678
1719
|
<pre><tt>result = plane_tbl.pack</tt></pre>
|
1679
1720
|
</div></div>
|
1721
|
+
<div class="admonitionblock">
|
1722
|
+
<table><tr>
|
1723
|
+
<td class="icon">
|
1724
|
+
<img src="./images/important.png" alt="Important" />
|
1725
|
+
</td>
|
1726
|
+
<td class="content">You can only call this method when connect_type==:local.</td>
|
1727
|
+
</tr></table>
|
1728
|
+
</div>
|
1680
1729
|
<div class="sidebarblock">
|
1681
1730
|
<div class="sidebar-content">
|
1682
1731
|
<div class="admonitionblock">
|
@@ -1854,6 +1903,8 @@ than one recno.</p>
|
|
1854
1903
|
KirbyBase will attempt to convert the values in the csv file into their
|
1855
1904
|
corresponding KirbyBase field types, based upon the field types you
|
1856
1905
|
designated when you created the table.</p>
|
1906
|
+
<p>If you have FasterCSV installed KirbyBase will use it instead of CSV from
|
1907
|
+
the standard library.</p>
|
1857
1908
|
<p>Returns an Integer specifying the total number of records imported.</p>
|
1858
1909
|
</div></div>
|
1859
1910
|
<div class="sidebarblock">
|
@@ -2165,10 +2216,10 @@ text-file. Here is an example:</p>
|
|
2165
2216
|
first field in the header is the record counter. It is incremented by
|
2166
2217
|
KirbyBase to create new record numbers when records are inserted.</p>
|
2167
2218
|
<p>The second field in the header is the deleted-records counter. Every time a
|
2168
|
-
line in the file is blanked-out (see "The pack method
|
2169
|
-
incremented. You can use this field in a maintenance script so
|
2170
|
-
table is packed whenever the deleted-records counter reaches, say,
|
2171
|
-
records.</p>
|
2219
|
+
line in the file is blanked-out (see <a href="#pack-method">The pack method</a>), this
|
2220
|
+
number is incremented. You can use this field in a maintenance script so
|
2221
|
+
that the table is packed whenever the deleted-records counter reaches, say,
|
2222
|
+
5,000 records.</p>
|
2172
2223
|
<p>The third field in the header is the record_class field. If you specified a
|
2173
2224
|
class when you created the table, its name will show up here and records
|
2174
2225
|
returned from a #select will be instances of this class. The default is
|
@@ -2266,7 +2317,7 @@ an Array like all of the regular indexes. So selects are even faster.</p>
|
|
2266
2317
|
</div>
|
2267
2318
|
<div id="footer">
|
2268
2319
|
<div id="footer-text">
|
2269
|
-
Last updated
|
2320
|
+
Last updated 26-Jun-2006 14:36:38 EDT
|
2270
2321
|
</div>
|
2271
2322
|
</div>
|
2272
2323
|
</body>
|
data/lib/kirbybase.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'time'
|
3
3
|
require 'drb'
|
4
|
-
require 'csv'
|
5
4
|
require 'fileutils'
|
6
5
|
require 'yaml'
|
6
|
+
|
7
|
+
begin # first choice--for speed
|
8
|
+
require 'faster_csv'
|
9
|
+
rescue LoadError # second choice--slower but standard
|
10
|
+
require 'csv'
|
11
|
+
end
|
7
12
|
|
8
13
|
#
|
9
14
|
# :main:KirbyBase
|
@@ -152,11 +157,32 @@ require 'yaml'
|
|
152
157
|
# field, the default value will no longer override the user specified nil
|
153
158
|
# value. Thanks to Assaph Mehr for suggesting this.
|
154
159
|
#
|
160
|
+
# 2006-06-27:: Version 2.6
|
161
|
+
# * Removed NilClass#method_missing. I have replaced it with a new class
|
162
|
+
# called KBNilClass. Thanks to a host of people for help on this,
|
163
|
+
# including: Assaph Mehr, James Edward Gray II, Matthew Desmarais,
|
164
|
+
# Logan Capaldo, Trans, John Carter, Dave Burt and anyone else I missed.
|
165
|
+
# * Added conditional require logic so that KirbyBase will use FasterCVS if
|
166
|
+
# it is available. Thanks to James Edward Gray II for this.
|
167
|
+
# * You can now delay index creation in local mode. Thanks to Nicholas Rahn
|
168
|
+
# for this.
|
169
|
+
# * Added ability to allow for a custom record class with no kb_create or
|
170
|
+
# kb_defaults methods. KirbyBase will return each result record as an
|
171
|
+
# instance of the custom record class, and will attempt to set attributes
|
172
|
+
# with the same names as the table's field names equal to the values of
|
173
|
+
# the table record's fields. Thanks to Hal Fulton for this idea.
|
155
174
|
#
|
156
175
|
#---------------------------------------------------------------------------
|
157
176
|
# KBTypeConversionsMixin
|
158
177
|
#---------------------------------------------------------------------------
|
159
178
|
module KBTypeConversionsMixin
|
179
|
+
# Constant that will represent a kb_nil in the physical table file.
|
180
|
+
# If you think you might need to write the value 'kb_nil' to a field
|
181
|
+
# yourself, comment out the following line and un-comment the line
|
182
|
+
# below that to use an alternative representation for kb_nil.
|
183
|
+
KB_NIL = 'kb_nil'
|
184
|
+
#KB_NIL = '&kb_nil;'
|
185
|
+
|
160
186
|
# Regular expression used to determine if field needs to be un-encoded.
|
161
187
|
UNENCODE_RE = /&(?:amp|linefeed|carriage_return|substitute|pipe);/
|
162
188
|
|
@@ -170,7 +196,11 @@ module KBTypeConversionsMixin
|
|
170
196
|
# Return value converted from storage string to native field type.
|
171
197
|
#
|
172
198
|
def convert_to_native_type(data_type, s)
|
173
|
-
return
|
199
|
+
return kb_nil if s == KB_NIL
|
200
|
+
|
201
|
+
# I added this line to keep KBTable#import_csv working after I made
|
202
|
+
# the kb_nil changes.
|
203
|
+
return nil if s.nil?
|
174
204
|
|
175
205
|
case data_type
|
176
206
|
when :String
|
@@ -236,6 +266,8 @@ module KBTypeConversionsMixin
|
|
236
266
|
# Return value converted to encoded String object suitable for storage.
|
237
267
|
#
|
238
268
|
def convert_to_encoded_string(data_type, value)
|
269
|
+
return KB_NIL if value.nil?
|
270
|
+
|
239
271
|
case data_type
|
240
272
|
when :YAML
|
241
273
|
y = value.to_yaml
|
@@ -342,7 +374,7 @@ class KirbyBase
|
|
342
374
|
include DRb::DRbUndumped
|
343
375
|
include KBTypeConversionsMixin
|
344
376
|
|
345
|
-
VERSION = "2.
|
377
|
+
VERSION = "2.6"
|
346
378
|
|
347
379
|
attr_reader :engine
|
348
380
|
|
@@ -422,13 +454,9 @@ class KirbyBase
|
|
422
454
|
# happens when the table instance is first created, I go ahead and
|
423
455
|
# create table instances right off the bat.
|
424
456
|
#
|
425
|
-
#
|
426
|
-
#
|
427
|
-
|
428
|
-
# Everything should and does go through the table instances created
|
429
|
-
# on the client-side. You can turn this off by specifying true for
|
430
|
-
# the delay_index_creation argument.
|
431
|
-
if server? and @delay_index_creation
|
457
|
+
# You can delay index creation until the first time the index is
|
458
|
+
# used.
|
459
|
+
if @delay_index_creation
|
432
460
|
else
|
433
461
|
@engine.tables.each do |tbl|
|
434
462
|
@table_hash[tbl] = \
|
@@ -2121,11 +2149,7 @@ class KBTable
|
|
2121
2149
|
|
2122
2150
|
new_recno = @db.engine.insert_record(self, @field_names.zip(
|
2123
2151
|
@field_types).collect do |fn, ft|
|
2124
|
-
|
2125
|
-
''
|
2126
|
-
else
|
2127
|
-
convert_to_encoded_string(ft, input_rec[fn])
|
2128
|
-
end
|
2152
|
+
convert_to_encoded_string(ft, input_rec[fn])
|
2129
2153
|
end)
|
2130
2154
|
|
2131
2155
|
# If there are any associated memo/blob fields, save their values.
|
@@ -2751,7 +2775,9 @@ class KBTable
|
|
2751
2775
|
records_inserted = 0
|
2752
2776
|
tbl_rec = @table_class.new(self)
|
2753
2777
|
|
2754
|
-
|
2778
|
+
# read with FasterCSV if loaded, or the standard CSV otherwise
|
2779
|
+
(defined?(FasterCSV) ? FasterCSV : CSV).foreach(csv_filename
|
2780
|
+
) do |row|
|
2755
2781
|
tbl_rec.populate([nil] + row)
|
2756
2782
|
insert(tbl_rec)
|
2757
2783
|
records_inserted += 1
|
@@ -2923,12 +2949,12 @@ class KBTable
|
|
2923
2949
|
|
2924
2950
|
get_meth_upd_res_str = <<-END_OF_STRING
|
2925
2951
|
def #{field_name}_upd_res
|
2926
|
-
return
|
2952
|
+
return kb_nil
|
2927
2953
|
end
|
2928
2954
|
END_OF_STRING
|
2929
2955
|
set_meth_str = <<-END_OF_STRING
|
2930
2956
|
def #{field_name}=(s)
|
2931
|
-
@#{field_name} =
|
2957
|
+
@#{field_name} = kb_nil
|
2932
2958
|
end
|
2933
2959
|
END_OF_STRING
|
2934
2960
|
end
|
@@ -2944,12 +2970,12 @@ class KBTable
|
|
2944
2970
|
END_OF_STRING
|
2945
2971
|
get_meth_upd_res_str = <<-END_OF_STRING
|
2946
2972
|
def #{field_name}_upd_res()
|
2947
|
-
return
|
2973
|
+
return kb_nil
|
2948
2974
|
end
|
2949
2975
|
END_OF_STRING
|
2950
2976
|
set_meth_str = <<-END_OF_STRING
|
2951
2977
|
def #{field_name}=(s)
|
2952
|
-
@#{field_name} =
|
2978
|
+
@#{field_name} = kb_nil
|
2953
2979
|
end
|
2954
2980
|
END_OF_STRING
|
2955
2981
|
end
|
@@ -3081,9 +3107,17 @@ class KBTable
|
|
3081
3107
|
# Read header record and update instance variables.
|
3082
3108
|
#
|
3083
3109
|
def update_header_vars
|
3084
|
-
@encrypted, @last_rec_no, @del_ctr, @record_class, @
|
3085
|
-
@
|
3086
|
-
@
|
3110
|
+
@encrypted, @last_rec_no, @del_ctr, @record_class, @col_names, \
|
3111
|
+
@col_types, @col_indexes, @col_defaults, @col_requireds, \
|
3112
|
+
@col_extras = @db.engine.get_header_vars(self)
|
3113
|
+
|
3114
|
+
# These are deprecated.
|
3115
|
+
@field_names = @col_names
|
3116
|
+
@field_types = @col_types
|
3117
|
+
@field_indexes = @col_indexes
|
3118
|
+
@field_defaults = @col_defaults
|
3119
|
+
@field_requireds = @col_requireds
|
3120
|
+
@field_extras = @col_extras
|
3087
3121
|
end
|
3088
3122
|
|
3089
3123
|
#-----------------------------------------------------------------------
|
@@ -3118,30 +3152,51 @@ class KBTable
|
|
3118
3152
|
result_rec = result_struct.new(*filter.collect { |f|
|
3119
3153
|
tbl_rec.send("#{f}_upd_res".to_sym) })
|
3120
3154
|
elsif @record_class == 'Struct'
|
3121
|
-
result_rec = result_struct.new(*filter.collect
|
3122
|
-
|
3155
|
+
result_rec = result_struct.new(*filter.collect do |f|
|
3156
|
+
if tbl_rec.send(f).kb_nil?
|
3157
|
+
nil
|
3158
|
+
else
|
3159
|
+
tbl_rec.send(f)
|
3160
|
+
end
|
3161
|
+
end)
|
3123
3162
|
else
|
3124
3163
|
if Object.full_const_get(@record_class).respond_to?(:kb_create)
|
3125
3164
|
result_rec = Object.full_const_get(@record_class
|
3126
|
-
).kb_create(*@field_names.collect
|
3127
|
-
|
3128
|
-
|
3129
|
-
|
3130
|
-
|
3131
|
-
|
3132
|
-
|
3133
|
-
|
3134
|
-
|
3135
|
-
|
3136
|
-
|
3165
|
+
).kb_create(*@field_names.collect do |f|
|
3166
|
+
# Just a warning here: If you specify a filter on
|
3167
|
+
# a select, you are only going to get those fields
|
3168
|
+
# you specified in the result set, EVEN IF
|
3169
|
+
# record_class is a custom class instead of Struct.
|
3170
|
+
if filter.include?(f)
|
3171
|
+
if tbl_rec.send(f).kb_nil?
|
3172
|
+
nil
|
3173
|
+
else
|
3174
|
+
tbl_rec.send(f)
|
3175
|
+
end
|
3176
|
+
else
|
3177
|
+
nil
|
3178
|
+
end
|
3179
|
+
end)
|
3137
3180
|
elsif Object.full_const_get(@record_class).respond_to?(
|
3138
3181
|
:kb_defaults)
|
3139
3182
|
result_rec = Object.full_const_get(@record_class).new(
|
3140
|
-
*@field_names.collect
|
3141
|
-
|
3142
|
-
|
3143
|
-
|
3144
|
-
|
3183
|
+
*@field_names.collect do |f|
|
3184
|
+
if tbl_rec.send(f).kb_nil?
|
3185
|
+
nil
|
3186
|
+
else
|
3187
|
+
tbl_rec.send(f) || Object.full_const_get(
|
3188
|
+
@record_class).kb_defaults[@field_names.index(f)]
|
3189
|
+
end
|
3190
|
+
end)
|
3191
|
+
else
|
3192
|
+
result_rec = Object.full_const_get(@record_class).allocate
|
3193
|
+
@field_names.each do |fn|
|
3194
|
+
if tbl_rec.send(fn).kb_nil?
|
3195
|
+
result_rec.send("#{fn}=", nil)
|
3196
|
+
else
|
3197
|
+
result_rec.send("#{fn}=", tbl_rec.send(fn))
|
3198
|
+
end
|
3199
|
+
end
|
3145
3200
|
end
|
3146
3201
|
end
|
3147
3202
|
|
@@ -3413,30 +3468,12 @@ class KBIndex
|
|
3413
3468
|
# Split the line up into fields.
|
3414
3469
|
rec = line.split('|', @col_poss.max+2)
|
3415
3470
|
|
3416
|
-
|
3417
|
-
# that make up this index and converting them to their
|
3418
|
-
# native types.
|
3419
|
-
idx_rec = []
|
3420
|
-
@col_poss.zip(@col_types).each do |col_pos, col_type|
|
3421
|
-
idx_rec << convert_to_native_type(col_type,
|
3422
|
-
rec[col_pos])
|
3423
|
-
end
|
3424
|
-
|
3425
|
-
# Were all the index fields for this record equal to NULL?
|
3426
|
-
# Then don't add this index record to index array; skip to
|
3427
|
-
# next record.
|
3428
|
-
next if idx_rec.compact.empty?
|
3429
|
-
|
3430
|
-
# Add recno to the end of this index record.
|
3431
|
-
idx_rec << rec.first.to_i
|
3432
|
-
|
3433
|
-
# Add index record to index array.
|
3434
|
-
@idx_arr << idx_rec
|
3471
|
+
append_new_rec_to_index_array(rec)
|
3435
3472
|
end
|
3436
3473
|
# Here's how we break out of the loop...
|
3437
3474
|
rescue EOFError
|
3438
3475
|
end
|
3439
|
-
|
3476
|
+
|
3440
3477
|
@last_update = Time.new
|
3441
3478
|
end
|
3442
3479
|
|
@@ -3444,11 +3481,7 @@ class KBIndex
|
|
3444
3481
|
# add_index_rec
|
3445
3482
|
#-----------------------------------------------------------------------
|
3446
3483
|
def add_index_rec(rec)
|
3447
|
-
@
|
3448
|
-
convert_to_native_type(col_type, rec[col_pos])
|
3449
|
-
end + [rec.first.to_i]
|
3450
|
-
|
3451
|
-
@last_update = Time.new
|
3484
|
+
@last_upddate = Time.new if append_new_rec_to_index_array(rec)
|
3452
3485
|
end
|
3453
3486
|
|
3454
3487
|
#-----------------------------------------------------------------------
|
@@ -3467,6 +3500,22 @@ class KBIndex
|
|
3467
3500
|
delete_index_rec(rec.first.to_i)
|
3468
3501
|
add_index_rec(rec)
|
3469
3502
|
end
|
3503
|
+
|
3504
|
+
#-----------------------------------------------------------------------
|
3505
|
+
# append_new_rec_to_index_array
|
3506
|
+
#-----------------------------------------------------------------------
|
3507
|
+
def append_new_rec_to_index_array(rec)
|
3508
|
+
idx_rec = []
|
3509
|
+
@col_poss.zip(@col_types).each do |col_pos, col_type|
|
3510
|
+
idx_rec << convert_to_native_type(col_type, rec[col_pos])
|
3511
|
+
end
|
3512
|
+
|
3513
|
+
return false if idx_rec.uniq == [kb_nil]
|
3514
|
+
|
3515
|
+
idx_rec << rec.first.to_i
|
3516
|
+
@idx_arr << idx_rec
|
3517
|
+
return true
|
3518
|
+
end
|
3470
3519
|
end
|
3471
3520
|
|
3472
3521
|
|
@@ -3573,7 +3622,7 @@ class KBTableRec
|
|
3573
3622
|
|
3574
3623
|
def clear
|
3575
3624
|
@tbl.field_names.each do |fn|
|
3576
|
-
send("#{fn}=",
|
3625
|
+
send("#{fn}=", kb_nil)
|
3577
3626
|
end
|
3578
3627
|
end
|
3579
3628
|
end
|
@@ -3680,6 +3729,7 @@ class KBResultSet < Array
|
|
3680
3729
|
y << b_value
|
3681
3730
|
end
|
3682
3731
|
end
|
3732
|
+
|
3683
3733
|
x <=> y
|
3684
3734
|
}
|
3685
3735
|
end
|
@@ -3737,6 +3787,70 @@ class KBResultSet < Array
|
|
3737
3787
|
end
|
3738
3788
|
|
3739
3789
|
|
3790
|
+
#---------------------------------------------------------------------------
|
3791
|
+
# KBNilClass
|
3792
|
+
#---------------------------------------------------------------------------
|
3793
|
+
class KBNilClass
|
3794
|
+
include Comparable
|
3795
|
+
|
3796
|
+
class << self
|
3797
|
+
def new
|
3798
|
+
@kb_nil ||= KBNilClass.allocate
|
3799
|
+
end
|
3800
|
+
end
|
3801
|
+
|
3802
|
+
def inspect
|
3803
|
+
'kb_nil'
|
3804
|
+
end
|
3805
|
+
|
3806
|
+
def kb_nil?
|
3807
|
+
true
|
3808
|
+
end
|
3809
|
+
|
3810
|
+
def to_s
|
3811
|
+
""
|
3812
|
+
end
|
3813
|
+
|
3814
|
+
def to_i
|
3815
|
+
0
|
3816
|
+
end
|
3817
|
+
|
3818
|
+
def to_f
|
3819
|
+
0.0
|
3820
|
+
end
|
3821
|
+
|
3822
|
+
def to_a
|
3823
|
+
[]
|
3824
|
+
end
|
3825
|
+
|
3826
|
+
def <=>(other)
|
3827
|
+
return 0 if other.kb_nil?
|
3828
|
+
return -1
|
3829
|
+
end
|
3830
|
+
|
3831
|
+
def coerce(other)
|
3832
|
+
return [other, to_i] if other.kind_of? Fixnum
|
3833
|
+
return [other, to_f] if other.kind_of? Float
|
3834
|
+
|
3835
|
+
raise "Didn't know how to coerce kb_nil to a #{other.class}"
|
3836
|
+
end
|
3837
|
+
|
3838
|
+
def method_missing(sym, *args)
|
3839
|
+
kb_nil
|
3840
|
+
end
|
3841
|
+
end
|
3842
|
+
|
3843
|
+
|
3844
|
+
#---------------------------------------------------------------------------
|
3845
|
+
# Kernel
|
3846
|
+
#---------------------------------------------------------------------------
|
3847
|
+
module Kernel
|
3848
|
+
def kb_nil
|
3849
|
+
KBNilClass.new
|
3850
|
+
end
|
3851
|
+
end
|
3852
|
+
|
3853
|
+
|
3740
3854
|
#---------------------------------------------------------------------------
|
3741
3855
|
# Object
|
3742
3856
|
#---------------------------------------------------------------------------
|
@@ -3747,33 +3861,9 @@ class Object
|
|
3747
3861
|
list.each {|x| obj = obj.const_get(x) }
|
3748
3862
|
obj
|
3749
3863
|
end
|
3750
|
-
end
|
3751
3864
|
|
3752
|
-
|
3753
|
-
|
3754
|
-
# NilClass
|
3755
|
-
#---------------------------------------------------------------------------
|
3756
|
-
class NilClass
|
3757
|
-
#-----------------------------------------------------------------------
|
3758
|
-
# method_missing
|
3759
|
-
#-----------------------------------------------------------------------
|
3760
|
-
#
|
3761
|
-
# This code is necessary because if, inside a select condition code
|
3762
|
-
# block, there is a case where you are trying to do an expression
|
3763
|
-
# against a table field that is equal to nil, I don't want a method
|
3764
|
-
# missing exception to occur. I just want the expression to be nil. I
|
3765
|
-
# initially had this method returning false, but then I had an issue
|
3766
|
-
# where I had a YAML field that was supposed to hold an Array. If the
|
3767
|
-
# field was empty (i.e. nil) it was actually returning false when it
|
3768
|
-
# should be returning nil. Since nil evaluates to false, it works if I
|
3769
|
-
# return nil.
|
3770
|
-
# Here's an example:
|
3771
|
-
# #select { |r| r.speed > 300 }
|
3772
|
-
# What happens if speed is nil (basically NULL in DBMS terms)? Without
|
3773
|
-
# this code, an exception is going to be raised, which is not what we
|
3774
|
-
# really want. We really want this expression to return nil.
|
3775
|
-
def method_missing(method_id, *stuff)
|
3776
|
-
return nil
|
3865
|
+
def kb_nil?
|
3866
|
+
false
|
3777
3867
|
end
|
3778
3868
|
end
|
3779
3869
|
|
@@ -3802,3 +3892,5 @@ class Symbol
|
|
3802
3892
|
("+"+self.to_s).to_sym
|
3803
3893
|
end
|
3804
3894
|
end
|
3895
|
+
|
3896
|
+
|
data/test/tc_local_db.rb
CHANGED
data/test/tc_local_table.rb
CHANGED
@@ -766,5 +766,38 @@ class TestTableLocal < Test::Unit::TestCase
|
|
766
766
|
tbl.update(:one => ['two', 3]) { |r| r.recno == 1 }
|
767
767
|
assert_equal(['two', 3], tbl[1].one)
|
768
768
|
end
|
769
|
+
|
770
|
+
def test_nil_values_001
|
771
|
+
tbl = @db.create_table(:nil_tests, :nil_value, :Integer,
|
772
|
+
:conditional, :Integer)
|
773
|
+
tbl.insert(nil, 100)
|
774
|
+
|
775
|
+
recs = []
|
776
|
+
|
777
|
+
assert_nothing_raised {rec = tbl.select {|r| r.nil_value > 100}}
|
778
|
+
assert_equal 0, recs.length
|
779
|
+
|
780
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value > 100 and
|
781
|
+
r.conditional > 100}}
|
782
|
+
assert_equal 0, recs.length
|
783
|
+
|
784
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value > 100 or
|
785
|
+
r.conditional > 100}}
|
786
|
+
assert_equal 0, recs.length
|
787
|
+
|
788
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value > 100 and
|
789
|
+
r.conditional == 100}}
|
790
|
+
assert_equal 0, recs.length
|
791
|
+
|
792
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value > 100 or
|
793
|
+
r.conditional == 100}}
|
794
|
+
assert_equal 1, recs.length
|
795
|
+
|
796
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value.kb_nil?}}
|
797
|
+
assert_equal 1, recs.length
|
798
|
+
|
799
|
+
assert_nothing_raised {recs = tbl.select {|r| r.nil_value == kb_nil}}
|
800
|
+
assert_equal 1, recs.length
|
801
|
+
end
|
769
802
|
end
|
770
803
|
|
metadata
CHANGED
@@ -1,131 +1,134 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.11
|
3
3
|
specification_version: 1
|
4
4
|
name: KirbyBase
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 2.
|
7
|
-
date: 2006-
|
8
|
-
summary:
|
9
|
-
system."
|
6
|
+
version: "2.6"
|
7
|
+
date: 2006-06-27 00:00:00 -04:00
|
8
|
+
summary: KirbyBase is a simple, pure-Ruby, plain-text, flat-file database management system.
|
10
9
|
require_paths:
|
11
|
-
|
12
|
-
email: jcribbs@
|
10
|
+
- lib
|
11
|
+
email: jcribbs@netpromi.com
|
13
12
|
homepage: http://www.netpromi.com/kirbybase_ruby.html
|
14
13
|
rubyforge_project: kirbybase
|
15
|
-
description:
|
16
|
-
databases. You can use it in either a single-user or client-server mode. You can
|
17
|
-
select records for retrieval/updating using code blocks."
|
14
|
+
description: KirbyBase is a class that allows you to create and manipulate simple, plain-text databases. You can use it in either a single-user or client-server mode. You can select records for retrieval/updating using code blocks.
|
18
15
|
autorequire: kirbybase
|
19
16
|
default_executable:
|
20
17
|
bindir: bin
|
21
18
|
has_rdoc: true
|
22
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
23
20
|
requirements:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
version: 0.0.0
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
28
24
|
version:
|
29
25
|
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
30
28
|
authors:
|
31
|
-
|
29
|
+
- Jamey Cribbs
|
32
30
|
files:
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
31
|
+
- lib/kirbybase.rb
|
32
|
+
- bin/kbserver.rb
|
33
|
+
- README
|
34
|
+
- changes.txt
|
35
|
+
- kirbybaserubymanual.html
|
36
|
+
- test/base_test.rb
|
37
|
+
- test/tc_local_db.rb
|
38
|
+
- test/tc_local_table.rb
|
39
|
+
- test/ts_local.rb
|
40
|
+
- examples/aaa_try_this_first
|
41
|
+
- examples/add_column_test
|
42
|
+
- examples/calculated_field_test
|
43
|
+
- examples/change_column_type_test
|
44
|
+
- examples/column_required_test
|
45
|
+
- examples/crosstab_test
|
46
|
+
- examples/csv_import_test
|
47
|
+
- examples/default_value_test
|
48
|
+
- examples/drop_column_test
|
49
|
+
- examples/indexes_test
|
50
|
+
- examples/kbserver_as_win32_service
|
51
|
+
- examples/link_many_test
|
52
|
+
- examples/lookup_field_test
|
53
|
+
- examples/many_to_many_test
|
54
|
+
- examples/memo_test
|
55
|
+
- examples/record_class_test
|
56
|
+
- examples/rename_column_test
|
57
|
+
- examples/rename_table_test
|
58
|
+
- examples/yaml_field_test
|
59
|
+
- examples/aaa_try_this_first/kbtest.rb
|
60
|
+
- examples/add_column_test/add_column_test.rb
|
61
|
+
- examples/calculated_field_test/calculated_field_test.rb
|
62
|
+
- examples/change_column_type_test/change_column_type_test.rb
|
63
|
+
- examples/column_required_test/column_required_test.rb
|
64
|
+
- examples/crosstab_test/crosstab_test.rb
|
65
|
+
- examples/csv_import_test/csv_import_test.rb
|
66
|
+
- examples/csv_import_test/plane.csv
|
67
|
+
- examples/default_value_test/default_value_test.rb
|
68
|
+
- examples/drop_column_test/drop_column_test.rb
|
69
|
+
- examples/indexes_test/add_index_test.rb
|
70
|
+
- examples/indexes_test/drop_index_test.rb
|
71
|
+
- examples/indexes_test/index_test.rb
|
72
|
+
- examples/kbserver_as_win32_service/kbserverctl.rb
|
73
|
+
- examples/kbserver_as_win32_service/kbserver_daemon.rb
|
74
|
+
- examples/link_many_test/link_many_test.rb
|
75
|
+
- examples/lookup_field_test/lookup_field_test.rb
|
76
|
+
- examples/lookup_field_test/lookup_field_test_2.rb
|
77
|
+
- examples/lookup_field_test/the_hal_fulton_feature_test.rb
|
78
|
+
- examples/many_to_many_test/many_to_many_test.rb
|
79
|
+
- examples/memo_test/memos
|
80
|
+
- examples/memo_test/memo_test.rb
|
81
|
+
- examples/memo_test/memos/blank.txt
|
82
|
+
- examples/record_class_test/record_class_test.rb
|
83
|
+
- examples/record_class_test/record_class_test2.rb
|
84
|
+
- examples/rename_column_test/rename_column_test.rb
|
85
|
+
- examples/rename_table_test/rename_table_test.rb
|
86
|
+
- examples/yaml_field_test/yaml_field_test.rb
|
87
|
+
- images/blank.png
|
88
|
+
- images/callouts
|
89
|
+
- images/caution.png
|
90
|
+
- images/client_server.png
|
91
|
+
- images/example.png
|
92
|
+
- images/home.png
|
93
|
+
- images/important.png
|
94
|
+
- images/kirby1.jpg
|
95
|
+
- images/next.png
|
96
|
+
- images/note.png
|
97
|
+
- images/prev.png
|
98
|
+
- images/single_user.png
|
99
|
+
- images/smallnew.png
|
100
|
+
- images/tip.png
|
101
|
+
- images/toc-blank.png
|
102
|
+
- images/toc-minus.png
|
103
|
+
- images/toc-plus.png
|
104
|
+
- images/up.png
|
105
|
+
- images/warning.png
|
106
|
+
- images/callouts/1.png
|
107
|
+
- images/callouts/10.png
|
108
|
+
- images/callouts/11.png
|
109
|
+
- images/callouts/12.png
|
110
|
+
- images/callouts/13.png
|
111
|
+
- images/callouts/14.png
|
112
|
+
- images/callouts/15.png
|
113
|
+
- images/callouts/2.png
|
114
|
+
- images/callouts/3.png
|
115
|
+
- images/callouts/4.png
|
116
|
+
- images/callouts/5.png
|
117
|
+
- images/callouts/6.png
|
118
|
+
- images/callouts/7.png
|
119
|
+
- images/callouts/8.png
|
120
|
+
- images/callouts/9.png
|
122
121
|
test_files:
|
123
|
-
|
122
|
+
- test/ts_local.rb
|
124
123
|
rdoc_options: []
|
124
|
+
|
125
125
|
extra_rdoc_files: []
|
126
|
+
|
126
127
|
executables:
|
127
|
-
|
128
|
+
- kbserver.rb
|
128
129
|
extensions: []
|
130
|
+
|
129
131
|
requirements:
|
130
|
-
|
131
|
-
dependencies: []
|
132
|
+
- none
|
133
|
+
dependencies: []
|
134
|
+
|