kirbybaserubymanual.html in KirbyBase-2.5 vs kirbybaserubymanual.html in KirbyBase-2.5.1
- old
+ new
@@ -260,12 +260,11 @@
<body>
<div id="header">
<h1>KirbyBase Manual (Ruby Version)</h1>
<span id="author">Jamey Cribbs</span><br />
<span id="email"><tt><<a href="mailto:jcribbs@twmi.rr.com">jcribbs@twmi.rr.com</a>></tt></span><br />
-<span id="revision">version 2.5,</span>
-1 December 2005
+v2.5.1 December 2005
</div>
<div id="preamble">
<div class="sectionbody">
<div class="imageblock">
<div class="content">
@@ -305,10 +304,20 @@
<a href="#recno">The recno field</a>
</p>
</li>
<li>
<p>
+<a href="#encrypt">Turning on encryption</a>
+</p>
+</li>
+<li>
+<p>
+<a href="#record-class">Specifying a custom record class</a>
+</p>
+</li>
+<li>
+<p>
<a href="#defaults">Specifying default values</a>
</p>
</li>
<li>
<p>
@@ -574,16 +583,16 @@
<a href="#tips-on-improving-performance">Tips on improving performance</a>
</p>
</li>
<li>
<p>
-<a href="#client-server-diagram">Client/Server memory space diagram</a>
+<a href="#single-user-diagram">Single-user memory space diagram</a>
</p>
</li>
<li>
<p>
-<a href="#single-user-diagram">Single-user memory space diagram</a>
+<a href="#client-server-diagram">Client/Server memory space diagram</a>
</p>
</li>
<li>
<p>
<a href="#license">License</a>
@@ -603,11 +612,11 @@
Some of its features include:</p>
<ul>
<li>
<p>
Since KirbyBase is written in Ruby, it runs anywhere that Ruby runs. It
-is easy to distribute, since the entire dbms is in one (approx. 100k) code
+is easy to distribute, since the entire DBMS is in one (approx. 100k) code
file.
</p>
</li>
<li>
<p>
@@ -651,11 +660,11 @@
</p>
</li>
<li>
<p>
All inserted records have an auto-incrementing primary key that is
-guaranteed to uniquely identify the record throughout it's lifetime.
+guaranteed to uniquely identify the record throughout its lifetime.
</p>
</li>
<li>
<p>
You can specify that the result set be sorted on multiple fields, each
@@ -722,11 +731,11 @@
<div class="listingblock">
<div class="content">
<pre><tt>db = KirbyBase.new(:client, 'localhost', 44444)</tt></pre>
</div></div>
<p>Of course, you would substitute your server's ip address and port number.</p>
-<p>To specify a different location other than the current directory for the
+<p>To specify a different location (other than the current directory) for the
database files, you need to pass the location as an argument, like so:</p>
<div class="listingblock">
<div class="content">
<pre><tt>db = KirbyBase.new(:local, nil, nil, './data')</tt></pre>
</div></div>
@@ -735,17 +744,32 @@
a different extension, pass this as an argument, like so:</p>
<div class="listingblock">
<div class="content">
<pre><tt>db = KirbyBase.new(:local, nil, nil, './', '.dat')</tt></pre>
</div></div>
+<p>To specify a different location other than the current directory for any
+memo/blob files, you need to pass the location as an argument, like so:</p>
+<div class="listingblock">
+<div class="content">
+<pre><tt>db = KirbyBase.new(:local, nil, './', '.tbl', './memos')</tt></pre>
+</div></div>
+<p>If you don't want KirbyBase to spend time initially creating all of the
+indexes for the tables in the database, you can pass false as the
+delay_index_creation argument:</p>
+<div class="listingblock">
+<div class="content">
+<pre><tt>db = KirbyBase.new(:local, nil, './', '.tbl', './', true)</tt></pre>
+</div></div>
+<p>KirbyBase will skip initial index creation and will create a table's
+indexes when the table is first referenced.</p>
<p>You can also specify the arguments via a code block. So, if you don't want
to have to specify a bunch of arguments just to get to the one you want,
put it in a code block attached to the method call. You could re-code the
previous example like so:</p>
<div class="listingblock">
<div class="content">
-<pre><tt>db = KirbyBase.new { |d| d.ext = '.dat' }</tt></pre>
+<pre><tt>db = KirbyBase.new { |d| d.delay_index_creation = true }</tt></pre>
</div></div>
</div>
<h2><a id="creating-a-new-table"></a>Creating a new table</h2>
<div class="sectionbody">
<p>To create a new table, you specify the table name, and a name and type for
@@ -785,10 +809,11 @@
auto-incremented each time a record is inserted. You can use this field in
select, update, and delete queries, but you can't modify this field.</td>
</tr></table>
</div>
</div></div>
+<h3><a id="encrypt"></a>Turning on encryption</h3>
<p>You can also specify whether the table should be encrypted. This will save
the table to disk encrypted (more like obfuscated) using a Vignere Cipher.
This is similar to rot13, but it uses a key to determine character
substitution. Still, this encryption will only stymie the most casual
of hackers. Do not rely on it to keep sensitive data safe! You specify
@@ -797,10 +822,11 @@
<div class="content">
<pre><tt>plane_tbl = db.create_table(:plane, :name, :String...) do |t|
t.encrypt = true
end</tt></pre>
</div></div>
+<h3><a id="record-class"></a>Specifying a custom record class</h3>
<p>You can also specify that you want records of the table to be returned to
you as instances of a class. To do this, simply define a class before you
call #create_table. This class needs to have an accessor for each fieldname
in the table. Also, this class needs to have a class method, called
#kb_create, that returns a new class instance. Here is an example class:</p>
@@ -867,13 +893,15 @@
<p>Normally, when you insert a record, if you don't specify a value for a field
or specify nil as the value, KirbyBase stores this as an empty string
(i.e. "") in the table's physical file, and returns it as a nil value when
you do a #select.</p>
<p>However, you can tell KirbyBase that you want a column to have a default
-value. This will be applied whenever either no value or a nil value is
-specified for the field when <strong>inserting</strong> a record only. When updating an
-existing record, defaults will not be applied.</p>
+value. Only KBTable#insert is affected by default values. Default values
+do not apply to updating a record. So, for inserts, there are two cases
+where a default value, if one is specified, will be applied: (1) if nil
+is specified for a field's value, and (2) if no value is specified for a
+field.</p>
<p>For example, to specify that the category column has a default value, you
would code:</p>
<div class="listingblock">
<div class="content">
<pre><tt>db.create_table(:addressbook, :firstname, :String,
@@ -882,11 +910,11 @@
</div></div>
<p>Notice that, since we are specifying advanced field type information, we
cannot just simply say :String for the second half of the field definition.
Instead, we have to pass a hash, with a :DataType item set to :String.
Next, because we are specifying a default value, we have to include a hash
-item called :Default with it's value set to whatever we want the default to
+item called :Default with its value set to whatever we want the default to
be. The default value must be of a type that is valid for the column.</p>
<h4><a id="requireds"></a>Required Fields</h4>
<p>Normally, when you insert or update a record, if you don't specify a value
for a field or specify nil as the value, KirbyBase stores this as an empty
string (i.e. "") in the table's physical file, and returns it as a nil
@@ -905,11 +933,11 @@
</div></div>
<p>Notice that, since we are specifying advanced field type information, we
cannot just simply say :String for the second half of the field definition.
Instead, we have to pass a hash, with a :DataType item set to :String.
Next, because we are specifying that a column is required, we have to
-include a hash item called :Required with it's value set to true.</p>
+include a hash item called :Required with its value set to true.</p>
<h4><a id="creating-indexes"></a>Indexes</h4>
<p>Indexes are in-memory arrays that have an entry that corresponds to each
table record, but just holds the field values specified when the index was
created, plus the :recno of the actual table record. Because index arrays
are smaller than the actual table and because they are in-memory instead of
@@ -929,11 +957,11 @@
</div></div>
<p>Notice that, since we are specifying advanced field type information, we
cannot just simply say :String for the second half of the field definition.
Instead, we have to pass a hash, with a :DataType item set to :String.
Next, because we are creating an index, we have to include a hash item
-called :Index with it's value set from 1 to 5. For compound indexes, like
+called :Index with its value set from 1 to 5. For compound indexes, like
the one in the above example, we need to make sure that all fields in the
index have the same number. To have another index for a table, just make
sure you increment the index number. So, for example, if we wanted to have
another index for the :addressbook table on the field phone number, we would
code:</p>
@@ -959,13 +987,14 @@
have a user application wait once upon initialization, rather than have it
wait the first time a table is referenced. A user is more used to waiting
for an application to properly initialize, so this initial delay, I thought,
would feel more natural to the user, rather than a wait time in the middle
of the application.</p>
-<p>Please let me know if this poses a problem for any of your applications. I
-have some ideas that I could implement that would allow the developer to
-specify when indexes are created.</p>
+<p>If you find that this initial delay while indexes are created is
+un-acceptable, you can pass delay_index_creation=true to KirbyBase.new.
+This will bypass the initial index creation for all tables. Indexes for an
+individual table will be created when the table is first referenced.</p>
<p>This is also an excellent reason to use the client/server capabilities of
KirbyBase. In client/server mode, the database initialization processing is
all done on the server, so, once this is done, any users starting their
client application and connecting to the server will experience no delay due
to index array creation.</p>
@@ -1028,11 +1057,11 @@
<p>For example, say you are creating an order entry system for your business.
You have a master table called :orders that holds one record for each
customer order that is placed. It has fields like: :order_id, :cust_id,
:order_date, etc.</p>
<p>Now, you also need a table that is going to have a record for each detail
-item type ordered. Let's call it :order_items and some of it's fields would
+item type ordered. Let's call it :order_items and some of its fields would
be: :item_no, :qty, :order_id.</p>
<p>Notice that the detail table has a field called :order_id. This will hold
the order_id linking it back to the :orders.order_id table. If a customer
order's only one type of item, then there will only be one record in the
:order_items table that has that order_id. But, if the customer places an
@@ -1060,11 +1089,11 @@
KBResultSet that contains :order_items whose :order_id field (the last item
in the array above), equals the value of the :orders.order_id field (the
first item of the array above).</p>
<p>If you opened up the :orders table file in a text editor, you would notice
that, for each record, the :items field is blank. No data is ever stored in
- this field, since it's value is always computed at runtime.</p>
+ this field, since its value is always computed at runtime.</p>
<h4><a id="creating-calculated-fields"></a>Calculated Fields</h4>
<p>When you specify that a field is a Calculated field, you are telling
KirbyBase to compute the value of the field at runtime, based on the code
string that you pass it at table creation time.</p>
<p>For example. let's say you have a table that is going to track your
@@ -1083,11 +1112,11 @@
</div></div>
<p>See how we tell KirbyBase how to calculate the field? By multiplying the
:qty field by the :price field.</p>
<p>If you opened up the :purchases file in a text editor, you would notice
that, for each record, the :total_cost field is blank. No data is ever
-stored in this field, since it's value is always computed at runtime.</p>
+stored in this field, since its value is always computed at runtime.</p>
</div>
<h2><a id="obtaining-a-reference-to-an-existing-table"></a>Obtaining a reference to an existing table</h2>
<div class="sectionbody">
<p>If a table already exists and you need to get a reference to it so that you
can insert, select, etc., you would call the #get_table method from your
@@ -1139,11 +1168,12 @@
r.country = 'USA'
r.role = 'Bomber'
r.speed = 315
r.range = 1400
r.began_service = Date.new(1937, 5, 1)
- r.still_flying = true</tt></pre>
+ r.still_flying = true
+end</tt></pre>
</div></div>
<h3>Insert a record using an instance of the table's custom record class:</h3>
<div class="listingblock">
<div class="content">
<pre><tt>foo = Foobar.new do |x|
@@ -1252,11 +1282,11 @@
<div class="listingblock">
<div class="content">
<pre><tt>plane_tbl.select_by_speed_index { |r| r.speed > 400 }</tt></pre>
</div></div>
<p>Notice that you simply insert the name of the field as part of the method
-name. It's as simple as that.</p>
+name. Its as simple as that.</p>
<p>For compound indexes, you just need to specify the
indexed field names in the select method in the same order as they are in
the table. So, let's say you have indexed the :plane table on :country and
:role, in one index. To select on this compound index, you would code:</p>
<div class="listingblock">
@@ -1308,10 +1338,11 @@
<div class="content">
<pre><tt>department_tbl.select do |r|
r.manager.firstname == 'John' and r.manager.lastname == 'Doe'
end</tt></pre>
</div></div>
+<p>Notice how the manager attribute is itself a Struct with its own members.</p>
<p>To print out all departments including the manager's full name:</p>
<div class="listingblock">
<div class="content">
<pre><tt>department_tbl.select.each do |r|
puts 'Department: %s Manager: %s %s' % [r.dept_name,
@@ -1328,11 +1359,11 @@
:Link_many=>[:order_id, :order_items, :order_id]})
order_items_tbl = db.create_table(:order_items, :item_no, :Integer,
:qty, :Integer, :order_id, :Integer)</tt></pre>
</div></div>
-<p>To print an order and all of it's associated detail items:</p>
+<p>To print an order and all of its associated detail items:</p>
<div class="listingblock">
<div class="content">
<pre><tt>result = order_tbl.select { |r| r.order_id == 501 }.first
puts '%d %d %s' % [result.order_id, result.cust_id, result.order_date]
@@ -1347,11 +1378,11 @@
<p>As stated above, the select method returns an instance of KBResultSet, which
is an array of Struct objects (or instances of the class specified in
record_class), each one representing a record that satisfied the selection
criteria.</p>
<p>Since each item in KBResultSet is a Struct object, you can easily reference
-it's members using field names. So, to print the name and speed of each
+its members using field names. So, to print the name and speed of each
German plane in the table you would code:</p>
<div class="listingblock">
<div class="content">
<pre><tt>plane_tbl.select(:name, :speed) { |r| r.country == 'German' }.each do |r|
puts '%s %s' % [r.name, r.speed]
@@ -1377,11 +1408,11 @@
<pre><tt>result_set = plane_tbl.select(:name, :country, :speed).sort(:country,
-:speed)</tt></pre>
</div></div>
<p>You can also explicitly specify that a field be sorted in ascending order by
putting a plus sign in front of it. This is not necessary, since ascending
-is the default, but it's there if you prefer to use it.</p>
+is the default, but its there if you prefer to use it.</p>
<h3><a id="to-report"></a>Producing a report from a result set</h3>
<p>Additionally, you can also transform the KBResultSet into a nicely formatted
report, suitable for printing, by calling KBResultSet#to_report. To print
a formatted report of all plane names, countries, and speeds, sorted by
name, you would code the following:</p>
@@ -1484,11 +1515,11 @@
<p>To update a table, you use the update method. You <strong>must</strong> specify a code
block that indicates which records are to be updated. Additionally, you must
specify the fields to be updated and the new values for those fields.</p>
<p>You can update records using a Hash, Struct, an Array, or an instance of a
class you defined. For example, to change the P-51's speed to 405mph and
-it's range to 1210 miles, you could code:</p>
+its range to 1210 miles, you could code:</p>
<div class="listingblock">
<div class="content">
<pre><tt>plane_tbl.update(:speed=>405, :range=>1210) { |r| r.name == 'P-51' }</tt></pre>
</div></div>
<p>or:</p>
@@ -1767,11 +1798,11 @@
<div class="sidebar-title">KBTable#[]</div>
<div class="listingblock">
<div class="content">
<pre><tt>plane_tbl[5]</tt></pre>
</div></div>
-<p>You can quickly select an individual record, by passing it's recno to a
+<p>You can quickly select an individual record, by passing its recno to a
table as if it were a hash.</p>
<p>Returns a single record either in the form of a Struct or an instance of
the table's custom record class, if specified.</p>
<div class="listingblock">
<div class="content">
@@ -2137,11 +2168,11 @@
line in the file is blanked-out (see "The pack method"), this number is
incremented. You can use this field in a maintenance script so that the
table is packed whenever the deleted-records counter reaches, say, 5,000
records.</p>
<p>The third field in the header is the record_class field. If you specified a
-class when you created the table, it's name will show up here and records
+class when you created the table, its name will show up here and records
returned from a #select will be instances of this class. The default is
"Struct".</p>
<p>The fourth field in the header is the :recno field. This field is
automatically added to the table when it is created. The field name and
field type are separated by a ":".</p>
@@ -2155,11 +2186,11 @@
</div>
<h2><a id="server-notes"></a>Server Notes</h2>
<div class="sectionbody">
<p>There is a server script included in the distribution called kbserver.rb.
This script uses DRb to turn KirbyBase into a client/server, multi-user
-dbms. This dbms server handles table locking for you so you don't have to
+DBMS. This DBMS server handles table locking for you so you don't have to
worry about it.</p>
</div>
<h2><a id="tips-on-improving-performance"></a>Tips on improving performance</h2>
<div class="sectionbody">
<h3>Beware of Date/DateTime</h3>
@@ -2180,11 +2211,11 @@
<div class="content">
<pre><tt>date_field_stored_as_string_field <= "2005-05-11"</tt></pre>
</div></div>
<h3>Create indexes on large tables</h3>
<p>The larger a table becomes, the more sense it makes to create an index on
-one or more of it's fields. Even though you take a hit when KirbyBase first
+one or more of its fields. Even though you take a hit when KirbyBase first
initializes because it has to create the index arrays, you make up for it
after that in greatly improved query speeds. I have noticed speed-ups of
as much as 10x on large tables.</p>
<h3>Create indexes on foreign keys</h3>
<p>If you have a Link_many on a table field, you might want to think about
@@ -2197,26 +2228,26 @@
:recno, use the built-in #select_by_recno_index method (or the #[] method).
This is even faster than selecting on a regularly indexed field, because the
:recno index that KirbyBase creates for each table is actually a Hash, not
an Array like all of the regular indexes. So selects are even faster.</p>
</div>
-<h2><a id="client-server-diagram"></a>Client/Server memory space diagram</h2>
+<h2><a id="single-user-diagram"></a>Single-user memory space diagram</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
-<img src="images/client_server.png" alt="images/client_server.png"/>
+<img src="images/single_user.png" alt="images/single_user.png"/>
</div>
-<div class="image-title">Figure: Client/Server (separate memory spaces) mode.</div>
+<div class="image-title">Figure: Single-user (embedded) mode.</div>
</div>
</div>
-<h2><a id="single-user-diagram"></a>Single-user memory space diagram</h2>
+<h2><a id="client-server-diagram"></a>Client/Server memory space diagram</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
-<img src="images/single_user.png" alt="images/single_user.png"/>
+<img src="images/client_server.png" alt="images/client_server.png"/>
</div>
-<div class="image-title">Figure: Single-user (embedded) mode.</div>
+<div class="image-title">Figure: Client/Server (separate memory spaces) mode.</div>
</div>
</div>
<h2><a id="license"></a>License</h2>
<div class="sectionbody">
<p>KirbyBase is distributed under the same license terms as Ruby.</p>
@@ -2233,11 +2264,10 @@
</tr></table>
</div>
</div>
<div id="footer">
<div id="footer-text">
-Version 2.5<br />
-Last updated 01-Dec-2005 13:28:12 Eastern Daylight Time
+Last updated 28-Dec-2005 13:27:25 Eastern Daylight Time
</div>
</div>
</body>
</html>