KirbyBase 2.5

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