OPL's Database Management System
Summary: OPL is a language that has always
placed great importance on its database functionality. OPL uses Symbian OS DBMS;
a relational database management system which supports SQL (the Standard Query
Language).
Contents
1. Compatibility with SIBO OPL
OPL provides more database functionality while maintaining compatibility with
the SIBO (as used on the Psion Series 3, 3a, 3c, 3mx, Siena and WorkAbout) OPL
methods of database programming. Existing code will not need to change except
for a couple of minor details:
- SIBO OPL's RECSIZE
and COMPRESS keywords
have been dropped
- It is necessary to use transactions to obtain maximum update speeds
- Databases no longer compress automatically on closing (although this may
be enabled with SETFLAGS)
Reason for these changes are explained Keyword Changes.
2. The database model
To explain the features of OPL's DBMS clearly, it is necessary to expand upon
the terminology that is currently used in the SIBO OPL manual. What were known
as data files are now known as databases. A database may contain one or more
'tables'. These tables, like data files in SIBO OPL, contain records which are
made up of fields. Field names, as well as the table names, are now stored away.
Taking a look at a typical example of the SIBO OPL CREATE
statement:
CREATE
"Datafile",A,f1%,f2&
OPL would create a database called "datafile" and a table with the
default name "table1" would be added to it. The field names are derived
from f1% and f2& which we now call 'field handles'. SQL does not permit
$, %, & in field names so $ is replaced by S, % by I and & by A (N.B.
avoid calling a field I$ as this will become "IS", a word reserved
by SQL which could cause you problems later). The type of the field, as with
SIBO OPL, is got from these field handles.
In the following SIBO OPL OPEN statement:
OPEN
"Datafile",A,f1%,f2&
OPL would open the default table, "table1", and provide access to
as many fields as there are handles supplied. The names of the field handles
is not important when OPENing, all that is required is that the types specified
by these handles match the types of the fields.
With OPL it is possible to do something like this.
CREATE
"Books FIELDS Author(40),Title,Price TO Fiction",G,a$,b$,d&
This will create a database called 'BOOKS' (or open it if it already exists)
and insert a table called 'FICTION' (a trappable error would occur if such a
table in BOOKS already existed). The table will have fields called
'AUTHOR', 'TITLE', and 'PRICE', whose respective types are, as always, specified
by the field handles ($ = string, &=long etc.). Author has a string length
of 40 bytes and title has the default length of 255 bytes. Notice that the logical
filename range has been expanded from A-D to A-Z and is more sensibly known
(as we shall see) as the logical view name.
Here is an example of such a table:
Author |
Title |
Price |
Dickens Charles |
Oliver Twist |
1799 |
Homer |
Odyssey |
999 |
Orwell George |
Nineteen Eighty Four |
899 |
Dickens Charles |
Bleak House |
1499 |
Conrad Joseph |
Amy Foster |
1299 |
Orwell George |
Animal Farm |
1149 |
Dickens Charles |
Homage To Catalonia |
1599 |
3. Views onto the database
It is possible to open multiple 'views' on a table and to specify which fields
are to be available in a view.
OPEN
"Books SELECT Title FROM Fiction",G,f1$
This statement would open a 'view' that would give you access to just the 'title'
field from the 'fiction' table.
The view (blue text shows the information that is available)
Author |
Title |
Price |
Dickens Charles |
Oliver Twist |
1799 |
Homer |
Odyssey |
999 |
Orwell George |
Nineteen Eighty Four |
899 |
Dickens Charles |
Bleak House |
1499 |
Conrad Joseph |
Amy Foster |
1299 |
Orwell George |
Animal Farm |
1149 |
Dickens Charles |
Homage To Catalonia |
1599 |
The string from 'SELECT'
onwards in the OPEN statement forms an SQL query which is passed straight on
to the underlying Symbian OS DBMS. Other example SQL queries follow.
SELECT
* FROM Fiction
The * is shorthand for "all the fields".
SELECT
Title, Author FROM Fiction WHERE Title < 'B'
This is an example of an SQL WHERE
clause, it contains a search condition to specify which records are wanted in
the view.
The view: (blue text shows the information that is available)
Author |
Title |
Price |
Dickens Charles |
Oliver Twist |
1799 |
Homer |
Odyssey |
999 |
Orwell George |
Nineteen Eighty Four |
899 |
Dickens Charles |
Bleak House |
1499 |
Conrad Joseph |
Amy Foster |
1299 |
Orwell George |
Animal Farm |
1149 |
Dickens Charles |
Homage To Catalonia |
1599 |
SELECT
* FROM Fiction ORDER BY Author ASC, Price DESC
This is a more advanced view, ordered by an index. The view would present the
'Author' fields in ascending alphabetical order (A through to Z) and, then,
if any author fields matched the Price field (descending numerically) this field
would be used to order these records. For this view to work, it would first
be necessary to create a corresponding index.
The ordered view:
Author |
Title |
Price |
Conrad Joseph |
Amy Foster |
1299 |
Dickens Charles |
Oliver Twist |
1799 |
Dickens Charles |
Homage To Catalonia |
1599 |
Dickens Charles |
Bleak House |
1499 |
Homer |
Odyssey |
999 |
Orwell George |
Animal Farm |
1149 |
Orwell George |
Nineteen Eighty Four |
899 |
SELECT
* FROM Fiction WHERE Author < 'B' ORDER BY Author ASC, Title ASC
This example combines some of the above.
4. Indexing the database
The commands for creating indexes have bean supplied as language extensions
via the OPX mechanism and can be found in "Dbase.oxh"
as follows.
DECLARE OPX DBASE,KUidOpxDBase&,KOpxDBaseVersion%
DbAddField:(keyPtr&,fieldName$,order&) : 1
DbAddFieldTrunc:(keyPtr&,fieldName$,order&,trunc&) : 2
DbCreateIndex:(index$,keyPtr&,dbase$,table$) : 3
DbDeleteKey:(keyPtr&) : 4
DbDropIndex:(index$,dbase$,table$) : 5
DbIsUnique&:(keyPtr&) : 10
DbMakeUnique:(keyPtr&) : 11
DbNewKey&: : 12
DbSetComparison:(KeyPtr&,comp&) : 14
END DECLARE
To use any of these procedures you would need the following statement at the
very top of every OPL module that requires them:
INCLUDE
"Dbase.oxh"
All the procedures in this OPX begin with "dB".
This is for neatness, identity and to reduce the likelihood of the names clashing
with other procedures. Although OPX procedures look like ordinary user-defined
procedures they are as fast to call as the language keywords.
DBCREATEINDEX
takes a name for the index so that it may one day be dropped from the database.
It also takes the name of the database and table on which the index is to
be be built and a key which specifies how the index is to be ordered. This
key will first need to be built.
DBEWKEY returns
a pointer to a key object. The procedures that require a key, like DBCREATEINDEX,
will check to make sure that the pointer is valid and prevent any invalid
accessing of memory.
DbADDFIELD:(key&,
field$, order&)
This procedure adds a field-name to the key, key&
(the pointer returned by DBNEWKEY).
The first field added to a key is the most significant in the ordering of
the records. If any of these fields then match the second field added to the
key, this key would be used and so on. Order&
specifies whether the field should be ordered alphanumerically forwards (order&=1)
or reverse (order&=0).
DbADDFIELDTRUNC:(key&,
field$, order&,trunc&)
This procedure is the same as DbADDFIELD
except it also takes a truncation value trunc&.
This is used to truncate string fields during the ordering process. i.e. if
this value was "1" then only the first letter of the field would
be used to order the records. N.B. This procedure must be used when ordering
string fields that were originally created with the default length of 255
bytes, i.e. the string length was not specified in the CREATE
statement. The maximum length that can be used is 240. If a string field is
not truncated the DBMS will attempt to use its full length, giving an error
for non truncated fields of length in excess of 240 bytes.
DbMAKEUNIQE:(key&)
Using this procedure on a key will cause any subsequent index created
with that key to be unique. A view, ordered by a unique index won't allow
any changes to the database which would result in exactly matching records
when ordered by that index. This is useful for preventing any unwanted repetition
of records.
5. Database Keyword Changes
COMPACT replaces
COMPRESS
This is because in maintaining compatibility COMPRESS
would need to copy the DATABASE to another file and if the target file already
existed then the records would be appended. However, OPL can have multiple
tables in a database file so it would be ambiguous to emulate this behavior.
OPL's new COMPACT
keyword can compress a database in place without needing to copy it elsewhere.
RECSIZE has
been dropped because OPL places no restriction on the size of a record, making
this keyword redundant
INSERT/ MODIFY,
PUT / CANCEL
These new keywords allow a database to be updated without having
to move records to the end of the table. An update is commenced with modify
or INSERT and
ended with PUT or
CANCEL.
DELETE dbase$, table$
Deletes the table,table$,
from the database, dbase$.
BOOKMARK, GOTOMARK,
KILLMARK
Bookmarks provide a method for fast record access and should also
be used instead of POSITION when using multiple views. BOOKMARK returns
a bookmark for the current record, GOTOMARK takes a bookmark and makes the
record that corresponds to that bookmark the current record. KILLMARK takes
a bookmark and removes that bookmark from the database.
BEGINTRANS, COMMITTRANS,
ROLLBACK, INTRANS
Transactions allow changes to a database to be committed in stages.
BEGINTRANS begins
a transaction, COMMITTRANS commits
the transaction, ROLLBACK
cancels the transaction and INTRANS tells you whether or not the current logical
view is in a transaction. Transactions should be used in OPL to obtain optimum
update speeds.
In the following example the 100 appends are done in a single transaction.
LOCAL i%
CREATE"Database",Z,f1&
BEGINTRANS
DO
z.f1&=i%
APPEND
i%=i%+1
UNTIL i%=99
COMMITTRANS
Another advantage of transactions is atomicity. You can ensure that changes
are only made to a database if all the changes that you desire can be made.
In the following example view G and view H are only updated if both views can
be updated.
OPEN"Staff SELECT * FROM Id",G,Name$,Id&
OPEN"Staff SELECT * FROM Salary",H,Id&,wage&
USE H
BEGINTRANS
USE G
BEGINTRANS
INSERT
INPUT G.Nam$
INPUT G.Id&
PUT
USE H
INSERT
INPUT H.Id&
INPUT H.wage&
PUT
USE H
COMMITTRANS
USE G
COMMITTRANS
Symbian is a trademark of Symbian Ltd.
The Symbian Developer Network logo is a trademark of Symbian Ltd.
This paper refers to trademarks of third parties and Symbian recognizes their
rights.
Back to opl-dev project homepage
|