KirbyBase 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.
Files changed (65) hide show
  1. data/README +73 -0
  2. data/bin/kbserver.rb +20 -0
  3. data/changes.txt +105 -0
  4. data/examples/aaa_try_this_first/kbtest.rb +207 -0
  5. data/examples/add_column_test/add_column_test.rb +27 -0
  6. data/examples/calculated_field_test/calculated_field_test.rb +51 -0
  7. data/examples/change_column_type_test/change_column_type_test.rb +25 -0
  8. data/examples/column_required_test/column_required_test.rb +33 -0
  9. data/examples/crosstab_test/crosstab_test.rb +100 -0
  10. data/examples/csv_import_test/csv_import_test.rb +31 -0
  11. data/examples/csv_import_test/plane.csv +11 -0
  12. data/examples/default_value_test/default_value_test.rb +43 -0
  13. data/examples/drop_column_test/drop_column_test.rb +24 -0
  14. data/examples/indexes_test/add_index_test.rb +46 -0
  15. data/examples/indexes_test/drop_index_test.rb +66 -0
  16. data/examples/indexes_test/index_test.rb +71 -0
  17. data/examples/kbserver_as_win32_service/kbserver_daemon.rb +47 -0
  18. data/examples/kbserver_as_win32_service/kbserverctl.rb +75 -0
  19. data/examples/link_many_test/link_many_test.rb +70 -0
  20. data/examples/lookup_field_test/lookup_field_test.rb +55 -0
  21. data/examples/lookup_field_test/lookup_field_test_2.rb +62 -0
  22. data/examples/lookup_field_test/the_hal_fulton_feature_test.rb +69 -0
  23. data/examples/many_to_many_test/many_to_many_test.rb +65 -0
  24. data/examples/memo_test/memo_test.rb +63 -0
  25. data/examples/memo_test/memos/blank.txt +0 -0
  26. data/examples/record_class_test/record_class_test.rb +77 -0
  27. data/examples/rename_column_test/rename_column_test.rb +46 -0
  28. data/examples/rename_table_test/rename_table_test.rb +38 -0
  29. data/examples/yaml_field_test/yaml_field_test.rb +47 -0
  30. data/images/blank.png +0 -0
  31. data/images/callouts/1.png +0 -0
  32. data/images/callouts/10.png +0 -0
  33. data/images/callouts/11.png +0 -0
  34. data/images/callouts/12.png +0 -0
  35. data/images/callouts/13.png +0 -0
  36. data/images/callouts/14.png +0 -0
  37. data/images/callouts/15.png +0 -0
  38. data/images/callouts/2.png +0 -0
  39. data/images/callouts/3.png +0 -0
  40. data/images/callouts/4.png +0 -0
  41. data/images/callouts/5.png +0 -0
  42. data/images/callouts/6.png +0 -0
  43. data/images/callouts/7.png +0 -0
  44. data/images/callouts/8.png +0 -0
  45. data/images/callouts/9.png +0 -0
  46. data/images/caution.png +0 -0
  47. data/images/client_server.png +0 -0
  48. data/images/example.png +0 -0
  49. data/images/home.png +0 -0
  50. data/images/important.png +0 -0
  51. data/images/kirby1.jpg +0 -0
  52. data/images/next.png +0 -0
  53. data/images/note.png +0 -0
  54. data/images/prev.png +0 -0
  55. data/images/single_user.png +0 -0
  56. data/images/smallnew.png +0 -0
  57. data/images/tip.png +0 -0
  58. data/images/toc-blank.png +0 -0
  59. data/images/toc-minus.png +0 -0
  60. data/images/toc-plus.png +0 -0
  61. data/images/up.png +0 -0
  62. data/images/warning.png +0 -0
  63. data/kirbybaserubymanual.html +2243 -0
  64. data/lib/kirbybase.rb +3662 -0
  65. metadata +126 -0
