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
@@ -0,0 +1,25 @@
1
+ # This script is an example of how to change a column type.
2
+ #
3
+ require 'kirbybase'
4
+
5
+ db = KirbyBase.new
6
+
7
+ # If table exists, delete it.
8
+ db.drop_table(:log) if db.table_exists?(:log)
9
+
10
+ log_tbl = db.create_table(:log, :log_timestamp, :DateTime, :msg, :String)
11
+
12
+ log_tbl.insert(DateTime.now, 'This is a log message')
13
+ log_tbl.insert(DateTime.now, 'This is a another log message')
14
+ log_tbl.insert(DateTime.now, 'This is the final log message')
15
+
16
+ p log_tbl.select
17
+ puts;puts
18
+
19
+ log_tbl.change_column_type(:log_timestamp, :String)
20
+
21
+ p log_tbl.select
22
+ puts;puts
23
+
24
+ p log_tbl.field_types
25
+
@@ -0,0 +1,33 @@
1
+ # This script is an example of how to specify that a value is required for a
2
+ # column.
3
+ #
4
+ require 'kirbybase'
5
+
6
+ db = KirbyBase.new
7
+
8
+ # If table exists, delete it.
9
+ db.drop_table(:address_book) if db.table_exists?(:address_book)
10
+
11
+ # Create a table. Notice how we specify a default value for :category.
12
+ address_book_tbl = db.create_table(:address_book,
13
+ :firstname, :String, :lastname, :String, :street_address, :String,
14
+ :city, :String, :phone, :String,
15
+ :category, {:DataType=>:String, :Required=>true})
16
+
17
+ begin
18
+ # Insert a record. Notice that I am passing nil for :category. This
19
+ # will cause KirbyBase to raise an exception.
20
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave',
21
+ 'Gotham City', '111-111-1111', nil)
22
+ rescue StandardError => e
23
+ puts e
24
+ puts;puts
25
+ end
26
+
27
+ # Now, let's turn off the required flag for :category.
28
+ address_book_tbl.change_column_required(:category, false)
29
+
30
+ # And we will attempt to add the record again.
31
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave',
32
+ 'Gotham City', '111-111-1111', nil)
33
+
@@ -0,0 +1,100 @@
1
+ # This script demonstrates how to use crosstab functionality of a
2
+ # KirbyBase result set. A KirbyBase result set automatically has an
3
+ # equivalent transposed array whereby all of the values of a column are
4
+ # available. I call this a crosstab, but I am probably using this term
5
+ # incorrectly. Perhaps the examples below will help explain what I am
6
+ # talking about.
7
+
8
+ # In this example, we have an order table and an order_item table. Each
9
+ # record in the order table represents a customer order. The order_item
10
+ # table holds the detail items for each order. We create a one-to-many link
11
+ # between the order table and the order_item table by providing extra
12
+ # information about the order.items field when we create the order table.
13
+
14
+ require 'kirbybase'
15
+
16
+ db = KirbyBase.new
17
+
18
+ # To run as a client in a multi-user environment, uncomment next line.
19
+ # Also, make sure kbserver.rb is running.
20
+ #db = KirbyBase.new do |d|
21
+ # d.connect_type = :client
22
+ # d.host = 'localhost'
23
+ # d.port = 44444
24
+ #end
25
+
26
+ # If tables exists, delete it.
27
+ db.drop_table(:order) if db.table_exists?(:order)
28
+ db.drop_table(:order_item) if db.table_exists?(:order_item)
29
+
30
+ # Create an order item table. This is the child table to the order table.
31
+ # Make sure you create the child table BEFORE you create the parent table
32
+ # so that KirbyBase can take advantage of any indexes that you have defined.
33
+ order_item_tbl = db.create_table(:order_item,
34
+ :item_id, :Integer,
35
+ :order_id, :Integer,
36
+ :descr, :String,
37
+ :qty, :Integer,
38
+ :price, :Float,
39
+ :total, {:DataType=>:Float, :Calculated=>'qty*price'}
40
+ )
41
+
42
+ # Create an order table. We are telling KirbyBase that the items field is
43
+ # to be linked to the order_item table by comparing the order.order_id
44
+ # field to the order_item.order_id field. By specifying :Link_many, we are
45
+ # telling KirbyBase to make this a one-to-many link. The result of this is
46
+ # that when you do a select, the items field of the order table is going to
47
+ # hold a reference to a ResultSet (i.e. Array) holding all order_item
48
+ # records whose order_id field match the order_id field in the order record.
49
+ order_tbl = db.create_table(:order,
50
+ :order_id, :Integer,
51
+ :customer, :String,
52
+ :items, {:DataType=> :ResultSet, :Link_many=> [:order_id, :order_item,
53
+ :order_id]}
54
+ )
55
+
56
+ # Insert some order records.
57
+ order_tbl.insert({:order_id=>345, :customer=>'Ford'})
58
+ order_tbl.insert({:order_id=>454, :customer=>'Microsoft'})
59
+ order_tbl.insert({:order_id=>17, :customer=>'Boeing'})
60
+
61
+ # Insert some order item records.
62
+ order_item_tbl.insert(1,345,'Steel',30,19.99,nil)
63
+ order_item_tbl.insert(2,345,'Glass',5,4.15,nil)
64
+ order_item_tbl.insert(5,454,'Floppies',750000,0.5,nil)
65
+ order_item_tbl.insert(3,17,'Wheels',200,2500.0,nil)
66
+ order_item_tbl.insert(4,17,'Wings',25,1000000.0,nil)
67
+
68
+
69
+ # Print all orders. Under each order print all items in that order. Notice
70
+ # that we are able to print the total for each order because we have access
71
+ # to the entire order_items.total column of the result set. We don't have
72
+ # to loop through all of the order item result set records to add up the
73
+ # total for each order.
74
+ puts "\nPrint all orders:\n"
75
+ order_tbl.select.each do |r|
76
+ puts "\nid: %3d customer: %-10s total charge: %11.2f" % [r.order_id,
77
+ r.customer, r.items.total.inject { |sum, n| sum + n }]
78
+
79
+ r.items.each do |i|
80
+ puts "\titem: %-10s %6d * %10.2f = %11.2f" % [i.descr,
81
+ i.qty, i.price, i.total]
82
+ end
83
+ end
84
+ puts '-' * 70;puts
85
+
86
+ # You can even use the ability to access an entire column of values in your
87
+ # select statements. In this example, we only want to select those orders
88
+ # whose total charges exceeds $100,000. We can do this because we have
89
+ # access to the entire total column of the child table, order items.
90
+ puts "Print only orders whose total charge exceeds $100,000:\n"
91
+ order_tbl.select { |r| r.items.total.inject { |sum, n| sum+n } > 100000
92
+ }.each do |r|
93
+ puts "\nid: %3d customer: %-10s total charge: %11.2f" % [r.order_id,
94
+ r.customer, r.items.total.inject { |sum, n| sum + n }]
95
+
96
+ r.items.each do |i|
97
+ puts "\titem: %-10s %6d * %10.2f = %11.2f" % [i.descr,
98
+ i.qty, i.price, i.total]
99
+ end
100
+ end
@@ -0,0 +1,31 @@
1
+ #Test of CSV file import.
2
+
3
+ require 'kirbybase'
4
+ require 'date'
5
+
6
+ db = KirbyBase.new
7
+
8
+ # To run as a client in a multi-user environment, uncomment next line.
9
+ # Also, make sure kbserver.rb is running.
10
+ #db = KirbyBase.new do |d|
11
+ # d.connect_type = :client
12
+ # d.host = 'localhost'
13
+ # d.port = 44444
14
+ #end
15
+
16
+ # If table exists, delete it.
17
+ db.drop_table(:plane) if db.table_exists?(:plane)
18
+
19
+ # Create a table.
20
+ plane_tbl = db.create_table(:plane, :name, :String, :country, :String,
21
+ :role, :String, :speed, :Integer, :range, :Integer, :began_service, :Date,
22
+ :still_flying, :Boolean)
23
+
24
+ # Import csv file.
25
+ puts 'Records imported: %d' % plane_tbl.import_csv('plane.csv')
26
+
27
+ puts
28
+
29
+ # Now, lets show that the csv file did, in fact, get imported.
30
+ puts plane_tbl.select(:name, :country, :role, :speed, :range).sort(:name
31
+ ).to_report
@@ -0,0 +1,11 @@
1
+ FW-190,Germany,Fighter,399,499,1942-12-01,false
2
+ P-51,USA,Fighter,405,1210,1943-06-24,true
3
+ P-47,USA,Fighter,365,888,1943-03-12,false
4
+ B-17,USA,Bomber,315,1400,1937-05-01,true
5
+ Typhoon,Great Britain,Fighter-Bomber,389,690,1944-11-20,false
6
+ Spitfire,Great Britain,Fighter,345,540,1939-02-18,true
7
+ Oscar,Japan,Fighter,361,777,1943-12-31,false
8
+ ME-109,Germany,Fighter,366,514,1936-07-07,true
9
+ JU-88,Germany,Bomber,289,999,1937-01-19,false
10
+ P-39,USA,Fighter,,,,false
11
+ Zero,Japan,Fighter,377,912,1937-05-15,true
@@ -0,0 +1,43 @@
1
+ # This script is an example of how to specify a default value for a column.
2
+ #
3
+ require 'kirbybase'
4
+
5
+ db = KirbyBase.new
6
+
7
+ # If table exists, delete it.
8
+ db.drop_table(:address_book) if db.table_exists?(:address_book)
9
+
10
+ # Create a table. Notice how we specify a default value for :category.
11
+ address_book_tbl = db.create_table(:address_book,
12
+ :firstname, :String, :lastname, :String, :street_address, :String,
13
+ :city, :String, :phone, :String,
14
+ :category, {:DataType=>:String, :Default=>'Super Hero'})
15
+
16
+ # Insert a record. Notice that I am passing nil for :category. KirbyBase
17
+ # will insert the default value, 'Super Hero', in that field.
18
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave', 'Gotham City',
19
+ '111-111-1111', nil)
20
+
21
+ # Insert another record. Here we supply the value for :category, so
22
+ # KirbyBase will use it instead of the default.
23
+ address_book_tbl.insert('Bugs', 'Bunny', '1234 Rabbit Hole', 'The Forest',
24
+ '222-222-2222', 'Cartoon Character')
25
+
26
+ # Now lets change the default value for :category to 'President'.
27
+ address_book_tbl.change_column_default_value(:category, 'President')
28
+
29
+ # And let's add another record without supplying a value for :category.
30
+ address_book_tbl.insert(firstname='George', lastname='Bush',
31
+ street_address='1600 Pennsylvania Ave', 'Washington', '333-333-3333', nil)
32
+
33
+ # Now, let's remove the default value for :category
34
+ address_book_tbl.change_column_default_value(:category, nil)
35
+
36
+ # And add another record. We won't specify a value for :category and,
37
+ # KirbyBase will not use a default value, because we removed it.
38
+ address_book_tbl.insert('Silver', 'Surfer', '1234 Galaxy Way',
39
+ 'Any City', '444-444-4444', nil)
40
+
41
+ # Now lets print the table out and you will see how all of the defaults
42
+ # worked.
43
+ puts address_book_tbl.select.to_report
@@ -0,0 +1,24 @@
1
+ #Test of drop_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.drop_column(:speed)
23
+
24
+ puts plane_tbl.select.to_report
@@ -0,0 +1,46 @@
1
+ # This script is an example of how to add an index to an existing table.
2
+ #
3
+ require 'kirbybase'
4
+
5
+ db = KirbyBase.new
6
+
7
+ # If table exists, delete it.
8
+ db.drop_table(:address_book) if db.table_exists?(:address_book)
9
+
10
+ address_book_tbl = db.create_table(:address_book,
11
+ :firstname, :String, :lastname, :String, :street_address, :String,
12
+ :city, :String, :phone, :String, :category, :String)
13
+
14
+ # Insert some contact info records.
15
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave', 'Gotham City',
16
+ '111-111-1111', 'Super Hero')
17
+ address_book_tbl.insert('Bugs', 'Bunny', '1234 Rabbit Hole', 'The Forest',
18
+ '222-222-2222', 'Cartoon Character')
19
+ address_book_tbl.insert('George', 'Bush', '1600 Pennsylvania Ave',
20
+ 'Washington', '333-333-3333', 'President')
21
+ address_book_tbl.insert('Silver', 'Surfer', '1234 Galaxy Way',
22
+ 'Any City', '444-444-4444', 'Super Hero')
23
+
24
+ # Select all super heros without using the index.
25
+ address_book_tbl.select { |r| r.category == 'Super Hero' }.each { |r|
26
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
27
+ }
28
+ puts;puts
29
+
30
+ address_book_tbl.add_index(:category)
31
+
32
+ # Now, do the same query, but use the category index. These
33
+ # select_by_index methods are automatically created by KirbyBase when you
34
+ # specify that a column be indexed.
35
+ address_book_tbl.select_by_category_index { |r|
36
+ r.category == 'Super Hero' }.each { |r|
37
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
38
+ }
39
+ puts;puts
40
+
41
+ address_book_tbl.add_index(:firstname, :lastname)
42
+
43
+ # Select Bugs Bunny using the firstname+lastname index.
44
+ address_book_tbl.select_by_firstname_lastname_index { |r|
45
+ r.firstname == 'Bugs' and r.lastname == 'Bunny'
46
+ }.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
@@ -0,0 +1,66 @@
1
+ # This script is an example of how to drop an index from an existing table.
2
+ #
3
+ require 'kirbybase'
4
+
5
+ db = KirbyBase.new
6
+
7
+ # If table exists, delete it.
8
+ db.drop_table(:address_book) if db.table_exists?(:address_book)
9
+
10
+ address_book_tbl = db.create_table(:address_book,
11
+ :firstname, {:DataType=>:String, :Index=>1},
12
+ :lastname, {:DataType=>:String, :Index=>1},
13
+ :street_address, :String,
14
+ :city, :String,
15
+ :phone, :String,
16
+ :category, {:DataType=>:String, :Index=>2}
17
+ )
18
+
19
+ # Insert some contact info records.
20
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave', 'Gotham City',
21
+ '111-111-1111', 'Super Hero')
22
+ address_book_tbl.insert('Bugs', 'Bunny', '1234 Rabbit Hole', 'The Forest',
23
+ '222-222-2222', 'Cartoon Character')
24
+ address_book_tbl.insert('George', 'Bush', '1600 Pennsylvania Ave',
25
+ 'Washington', '333-333-3333', 'President')
26
+ address_book_tbl.insert('Silver', 'Surfer', '1234 Galaxy Way',
27
+ 'Any City', '444-444-4444', 'Super Hero')
28
+
29
+ p address_book_tbl.field_indexes
30
+ puts;puts
31
+
32
+ address_book_tbl.select_by_category_index { |r|
33
+ r.category == 'Super Hero' }.each { |r|
34
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
35
+ }
36
+ puts;puts
37
+
38
+ address_book_tbl.drop_index(:category)
39
+
40
+ begin
41
+ address_book_tbl.select_by_category_index { |r|
42
+ r.category == 'Super Hero' }.each { |r|
43
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
44
+ }
45
+ rescue StandardError => e
46
+ puts e
47
+ puts;puts
48
+ end
49
+
50
+ # Select Bugs Bunny using the firstname+lastname index.
51
+ address_book_tbl.select_by_firstname_lastname_index { |r|
52
+ r.firstname == 'Bugs' and r.lastname == 'Bunny'
53
+ }.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
54
+
55
+ address_book_tbl.drop_index(:firstname, :lastname)
56
+
57
+ begin
58
+ address_book_tbl.select_by_firstname_lastname_index { |r|
59
+ r.firstname == 'Bugs' and r.lastname == 'Bunny'
60
+ }.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
61
+ rescue StandardError => e
62
+ puts e
63
+ puts;puts
64
+ end
65
+
66
+ p address_book_tbl.field_indexes
@@ -0,0 +1,71 @@
1
+ # This script is an example of how to use indexes in KirbyBase. Indexes
2
+ # allow for faster queries on large datasets.
3
+ #
4
+ # To use indexes, you must first specify which fields are to be indexed.
5
+ # You do this at table creation time. Both single and compound indexes can
6
+ # be created. Then, when performing a select query, you simply use the
7
+ # automatically created select_by_?????_index method, where ????? is
8
+ # replaced by the name(s) of the indexed field(s). That's it. Everything
9
+ # else concerning building and maintaing indexes is done by KirbyBase.
10
+ require 'kirbybase'
11
+
12
+ db = KirbyBase.new
13
+
14
+ # To run as a client in a multi-user environment, uncomment next line.
15
+ # Also, make sure kbserver.rb is running.
16
+ #db = KirbyBase.new do |d|
17
+ # d.connect_type = :client
18
+ # d.host = 'localhost'
19
+ # d.port = 44444
20
+ #end
21
+
22
+ # If table exists, delete it.
23
+ db.drop_table(:address_book) if db.table_exists?(:address_book)
24
+
25
+ # Here we are creating a table to hold contact info. We are going to create
26
+ # two indexes. One index is going to be a compound index containing the
27
+ # firstname and lastname fields. Notice how we group the firstname and
28
+ # lastname fields into one index by specifying :Index=>1 for both of them.
29
+ # This just tells KirbyBase that the two fields should be combined into one
30
+ # compound index because they both are using the same index number. The
31
+ # second index is going to be a single index containing the category field.
32
+ # Since we want it to be a separate index, we simply use the next available
33
+ # number, 2, as the value of it's :Index key.
34
+ address_book_tbl = db.create_table(:address_book,
35
+ :firstname, {:DataType=>:String, :Index=>1},
36
+ :lastname, {:DataType=>:String, :Index=>1},
37
+ :street_address, :String,
38
+ :city, :String,
39
+ :phone, :String,
40
+ :category, {:DataType=>:String, :Index=>2}
41
+ )
42
+
43
+ # Insert some contact info records.
44
+ address_book_tbl.insert('Bruce', 'Wayne', '1234 Bat Cave', 'Gotham City',
45
+ '111-111-1111', 'Super Hero')
46
+ address_book_tbl.insert('Bugs', 'Bunny', '1234 Rabbit Hole', 'The Forest',
47
+ '222-222-2222', 'Cartoon Character')
48
+ address_book_tbl.insert('George', 'Bush', '1600 Pennsylvania Ave',
49
+ 'Washington', '333-333-3333', 'President')
50
+ address_book_tbl.insert('Silver', 'Surfer', '1234 Galaxy Way',
51
+ 'Any City', '444-444-4444', 'Super Hero')
52
+
53
+ # Select all super heros without using the index.
54
+ address_book_tbl.select { |r| r.category == 'Super Hero' }.each { |r|
55
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
56
+ }
57
+ puts;puts
58
+ # Now, do the same query, but use the category index. These
59
+ # select_by_index methods are automatically created by KirbyBase, based on
60
+ # the indexes you specified at table creation.
61
+ address_book_tbl.select_by_category_index { |r|
62
+ r.category == 'Super Hero' }.each { |r|
63
+ puts '%s %s %s' % [r.firstname, r.lastname, r.phone]
64
+ }
65
+ puts;puts
66
+ # Select Bugs Bunny using the firstname+lastname index.
67
+ address_book_tbl.select_by_firstname_lastname_index { |r|
68
+ r.firstname == 'Bugs' and r.lastname == 'Bunny'
69
+ }.each { |r| puts '%s %s %s' % [r.firstname, r.lastname, r.phone] }
70
+
71
+ p address_book_tbl.field_indexes