Node:Modes of deployment,
Next:Application definition file syntax,
Previous:What is kort,
Up:Top
Modes of deployment
Following concepts are used in this document:
- Schema means a set of database tables that store data belonging to
known application or problem domain. Some tables need to have known
name and structure (like table kort_ui) or only partially known
structure (like that column recid must always be present in
every data table)
- See Kort. program is the program that runs an application
definition and lets user mess thingies.
- Application definition file is a text file that you make with your
favourite UTF-8 capable text editor1 and
follows a strict syntax hopefully described
in this manual.
- Record is set of values. One record is stored in one database table, one row.
There may be 0-n records in one table. One (or zero) record at time is
displayed for user when user runs kort. From database-perspective
a record is one row in database. From user-interface perspective one
record must make up one form that is shown to user.
- Form. See record.
- Field is one piece of data saved to db table in one column, in one row.
Field gets displayed in a form. It has several properties like data type,
max length of data, format and "physical" location in a form where
it belongs to.
- Relation2
is a rule that ties records to their parent record.
Kort allows you to create 1-n relations e.g. a record may have
subrecords and subrecords may have subsubrecords etc. Kort does not
(without TCL tinkering) support m-n relations or a record referencing
another record from same table. Relations are supported with method of
kort-generated surrogates, one for each record, another for specifying
a optional master record in another table.
- Command is something user initiates and hopefully gets done. There are
built-in commands like "save record", "save record as new", "go to another
record" etc. and then application developer may define new commands
as TCL scripts. A command relates to record or record-field and is
initiated by press of function key (F1-Fn depending on your terminal).
There is no other way of giving commands, except for exiting where
ctrl-q seems to do the trick.
- TCL script may be run either as initiated by user or by some event.
Possible events are thingies like "after saving of record", "before
entering to record", "when a message is received from network".
You may do whatever tcl lets you to do, including database interaction,
networking, graphics via tk etc.
- Locking in kort is performed in application level. In each data table
there are two columns for locking, one showing the lock holder, another
showing time of last lock. Before user of kort is allowed to make
modifications to a record, existence of lock is checked and user is
asked if he wants to continue in editing as the record is locked. In
current incarnation user may choose to not to care about previous lock
and edit and save the record anyway.
After application developer has finished analyzing requirements for
her application, designing database structure and structure of the
application, all the time keeping in mind minor limitations set by
kort then kort comes to picture. Most easily kort suits for
pretty straigh-forward client-server applications where database stores
the data and all the processing or "logic" is done in the client-side.
With some TCL-tinkering it is not at all impossible to implement
application logic with some other tool, running in some remote (centralized)
computer that kort talks to with some message passing mechanism.
Kort already knows UDP/IP message passing but as UDP/IP is by definition
unreliable, implementing "must happen" -type application logic over UDP/IP
might not be the wisest thing to do; instead hogging ORB or SOAP or xmlrpc
or some other message-passing scheme that has programmatic interface in
TCL might be better idea and is easy to do.
Most basic thing that kort lets you to do is to be able to define
a data record and an associated form for editing records. In kort
data record definition is the same thing as form definition for a
data record. Kort then lets end user to load records one at time to
this form and edit, delete and save records. This can very easily
be extended to abling records to have subrecords in very same manner.
Subrecords also may have subsubrecords etc.
Lets consider an example of an application definition file:
# this is a sample application definition file
RECORD FooMaticEntry DBTABLE foomatic_orders
FUNCTION_KEY 1 SAVERECORD "Save" BUTASKFIRST
FUNCTION_KEY 2 SAVERECORDASNEW "SaveNew" BUTASKFIRST
FUNCTION_KEY 3 SELECTANOTHERRECORD "Find"
FUNCTION_KEY 4 EXITRECORD "Exit"
LABEL 2 8 "Foo-Matic order entry form"
RECFIELD 5 2 20 customer_name STRING "Who orders: "
RECFIELD 6 2 20 delivery_streed_addr STRING "Street address: "
RECFIELD 7 2 20 delivery_city STRING "City: "
RECFIELD 8 2 delivery_date DATETIME "Date of delivery: " "mm/dd/yyyy"
RECFIELD 9 2 20 customer_phone STRING "Phone: "
This file defines one record, named "FooMaticEntry" that is saved to
database table "foomatic_orders". When a record is displayed, following
function keys have following actions defined:
F1 saves the record currently displayed and asks before saving.
F2 saves the current record as new one and asks before saving.
F3 forces user to choose another (or same) record from table
foomatic_orders.
F4 simply exits the application, no questions asked.
For first 8 function keys labels for keys are shown on bottom of the
screen, those labels in this application are "Save", "SaveNew", "Find" and
"Exit", respectively. When required database tables are created the
application definition file may be run and when given to kort the
application in action looks like this:
Image 1: Foomatic order entry form in action
In order to be able to run this, a MySQL database is needed. Within
MySQL the "database name" must be set to "kort", currently this name
is hard-coded into kort sources so as MySQL by default comes with
database names "mysql" and "test", yet another one must be created
(and "test" dropped if you wish). The following SQL creates the
table that will hold the order entries:
create table foomatic_orders (
customer_phone CHAR(20),
customer_name CHAR(20),
delivery_city CHAR(20),
delivery_date INTEGER(11),
delivery_streed_addr CHAR(20),
recid integer not null,
recid_master integer not null,
lock_status char(30),
lock_time integer
);
Here data columns are the first five columns. Column recid is
a generated surrogate, an unique value that kort uses to distinguish
between records. Column recid_master is used in sub-record-tables
to hold value of master record, the record that current record
joins to. In Foomatic order entry form value of recid_master
is not important. Kort will generate a non-null, non-meaningful value
for records that are not sub-records of any other record. Column
lock_status has non-null value when record is locked and
null when locked. The value in the column should identify the kort
instance uniquely, right now kort uses scheme of <host>-<pid>-<time>
to generate lock_status values. Column lock_time
holds the value of last lock, after a record has been locked the
value of this column is not set NULL i.e. this will contain the
time of last modification made through kort user interface. Also note
that the data type for date is INTEGER, instead of DATE that MySQL
also defines. Reason for this is two-fold: MySQL doesn't know a
heck about time zones3 and
therefore nothing about summer time/winter time. Second reason is
that original programmer of kort feels comfortable when he has his
time in seconds, as time_t in several implementations happens to
be4 ; third reason being that handling internally dates
as seconds since beginning of year 1970 makes it easy to pass
date and time values to/from TCL that happens to use the very same
system
A few more tables are needed before kort may be run:
create table surrogates (
foomatic_orders integer not null
);
insert into surrogates (
foomatic_orders
) values (
1
);
create table kort_ui (
addr char(20),
port integer(5),
lock_info_str char(30),
recname char(30),
recid integer,
recid_master integer
);
Table surrogates is used to hold last used value of recid for
each table. This last value is incremented when needed. In this table
exactly one row must be present, no more, no less. Table kort_ui
is used to keep a list kort user interface instances that are
connected to database. Columns in this table are the following:
- addr is the IP address of the host where kort is being run.
- port is the UDP/IP port where this instance is listening for incoming
packets.
- lock_in_str is the same string that is written to lock_status
column of data tables.
- recname is name of the record currently selected for viewing/editing
from said instance.
- recid is value of column recid in the record that is currently
open for viewing/editing in said instance.
- recid_master works like recid.
Reason for kort_ui table being present is UDP/IP sending. Kort sends
information to other instances connected to same database (and
registered to kort_ui table) in two occasions: when a record
is saved after editing a notify is sent to all kort instances that
view the same record. Functionality of kort is to re-load record
from database upon receiving such a notify. Kort also sends messages
to other instances when instructed to do so from TCL code that may
be used in application definition file.
Footnotes
-
like yudit from
http://www.yudit.org/ or vim from any linux distro.
-
Note slight deviation in terms as compared to Elmasri
& Navathe; fundamentals of database systems ; ISBN: 0-8053-1753-8 ; it roks.
-
Please correct me when I'm wrong
-
And that makes kort unportable to environments where
time_t is something else than seconds since 1970, or not unportable
but more painful