data/README ADDED
@@ -0,0 +1,73 @@
1
+ = KirbyBase 2.5
2
+
3
+ A small, plain-text, dbms written in Ruby. It can be used either embedded
4
+ or client/server.
5
+
6
+
7
+ == Installation
8
+
9
+ Unpack the file you downloaded. Execute "ruby install.rb" or simply make
10
+ sure kirbybase.rb is somewhere in your Ruby library path.
11
+
12
+
13
+ == Documentation
14
+
15
+ Documentation is in kirbybaserubymanual.html. Also, RDoc generated
16
+ documentation is in the doc directory.
17
+
18
+ See the examples directory for examples of how to use KirbyBase.
19
+
20
+
21
+ == Manifest
22
+
23
+ * README - this file
24
+ * install.rb - install script
25
+ * changes.txt - history of changes.
26
+ * kirbybaserubymanual.html - documentation
27
+ * kirbybase.rb - dbms library
28
+ * kbserver.rb - multi-threaded database server script.
29
+ * examples directory - many example scripts demonstrating features.
30
+ * doc directory - RDoc generated documentation in html format.
31
+ * images directory - images used in manual.
32
+
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
+ == Author
41
+
42
+ Written in 2005 by Jamey Cribbs <mailto:jcribbs@twmi.rr.com>
43
+
44
+
45
+ == License
46
+
47
+ KirbyBase is distributed under the same license as Ruby.
48
+
49
+ Copyright (c) 2005 Jamey Cribbs
50
+
51
+
52
+
53
+ == Warranty
54
+
55
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
61
+ IN THE SOFTWARE.
62
+
63
+
64
+ == Feedback
65
+
66
+ Please send any bug reports, suggestions, ideas,
67
+ improvements, to:
68
+
69
+ jcribbs@twmi.rr.com
70
+
71
+ == Home Page
72
+
73
+ http://www.netpromi.com/kirbybase_ruby.html
@@ -0,0 +1,20 @@
1
+ # Multi-user server script for KirbyBase.
2
+
3
+ require 'kirbybase'
4
+ require 'drb'
5
+ require 'benchmark'
6
+ include Benchmark
7
+
8
+ host = ''
9
+ port = 44444
10
+
11
+ puts 'Initializing database server and indexes...'
12
+
13
+ # Create an instance of the database.
14
+ db = KirbyBase.new(:server)
15
+
16
+ DRb.start_service('druby://:44444', db)
17
+
18
+ puts 'Server ready to receive connections...'
19
+
20
+ DRb.thread.join
@@ -0,0 +1,105 @@
1
+ 2005-12-01:: Version 2.5
2
+ * Fixed a subtle bug in KBTable#create_indexes.
3
+ * Added the following new methods to KBTable: add_index, drop_index,
4
+ rename_column, change_column_type, change_column_default_value, and
5
+ change_column_required.
6
+ * Added the ability to specify a default column value at table creation
7
+ time.
8
+ * Added the ability to specify, at table creation time, that a column value
9
+ is required when inserting or updating records.
10
+ * Removed #add_table_column and #drop_table_column from KirbyBase class
11
+ and added #add_column and #drop_column to KBTable class. I felt like
12
+ it made more sense to have these methods in the table's class rather
13
+ than the database's class.
14
+ * Added KirbyBase#rename_table method.
15
+ * Added the ability to, upon database initialization, specify that index
16
+ creation should not happen until a table is actually opened. This
17
+ speeds up database initialization at the cost of slower table
18
+ initialization later.
19
+
20
+ 2005-11-13:: Version 2.4
21
+ * Added a new column type: :Time. Thanks to George Moschovitis for coding
22
+ this enhancement.
23
+ * Added more functionality to Memo and Blob fields. They are no longer
24
+ just read-only. You can now also write to them from KirbyBase. The
25
+ interface for Memo and Blob fields has changed because of this.
26
+ * Added the ability to specify, when you initialize a database connection,
27
+ a base directory where memo/blob fields will be stored.
28
+ * Changed the way indexes are handled by KBTable in client/server mode.
29
+ Now, when KBTable grabs an index from KBEngine, it will hold onto it and
30
+ re-use it unless it has been modified since the last time it grabbed it.
31
+ This speeds up subsequent queries on the same index.
32
+ * Removed the restriction that the child table had to exist before you
33
+ could define a Link_many field in #create_table. I did this so that
34
+ it would possible to now define many-to-many links. See the example in
35
+ the distribution. This also goes for Lookup fields.
36
+ * Added two sample scripts: kbserverctl.rb and kbserver_daemon.rb, that
37
+ show how to set up a KirbyBase server process as a Windows Service.
38
+ Thanks to Daniel Berger for his excellent package, win32-service.
39
+ * Thouroughly revised the manual. I used the excellent text document
40
+ formatter, AsciiDoc. Many thanks to Stuart Rackham for developing this
41
+ great tool.
42
+ * Fixed a bug in KBTable#clear that was causing the recno counter not to
43
+ be reset. Thanks to basi for this.
44
+
45
+ 2005-10-10:: Version 2.3
46
+ * Added ability to specify lookup fields.
47
+ * Added ability to specify one-to-many links between tables.
48
+ * Added ability to specify calculated fields in tables.
49
+ * Added Memo and Blob field types.
50
+ * Added YAML field type. Many thanks to Logan Capaldo for this idea!
51
+ * Added indexing to speed up queries.
52
+ * Two new methods: #add_table_column and #drop_table_column.
53
+ * Added the ability to designate a table field as the "key" field, for
54
+ Lookup purposes. This simply makes it easier to define Lookup fields.
55
+ * Added "crosstab" capabilities to KBResultSet.
56
+
57
+ 2005-08-09:: Version 2.2.1
58
+ * Fixed a bug in with_write_lock. Thanks to Zed A. Shaw for this bugfix.
59
+ * Fixed a bug that occurred if @record_class was a nested class. Thanks
60
+ to Hal Fulton for this bugfix.
61
+
62
+ 2005-05-02:: Version 2.2
63
+ * By far the biggest change in this version is that I have completely
64
+ redesigned the internal structure of the database code. Because the
65
+ KirbyBase and KBTable classes were too tightly coupled, I have created
66
+ a KBEngine class and moved all low-level I/O logic and locking logic
67
+ to this class. This allowed me to restructure the KirbyBase class to
68
+ remove all of the methods that should have been private, but couldn't be
69
+ because of the coupling to KBTable. In addition, it has allowed me to
70
+ take all of the low-level code that should not have been in the KBTable
71
+ class and put it where it belongs, as part of the underlying engine. I
72
+ feel that the design of KirbyBase is much cleaner now. No changes were
73
+ made to the class interfaces, so you should not have to change any of
74
+ your code.
75
+ * Changed str_to_date and str_to_datetime to use Date#parse method.
76
+ Thanks to Emiel van de Laar for this enhancement.
77
+ * Changed #pack method so that it no longer reads the whole file into
78
+ memory while packing it.
79
+ Thanks to Hugh Sasse for reporting this bug.
80
+ * Changed code so that special character sequences like &linefeed; can be
81
+ part of input data and KirbyBase will not interpret it as special
82
+ characters.
83
+ Thanks to Hugh Sasse for this bug fix.
84
+
85
+ 2005-04-11:: Version 2.1
86
+ * Changed the interface to KirbyBase#new and KirbyBase#create_table. You
87
+ now specify arguments via a code block or as part of the argument list.
88
+ * Added the ability to specify a class at table creation time.
89
+ Thereafter, whenever you do a #select, the result set will be an array
90
+ of instances of that class, instead of instances of Struct. You can
91
+ also use instances of this class as the argument to #insert, #update,
92
+ #set.
93
+ * Added the ability to encrypt a table so that it is no longer stored as
94
+ a plain-text file.
95
+ * Added the ability to explicity specify that you want a result set to be
96
+ sorted in ascending order.
97
+ * Added the ability to import a csv file into an existing table.
98
+ * Added the ability to select a record as if the table were a Hash with
99
+ it's key being the recno field.
100
+ * Added the ability to update a record as if the table were a Hash with
101
+ it's key being the recno field.
102
+
103
+ 2005-03-28:: Version 2.0
104
+ * New version with completely new interface. A huge thanks to Hal Fulton
105
+ for all of his help with this new version.
@@ -0,0 +1,207 @@
1
+ #Simple test of KirbyBase.
2
+
3
+ require 'kirbybase'
4
+ require 'date'
5
+
6
+ def print_divider(text)
7
+ puts
8
+ puts text.center(75, '-')
9
+ puts
10
+ end
11
+
12
+ #-------------------- Initialize KirbyBase Instance ------------------------
13
+ # To run local, single-user, uncomment next line.
14
+ db = KirbyBase.new
15
+
16
+ # To run as a client in a multi-user environment, uncomment next line.
17
+ # Also, make sure kbserver.rb is running.
18
+ #db = KirbyBase.new do |d|
19
+ # d.connect_type = :client
20
+ # d.host = 'localhost'
21
+ # d.port = 44444
22
+ #end
23
+
24
+ #----------------------- Drop Table Example --------------------------------
25
+ # If table exists, delete it.
26
+ db.drop_table(:plane) if db.table_exists?(:plane)
27
+
28
+ #----------------------- Create Table Example ------------------------------
29
+ # Create a table.
30
+ plane_tbl = db.create_table(:plane, :name, :String, :country, :String,
31
+ :role, :String, :speed, :Integer, :range, :Integer, :began_service, :Date,
32
+ :still_flying, :Boolean) { |obj| obj.encrypt = false }
33
+
34
+ #----------------------- Insert Record Examples ----------------------------
35
+ # Four different ways to insert records in KirbyBase.
36
+
37
+ # 1) Insert a record using an array for the input values.
38
+ plane_tbl.insert('FW-190', 'Germany', 'Fighter', 399, 499,
39
+ Date.new(1942,12,1), false)
40
+
41
+ # 2) Insert a record using a hash for the input values.
42
+ plane_tbl.insert(:name => 'P-51', :country => 'USA',
43
+ :role => 'Fighter', :speed => 403, :range => 1201,
44
+ :began_service => Date.new(1943,6,24), :still_flying => true)
45
+
46
+ # 3) Insert a record using a Struct for the input values.
47
+ InputRec = Struct.new(:name, :country, :role, :speed, :range,
48
+ :began_service, :still_flying)
49
+ rec = InputRec.new('P-47', 'USA', 'Fighter', 365, 888, Date.new(1943,3,12),
50
+ false)
51
+ plane_tbl.insert(rec)
52
+
53
+ # 4) Insert a record using a code block for the input values.
54
+ plane_tbl.insert { |r|
55
+ r.name = 'B-17'
56
+ r.country = 'USA'
57
+ r.role = 'Bomber'
58
+ r.speed = 315
59
+ r.range = 1400
60
+ r.began_service = Date.new(1937, 5, 1)
61
+ r.still_flying = true
62
+ }
63
+
64
+ # If a table is already existing and you need to get a reference to it so
65
+ # that you can insert, select, etc., just do a get_table.
66
+ plane_tbl_another_reference = db.get_table(:plane)
67
+
68
+ # Then, you can use it just like you have been using the reference you got
69
+ # when you created the table.
70
+ plane_tbl_another_reference.insert('Typhoon', 'Great Britain',
71
+ 'Fighter-Bomber', 389, 690, Date.new(1944,11,20), false)
72
+
73
+ # Insert a bunch more records so we can have some "select" fun below.
74
+ plane_tbl.insert('Spitfire', 'Great Britain', 'Fighter', 345, 540,
75
+ Date.new(1939,2,18), true)
76
+ plane_tbl.insert('Oscar', 'Japan', 'Fighter', 361, 777,
77
+ Date.new(1943,12,31), false)
78
+ plane_tbl.insert('ME-109', 'Germany', 'Fighter', 366, 514,
79
+ Date.new(1936,7,7),true)
80
+ plane_tbl.insert('JU-88', 'Germany', 'Bomber', 289, 999,
81
+ Date.new(1937,1,19), false)
82
+ plane_tbl.insert('P-39', 'USA', 'Fighter', nil, nil,
83
+ nil, false)
84
+ plane_tbl.insert('Zero', 'Japan', 'Fighter', 377, 912,
85
+ Date.new(1937,5,15), true)
86
+
87
+ #--------------------- Update Examples -------------------------------------
88
+ # Four different ways to update existing data in KirbyBase. In all three
89
+ # instances, you still need a code block attached to the update method in
90
+ # order to select records that will be updated.
91
+
92
+ # 1) Update record using a Hash, Struct, or an Array.
93
+ plane_tbl.update(:speed => 405, :range => 1210) { |r| r.name == 'P-51' }
94
+
95
+ # 2) Update record using a code block, via the set command.
96
+ plane_tbl.update {|r| r.name == 'P-51'}.set {|r|
97
+ r.speed = 405
98
+ r.range = 1210
99
+ }
100
+
101
+ # 3) Update record using a Hash, Struct, or an Array, via the set
102
+ # command.
103
+ plane_tbl.update {|r| r.name == 'P-51'}.set(:speed => 405, :range => 1210)
104
+
105
+ # 4) Update record by treating table as if it were a Hash and the keys were
106
+ # recno's.
107
+ plane_tbl[2] = {:speed => 405, :range => 1210}
108
+
109
+ #--------------------- Delete Examples -------------------------------------
110
+ # Delete 'FW-190' record.
111
+ plane_tbl.delete { |r| r.name == 'FW-190' }
112
+
113
+ # Remove deleted records from the table.
114
+ plane_tbl.pack
115
+
116
+ #---------------------- Select Example 0 -----------------------------------
117
+ print_divider('Select Example 0')
118
+ # Select all records, including all fields in result set.
119
+ plane_tbl.select.each { |r|
120
+ puts(('%s ' * r.members.size) % r.to_a)
121
+ }
122
+
123
+ #-------------------------- Select Example 1 -------------------------------
124
+ print_divider('Select Example 1')
125
+ # Select all Japanese planes. Include just name and speed in the result.
126
+ plane_tbl.select(:name, :speed) { |r| r.country == 'Japan' }.each { |r|
127
+ puts '%s %s' % [r.name, r.speed]
128
+ }
129
+
130
+ #-------------------------- Select Example 2 -------------------------------
131
+ print_divider('Select Example 2')
132
+ # Select all US planes with a speed greater than 350mph. Include just name
133
+ # and speed in result set.
134
+ plane_tbl.select(:name, :speed) { |r|
135
+ r.country == 'USA' and r.speed > 350
136
+ }.each { |r| puts '%s %s' % [r.name, r.speed] }
137
+
138
+ #-------------------------- Select Example 3 -------------------------------
139
+ print_divider('Select Example 3')
140
+ # Select all Axis fighters.
141
+ plane_tbl.select { |r|
142
+ (r.country == 'Germany' or r.country == 'Japan') and r.role == 'Fighter'
143
+ }.each { |r| puts r }
144
+
145
+ #-------------------------- Select Example 4 -------------------------------
146
+ print_divider('Select Example 4')
147
+ # Same query as above, but let's use regular expressions instead of an 'or'.
148
+ plane_tbl.select { |r|
149
+ r.country =~ /Germany|Japan/ and r.role == 'Fighter'
150
+ }.each { |r| puts r }
151
+
152
+ #-------------------------- Select Example 5 -------------------------------
153
+ print_divider('Select Example 5')
154
+ # Select all Bombers (but not Fighter-Bombers) and return only their name
155
+ # and country. This is also an example of how to get a reference to an
156
+ # existing table as opposed to already having a reference to one via the
157
+ # table_create method.
158
+ match_role = /^Bomber/
159
+ plane_tbl2 = db.get_table(:plane)
160
+ plane_tbl2.select(:name, :country) { |r| r.role =~ match_role }.each { |r|
161
+ puts '%s %s' % r.to_a
162
+ }
163
+
164
+ #-------------------------- Select Example 6 -------------------------------
165
+ print_divider('Select Example 6')
166
+ # Select all planes. Include just name, country, and speed in result set.
167
+ # Sort result set by country (ascending) then name (ascending).
168
+ plane_tbl.select(:name, :country, :speed).sort(:country,
169
+ :name).each { |r| puts "%s %s %d" % r.to_a }
170
+
171
+ #-------------------------- Select Example 7 -------------------------------
172
+ print_divider('Select Example 7')
173
+ # Select all planes. Include just name, country, and speed in result set.
174
+ # Return result set as a nicely formatted report, sorted by
175
+ # country (ascending) then speed (descending).
176
+ puts plane_tbl.select(:name, :country, :speed).sort(+:country,
177
+ -:speed).to_report
178
+
179
+ #-------------------------- Select Example 8 -------------------------------
180
+ print_divider('Select Example 8')
181
+ # Select planes that are included in nameArray.
182
+ nameArray = ['P-51', 'Spitfire', 'Zero']
183
+ plane_tbl.select { |r| nameArray.include?(r.name) }.each { |r| puts r }
184
+
185
+ #-------------------------- Select Example 9 -------------------------------
186
+ print_divider('Select Example 9')
187
+ # You can select a record as if the table is a hash and it's keys are the
188
+ # recno's.
189
+ # Select the record that has a recno of 5.
190
+ puts plane_tbl[5].name
191
+
192
+ #-------------------------- Select Example 10 -------------------------------
193
+ print_divider('Select Example 10')
194
+ # You can even have a select within the code block of another select. Here
195
+ # we are selecting all records that are from the same country as the Zero.
196
+ puts plane_tbl.select { |r|
197
+ r.country == plane_tbl.select { |x| x.name == 'Zero' }.first.country
198
+ }
199
+
200
+ #-------------------------- Misc. Methods Examples -------------------------
201
+ print_divider('Misc. Methods Examples')
202
+ puts 'Total # of records in table: %d' % plane_tbl.total_recs
203
+ puts
204
+ puts 'Fields for plane.tbl:'
205
+ plane_tbl.field_names.zip(plane_tbl.field_types).each { |r|
206
+ print r[0].to_s.ljust(15), r[1].to_s, "\n"
207
+ }
@@ -0,0 +1,27 @@
1
+ #Test of add_column method.
2
+
3
+ require 'kirbybase'
4
+
5
+ db = KirbyBase.new
6
+
7
+ # If table exists, delete it.
8
+ db.drop_table(:plane) if db.table_exists?(:plane)
9
+
10
+ # Create a table.
11
+ plane_tbl = db.create_table(:plane, :name, :String, :speed, :Integer,
12
+ :service_date, :Date, :still_flying, :Boolean)
13
+
14
+ # Insert a bunch more records so we can have some "select" fun below.
15
+ plane_tbl.insert('Spitfire', 345, Date.new(1939,2,18), true)
16
+ plane_tbl.insert('Oscar', 361, Date.new(1943,12,31), false)
17
+ plane_tbl.insert('ME-109', 366, Date.new(1936,7,7),true)
18
+ plane_tbl.insert('JU-88', 289, Date.new(1937,1,19), false)
19
+ plane_tbl.insert('P-39', nil, nil, false)
20
+ plane_tbl.insert('Zero', 377, Date.new(1937,5,15), true)
21
+
22
+ plane_tbl.add_column(:range, {:DataType=>:Integer, :Index=>1}, :speed)
23
+
24
+ plane_tbl.update { |r| r.name == 'Spitfire' }.set(:range => 454)
25
+
26
+ puts plane_tbl.select_by_range_index { |r| r.range > 400 }.sort(:recno
27
+ ).to_report
@@ -0,0 +1,51 @@
1
+ # This example script shows how to specify calculated fields in a KirbyBase
2
+ # table. Calculated fields are "virtual" fields. They do not really exist
3
+ # in the table, but are calculated during a select query. However, once
4
+ # calculated, they behave just like "real" table fields.
5
+
6
+ # In this example, we will create an expenses table that holds information
7
+ # on recent purchases. The total_cost field is a calculated field. We tell
8
+ # KirbyBase how to calculate it's value, i.e. by multiplying the quantity
9
+ # field by the price field.
10
+
11
+ require 'kirbybase'
12
+ require 'date'
13
+
14
+ db = KirbyBase.new
15
+
16
+ # To run as a client in a multi-user environment, uncomment next line.
17
+ # Also, make sure kbserver.rb is running.
18
+ #db = KirbyBase.new do |d|
19
+ # d.connect_type = :client
20
+ # d.host = 'localhost'
21
+ # d.port = 44444
22
+ #end
23
+
24
+ # If table exists, delete it.
25
+ db.drop_table(:expenses) if db.table_exists?(:expenses)
26
+
27
+ # Create a table.
28
+ expenses_tbl = db.create_table(:expenses,
29
+ :transaction_date, :Date,
30
+ :description, :String,
31
+ :quantity, :Integer,
32
+ :price, :Float,
33
+ :total_cost, {:DataType=>:Float, :Calculated=>'quantity * price'}
34
+ )
35
+
36
+ # Insert a couple of expense records.
37
+ expenses_tbl.insert({:transaction_date => Date.new(2005, 9, 7),
38
+ :description => 'Pencils', :quantity => 100, :price => 0.50})
39
+ expenses_tbl.insert({:transaction_date => Date.new(2005, 9, 8),
40
+ :description => 'Books', :quantity => 3, :price => 45.0})
41
+
42
+ # Select all records and send the result to the screen in report format.
43
+ # Notice how the total_cost field for each record has been calculated for
44
+ # you by multiplying price times quantity.
45
+ puts "\nSelect all records:\n\n"
46
+ puts expenses_tbl.select.to_report
47
+
48
+ # And, you can even use a calculated field in your select condition. Here
49
+ # we are only selecting records whose total cost is greater than $100.
50
+ puts "\n\nSelect only records with a total cost greater than $100:\n\n"
51
+ puts expenses_tbl.select { |r| r.total_cost > 100.00 }.to_report