Вы находитесь на странице: 1из 344

Users Guide

20-7302-1002

Trademarks
Centura, the Centura logo, Centura net.db, Centura Web Developer, Gupta, the Gupta
logo, Gupta Powered, the Gupta Powered logo, Fast Facts, Object Nationalizer, Quest,
QuickObjects, SQL/API, SQLBase, SQLBase Exchange, SQLConsole, SQLGateway,
SQLHost, SQLNetwork, SQLRouter, SQLTalk, and Team Object Manager, RDM, ROM,
db_QUERY, db_REVISE and Velocis are trademarks of Centura Software Corporation
and may be registered in the United States of America and/or other countries.
SQLWindows is a registered trademark and TeamWindows, ReportWindows and
EditWindows are trademarks exclusively used and licensed by Centura Software
Corporation.
Adobe is a trademark of Adobe Systems, Incorporated.
IBM, OS/2, NetBIOS, and AIX are registered trademarks of International Business
Machines Corporation.
UNIX is a registered trademark licensed exclusively by The Open Group.
SCO UNIX is a trademark of Santa Cruz Operation, Incorporated.
Microsoft is a registered trademark, and DOS, Windows, Windows NT, and Windows 95
are trademarks, of Microsoft Corporation.
Java and Solaris are trademarks of Sun Microsystems, Incorporated.
Microsoft, Internet Explorer, Internet Information Server, DOS, Win 32, Windows,
Windows NT, Windows 95 and Visual Basic are either registered trademarks or
trademarks of Microsoft Corporation in the United States of America and/or other
countries.
Novell is a registered trademark, and NetWare is a trademark, of Novell Incorporated.
All other product or service names mentioned herein are trademarks or registered
trademarks of their respective owners.

Copyright
Copyright 2000 by Centura Software Corporation. All rights reserved.
RDM 5.0 Users Guide
20-7302-1002
May 2000

Contents
Chapter 1 Introduction
1.1
1.2

Overview ....................................................................................................................... 1-1


RDM Documentation ................................................................................................... 1-2
1.2.1
About This Manual .............................................................................................. 1-2
1.2.2
Related RDM Documents ................................................................................... 1-4
1.2.3
Document Conventions....................................................................................... 1-4
1.3
Other Helpful Resources ............................................................................................. 1-5

Chapter 2 Database Concepts


2.1
2.2
2.3
2.4

Introduction................................................................................................................... 2-1
Definitions ..................................................................................................................... 2-1
The Network Database Model .................................................................................... 2-4
Other Database Models ............................................................................................... 2-7
2.4.1
The Hierarchical Database Model...................................................................... 2-8
2.4.2
The Relational Database Model.......................................................................... 2-8
2.5
Advantages of the Combined Model......................................................................... 2-9
2.6
Access Methods in RDM ........................................................................................... 2-10
2.7
Elements of an RDM Database ................................................................................. 2-11

Chapter 3 Operational Overview


3.1
3.2

Introduction................................................................................................................... 3-1
System Components..................................................................................................... 3-1
ddlp ................................................................................................................................ 3-1
initdb .............................................................................................................................. 3-2
RDM Runtime Library ................................................................................................. 3-3
lock manager ................................................................................................................. 3-3
lmclear............................................................................................................................ 3-3
dbclrlb ............................................................................................................................ 3-3
ida ................................................................................................................................... 3-3
dal ................................................................................................................................... 3-3
dbcheck .......................................................................................................................... 3-4
dbedit ............................................................................................................................. 3-4
dbimp ............................................................................................................................. 3-4
dbexp.............................................................................................................................. 3-4
keybuild ......................................................................................................................... 3-4
keypack .......................................................................................................................... 3-4
prdbd.............................................................................................................................. 3-5
console............................................................................................................................ 3-5

Contents

datdump ........................................................................................................................ 3-5


keydump........................................................................................................................ 3-5
db_QUERY .................................................................................................................... 3-5
db_REVISE .................................................................................................................... 3-5
3.3
Operational Flow .......................................................................................................... 3-6
3.4
Introductory Example.................................................................................................. 3-8
3.4.1
Requirements........................................................................................................ 3-8
3.4.2
Database Design................................................................................................... 3-9
3.4.3
Program Design.................................................................................................. 3-12
3.4.4
Program Description ......................................................................................... 3-13
3.5
Directory Structure..................................................................................................... 3-19

Chapter 4 Database Design


4.1
4.2

Introduction................................................................................................................... 4-1
Database Definition Language (DDL) ....................................................................... 4-1
4.2.1
DDL Basics............................................................................................................ 4-1
4.2.2
Database Statement.............................................................................................. 4-3
4.2.3
Timestamp Statement.......................................................................................... 4-4
4.2.4
File Declarations................................................................................................... 4-5
4.2.5
Record Declarations............................................................................................. 4-7
4.2.6
Field Declarations ................................................................................................ 4-9
4.2.7
Set Declarations.................................................................................................. 4-13
4.3
DDL Processor Operation.......................................................................................... 4-16
4.3.1
DDL Processor Execution ................................................................................. 4-16
4.3.2
ddlp Alignment.................................................................................................. 4-20
Nested Structures ....................................................................................................... 4-21
4.3.3
ddlp Alignment in Windows............................................................................ 4-21
4.4
Database Design Considerations .............................................................................. 4-21
4.4.1
Logical Design Considerations......................................................................... 4-22
Use of Keys.................................................................................................................. 4-22
Use of Sets.................................................................................................................... 4-26
Use of Multiple Databases......................................................................................... 4-31
4.4.2
Physical Design Considerations....................................................................... 4-32
RDM File Structure..................................................................................................... 4-32
Record and Key Placement ....................................................................................... 4-33
ddlp File Structure Report......................................................................................... 4-34
File Page Sizes ............................................................................................................. 4-36
4.5
Database Design Example ......................................................................................... 4-36
4.5.1
Introduction ........................................................................................................ 4-36
4.5.2
Requirements...................................................................................................... 4-37
4.5.3
Database Design................................................................................................. 4-38

ii

Centura RDM Users Guide

Chapter 5 Database Manipulation


5.1
5.2

Introduction................................................................................................................... 5-1
Database Control .......................................................................................................... 5-2
5.2.1
Opening and Closing Databases ........................................................................ 5-4
5.2.2
Operational Environment ................................................................................... 5-4
Path Specification in d_open....................................................................................... 5-5
Environment Variables ................................................................................................ 5-5
Environment Control Functions ................................................................................. 5-9
Substituting Database Files ....................................................................................... 5-10
5.2.3
Dynamic Database Initialization ...................................................................... 5-11
5.2.4
Runtime Control................................................................................................. 5-12
Maximum Open Files................................................................................................. 5-12
Size of Runtime Cache ............................................................................................... 5-13
Option Settings ........................................................................................................... 5-14
5.3
Currency Tables.......................................................................................................... 5-15
5.4
Data Retrieval.............................................................................................................. 5-18
5.4.1
Data Retrieval Using Keys ................................................................................ 5-19
5.4.2
Data Retrieval Using Sets.................................................................................. 5-23
5.4.3
Direct Access Retrieval...................................................................................... 5-31
5.5
Data Creation .............................................................................................................. 5-34
5.6
Data Modification....................................................................................................... 5-38
5.7
Data Deletion............................................................................................................... 5-39
5.8
Database Error Reporting.......................................................................................... 5-42
5.9
Multiple Database Access.......................................................................................... 5-44
5.9.1
Opening Multiple Databases ............................................................................ 5-44
5.9.2
Accessing Multiple Databases.......................................................................... 5-45
5.10 Context Switching ...................................................................................................... 5-47
5.11 International Character Sets ...................................................................................... 5-50

Chapter 6 Transaction Processing


6.1
6.2
6.3
6.4
6.5

Introduction................................................................................................................... 6-1
Operational Environment............................................................................................ 6-2
Transaction Processing Functions .............................................................................. 6-3
Transaction Processing ................................................................................................ 6-4
Database Recovery ....................................................................................................... 6-5
6.5.1
External Recovery ................................................................................................ 6-6
6.5.2
Automatic Recovery ............................................................................................ 6-6
6.6
Archive Logging ........................................................................................................... 6-7

Chapter 7 Multi-User Database Control


7.1
7.2

Introduction................................................................................................................... 7-1
Operational Environment............................................................................................ 7-3

Contents

iii

7.3

File Locking ................................................................................................................... 7-4


7.3.1
Introduction .......................................................................................................... 7-4
7.3.2
Read Locks ............................................................................................................ 7-8
7.3.3
Write Locks ........................................................................................................... 7-9
7.3.4
Exclusive Locks .................................................................................................... 7-9
7.3.5
Upgrading/Downgrading of File Locks......................................................... 7-10
7.3.6
Grouped Lock Requests .................................................................................... 7-10
7.3.7
Lock Status Functions........................................................................................ 7-11
7.3.8
Static Records ..................................................................................................... 7-12
7.4
Timestamping ............................................................................................................. 7-12
7.4.1
Introduction ........................................................................................................ 7-12
7.4.2
Implementation .................................................................................................. 7-13
7.5
Advisory Record Locks.............................................................................................. 7-17
7.6
Program Design Considerations............................................................................... 7-18
7.6.1
Basic Guidelines ................................................................................................. 7-18
7.6.2
Data Entry ........................................................................................................... 7-19
7.6.3
Data Deletion ...................................................................................................... 7-21
7.6.4
Data Modification .............................................................................................. 7-22
7.6.5
Data Retrieval ..................................................................................................... 7-24
7.6.6
Other Considerations ........................................................................................ 7-27
7.7
One User Mode........................................................................................................... 7-27

Chapter 8 Interactive Database Access Utility (ida and wida)


8.1

iv

Using ida........................................................................................................................ 8-1


8.1.1
The ida Utility....................................................................................................... 8-1
8.1.1.1
Accessing ida ............................................................................................... 8-1
8.1.1.2
The ida Main Menu..................................................................................... 8-2
8.1.1.3
Using ida: Concepts and Procedures........................................................ 8-3
8.1.2
Using the Main Menu Commands .................................................................... 8-6
Open command....................................................................................................... 8-6
Access command..................................................................................................... 8-6
Initialize command ................................................................................................. 8-7
Close command....................................................................................................... 8-7
Parameters command............................................................................................. 8-7
Quit command ........................................................................................................ 8-8
8.1.3
Entering and Modifying Records....................................................................... 8-8
8.1.3.1
Accessing the Display/Edit Record Submenu........................................ 8-8
8.1.3.2
Using the Display/Edit Record Submenu Commands.......................... 8-9
Edit command ......................................................................................................... 8-9
Init command .......................................................................................................... 8-9
Next command........................................................................................................ 8-9
Prev command ...................................................................................................... 8-10
Write command..................................................................................................... 8-10
Centura RDM Users Guide

Store_key command ............................................................................................. 8-10


Delete_key command ........................................................................................... 8-10
Owner command .................................................................................................. 8-10
Connect command................................................................................................ 8-10
8.1.3.3
Editing a Data Field .................................................................................. 8-10
8.1.3.4
Using Edit Modes and Field Edit Commands....................................... 8-11
8.1.4
Using the Access Menu Commands................................................................ 8-13
8.1.4.1
Using the Access Record Commands..................................................... 8-14
Keyscan command................................................................................................ 8-14
Get command ........................................................................................................ 8-16
Enter command..................................................................................................... 8-16
Modify command ................................................................................................. 8-16
Delete command ................................................................................................... 8-16
Recscan command ................................................................................................ 8-16
8.1.4.2
Using the Access Set Commands............................................................ 8-17
Scan command ...................................................................................................... 8-17
Owner command .................................................................................................. 8-17
First command....................................................................................................... 8-17
Next command...................................................................................................... 8-18
Last command ....................................................................................................... 8-18
Prev command ...................................................................................................... 8-18
Connect command................................................................................................ 8-18
Discon command .................................................................................................. 8-18
Total command ..................................................................................................... 8-18
8.1.4.3
Using the Access Currency Commands................................................. 8-18
Owner command .................................................................................................. 8-18
Member command................................................................................................ 8-19
Record command .................................................................................................. 8-20
Auto_set command............................................................................................... 8-20
Display command................................................................................................. 8-20
Timestamp command........................................................................................... 8-21
8.1.4.4
Using the Access Transaction Commands............................................. 8-21
Begin command .................................................................................................... 8-21
End command ....................................................................................................... 8-21
Abort command .................................................................................................... 8-22
8.1.4.5
Using the Access Lock Commands......................................................... 8-22
Record command .................................................................................................. 8-22
Set command ......................................................................................................... 8-22
Key command ....................................................................................................... 8-22
Current command................................................................................................. 8-22
Timeout command................................................................................................ 8-22
Display command................................................................................................. 8-23
8.1.4.6
Using the Access Free Commands.......................................................... 8-23
Contents

Record command .................................................................................................. 8-23


Set command ......................................................................................................... 8-23
Key command ....................................................................................................... 8-23
All command ......................................................................................................... 8-23
Current command................................................................................................. 8-23
8.1.4.7
Using the Access Miscellaneous Commands ........................................ 8-24
Files command ...................................................................................................... 8-24
Locks command .................................................................................................... 8-24
8.1.5
Cross-Referencing RDM Functions to ida Commands ................................. 8-25
8.2
Using wida .................................................................................................................. 8-28
8.2.1
About the wida Utility ...................................................................................... 8-28
8.2.1.1
About Common Dialog Boxes................................................................. 8-28
Records Dialog Box .................................................................................................... 8-28
Current Record Dialog Box ....................................................................................... 8-28
8.2.2
Using the File Menu Commands ..................................................................... 8-30
Open Database ............................................................................................................ 8-31
Close Database ............................................................................................................ 8-31
Incremental Open ....................................................................................................... 8-31
Incremental Close ....................................................................................................... 8-31
Database Number....................................................................................................... 8-31
Initialize Database ...................................................................................................... 8-31
Destroy Database........................................................................................................ 8-32
Quit............................................................................................................................... 8-32
8.2.3
Using the Key Menu Commands..................................................................... 8-32
Scan............................................................................................................................... 8-32
First............................................................................................................................... 8-33
Last ............................................................................................................................... 8-33
Next .............................................................................................................................. 8-33
Previous ....................................................................................................................... 8-33
Delete ........................................................................................................................... 8-33
Exist .............................................................................................................................. 8-33
Store.............................................................................................................................. 8-34
Keybuild ...................................................................................................................... 8-34
8.2.4
Using the Set Menu Commands ...................................................................... 8-34
Scan............................................................................................................................... 8-34
First............................................................................................................................... 8-35
Last ............................................................................................................................... 8-35
Next .............................................................................................................................. 8-35
Previous ....................................................................................................................... 8-35
Owner .......................................................................................................................... 8-35
Connect ........................................................................................................................ 8-35
Disconnect ................................................................................................................... 8-35
Members ...................................................................................................................... 8-36
vi

Centura RDM Users Guide

Is Owner?..................................................................................................................... 8-36
8.2.5
Using the Record Menu Commands ............................................................... 8-36
Scan............................................................................................................................... 8-36
First............................................................................................................................... 8-37
Last ............................................................................................................................... 8-37
Next .............................................................................................................................. 8-37
Previous ....................................................................................................................... 8-37
Enter new record ........................................................................................................ 8-37
Modify.......................................................................................................................... 8-37
Delete ........................................................................................................................... 8-38
Disconnect & Delete ................................................................................................... 8-38
8.2.6
Using the Currency Menu Commands ........................................................... 8-38
Set Current Owner ..................................................................................................... 8-39
Set Current Member................................................................................................... 8-39
Set Current Record ..................................................................................................... 8-39
Display Timestamp Status......................................................................................... 8-39
Display Currency Tables ........................................................................................... 8-39
8.2.7
Using the Transactions Menu Commands ..................................................... 8-40
Begin............................................................................................................................. 8-40
End ............................................................................................................................... 8-40
Abort ............................................................................................................................ 8-40
8.2.8
Using the Locks Menu Commands ................................................................. 8-40
Lock Types................................................................................................................... 8-41
Free Types ................................................................................................................... 8-41
Set Record Lock Bit..................................................................................................... 8-41
Clear Record Lock Bit ................................................................................................ 8-42
Test Record Lock Bit................................................................................................... 8-42
Display Lock Status.................................................................................................... 8-42
8.2.9
Using the Special Menu Commands ............................................................... 8-42
Cache Pages................................................................................................................. 8-42
File Handles................................................................................................................. 8-42
Close Handles ............................................................................................................. 8-43
TAF and LOG File Paths............................................................................................ 8-43
Lock Manager ............................................................................................................. 8-43
8.2.10 Using the Options Menu................................................................................... 8-43
Closefiles...................................................................................................................... 8-44
Delete Chain ................................................................................................................ 8-44
Delete Log.................................................................................................................... 8-44
Ignorecase.................................................................................................................... 8-44
Prealloc......................................................................................................................... 8-44
Readonly ...................................................................................................................... 8-44
Remotesync ................................................................................................................. 8-44
Syncfiles ....................................................................................................................... 8-44
Contents

vii

Transaction Logging................................................................................................... 8-45


TxTest........................................................................................................................... 8-45
8.2.11 Cross-Referencing wida Commands to RDM Functions.............................. 8-45

Chapter 9 RDM Unicode Support


9.1

Unicode Support at the Compiler and OS Level...................................................... 9-1


String Fields in the Database ............................................................................................ 9-1
Definitions ........................................................................................................................... 9-2
Conversion between ANSI and Unicode ........................................................................ 9-2
9.2
RDM 5.0 Implementation ............................................................................................ 9-3
RDM 5.0 on UNIX .............................................................................................................. 9-3
RDM 5.0 on Win32 ............................................................................................................. 9-4
Unicode Data Fields........................................................................................................... 9-5
Function Prototypes........................................................................................................... 9-6
9.3
RDM for Win32............................................................................................................. 9-7
9.3.1
db_QUERY and db_REVISE............................................................................... 9-7
9.3.2
Utilities and Win32 .............................................................................................. 9-8
9.3.3
ddlp and DBD File Compatibility...................................................................... 9-8
9.3.4
The Lock Manager and Win32 ........................................................................... 9-9
Non-Unicode Interfaces..................................................................................................... 9-9
9.4
Other Compatibility Issues........................................................................................ 9-10
9.4.1
Is Compatibility Necessary? ............................................................................. 9-10
9.4.2
Detecting Incompatibilities............................................................................... 9-10
9.5
Unicode Prototypes for Specific Functions ............................................................. 9-11

Chapter 10 File Transfer Utilities (dbimp, dbexp)


10.1 Introduction................................................................................................................. 10-1
10.2 Exporting Data............................................................................................................ 10-3
10.3 Importing Data............................................................................................................ 10-5
10.3.1 Import Program Usage...................................................................................... 10-6
10.3.2 Import Specification Language ........................................................................ 10-7
10.3.3 Data Conversion............................................................................................... 10-21
10.4 Using Export and Import Together........................................................................ 10-22

Chapter 11 Database Access Language (dal)


11.1 Introduction................................................................................................................. 11-1
11.2 Using dal...................................................................................................................... 11-1
11.3 General dal Syntax ..................................................................................................... 11-2
11.4 Differences between dal and C Conventions.......................................................... 11-2
11.5 Supported RDM Functions ....................................................................................... 11-3
11.6 dal-Specific Commands ............................................................................................. 11-4
def_rec, def_fld ................................................................................................................. 11-4
abort ................................................................................................................................... 11-5
viii

Centura RDM Users Guide

curr ..................................................................................................................................... 11-5


exit ...................................................................................................................................... 11-5
input................................................................................................................................... 11-6
print.................................................................................................................................... 11-7
rewind................................................................................................................................ 11-7
schema ............................................................................................................................... 11-8
whileok .............................................................................................................................. 11-8
11.7 dal Limitations ............................................................................................................ 11-9

Chapter 12 Database Editor (dbedit)


12.1 Introduction................................................................................................................. 12-1
12.2 Usage of dbedit ........................................................................................................... 12-1
12.3 Information Display ................................................................................................... 12-2
12.4 Navigation ................................................................................................................... 12-5
12.5 Editing.......................................................................................................................... 12-6
12.5.1 Editing Record Types ........................................................................................ 12-6
12.5.2 Editing Set and Member Pointers .................................................................... 12-6
12.5.3 Editing the Database Address .......................................................................... 12-7
12.5.4 Editing the Optional Key Bits........................................................................... 12-7
12.5.5 Editing Page Zero .............................................................................................. 12-7
12.5.6 General Hexadecimal Editing .......................................................................... 12-7
12.6 Diagnostics .................................................................................................................. 12-9
12.7 Miscellaneous.............................................................................................................. 12-9
12.8 Command Summary................................................................................................ 12-10

Chapter 13 Maintenance Utilities


13.1
13.2
13.3
13.4
13.5
13.6
13.7
13.8
13.9
13.10

Introduction................................................................................................................. 13-1
Formatted Data File Dump Utility (datdump) ....................................................... 13-1
Database Consistency Check Utility (dbcheck) ...................................................... 13-2
Delete Chain Sort Utility (dchain) ............................................................................ 13-3
Database Initialization Utility (initdb) ..................................................................... 13-3
Key File Build Utility (keybuild) .............................................................................. 13-3
Formatted Key File Dump Utility (keydump)........................................................ 13-4
Key File Pack Utility (keypack) ................................................................................ 13-4
Database Dictionary Print Utility (prdbd)............................................................... 13-5
Clear Lock Bit Utility (dbclrlb) ................................................................................. 13-5

Chapter 14 File Formats and Dictionary Tables


14.1 Introduction................................................................................................................. 14-1
14.2 Database File Organization ....................................................................................... 14-1
14.2.1 General File Structure........................................................................................ 14-2
14.2.2 Data File Organization ...................................................................................... 14-3
Database Addresses ................................................................................................... 14-4
Contents

ix

Set and Member Pointers .......................................................................................... 14-5


Data Record Organization ......................................................................................... 14-7
Delete Chain ................................................................................................................ 14-9
14.2.3 Key File Organization...................................................................................... 14-10
Node Structure.......................................................................................................... 14-10
Key Slot Structure..................................................................................................... 14-12
B-Tree Organization ................................................................................................. 14-12
Delete Chain .............................................................................................................. 14-14
14.3 Database Dictionary Table Structure ..................................................................... 14-15
14.3.1 Contents of the Dictionary File....................................................................... 14-16
14.3.2 File Table ........................................................................................................... 14-18
14.3.3 Record Table ..................................................................................................... 14-19
14.3.4 Field Table......................................................................................................... 14-20
14.3.5 Set Table ............................................................................................................ 14-22
14.3.6 Member Table................................................................................................... 14-23
14.3.7 Sort Table .......................................................................................................... 14-23
14.3.8 Compound Key Table ..................................................................................... 14-23
14.3.9 Dictionary Tables Example............................................................................. 14-25
14.3.10 Database Table ................................................................................................. 14-29
14.3.11 Contents of the Header File ............................................................................ 14-30
14.4 Currency Tables........................................................................................................ 14-32
14.5 Source Code Details ................................................................................................. 14-32
14.5.1 Function Prototyping....................................................................................... 14-32
14.5.2 Pascal Calling Conventions ............................................................................ 14-33

Centura RDM Users Guide

Tables
Table 1-1.
Table 3-1.
Table 5-1.
Table 5-2.
Table 5-3.
Table 5-4.
Table 5-5.
Table 5-6.
Table 5-7.
Table 5-8.
Table 6-1.
Table 6-2.
Table 7-1.
Table 7-2.
Table 7-3.
Table 7-4.
Table 7-5.
Table 7-6.
Table 7-7.
Table 7-8.
Table 7-9.
Table 7-10.
Table 8-1.
Table 8-2.
Table 8-3.
Table 8-4.
Table 9-1.
Table 9-2.
Table 12-1.
Table 13-1.
Table 14-1.
Table 14-2.
Table 14-3.
Table 14-4.
Table 14-5.
Table 14-6.

Contents

Document Notational Conventions................................................................. 1-5


RDM Directory Structure................................................................................ 3-20
Database Control Functions ............................................................................. 5-3
Environment Variables and Related Functions ........................................... 5-10
Currency Control Functions........................................................................... 5-17
Data Retrieval Functions................................................................................. 5-18
Data Creation Functions ................................................................................. 5-34
Modification Functions ................................................................................... 5-38
Data Deletion Functions.................................................................................. 5-39
Context Switching Functions.......................................................................... 5-48
Transaction Processing Functions.................................................................... 6-3
Actions of Transaction Processing Functions................................................. 6-4
Two Users Updating a Record ......................................................................... 7-1
Two Users Updating a Record, Using Locks ................................................. 7-2
File Locking Functions ...................................................................................... 7-5
File Lock Types .................................................................................................. 7-7
Read Functions that Do Not Need a Lock ...................................................... 7-8
Timestamp Status Functions .......................................................................... 7-14
Timestamp Status Codes................................................................................. 7-14
Timestamp Currency Functions..................................................................... 7-15
Corresponding Currency Access Functions................................................. 7-15
Record Locking Functions .............................................................................. 7-17
Example Data Field Contents......................................................................... 8-11
ida Field Edit Commands and Descriptions ................................................ 8-12
Function Key Table.......................................................................................... 8-13
File Status Information (From the Miscellaneous Files Command) .......... 8-24
OS Definitions for wchar_t ............................................................................... 9-2
Unicode and ANSI Program Names ............................................................... 9-5
Hex Mode Commands .................................................................................... 12-8
RDM Utilities.................................................................................................... 13-1
Page Zero Contents.......................................................................................... 14-2
Set Pointer Contents ........................................................................................ 14-5
Member Pointer Contents............................................................................... 14-6
Record Contents............................................................................................... 14-7
Key File Node Structure................................................................................ 14-11
Key Slot Structure .......................................................................................... 14-12

xi

Figures
Fig. 2-1.
Fig. 2-2.
Fig. 2-3.
Fig. 2-4.
Fig. 2-5.
Fig. 2-6.
Fig. 3-1.
Fig. 3-2.
Fig. 3-3.
Fig. 4-1.
Fig. 4-2.
Fig. 4-3.
Fig. 4-4.
Fig. 4-5.
Fig. 5-1.
Fig. 5-2.
Fig. 7-1.
Fig. 8-1.
Fig. 8-2.
Fig. 8-3.
Fig. 8-4.
Fig. 8-5.
Fig. 8-6.
Fig. 8-7.
Fig. 8-8.
Fig. 8-9.
Fig. 8-10.
Fig. 8-11.
Fig. 8-12.
Fig. 8-13.
Fig. 8-14.
Fig. 8-15.
Fig. 8-16.
Fig. 8-17.
Fig. 8-18.
Fig. 8-19.
Fig. 8-20.
Fig. 8-21.
Fig. 8-22.

xii

Example of Set Relationships ........................................................................... 2-4


Example of a Schema Diagram ........................................................................ 2-5
Example of a Network Structure ..................................................................... 2-7
Example of a Hierarchical Structure ............................................................... 2-8
Relational DBMS Overhead.............................................................................. 2-9
Network DBMS Overhead................................................................................ 2-9
RDM System Components ............................................................................... 3-2
RDM Operation.................................................................................................. 3-6
Call Structure of the Example Program ........................................................ 3-13
Incorrect Many-to-Many Implementation.................................................... 4-27
Correct Many-to-Many Implementation ...................................................... 4-28
Example Variable-Length Text Implementation ......................................... 4-29
Better Variable-Length Text Implementation .............................................. 4-30
tims Database Schema..................................................................................... 4-38
Example Currency Table ................................................................................ 5-16
Function by_key Operation ............................................................................ 5-28
Multi-User Operational Environment............................................................. 7-3
ida Main Menu................................................................................................... 8-2
Example Selection List ...................................................................................... 8-3
Database Access Commands Menu................................................................. 8-5
Record Manipulation Functions Menu ........................................................... 8-5
Scan and View Records Menu.......................................................................... 8-6
Set RDM Operational Parameters Submenu .................................................. 8-7
An Example Display/Edit Record Screen ...................................................... 8-9
The Display/Edit Record Submenu ................................................................ 8-9
Record Manipulation Functions Submenu................................................... 8-14
Scan and View Record Based on Key Submenu .......................................... 8-14
A Sample Keyscan/Scan Display .................................................................. 8-15
Scan and View Record Based on Database Address Submenu ................. 8-16
Set Manipulation Functions Submenu......................................................... 8-17
Currency Table Manipulation Functions Submenu .................................... 8-18
Change Current Owner of Set Submenu ...................................................... 8-19
Change Current Member of Set Submenu ................................................... 8-19
Change Current Record Submenu................................................................. 8-20
Timestamp Currency Functions Submenu................................................... 8-21
Transaction Processing Functions Submenu................................................ 8-21
Timestamp Currency Functions Submenu................................................... 8-22
Multi-user Set/Record Free Locks Functions Submenu............................. 8-23
Miscellaneous ida Functions Submenu......................................................... 8-24

Centura RDM Users Guide

Fig. 8-23.
Fig. 8-24.
Fig. 8-25.
Fig. 8-26.
Fig. 8-27.
Fig. 8-28.
Fig. 8-29.
Fig. 8-30.
Fig. 8-31.
Fig. 8-32.
Fig. 10-3.
Fig. 12-1.
Fig. 12-2.
Fig. 12-3.
Fig. 14-1.
Fig. 14-2.
Fig. 14-3.
Fig. 14-4.
Fig. 14-5.
Fig. 14-6.
Fig. 14-7.
Fig. 14-8.
Fig. 14-9.
Fig. 14-10.
Fig. 14-11.
Fig. 14-12.
Fig. 14-13.
Fig. 14-14.
Fig. 14-15.

Contents

The Current Record dialog box...................................................................... 8-29


The File Menu................................................................................................... 8-30
The Key Menu .................................................................................................. 8-32
The Set Menu.................................................................................................... 8-34
The Record Menu............................................................................................. 8-36
The Currency Menu ........................................................................................ 8-38
The Transactions Menu................................................................................... 8-40
The Locks Menu............................................................................................... 8-41
The Special Menu............................................................................................. 8-42
The Options Menu ........................................................................................... 8-43
Family Tree Schema....................................................................................... 10-14
Display of Current Record.............................................................................. 12-3
Show Record Info............................................................................................. 12-4
Show Set Has_published ................................................................................ 12-4
Units of an RDM Database ............................................................................. 14-2
Page Zero .......................................................................................................... 14-3
RDM File Structure.......................................................................................... 14-3
Database Address ............................................................................................ 14-4
Set Pointer......................................................................................................... 14-5
Member Pointer ............................................................................................... 14-6
Three Member Set Instance ............................................................................ 14-6
Physical Structure of Set Instance.................................................................. 14-7
Physical Record Organization ........................................................................ 14-8
Example Data File Delete Chain .................................................................. 14-10
B-Tree Node.................................................................................................... 14-11
Key Slot ........................................................................................................... 14-12
Example B-Tree .............................................................................................. 14-13
Example Key File Delete Chain.................................................................... 14-15
Dictionary Table Interrelationships............................................................. 14-28

xiii

Chapter 1
Introduction
1.1

Overview

The RDM database management system (DBMS) is designed to provide powerful,


flexible, high-performance capabilities for developing C language database applications.
By combining the network and relational model technologies in a single system, RDM
lets you organize and access information efficiently, regardless of the complexity of your
data. This combined technology provides tremendous speed advantages, and minimizes
data redundancy.
RDM is written in the C language, so the applications you create with it are easily ported
to a variety of operating systems, including UNIX and Windows 32-bit. The potential
market for your applications spans from single-user microcomputers and LANs, to minis
and mainframes. Further, complete source code is available to you, so you have full
control over any application you create.
The major features of RDM include:
Multi-user support for local-area networks (LANs) and multi-user computers.
Transaction processing and logging.
Automatic database recovery.
Access methods based on the network and relational database models.
A Database Definition Language patterned after C, for defining the content and
structure of an RDM database.
Multiple database access. More than one database can be opened and accessed at
a time from an application program.
Incremental opens and closes of multiple databases.
Interactive and batch database access utilities, for easy manipulation of the information in an RDM database.
File transfer utilities for importing and exporting data between ASCII and Unicode
text files and an RDM database.
Ability to use multiple volumes for data storage.
A database consistency check utility for reporting problems with database
integrity.
Virtual memory disk caching, for fast database access.
A runtime library of over 130 functions, for complete database control.
Introduction

1-1

Royalty-free runtime distribution.


Three companion products accompany our database engine and complete the RDM
database development system:
db_QUERY is an SQL-based, C-linkable, ad-hoc query system for RDM databases.
It provides relational queries to network model RDM databases, thus combining
the easy-to-use relational model with the highly efficient network database model.
db_REVISE is a tool for incorporating database design revisions into existing RDM
databases, without requiring you to write a conversion program or export and
import the database. db_REVISE is one of the most sophisticated database
restructuring tools available, allowing you to make virtually any kind of database
revision.
Centura ROM is a class library written in C++. It provides persistence to C++
classes through inheritance, and is a fully reentrant interface.

1.2

RDM Documentation

RDM documentation is a three-manual set and includes this Users Guide, the RDM
Reference Manual and the RDM Multi-User Guide. Companion books for supporting
utility products are the db_QUERY Users Guide, db_REVISE Users Guide, and the ROM
manuals. The full set is provided in PDF format and in hard copy by separate order.
This volume, the RDM Users Guide, contains general information and examples on the
use of the system.

1.2.1 About This Manual


The Users Guide is organized as described below.
Chapter 1 is introductory.
Chapter 2, "Database Concepts," should be read by everyone, regardless of the extent of
their database background. It presents basic RDM database concepts, such as definitions
of the database terminology used in this manual, a description of the network database
model and the differences between it and the relational model, and an explanation of the
elements of an RDM database.
Chapter 3, "Operational Overview," gives an overview of each of the components of an
RDM DBMS. It describes the general operational flow for creating an RDM application
program, and provides a simple (but complete) introductory example.
Chapter 4, "Database Design," describes in detail RDMs Database Definition Language
(DDL) and the operation of the DDL processor. It also explains how to design an RDM
database, and includes an example of database design that illustrates some of the more
commonly used structures.

1-2

Centura RDM Users Guide

Chapter 5, "Database Manipulation," explains the use of RDM runtime functions for
controlling, accessing, and manipulating a database from a C application program.
Chapter 6, "Transaction Processing," describes transaction processing functions and tells
you how to use transactions in a single- or multi-user environment. This chapter will
help you design transactions that meet the needs of your application.
Chapter 7, "Multi-User Database Control," describes the use of RDM in multi-user,
shared database applications. Basic multi-user concepts are presented, as is a detailed
description of RDMs multi-user implementation. Chapter 7 also explains how to use the
runtime multi-user control functions to efficiently synchronize shared database access.
Chapter 8, "Interactive Database Access Utility (ida and wida)," provides complete
information on the use of the command line ida utility for UNIX users, and the menudriven Windows version called wida.
Chapter 9, "RDM Unicode Support" explains the use of the Unicode features and how
RDM incorporates this character encoding standard.
Chapter 10, "File Transfer Utilities (dbimp and dbexp)," describes the utilities used for
transferring data between an RDM database and ASCII text.
Chapter 11, "Database Access Language (dal)," describes a tool for accessing a database
interactively or in batch mode. dal uses the RDM runtime library functions, plus a few
information and control commands. It is an excellent educational tool.
Chapter 12, "Database Editor (dbedit)," contains a description of the low-level database
editing utility, which allows viewing and changing a database at the "bits and bytes"
level. The database editor is the ultimate database repair program.
Chapter 13, "Maintenance Utilities," provides information on the use of the following
utilities: database initialization utility (initdb), database consistency check utility
(dbcheck), delete chain sort utility (dchain), key file build utility (keybuild), dictionary
print utility (prdbd), formatted data file dump utility (datdump), key file packing utility
(keypack), formatted key file dump utility (keydump), and the clear lock bit utility
(dbclrlb).
Chapter 14, "File Formats and Dictionary Tables," provides detailed information on RDM
data and key files, and on the structure and organization of the RDM dictionary.
The Glossary defines a number of database terms used in this manual and the other
books of the RDM set.

Introduction

1-3

1.2.2 Related RDM Documents


RDM Reference Manual contains detailed descriptions of RDM API functions, function
prototypes, utilities, and return codes and error messages.
RDM Multi-User Guide describes operation of the lock manager (a centralized file lock
and recovery manager) and provides details about the various operating environments
supported by this release.
Each of the RDM companion products has accompanying documentation.
db_QUERY Users Guide describes how to create relational ad hoc queries for RDM
databases.
db_REVISE Users Guide explains how to incorporate database design revisions into
existing RDM databases.
ROM Users Guide fully describes RDMs C++ interface. ROM Reference Manual
defines all the C++ classes in detail and provides practical code examples.
RDM system components are furnished on a CD. The CD includes a readme.txt file that
contains the release notes for your particular operating environment. Be sure to read this
file carefully. It provides detailed information about:
Recent changes to the system that are not documented in the current manuals.
Issues specific to your particular operating system or compiler.

1.2.3 Document Conventions


Table 1-1 describes the notational conventions used in this guide.

1-4

Centura RDM Users Guide

Table 1-1. Document Notational Conventions


Convention

Description

Bold Text

Indicates the names of functions, commands, data structures,


statements, databases, utilities, files, etc. Note that the case
distinctions used in the names are not significant for all
operating systems.

Italic Text

Represents the names of variables, such as parameters and


command options. The RDM documents also use italics for
the names of books.

Courier Text

Indicates a programming example or a command line entry.


Programming examples in this book are enclosed in boxes.

Brackets ([ ])

Indicate optional fields or parameters in command lines and


syntax statements.

Bar Symbol (|)

Separates alternative selections. You should enter one of the


items separated by the bar.

Ellipsis (...)

Indicates that you can repeat the preceding item. Both


horizontal and vertical ellipses are used in programming
examples to indicate omitted code.

Arrow Symbols (< >)

Indicate information that you must supply. For example,


<filename>.h represents a header file that you name. Arrow
symbols are also used in text to set off keyboard key names,
as in <Ctrl>.

1.3

Other Helpful Resources

Centura offers various options for additional information on RDM.


Centura Books Online
The Centura RDM document set is available online. This document collection lets
you perform full-text indexed searches across the product document set, navigate the
table of contents using the expandable/collapsible browser, or print any chapter.
Access the collection by going to the CD, navigating to the Book Set folder, and
opening the PDF file listed in that directory.
Worldwide Web
The Centura Worldwide Web home page is located at http://www.centurasoft.com.
The Centura web server provides access to a wealth of information about Centura
products and services.

Introduction

1-5

Chapter 2
Database Concepts
2.1

Introduction

This chapter presents the basic database concepts of the RDM system. The database
terms used in this manual are defined in section 2.2. The network database model, which
forms the basis of the RDM system, is described in section 2.3. Section 2.4, "Other
Database Models," describes the hierarchical and relational database models. Section 2.5
describes the advantages of the network model over the relational database model.
Specific elements of an RDM database are described in the final section.
To use RDM productively, you need to understand RDM database concepts. This
chapter intends to provide sufficient information for a database novice to use RDM
effectively. As part of our efforts to familiarize you with database concepts, we have
provided a Glossary of database terms at the end of this manual.

2.2

Definitions

The basic unit of information in a database is a field. A field (or data field) is an item of
data with attributes such as name, type (for example, a character or an integer), and
length. Examples of fields are employee name, date of birth, social security number, inventory item code, and serial number. Other database systems or books may use other
terms (such as attribute, entity, or column) for field.
A record is a named collection of related fields, which are stored and accessed as a unit.
Other database systems or books may use other terms (such as table or file) for record.
For example, a record named check in a checking account database may have the
following fields:
date
check number
paid to
amount
Each occurrence (or instance) of a check record in the database contains a value for each
of these fields. The definition of a record (made up by its fields) is called the record type
and is similar to Pascal or COBOL records and C or PL/1 structures.
All occurrences of a particular record type are stored in an operating system file. Files
are the primary physical storage units of database organization. A database, therefore, is
a collection of related files.
Database Concepts

2-1

A key is a field through which rapid or sorted access to a record is possible. In the check
record, you might define check number as a key field, to allow quick retrieval of a check
record occurrence through specification of a check number.
An index is a file containing only keys. It is synonymously referred to as a key file. The
index to this manual demonstrates the features of a key file: the individual subject
entries in the index are the "keys," while the page where the subject is discussed is
analogous to the associated "records." You can find the page that discusses a desired
subject much more quickly by using the index than by reading through each page. And,
because the keys are sorted in the index, you can quickly find a specific key. Key files are
similar, except the computer does the sorting and look-ups for you. To maintain its key
files, RDM uses the B-tree method, one of the most efficient techniques for implementing
an index.
In a key scan operation, the keys in an index are read in the order they appear. Key scans
are used to produce sorted listings of records and for fast search operations requiring
inspection of a large number of record occurrences (for example, retrieving all checks
entered between two dates).
Data relationships often exist between record types. For example, the checking account
database may include budget categories. A second record type named budget could be
defined with the following data fields:
budget code (a key field)
category description
monthly allocation
balance
To associate a particular budget category with each check record, we add a budget code
field to the check record type, forming a relationship between the budget record and the
check record. Whenever a check is entered, the related budget record is located via the
budget code, and the balance for that budget is updated by the amount specified in the
check record.
The schema is the conceptual definition of the content and organization of a database. A
schema will include the definitions of all record types, with their fields and keys. The
form of the schema used by the DBMS is called the dictionary. In RDM (and most other
DBMSs) a Database Definition Language, or DDL, specifies the schema. An RDM DDL
specification for the checking account database is shown below. The specifics of the
actual DDL statements are explained in Chapter 4, "Database Design."

2-2

Centura RDM Users Guide

database ckngacct {
data file "chkng.dat" contains budget, check;
key file "chkng.key" contains code, check_no;
record budget {
key char code[6];
char cat_desc[48];
float allocation;
float balance;
}
record check {
key int check_no;
int check_date;
char bud_code[6];
char paid_to[48];
float amount;
}
}

A data model (or database model) is a conceptual representation of inter-record relationships. The relational database model establishes and maintains inter-record relationships
through common data fields. For example, in the checking account example a common
data field, budget code, establishes the relationship between the budget record and the
check record.
Other database models, in particular the network database model, establish inter-record
relationships directly, through physical links between the related records, rather than
through common data fields. These models are discussed in the following sections.
Since RDM supports both the relational and the network database models, you can
combine the features of these models to meet the needs of your particular application.

Database Concepts

2-3

2.3

The Network Database Model

In the network database model, the relationships between record types are explicitly
defined and directly maintained through sets. A set defines a one-to-many relationship
between two record types. Examples of sets are:
one baseball league has many teams
one baseball team has many players
Sets are implemented with linked lists of pointers to the record locations of the set
members and owners. The result is a network of interconnected records.
Figure 2-1 illustrates the set relationships for the baseball example. The boxes represent
instances of the league, team, and player record types. The arrows represent the links
that connect the related records.
American League West
League: Team set
Team: Player set
Seattle Mariners
K. C.

94
Royals
Texas

68
89
Rangers

73
83

79

Bradley, Scott
Brett, George
Davis, Alvin
Griffy, Jr.

Jackson, Bo
Tartabull, Danny

Reynolds, Harold
Wilson, Willie

Fig. 2-1. Example of Set Relationships

2-4

Centura RDM Users Guide

Schema diagrams are used to illustrate graphically the inter-record relationships of the
database design. Figure 2-2 shows the schema diagram for the baseball example. In this
diagram (and in all other schema diagrams in this manual), the boxes represent record
types and the arrows represent set types. The league_team set forms a one-to-many
relationship between the league record type (called the owner of set league_team) and
the team record type (called the member of set league_team). The team_player set forms
a one-to-many relationship between the team record type and the player record type.

LEAGUE

LEAGUE is the owner


of the LEAGUE_TEAM
set.

LEAGUE_TEAM
Boxes
represent
records.
Arrows
represent
sets.

TEAM

TEAM is the member of the


LEAGUE_TEAM set and
the owner of the
TEAM_PLAYER set.

TEAM_PLAYER

PLAYER

PLAYER is the member


of the TEAM-PLAYER
set.

Fig. 2-2. Example of a Schema Diagram

Database Concepts

2-5

In the checking account example discussed earlier, the relationship between the budget
and check record types could be specified using a set called transactions, defining a oneto-many relationship between a budget record (owner) and the check records (members)
written against a particular budget category. In this case, the bud_code field in the check
record would not be defined in the check record type, as it is redundant. The RDM DDL
would be modified as follows:
database ckngacct {
data file "chkng.dat" contains budget, check;
key file "chkng.key" contains code, check_no;
record budget {
key char code[6];
char cat_desc[48];
float allocation;
float balance;
}
record check {
key int check_no;
int check_date;
char paid_to[48];
float amount;
}
set transactions {
order last;
owner budget;
member check;
}
}

2-6

Centura RDM Users Guide

Any given record type can be the owner of any number of different sets and also a
member of any number of different sets. Thus, network structures like that shown in
Figure 2-3 are valid.

Fig. 2-3. Example of a Network Structure


Notice that record type E owns itself. Record type C is a member of two sets (A and B)
and itself owns two sets (D and E). Records also can own other records through multiple
sets, as in the case of B owning E. All these are legitimate constructs in RDM.

2.4

Other Database Models

Two other major database models are the hierarchical and relational models. These are
described below.

Database Concepts

2-7

2.4.1 The Hierarchical Database Model


In the hierarchical database model (a subset of the network model) a record type is
allowed to be a member of only one set. Record types can still, however, own more than
one set. The owner is called the parent and the member is called the child.
As in the network model, sets are implemented through linked lists. Figure 2-4 shows an
example of a hierarchical schema structure.

Fig. 2-4. Example of a Hierarchical Structure

2.4.2 The Relational Database Model


The relational database model views the database as a set of two-dimensional tables (or
relations). The columns (also called attributes) of a table correspond to data fields, and
the rows of the table correspond to record occurrences. This tabular view of a database is
particularly easy to manipulate with standard relational database operations, which are
based on mathematical set theory.
In the relational model, relationships between tables are usually established through
common data fields. Recall from the initial checking account example that the relationship between the budget and check records was formed by including in the check record
a budget code field to identify the budget category.
The principal distinction between the relational and network models is that in the relational model, relationships are formed through common data fields between the related
record types, while in the network model those relationships are defined directly.
Note that it is possible to transform databases from relational to network and from network to relational.

2-8

Centura RDM Users Guide

2.5

Advantages of the Combined Model

Relational model database systems have been extremely popular, primarily because the
simplicity of the underlying data model makes them easy to use. With the network
model, the primary benefits are better performance, reduced storage requirements, and
greater assurance of data integrity. Consider the diagram in Figure 2-5.

Table 1

Index

A B C

Table 2

C D E

Fig. 2-5. Relational DBMS Overhead


This diagram shows two tables that are related through a common data field, C. Note
that C must be defined in both tables and that an index must exist in order to access the
related table 2 occurrences. Contrast this with the corresponding network model diagram in Figure 2-6.

Record 1

A
B

Set
Pointer

Record 2

D
E

C
Fig. 2-6. Network DBMS Overhead

Database Concepts

2-9

The network model eliminates data redundancy by relating the two record types directly,
without requiring the duplicate field and index file. Moreover, the related record is
accessed directly with one database read operation, where the relational model forces
you to read first an index and then the related record.
For those situations where an index is more efficient, RDM provides you with that
option. With RDM, network access and indexed access are independent methods, so you
can combine them to suit the needs of your particular application. Combining these
technologies gives you maximum database design flexibility.

2.6

Access Methods in RDM

We have already discussed two access methods available in RDM: indexes and sets. A
third method is called sequential access. All three methods can be used together for
navigating and searching in a database. Each has its own ways of establishing and
changing a position in the database. The methods are nearly orthogonal, meaning that
the use of one will not disrupt the use of the others. The one value they share is the
current record, which points to the record in the database that has been found most recently. The current record is the default object for many of the RDM functions. All three
access methods set the current record.
The indexed method allows you to find a record occurrence by supplying a key. The key
can be an exact match, in which case you are positioned directly on a record, or a near
match, which will position you just before the record containing a key value higher in the
collating sequence. You can also position yourself to the first or last keys of a given key
type, regardless of their values. Once at a position, you can move to the previous or next
key in the collating sequence. The keys are maintained and navigated in the order
maintained in the index, regardless of the physical order of the records to which they
point.
The set method allows you to move through set connections in various directions. You
can move from the owner of a set instance to the first or last member of the set. From a
set member, you can move to the next or previous member record, or to the owner
record. During the navigation of sets, positions are established on a per-set basis: the
current owner and current member is indicated for each set type that has been used. If
defined, a system record can be used as the entry point into a database. When the
database is opened, the system record is the current owner of all sets owned by the
system record.
The sequential method allows you to find the first, last, next, or previous physical
instance of a given record type. RDM does not allow the programmer to insert records at
specific physical positions in a file. Their insertion is normally at the end of a file, but this
is not guaranteed if you are using the delete chain (see the entry on Option Settings in
section 5.2.4, "Option Settings," of Chapter 5). The sequential method is useful when you
are searching all records of a given type, but do not care about the order.

2-10

Centura RDM Users Guide

2.7

Elements of an RDM Database

An RDM database consists of:


A dictionary, which stores information describing the content and organization of
the database
Data files, which contain occurrences of one or more record types
Key files, which contain an index for one or more key fields
Records contain data fields, key fields, and set linkages (which are transparent to the
user). They can be accessed through set navigation (that is, traversing through the linked
lists associated with specific sets), through key fields (using a fast look-up of the index),
sequentially, or through a combination of all three methods.
Details relating to these elements are fully discussed in Chapters 4 and 5, "Database
Design," and "Database Manipulation" respectively.

Database Concepts

2-11

Chapter 3
Operational Overview
3.1

Introduction

This chapter presents an overview of the basic operation of the RDM DBMS. Each
system component is identified and described, and the operational flow of an RDM C or
C++ program is given. A simple, introductory example is then developed illustrating the
basic use of the system. Your understanding of what each component does and how it
fits into the overall system is essential to your ability to use RDM effectively. (Note that
RDM does provide support for Unicode. For information about this feature, see Chapter
9.)

3.2

System Components

Figure 3-1 is a diagram of all of the RDM system components. Arrows indicate input and
output between the components and text files (for example, schema), specific file types in
the database (for example, key files), or the database in general.

ddlp
The Database Definition Language Processor, ddlp, is a utility that compiles a DDL
specification, called a schema, and produces the database dictionary. The dictionary contains database content and organization data that is used by the RDM runtime library
functions (see below).
A C or C++ header file (not shown in Figure 3-1) also is created by the ddlp. This file
contains constants and declarations associated with a specific database for use by the C
or C++ programs that access the database.

Operational Overview

3-1

Currency manipulations

B-Tree Functionality

Set Navigation Made Easy

Task functions

C Program

Runtime
Library

initdb

Schema

RDM
Database

db_QUERY

ddlp

prdbd

db_REVISE

Dictionary
dal
ida

dbimp

TAF
lockmgr

ASCII

lmclear

Log Files
console
dbexp
keypack
ASCII

Key Files

keydump
keybuild

dbcheck

dbclrlb
dbedit

Data Files

datdump

dchain

Fig. 3-1. RDM System Components

initdb
The initialization of the data and key files for a new database is performed by the database initialization utility, initdb.

3-2

Centura RDM Users Guide

RDM Runtime Library


Database manipulation and control is performed through calls to C functions contained
in the RDM runtime library. The library is linked with the object code for a C or C++
database application program to produce the executable program.
The runtime library functions contained in the library perform such operations as opening and closing the database, creating and modifying records and fields, connecting and
disconnecting sets, searching for records through keys and sets, and controlling multiuser access through interaction with the system lock manager.

lock manager
Management of system-wide multi-user lock information and database recovery control
is performed by the RDM lock manager. The lock manager runs as a background task
under the UNIX or QNX operating systems. Under Windows, the lock manager runs in a
separate window.
All multi-user RDM programs communicate with the lock manager to request
permission to access data and key files contained in an RDM database.

lmclear
lmclear is a utility used to clear a database user process that has failed or terminated
without having properly closed a database. The actual effect of the operation depends
upon the operating environment but, in general, lmclear informs the lock manager of the
failed condition (when the lock manager cannot get this information from the operating
system on its own) so that certain user tables maintained by the lock manager can be
properly cleared.

dbclrlb
The clear lock bit utility, dbclrlb, clears any set record lock bits in the specified data files.
It is usually considered to be an error for these advisory record instance locks to remain
set after the application terminates.

ida
The Interactive Database Access utility, ida, is a menu-driven database manipulation tool
that provides an easy-to-use interface for entering, modifying, and retrieving database
information through most of the RDM functions.
The ida utility is a useful tool for learning to use RDM as well as a tool for maintaining
existing databases.

dal
The Database Access Language, dal, is a simple, interpreted language that includes most
of the RDM user-level functions as its commands. With built-in variables and a looping

Operational Overview

3-3

construct, it allows quick prototyping of simple sequences of RDM function calls. In


addition, a database programmer can learn more about RDM by using dal.

dbcheck
The consistency of an RDM database can be checked using the dbcheck utility. This
utility checks to ensure that data and key files are consistent and that all set linkages are
correct. Thus, dbcheck is used to check for database corruption.

dbedit
The dbedit utility is a low-level database editor that allows a skilled developer to change
an RDM data file. It interprets the database dictionary, but does not perform a formal
database open. Editing of all portions of all records is allowed.

dbimp
Data from ASCII text files can be imported into an RDM database using the dbimp
utility. This utility is able to create, store, and form set connections involving one or
more record types from data in a standard ASCII format.
The dbimp utility is useful in setting up test data, transporting RDM data between
systems, importing data from another DBMS, and, in conjunction with dbexp,
performing ASCII file dumps and reloads of an RDM database.

dbexp
The database export utility, dbexp, is used to output the contents of an RDM database
into a standard ASCII format. The exported data can then be used by another DBMS.
You may also use dbexp with dbimp to transfer a database to a different environment or
for performing an ASCII file dump and reload.

keybuild
Utility keybuild is used to recreate key (index) files from the contents of data files. It is
useful for implementing DDL changes where non-key fields are changed to key fields or
key fields are changed to non-key fields. It can also be used to rebuild the key files after
a database corruption (for example, as reported by dbcheck).

keypack
The Key File Packing utility can be used to decrease the size of existing key files. This
utility is designed especially for large, static key files which will require very little or no
modification after they are packed. The keypack utility places as many keys as possible
into each B-tree node so that the key file is smaller and lookups are quicker. However,
modification of the key file after it has been packed becomes a very expensive operation.

3-4

Centura RDM Users Guide

prdbd
The print database dictionary utility, prdbd, prints a formatted report showing the contents of all the dictionary tables for a particular database. This detailed information on
the structure of the dictionary enables you to write database utilities or to perform database maintenance.

console
The console utility will display the lock manager tables. This information can be useful
to system administrators.

datdump
The data file dump utility, datdump, produces a formatted dump of the contents of a
data file. This report shows the data field contents and set linkage pointers for each
record occurrence on a data file. It is primarily for use in performing database maintenance and for learning how data files are organized.

keydump
Similar to datdump, the keydump utility produces a formatted dump of the contents of a
key file. It is primarily for use in performing database maintenance and for learning how
key files are organized.

db_QUERY
db_QUERY is an ad hoc query and basic report writing system based on SQL (IBMs
Structured Query Language). It provides conditional selection and sorting of
information contained in an RDM database. The data is accessed by a db_QUERY
program through a relational view of the network model. This unique approach is faster
than query processing in more traditional relational systems because it reduces the
amount of data that needs to be retrieved. db_QUERY is a C-linkable and royalty-free
library.

db_REVISE
Changes to the structure of an existing database design, such as the addition of new data
fields, record types, and sets, can easily be made using db_REVISE. A wide range of
database structure revisions are supported by db_REVISE, making it one of the most
powerful database restructuring tools available with any DBMS on micro, mini, or even
mainframe computers.

Operational Overview

3-5

3.3

Operational Flow

The basic operational flow for creating an RDM C or C++ application program is shown
in Figure 3-2.
DDL
Specs

ddlp

Dictionary

C Header
File

C Source
File

vista.h

C Compiler

Object
Code

Runtime
Library

Linker

Executable
Program

RDM
Database

Fig. 3-2. RDM Operation


The Database Definition Language specification is submitted to the DDL processor,
which compiles the DDL and creates the database dictionary. The DDL processor also
creates a C or C++ header file of structure, constant, and class declarations for use with
the C or C++ programs that access the database.

3-6

Centura RDM Users Guide

The source code for your C or C++ application program, which includes the header file
created by ddlp and the standard RDM header file (vista.h), is then compiled, and the
resulting object code is linked with the RDM runtime library to create the executable
application program. The RDM library functions called from within the program
manipulate the database content as defined by the dictionary.
The following procedure summarizes the basic steps necessary to create an RDM
application.
1.

Design the database. That is, determine what data is to be stored in the database
and how it should be organized.

2.

Prepare the DDL specification using your usual text editor.

3.

Compile the DDL specification using the DDL processor, ddlp.

4.

Correct any DDL errors reported by ddlp.

5.

Initialize the database using initdb.

6.

Experiment with the database, using dal or ida to create and access some test
data. Refine your database design as necessary.

7.

Design and code your C or C++ application program, incorporating the


appropriate calls to the RDM functions. Your program should include the
vista.h header and the header file created by ddlp.

8.

Compile the C or C++ program.

9.

Link the program with the RDM library to create your executable.

10. If it is a multi-user application, start the lock manager.


11. Run your RDM application program.
The following section illustrates each of these steps by describing the development of a
simple database application.

Operational Overview

3-7

3.4

Introductory Example

This section introduces the use of RDM through the development of a simple database
application. A description of the program requirements is given in the next section. The
database design is then explained followed by the program design. Finally, the program
code is described with particular attention paid to the RDM function calls.

3.4.1 Requirements
The purpose of the example project is to write a program that will maintain a database of
books, magazines (journals), and articles contained in a technical library. Information to
be stored in the database includes:

Identification code: a text field containing a Dewey-Decimal code or other kind of


code to be determined by a user.

Author name: a text field containing the name of the author in "last, first, middle"
format.

Title: a text field containing the title of the book, magazine, or article.

Publisher: a text field containing the name of the publisher.

Date published: a date field containing the copyright date of the publication.

Information type: an integer field containing a code that identifies whether the
information is a book, magazine, or article.

The stored information must be retrievable by either the identification code or author
name. If an author has more than one publication in the library, all of the publications
must be displayed.
User interaction will be performed by using simple text input and output. Five commands will be provided:

Enter technical information

Delete technical information

Find technical information by id code

Find technical information by author

Close database and quit

The commands will be selected from a simple menu.

3-8

Centura RDM Users Guide

3.4.2 Database Design


The database will be composed of one record type which contains the following data
fields:
id_code

15-character field containing the identification code

info_title

79-character field containing the title

author

31-character field containing author name

publisher

31-character field containing publisher name

pub_date

11-character field containing publication date

info_type

Integer code field which identifies the information type


as follows: 0 = book, 1 = magazine, 2 = article

Field id_code will be a unique key field. That is, it will be used to uniquely access a single record occurrence in the database.
The author field will be a non-unique key field. This will provide access to all information records associated with a particular author. This is because keys are maintained in
the index in sorted order and, thus, all duplicate keys will be grouped together.
The RDM DDL that implements this database design (assume it is contained in file
tims.ddl) is given below.
/* Technical Information Management System*/
database tims
{
data file "tims.d01" contains info;
key file "tims.k01" contains id_code;
key file "tims.k02" contains author;
record info
{
unique key char id_code[16];
char info_title[80];
key char author[32];
char publisher[32];
char pub_date[12];
int info_type;
}
}

The first line is a comment that describes the database. As in C, comments are specified
in DDL between "/*" and "*/" pairs. Although comments may be placed throughout the
database definition file, those comments before the keyword database will be copied into
the resulting header file.

Operational Overview

3-9

The database statement names the database. The name chosen here, tims, is an acronym
for "Technical Information Management System."
The DDL file (or schema) defines the database to be composed of one data file, tims.d01,
and two key files, tims.k01 (containing id_code keys) and tims.k02 (containing author
keys).
One record type named info is declared to contain each of the data fields. To accommodate the null byte that terminates strings in C, each character field is one character longer
than specified in the requirements . Note that id_code is identified as a unique key and
that author is identified as a key. (Duplicate keys are allowed unless the unique qualifier
is present).
The schema is compiled with the following command:
ddlp tims.ddl

The ddlp will display the following text:


RDM Version 5.0
Database Definition Language Processor
Copyright (C) 1984-2000 Centura Corporation, All Rights Reserved
Runtime dictionary memory reqts:
file table
: 180
record table : 12
field table : 120
set table
:
0
member table :
0
sort table
:
0
key table
:
0
total

: 312

0 errors detected

The ddlp reports the amount of dynamic memory that will be allocated by the RDM
runtime system for the dictionary.

3-10

Centura RDM Users Guide

Upon successful completion, the ddlp will have created two files. File tims.dbd contains
the database dictionary. File tims.h is the header file to be included in each C source file
using the tims database. The contents of tims.h are shown below.
#ifndef TIMS_H
#define TIMS_H
/* RDM Version: 5.0 */
/* Technical Information Management System*/
/* database tims record/key structure declarations */
struct info {
char id_code[16];
char info_title[80];
char author[32];
char publisher[32];
char pub_date[12];
int info_type;
};
/* record, field and set table entry definitions */
/* File Id Constants */
/* Record Name Constants */
#define INFO 10000
/* Field Name Constants */
#define ID_CODE 0L
#define INFO_TITLE 1L
#define AUTHOR 2L
#define PUBLISHER 3L
#define PUB_DATE 4L
#define INFO_TYPE 5L
/* Set Name Constants */
/* Field Sizes */
#define SIZEOF_ID_CODE 16
#define SIZEOF_INFO_TITLE 80
#define SIZEOF_AUTHOR 32
#define SIZEOF_PUBLISHER 32
#define SIZEOF_PUB_DATE 12
#define SIZEOF_INFO_TYPE 2
#endif

/* TIMS_H */

Operational Overview

3-11

This file contains a struct declaration for the info record. This struct is for use by the
application in declaring variables that contain occurrences of the info record from the
database. Also included in this file are constant definitions for the info record and for
each data field. These constants will be passed to the RDM C functions that require
them.
The next step is to initialize the database with the following command:
initdb tims

RDM will display the following text and, except in the very first initialization, prompt
you for confirmation:
RDM Version 5.0
Database Initialization Utility
Copyright (C) 1984-2000 Centura Corporation, All Rights Reserved
Initialization of database: tims
This will destroy contents of the following files:
tims.d01
tims.k01
tims.k02
continue? (y/n)

A "y" (yes) response will complete the initialization of the database files; the listed files
will be overwritten.

3.4.3 Program Design


The program for this example consists of the following functions.
main

Main program, command menu control

ent_info

Enter technical information data

del_info

Delete technical information data

by_id

Find technical information by id_code

by_author Find technical information by author


get_info

Get technical information data from user

pr_info

Print technical information data

3-12

Centura RDM Users Guide

Figure 3-3 shows the function call structure for the program.

main

ent_info

del_info

get_info

by_id

by_author

pr_info

Fig. 3-3. Call Structure of the Example Program


The RDM runtime library functions to be used in the example are summarized in the
following table. Note that, by convention, all RDM runtime functions begin with a d_
prefix.
d_lockcomm

Select a lock manager communication protocol

d_open

Open a database

d_close

Close a database

d_fillnew

Fill and store a new record occurrence

d_keyfind

Find a key occurrence

d_keynext

Find the next key occurrence

d_keyread

Read a key value

d_recread

Read a record contents

d_delete

Delete a record occurrence

3.4.4 Program Description


The C code for the main program is given below. The first four lines include directives to
incorporate the standard C header file stdio.h, the standard RDM header file vista.h, and
the tims database header file tims.h. The RDM header file contains the constant definitions for the RDM function return status code. The definition of LOCKCOMM_DATA
needs to be done before vista.h is included in one module in your application.
Applications using Microsoft Windows DLLs do not need this line.

Operational Overview

3-13

A variable called irec is a globally declared info structure (declared in tims.h) to be used
by all of the functions for storing info record data.
#include <stdio.h>
#define LOCKCOMM_DATA
#include "vista.h"
#include "tims.h"
struct info irec;
/* Technical Information Management System */
main()
{
char cmd[20]; /* command entry string */
/* Use no lock manager */
d_lockcomm(LMC_NONE);
/* open the "tims" database */
d_open("tims","o");
for ( ; ; )
{
/* display command menu */
printf("\nTIMS Commands:\n");
printf("
1 - Enter technical information\n");
printf("
2 - Delete technical information\n");
printf("
3 - Find technical info by id_code\n");
printf("
4 - Find technical info by author\n");
printf("
q - Quit\n");
printf("enter command: ");
gets(cmd);
switch (cmd[0])
{
case 1: ent_info(); break;
case 2: del_info(); break;
case 3: by_id();
break;
case 4: by_author(); break;
case q: d_close();exit(0);
default :
printf("*** bad command--re-enter\n");
break;
}
}
}

The d_lockcomm call initializes the interface to the lock manager. RDM communicates
with the lock manager using several protocols. These protocols are specific to the
hardware or operating system platform on which your application is running. In this
example we are opening the database in single user mode, so we can specify no lock
manager communication type. For a full explanation of the various lock manager
communication options and issues, see the RDM Multi-User Guide.

3-14

Centura RDM Users Guide

The d_open call requires two arguments. The first argument is the name of the database
to be opened. The second argument (o) indicates that the database is to be opened in one
user mode (that is, only one user will access the database, and the lock manager is not
required). In the single-user version, the second argument is required to be o.
The main program displays the command menu, prompts for and gets a command character from the user, and calls the function associated with the command. If q is entered,
the database is closed (d_close) and execution is terminated (exit).
Function get_info gets the info record data from the user and stores it in variable irec.
Function pr_info displays to the user the contents of irec. These functions are given
below.
/* Fill irec with info data from user*/
int get_info()
{
char txt[40];
printf("author
: ");
if ((gets(irec.author) == NULL) || (irec.author[0] == \0))
return( EOF );
else
{
for ( ; ; )
{
printf("id_code : ");
gets(irec.id_code);
printf("title
: ");
gets(irec.info_title);
printf("publisher: ");
gets(irec.publisher);
printf("pub. date: ");
gets(irec.pub_date);
for ( ; ; )
{
printf("info type: ");
gets(txt);
sscanf(txt, "%d", &irec.info_type);
if ((irec.info_type >= 0) && (irec.info_type <= 2))
break;
printf("invalid - correct types are:\n");
printf("0=book, 1=magazine, 2=article\n");
}
printf("enter data (y/n)? ");
gets(txt);
if ((txt[0] == y) || (txt[0] == Y))
return( 0 );
}
}
}

Operational Overview

3-15

Note that get_info validates the info_type code to ensure that it is 0, 1, or 2. The function
returns EOF whenever gets returns NULL or the user enters only a <Return>.
/* Print technical information record
*/
pr_info()
{
printf("id code : %s\n", irec.id_code);
printf("author
: %s\n", irec.author);
printf("title
: %s\n", irec.info_title);
printf("publisher: %s\n", irec.publisher);
printf("pub date : %s\n", irec.pub_date);
printf("info type: ");
switch (irec.info_type)
{
case 0: printf("book\n");
break;
case 1: printf("magazine\n"); break;
case 2: printf("article\n"); break;
}
}

Function pr_info interprets the info_type code to display "book", "magazine", or "article."
Function ent_info (below) repeatedly calls get_info until EOF is returned and then calls
the RDM function d_fillnew to fill and store a new occurrence of the info record from
the contents of irec. The first argument passed to d_fillnew is record constant INFO
which is declared in file tims.h. If the id_code key value exists in the database, d_fillnew
returns status code S_DUPLICATE.
/* Enter technical information records into TIMS database
*/
ent_info()
{
char s[32]; /* generic string variable */
/* enter tech info into TIMS database */
while (get_info() != EOF)
{
/* create new tech. info record */
if (d_fillnew(INFO, &irec, CURR_DB) == S_DUPLICATE)
printf("duplicate id_code: %s\n", irec.id_code);
}
}

Function del_info deletes an info record occurrence. The record to be deleted is identified from a user-specified id_code. Function d_keyfind is used to locate the specified
id_code key and returns status S_NOTFOUND if the key is not on file. If the key is
found, d_recread is called to read the contents of the record into variable irec. Then
pr_info displays the contents of irec, and the user is prompted for confirmation of the
delete operation. If confirmed, d_delete is called to delete the record (and its keys).

3-16

Centura RDM Users Guide

/* Delete technical information records from TIMS database*/


del_info()
{
char id[16];
printf("id_code: ");
gets(id);
/* search database for matching id_code key */
if (d_keyfind(ID_CODE, id, CURR_DB) == S_NOTFOUND)
printf("id_code %s not on file\n", id);
else
{
/* read record associated with the found key */
d_recread(&irec, CURR_DB);
pr_info();
printf("delete (y/n)? ");
gets(id);
if ((id[0] == Y) || (id[0] == y))
d_delete(CURR_DB);
/* delete the record */
}
}

Function by_id is actually similar to del_info in that an info record is located through a
d_keyfind of a user-specified id_code value. If found, the contents are read by
d_recread and are displayed by pr_info. Of course, no delete occurs since the display of
the record contents is all thats desired.
/* Find technical information by id_code*/
by_id()
{
char id[16];
printf("id_code: " );
gets(id);
/* search database for matching id_code key */
if (d_keyfind(ID_CODE, id, CURR_DB) == S_NOTFOUND)
printf("id_code %s not on file\n", id);
else
{
/* read found record and print contents */
d_recread(&irec, CURR_DB);
pr_info();
}
}

Locating info record occurrences by the authors name is somewhat more complex in that
there may be more than one record per author and all are to be displayed.

Operational Overview

3-17

Function by_author searches for the user-specified author name through the call to
d_keyfind. If found, the record contents are read into irec by d_recread and displayed
by pr_info. The user is prompted to press <Enter> when ready to continue. The call to
function d_keynext positions to the next higher author key, returning status S_OKAY if
there was indeed a next key (status S_NOTFOUND is returned when at the end of the
key file). Function d_keyread reads the value of the key into the author variable, which
is then compared (strcmp) with the author field in irec.
/* Find technical information by author
*/
by_author()
{
char author[32], reply[5];
int status;
printf("author: ");
gets(author);
/* search database for matching author key */
if (d_keyfind(AUTHOR, author, CURR_DB) == S_NOTFOUND)
printf("author %s not on file\n", author);
else
{
do
{
/* read found record */
d_recread(&irec, CURR_DB);
/* print record contents */
pr_info();
printf("--- press <enter> to continue");
gets(reply);
/* read next key on file--keys are always sorted */
status = d_keynext(AUTHOR, CURR_DB);
if (status == S_OKAY)
status =d_keyread(author, CURR_DB); /* read key
value */
/* continue while keys have same author name */
} while ((status == S_OKAY) &&
(strcmp(irec.author, author) == 0));
}
}

3-18

Centura RDM Users Guide

Assuming that the program was contained in file intro.c, and that you use the Microsoft
C compiler, the following command would compile the example program (in the large
memory model):
cl /c /AL /DMSC intro.c

To link the object code with the RDM library and produce the executable, use the
following command:
link intro,,,vistal;

Then to execute the program simply enter:


intro

Note that these commands all assume that you have the appropriate Microsoft C
environment set up for locating include files and libraries. In particular, files tims.h and
vista.h should be in either the current directory or in one of the directories listed by the
INCLUDE environment variable. The RDM runtime library should be located either in
the current directory or the LIB environment variables.

3.5

Directory Structure

Table 3-1 describes the directory structure for the RDM system.
The directory structure is designed so that RDM for Windows is installed in the
rdm_home directory.
The RDM directory structure includes directories for the components of db_QUERY and
db_REVISE. Those directories are also described in Table 3-1.

Operational Overview

3-19

Table 3-1. RDM Directory Structure


General Directories
All the pre-made RDM utilities.
bin
dal

Source code for the Database Access Language utility.

dbedit

Source code for the database editor utility.

dbimp

Source code for the database import utility.

examples

Subdirectories of sample programs and databases.

include

Header files.

lib

The pre-made libraries, divided into subdirectories by compiler.


Windows import libraries and DLLs for RDM are stored in
subdirectory, vwin. Windows db_QUERY is stored in
subdirectory, qwin.

lockmgr

Source code for the lock manager and remote console utilities.

query

db_QUERY example program sources and executables. (If you


install db_QUERY, its library source code is placed in this
directory.)

revise

A tool for incorporating database design revisions into existing


RDM databases.

rom

A class library written in C++.

runtime

Source code for the RDM libraries.

utility

Source code for most of the RDM utilities.

Directories for Non-Windows Components


Non-Windows source code for the Interactive Database Access
ida
utility.
Directories for Windows Components
Source code to build the RDM ActiveX control.
activex
wida

3-20

Windows version of the ida directory.

Centura RDM Users Guide

Chapter 4
Database Design
4.1

Introduction

A database design is a description of the data that will be stored in a database and the
relationships that will exist within that data. The design of a particular database is
driven by the requirements of the application it will support, and is therefore a major
part of the total application design process.
Our purpose in this chapter is to provide you with the information necessary to design
RDM databases. If you carefully study this chapter and the example database design,
you should be able to design a workable RDM database, even if you have no database
design experience.
The chapter begins with a detailed description of RDMs Database Definition Language
(DDL). Each DDL statement is explained and illustrated through examples. The operation of the DDL processor is explained followed by a section on database design
considerations. The final section builds on the tims database example introduced in
Chapter 3 by expanding the requirements and describing how the database design
supports those requirements.

4.2

Database Definition Language (DDL)

4.2.1 DDL Basics


An RDM database design is specified in the Database Definition Language. One DDL
specification file exists for each RDM database. In general there is one database per
application, although some applications may require the use of several databases.
(Section 4.4.1, "Logical Design Considerations," discusses multiple database design.) A
DDL specification identifies the database, defines the files that comprise the database,
and contains declarations for all record types, data and key fields, and set relationships
that will exist in the database.
Below is an example DDL specification. It is an expanded version of the checking
account schema given in Chapter 3. It is provided here to illustrate some additional DDL
statements and to serve as a baseline example in the descriptions that follow. A complete
DDL syntax summary can be found in Chapter 2, "Utility Descriptions," of the RDM
Reference Manual.

Database Design

4-1

database ckngacct[512]
{
timestamp records budget;
data file datfile = "chkg.dat" contains budget, check;
key file[1024] keyfile1 = "chkg.k01" contains code;
key file[2048] keyfile2 = "chkg.k02" contains check_no, check_date;
record budget
{
unique key char code[6];
char cat_desc[48];
float allocation;
float balance;
}
record check
{
unique key int check_no;
key int check_date;
char paid_to[48];
float amount;
}
set transactions
{
order last;
owner budget;
member check;
}
}

The DDL specification is stored in a text file and is created using your usual text editor.
Input is free form with comments specified, as in C, between /* */ pairs. Comments do
not nest. This can be an ASCII text file, or, on a Unicode-supported platform, a Unicode
file. For information about RDM support of Unicode, see Chapter 9.
Identifiers are used to name the database, files, records, fields, and sets. They are
formed, as in C, from any combination of letters, digits, and underscores (_) beginning
with a letter.
File, record, and set statements may be interspersed provided that:

Data and key file statements are specified ahead of the declarations of the records
and key fields they contain.

The declarations of set owner and member record types are specified ahead of their
respective set declarations.

Timestamp statements may appear anywhere within a DDL specification.


General practice is to place all file statements first, followed by all timestamp statements,
followed by all record type declarations, followed by all set declarations. The ddlp can,

4-2

Centura RDM Users Guide

optionally, produce a record, field, and set name cross-reference listing to help you locate
names contained in a long DDL specification (see section 4.3, "DDL Processor
Operation").

4.2.2 Database Statement


Syntax:
database dbname [ [pgsize] ] {
ddl statements ...
}
Description:
The database statement is used to specify the name of the database and, optionally, the
default page size of all files.
The name of the database dbname is an identifier and is used by ddlp to form the names
of the database dictionary file and the C or C++ header file. The dictionary file is named
dbname.dbd and the header file is named dbname.h for C and dbname.hpp for C++.
Note that although the length of this name can be up to 31 characters, only the beginning
characters (eight for Windows, 11 for UNIX) are used to form the dictionary and header
file names.
The database name, dbname, is passed to function d_open to identify the name of the
database to be opened and subsequently accessed. It is also passed to utilities such as
initdb to identify the database to be operated on (initialized) by the particular utility.
/The RDM data and key files are blocked or divided into fixed-length pages, each
containing as many record or key occurrences as will fit on a page. The pgsize parameter
determines the default database page size in bytes. This value should, for performance
reasons, always be a multiple of the basic block size for your operating system (a
multiple of 512 will work for most systems). If not specified, the default database page
size is at least 1024 bytes, but will be the first number divisible by 512 that is large
enough to contain the largest record.
Examples:
database ckngacct[512] { ... }

For the checking account example, the name of the database is ckngacct and it has a
default database page size of 512 bytes. The name of the dictionary file created by ddlp
is ckngacct.dbd. The name of the C header file created by ddlp is ckngacct.h.
database acctsrec { ... }

Database Design

4-3

The above is a possible database statement for an accounts receivable database. Since no
page size parameter is specified the default database page size is 1024 bytes. The
dictionary will be stored in file acctsrec.dbd and the C header file will be named
acctsrec.h.

4.2.3 Timestamp Statement


Syntax:
timestamp records [ recname [, recname...] ] ;
timestamp sets [ setname [, setname...] ] ;
Description:
Timestamping is a multi-user database technique used to detect possible changes to
record and set occurrences since the last time they were accessed by a particular user.
Refer to section 7.4, "Timestamping," for a complete discussion of the use of timestamping.
Timestamp statements may appear anywhere within a DDL specification.
Record types or set types to be timestamped are listed, separated by commas, in the
timestamp statement. If no record or set names appear in the timestamp statement then
all record types or set types will be timestamped.
Record timestamping adds eight bytes of additional disk space overhead to each timestamped record slot. Set timestamping adds four bytes of additional overhead to each set
pointer contained in set owner records. (Section 4.4.2, "Physical Design Considerations,"
describes all record and set space overhead.)
Examples:
timestamp records budget;

In the checking account database, only the budget record type is to be timestamped. This
allows an appraisal to see if another user has modified or deleted a particular budget
record before a check is written to the database, which updates the balance for that
budget category.
timestamp records;
timestamp sets;

The database for the above example requires that all record and set types be timestamped.

4-4

Centura RDM Users Guide

4.2.4 File Declarations


Syntax:
data file [[pgsize]] [fileid =] filename contains recname[, recname]... ;
key file [[pgsize]] [fileid =] filename contains [recname.]keyfld
[, [recname.]keyfld]... ;
Description:
File declarations identify the physical files to contain the data stored in the database. The
data file statement defines a file that will contain the occurrences of one or more record
types. The key file statement defines a file that will contain the index for one or more
key fields.
The RDM data and key files are blocked or divided into fixed-length pages, each
containing as many record or key occurrences as will fit on a page. The optional pgsize
parameter specifies the page size for the file. If not specified, the page size for the file
will be the default database page size. This value should always be a multiple of the
basic block size for your operating system (a multiple of 512 will work for most systems).
Otherwise, the operating systems file access performance will be impaired.
The name of the file, filename, is a string enclosed in quotation marks (") containing the
physical (operating system) name of the file. It may be a fully qualified path name but
must not exceed 47 characters in length. If the name of the file is not qualified (that is, it
does not include a directory name), applications using the database must be executed
from within the directory containing the database files, subject to the environmental
conditions discussed in section 5.2.2, "Operational Environment."
Associated with a database file is an optional file, fileid, which is used to identify files
within an application program independent of the physical name of the file. It is
intended to be used for dynamic initialization of individual files using the d_initfile
function (section 5.2.3, "Dynamic Database Initialization") or for dynamically substituting
files using the d_renfile function (section 5.2.2, "Operational Environment").
All record types defined in the DDL must be contained in a data file. All occurrences of
the record types listed in the contains clause will be stored in that file. Occurrences of a
given record type can only be stored in a single file. Each page in the data file consists of
one or more fixed-length record slots. The size of the record slot is based upon the size of
the largest record type contained in the file. Smaller record types will occupy the same
record slots, thus leaving unused space. You can define all record types to be contained
in one file or you can have a separate data file for each individual record type. The
choice is yours.

Database Design

4-5

A special system-defined record named system may be listed as the first record type in
the contains clause of one (and only one) of the data files. Only one occurrence of the
system record exists in the database. It is used as the owner of any number of sets to
provide the means for records to be connected to the top or root of the network. When
the database is opened, the current record and the current owners of all system-owned
sets are initialized to the system record.
All key fields defined in the DDL must be contained in a key file. All occurrences of the
key fields listed in the contains clause will be stored in the file. Occurrences of a given
key type can only be stored in a single file. Each page in the key file consists of one or
more fixed-length key slots. The size of the key slot is based upon the size of the largest
key field contained in the file. Smaller key fields will occupy the same slots, thus leaving
unused space. You can define all key fields to be contained in one file or you can have a
separate key file for each individual key field. The choice is yours.
Section 4.4.2, "Physical Design Considerations," provides some guidelines to help you
determine the best file organization for your particular application.
Examples:
data file datfile = "chkg.dat" contains budget, check;
key file[1024] keyfile1 = "chkg.k01" contains code;
key file[2048] keyfile2 = "chkg.k02" contains check_no;

The checking account database consists of one data file and two key files. The data file
identified as datfile contains occurrences of both the budget and check record types in
the physical file named chkg.dat. From the database statement the page size for datfile
is 512 bytes. The key file identified as keyfile1 has a page size of 1024 bytes and contains
the index for key field code in file chkg.k01. Key file keyfile2 has a page size of 2048
bytes and contains the index for key field check_no in file chkg.k02.
data file "/client/master.dat" contains system, master;

The above file name specified in this data file statement includes the fully qualified path
for file master.dat located in the client directory. In addition to the occurrences of the
master record, this file will contain the system record.
key file "invnt.k01" contains stock.id_code;
key file "invnt.k02" contains bkorder.id_code;

The above example shows duplicate key names that are qualified by the record type in
which they are defined. When duplicate field names are used, it is necessary to use the
-d option with the ddlp command (see section 4.3, "DDL Processor Operation").

4-6

Centura RDM Users Guide

4.2.5 Record Declarations


Syntax:
[static] record recname {
[field_stmt]
...
[comkey_stmt]
...
}
Description:
The record statement defines a group of related data fields named recname that will be
stored and accessed together on the database as a single unit. The record declaration
consists of zero or more field statements followed by zero or more compound key
statements. A record specification with no data fields is valid, and often is used in the
implementation of many-to-many sets (see "Use of Sets" in section 4.4.1).
The ddlp utility will use the identifier recname to create two C or C++ identifiers in the
dbname.h or dbname.hpp file. For C, a struct named recname, containing the C declarations for the data fields defined in the record, will be declared in dbname.h. For C++, a
class names recname, containing the C++ declarations for the data fields as well as some
default methods and macros (for use by Centuras C++ product, ROM) will be declared
in dbname.hpp. The name of the struct or class will identically match the name of the
record as specified in the DDL. An upper-case form of recname will define an integer
constant record number to be passed to those RDM runtime functions that manipulate
records. Record names, therefore, should never be specified entirely in upper-case.
The static attribute specifies that the records are never updated when the database is
opened in shared mode. This allows the RDM runtime to optimize access to the static
record occurrence, yielding much better performance. Static records are used for storing
information such as menus, data entry forms, help screens, system messages, coded
value information, etc. Multi-user database programs are not required to place locks on
this data in order to access it. Static records can only be modified when the database is
opened in exclusive access mode. Single-user applications may modify static records at
any time. The data and key files containing static record information can only contain
static data. The system record is a special case and can be included in a data file that
contains either static or not static records. Static records can only be used in sets which
themselves are not modified except in exclusive access mode.

Database Design

4-7

Example:
record check {
unique key int check_no;
int check_date;
char paid_to[49];
float amount;
}

The check record type in the checking account database contains two integer fields (one
of which is a key), a character string field, and a floating point field. File chkgacct.h will
contain the following definitions associated with the check record type:
struct check {
int check_no;
key int check_date;
char paid_to[49];
float amount;
};
#define CHECK 10001

Record trans below contains two compound key field declarations. (For more information, see "Use of Keys" in section 4.4.1, "Logical Design Considerations."
record trans {
unique key int checkno;
int trdate;
char vendid[8];
long amount;
compound key tr_key {
trdate descending;
vendid ascending;
}
compound key ven_chks {
vendid; checkno;
}
}

Below are two record types and a set that might be defined for a multi-user data entry,
forms management system. Note that both records are declared to be static, since during
normal operation of an application using the forms manager, form and field records are
not modified.

4-8

Centura RDM Users Guide

static record form {


unique key char form_id[11];
}
static record field {
unique key char field_id[21]; /* Display name of field */
int id_row;
/* Row where field_id displayed */
int id_col;
/* Column where field_id displayed /
int data_row;
/* Row where data starts */
int data_col;
/* Column where data starts */
int field_len;
/* Editable field length */
char required;
/* Required field */
int edit_fcn;
/* Editing function called on entry */
int disp_fcn;
/* Display function called on output /
int rtype;
/* Record type containing the field */
long ftype;
/* RDM field type */
}
set form_fields {
order last;
owner form;
member field;
}

4.2.6 Field Declarations


Data Fields
Syntax:
[[optional] [unique] key] type fldname [ [dim]...] [om_field] ;
or
[[optional] [unique] key] struct {
field_stmt
...
} fldname [[dim]...] ;
type =
[unsigned] int | [unsigned] short | [unsigned] long |
char | wchar_t | float | double | DB_ADDR
om_field =
directref recname
or
relatedto recname thru fldname

Database Design

4-9

The fldname is an identifier that names the particular data field. Field names may not
duplicate record or set names, nor by default other field names.
The syntax for a data field statement is similar to, although not as general as, a C data
declaration. In fact, most of the basic data types in C are directly supported in the DDL.
Arrays of any type are available, where dim specifies the size of a given array dimension.
One-dimensional character arrays are treated by the RDM runtime functions as C strings.
Thus, these fields should always be terminated by a null byte, and the length as specified
in the field declaration should include the null byte. If a one-dimensional character array
is needed that is not intended to be treated like a string (for example, a byte array), it
should be declared as a two-dimensional array where the second dimension is one.
A data field that is also to be used as a key to the record has the key attribute. Key field
values are stored on the key file in the natural order based on the data type. If only
unique keys are allowed then the field should be qualified as a unique key field. The
maximum length of a key field is 246 bytes. Fields defined as a unique key must contain
a value that does not already exist on the key file at the time its associated record is
entered into the database. If a record is entered (modified) with a duplicate value in a
unique key field, the status code S_DUPLICATE is returned and the record is not
entered (or modified).
The optional attribute indicates that the data field is an optional key. Optional key
values are not inserted into the key file until the application program calls function
d_keystore. Optional keys can be manually deleted using function d_keydel. When an
optional key is modified (through a d_recwrite or d_crwrite call), the key file will be
updated only if the current value exists in the key file.
Fields declared as struct cannot be nested. Sub-fields of an arrayed struct field cannot be
defined as key fields nor accessed individually.
Data fields of type DB_ADDR contain the database addresses of specific record occurrences in the database. Database addresses can be directly accessed using the currency
table access functions described in section 5.3, "Currency Tables." This allows you to
maintain your own record linkages directly, if desired.
The optional om_field should only be used when ddlp will be used to generate C++
classes for ROM. The directref option must be used on a DB_ADDR field. With this
option, methods are created in the resulting class to allow ROM to have direct access
from this record to the record being referenced through this field. The relatedto option is
designed to allow ROM to know about relational links. The field in the record that is
being related to this field must be a key field. This allows ROM to create methods to
easily navigate through this relational link.

4-10

Centura RDM Users Guide

Data fields will be aligned within the record in order to match the struct field alignment
rules followed by your particular compiler and computer. A ddlp option can be used to
disable this alignment if desired (see section 4.3, "DDL Processor Operation").
Examples:
unique key char code[6];

Field code is a character string field of six characters long (five characters plus one null
terminator) that is defined as a unique key.
float balance;

Field balance is a floating point field which, in the checking account database, contains a
monetary value.
key int check_date;

Key field check_date is used to store a date in the application-defined Julian format (for
example, number of elapsed days since January 1, 1900). Its values are stored on the key
file in integer order. Thus, check records can be retrieved in check date order through
use of the key retrieval functions (see section 5.4.1, "Data Retrieval Using Keys").
struct {
double imag;
double real;
} complex[3];

This field statement defines a structure array field, complex, which stores an array of
three complex numbers composed of an imaginary part and a real part.
key long coordinates[3];

Coordinates is an array of three long type variables, and is also a key. It may be used to
locate an object on a large three-dimensional grid.
int bitmap;

Field bitmap is used to store a bitmap of attribute flags, which are tested using binary
operators and masks. For example, assuming this field was declared in record type rec,
rec.bitmap & 0x0001 is non-zero if the low order bit is set. (Note that RDM does not
directly support C bit fields.)
char byte_array[16][1];

Database Design

4-11

Byte array fields are implemented, as in byte_array, as a two-dimensional character array


where the second dimension is one. This will force the RDM runtime to manipulate all
16 bytes of the field rather than stopping at the first null byte as it does with string fields.
DB_ADDR ptr_array[20];

Field ptr_array is an array of type DB_ADDR. It is used to store an array of the database
addresses of record occurrences that are related to the record type in which ptr_array is
defined. Use of DB_ADDR fields provides unlimited data organization possibilities to
the programmer. However, these alternatives should only be used in those rare instances
when the standard capabilities provided by keys and sets are insufficient for a particular
requirement.
optional key struct {
char last_name[21];
char first_name[21];
char initial[2];
} name;

Name is a struct field to contain person names and is composed of three string fields for
the last and first names and the middle initial. Last_name is the first field specified since,
because name is a key field, the last name can be used in a partial key search to find, for
example, all the Smiths on file. Thus, the order of the fields in a keyed struct field
specifies the major and minor sort sequences for the key on the key file.
This field is defined as an optional key. Optional keys are often used to defer the overhead associated with storing keys to a time when the system is less busy. For example, it
might be that the record which contains name needs to be stored as rapidly as possible
during the day. At night a batch program can be run to create the optional keys.

Compound Key Fields


Syntax:
compound [optional] [unique] key keyname {
fldname [ asc[ending] | desc[ending] ] ;
...
}
Description:
The preceding syntax is used to define a compound key field named keyname.
Compound keys are key field definitions consisting of any combination of fields (not
necessarily contiguous) from a given record. Each sub-field of the compound key can be
specified to be sorted in either ascending (default) or descending sequence. Compound
keys differ from normal key fields in that they do not define additional data fields in the

4-12

Centura RDM Users Guide

record. By using compound keys, you can have a field appear in multiple keys within a
record, without needing to duplicate the fields value in the data file.
The compound key specifications must follow all other field statements in a record declaration. The order in which the sub-fields are specified determines the major and minor
sort sequences. The fldname must be the name of a field that is defined in the record and
is not defined as a struct. If the optional qualifier is specified, the key will only be stored
when d_keystore is called. Otherwise, the key is created when the record is created. All
of the key functions that apply to normal key fields also apply to compound keys.
ddlp will create in the dbname.h or dbname.hpp file a struct (or class) declaration
named keyname for each compound key defined in the schema, similar to the struct declarations associated with records. These can be used in conjunction with the key manipulation functions of the RDM runtime library.
Because of the nature of compound keys, records containing them can only be created
using function d_fillnew (not d_makenew).
Examples:
compound key tr_key {
trdate descending;
vendid ascending;
}
compound key ven_chks {
vendid;
checkno;
}

Assume that a record type called trans (transaction) contains two compound key definitions. Key tr_key is composed of fields trdate and vendid. Scanning through transaction
records by tr_key would produce a sorted list in descending transaction date order, and
ascending vendor id order within each date. Key ven_chks consists of two fields: vendid
and checkno. Scanning through transaction records by ven_chks would give a sorted
list in ascending vendor id order, and in ascending check number order within each
vendor.

4.2.7 Set Declarations


Syntax:
[ bitmap | blob | varilen ] set setname {
order { asc[ending] | desc[ending] | first | last | next }
owner recname ;
member recname [ by fldname [, fldname...] ];
...
}

Database Design

4-13

Description:
Set declarations define explicit, one-to-many relationships between record types. Sets are
implemented as a linked list of member record instances connected to a single instance of
an owner record, which serves as the root or head of the list (see "Set and Member
Pointers" in section 14.2.2, "Data File Organization"). The order in which member records
are inserted into this list is specified in the set order clause.
Possible set orderings are defined as follows:
first

New member records are connected (that is, inserted) at the


front of the list.

last

New member records are connected at the end of the list.

ascending

New member records are connected in ascending order


based on the contents of the data fields specified in the by
part of the member clause of the set statement.

descending

New member records are connected in descending order


based on the contents of the data fields specified in the by
part of the member clause of the set statement.

next

New member records are connected immediately following


the current member of the set, or, if the current member is
null, at the front of the list.

The by part of the member clause is only supplied when ascending or descending order
is specified. For sorted sets having more than one member record type, the sort field(s)
of those record types should correspondingly be of the same type and length and be
listed on the by clause in the same order.
When the sort field values of new member records of a sorted set duplicate existing
members, the new members are added in front of the members with matching values.
The set owner may be specified as system. Use of the system record is not required. If
one is used, do not declare it in a DDL record statement. ddlp automatically creates the
system record when it is specified in a data file statement. There is only one occurrence
of the system record in the database. It is used as the owner of any number of sets
providing the means whereby records can be connected to the top or root of the network.
When a database is opened, the current record and the current owner of all
system-owned sets are initialized to the system record (see section 5.3, "Currency Tables,"
for a discussion of currency).
Connecting member records to sets of order first, last, or next is faster than connecting to
sets of order ascending or descending. This is because the list of member records
associated with ascending or descending sets must be scanned each time a new member
is connected, in order to find the proper insertion point. Thus, a connection to an ascend-

4-14

Centura RDM Users Guide

ing or descending set with a large number of members can be relatively slow. If you
need a large sorted set, explore alternative approaches using keys or reverse ordering to
maintain the ordering.
Note: RDM does not implement ascending or descending sets through an index. As
with all sets, they are implemented as a linked list (or chained) structure. RDM does
provide a keyed record access (through a B-tree index) but it is totally distinct from sets.
A record can both have keys and be an owner and/or member of sets, but sets do not use
keys and keys do not use sets. Thus, sort fields of ascending or descending sets do not
need to be declared as key fields.
The keywords bitmap, blob, and varilen should be used only when ddlp is generating
C++ output for ROM. Each provides different ROM capabilities when the set is being
used to store bitmaps, blobs and variable length text. Refer to the ROM documentation
for more details.
Examples:
set transactions {
order last;
owner budget;
member check;
}

Transactions is a set between the budget record and the check record in the checking
account database. Each check written is to be applied to a particular budget account.
Each budget account has a set of checks that have been written against it. As a new check
is written and entered into the database, it is connected to the transactions set instance,
where the appropriate budget record has been identified as the current owner of the set.
The new check record will be connected to the end of the set. Thus (assuming checks are
written in order), they will be stored in check number order (and probably date order as
well).
To ensure that checks are stored in date order, the set specification could be modified as
follows:
set transactions {
order ascending;
owner budget;
member check by check_date;
}

Here the order has been changed to ascending and the member clause now includes the
by part to indicate that the set is to be sorted on the check_date field of the check record.
Again, the connect operation will be slower than if the order is last. However, if the sort
field is known to usually force the insertion to be at the end of the set instance, the
ordering of the set could be reversed so that the set remained sorted and so that the
insertion was usually made quickly at the front of the list.

Database Design

4-15

set comment {
order first;
owner note;
member project;
member task;
member work_day;
}

The comment set illustrates a use of multiple member sets to reduce unnecessary space
overhead. Each of the project, task, and work_day record types in a project management
database can have an optional comment associated with it in the note record. In this example, an occurrence of project, task, or work_day can be associated with only a single
occurrence of note. Thus each set instance is strictly one-to-one. Use of a single set is
preferred over three separate sets because it will use less space for the set overhead (one
set pointer is needed instead of three). See section 4.4.2, "Physical Design
Considerations," for more information.

4.3

DDL Processor Operation

4.3.1 DDL Processor Execution


The Database Definition Language Processor, ddlp, is executed as follows:
ddlp [-r] [-x] [-b] [[-c] [-ln]] [-d] [-n] [-s[-]] [-oxxxx] [-z] [-axxx] ddlspec
File ddlspec is the name of the text file containing the DDL specification. This file is
sometimes called the schema file. For ddlp, this must be an ASCII file. However, if you
are using the ddlpu utility for a Unicode-supported platform, the text file can be
Unicode. For further information about RDM support for Unicode, see Chapter 9.
The ddlp will compile the DDL in file ddlspec and report any errors to stdout with the
line number where the error was detected.
The compiled DDL is stored in the database dictionary file for use by the RDM runtime
library functions. The name of the dictionary is taken from the dbname of the database
DDL statement and given an extension .dbd, forming dbname.dbd. The amount of
dynamically allocated memory required by the RDM runtime for storage of the
dictionary is reported by ddlp upon completion, if no errors were detected. Otherwise,
the dictionary file is not created.
If the -r option is specified, ddlp will display (in stdout) the File Structure Report. (See
"ddlp File Structure Report" in section 4.4.2 for an explanation of the use of this report.)

4-16

Centura RDM Users Guide

If the -x option is given, a cross-reference listing of the records, fields, and set identifiers
is displayed in stdout. An example report is shown below for the checking account
schema.
RDM Version 5.0
DDL X-Ref Listing of File: ckngacct.ddl
Wed May 04 16:53:32 1999
allocationfield
12
amount
field
balance
field
budget
record
cat_desc
field
check
record
check_datefield
7 17
check_no
field
code
field
paid_to
field
transactions
set

19
13
3

23

11
5
7

15 24

16
6 10

8
21

The names are listed in alphabetical order, with the associated type and the line numbers
in the DDL file where the name is referenced.
The -b option is used to instruct ddlp not to perform any data field alignment. Normally,
the offset to the start of each data field in a record is aligned according to the default
struct field alignment rules enforced by your particular C compiler. Some compilers,
however, provide an option to pack struct fields. If you use this option when you
compile any C modules that use the struct declarations created by ddlp, you must also
compile the DDL using the -b option.
The -c option is used to maintain alignment compatibility with RDM version 2.x
databases. If -c is specified, and the number of bytes per word is other than 2 bytes, then
you must use the -ln option to inform ddlp of the number, n, of types per word for your
machine. For example, VAX and M68000 processor users should always compile with
-l4.
With the -d option, ddlp allows duplicate field names, such that field types within different record types may have the same name. The record structures created by ddlp will
contain the name as specified in the schema. The constant definitions for the fields will
be a concatenation of the record type and field type, separated by an underscore. For
example:

Database Design

4-17

record ticket {
.
.
float unit_cost;
}
record invoice {
.
float unit_cost
}

will cause the following constant definitions:


#define TICKET_UNIT_COST 4005
#define INVOICE_UNIT_COST 6014

If duplicate field names are used with key fields, then each reference to the key field
name in the key file statement must have a prefix showing the record type that contains
the field. The syntax is recname.fldname.
The -n option instructs ddlp to omit writing the ASCII record, set, and field names to the
dictionary file. This creates a smaller dictionary file, but makes names unavailable to
utilities such as ida, dbimp, and db_REVISE, and programs made with db_QUERY.
ddlp creates C struct (C++ class) declarations for each record type and compound key
field defined in the DDL and stored with file id, record, field, and set constants in a
header file also named from the dbname of the database statement forming dbname.h
(dbname.hpp). By default, case is preserved on all of the names used. The -s- option
may be used to instruct ddlp to convert all of the names to lowercase to be compatible
with previous versions.
The ddlp can process constants, #defines, predefined structures, and typedefs. All of
these keywords must be used before ddlp recognizes the keyword database. Everything
before the keyword database is copied to the resulting header file, so the application will
not need to redefine anything.
As an example, the contents of file ckngacct.h, which was created when the checking
account schema (as given in section 4.2.1, "DDL Basics") was processed by ddlp, is shown
below.

4-18

Centura RDM Users Guide

#ifndef CKNGACCT_H
#define CKNGACCT_H
/* RDM Version 5.0 */
/* database ckngacct record/key structure declarations */
struct budget {
char code[6];
char cat_desc[48];
float allocation;
float balance;
};
struct check {
int check_no;
int check_date;
char paid_to[48];
float amount;
};
/* record, field and set table entry definitions */
/* File
#define
#define
#define

Id Constants */
DATFILE 0
KEYFILE1 1
KEYFILE2 2

/* Record Name Constants */


#define BUDGET 10000
#define CHECK 10001
/* Field Name Constants */
#define CODE 0L
#define CAT_DESC 1L
#define ALLOCATION 2L
#define BALANCE 3L
#define CHECK_NO 1000L
#define CHECK_DATE 1001L
#define PAID_TO 1002L
#define AMOUNT 1003L
/* Set Name Constants */
#define TRANSACTIONS 20000
/* Field Sizes */
#define SIZEOF_CODE 6
#define SIZEOF_CAT_DESC 48
#define SIZEOF_ALLOCATION 4
#define SIZEOF_BALANCE 4
#define SIZEOF_CHECK_NO 2
#define SIZEOF_CHECK_DATE 2
#define SIZEOF_PAID_TO 48
#define SIZEOF_AMOUNT 4
#endef

/* CKNGACCT_H */

The #define constants are passed to runtime library functions to identify the particular
file, record, field, or set type involved in the operation. The actual values represent

Database Design

4-19

entries into the tables that make up the database dictionary. The constants also have
some additional control information encoded, as follows:
Record name constants consist of a record number (record 0 is the first record defined
in the DDL, record 1 is the second, and so on) plus 10000.
Set name constants consist of a set number (numbered sequentially, as are records)
plus 20000. This information is used by RDM runtime functions to distinguish
between record and set constants.
Field name constants are formed using the following formula:
(record number * 1000) + number of field within record
This can simplify the work involved in adding a new field to a record. In pre-3.00
versions of RDM, the field constant was simply the index of its dictionary entry.
However, if a new field was added, all source modules had to be recompiled because the
new field changed the values of the field constants. With the new technique, if a new
field is only added to the end of a record, only those modules that need to reference the
new field need to be recompiled. Note that field constants are long integers, whereas file,
record, and set constants are standard integers.
The SIZEOF_?????? constants are added in the header file as a convenience of the user. If
they are not needed, or are causing problems with large databases, they can be removed
with a -z option.
The database header file should be #included in every C source module that needs to
access the database.

4.3.2 ddlp Alignment


The current version of ddlp may create different alignment patterns than previous versions of ddlp. If you have existing databases created with previous versions of RDM, be
careful about running a new ddlp. Doing so may result in a different alignment, which
would cause problems with your existing data files. It is not necessary to run a newer
ddlp once you have a dictionary with the proper alignment with an older version of
ddlp.
To see if the newer version of ddlp will result in a different alignment, rename your existing database dictionary (.dbd) file and then run ddlp on your schema. Then use prdbd
to examine the alignments of the two dictionaries. If theyre the same, you wont have a
problem using the newer version of ddlp. If theyre different, you can choose whether or
not to convert your database to the newer version. If you dont want to convert your
database to the newer ddlp, the newer RDM libraries still will work with any 3.00 or
higher version of the dictionary.

4-20

Centura RDM Users Guide

If you have existing data that needs to be preserved, you can either use db_REVISE to
convert from the older ddlp to the newer version, or you can use the dbexp and dbimp
utilities.
You also should check the alignment of your data structures any time you change
compilers. If the alignment is different, you may need to adjust your alignment for the
compiler and the database.

Nested Structures
Be very careful about using nested structures in records. The alignment of nested structures is very compiler-dependent. Although RDM compensates for this dependence,
ddlp may not always be able to produce the correct alignment of nested structures.
While numeric and character data can be included in the same record, we recommend
that numeric data and character data not be mixed together. You should put the
doubles, longs, ints, and shorts first, with the chars last. This will create the smallest
possible records without artificially packing the structures and avoid most alignment
problems.
If you plan to use nested structures, we recommend that they start on word boundaries
(that is, with numeric data). Starting the structures on eight-byte boundaries may be
necessary on some machines when the structures contain double data types.

4.3.3 ddlp Alignment in Windows


In the Windows environment, ddlp takes the following new arguments:
-amsc

Alignment for Microsoft C (overridden by -b)

-abcc

Alignment for Borland C++ (overridden by -b)

ddlp can also use the ddlp environment variable to set word alignment. To set ddlp to
use word alignment for Microsoft C, use either the -amsc switch or use set ddlp=msc to
set the ddlp environment variable.
Applications should use -b for byte alignment when packing structures.

4.4

Database Design Considerations

C programmers prefer the flexibility to make intelligent decisions based on a number of


design alternatives, rather than having to rely on a less flexible system (which may do a
lot more of our work for us, but not always in the way we want it done). Much of the
power of RDM stems from the flexibility it allows the application developer in
organizing the database. This flexibility, however, requires the programmer to make
design decisions from a wide variety of alternatives.

Database Design

4-21

This section presents database design considerations as they pertain to RDM. These
design considerations are separated into logical design and physical design issues.
Logical design (as defined here) involves those aspects of the database organization that
directly affect the manner in which the C applications have to access and manipulate the
stored information. Physical design addresses the organization of the database into data
and key files and (except for file renaming and initialization) is transparent to the
application program.

4.4.1 Logical Design Considerations


The logical design considerations discussed here address the use of keys, sets, and multiple databases. Note that the examples given show only the DDL and not the actual
code that uses it. Chapter 5, "Database Manipulation," will complete many of these examples by providing the necessary code.

Use of Keys
General Key Usage
Key fields are basically used:

To provide fast access to individual record occurrences

To provide efficiently sorted and selectable retrieval of a large number of record


occurrences

What are the possibilities for locating a specific record occurrence among many? One
could read and inspect each record occurrence in the order they were stored in the file,
until the desired record is found. This would take some time if there are many occurrences. On average, half of the records on file would have to be inspected to find a specific record, and all would have to be inspected to determine that the record was not on
file.
Alternatively, sets could be navigated through the network structure to locate the desired
record (see section 4.5.3, "Database Design"). This would generally mean that fewer
records would have to be read, but the process still would be too slow, depending on the
application requirements.
Because of the efficiency of the B-tree indexing method, locating a record through a key
will involve at most only a few disk read operations (usually three or four). Thus, it is an
ideal way to locate specific record occurrences rapidly.
In RDM, any field defined in a record can be a key. Thus there are a wide variety of
potential ways to access a particular record. Fields can be defined as unique keys, to
prevent the entry of records containing duplicate key values. When key fields are not
defined as unique, records with duplicate keys are allowed to reside in the database. For
example, zip code may be a key in a person record containing an address.

4-22

Centura RDM Users Guide

In the checking account database, check_no was defined as a unique key to allow the
program to retrieve the check record for a particular check number. Other examples of
data fields that would be good candidates for keys are:
employee number
social security number
vehicle identification number
inventory item number
budget code
serial number
personal name
Many different kinds of fields containing coded values are best implemented using a key.
If new codes are needed, they can be added to the database without recompiling. For
example, consider the following record declarations:
/* vehicle make validation table */
record vehicle
{
unique key vma_code[7]; /* vehicle make code */
char vma_desc[25];
/* vehicle make description */
}
/* vehicle fleet record */
record fleet {
unique key char vin[25];
/* vehicle id number */
char vma[5];
/* vehicle make */
char vmo[5];
/* vehicle model */
char vyr[3];
/* vehicle year */
int lsd;
/* last svc. date */
}

An example vehicle record occurrence might be:


vma_code: CHEV
vma_desc: Chevrolet

When a new fleet record is entered, the application program can easily validate that the
vma field contains a correct code by doing a key find operation on its contents (specifics
of how to do this are explained in section 5.4.1, "Data Retrieval Using Keys").
The check_date field in the checking account database example was not a unique key.
This provided the ability to write multiple checks with a common date and to quickly
retrieve all checks written on a specific date or within a particular range of dates.
Key fields can also be used for rapid pattern-matching type searches. Many more keys
than records can be retrieved in a single disk read. Use of a key field for certain search
requirements will result in much faster processing, especially when all occurrences need
to be checked by the search operation.

Database Design

4-23

For example, consider a law enforcement database containing "method of operation"


records, which give the details of how specific crimes were committed. These records
contain perhaps 25 data fields, each containing a numeric code identifying a particular
aspect of the crime. One field in the record might describe a burglars method of entry
into a home as follows:
Code

Meaning

Broke in through front door

Broke in through back door

Broke in through window

Picked front door lock

Picked back door lock

Came down the chimney

Other

The reason for maintaining m.o. records in the database is, of course, to allow searches
for a match of a selection of the fields. The key for the search would be a 25-element byte
array in which each elements value would be a numeric code, with zero meaning "not
supplied."
record mo {
key char mo_data[25][1];
}

The fields in the key would be ordered with the highest priority search field first and the
lowest priority search field last. The highest priority search field is the one most often
used in the searches. By listing it first, you can reduce the number of keys to be scanned
in the maximum number of cases. If the first field is not used in the search, all keys must
be scanned.
Compound Key Usage
In general, compound keys are used when one of the following conditions exists:

A data field needs to participate in more than one key in the record.

A key is needed that contains multiple fields, where a mix of ascending and
descending order is required among the sort fields.

Suppose a record is to be searched based on the contents of two fields, where search
values for either field are not always available. If a struct key field were used and the
first field in the key was not available, all keys would need to be scanned. The use of two
compound keys would solve the problem.

4-24

Centura RDM Users Guide

record combo_search {
int field1;
int field2;
compound key f1_1st {
field1; field2;
}
compound key f2_1st {
field2; field1;
}
}

If only field1 data were available for the search, then key f1_1st would be scanned. If
only field2 data were supplied, then key f2_1st would be scanned. If both were supplied, by convention, f1_1st would be scanned.
Compound keys allow sort fields to be individually sorted in either ascending or descending order. As an example, suppose in the checking account database we wanted to
be able to list the checks sorted by the paid_to field, and, within that, in check number
order with the most recent checks listed first. The easiest way to do this is to use
db_QUERY, but for the purpose here we will use a compound key, as follows:
record check
{
unique key int check_no;
key int check_date;
char paid_to[48];
float amount;
compound key pay_list
{
paid_to ascending;
check_no descending;
}
}

Optional Key Usage


Optional keys are not created when the record is created, but only when specifically
requested by the application program through the d_keystore function.
Optional keys should be used for fields that are not mandatory (the fields contents are
not always supplied), but that need to be keyed when they are used.
Optional keys can also be used when it is desirable to defer the key creation to a time
other than when the record is first stored. In many applications the number of record
updates per a given time period (called the transaction rate) often needs to be
maximized. Normally, the key fields in a record are created when the record is created,
and this involves additional overhead of up to three or four disk input and output
operations per key. The ability to defer key creation can greatly improve the transaction
rate. Usually a separate program performs the key creation during non-peak system load
times (for example, late at night).
Database Design

4-25

Use of Sets
Set relationships form the basis of the network database model. The basic use of sets in
forming one-to-many relationships was introduced in Chapter 2, "Database Concepts,"
and illustrated in the checking account database example. This section will expand the
use of sets by showing how they can be used to implement many-to-many relationships
and variable-length records.
Many-to-Many Relationships
Many-to-many set relationships are best explained through an example. A typical
example is students and classes in college. Each class has many students and each
student takes many classes. Thus, there is a many-to-many relationship between classes
and students.
Sets, however, only implement one-to-many relationships. On the surface, it might
appear that the following incorrect implementation using two sets would work.
record class {
unique key char class_id[6];
... other fields
}
record student {
key char name[36];
... other fields
}
set my_students {
order last;
owner class;
member student;
}
set my_classes {
order last;
owner student;
member class;
}

4-26

Centura RDM Users Guide

The schema diagram in Figure 4-1 illustrates the relationships.

class

my_students

my_classes

student

Fig. 4-1. Incorrect Many-to-Many Implementation


Consider, however, the following instance of the my_students set.
Class:

Computer Science 101 (CS101)

Students: Smith
Jones
Kelly
Carlson

A problem occurs when the my_classes set instances for these students is examined.
Each student in CS101 must have that same class as a member of his my_classes set
instance. This is not possible, however, since CS101 can only be connected to a single
owner in the my_classes set.
The correct technique for implementing many-to-many relationships does indeed utilize
two sets but through the use of an intersection record type, as follows:

Database Design

4-27

record class {
unique key char class_id[6];
... other fields
}
record student {
key char name[36];
... other fields
}
record intersect {
}
set my_students {
order last;
owner class;
member intersect;
}
set my_classes {
order last;
owner student;
member intersect;
}

Figure 4-2 shows the schema diagram that corresponds to the above DDL.

student

class

my_classes

my_students
intersect

Fig. 4-2. Correct Many-to-Many Implementation


Each student record occurrence will have its own set of intersect record occurrences
through the my_classes set. Each of these intersect records is also owned by a specific
class record through the my_students set. Similarly, each class record will have its own
set of intersect record occurrences through the my_students set, each of which is owned
by an individual student record through the my_classes set.
In this case the intersection record has no user-defined data in it. However, it could be an
ideal place to store the students grade for the class if that was needed. In that case you
would probably want to change the name of the record type from intersect to grade or
some other more meaningful name.
A description of the actual database manipulation involved in maintaining many-tomany relationships, based on the database design example presented in section 4.5, is
provided in Chapter 5.

4-28

Centura RDM Users Guide

Variable-length Records
Only fixed-length records are allowed in RDM. In systems where variable-length records
are supported, they are often implemented by storing the variable-length information in
a linked list of fixed-length segments. This technique can be implemented by the RDM
application developer through sets.
In the simplest example, a note of arbitrary length is associated with a record such as a
customer record. If the note is stored as a field in the customer record, then an arbitrary
limit on the length of the note text would need to be imposed. Much of the space taken
up by the field would never be used. If, however, a separate record type were defined to
store a single line of text, a set relationship between the customer and note text line
would allow any number of text lines to be connected to a particular customer. The
schema diagram in Figure 4-3 shows this relationship.

customer
cust_notes

text
Fig. 4-3. Example Variable-Length Text Implementation
The corresponding DDL statements are shown below.
record customer {
unique key char cust_id[7];
char company[21];
... other fields
}
record text {
char line[80];
}
set cust_notes {
order last;
owner customer;
member text;
}

Database Design

4-29

Use of multiple member sets can save even more space. Consider the alternative schema
diagram in Figure 4-4.

customer
cust_notes

text30

text55

text80

Fig. 4-4. Better Variable-Length Text Implementation


The DDL corresponding to this implementation follows:
record customer {
unique key char cust_id[7];
char company[21];
... other fields
}
record text30 {
char t30_line[30];
}
record text55 {
char t55_line[55];
}
record text80 {
char t80_line[80];
}
set cust_notes {
order last;
owner customer;
member text30;
member text55;
member text80;
}

Multiple member sets allow any occurrences of the record types that are defined as valid
members to exist in the same set instance. Thus, in this example, a customer record may
have text30, text55, and text80 record occurrences connected through the cust_notes set.
This allows the program to choose the record type that best fits the amount of text
actually entered for a given line of text. Note, however, that each of the text record types

4-30

Centura RDM Users Guide

should be contained in a separate data file, or no real space savings will occur (see section
4.4.2, "Physical Design Considerations").
The C code that manages the cust_notes set connections is described in Chapter 5,
"Database Manipulation."

Use of Multiple Databases


Application programs can open and access more than one database at a time. The use of
multiple databases in an application can yield certain advantages and therefore should
be a consideration in the design of the database. In this sense, an applications database
may actually consist of several RDM databases.
There are at least two situations in which multiple database design is useful:

A temporary control or working database is desired

An application is to consist of optional, modular components

Sometimes temporary application control information needs to be manipulated in sufficient quantities to benefit from the use of database operations on that data. This information can be stored in a temporary working database, which is initialized when the
program begins and deleted when the program terminates.
db_REVISE uses just such a working database to control the restructuring of an old database into a new one. Thus, in db_REVISE three databases are opened and accessed at the
same time. db_QUERY uses a working database to perform sorting.
An accounting package is a good example of a modular database application. Most such
packages provide separate modules for various accounting functions. Companies only
purchase the modules they need. A typical package would include these modules :
General Ledger
Accounts Receivable
Accounts Payable
Payroll
Inventory
Sales Orders
Almost all the modules require the general ledger module. The amount of shared information between the other modules depends on the application.

Database Design

4-31

When designing an application that will use multiple databases, keep in mind that
inter-database relationships can exist, but can only be implemented through keys or
through the use of DB_ADDR fields containing the database addresses of records in
another database. It is not possible to have a set with an owner defined in one database
and a member defined in another. However, an account number stored in the accounts
receivable database can be used to find the associated account record in the general
ledger.

4.4.2 Physical Design Considerations


This section describes those aspects of the physical characteristics of an RDM database
that can impact the disk space usage and access performance of an application program.
An understanding of these physical implementation issues will help you design the most
efficient databases possible under RDM.

RDM File Structure


Data and key files consist of pages, which contain a specific number of fixed-length
record and key slots. Control information, as well as the normal record and key contents,
are stored in these fixed-length slots. The size of the record and key slots in a file is based
on the size of the largest record or key contained in that file. Smaller records or keys will
of necessity contain unused slot space.
The amount of control information in a key is always 10 bytes. However, the amount of
space required for the control information in a record varies, and can therefore have
database design implications.
The control information maintained by RDM in a record is as follows:

Record number (two bytes), required

Database address (four bytes), required

Optional key bit maps (one byte for every eight optional keys defined in the record)

If record type is timestamped, creation timestamp (four bytes)

If record type is timestamped, update timestamp (four bytes)

One set pointer (12 or 16 bytes) for each set for which record type is defined as an
owner. A set pointer for a timestamped set uses 16 bytes, otherwise only 12 bytes are
used

One member pointer (12 bytes) for each set for which record type is defined as a
member

4-32

Centura RDM Users Guide

The information to be considered in database design is the space required for set and
member pointers, as this is determined from the DDL.
Chapter 14, "File Formats and Dictionary Tables," describes in detail the structure of
RDM files, records, and keys.

Record and Key Placement


The factors that dictate the optimal placement of records and keys into files are not
always easy to determine, and are sometimes even mutually exclusive. Here are some
"rules of thumb" to assist you. Some of these involve conflicting requirements. The best
determination for your particular environment will be based on your own intuition
supported by some testing, but ultimately through experience gained from actual use.

Place dissimilar sized records and keys in separate files.


Minimizing the slot space that would be unused in the smaller records is the motivation for this guideline.

Place records and keys in separate files for better multi-user concurrency.
The chances of multiple users locking the same file is increased when several record
or key types are contained in the same file. Placing each key and record type in its
own file will minimize access conflicts.

Place owner and member record types in the same file for improved set access
performance.
If new owner and member record occurrences are stored and connected in the same
transaction and if they are located on the same file the likelihood of their being
placed on the same database page is increased. This could yield better set access
performance.

Minimize the number of separate key files to improve virtual memory performance.
Virtual memory is a technique in which frequently accessed database pages are kept
in memory, thus reducing the amount of actual disk input and output required.
Using fewer key files increases the probability that needed index pages will be in the
cache (that is, the virtual memory buffers).

Experiment with the size of the pages to change the number of slots per page.
Once the application is built, there will be only a fixed amount of memory left over
that can be used for the RDM cache. Some applications get better performance from
a smaller number of larger-sized pages that contain more slots per page. Other applications get better performance from a larger number of smaller-sized pages that
contain fewer slots per page.

Database Design

4-33

ddlp File Structure Report


The File Structure Report is produced by using the -r option on the ddlp command line.
This report summarizes the physical characteristics for each file and record type defined
in the DDL. The report produced for the checking account database is given below.
RDM Version 5.0 Summary of Database: ckngacct
Fri Dec 17 15:05:41 1999
FILE: chkg.dat
Id
: 0
Type
: data
Size of record slots: 88
Record slots per page : 5
Unused page space
: 68
FILE: chkg.k01
Id
: 1
Type
: key
Size of record slots: 16
Record slots per page : 63
Unused page space
: 6
FILE: chkg.k02
Id
: 2
Type
: key
Size of record slots: 12
Record slots per page : 169
Unused page space
: 10
RECORD: BUDGET
Id
: 0
File
: chkg.dat [0]
Total set pointers
Total member pointers
Offset to data
Size of record
Unused slot space

: 1
: 0

RECORD: CHECK
Id
: 1
File
: chkg.dat [0]
Total set pointers
Total member pointers
Offset to data
Size of record
Unused slot space

: 0
: 1

4-34

: 26
: 88
: 0

: 18
: 74
: 14

Centura RDM Users Guide

The summary for each data and key file includes the following:

File name

File id number

File type: data or key

Size of each record or key slot in bytes

Total number of slots per page

Total amount of unused page space

The information most significant to database design is the number of slots per page and
the amount of unused page space in a data file. The unused page space occurs because
the slot size multiplied by the number of slots per page does not always exactly equal the
size of the database page. Much of this unused space can be reserved by adding an extra
(unused) data field to the largest record on the file. The length of the field is computed as
follows:
length = (unused page space) / (slots per page)
The unused space is contained in a record so that if additional data needs to be stored in
that record, space will be available. If the reserved space is large enough, the new field
can be added without restructuring the database.
The record summary contains the following information.

Record name

Record number

File in which record is contained

Total number of set pointers (sets owned by record)

Total number of member pointers (sets in which record is member)

Offset to start of data from start of record

Total size of record in bytes

Amount of unused slot space

The design-related information in this report is the unused slot space. This space can
easily be converted into a usable form by adding an extra field the length of the unused
slot space to the record. Then, as explained above, the space is available for additional
data to be stored in the record at a later date, without requiring a restructure of the database.

Database Design

4-35

Also important in calculating the size of the records is the ordering and size of the data
types used in the record. Most systems require numeric data to start on word boundaries. This means that if the field preceding a numeric field does not end on a word
boundary, unseen and unusable padding is inserted to force the numeric data to the
word boundary. When character and numeric data are not carefully mixed, wasted
space can be generated.

File Page Sizes


To optimize file access performance, the page sizes for data and key files should be a
multiple of the file block size used by your operating system. Many systems have a block
size of 512 bytes. In these systems block sizes of 512, 1024, 1536, etc. would be acceptable.
The best page size for a given file is not always easily determined, and will be based on
application implementation details. Key file pages should be large enough to hold a
reasonable number of keys, so that the number of levels in the resulting B-tree are kept as
small as possible (less than or equal to four). Data file page sizes should be based on the
number of records you want to store on each page. For example, if all members of a set
are stored together, then they will likely be stored in contiguous record slots. If they will
usually be accessed together as well, then you may decide that the page size should be
large enough to hold the average number of set members in order to minimize the actual
disk accesses necessary to read each member.
The initial RDM runtime page buffers are sized based upon the largest page size
specified in the DDL. For example, if you have specified four files with a 1024-byte page
size and one file with a 4096-byte page size, RDM will allocate 4096 bytes for each page in
the cache. You need to be aware of your memory requirements in deciding on page
sizes.

4.5

Database Design Example

4.5.1 Introduction
The example to be presented in this section is an elaboration of the tims database introduced in Chapter 3. It will be used in examples throughout the remainder of this
document. A solid understanding of this example design is necessary.
The requirements for the tims application are given first, followed by a description of the
schema with explanations of how the design will be used to satisfy the stated
requirements.

4-36

Centura RDM Users Guide

4.5.2 Requirements
The system is to be used to maintain a database of technical information contained in
books, technical journals or magazines, and articles. In the following discussion, a single
book, journal issue, or article will be generally referred to as an info item.
The following data is to be stored for each book, journal, or article:
authors name
information id code
title
publisher
date published
abstract
topical key words
The id code will be a unique Dewey-Decimal library code assigned by the user. The
abstract will be a brief description (up to several paragraphs) of the info item. Each info
item may have several key words associated with it that identify topics discussed in it.
Functions are to be provided to allow info item entry and deletion.
The info item data is to be retrieved as follows:

By author name, where all info items for a given author are reported

By id code, through which individual occurrences can be found or all occurrences


can be retrieved in id code order

By key word, where all info items for a given key word are reported

The ability to keep track of loaned books and magazines is also to be provided, where the
borrowers name, the date borrowed, and the date returned are stored for each item
loaned. A loan history is to be maintained for each info item. In addition, the ability to
report all unreturned info items is to be provided.

Database Design

4-37

4.5.3 Database Design


The schema diagram for the database design is shown in Figure 4-5 below.

system
author_list
loan_history
author

has_published
articles
key_word

info
loaned_books

info_to_key
key_to_info
abstract
intersect

text

borrower

Fig. 4-5. tims Database Schema


The principal data for each info item is stored in a record called info. This includes the id
code, title, publisher, and publication date. Also included is a coded-value field for
storing the type of info, where 0 = book, 1 = journal or magazine and 2 = article. The id
code will be a key in order to quickly find specific info occurrences.
Because there may be many books or articles written by a single author, storing the
author name in the info record would replicate multiple occurrences of the same author.
This is often referred to as redundant data. So, the author is stored in a separate record
with a set, has_published, connecting an author to that authors info records.
Since the info records for a given author are to be retrievable by author name, a set,
ordered by author name, called author_list, has been defined with the system record as
the owner. To find a specified author, this set is searched. This is sufficient for a small
personal library where there would be relatively few authors (less than 100) and the
system is only used by a single user. In a large library with many authors, access would

4-38

Centura RDM Users Guide

be faster if we used the author name as a key field and did not use a set. Here (mainly
for instructional purposes), the assumption is that the system is for a small, personal
library.
A simple variable-length text structure is used for storing the abstract. A record type
called text is defined that stores a text string of up to 80 characters, including a sentinel
null byte. A set called abstract with order last is defined with info as owner and text as
member, forming a one-to-many set between an info record and each line of abstract text.
The relationship between key words and item info records is many-to-many. A key
word is stored in a record type named key_word. The key word is a string field that is
keyed to allow rapid retrieval of individual key word occurrences and to allow alphabetized key word perusal. The many-to-many relationship is implemented through the
use of two sets, as described in section 4.4.1, "Logical Design Considerations." Key_word
records and info records are connected to an intersection record called intersect. Set
key_to_info is used to find the info records corresponding to a particular key word. Set
info_to_key is used to find the key words associated with a given info record. The
intersect record has one field to hold a copy of the info type from its info owner through
the info_to_key set. By eliminating an extra disk read of the info record for non-books,
this facilitates the kind of key word searches where, for example, youre only interested
in finding the books covering a specific topic. Redundant data is sometimes incorporated
into a database design in order to improve data access performance.
A record type named borrower will contain the name of the borrower, the date loaned,
and the date returned. The borrowers name will be a key field, in order to be able to
quickly find all of the items borrowed by a particular person. Dates will be stored as a
long integer of the form YYMMDD (for example, 870709 is July 9, 1987). A date of zero
indicates that the loaned item has not yet been returned. When an item is loaned, a new
borrower record is created and is connected to two sets. A set called loaned_books
connects the borrower record to the info record for the loaned item. These records will
normally remain members of this set even after the item is returned, to maintain a loan
history for each item in the library. The borrower record is also connected to a set called
loan_history, which is owned by the system record. This set is scanned when a list of all
unreturned books is desired. Both sets are in last order so the records will be connected
in chronological order (without having to specify ascending order by date loaned).
One final set has been included. The set named article_list has info records participating
as both owner and member of the same set (which is legal in RDM). Here, the set is
intended to connect article info records to the info record of the journal or magazine in
which it is published.
The RDM DDL that implements the tims database design is presented on the next page.
Two data files and two key files have been defined. Data file tims.d01 contains the
system record (of which there is only one occurrence and is small because it has no

Database Design

4-39

fields), key_word records and intersect records. Data file tims.d02 contains the
occurrences of record types author, borrower, info, and text. This organization is arbitrary in this case since the database is not large.
Key field id_code is much smaller than keys friend and word and is therefore stored in a
separate key file, as is shown in the example below.
/*-------------------------------------------------------------------Technical Information Management System (TIMS) Database
--------------------------------------------------------------------*/
database tims
{
data file "tims.d01" contains system, key_word, intersect;
data file "tims.d02" contains author, borrower, info, text;
key file "tims.k01" contains id_code;
key file "tims.k02" contains friend, word;
record author {
char name[32];
}
record info {
unique key char id_code[16];
char info_title[80];
char publisher[32];
char pub_date[12];
int info_type;
}
record borrower {
key char friend[32];
long date_borrowed;
long date_returned;
}
record text {
char line[80];
}
record key_word {
unique key char word[32];
}
record intersect {
int int_type;
}

/* authors name: "last, first" */


/* or editors name */
/*
/*
/*
/*
/*

dewey dec. code */


title of book, article, mag. */
name of publisher */
date of publication */
0=book, 1=mag, 2=art */

/* name of borrower */
/* dates are stored initially */
/* numeric YYMMDD */
/* line of abstract text */
/* subject key words */
/* copy of info_type */

(continued)

4-40

Centura RDM Users Guide

(continued)
set author_list {
order ascending;
owner system;
member author by name;
}
set has_published {
order ascending;
owner author;
member info by info_title;
}
set articles {
order last;
owner info;
member info;
}
set loaned_books {
order last;
owner info;
member borrower;
}
set abstract {
order last;
owner info;
member text;
}
set key_to_info {
order last;
owner key_word;
member intersect;
}
set info_to_key {
order last;
owner info;
member intersect;
}
set loan_history {
order last;
owner system;
member borrower;
}
}

Database Design

4-41

Chapter 5
Database Manipulation
5.1

Introduction

RDM databases are manipulated by C language application programs through calls to


functions provided in the RDM runtime library. Database manipulation capabilities
include all functions needed to create, retrieve, modify and delete information in a
database. Also included are functions that control the operation of the RDM runtime
environment. The library functions that pertain specifically to multi-user database
manipulation are described in the RDM Multi-User Guide.
The runtime library functions are grouped into different categories based on each ones
purpose. See the list of categories below.
database control

Functions that open, close, and initialize databases, and


set runtime control parameters and options.

currency control

Functions that access and manipulate the currency tables.

data retrieval

Functions that access and read information from the database.

data creation

All functions used to store new information and relationships


in the database.

data modification Functions that modify information and relationships stored


in the database.
data deletion

Functions used to remove information and relationships


from the database.

Note that all RDM function names are prefixed by d_ or dt_ (for example, d_keyfind or
dt_opentask) so as to avoid name conflicts with other user or system library functions.
The return value of all RDM functions is an integer completion status for the requested
operation. A status code of zero (S_OKAY) indicates that the operation completed
successfully. These status codes will be introduced as required in the discussions that
follow. A complete list can be found in section 5.8, "Database Error Reporting," and
complete descriptions are provided in the RDM Reference Manual.

Database Manipulation

5-1

The purpose of this chapter is to introduce the use of the principal functions through
explanation and examples. Complete details relating to the use of each function are
provided in the RDM Reference Manual.
Most of the RDM functions must be passed a database number. In the examples, a
constant called CURR_DB has been passed to the functions. The database number must
always be passed, even when only one database is open. See section 5.9.2, "Accessing
Multiple Databases," for complete details regarding multiple database access and the
database number argument.

5.2

Database Control

Database control functions provide control over the runtime systems operational
environment. They provide for the opening and closing of databases, location and names
of database files, initialization of databases and files, and various runtime tuning
parameters and options.
The database control functions are listed in Table 5-1 and have been grouped into two
categories. The "pre-open" functions are those that can only be called prior to a d_open
call, which opens the database. The "post-open" functions can only be called after the
database has been opened. Functions d_off_opt and d_on_opt, however, can be
executed either before or after the database is opened.

5-2

Centura RDM Users Guide

Table 5-1. Database Control Functions

Pre-Database Open Functions


d_dbdpath(dbd_dir)
dictionary.

Set path to directory containing the database

d_dbfpath(dbf_dir)

Set path to directory containing the database files.

d_dblog(log_name)

Set path or name of the database transaction log file.

d_dbtaf(taf_name)

Set path or name of the database family


transaction activity file.

d_dbtmp(tmp_dir)

Set path to directory to contain temporary files.

d_ctbpath(ctb_dir)

Set path to directory containing the country table file.

d_lockcomm(lm_type)

Set the protocol type of the lock manager.

d_lockmgr(lm_name)

Set name of lock manager.

d_checkid(userid)

Check a userid to see if it is valid and unique.

d_dbuserid(userid)

Set database user identifier.

d_open(dbnames, mode)

Open a (set of) database(s).

d_renfile(dbname, FILE,filenm)

Substitute a database file.

d_renclean()
commands.

Clean up all memory related to previous renfile

d_setfiles(num)

Set the maximum number of open files.

d_setpages(num, num)

Set the number of pages in the cache.

d_rdmini(ini_dir)

Set path to the RDM initialization file.

Post-Database Open Functions


d_close()

Close database.

d_closeall()
databases).

Close all open data and key file handles (not

d_destroy(dbn)

Destroy (delete) all data and key files in the database.

d_iclose(dbn)

Incrementally close a database.

d_initfile(FILE, dbn)

Initialize a database file.

d_initialize(dbn)

Initialize all database files.

d_iopen(dbnames)

Incrementally open a (set of) database(s).

d_off_opt(options)

Turn off specified runtime options.

d_on_opt(options)

Turn on specified runtime options.

Database Manipulation

5-3

5.2.1 Opening and Closing Databases


Function d_open is called to open a database. It is called with the name(s) of the
database(s) to be opened and a parameter that identifies the mode of database access (see
Chapter 6, "Transaction Processing").
For example, the following code will open database tims in exclusive access:
d_open("tims", "x");

Database access or update functions called prior to a successful opening of the database
will return error code S_DBOPEN.
When d_open is called, the RDM runtime library will allocate and initialize memory
space for all of its internal tables, and will read into memory the database dictionary for
the requested databases. Memory is also allocated for the RDM cache. If there is not
enough memory available for the tables or cache, d_open will return status code
S_NOMEMORY.
Function d_close will close all open databases by flushing all buffers, closing all database
files, and freeing all of its dynamically allocated memory.
Note: The database should always be closed before a program terminates. Failure to do
so could impair the integrity of (that is, corrupt) the database.
If a subsequent d_open call is made before the first database is closed, RDM will abort
any active transaction, close the open database(s), and open the new database(s). (See
section 5.9, "Multiple Database Access," to learn how to open and access more than one
database at a time.)

5.2.2 Operational Environment


RDM databases are composed of the following files:
Dictionary files:
dbname.dbd

Database Dictionary

Control files:
vista.taf

Transaction Activity File

vista.ctb

International Character Set Mapping File

userid.log

Database Overflow/log File

rdm.ini Initialization File for settings and options


Database files:
Data and key files are defined in the DDL specification

5-4

Centura RDM Users Guide

Unless otherwise specified, all files are located in the users current (or working)
directory.
Several techniques are available for providing the path names of alternative directories
for the dictionary, control, and database files.

Path Specification in d_open


The name of the database, as passed to function d_open, can include a path name of the
directory containing the dictionary and database files. The path name may be absolute or
relative. See the following example for Windows.
d_open("\\timsdb\\tims", "x");

The same example for UNIX,


d_open("/timsdb/tims", "x");

This example will prefix \timsdb\ to all file specifications as specified in the DDL,
including any directory path. Thus the file specification for the dictionary would be
\timsdb\tims.dbd and the spec for the data file would be \timsdb\tims.dat.
Multiple databases (see section 5.9, "Multiple Database Access") that are located in
different directories can be opened simply by providing d_open with the appropriate
path names, as in the following example:
d_open("\\centura\\tims;\\acme\\tims", "x");

Here, database 0 would be the tims database for Centura and database 1 would be the
tims database for Acme. Both directories would need to contain the dictionary file
tims.dbd even if they are identical. (Under UNIX they could be linked.)

Environment Variables
Five UNIX environment variables can be used to identify the directories that contain the
dictionary, control, and database files.
The directory containing the dictionary files can be specified by an environment variable
named DBDPATH. The directory that is to contain the database files can be specified by
an environment variable named DBFPATH, shown in the following example.
set DBDPATH=\dbdefs\
set DBFPATH=\timsdb\

Note: Function d_open will append a backslash (\), or slash (/) in UNIX, to these path
names if not specified.
Assume that the DDL for database tims includes the following data and key file
statements:

Database Manipulation

5-5

data file "centura\tims.dat" contains ...


key file "centura\tims.key" contains ...

When the database is opened, RDM would expect to find file tims.dbd in directory
\dbdefs (that is, the file specification for the dictionary would be \dbdefs\tims.dbd).
The file specifications for the database files would be \timsdb\centura\tims.dat and
\timsdb\centura\tims.key.
In addition to the above, the d_open call may contain a partial path name:
d_open( "wayne\\tims", "x" );

In this case the additional path specification (wayne\) placement would precede the
DBDPATH or DBFPATH values. The resulting file names are shown below:
\dbdefs\wayne\tims.dbd
\timsdb\wayne\centura\tims.dat
\timsdb\wayne\centura\tims.key

You can provide any combination of path specifications in the environment variables
DBDPATH and DBFPATH, in the d_open statement, and in the schema. The resulting
paths to the data and key files are built according to the following rules:

A path is considered absolute if it starts with a directory character ("/" for UNIX).
Otherwise the path is considered relative. Device (or logical device) specifications
are transparent.
For example, on Windows, c:\users\mis is considered an absolute path, whereas
c:users\mis is relative.

The final path is constructed by concatenating the various paths from the various
sources. Construction stops when the final path becomes absolute.

Construction of the final path works backward. When a path precedes the final path,
any previous device designator is thrown away (for example, a:sys\users put in
front of c:mis results in a:sys\users\mis).

In constructing the final path for the dictionary file, the (optional) path supplied to
d_open is used, preceded by the (optional) path in the environment variable
DBDPATH.

In constructing the final path for the data and key files, the (optional) path in the
schema is used, preceded by the (optional) path supplied to d_open, with the
(optional) path in the environment variable DBFPATH preceding all.

Consider the examples below.

5-6

Centura RDM Users Guide

Case 1 - No path information:


Environment variable values:
set DBDPATH=
set DBFPATH=

Application code d_open statement:


d_open( "tims", "o" );

DDL specification of files:


data file "tims.dat" contains ...
key file "tims.key" contains ...

Resulting file names:


tims.dbd
tims.dat
tims.key

Case 2 - Overriding a default drive with environment variables


Environment variable values:
set DBDPATH=c:
set DBFPATH=c:

Application code d_open statement:


d_open( "tims", "o" );

DDL specification of files:


data file "m:tims.dat" contains ...
key file "m:tims.key" contains ...

Resulting file names:


c:tims.dbd
c:tims.dat
c:tims.key

Database Manipulation

5-7

Case 3 - Environment variables overridden by d_open statement:


Environment variable values:
set DBDPATH=\dbd_dir
set DBFPATH=\dbf_dir

Application code d_open statement:


d_open( "c:\\tims", "o" );

DDL specification of files:


data file "dat\tims.dat" contains ...
key file "key\tims.key" contains ...

Resulting file names:


c:\tims.dbd
c:\dat\tims.dat
c:\key\tims.key
Both DBDPATH and DBFPATH can contain multiple elements, separated by semicolons.
The elements in the path variables correspond one-for-one with the database numbers of
multiple open databases; they are not search paths. For example, the environment
variables may have the following settings:
set DBDPATH=d:\sales;d:\invntory
set DBFPATH=c:\dbfiles;c:\dbfiles

Look at the following:


d_open( "sales;invntory", "s" );

This open will find the sales dictionary in d:\sales\sales.dbd, the sales data and key files
in c:\dbfiles\, the inventory dictionary in d:\invntory, and the inventory data and key
files in c:\dbfiles\.
The same paths would be used if the second database were incrementally opened:
d_open( "sales", "s" );
...
d_iopen( "invntory" );

If the number of elements in one of the path variables is less than the database number of
an open database, then the "extra" databases get no path. However, if only one path is
given, it applies to all databases. Note that the DBFPATH shown above did not need to
contain the same directory twice. The following value would have the same effect:
set DBFPATH=c:\dbfiles

5-8

Centura RDM Users Guide

A path may contain null elements. If the path ends in a semi-colon, then all subsequent
elements are null and the search will be made in the current directory. For example, the
following DBDPATH contains a null element 1, and DBFPATH contains null elements 1,
2, ...
set DBDPATH=c:\sales;;c:\sales
set DBFPATH=c:\dbfiles;

The location and name of the transaction activity file (see section 6.2, "Operational
Environment") can be specified with environment variable DBTAF. Environment
variable DBLOG can be used to specify the location and name of the database log file. If
either variable ends with the directory separator character ("/" on UNIX), the default file
names are appended to the specified path name in order to form the fully qualified file
name. The default file names are vista.taf for the transaction activity file and userid.log
for the log file, and are assumed to be located in the working (or current) directory. If the
environment variable does not end with the directory separator character, RDM will
assume that the variable is the complete file name.
The userid must be defined either through an environment variable called DBUSERID or
through function d_dbuserid (as described in the next section). There is no default. The
user identifier is used to activate communication between the RDM user and the lock
manager, and is used in the forming of the default name of the users database log file.
Note that the userid is only needed when the database is opened in shared or exclusive
access mode. It is not needed in one-user mode or in the single-user version.
There is only one transaction activity file across the system for each database family, and
it must be accessible to every user. Each user must have his or her own individual log
file, which must also be accessible to all users on the system. Also, all log files for each
database family must be located in the same physical directory.

Environment Control Functions


For each of the environment variables discussed in the preceding section, there is an
RDM runtime function that allows dynamic setting of the variable. Each of these
functions is passed a string specifying the value of the appropriate environment variable.
Table 5-2 shows the relationship of these functions to each of the environment variables.
If used, these functions must be called before the database is opened. Also, all the above
mentioned environment variables except DBUSERID could be placed in the rdm.ini file
instead of the environment.

Database Manipulation

5-9

Table 5-2. Environment Variables and Related Functions


Environment
Variable
DBUSERID

Function
Name
d_dbuserid

DBDPATH

d_dbdpath

Set path to directory containing the


dictionary and header files.

DBFPATH

d_dbfpath

Set path to directory containing


the database files.

DBLOG

d_dblog

Set path or name of database log file.

DBTAF

d_dbtaf

Set path or name of database family


transaction activity file.

LOCKMGR

d_lockmgr

Set the name of the lock manager


to be used by this application.

Description
Set database user identifier.

Substituting Database Files


Alternate names for data and key files can be specified at runtime, prior to opening a
database, through use of the d_renfile function. In order to use this function, however, a
file identifier must be provided in the DDL data and key file statements for those files
that are to be renamed. The DDL file statement syntax including the specification of a
file identifier is as follows:
data file [fileid =] filename contains recname [,recname]... ;
key file [fileid =] filename contains recname [,recname]... ;
If provided, fileid must be an identifier. It will be included in dbname.h as a #define
constant that is defined to be the file table dictionary entry number for the specified data
or key file.
See the example below:
database tims {
data file timsdat = "tims.dat" contains ...;
key file timskey = "tims.key" contains ...;
...

File tims.h would include the following constants:


#define
#define

TIMSDAT 0
TIMSKEY 1

Function d_renfile could then be used to substitute the files as follows:


d_renfile("tims", TIMSDAT, "centura.dat");
d_renfile("tims", TIMSKEY, "centura.key");
d_open("tims","x");

5-10

Centura RDM Users Guide

The calls to d_renfile must be issued prior to the call to d_open of database tims. The
name of the database needs to be specified in the d_renfile call, to distinguish between
files contained in different databases if more than one is opened.
Note: When d_open is locating the database files, the database file specification
provided in the d_renfile call overrides the environment variable (DBFPATH) and any
path prefix to the database name. The dictionary and control file specifications are
unaffected.
The d_renfile function has a companion function, d_renclean. Function d_renclean can
only be called while all databases are closed, and will clean up all memory and references
used by d_renfile. This allows switching back and forth between databases as seen in
the following example. In this example, there are two copies of the data files, one copy
that is shared by everyone on the network (drive s:) and the other one on the users hard
drive (drive c:).
d_open("tims", "s");
/* normal processing on network copy */
d_close();
d_renfile("tims", TIMSDAT, "c:\\tims\\tims.dat");
d_renfile("tims", TIMSKEY, "c:\\tims\\tims.key"):
d_open("tims", "o"):
/* processing on the local copy */
d_close();
d_renclean();
*/

/* clean up all memory from previous d_renfile functions.

d_open("tims", "s");
/* back to processing on the network copy */
d_close();

5.2.3 Dynamic Database Initialization


Dynamic database initialization functions allow a program to initialize an entire
database, or one or more files, in a database at program execution time. These functions
are useful when a first-time initialization needs to be included as part of an application or
when a temporary database is needed.
Note: These functions will destroy existing data. They are not part of a normal database
open sequence.
Function d_initialize will initialize all database data and key files associated with the
open database. In multi-user environments, it can only be called when the database is
opened in exclusive access mode or exclusive locks have been placed on all the files.
Function d_destroy is called to close the database and to delete all of the database files
comprising the open database.

Database Manipulation

5-11

Note: If d_renfile has been called, d_destroy will remove the new file names and leave
the original ones untouched.
Individual files that have a fileid specified in the DDL file statement can be initialized
using function d_initfile. For example, the following DDL defines files that keep track of
a daily user login history:
key file day_key = "dayfile.key" contains login_id;
data file day_data = "dayfile.dat" contains login_history;

These files are initialized by the application when the user logs in at the beginning of the
day, as follows:
#include "vista.h"
#include "login.h"
#include "mis.h"
...
/* Open Login and Mgt Info System databases */
d_open("login;mis", "s");
/* Since each user has his own login file, an
exclusive lock on that file will preclude the use of
other locks and yield better performance. */
d_reclock(LOGIN_HISTORY, "x", CURR_DB);
/* Initialize daily login files */
d_initfile(DAY_KEY, CURR_DB);
d_initfile(DAY_DATA, CURR_DB);
...

5.2.4 Runtime Control


Runtime control functions inform the RDM runtime of the maximum number of files that
can be opened at a time and the size of the database cache, and are used to turn on or off
one or more of several runtime options. These functions provide the flexibility to tune
runtime performance to meet the requirements of individual applications.

Maximum Open Files


Many operating systems impose a limitation on the number of files that an application
program can have open at one time. UNIX usually has an upper limit of 20 open files.
Many database management systems restrict the maximum number of files in a database
to this operating system limit, but RDM allows up to 256 files to be accessed in a single
database. This is done by dynamically opening and closing files as necessary to keep the
number of open files within the operating systems limit.
Before the database is opened, the program must inform RDM of the maximum number
of data and key file handles it can have open at a time. This is accomplished with
function d_setfiles, which is passed an integer value specifying this maximum. Function
d_setfiles must be called before the database is opened, and the value passed must be

5-12

Centura RDM Users Guide

less than or equal to the operating system limit, minus the maximum number of
additional files the application will have open at a time. The default is a maximum of
eight open files at a time.
For example, normally a standard C program will have (at least) five files open upon
initiation: stdin, stdout, stderr, stdprn, and stdaux . If the operating system limit is 20,
then the following call will ensure that RDM will not open too many files:
d_setfiles(15);
d_open("tims");

/* RDM can open 15 files */


/* Open database "tims" */

Setting the number of open files too small may result in some performance degradation
due to unnecessary file closings and openings.
If there are occasions when the application needs more file handles than are available, it
is possible to tell the runtime to close all files it currently holds open. The d_closeall
function, which takes no parameters, will close all files under RDM control that are
currently open. The files will be re-opened as needed. If this function is used frequently,
overall performance will decrease due to the extra opening and closing of files.

Size of Runtime Cache


RDM performs all input and output for the database files through a cache consisting of a
fixed number of database page buffers. This technique yields large performance benefits
by reducing the number of actual disk accesses required to read or write information in
the database.
The programmer can specify the number of buffers to allocate for the cache with function
d_setpages. In general, the more pages specified the better the potential performance
gains. The first argument to this function specifies the number of pages in the standard
database cache. A second argument specifies the number of pages in the transaction
overflow-index cache (which should be small because an overflow should occur
infrequently).
If d_setpages is not called, RDM will allocate 17 pages in the database cache and five
pages in the transaction overflow cache. The cache lookups are performed using a
hashing algorithm, as shown below:
d_setpages(128, 4);

The initial size of the pages allocated for the database cache will be equal to the size of
the largest page in the database. Thus, if the largest page is 4096 bytes long, then the
database cache in the above example will occupy 524K bytes (128 * 4096). The size of the
pages in the overflow cache is fixed at 1024 bytes. If there is not enough memory
available to accommodate the requested number of pages, function d_open will return
status S_NOMEMORY.

Database Manipulation

5-13

Option Settings
Various runtime option settings allow you to do these activities plus others:

Turn on or off the use of delete chain slots (for when new records are created)

Turn on or off transaction logging and recovery

Turn on or off archive logging

Change between case-insensitive and case-sensitive sorting

Dictate how often to close files

Dictate exclusive use of GlobalAlloc (in Windows)

Rather than supplying separate functions to control the setting of these runtime options,
RDM provides two parameter-based system option setting functions called d_on_opt
and d_off_opt. These functions are passed a bit status word, which has a bit associated
with each option. These options have been assigned constants in vista.h. See the RDM
Reference Manual for a complete list.
Here are some examples. To turn on delete chain usage and archive logging:
d_on_opt(DBCHAINUSE | ARCLOGGING);
To turn off transaction logging and archive logging:
d_off_opt(TRLOGGING | ARCLOGGING);
Transaction and archive logging are discussed in Chapter 6, "Transaction Processing."
The ability to turn on or off the use of deleted record slots provides some application
control over the placement of related records in the database. If all member record
occurrences of a given set are entered together, and use of the delete chain is turned off,
the records will all be physically placed in the order in which theyre entered at the end
of the data file. This will improve performance when, later, they are all accessed
together.
To establish case-insensitive sorting with keys:
d_on_opt(IGNORECASE );
This option will re-define the collating sequence of characters, and must be used for the
lifetime of a database. You cannot build a database with this option turned on, then later
use it with it turned off.
When an environment requires minimum use of file handles, you may need to use the
CLOSEFILES option, which will cause all open file handles to be closed before an RDM

5-14

Centura RDM Users Guide

function returns. This is often needed in Microsoft Windows. Be sure, however, that this
is needed, because it can have a detrimental effect on performance.
When RDM allocates memory in the Microsoft Windows environment, it will use
LocalAlloc calls when the allocation is small (less than 128 bytes). If local memory is
exhausted, or if the allocation is greater than 128 bytes, GlobalAlloc is used. If an
applications data segment is full, RDM may be instructed to use GlobalAlloc exclusively,
by setting the GLOBALALLOCS option.
The initial settings have transaction logging and delete chain use turned on and archive
logging, case-insensitive sorting, automatic file closing, global allocation, and session
status call restriction turned off.

5.3

Currency Tables

All of the data contained in an RDM database is accessed through use of the currency
tables. Thus, a thorough understanding of the use of these tables is necessary.
The retrieval of RDM data is always a two-step process. First the location of the data is
established, and then the data is read. The located data is always in the form of a specific
record occurrence. The database address of a record is the location in the database where
the record is stored. The currency tables contain database addresses as follows:
current record

The database address of the most recently accessed record


occurrence.

current owner

The database address of an owner record occurrence for the set.


There is a current owner entry for each set in the database.

current member The database address of a member record occurrence for the set.
There is a current member entry for each set in the database.
A currency table value is established through the record location functions (for example,
d_keyfind or d_findnm), and through additional functions that directly modify currency
table entries (for example, d_setor copies the current record value to the current owner
entry of the specified set). Once a record has been located, its database address is
automatically stored in the currency table. Its contents can then be read (for example,
d_recread reads the contents of the current record).
Locating record occurrences through set relationships directly involves manipulation of
the currency tables. This process is called set navigation. The currency tables are used
to keep track of the path through the network of set relationships that was followed to
arrive at a particular record occurrence.

Database Manipulation

5-15

A portion of the tims database schema is given in Figure 5-1, with an example of a
possible currency table state showing pointers to particular record occurrences in the
database.

SCHEMA
system

DATABASE

CURRENCY TABLES

system

current owner
author_list

author

Flavin, M.
Knuth, D.
Kruglinski, D.

has_published
abstract

Fundamentals of Info

current member
author_list

info

Fundamental Algorithms
Semi-numerical Algorithms
Searching and Sorting

has_published
abstract

Database Management ...

current record

text

The definitive text on ...


searching and sorting
internal and external ...

Fig. 5-1. Example Currency Table


Because of the importance of the currency tables, a rich set of functions is provided to
give the programmer complete control over currency table settings. These functions are
listed in Table 5-3. The d_setXY functions have a naming convention in which X specifies
the destination currency and Y specifies the source currency for the assignment
operation. For example, in d_setro, the r indicates that the current record is to be
assigned and the o indicates that it is to be assigned from the current owner of the
specified set. Use of the currency tables will be explained in the sections which follow.

5-16

Centura RDM Users Guide

Table 5-3. Currency Control Functions


Currency Manipulation Functions
d_setro(SET, dbn)

Set current record from current owner of SET.

d_setrm(SET, dbn)

Set current record from current member of SET.

d_setor(SET, dbn)

Set current owner of SET from current record.

d_setom(SET1, SET2, dbn)

Set current owner of SET1 from current member of SET2.

d_setoo(SET1, SET2, dbn)

Set current owner of SET1 from current owner of SET2.

d_setmr(SET, dbn)

Set current member of SET from current record.

d_setmo(SET1, SET2, dbn)

Set current member of SET1 from current owner of SET2.

d_setmm(SET1, SET2, dbn) Set current member of SET1 from current member of SET2.
Currency Access Functions
d_crget(dba, dbn)

Get database address of current record.

d_crset(dba, dbn)

Set database address of current record.

d_csmget(SET, dba, dbn)

Get database address of current member of SET.

d_csmset(SET, dba, dbn)

Set database address of current member of SET.

d_csoget(SET, dba, dbn)

Get database address of current owner of SET.

d_csoset(SET, dba, dbn)

Set database address of current owner of SET.

Database Manipulation

5-17

5.4

Data Retrieval

Table 5-4 lists the functions used for data retrieval.


Table 5-4. Data Retrieval Functions
Key Access Functions
d_keyfrst(KEY, dbn)
d_keylast(KEY, dbn)
d_keyfind(KEY, val, dbn)
d_keynext(KEY, dbn)
d_keyprev(KEY, dbn)
d_keyread(val, dbn)
d_curkey(dbn)

Find record with first KEY.


Find record with last KEY.
Find first record with exactly matching KEY.
Find record with next KEY.
Find record with previous KEY.
Read contents of last key scanned.
Set current keys from current record.

Set Navigation Functions


d_findfm(SET, dbn)
d_findlm(SET, dbn)
d_findnm(SET, dbn)
d_findpm(SET, dbn)
d_findco(SET, dbn)

Find first member of SET.


Find last member of SET.
Find next member of SET.
Find previous member of SET.
Find owner of current record.

Direct Access Retrieval Functions


d_recfrst(REC, dbn)
d_reclast(REC, dbn)
d_recnext(dbn)
d_recprev(dbn)
d_recset(REC, dbn)
d_recread(val, dbn)
d_crread(FLD, val, dbn)
d_csmread(SET, FLD, val, dbn)
d_csoread(SET, FLD, val, dbn)
d_encode_dba(file, slot, dba)
d_decode_dba(dba, file, slot)

Find first occurrence of record type REC.


Find last occurrence of record type REC.
Find next occurrence of current record type.
Find previous occurrence of current record type.
Set the current occurrence of the record type
to the current record.
Read whole contents of current record.
Read data from field of current record.
Read data from field of current member.
Read data from field of current owner.
Encode database address from file and slot number.
Decode file and slot number from database address.

Record occurrences are located using RDMs key retrieval functions, set navigation
functions, direct access, or any combination of these.

5-18

Centura RDM Users Guide

5.4.1 Data Retrieval Using Keys


Key field usage from the database design perspective was introduced in section 4.4.1,
"Logical Design Considerations." The database manipulation aspects of key field usage is
presented here, using the C code that would implement the examples presented in that
section.

Code Validation
The following example from the "vehicle make" example illustrates how to use keys to
validate coded data fields.
char vma_desc[25];
struct fleet f;

/* variable to contain vehicle make */


/* variable to hold a fleet record */

get_user_info(&f);

/* fleet record entered by user */

/* validate correct vehicle make code */


if (d_keyfind(VMA_CODE, f.vma, CURR_DB) == S_NOTFOUND)
entry_error("invalid vma code");
else
{
/* read vehicle description */
d_crread(VMA_DESC, vma_desc, CURR_DB);
/* enter fleet record */
...
}

The vehicle make code entered by the user as part of the fleet record is used as the key
value argument of the d_keyfind function, to check that a vehicle record for that make
exists in the database. If the record does exist, its description is read (function d_crread)
and is displayed to the user once the record entry is completed. VMA_CODE and
VMA_DESC are constants defined in the database header file created by ddlp. The
second argument to both d_keyfind and d_crread are pointers to the variables that
contain the necessary data.

Retrieval Based On a Range of Values


Recall from the "checking account" database example of Chapter 4, "Database Design,"
that the check record type contained a key field called check_date. This field was
defined as a key field to facilitate rapid retrieval of the check record occurrences for a
particular time period. The example code below prints the checks dated in the month of
May, 1993.

Database Manipulation

5-19

struct check chk;


int start_date;
int end_date;
int date;

/* check record variable */


/* julian of start date of range */
/* julian of end date of range */
/* last scanned check date */

/* application functions found elsewhere */


extern char *calendar();
/* converts julian to calendar date */
extern int julian();
/* converts calendar to julian date */
start_date = julian("05/01/93");
end_date
= julian("05/31/93");
/* position to first key in range */
if (d_keyfind(CHECK_DATE, &start_date, CURR_DB) == S_NOTFOUND)
d_keynext(CHECK_DATE, CURR_DB);
/* scan thru all keys in range */
while (db_status == S_OKAY)
{
d_keyread(&date, CURR_DB);
if (date > end_date)
break;
/* no longer in range */
d_recread(&chk, CURR_DB);
printf("number
: %d\n", chk.check_no);
printf("date
: %s\n", calendar(chk.check_date));
printf("paid to : %s\n", chk.paid_to);
printf("amount
: $ %f.2\n", chk.amount);
d_keynext(CHECK_DATE, CURR_DB);
}

The d_keyfind call will position to the first check date key equal to start date. If there are
no checks dated 05/01/93 on file, then function d_keynext is called to position to the first
check whose date is greater than the start date. The while loop first reads the value of
the positioned key using function d_keyread. Note that this reads the key value only
and does not read the record. The record contents are only read if the check date
returned from the d_keyread call is within the desired range. Function d_recread reads
the contents of the current record for display by the subsequent printf calls. The final
d_keynext call positions to the next check date key.

Complex Searches
The m.o. (modus operandi) example of Chapter 4, "Database Design," introduced how
complex searches can be rapidly performed through the use of keys. The m.o. record
consists of a single 25-byte key field in which each element of the array represents a
coded m.o. attribute.
The simplest approach is to scan through all of the mo_data keys, checking each one for a
match, as follows:

5-20

Centura RDM Users Guide

char mo_key[25];
/* m.o. key is 25 byte array */
char mo_search[25]; /* user entered search data */
int status;
...

/* user enters m.o. search data */

for (
status = d_keyfrst(MO_DATA, CURR_DB);
status == S_OKAY;
status = d_keynext(MO_DATA, CURR_DB) )
{
d_keyread(mo_key);
if (mo_match(mo_key, mo_search))
...
/* report match */
}

Function mo_match checks the m.o. key against the m.o. search data entered by the user,
returning true (that is, non-zero) if they match and false (that is, zero) if they do not. A
zero value in an m.o. search data element means that attribute is not to be used in the
search.
/* Check for matching m.o.s */
mo_match(mo1, mo2)
char *mo1;
char *mo2;
{
int x;
for ( x = 0; x < 25; ++x )
{
if ((mo2[x] != 0) && (mo1[x] != mo2[x]))
return (0);
}
return (1);
}

Since keys are sorted, the number of keys that need to be scanned can be reduced when
the first element (and any subsequent elements) is non-zero. For example, if the user has
supplied m.o. values for the first three elements, a key scan of only the keys on file with
those values can be performed, yielding great performance improvements.

Database Manipulation

5-21

char mo_key[25];
/* m.o. key is 25 byte array */
char mo_search[25]; /* user entered search data */
int mo_prefix;
/* initial non-0 elements in mo_search */
int lc;
/* loop control index */
...

/* user enters m.o. search data */

/* compute mo_prefix */
for (mo_prefix = 0; mo_search[mo_prefix] != 0; ++mo_prefix)
;
/* count number of initial non-0 elements */
/* initialize mo_key */
for (lc = 0; lc < 25; ++lc)
{
if ( lc < mo_prefix )
mo_key[lc] = mo_search[lc];
else
mo_key[lc] = 0;
}
/* position to first key with matching prefix */
if (d_keyfind(MO_DATA, mo_key, CURR_DB) == S_NOTFOUND)
d_keynext(MO_DATA, CURR_DB);
/* scan all keys with matching prefix */
while (db_status == S_OKAY)
{
d_keyread(mo_key);
/* ensure prefix still matches */
for (lc = 0; (lc < mo_prefix) && (mo_key[lc] == mo_search[lc]); ++lc)
;
if (i < mo_prefix)
break;
/* prefix doesnt match - scan ends here */
if (mo_match(mo_key, mo_search))
...
/* report match */
d_keynext(MO_DATA, CURR_DB);
}

Notice that this example is very similar to the example of retrieval by a range of values.
Also notice that if the first element of mo_search is zero, all mo_data keys will be
checked.

Using Compound Keys


Suppose that the tims borrower record definition (presented in section 4.5.3, "Database
Design") were modified such that the friends name was not one field, but two (for the
last and first name). A compound key may be defined to make one key from the two
fields:

5-22

Centura RDM Users Guide

record borrower
{
key char
fr_last[16];
char
fr_first[16];
long
date_borrowed;
long
date_returned;
compound unique key friend
{
fr_last;
fr_first;
}
}

Note that the last name may be used as a key by itself. A new key definition, named
friend, is defined in the record. (It must also be included in a key file list.)
When ddlp encounters a compound key, it creates a special structure for the key in the
header file it generates. In this case, within tims.h will be the following structure
definition:
struct friend {
char fr_last[16];
char fr_first[16];
};

The definition is intended to be used to perform searches for compound keys, as in the
following code fragment:
#include "tims.h"
...
struct friend fr;
...
printf("Last name: ");
gets(fr.fr_last);
printf("First name: ");
gets(fr.fr_first);
if (d_keyfind(FRIEND, &fr, CURR_DB) == S_NOTFOUND)
printf( "No one by that name found\n" );
else {
/* use the borrower record */

5.4.2 Data Retrieval Using Sets


The process of retrieving records from a database by moving through the various set
relationships defined in the schema is called set navigation. A general procedure for
navigating sets follows:
1.

Find the record that is the owner of the set whose members are to be read. Typically,
this can be done using keys, by iteratively applying this procedure, or by a
combination of both.

Database Manipulation

5-23

2.

Make the located owner record the current owner of the set to be traversed, using an
appropriate currency manipulation function (such as d_setor).

3.

Find the members of the set, using the set navigation functions (for example,
d_findnm will set the current record and current member of the set to the next
member record).

Each of the set member find functions (d_findXm) will set both the current member and
the current record to point to the found record occurrence. A reciprocal function,
d_findco, will set the current owner of the specified set from a current record that is
connected through the specified set. The currency changes made by each RDM function
are identified in the function descriptions in the RDM Reference Manual.
As an example of the above procedure, consider the transactions set from the checking
account example in Chapter 4, "Database Design." The budget record is the owner and
the check record is the member. The following code will display all of the checks written
against budget category FOOD.
/* locate the budget record for the FOOD budget */
d_keyfind(CODE, "FOOD", CURR_DB);
/* make the FOOD budget the current owner of set transactions */
d_setor(TRANSACTIONS, CURR_DB);
/* find each member of the set and read and print its contents */
for (
d_findfm(TRANSACTIONS, CURR_DB);
db_status == S_OKAY;
d_findnm(TRANSACTIONS, CURR_DB))
{
d_recread(&chk, CURR_DB);
... /* print check record */
}

The set navigation procedure above describes a top-down navigation, wherein the owner
is located and then the members. RDM also provides the ability to first locate a member
and then the owner by using function d_findco, which finds the owner of the current
record for the specified set. For example, the following code will locate a check record by
check number, and then find and print its budget category.

5-24

Centura RDM Users Guide

struct check chk;


struct budget bud;

/* check record variable */


/* budget record variable */

/* locate check numbered 3104 */


chk.check_no = 3104;
d_keyfind(CHECK_NO, &chk.check_no, CURR_DB);
/* read check record contents */
d_recread(&chk, CURR_DB);
/* find its owner thru the transactions set */
d_findco(TRANSACTIONS, CURR_DB);
/* read budget record contents */
d_recread(&bud, CURR_DB);
/* print results */
printf("check
: %d\n", chk.check_no);
printf("date
: %s\n", calendar(chk.check_date));
printf("paid to
: %s\n", chk.paid_to);
printf("amount
: $ %f.2\n", chk.amount);
printf("budget
: %s\n", bud.code);

Many-to-Many Navigation
The navigation of the students to classes, many-to-many, set example in Chapter 4,
"Database Design," is shown in the following code, which lists the students registered in
class CS101.
struct class crec; /* class record variable */
struct student srec;/* student record variable */
/* find CS101 class record */
d_keyfind(CLASS_ID, "CS101", CURR_DB);
/* read contents of class record */
d_recread(&crec, CURR_DB);
/* make the class record owner of the my_students set */
d_setor(MY_STUDENTS, CURR_DB);
/* scan each member of my_students set */
while (d_findnm(MY_STUDENTS, CURR_DB) == S_OKAY)
{
/* find student record which owns current intersect record */
d_findco(MY_CLASSES, CURR_DB);
/* read and print contents of student record */
d_recread(&srec, CURR_DB);
printf("CS101: %s\n", srec.name);
}

Note that function d_setor actually sets both the current owner and the current member
of set my_students. The current owner is set to the CS101 record, and the current

Database Manipulation

5-25

member is set to NULL_DBA. This allows the initial call to d_findnm to return the first
member of the set. The output from execution of the above code might be:
CS101:
CS101:
CS101:
CS101:

Carlson
Jones
Kelly
Smith

From this example you should be able to produce the code for listing the classes in which
a particular student is registered.

Variable-length Text Retrieval


Section 4.4.1, "Logical Design Considerations," included a description of the use of
multiple-member sets in implementing text data. The code needed to retrieve the text
data in this example is quite simple, as shown below. Here the customer note for
customer id IBMFL is displayed.
struct customer cust; /* customer record variable */
char text[80];
/* text data - size of largest line */
/* find customer with id IBMFL */
d_keyfind(CUST_ID, "IBMFL", CURR_DB);
/* make customer current owner of cust_notes set */
d_setor(CUST_NOTES, CURR_DB);
/* fetch each member of set and display text */
while (d_findnm(CUST_NOTES, CURR_DB) == S_OKAY)
{
d_recread(text, CURR_DB);
printf("%s\n", text);
}

Each member of the cust_notes set is an occurrence of either the text30, text55, or text80
record types. Here it does not matter which record type is read, since each contains only
one string field. The character array text is used to store the contents of all. The function
d_crtype, however, could have been used to determine the type of the text records.

Database Examples from tims


One of the requirements for the tims database examples was to list technical publications
in the library by key word or phrase. This involves traversing the many-to-many
relationship between the key_word record and the info record twice (once to get the info
record from the specified key word, and again to retrieve all of the key words associated
with that located info record), and then scanning the abstract set to retrieve the text for
the abstract.
Function by_key lists all of the info records that have the user-entered key word or
phrase. For each info record selected, all of its key words and its abstract are printed.

5-26

Centura RDM Users Guide

/* Find publications by key word or phrase */


by_key()
{
struct info irec;
/* info record variable */
char name[32];
/* authors name */
char key[32];
/* key word */
/* find key word record */
printf("key word: ");
gets(key);
if (d_keyfind(WORD, key, CURR_DB) == S_NOTFOUND)
printf("no records found\n");
else
{
/* scan thru key_to_info set */
d_setor(KEY_TO_INFO, CURR_DB);
while (d_findnm(KEY_TO_INFO, CURR_DB) == S_OKAY)
{
/* find curr owner of curr intersect record and read it
*/
d_findco(INFO_TO_KEY, CURR_DB);
d_recread(&irec, CURR_DB);
/* find author of info record */
d_findco(HAS_PUBLISHED, CURR_DB);
d_crread(NAME, name, CURR_DB);
/* print results */
printf("id_code : %s\n", irec.id_code);
printf("author
: %s\n", name);
printf("title
: %s\n", irec.info_title);
printf("publ.
: %s, %s\n",
irec.publisher, irec.pub_date);
pr_keywords();
pr_abstract();
}
}
}

Figure 5-2 illustrates the operation of function by_key up to the point where function
pr_keywords is called. The d_keyfind locates the key_word record occurrence, which is
then made the current owner of set key_to_info. As each intersect record that is a
member of the info_to_key set is found (using d_findnm(KEY_TO_INFO, CURR_DB)),
its owner through the info_to_key set is found (using d_findco(INFO_TO_KEY,
CURR_DB)), and the info record contents are read. The author is found (and made
current) through the has_published set (using d_findco(HAS_PUBLISHED, CURR_DB))
and the name is read using function d_crread to read a field of the current record.

Database Manipulation

5-27

author

d_keyfind(WORD, key)

d_findco(HAS_PUBLISHED)

key_word

info

d_setor(KEY_TO_INFO)

d_findco(INFO_TO_KEY)

d_findnm(KEY_TO_INFO)

intersect

Fig. 5-2. Function by_key Operation


Function pr_keywords is called to print all of the key words and phrases associated with
an info record (note that at least one key word will appear in each list, the one chosen in
the call to by_key). Function d_members returns, in variable count, the number of
members in set info_to_key. If there are any members, then the owner of each intersect
member record is found through the key_to_info set, and from this owner record the key
word is read and displayed. This function (pr_keywords) will change the currency
associated with set key_to_info, which is used by function by_key in its scanning of that
set. Thus, it is necessary for the current member of key_to_info to be saved (by
d_csmget) before the key words are retrieved, and then restored (by d_csmset, which
sets both current member and current owner) after they have been retrieved.

5-28

Centura RDM Users Guide

/* Print key words */


pr_keywords()
{
long count;
/* number of info_to_key members */
char key[32];
/* key word or phrase */
DB_ADDR dba;
/* db addr of key_to_info member */
/*

the current member of the has_published set is the


info record whose key words are to be listed */
d_setom(INFO_TO_KEY, HAS_PUBLISHED, CURR_DB);
/* fetch number of members of info_to_key */
d_members(INFO_TO_KEY, &count, CURR_DB);
/* list the key words, if any */
if (count > 0L)
{
/* save current member of key_to_info because its
going to change and we may be currently scanning
though that set */
d_csmget(KEY_TO_INFO, &dba, CURR_DB);
printf("key words:\n----------\n");
/* find each intersect member record */
while (d_findnm(INFO_TO_KEY, CURR_DB) == S_OKAY)
{
/* find, read and print corresponding key_word */
d_findco(KEY_TO_INFO, CURR_DB);
d_crread(WORD, key, CURR_DB);
printf("
%s\n", key);
}
printf("\n");
/* reset key_to_info current member and owner */
if (dba != NULL_DBA)
d_csmset(KEY_TO_INFO, &dba, CURR_DB);
}
}

The abstract is printed by function pr_abstract, which simply scans through the abstract
set owned by the current info record to read and display each line of abstract text.

Database Manipulation

5-29

/* Print abstract */
pr_abstract()
{
long count;
/* number of abstract members */
char txt[80];
/* line of abstract text */
/*

the current member of has_published


is the info record whose abstract is to be printed */
d_setom(ABSTRACT, HAS_PUBLISHED, CURR_DB);
/* fetch number of lines in abstract */
d_members(ABSTRACT, &count, CURR_DB);
/* print abstract, if one exists */
if ( count > 0L )
{
printf("abstract:\n---------\n");
/* find, read and print each abstract text line */
while (d_findnm(ABSTRACT, CURR_DB) == S_OKAY)
{
d_csmread(ABSTRACT, LINE, txt, CURR_DB);
printf(" %s\n", txt);
}
}
printf("\n");
}

The other retrieval requirement is to be able to list all of the publications in the tims
database that are by a particular author. This is accomplished with function by_author.
The author is located by scanning through the (system-owned) author_list set, and
comparing a user-specified name with the author name. When a match is found, each
info record owned by the located author is read and displayed, along with its associated
key words and abstract.

5-30

Centura RDM Users Guide

/* Find publication by author */


by_author()
{
struct info irec;
/* info rec variable */
char search[32]; /* author to search for */
char name[32];
/* find author record */
printf("author: ");
gets(search);
for ( d_findfm(AUTHOR_LIST, CURR_DB);
db_status == S_OKAY;
d_findnm(AUTHOR_LIST, CURR_DB))
{
d_crread(NAME, name, CURR_DB);
if (strcmp(search, name) == 0)
break;
else if (strcmp(search, name) < 0)
{
db_status = S_NOTFOUND;
break; /* sorted alphabetically */
}
}
if (db_status == S_OKAY )
{
d_setor(HAS_PUBLISHED, CURR_DB);
for ( d_findfm(HAS_PUBLISHED, CURR_DB);
db_status == S_OKAY;
d_findnm(HAS_PUBLISHED, CURR_DB))
{
/* read and print info record */
d_recread(&irec, CURR_DB);
printf("id_code : %s\n", irec.id_code);
printf("author
: %s\n", name);
printf("title
: %s\n", irec.info_title);
printf("publ.
: %s, %s\n",
irec.publisher, irec.pub_date);
pr_keywords();
pr_abstract();
}
}
else
printf("author record not found\n");
}

5.4.3 Direct Access Retrieval


Direct access retrieval is used to locate sequentially all occurrences of a particular record
type and to directly read the contents of a record that has first been located by a key, set,
or sequential retrieval. Sequential retrieval is performed using these functions:
d_recfrst

Database Manipulation

Locates the first occurrence on the data file of the specified


record type.

5-31

d_reclast

Locates the last occurrence on the data file of the specified


record type.

d_recnext

Finds the next occurrence of a record of the same type.

d_recprev

Finds the next previous occurrence of a record of the same


type.

When the retrieval order is not important (the physical order of records on a file may
seem random), the sequential functions are the quickest way to scan records. The id_list
function is an example of such a scan.
/* produce a quick sequential listing of all id_codes */
id_list()
{
char id_code[17];
for (

d_recfrst(INFO, CURR_DB);
db_status == S_OKAY;
d_recnext(CURR_DB))

{
d_crread( ID_CODE, id_code, CURR_DB);
printf("%s\n", id_code);
}
}

These functions maintain their own currency by record type. In a loop, these four
functions will maintain their own positional information, even if there are other functions
in the loop that change currency table settings. To establish or restore a position from
which to continue scanning, the function d_recset can be used. This function will set the
current position of a sequential scan from the current record. Thus if a
d_recfrst/d_recnext loop needs to contain an inner loop for a different record type, the
position can be saved and restored around the inner loop, as follows:
DB_ADDR t1dba;
int status1, status2;
for (
status1 = d_recfrst(TYPE1, CURR_DB);
status1 == S_OKAY;
status1 = d_recnext(CURR_DB))
{
d_crget(&t1dba, CURR_DB);
...
for ( status2 = d_reclast(TYPE2, CURR_DB);
status2 == S_OKAY;
status2 = d_recprev(, CURR_DB))
{
...
}
d_crset(&t1dba, CURR_DB);
d_recset(TYPE1, CURR_DB);
}

5-32

Centura RDM Users Guide

The function page_full begins with the current record (which is assumed to be a
key_word type), and creates a list of the next twenty key word occurrences, as shown
below:
/* create a list of key words for display */
page_full( pglist, dir )
char *pglist[20];
/* list of key words */
int dir;
/* direction of the scan */
{
int i, status;
for (

status = d_recset(KEY_WORD, CURR_DB), i = 0;


(status == S_OKAY) && (i < 20);
status = (dir ? d_recnext(CURR_DB) : d_recprev(CURR_DB)), i++ )

{
d_crread(WORD, pglist[i], CURR_DB);
}
}

Functions d_recread, d_crread, d_csoread, and d_csmread read part or all of the contents
of the current record, owner, or member, copying the data to an application program
defined buffer. A pointer to this buffer is an argument to each of these functions.
Functions d_decode_dba and d_encode_dba are used to decode and encode a database
address with its file number and slot number. It can be used in conjunction with
functions d_crget and d_crset to utilize a records database address as a primary key,
which can be displayed and referenced by a user in order to directly access individual
record occurrences. For example, a database address for the record at slot number 17112
on file number 11 could be displayed as a primary key field called id number that, to the
user, could look like the following:
id number:

11-17112

By always displaying this number (actually the database address) when a record is
displayed, and by requiring this field to be entered whenever the record is modified, the
record can be located in a single disk read. The code to display the field follows.
DB_ADDR dba;
/* database address of current record */
short file;
/* file number */
unsigned long slot; /* slot number */
...
/* record to be displayed is current record */
d_crget(&dba, CURR_DB);
d_decode_dba(dba, &file, &slot);
printf("id number: %d-%ld\n", file, slot);

Database Manipulation

5-33

When the user has entered an id number, the record can be read as follows:
DB_ADDR dba;
/* database address */
int file;
/* file number */
unsigned long slot; /* slot number */
struct record rec; /* RDM record buffer */
...
/* extract file number of slot number from id number string */
... (you supply the tedious stuff)
/* form database address */
d_encode_dba(file, slot, &dba);
/* set current record and read record contents */
d_crset(&dba, CURR_DB);
d_recread(&rec, CURR_DB);
/* display record */
...

5.5

Data Creation

The RDM functions used to create record and key occurrences and to make set
connections are listed in Table 5-5 below.
Table 5-5. Data Creation Functions
Record/key Creation Functions
d_fillnew(REC, val, dbn)
d_setkey(FLD, val, dbn)
d_makenew(REC, dbn)
d_crwrite(FLD, val, dbn)
d_keystore(FLD, dbn)

Create and fill contents of new record occurrence.


Set key field value for new record.
Make a new record occurrence slot and store associated keys.
Write data to specified field of new record occurrence.
Create optional key entry.

Set Creation Function


d_connect(SET, dbn)

Connect new record to SET.

New record occurrences are entered into the database by using either the d_fillnew or
d_makenew function. To d_fillnew is passed the record type of the record to be created
and a pointer to the records value. This pointer usually points to a variable of that
records struct type, as declared in file dbname.h. Function d_makenew creates an
(almost) empty record occurrence, in which the field values will be stored later, usually
through individual calls to d_crwrite. However, d_makenew must store the key fields in
the record and create the key file entries at the time of the call. Prior to the call to
d_makenew, function d_setkey must be called for each (non-optional) key field, to save
the values of each key field for d_makenew. Generally, it is simplest to use only

5-34

Centura RDM Users Guide

d_fillnew, which automatically creates the key entries for you without a call to d_setkey.
Function d_makenew is useful when a record is to be created before the contents of the
fields are known, or for creation of records that have no fields (such as an empty
intersection record of a many-to-many set).
Function d_keystore is used to create the key file entries for optional keys in the current
record. Optional keys are often used to defer key creation until non-peak system load
times, in order to maximize data entry performance.
The data creation process involves not only record creation, but set creation as well.
After a record has been created, it often needs to be connected to appropriate sets. This
may involve data retrieval to set up the currency tables properly.
Entry of an info record into the tims database provides a good illustration of what is
typically involved in creating RDM data.
Three functions are presented below. Function ent_info enters the info record and, if
necessary, the author record, and makes the proper set connections. Function
enter_key_words is called by enter_info to read each key word from the user and set up
the many-to-many relationship with the entered info record. Function enter_abstract is
called to read from the user each line of the abstract and connect it to the info record
through set abstract. One function that is called but not shown is function get_info,
which reads from the user, the author name, and info record fields.

Database Manipulation

5-35

#include <stdio.h>
#include "vista.h"
#include "tims.h"
static struct info irec;
/* info record variable */
static struct author arec; /* author record variable */
/* Enter technical information records into TIMS database */
ent_info()
{
char s[32];
/* generic string variable */
int status;
/* enter tech info into TIMS database */
while (get_info() != EOF)
{
/* see if author exists */
for ( status = d_findfm(AUTHOR_LIST, CURR_DB);
status == S_OKAY;
status = d_findnm(AUTHOR_LIST, CURR_DB))
{
d_crread(NAME, s, CURR_DB);
if (strcmp(arec.name, s) == 0)
break;
/* author record on file */
}
if (status == S_EOS)
{
/* author not on file
-- create record and connect to author list */
d_fillnew(AUTHOR, &arec, CURR_DB);
d_connect(AUTHOR_LIST, CURR_DB);
}
/* make author current owner of has_published set */
d_setor(HAS_PUBLISHED, CURR_DB);
/* create new tech. info record */
if (d_fillnew(INFO, &irec, CURR_DB) == S_DUPLICATE)
printf("duplicate id_code: %s\n", irec.id_code);
else
{
/* connect to author record */
d_connect(HAS_PUBLISHED, CURR_DB);
/* set current owner for key words and abstract */
d_setor(INFO_TO_KEY, CURR_DB);
d_setor(ABSTRACT, CURR_DB);
enter_key_words();
enter_abstract();
}
}
}

After the data has been collected from the user (get_info), function ent_info is used to
scan the author_list set for the user-specified author name. If no match is found

5-36

Centura RDM Users Guide

(status == S_EOS), an author record is created and connected to author_list (the current
owner of author_list is always the system record). The found or newly created author
record is set as the current owner of set has_published, using d_setor. The info record is
created and if its id_code is not a duplicate, the id is connected to its author record. The
new info record occurrence is then made the current owner of sets info_to_key and
abstract. Key words and abstract text will be connected to it by the function calls that
follow.
/* Enter any key words */
static enter_key_words()
{
char s[32];
for ( ; ; )
{
printf("key word: ");
if ((gets(s) == NULL) || (s[0] == \0))
break;
/* see if key word record exists */
if (d_keyfind(WORD, s, CURR_DB) == S_NOTFOUND)
{
/* create new key word record */
d_setkey(WORD, s, CURR_DB);
d_makenew(KEY_WORD, CURR_DB);
}
/* create empty intersection record */
d_setor(KEY_TO_INFO, CURR_DB);
d_makenew(INTERSECT, CURR_DB);
d_crwrite(INT_TYPE, &irec.info_type, CURR_DB);
d_connect(KEY_TO_INFO, CURR_DB);
d_connect(INFO_TO_KEY, CURR_DB);
}
}

Function enter_key_words shows how to create many-to-many relationships. For each


key word entered by the user, d_keyfind is called to check if it is already on file. If not, a
new key_word record is created. The found (or new) key_word is then set as the current
owner of the key_to_info set, and an intersect record is created, which is then connected
to both the key_word record through set key_to_info and the info record through set
info_to_key.

Database Manipulation

5-37

/* Enter abstract description */


static enter_abstract()
{ char text_line[80];
for ( ; ; )
{
printf("abstract: ");
if ((gets(text_line) == NULL) || (text_line[0] == \0))
return;
d_fillnew(TEXT, text_line, CURR_DB);
d_connect(ABSTRACT, CURR_DB);
}
}

Function enter_abstract is very simple. As each line of abstract text is entered, the text
record is created and connected to the info record, which is the current owner of set
abstract.

5.6

Data Modification

The functions used to modify fields, records, and sets are shown in Table 5-6.
Table 5-6. Modification Functions
Record/Key Modification Functions
d_recwrite(val, dbn)
d_crwrite(FLD, val, dbn)
d_csmwrite(SET, FLD, val, dbn)
d_csowrite(SET, FLD, val, dbn)

Write contents of current record.


Write data in field of current record.
Write data in field of current member of set.
Write data in field of current owner of set.

Set Modification Functions


d_discon(SET, dbn)
d_connect(SET, dbn)

Disconnect current member from set.


Connect current record to set.

Modification of data is very straightforward. To modify a record or field, you first


retrieve the record, read the record or field contents, make the desired changes and then
write out the updated data using a record modification function.
Set modifications often involve disconnecting a record from one set and connecting it to
another.
Note: If two or more fields in a record are used as sort fields in an ascending or
descending set, and function d_recwrite is used to modify the contents of both fields,
better performance will result if you first disconnect the record from the set before calling
d_recwrite and then reconnect the record after returning from d_recwrite. Otherwise,
RDM will still adjust the position of the set for each field.

5-38

Centura RDM Users Guide

Optional keys are automatically modified if a key existed for the old value when its field
was modified. If a key entry did not exist for the old value, none will be created for the
new value. However, the fields value in the record is updated.

5.7

Data Deletion

The functions involved in data deletion appear in Table 5-7.


Table 5-7. Data Deletion Functions
d_delete(dbn)
d_keydel(KEY, dbn)
d_discon(SET, dbn)
d_disdel(dbn)

Delete current record.


Delete optional key value.
Disconnect current member from set.
Disconnect current record from all sets and delete it.

A record can only be deleted if it is not connected as an owner or member of any sets.
The general deletion procedure is, therefore, to disconnect a record from all sets for
which it is a member and disconnect all members from sets owned by that record, and
then delete the record. All disconnections and the delete can be performed with one call
by using function d_disdel.
Function d_keydel is used to delete the key entry of an optional key field in the current
record. The field value in the record itself, however, does not change. All key entries,
including optional keys, are deleted from their respective key files when a record is
deleted using either function d_delete or d_disdel.
Below is the code for function del_info, which deletes an info record from the tims
database.

Database Manipulation

5-39

#include <stdio.h>
#include "vista.h"
#include "tims.h"
/* Delete technical information records from tims database */
del_info()
{
struct info irec;
long count;
char id[16], name[32];
/* find info to be deleted */
printf("id_code: " );
gets(id);
if (d_keyfind(ID_CODE, id, CURR_DB) == S_NOTFOUND)
{
printf("id_code %s not on file\n", id);
return;
}
d_recread(&irec, CURR_DB);
/* get author name */
d_findco(HAS_PUBLISHED, CURR_DB);
d_crread(NAME, name, CURR_DB);
... /* confirm delete request */
... /* disconnect and delete any listed articles */
... /* disconnect and delete borrowers */
/* disconnect and delete abstract */
d_setom(ABSTRACT, HAS_PUBLISHED, CURR_DB);
while (d_findfm(ABSTRACT, CURR_DB) == S_OKAY)
{
d_discon(ABSTRACT, CURR_DB);
d_delete(CURR_DB);
}
/* disconnect and delete intersect and (possibly) key word */
d_setom(INFO_TO_KEY, HAS_PUBLISHED, CURR_DB);
while (d_findfm(INFO_TO_KEY, CURR_DB) == S_OKAY)
{
d_discon(INFO_TO_KEY, CURR_DB);
d_setmr(KEY_TO_INFO, CURR_DB);
d_discon(KEY_TO_INFO, CURR_DB);
d_delete(CURR_DB);
d_members(KEY_TO_INFO, &count, CURR_DB);
if (count == 0L)
{
/* delete key word */
d_setro(KEY_TO_INFO, CURR_DB);
d_delete(CURR_DB);
}
}

(Continued)

5-40

Centura RDM Users Guide

(Continued)
/* disconnect info record from author and delete */
d_discon(HAS_PUBLISHED, CURR_DB);
d_delete(CURR_DB);
/* delete author too, if he has no other pubs */
d_members(HAS_PUBLISHED, &count, CURR_DB);
if (count == 0L)
{
d_setmo(AUTHOR_LIST, HAS_PUBLISHED, CURR_DB);
d_discon(AUTHOR_LIST, CURR_DB);
d_delete(CURR_DB);
}
}

Function del_info first prompts the user for the id code of the info record to be deleted.
If the id code is on file, the info record contents are read into variable irec, the author
name is found from the owner of info through set has_published, and a confirmation of
the delete is requested by displaying the data (not shown).
If the info item to be deleted is a journal or magazine, any articles contained in it must
also be deleted. This is done first (not shown).
Next, any borrower records that are members of that info item are disconnected and
deleted (also not shown).
The abstract is deleted by repeatedly disconnecting and deleting the first member of the
abstract set until there are no more members. Note that the current owner of abstract
had to be initially set to the info record that is the current member of has_published (as
established by the earlier d_findco(HAS_PUBLISHED) call).
Deletion of the key words associated with the info record is similar, but more
complicated. Intersect records are deleted just like the abstract was, except that they
need to be disconnected from set key_to_info as well as from set info_to_key. If the
key_to_info set is empty after deleting the intersect record, the key_word must also be
deleted. Note the call to d_setro to set the current record from the current owner of set
key_to_info (that is, the key_word record). This is necessary because function d_delete
deletes the current record, and the key_word record was not the current record.
The info record is disconnected from its final set, has_published, and can now be
deleted. Function d_discon disconnects the current member from the specified set and
makes the deleted record the current record.
One last task is a check to see if the author has other info items in the database. If not,
then the author record is disconnected from set author_list and is deleted as well.

Database Manipulation

5-41

5.8

Database Error Reporting

All RDM runtime functions return an integer database status code as the value of the
function. These status codes are classified into the following three categories:
User Errors

These correspond to programming errors, such as passing a


record type to a function with a set type as its argument. User
error codes range from -1 to -99.

System Errors

These errors occur when RDM detects an abnormal database


condition, such as no more file space. System error codes range
from -900 to -999.

Function Statuses

These status codes are returned to inform the program of normal


function results. For example, when function d_keyfind returns
code S_NOTFOUND it indicates that the key value was not on
the key file. Status codes are positive numbers starting at zero.

When user errors are reported, either the arguments to an RDM function are not correct
or the database environment has not been properly set up for the called function. For
example, function d_csoread will return user error S_NOCO if the current owner of the
specified set is NULL_DBA. All user errors in an RDM program should be corrected.
Only one system error is recoverable. The system error S_NOSPACE is returned when
there is no more space available on the disk, but it is recoverable. A recovery technique
is described with function d_trend in the RDM Reference Manual. All other system errors
(and sometimes even error S_NOSPACE) indicate that a serious error has occurred and
processing should be terminated immediately. Usually, these errors result from an
application programming error that corrupts the RDM runtime environment. These
errors are caused by improper use of pointers, by memory mismanagement, and by
operations on strings that are not terminated by a null byte. The most common pointer
error is passing a function argument by value rather than by reference (that is, rather
than by using a pointer).
An external integer variable called db_status always contains the current value of the
database status in the single-tasking, static-link libraries, as assigned by the most recently
called RDM function. It may be referenced by an application program as needed.
The standard RDM C header file, vista.h, contains constant definitions for all status and
error codes that can be returned from an RDM function. This file should be #included in
each C source file that uses RDM. Detailed explanations for each status code can be
found in the RDM Reference Manual.
The internal function dberr is automatically called by the RDM runtime functions
whenever a user or system error occurs. Whenever a user or system error occurs, this
version of dberr will display the error code and description, and then prompt for a

5-42

Centura RDM Users Guide

<Return> to continue. You may need to customize the error reporting to make it more
suitable for the user interface style of your application.
The recommended method is to use d_set_dberr, which allows you to supply the RDM
runtime with a callback function to call when reporting an error. This is the only
customization method available when using Microsoft Windows DLLs. After calling
d_set_dberr, the dberr function will call the function you supply, instead of printing the
message itself. Since dberr is calling your function, you do not need to set db_status or
return a value. Your error reporting function should be declared as follows:
void EXTERNAL_FIXED my_dberr(int, char *);

The first parameter is the error number, and the second parameter is the textual message
that dberr would have printed regarding the error. The void EXTERNAL_FIXED
preceding the function name ensures that its declaration will match that expected by
RDM. The macros are defined in vista.h. Use the function as follows:
#define "vista.h"
void EXTERNAL_FIXED my_dberr(int, char *);
...
main()
{
...
d_set_dberr(my_dberr);
...
}
void EXTERNAL_FIXED my_dberr(err_no, err_msg)
int err_no;
char *err_msg;
{
/* Special handling of some error codes here */
if (err_no <= -900)
{
/* take care in calling d_close, because it may
call dberr again */
exit(err_no);
}
...
/* You may choose to ignore some codes */
if (err_no == S_NOCM)
return;
...
/* Report errors */
...
return;
}

Database Manipulation

5-43

5.9

Multiple Database Access

RDM allows more than one database at a time to be opened and accessed within a single
application program. This capability has been implemented with very little performance
impact for those RDM applications that only need to access a single database. Section
4.4.1, "Logical Design Considerations," described some of the uses of multiple database
access from a database design standpoint. This section explains how to open and access
multiple databases.

5.9.1 Opening Multiple Databases


To open more than one database, the desired database names are passed, separated by a
semicolon (;), as the first argument to function d_open or d_iopen. No white space (that
is, spaces, tabs, etc.) should be embedded between the database names. An improperly
constructed list will result in error S_INVDB being returned. Any number of databases
may be opened, limited only by the amount of available memory. All opened databases
are opened in the same mode. It is not possible to open some in exclusive access and
others in shared or one-user access. You can, however, open all databases in shared
mode and then place exclusive locks on all of the files in one or more databases.
A currency value is defined called current database. The current database will be zero
(that is, the first one listed) after execution of d_open. See the example below:
if (d_open("genledg;acctsrec;acctspay", "s") != S_OKAY) {
if (db_status == S_UNAVAIL)
printf("database(s) not currently available\n");
exit(1);
}

Here, the databases named genledg, acctsrec and acctspay are all opened for shared
access. Each is assigned a number by the system in order from left to right, beginning
with zero. Thus database 0 is genledg, database 1 is acctsrec, and database 2 is acctspay.
These numbers are used to specify to the runtime functions which database to access.
After the d_open call, database genledg will be the current database.

5-44

Centura RDM Users Guide

It is not necessary to open all databases at one time. The function d_iopen will
incrementally open a new (set of) database(s) in the same open mode as the already
opened databases. The following statements would be equivalent to the example above,
except that the current database will be two instead of zero:
if (
(d_open("genledg","s") != S_OKAY) ||
(d_iopen("acctsrec") != S_OKAY) ||
(d_iopen("acctspay") != S_OKAY) )
{
if (db_status == S_UNAVAIL)
{
printf("database(s) not currently available\n");
exit(1);
}
}

Whether the databases are opened all at once, or incrementally, they may all be closed
with the d_close call. They may be incrementally closed with the d_iclose call. For
example, after the above opens, the call:
d_iclose(1);

will close the acctsrec database. All database numbers will shift accordingly (in this case,
the database number for acctspay will shift from two to one). If database 2 (acctspay)
was the current database, then database 1 (still acctspay) will be the current database
following the d_iclose.
In addition to the current database, a current record is maintained for each database.
Whenever the current database is changed, the current record for the old database is
saved and the current record for the database that is to be made current is restored.

5.9.2 Accessing Multiple Databases


There are two methods for accessing multiple databases. Every database-specific
function must be called with a database number (dbn). The dbn may be -1, which causes
the current database to be used. The vista.h header file contains a #define constant
called CURR_DB that is equal to -1. The current database may be altered by the d_iopen
or d_setdb functions. Alternatively, the dbn parameter may be a positive number that
explicitly selects a database. These methods may be used interchangeably.
If only one database is opened, the database number parameter is still required and must
be zero (0) or CURR_DB.
Note: When a module (that is, a .c file) is to access multiple databases, care must be taken
to ensure that there are no record, field, or set name conflicts between those databases. If
there are, the compiler will only recognize the last #define statement from the dbname.h
files containing the duplicate names.

Database Manipulation

5-45

Method 1
In this method, function d_setdb is called to set the current database. The dbn parameter
must be -1 (or its equivalent CURR_DB). An example of this technique follows.
#include "vista.h"
...
d_open("genledg;acctsrec", "s");
...
/* enter billing record into acctsrec database */
d_setdb(1);
d_fillnew(BILLING, &bill, CURR_DB);
/* find and update ledger account in genledg database */
d_setdb(0);
d_keyfind(ACCT_ID, bill.gl_id, CURR_DB);
d_recread(&glacct, CURR_DB);
..
/* update gen. ledger account record */
d_recwrite(&glacct, CURR_DB);

Method 2
In this method, the database number is passed as to the RDM functions that access or
control database content. An example of this technique follows.
d_open("genledg;acctsrec", "s");
...
/* enter billing record into acctsrec database */
d_fillnew(BILLING, &bill, 1);
/* find and update ledger account in genledg database */
d_keyfind(ACCT_ID, bill.gl_id, 0);
d_recread(&glacct, 0);
..
/* update gen. ledger account record */
d_recwrite(&glacct, 0);

Mixed Method
It is possible to use d_setdb to set the current database, but override it with an explicit
database number when necessary.
d_open("genledg;acctsrec", "s");
...
/* enter billing record into acctsrec database */
d_setdb(0);
d_fillnew(BILLING, &bill, 1);
/* find and update ledger account in genledg database */
d_keyfind(ACCT_ID, bill.gl_id, CURR_DB);
d_recread(&glacct, CURR_DB);
..
/* update gen. ledger account record */
d_recwrite(&glacct, CURR_DB);

5-46

Centura RDM Users Guide

5.10 Context Switching


For the purpose of this discussion, we will define the context of an application to be its
current state. This includes such factors as which database is open, the current record,
current set owners and members, record and set locks, and many other items that
represent the situation of the application. Below is a list of the most significant context(or task-) specific data:

Whether there is an open database

The DBUSERID

The DBDPATH

The DBFPATH

The CTBPATH

The status of all key files (position, last found value, etc.)

The database options

The names of renamed files

The default page size of database(s)

The current record

The current set owners

The current set members

The complete data dictionary (or dictionaries, if multiple databases are open)

The status of all record, set, and key locks

The country table

All in-memory timestamp information

The current records as used by the sequential scanning functions

The database address of the system record

The transaction id

The transaction log file name

Context switching within RDM is the ability to save and restore this task-specific data in
an allocated structure. With this capability, multiple contexts can be operated on by the
same copy of the runtime library. Typically, a context is associated with a task, which
RDM defines as an independent unit of code execution.
This is a deliberately broad definition. You can program multiple database tasks within a
single process or you can run Windows with the DLL version of RDM in multiple
windows. In each case, a task would operate within one RDM context.

Database Manipulation

5-47

It is not necessary to associate a database context with an operating system task. A


separate context can be opened for the purpose of accessing additional databases in a
different open mode. For example, you may have a database open in shared mode, but
then want to open an additional database exclusively. To do this, you must use context
switching, because the d_iopen function does not allow an open-mode change.
The following four functions exist exclusively in the context-switching library:
Table 5-8. Context Switching Functions
dt_opentask(DB_TASK *)

Open one task instance.

dt_newcache(DB_TASK *, int)

Set up multiple cache control.

dt_sharecache(DB_TASK *, DB_TASK *)

Control multiple caches.

dt_closetask(DB_TASK *)

Close one task instance.

Note: The context-switching functionality is provided in a separate runtime library. Use


this library only if you intend to use context switching. The noncontext-switching library
is smaller and requires fewer parameters in each function call.
A context is established by a call to dt_opentask. The one parameter to this function is a
pointer to a structure of type DB_TASK. Within this structure type are two pointers: one
to an RDM context structure, and one to a db_QUERY context structure. The
dt_opentask function will allocate an RDM context structure and point the RDM pointer
to it. The db_QUERY structure is not allocated unless db_QUERY is being used.
When using the context-switching library, at least one call must be made to dt_opentask.
Also, the DB_TASK parameter must be supplied to (nearly) every RDM function. All of
the task-specific RDM functions are re-named in the context-switching library: the d_ has
been changed to dt_. The functions have identical functionality and the same
parameters, except that there is the additional task parameter. The task parameter is
placed before the database number parameter for those functions that use a database
number. Otherwise, it is the last argument. A complete list of context-switching
functions is provided in the RDM Reference Manual, at the front of Chapter 3,
"Operational Overview."
The following code shows a simple single-process application using two contexts.

5-48

Centura RDM Users Guide

#define LOCKCOMM_DATA
#include "vista.h"
DB_TASK ControlTask;
DB_TASK ClientTask;
main()
{
struct client cl2;
dt_opentask(&ControlTask);
dt_open("ctrl", "x", &ControlTask);
/* Initialize control database */
...
dt_opentask(&ClientTask);
dt_open("client1;client2;client3", "s", &ClientTask);
...
/* Access client database */
dt_fillnew(CLIENT, &cl2, &ClientTask, 2);
...
dt_close(&ClientTask);
dt_closetask(&ClientTask);
...
dt_close(&ControlTask);
dt_closetask(&ControlTask);
}

Two variables of type DB_TASK are defined. One context is created to open a single
control database in exclusive access mode. Then a second context is created to open a
group of shared databases, each representing one client.
A set of "cover" macros have been provided that allow you to use the familiar d_ function
names in applications that will use just one context. A tasking application that uses the
macros would look like this:
#define LOCKCOMM_DATA
#include "vista.h"
DB_TASK Currtask;
main()
{
dt_opentask(&Currtask);
/* Normal RDM code*/
d_open("db", "x");
d_close();
dt_closetask(&Currtask);
}

Currtask is the DB_TASK variable name that is automatically supplied by the macros.
For example, the d_open call above is translated to:
dt_open("db", "x", &Currtask);

Database Manipulation

5-49

You must compile your application with the -DMULTI_TASK command line argument
or place #define MULTI_TASK in your source file.
There are two functions that do not take a task parameter. They are:
d_decode_dba
d_encode_dba
Note: DB_TASK variables can not be shared between applications through DLLs. Each
application must have its own DB_TASK variables. If the DB_TASK variables are located
in the DLL instead of the application, the DLL must somehow track which application is
using which DB_TASK.
The Microsoft Windows Guide to Programming (Microsoft Press 1990, section 20.2.1) states
the following:
DLLs can be used to share objects between applications. Certain types of objects, including
code and resources, can be freely shared using a DLL. The sharing of other type of objects,
including data and file handles, is much more limited. This is because file handles and data
are created in an applications private address space. Attempts to share file handles, or to
share data (outside of DDE, the clipboard, and the librarys data segment) will lead to
unpredictable results, and could be incompatible with future versions of Windows.

5.11 International Character Sets


In RDM, support for international character sets provides the ability to redefine the
display and collating sequence of any character in the ASCII character set. An additional
effect is the ability to ignore the case of letters in sorting. For example, the German "" is
just a different way of writing "AE" and needs to be sorted as such. However, the
standard ASCII tables, which define the normal sort orders, put the letter "A" at 65 and
the "" at well over 127 (depending on the code page being used by your computer),
causing the normal sort order to be far from what is desired.
At the center of this capability is the country table. The country table contains one entry
for each character that is to be recognized as a displayable character, or that is to be
sorted in an order other than its normal sequence. An optional country table directive
allows all lowercase letters to be mapped into uppercase letters during sorting.
Note that the Country Table is not used in sorting Unicode data. For information about
RDM support for Unicode, see Chapter 9.
The country table is contained in a file named vista.ctb. RDM will read the country table
file, if present, during each database open. The country table file is found by searching
the directory indicated in the CTBPATH environment variable (the country table path
can also be established with the d_ctbpath function or the rdm.ini file). If CTBPATH has
not been set, then the current directory will be searched.

5-50

Centura RDM Users Guide

Note: A database that is built with a particular country table must always use the same
country table, because sorted sets and keys will appear to be corrupted to RDM because
they are out of order if the table is changed or omitted.
When a country table is being used for sorting purposes, single character fields will be
compared using the country table when they are declared as signed (e.g., char
my_field;). Unsigned character fields will be sorted without the use of the country table.
The country table has the following format:
w,x,y,zz
w,x,y,zz
...
where:
w
x
y
z

=
=
=
=

Input character as stored on disk


Output character as displayed
Subsort value, described below (value 0 or 1)
Sort-as character(s) (up to two)

The input character, w, will be displayed as the character x in ida, datdump, and
keydump, since these utilities interpret the data. It will be sorted as though it were z.
The y (or subsort) value indicates what to do when this character sorts to a value equal to
an existing character. The z (or sort-as) field can contain one or two characters. If it
contains two characters, then the input character will be sorted as though it were two
characters. By default any character not listed as an input character within the country
table gets sorted and displayed as itself.
When two or more characters are mapped to the same subsort character(s), they become
members of a grouping. The subsort value controls how characters in a group are
subsorted within the group. A zero means that the two input characters will be treated
as identical. A one means that the input characters are considered part of the same
group, but are sorted by ASCII value within the group.
As an example, look at the country table and data below:
a,a,0,A
b,b,0,B
c,c,0,C
...
z,z,0,Z

Database Manipulation

ab1
AB2
AA3
aa4
bb5
aB6
Ab7
BB8

5-51

The left column below shows how this data would be sorted. The right column shows
the internal representation used during the sort.
AA3
aa4
ab1
AB2
aB6
Ab7
bb5
BB8

AA3
AA4
AB1
AB2
AB6
AB7
BB5
BB8

Note that case in the original data is intermixed after the sorting. Because of the zero
subsort value, if we used d_recwrite to change the bb5 to BB5, RDM would not write the
change to disk since, according to the country table, the data did not change. Note that
this mapping of the lowercase letters to the uppercase letters with a subsort value of zero
is exactly what ignorecase (explained later in this section) does in the country table.
Suppose we use the same data with the same country table but we change all the subsort
values to one as listed below,
a,a,1,A
b,b,1,B
c,c,1,C
...
z,z,1,Z

ab1
AB2
AA3
aa4
bb5
aB6
Ab7
BB8

The sorting sequence will be changed from the normal ASCII ordering below
A B C ... Z ... a b c ... z
to the new ordering of:
A a B b C c ... Z z

5-52

Centura RDM Users Guide

The left column below shows how the above data will be sorted. The right column
shows the internal representation used during the sort.
AA3
AB2
Ab7
aa4
aB6
ab1
BB8
bb5

AA3
AB2
A B7
AA4
AB 6
AB1
BB8
BB5

Since the subsort value of one means that the input characters are not identical, bb5
could be easily changed to BB5 because RDM would see the bb and BB as not exactly the
same.
One other point to note is that the country table processing is a one-pass lookup; it will
not recursively lookup characters. For example,
d,d,0,a
a,a,0,A
maps d to a and also maps a to A. However, transitive properties do not apply, which
means that d would not be mapped to A. To get a and d to be sorted as the same
character(s), the exact sort-as string must be used for both as shown below:
d,d,X,A
a,a,X,A
An additional country table directive may appear as the first line in vista.ctb. The first
line may say ignorecase, which will cause all lowercase letters (a - z) to have their sort-as
characters changed to their uppercase counterparts (A - Z) using a subsort value of zero.
Sorting will ignore the case of the letters, but the display of the characters will not be
changed. If the ignorecase option is not used, it is necessary to specify all of the sort-as
characters in uppercase to get the same effect.
A possible German country table is shown below:
,,0,AE
,,0,ae
,,0,UE
,,0,ue
,,0,OE
,,0,oe
,,0,ss

Database Manipulation

5-53

Case insensitivity for the same data would be indicated as follows:


ignorecase
,,0,AE
,,0,AE
,,0,UE
,,0,UE
,,0,OE
,,0,OE
,,0,SS
A an example, given the case-sensitive, German table above, the string "lan" would be
sorted as if it was the string "AElan".
Note: The country table file is a binary file that just happens to contain only text data.
Usually the country table file will be created though the use of a text editor. However,
some text editors put end-of-file (EOF) markers (ASCII 26) at the end of files they create.
It is important to ensure your editor does not do this as it will cause problems during the
interpretation of the file; the EOF marker will be treated as part of the string being read
from the file.
The functionality of the country table can be created programmatically using the
d_mapchar and d_on_opt functions (see the function descriptions in the RDM Reference
Manual). The following calls can be made before opening the database to create the casesensitive German character set mapping (note the change in the parameter ordering):
d_mapchar( '', '', "AE", 0 );
d_mapchar( '', '', "ae", 0 );
d_mapchar( '', '', "UE", 0 );
d_mapchar( '', '', "ue", 0 );
d_mapchar( '', '', "OE", 0 );
d_mapchar( '', '', "oe", 0 );
d_mapchar( '', '', "ss", 0 );
or the case insensitive option:
d_on_opt( IGNORECASE );
d_mapchar( '', '', "AE", 0 );
d_mapchar( '', '', "AE", 0 );
d_mapchar( '', '', "UE", 0 );
d_mapchar( '', '', "UE", 0 );
d_mapchar( '', '', "OE", 0 );
d_mapchar( '', '', "OE", 0 );
d_mapchar( '', '', "SS", 0 );

5-54

Centura RDM Users Guide

The use of the functions eliminates the need for the country table file, but there are big
disadvantages to using the functions instead of the country table file. The country table
file is used by all RDM utilities and applications that call d_open. Hence if a database is
built by an application using the above function calls, and a utility such as ida is used on
the database, it may find the keys in an order other than expected. Worse yet, if it adds
keys to the database, it will do so with a different collating sequence, which will cause
the key files to become corrupted.
The safest way to use international characters is to define them in a country table that
will always be used when the database is used. If the function calls are used in
application code (to eliminate the extra file), it will still be necessary to use a country
table file when the utilities are used on the same database. Alternatively, the ignorecase
and CTBPATH information can be put into the rdm.ini file.

Database Manipulation

5-55

Chapter 6
Transaction Processing
6.1

Introduction

Transaction processing is used to maintain the logical consistency of a database by


allowing multiple, related updates to be grouped together and then written to the
database as a unit. For example, in the tims database the entry of a book into the library
could involve the creation of up to five records (author, info, text, intersect, key_word)
and connections to five sets (author_list, has_published, abstract, info_to_key,
key_to_info). If all of these changes were coded as a transaction and a failure occurred
before the transaction ended, none of the changes would be in the database. Without
transaction processing, the changes would be written to the database only as necessary,
and a failure would leave the database in an inconsistent state (for example, it could
leave an info record that is not connected to an author record).
Transaction processing is required during multi-user operation (see Chapter 7, "MultiUser Database Control"). It is recommended during one-user, exclusive, or single-user
operation, but not required.
Note: Transactions are not intended for use when reading the database. Reading may
occur outside of transactions (with read locks if in shared mode). A transaction should
begin only when an application is fully ready to perform an update to the database.
Fully ready, in this case, means that the application should not have to wait for any more
information from the user or otherwise during the update. The transaction should go
from beginning to end without user interruption.
Transaction logging is used to provide data integrity protection if a failure occurs while a
transactions changes are actually being written to the database. The process wherein the
changes are written to the database is called the transaction commit. Failures that occur
during a commit are detected by the system, automatically initiating a recovery
operation, which takes a copy of the changes stored on the transaction log and completes
the commit by writing those changes to the database. Transaction logging is the process
of writing the changes to the transaction log before doing the commit.

Transaction Processing

6-1

6.2

Operational Environment

Transaction processing affects the following files:


Control files:
vista.taf
dbuserid.log
Database files:
Data and key files defined in the DDL specification
The file named vista.taf is a database-family transaction activity file (TAF). In it are
stored the names of the log files of all currently committing transactions. Log files are
typically named by adding the .log suffix to the DBUSERID, but not necessarily. The
DBUSERID is set with the environment variable DBUSERID, or with the d_dbuserid
function. The directory containing the TAF file is determined from a d_dbtaf function
call, the rdm.ini file, or the DBTAF environment variable. If none of the former define a
path, then the current directory is used. The directory containing the log file is
determined from a d_dblog function call, the rdm.ini file, or the DBLOG environment
variable. The current directory is used if no DBLOG value is found.
Note: Both the TAF and log files can be given different, explicit names (for example,
n:\dbvista\taf is a file name since it doesnt end in a directory character). However, it is
recommended that you use the default names. This is especially important in a multiuser environment.

6-2

Centura RDM Users Guide

6.3

Transaction Processing Functions

Three functions are provided in RDM to support transaction processing. These are listed
in Table 6-1. Function d_trbegin is used to mark the beginning of a transaction. All
changes specified after the d_trbegin call are written to the database at the same time,
when function d_trend is called to end the transaction. If any errors are detected, or if a
requested lock is not available after d_trbegin has been called, function d_trabort can be
called to abort the transaction. Function d_trabort will discard any changes that have
been made since the beginning of the transaction, ensuring that the state of the database
is the same after d_trabort as it was before d_trbegin.
Table 6-1. Transaction Processing Functions
d_trbegin(trx_id)

Begin transaction

d_trend()

End transaction

d_trabort()

Abort transaction

When a database is opened in shared access mode (see Chapter 7, "Multi-User Database
Control"), all database updates must be made from within a transaction (unless the files
being updated have been exclusively lockedsee section 7.3.4, "Exclusive Locks"). When
using one-user or exclusive modes, or when using the single-user library, transactions are
not required, but are recommended for all database updates.
Function d_trbegin is called to notify the RDM runtime of the start of a new transaction.
Transactions cannot be nested within a DB_TASK. If d_trbegin is called from within an
active transaction, error code S_TRACTIVE will be returned.
Function d_trend completes a transaction by committing all changes to the database.
Function d_trabort disregards all changes proposed since the d_trbegin call, and frees all
unkept and non-exclusive file locks.

Transaction Processing

6-3

6.4

Transaction Processing

A single transaction performs a great deal of work in order to guarantee the successful
commit of an update. The following list shows the sequence of function calls to be made
by an application, along with the underlying action performed by RDM.
Table 6-2. Actions of Transaction Processing Functions
Function

Action

d_trbegin

The log file, usually dbuserid.log, is initialized.

d_lock

A group lock request is issued. All locks are granted or denied as a


unit. A group lock is recommended over a series of d_reclock and
d_setlock calls to avoid deadlock.*

transaction body Here, a series of function calls to modify the database are made.
If modified pages fill the cache (called a transaction overflow), then
extra cache space is created by writing modified pages to the log file.
d_trend

During this call, the commit is made to the database. At any point
after the d_trbegin and before the d_trend, updates can be thrown
away and locks released by issuing a d_trabort call. During a d_trend,
the following sequence occurs:
1.

Modified database pages are written to the transaction log file


(if transaction logging is enabled).

2.

Lock manager is informed of the commit.*

3.

The name of the log file is added to the TAF.

4.

Changed pages are written to the database from cache. If an


overflow occurred earlier, then changed pages contained only in
the log file are read from it and written to the database.

5.

The log file name is deleted from the TAF.

6.

Lock manager is informed of the end of the transaction.*

7.

All unkept and non-exclusive file locks are freed.

* This step occurs in a multi-user environment only.

One log file is maintained for each user. This file is used within a transaction for storing
modified database pages after the page buffers (cache) have been filled. Thus, there is
effectively no limit to the number of changes that can be made within a transaction.
When the transaction ends, all modified pages are first written to this file (whether or not
an overflow occurred). The database is then updated.

6-4

Centura RDM Users Guide

Note: The size of your transactions should be carefully balanced. Even the most trivial
update (for example, one d_fillnew) incurs the full overhead of steps 1-7 above. As a
general rule, do as much as you can within one transaction. On the other hand,
remember that during the time between the d_lock and d_trend calls, other users are
prevented from using the same files. A transaction that is too long will cause uneven
response times in the overall system.
If a transaction is aborted, the modified pages in the page buffers are cleared.
An indexing technique has been developed to provide fast access to the changed
database pages that are stored in the log file after a cache overflow has occurred. It
utilizes a separate cache for the management of all database pages on the log file. The
size of this index cache (that is, the number of page buffers) is specified as an argument
to function d_setpages as follows:
d_setpages(dbpgs, ixpgs)

where dbpgs is an integer specifying the number of pages to be used for the standard
database cache and ixpgs is an integer specifying the number of pages to be used for the
overflow index cache. Both arguments are required on any call to d_setpages.
If your application is prone to large transaction overflows, you will want a fairly large
index cache (for example, 17 pages). Usually, however, a small number of index pages is
all that is necessary (for example, five pages, the default).

6.5

Database Recovery

If a program crashes while a transaction is active (after the d_trbegin but before a
transaction end or d_trend has been issued), the database is guaranteed to be consistent
since it has not been written to. Only the changes made since the beginning of the
transaction are lost. If the program fails while the modified pages are being written to
the log file (step 1 in section 6.4, above), the same situation exists. However, after the
changes have been written to the log file, if the program fails while the database is being
updated, recovery is possible. If the program fails while committing the database from
the log file, recovery is required.

Transaction Processing

6-5

6.5.1 External Recovery


In a system with only one active user (single-user version, one-user mode, or multi-user
mode with only one active user), recovery is facilitated by the TAF. If this one user
crashes after the log file name has been written to the TAF (step 3 in section 6.4, above),
but before it has been removed (step 5), then the assumption is made that the database
needs recovering. The TAF is checked the next time a database is opened. If one or more
log file names are present in the TAF, they are all recovered by the first application to use
this TAF during the d_open call.

6.5.2 Automatic Recovery


In multi-user shared mode, automatic recovery is accomplished through cooperation
between the transaction processing functions and the lock manager. The lock manager,
which runs as an independent process, is notified of the name of the log file when the
update is initiated (referred to as the transaction commit point, step 2 in section 6.4,
above) and is notified when the update is complete (step 6). The recovery automatically
occurs when the lock manager determines that a process performing a transaction
commit has abnormally terminated. When failed processes that were not doing a
transaction commit are detected by the lock manager, the lock manager simply releases
the locks held by the failed process.
The recovery will occur automatically when the lock manager receives an open or lock
request from another active process using the same TAF. The lock manager will transfer
responsibility for the completion of the failed transaction to the process requesting the
open or lock. The read locks held by the failed process are freed, but write locks are held
until the transaction has recovered.
Upon successful completion of the commit, the lock manager is informed and the log file
name is removed from the TAF. If both the committing process and the lock manager
fail, all RDM processes on the system should be shut down. When the lock manager is
restarted, the first database process to open a database will check the TAF and perform
an external recovery on any listed transaction log files. The lock manager will delay all
other database processes for the database families using that TAF until the recovery is
complete.
Both the log file and the TAF need to be accessible by all database tasks. Moreover, all
the log files for the users of each TAF need to be in the same physical directory. The path
and names of these files can be established through use of functions d_dblog and
d_dbtaf, or through environment variables DBLOG and DBTAF, or with the rdm.ini file
(see section 6.2, above). All users of all databases need to have read/write access to all
database files. It is possible for an application using one database to do recovery for a
completely different database, but only when both databases are using the same TAF. It
is recommended that each database family use a different TAF.

6-6

Centura RDM Users Guide

On some networks (for example Novell) it may be necessary to create each log file prior
to running the first RDM program to ensure that they are shareable. The initial content
of the files is immaterial, since they are re-initialized when the database is opened. The
problem on Novell is that files created dynamically are always marked unshareable even
when requested as shareable and can only be made shareable through execution of the
Novell flag utility.
Whenever RDM initiates a recovery operation, the error reporter is called with the
message "recovery about to occur." The purpose of this function is simply to inform the
user that a recovery is about to take place. You will probably wish to tailor the error
reporting for your particular application requirements through d_set_dberr.
S_RECOVERY is probably one of the return codes that you will want to "ignore" in your
error reporter.

6.6

Archive Logging

A system-wide transaction archive log can be supported through user-defined functions,


which can be called automatically by the RDM runtime system. In the rare event that
automatic recovery is not possible, the transaction identifier for the incomplete
transaction will be known by the lock manager, and a user-initiated database restore can
be performed. This would involve reloading the database from the last complete backup
and using a utility to reapply the changes recorded on the archive log, up to but not
including the last transaction.
Module trlog.c contains complete information, along with the skeletal function
declarations necessary for implementing archive logging.
The user-defined functions are needed because of the diversity of devices that could be
used for storing the archive data (for example, cartridge tapes, floppies, files, nine-track
tapes, write-once laser disks, etc.). Access to these devices cannot be accommodated
through any standard techniques.
However, the performance cost incurred by maintaining an archive log, in addition to
automatic transaction logging, would almost always be much greater than the benefits of
the additional level of recoverability. Keeping regular backups of the database files is the
best method for protecting the database beyond the automatic recovery capability
previously described.

Transaction Processing

6-7

Chapter 7
Multi-User Database Control
7.1

Introduction

In the example below, two users are attempting to update a record from the database at
about the same time. The left column gives a relative time and the other columns
identify the actions that occur for the respective user at each time.
Table 7-1. Two Users Updating a Record
Time
1

User 1
Read record

2
3

Read record
Modify record

4
5

User 2

Modify record
Write record

Write record

At Time 1, User 1 reads the record from the database. At Time 2, User 2 reads the record.
Both users then modify and write the record back to the database. But User 2s copy of
the record does not have User 1s changes (they were made after User 2 read the record).
Thus when User 2s record is written to the database, User 1s changes are lost. If User 2
had not read the record until after Time 5, the changes from User 1 would not have been
lost. But without any control there is no way to guarantee that User 2 will put off
reading until User 1s updates are completed.
The solution is to provide a mechanism whereby updates to shared data are
synchronized, so that only one user can be updating the shared data at a time. The
mechanism usually is some form of a lock, which is used to serialize updates to data
shared among multiple users. A lock must be applied before shared data is updated, so
that other users cannot update the locked data. Thus, through use of a lock, the above
example would proceed as shown in the following table:

Multi-User Database Control

7-1

Table 7-2. Two Users Updating a Record, Using Locks


Time

User 1

Request record lock

Lock granted

Read record

Modify record

Write record

Free lock

User 2
Request record lock

Lock granted

Read record

Modify record

Write record

10

Free lock

Once User 1s lock request is granted at Time 2, User 2 will wait for the record to be
unlocked before continuing. When User 1 has completed the update, the lock is freed at
Time 6. User 2 is then granted the lock, and the record (which now includes User 1s
changes) is read and then updated with User 2s changes.
As the above example illustrates, the key issue in multi-user database applications is data
integrity, ensuring that no data is lost and that the data is logically consistent (that is, the
interdata relationships that should exist do exist). Data integrity is supported in RDM
through three interrelated facilities:
File and record locking
Transaction processing
Transaction logging and recovery
File locking and record locking are used, as in the example, to prevent loss of data by
synchronizing access to shared files and records so that only one user at a time can
update them.
Multi-user database application programming is a difficult task, which should be
approached with careful planning and design. The problems that can occur in multi-user
programs are often very difficult to resolve. The capabilities provided in RDM are
sufficient for you to ensure both data integrity and good performance. The remainder of
this chapter explains the RDM implementation of these capabilities, including guidelines
for their effective use.

7-2

Centura RDM Users Guide

7.2

Operational Environment

The RDM multi-user operational environment is depicted in Figure 7-1.

Lock Manager

Lock Requests

Lock Requests
Lock
Requests

USER:ALPHA

File I/O

USER:BETA

USER:GAMMA

File I/O

File I/O

USER:DELTA

File I/O

File Server

Database
Files

vista.taf

alpha.log

gamma.log

beta.log

delta.log

Fig. 7-1. Multi-User Operational Environment


Each user executes their own copy of the database program. On a multi-user UNIX
system, the program executes as a separate process and interacts with the user through a
terminal. Each users program execution will be referred to as a process. Each user must
have a unique user identifier. The user id can be specified either through the DBUSERID
environment variable or through a call to function d_dbuserid prior to the d_open call.
The rdm.ini file cannot be used to specify the user id.
If transaction logging is to be used, each user will have a unique transaction log file. By
default, the name of the log file is userid.log. The log files name and location can be
specified through either the DBLOG environment variable or the rdm.ini file or function
d_dblog, which also must be called before the database is opened. The transaction log
contains the database changes made by the user within a transaction, and is used to
support recovery.
Management of the RDM locks, and control of automatic recovery, is performed by the
RDM lock manager. Each process sends lock requests to the lock manager, which queues
the requests on a "first come, first served" basis. The process will wait for the lock
manager to send a reply either granting or denying the request. Locks are denied when
the lock request has waited on the queue for a period longer than the timeout value
Multi-User Database Control

7-3

specified by the requesting process. The lock manager is a program that can be executed
from any node on a network or as a background task on a stand-alone machine. See the
RDM Multi-User Guide for a complete description of the lock manager.
A database-family transaction activity file (TAF) is used by the RDM runtime to control
database recovery in the event the lock manager goes down. This file is named vista.taf
by default, but can be named or located through either environment variable DBTAF or
function d_dbtaf, or the rdm.ini file, which must be called before d_open.
Each database family must use only one TAF so that automatic recovery is done
correctly. Also, all log files for the database family (TAF) must be located in the same
physical directory. The application must enforce these rules through the consistent use
of the environment variables, their corresponding d_ functions, and the rdm.ini file.
Multi-user database programs must open the database in shared access mode. This is
done by passing an open type of s to function d_open. For example, to open the tims
database for multi-user access, issue the following call:
if (d_open("tims", "s") == S_UNAVAIL)
{
printf("database unavailable\n");
exit(1);
}

Status code S_UNAVAIL is returned when some other database program has opened the
tims database in exclusive access mode.

7.3

File Locking

7.3.1 Introduction
The principal locking mechanism provided by RDM is the file lock. An advisory record
locking capability, which is used in conjunction with file locking, is also provided and is
described in section 7.5, "Advisory Record Locks." Although file locking is often
regarded as an inferior multi-user locking mechanism, in the RDM environment it can be
used very effectively without sacrificing performance. In fact, well-performing multiuser applications can and have been written using only file locking.
Much of the file locking functionality provided in RDM has been developed to optimize
multi-user performance. In addition, section 7.6, "Program Design Considerations," gives
some general program design guidelines to help you effectively use the RDM
capabilities. Table 7-3 lists the file locking functions.

7-4

Centura RDM Users Guide

Table 7-3. File Locking Functions


Function

Definition

d_reclock(REC, type, dbn)

Lock data and key files associated with


record type

d_setlock(SET, type, dbn)

Lock data files associated with set type

d_keylock(FIELD, type, dbn)

Lock key file containing key field

d_lock(num, pkt, dbn)

Lock group of record and set types

d_recfree(REC, dbn)

Free lock on record type

d_setfree(SET, dbn)

Free lock on set type

d_keyfree(FIELD, dbn)

Free lock on key field type

d_freeall()

Free all read locks

d_reclstat(REC, type, dbn)

Get record types lock status

d_setlstat(SET, type, dbn)

Get set types lock status

d_keylstat(FIELD, type, dbn)

Get key field types lock status

d_timeout(secs)

Specify wait time before timeout

d_locktimeout(readsecs,writesecs)

Specifies number of seconds lock manager


will allow locks to be held.

Note that functions d_trend and d_trabort are also used with file locking although they
are not listed here. Recall that both functions free locked files. The remaining pages of
this section describe the functions listed in Table 7-3.
Function d_reclock locks the data file containing the record type, as well as all key files
containing key fields defined in the specified record type. For example, assume the
following DDL statements appear in your schema:

Multi-User Database Control

7-5

data file "tims.d01" contains system, key_word, intersect;


data file "tims.d02" contains author, borrower, info, text;
key file "tims.k01" contains id_code;
key file "tims.k02" contains friend, word;
...
record info {
unique key char id_code[16];
/* dewey dec. code */
char info_title[80];
/* title of book, article, mag. */
char publisher[32];
/* name of publisher */
char pub_date[12];
/* date of publication */
int info_type;
/* 0=book, 1=mag, 2=art */
}
...
record key_word {
unique key char word[32];
/* subject key words */
}
...
set key_to_info {
order last;
owner key_word;
member intersect;
}

The call d_reclock(INFO, "r", CURR_DB) will cause tims.d02 and tims.k01 to be readlocked. The call d_reclock(KEY_WORD,"r", CURR_DB) will cause tims.d01 and tims.k02
to be read-locked. Record locks are always necessary when creating a record with keys,
or when modifying key fields in records, because they guarantee that all of the files
related to the record will be locked.
Function d_setlock locks the data files that contain the owner and member record types
of the specified set. The call d_setlock(KEY_TO_INFO, "r", CURR_DB) will cause only
file tims.d01 to be read-locked, because both record types are contained in the same file.
This function does not lock key files associated with records. Set locks are necessary
when connecting or disconnecting records in sets, or when traversing sets, because they
guarantee that all of the files related to the set will be locked. Note, however, that if
record locks had already been applied to both the key_word and intersect record types,
the set lock would not be needed (although it would be accepted). Any time the correct
files have been locked, even though by a different locking call, functions that use the files
will execute without locking errors.
Function d_keylock locks the key file that contains the specified key field. The call
d_keylock(ID_CODE, "r", CURR_DB) will lock only file tims.k01. By locking only a key
file, you may scan keys, as in the following code:

7-6

Centura RDM Users Guide

d_keylock(ID_CODE, "r", CURR_DB);


for (
d_keyfrst(ID_CODE, CURR_DB);
db_status == S_OKAY;
d_keynext(ID_CODE, CURR_DB) )
{
d_keyread(id_code, CURR_DB);
printf("id code: %s\n", id_code);
}
d_keyfree (ID_CODE, CURR_DB);

By locking only the key file, you eliminate the overhead of obtaining locks on the data
file, and possibly other key files related to the same record type. Also, in a multi-user
environment, it is important not to lock any files that are not going to be used, because
you may be preventing other users from making progress.
Function d_lock is used to lock a group of record and set types, and is described in detail
in section 7.3.6, "Grouped Lock Requests."
Table 7-4 lists the types of locks that can be applied.
Table 7-4. File Lock Types
Type

Description

Read lock.

Write lock.

Exclusive lock.

Keep lock.

Functions d_recfree, d_setfree, and d_keyfree free read locks or exclusive locks on their
respective record, set, or key field types for their database. Function d_freeall will free
all read-locked files across all databases.
The current lock status of a record, set, or key type can be found by calling functions
d_reclstat, d_setlstat, or d_keylstat.
Function d_timeout is used to inform the lock manager of the number of seconds that
lock requests from this process are to wait on the queue before being denied.
Function d_locktimeout is used to tell the lock manager how long to allow read locks and
write locks to be held in the absence of communication from the runtime. This is
intended to prevent frozen clients from making the database permanently unavailable,
and works only with network lock managers (like TCP/IP).

Multi-User Database Control

7-7

7.3.2 Read Locks


A lock type r passed to a locking function specifies that the files are to be read-locked. A
read lock on a file prevents other processes from placing a write or exclusive lock on that
file. Other processes are allowed to read-lock the file. Thus, when a file is read-locked,
other processes are allowed to read the file but are prevented from updating the file.
Functions that only read from the database but cannot be safely executed concurrently
with updates require that the files involved be read-locked. In addition, the key access
functions and set navigation functions require that the files be read-locked. The record
access functions listed in Table 7-5 can be executed concurrently with updates and,
therefore, do not require that the data file be locked. If the record being read happens to
have been deleted, status code S_DELETED will be returned by the function.
Note: Using these functions without a lock will retrieve data from your local cache
without ensuring that it is the most up-to-date data. To ensure synchronization of cache
pages, use a read lock.
Table 7-5. Read Functions that Do Not Need a Lock
Function

Definition

d_cmtype(SET, &type, dbn)

Get record type of current member.

d_cotype(SET, &type, dbn)

Get record type of current owner.

d_crread(FIELD, &val, dbn)

Read field from current record.

d_csmread(SET, FIELD, &val, dbn)

Read field from current member.

d_csoread(SET, FIELD, &val, dbn)

Read field from current owner.

d_members(SET, &count, dbn)

Get count of set members.

d_recfrst(REC, dbn)

Position to first occurrence of record type.

d_reclast(REC, dbn)

Position to last occurrence of record type.

d_recnext(dbn)

Position to next occurrence of record type.

d_recprev(dbn)

Position to previous occurrence of record type.

d_recread(&val, dbn)

Read current record.

Read locks can be requested either from outside or within a transaction. Read locks that
are issued within a transaction, or are not freed prior to a call to d_trbegin, are freed by
either d_trend or d_trabort (unless the lock is to be keptsee section 7.3.5,
"Upgrading/Downgrading of File Locks"). Read locks requested outside a transaction
are freed by calling the appropriate lock freeing function, or by the termination of an
intervening transaction.

7-8

Centura RDM Users Guide

7.3.3 Write Locks


In order to update the database, the files to be updated must be write-locked. Write locks
are requested by passing a w lock type to the lock function. A write lock gives the
requesting process exclusive access to the locked file.
Write locks can only be requested within a transaction. Error code S_TRNOTACT will be
returned by the lock function if a transaction is not active when the write lock request is
made. Write locks are freed by d_trend or d_trabort.
A multi-user programming problem that often occurs is called deadlock. Deadlock is the
situation where multiple processes each hold locks on certain resources, and each is
waiting to lock resources that are held by the others. The simplest example of deadlock
is where Process 1 has Resource A locked and is requesting a lock on Resource B, while
Process 2 has a lock on Resource B and is requesting a lock on Resource A. Both
processes require access to both resources in order to complete their transactions, but
both will wait forever for the other to free its resources.
Deadlock situations can arise in RDM when multiple processes are attempting to write
lock the same files. Only one process will be granted the write lock, and the remaining
processes will wait on the queue until the locked file is freed. In a deadlock, those
processes will wait on the queue forever because the locked file is never freed. To avoid
this situation, RDM provides function d_timeout, which allows the application to specify
how long to wait on the queue before denying a lock request. The default wait time is 10
seconds. An integer argument is passed to d_timeout to specify the number of seconds
before timing out. A negative value disables timeouts (you should be certain your
program is deadlock free). A value of zero may be used to cause a timeout when a lock
request cannot be immediately granted. When status S_UNAVAIL is returned from a
lock function (indicating a timeout) the program should abort the transaction and then
restart it, in order to prevent deadlock. Status S_UNAVAIL is also returned when the
lock manager is temporarily unable to handle the lock request.

7.3.4 Exclusive Locks


The ability to gain exclusive access to database files is provided by passing an exclusive
lock type (x) to the appropriate lock function. Exclusive access to a record or set type
differs from a write lock in that it allows updates independent of transactions and other
locks. Updates to files in exclusive access can still be made within transactions, if
desired. The purpose of this capability is to allow unlocked updates to be made to only a
portion of the database while allowing other programs to have shared access to other
parts of the database.
Exclusive locks are only released by calling d_recfree, d_setfree, or d_keyfree. Unless
explicitly freed, exclusive access locks are held even after the database has been closed by
the process that applied the exclusive locks. In this case, the exclusive locks will still be
in place when that same user re-opens the database. This provides for situations (for
Multi-User Database Control

7-9

example, month-end closings) where large time-consuming updates requiring exclusive


file access arent completed by the end of the day, and the database program doing the
update needs to be terminated and will not be restarted until the next day. Note,
however, that if the lock manager goes down, any exclusive locks will be lost.

7.3.5 Upgrading/Downgrading of File Locks


Record, set, and key types that are read-locked do not need to be freed when a
transaction is started. Moreover, the capability to upgrade a read lock to a write or
exclusive lock is provided. Similarly, a capability is provided to prevent d_trend from
freeing a lock, keeping the record or set type read-locked after the transaction has ended.
This provides for improved performance by allowing database data to remain in the
virtual page buffers, reducing the amount of required disk I/O.
To upgrade a read lock to a write lock, leave the record, set, or key type locked and reissue the d_reclock, d_setlock, or d_keylock call (with type w) after d_trbegin. The
upgrade is only granted if there are no upgrade requests queued and all other read locks
have been freed. Granted upgrade requests ensure that no changes have been made by
other processes between the read and write lock activity. If any normal write locks (that
is, not upgrades) are on the queue, the requested upgrade will be granted after all read
locks have been freed but before the first queued write lock. If another upgrade request
has been queued by the lock manager, the upgrade will be denied immediately
(S_UNAVAIL status) but the record or set type will remain read-locked. The proper
action in this situation is as follows:
1.

Abort the transaction.

2.

Start a new transaction.

3.

Request a normal write lock.

4.

Update the necessary data.

If the normal write lock request is denied, you should abort and restart the transaction as
usual. To upgrade a read lock to an exclusive lock, simply re-issue the d_reclock or
d_setlock with type x. The constraints that apply to upgrades from read locks to write
locks also apply to upgrades from read locks to exclusive locks.
To downgrade a write lock to a read lock, or to keep a record or set type read-locked after
execution of d_trend, re-issue a d_reclock or d_setlock call with type k prior to d_trend.

7.3.6 Grouped Lock Requests


Functions d_reclock and d_setlock only allow for locking record or set types one at a
time, requiring each request to be granted by the lock manager before the next lock
request is processed. Often it is desirable to lock a group of record or set types in a single
request, none of the locks being granted unless all of the requested files are available. In

7-10

Centura RDM Users Guide

fact, deadlock-free programs result when all needed locks are requested at the beginning
of each transaction and processing only continues when all have been granted. This is
one of the standard techniques for avoiding deadlock.
Function d_lock provides this grouped lock request capability. The first argument
passed to d_lock is an integer containing the count of the number of items to be locked.
The second argument is a pointer to the packet of lock requests. Each lock request is
placed in a LOCK_REQUEST structure entry as defined below and declared in file
vista.h.
typedef struct {
int item;
/* number of record or set to be locked */
char type;
/* type of lock */
} LOCK_REQUEST;

Structure field item contains the record or set constant (as defined in dbname.h) for the
record or set to be locked. Key types cannot be locked using function d_lock. Field type
contains the type of lock to be applied: r, w, x, or k. (Note that these are single character
constants and not strings.)
Grouped lock requests can be statically defined. For example, suppose that, for
transaction trxc02, record types EMP and JOBS and set DEPT_EMPS are to be locked.
The following variables could be declared and used as follows:
LOCK_REQUEST trxc02[] = {
{EMP,
w},
{JOBS,
w},
{DEPT_EMPS, r}
};
int trxc02_count = 3; /* sizeof(trxc02) / sizeof(trxc02[0]) */
...
d_trbegin("trxc02");
if (d_lock(trxc02_count, trxc02, CURR_DB) == S_OKAY) {
... /* process transaction */
d_trend();
}
else
d_trabort();

The trade-off associated with using d_lock, as opposed to waiting until you actually need
the lock before you request it, is that the files are locked and others are prevented from
using them for a longer period of time. The actual impact will depend on how you
design your application program. The peace of mind associated with knowing your
program is free of deadlock is often worth some performance penalty.

7.3.7 Lock Status Functions


Three lock status functions are provided, which return the current lock status of a record,
set, or key for the requesting process. Function d_reclstat returns the current lock status
of the specified record type. Function d_setlstat returns the current lock status of the

Multi-User Database Control

7-11

specified set type. Function d_keylstat returns the current lock status of the specified
key field type. A pointer to a character variable that is to contain the lock status is
passed to each of the functions. Note that these functions only return the status of the
locks held by the requesting process.

7.3.8 Static Records


In a multi-user environment, there are applications in which certain information in the
database is virtually static (that is, it does not change). Examples of this kind of data
would be menus, data entry forms, help screens, user messages, etc. Rather than
requiring database programs to place locks on this data in order to access it, a record
attribute called static can be defined in the DDL to identify this kind of information as
follows:
[static] record recname {
...
}
Data files that contain a static record must contain only static records. Static records can
be used in sets, but only when the set itself also does not change.
To change static records, the database must be opened in exclusive access mode.
The principal advantage in using static records is performance improvements due to
better virtual paging of the static data. Dynamic data requires that the page buffers be
cleared when a file lock is requested, in order to ensure concurrent database
synchronization. Static data does not need to be cleared because no synchronization is
necessary when there are no changes.

7.4

Timestamping

7.4.1 Introduction
Consider the following RDM database access scenario:
d_reclock(REC, "r", CURR_DB);
d_keyfind(KEY, value, CURR_DB);
d_crget(&dba, CURR_DB);
/*
d_recfree(REC, CURR_DB);
/*
...
...
d_reclock(REC, "r", CURR_DB);
d_crset(&dba, CURR_DB);
/*
d_recread(REC, CURR_DB);
/*
...

/* lock data and key files for REC */


/* find record by key */
save currency */
free record lock */
/* relock record type */
restore currency */
read and process record */

The first four statements lock a record type, locate a record occurrence through a key
field, save the database address of that record, and then free the lock. The last three
statements re-lock the record type, set the current record to the saved database address,

7-12

Centura RDM Users Guide

and then read the record from the database. However, while the record type was
unlocked by this process another process may have updated the database and modified
or deleted the record associated with the saved database address. Thus, when the record
type is re-locked, the record occurrence is read directly through the database address,
which may now contain a deleted record (which would result in a database error) or a
modified record (in which case the user would not be made aware of the modifications).
One way to avoid this problem is to re-access the record with another d_keyfind, which
would return a "not found" status if the record had been deleted. However, this would
not reflect changes to the record, and it would be slower than a direct access through the
database address.
Timestamping is a technique whereby it is possible to detect whether a particular record
occurrence still exists, and if it has been modified since it was last accessed by a given
process. This allows direct access to a record after the file has been unlocked and
subsequently re-locked for those records that havent been updated in the interim.

7.4.2 Implementation
Each timestamped record occurrence contains two values in its record slot header. One
is the time when the record was created and the other is the time when the record was
last updated. When a record slot is accessed, the maximum of these two values (that is,
the time of last modification) is placed, along with the database address, in the currency
tables. Functions are provided that compare the value placed in the currency table
against the times stored in the record, in order to determine if the record has changed.
There may also be situations in which it is desirable to know if a set has changed since
last accessed. Thus, the time of last update value (connect or disconnect) is stored in the
timestamped set pointers, to be used to detect changed sets.
The time values cannot simply be the system clock time. In a network environment the
clocks of the different computers are not synchronized. What is used is a sequence
counter, which is accessible by all processes. This sequence counter is stored in the file
headers (page zero) for each database file, and is incremented each time a write lock is
placed on the file or the database is opened for exclusive access. The counter is
initialized to zero only when the database is initialized.
Timestamping is an optional feature enabled through the following DDL specifications:
timestamp records [ recname [, recname... ] ] ;
timestamp sets [ setname [, setname... ] ] ;
These statements may appear anywhere within a DDL schema specification file. If no
record or set names are specified, all records or sets will be timestamped.

Multi-User Database Control

7-13

Record timestamping adds eight bytes of additional space overhead to each record slot.
Set timestamping adds four bytes of additional space overhead to each set pointer
contained in set owner records.
The RDM runtime support for timestamping includes the following:
Last access timestamps, incorporated with the currency tables
Currency table access functions to handle the last access timestamps
Functions that test the timestamp status
If timestamping is enabled for a record, the currency table will associate the most recent
modification time of that record with its database address. Whenever the currency of
that record changes (current owner, current record, or current set) through the
navigation functions, that modification time will be adjusted. These timestamp values
are then used by the five functions listed in Table 7-6 to test the modification status of
that record.
Table 7-6. Timestamp Status Functions
Function

Definition

d_crstat(dbn)

Test last access status of current record.

d_costat(SET, dbn)

Test last access status of current owner.

d_cmstat(SET, dbn)

Test last access status of current member.

d_csstat(SET, dbn)

Test last access status of current set.

d_recstat(dba, time, dbn)

Test last access status of record.

Each of the above functions returns one of the status codes listed in Table 7-7 below.
Table 7-7. Timestamp Status Codes
S_OKAY

The record or set has not changed.

S_UPDATED

The record or set has been modified.

S_DELETED

The record has been deleted.

Status S_DELETED is returned if the record slot contains either a deleted record, or a
record with a creation date that is later than the current last access timestamp. Status
S_UPDATED is returned if the record or set has been updated since it was last accessed.
The functions listed in Table 7-8 provide the ability to get and set the last access (or
currency) timestamp values stored with the timestamps. All timestamp variables are of
type "unsigned long."

7-14

Centura RDM Users Guide

Table 7-8. Timestamp Currency Functions


Function

Definition

d_gtscr(&ts, dbn)

Get last access timestamp of current record.

d_gtsco(set, &ts, dbn)

Get last access timestamp of current owner.

d_gtscm(set, &ts, dbn)

Get last access timestamp of current member.

d_gtscs(set, &ts, dbn)

Get last access timestamp of current set.

d_stscr(ts, dbn)

Set last access timestamp of current record.

d_stsco(set, ts, dbn)

Set last access timestamp of current owner.

d_stscm(set, ts, dbn)

Set last access timestamp of current member.

d_stscs(set, ts, dbn)

Set last access timestamp of current set.

Whenever a database address in the currency table is to be saved and restored, it is


imperative that its corresponding last access timestamp be saved and restored along with
it, if the record type is timestamped. Table 7-9 lists the standard currency access
functions from Chapter 5, "Database Manipulation," and their timestamp counterparts.
These must be called together when the subject record type is timestamped. Functions
d_gtscs and d_stscs need to be called with d_csoget and d_csoset when the specified set
type is timestamped.
Table 7-9. Corresponding Currency Access Functions
If called

Also call

d_crget

d_gtscr

d_csoget

d_gtsco, d_gtscs

d_csmget

d_gtscm

d_crset

d_stscr

d_csoset

d_stsco, d_stscs

d_csmset

d_stscm

Using these capabilities, the example given in the introduction could be coded as follows:

Multi-User Database Control

7-15

DB_ADDR dba;
ULONG rts;
...
d_reclock(REC, "r", CURR_DB);
d_keyfind(KEY, value, CURR_DB);
d_crget(&dba, CURR_DB);
/*
d_gtscr(&rts, CURR_DB);
/*
d_recfree(REC, CURR_DB);
/*
...
...
d_reclock(REC, "r", CURR_DB);

/* lock data and key files for REC */


/* find record by KEY */
save current record */
and its timestamp */
free record lock */
/* relock record type */

/* reset current record and its timestamp */


d_crset(&dba, CURR_DB);
d_stscr(rts, CURR_DB);
/* test update status of current record */
if (d_crstat(CURR_DB) == S_OKAY)
{
d_recread(&rec, CURR_DB);
... /* process record */
}
else if (db_status == S_UPDATED)
{
... /* check modifications */
}
else
{
... /* record was deleted */
}
...

Status code S_TIMESTAMP is returned when the record or set involved in the function is
not timestamped. Status S_NOTLOCKED is returned when the record or set type
involved in the function is not locked.

7-16

Centura RDM Users Guide

7.5

Advisory Record Locks

Three functions that support the locking of individual record occurrences are given in
Table 7-10. These functions are used in conjunction with file locking to support end-user
modification of data without having to keep a file locked.
Table 7-10. Record Locking Functions
Function

Definition

d_rlbset(dbn)

Set current records lock bit

d_rlbtst(dbn)

Test current records lock bit

d_rlbclr(dbn)

Clear current records lock bit

A bit in the record is used as a flag that indicates whether the record occurrence is locked.
This bit is called the record lock bit. The record locking functions are used to set, test,
and clear the record lock bit of the current record.
Function d_rlbset is called to set the record lock bit of the current record. The data file
containing the record need not be locked. The RDM runtime will automatically
synchronize access to the record. The current record is accessed directly, without using
the cache, so that upon successful completion of the call the bit is physically set in the
record on the disk. Function d_rlbset will return status S_UNAVAIL if the system
cannot gain access to the data file (due to its being write or exclusively locked). Status
S_LOCKED is returned if the current records lock bit is already set. Status S_OKAY is
returned when the function has successfully set the lock bit. If d_rlbset is called within a
transaction, the operation still goes directly to the file, bypassing use of the cache. Thus,
a d_trabort call does not undo any record lock bit settings that were performed within
the transaction.
Function d_rlbclr is called to clear the record lock bit of the current record. After a
record occurrence is locked, the record will remain locked until function d_rlbclr is called
to clear the lock bit. If d_rlbclr is called from within a transaction, the data file
containing the current record must be write-locked. User error S_NOTLOCKED is
returned if the function is called within a transaction and the data file of the current
record is not write-locked. The clearing of the record lock bit cannot be applied until the
transaction ends because other modifications to the record are usually involved in the
transaction. If d_trabort is called after d_rlbclr, the clear is aborted and the record
remains locked. When d_rlbclr is called within a transaction, the lock bit is cleared
through the cache rather than directly to the file. If d_rlbclr is called outside of a
transaction, the file does not need to be locked and the operation will directly clear the
lock bit on the file. This is used to clear a lock after it has been determined that the
record no longer needs to be updated.
Multi-User Database Control

7-17

Function d_rlbtst can be called to test the lock bit status of the current record. Status
code S_LOCKED is returned if the lock bit of the current record is set; code
S_UNLOCKED is returned if the lock bit is clear. The data file containing the current
record does not need to be locked in order to call d_rlbtst.
In addition to the above functions, the system provides a global integer status variable in
the single-tasking, static-link libraries called rlb_status, which is set to S_LOCKED or
S_UNLOCKED by the following record read functions:
d_recread
d_crread
d_csoread
d_csmread
No records that have been locked by the program should remain locked after the
database is closed. The Database Consistency Check utility, dbcheck, can be used to
report all record occurrences that have the lock bit set, or the utility dbclrlb can be used
to clear them.
Note: The setting of a records lock bit (RLB) will not automatically prevent another
process from updating the locked record. It is the responsibility of the application to
check if a record occurrence is locked before allowing updates to it, by either calling
d_rlbtst or checking rlb_status after reading the records contents. The RDM functions
that modify the database do not use the status of the RLB.
Use of these functions will be illustrated in the next section.

7.6

Program Design Considerations

7.6.1 Basic Guidelines


The primary guideline to follow in designing a multi-user application that uses the RDM
locking functionality is:
Minimize the amount of time that a file is locked.
The application program has complete control over the use of file locks. If the program is
designed to adhere to the above principle, then well-performing multi-user applications
can result. A necessary corollary to the above principle is:
Never allow the end-user to control the duration of a file lock!
That is, never design the program so that a file is kept locked while the program is
waiting for the end-user to perform some function. With the capabilities provided in
RDM there is never any reason for these guidelines to be violated.

7-18

Centura RDM Users Guide

The design techniques that follow show how these principles are applied in data entry,
deletion, modification, and retrieval.

7.6.2 Data Entry


The entry of new records and set connections into a database is very straightforward.
The steps involved are outlined below.
1.

Collect all relevant data from user.

2.

Begin transaction.

3.

Write-lock necessary record and set types.

4.

Create new record occurrences and make necessary set connections.

5.

End transaction.

The goal is to minimize the amount of time that a file is locked. In this procedure, the
files are locked for only the amount of time it takes to perform Steps 4 and 5. If the time
required to perform those steps is great (more than a few seconds), it may be beneficial to
try to divide the transaction into two or more smaller ones. In general, however, this will
not be required. A segment of the ent_info code from Chapter 5, "Database
Manipulation," is given below with multi-user control functions added.

Multi-User Database Control

7-19

int info_cnt = 5;
LOCK_REQUEST info_pkt[] = {
{AUTHOR_LIST, w},
{INFO,
w},
{ABSTRACT,
w},
{INTERSECT, w},
{KEY_WORD,
w}
};
...
/* Enter technical information records into TIMS database */
ent_info()
{
char s[32]; /* generic string variable */
/* enter tech info into TIMS database */
while (get_info() != EOF)
{
d_trbegin("ent_info");
while (d_lock(info_cnt, &info_pkt, CURR_DB) == S_UNAVAIL)
; /* wait until locks are available */
if (db_status != S_OKAY)
{
d_trabort();
... /* notify user of problem */
return (0);
}
/* see if author exists */
...
/* create new tech. info record */
if (d_fillnew(INFO, &irec, CURR_DB) == S_DUPLICATE)
{
d_trabort();
printf("duplicate id_code: %s\n", irec.id_code);
return;
}
else
{
/* connect to author record */
...
enter_key_words();
enter_abstract();
}
d_trend();
}
}

In the info_pkt lock request packet, one set type and four record types are locked, even
though five set types are involved in the transaction. The RDM runtime system does not
care how a file lock is obtained, as long as the appropriate files are locked when the
operation requiring the lock is performed. The data files involved in the set operations
are locked when the record types are locked. The lock packet could have listed every set
type and every record type involved in the transaction, but this would make it larger
than necessary. (RDM does optimize the lock requests so that a lock request for a given
file is made only once). The d_lock call is repeated until the file locks are granted. This

7-20

Centura RDM Users Guide

cannot produce a deadlock in this situation since no other files are locked. Notice that if
the id_code is a duplicate, the transaction is aborted.
In this case, however, another data entry guideline has been violated, which is that files
should not be kept locked while control has been given to the user. Functions
enter_key_words and enter_abstract both prompt the user for information while the files
are locked. To properly implement the function, it would be necessary to redesign the
program so that the user first enters all of the needed information (that is, have get_info
also prompt for the key words and abstract), after which the transaction is processed.

7.6.3 Data Deletion


Deletion of records and sets follows basically the same guidelines as data entry:
1.

From user, identify data to be deleted.

2.

Read-lock relevant files (if necessary).

3.

Read data to be deleted.

4.

Free files.

5.

Display data to user and request confirmation.


Cancel operation if not confirmed.

6.

Begin transaction.

7.

Write-lock necessary set and record types.

8.

Perform necessary set disconnections and record deletions.

9.

End transaction.

Steps 2 through 5 are optional. They should not occur between Steps 7 and 8, however,
because of the confirmation request. In this procedure the files are read-locked for the
duration of Step 3 and write-locked for the duration of steps 8 and 9. In Step 2, read
locks are necessary if the data is to be accessed by key or by set. If it can be accessed
directly (for example, d_recread), the file need not be read-locked at all.
Function del_info from Chapter 5, "Database Manipulation," illustrates the previous
procedure.

Multi-User Database Control

7-21

int info_cnt = 5;
LOCK_REQUEST info_pkt[] = {
{AUTHOR_LIST, w},
{INFO,
w},
{ABSTRACT,
w},
{INTERSECT, w},
{KEY_WORD,
w}
};
del_info()
{
struct info irec;
long count;
char id[16], name[32];
printf("id_code: " ); /* get info to delete */
gets(id);
d_reclock(INFO, "r", CURR_DB);
if (d_keyfind(ID_CODE, id, CURR_DB) == S_NOTFOUND)
{
d_recfree(INFO, CURR_DB);
printf("id_code %s not on file\n", id);
return;
}
d_recread(&irec, CURR_DB);
d_reclock(AUTHOR, "r", CURR_DB); /* get name */
d_findco(HAS_PUBLISHED, CURR_DB);
d_crread(NAME, name, CURR_DB);
d_recfree(INFO, CURR_DB);
d_recfree(AUTHOR, CURR_DB);
...
/* display data and confirm delete request */
d_trbegin("del_info");
while (d_lock(info_cnt, &info_pkt, CURR_DB) == S_UNAVAIL)
;
/* wait till locks are available */
/* disconnect and delete abstract */
...
/* disconnect, delete intersect and key word */
...
/* disconnect info rec from author, delete */
...
/* delete author, if no other pubs records */
...
d_trend();
}

7.6.4 Data Modification


The general procedure for the modification of data follows:
1.
2.
3.
4.
5.

7-22

From user, identify data to be modified.


Read-lock relevant record and set types (if necessary).
Read data to be modified.
Free files.
Allow user to edit data.

Centura RDM Users Guide

6.
7.
8.
9.

Begin transaction.
Write-lock necessary set and record types.
Perform necessary modifications.
End transaction.

Here again, no files are locked while the user is editing the data. But notice that since the
files are not locked, it is possible that some other process may try to modify the same
data at the same time. In many cases, however, even though it may be theoretically
possible, it is not practically possible. The nature of the application may render it
impossible for two users to modify the same data at the same time. For example, in the
tims database it isnt possible for the same book to be returned by more than one
borrower at the same time. In designing your application you should carefully analyze
the real-world use of your data and avoid incorporating unnecessary code to handle
impossible circumstances.
However, there are many situations where it is possible for two users to attempt to
modify the same data at the same time. Record locking is used to synchronize these
updates, as in the following procedure:
1.

From user, identify record to be modified.

2.

Lock record occurrence (using function d_rlbset).

3.

Cancel operation if record is already locked.

4.

Allow user to edit record.

5.

Begin transaction.

6.

Write-lock record type.

7.

Modify record.

8.

Clear record occurrence lock (using function d_rlbclr).

9.

End transaction.

This illustrates simple modification of a single record occurrence. If a set occurrence is to


be modified, the program could adopt a convention whereby if the owner record
occurrence is locked, neither the data in that record nor any sets owned by that record
can be modified by a separate process. The use and interpretation of the record locking
functionality is a program design decision, but it must be consistently applied
throughout all applications accessing the same databases. An implementation of this
procedure is shown in the following example of an info record occurrence modification:

Multi-User Database Control

7-23

struct info irec;


int stat;
...
printf("enter id code: ");
gets(irec.id_code);
d_keylock(ID_CODE, "r", CURR_DB);
stat = d_keyfind(ID_CODE, irec.id_code, CURR_DB);
d_keyfree(ID_CODE, CURR_DB);
if (stat != S_OKAY)
printf("record not found\n");
else if (d_rlbset(CURR_DB) != S_OKAY)
printf("unable to access record\n");
else
{
d_recread(&irec, CURR_DB);
...
/* display record and allow edits of all but id_code */
d_trbegin("mod_info");
while (d_reclock(INFO, "w", CURR_DB) == S_UNAVAIL)
; /* wait until locks are available */
d_recwrite(&irec, CURR_DB);
/* update record */
d_rlbclr(CURR_DB);
/* clear record lock bit */
d_trend();
/* write changes to database */
}

7.6.5 Data Retrieval


In a typical database application, data retrieval operations usually fall into one of the
following three types:
1.

Locating a record or related record occurrences.

2.

Browsing through a list of records where there may be one record per line
on the display.

3.

Producing reports where many records in the database may need to be accessed.

For Type 1 data retrieval in RDM, the procedure is just to lock the necessary record, set,
or key types, then access the data, free the locks, and display the results. For example,
the following code displays an item by id code from the tims database:

7-24

Centura RDM Users Guide

struct info irec;


/* info record variable */
char name[32];
/* authors name */
...
printf("enter id code: ");
gets(irec.id_code);
d_keylock(ID_CODE, "r", CURR_DB);
d_setlock(HAS_PUBLISHED, "r");
if (d_keyfind(ID_CODE, irec.id_code, CURR_DB) == S_OKAY)
{
d_keyfree(ID_CODE, CURR_DB);
d_recread(&irec, CURR_DB);
d_findco(HAS_PUBLISHED, CURR_DB);
d_recread(AUTHOR, name, CURR_DB);
d_setfree(HAS_PUBLISHED, CURR_DB);
...
/* display author & info record contents */
}
else
{
d_freeall();
printf("info record not found\n");
}

Since the info record is accessed by id_code, d_keylock is used to lock only the key file
containing id_code keys. Function d_reclock could also be used to lock the data and key
files associated with info. In this case it would make no difference which one you used.
In general, however, d_reclock may lock key files that are not involved in the operation
(since it locks all key files and some may not be used). The d_setlock call locks the data
files containing the owner and member record types of set HAS_PUBLISHED, which in
this case is simply tims.d02 (see tims DDL specification in section 4.5.3, "Database
Design"). Notice that the file locks are freed as soon as they are no longer needed.
Data retrieval of Types 2 and 3 use the following procedure:
1.

Lock necessary record, set, or key types.

2.

Retrieve some predetermined amount of data. For example,


if browsing, this may be a screen full.

3.

Free locks.

4.

If browsing, display retrieved data.

5.

Go to step 1.

With interactive browsing, it is imperative that the locks be freed at Step 3. Otherwise
the duration of the locks would be dependent on the end-user, who typically would
press some key to view the next page of data.
In a report, the data is printed in Step 2, and Step 4 is eliminated. Although the locks
could remain in place for the duration of the report, this would prevent any updates to
the locked files until the report completes. This procedure allows updates by iteratively
freeing and re-locking the files during the report. The duration of the locks should
remain reasonably small (for example, access 10 to 20 records each time). The following

Multi-User Database Control

7-25

code will print a report of all info records contained in the tims database in id_code
order:
struct info irec;
int i;

/* info record variable */

for ( i = 0; ; )
{
if (i == 0)
d_reclock(INFO, "r", CURR_DB);
if (d_keynext(ID_CODE, CURR_DB) != S_OKAY)
{
d_recfree(INFO, CURR_DB);
break;
}
d_recread(&irec, CURR_DB);
printf("id_code: %-20s title: %s\n", irec.id_code, irec.info_title);
if (++i == 20)
{
d_recfree(INFO, CURR_DB);
i = 0;
}
}

The lock on the info record type will be freed every 20 records, allowing any queued
write-lock requests access to the locked files.
This procedure is slightly more complicated when a set is scanned instead of a key. The
problem occurs when an update is made to the set occurrence being scanned while the
set lock is freed. If the current member at the time of the d_setfree is disconnected, then
when the scan continues it will result in an error detected by RDM. If the set is
timestamped, its status can be checked after the set type is locked to determine whether
the set has been updated. If so, the operation can be terminated or restarted. This will
often be acceptable when there are many occurrences of the scanned set type. If it is a
system-owned set, however, there is only one occurrence, and if updates are common,
timestamping the set will not help. In this situation, use of a record lock on the current
member can be used to keep it from being disconnected. This is illustrated in the
following code, which produces a report of authors:

7-26

Centura RDM Users Guide

d_csmset(AUTHOR_LIST, NULL, CURR_DB);


for (i = -1; ;)
{
if (i <= 0)
{
d_setlock(AUTHOR_LIST, "r", CURR_DB)
if (i == 0)
d_rlbclr(CURR_DB);
}
if (d_findnm(AUTHOR_LIST, CURR_DB) != S_OKAY)
break;
d_crread(NAME, name, CURR_DB);
printf("author: %s\n", name);
if (++i == 20)
{
if (d_rlbset(CURR_DB) == S_LOCKED)
--i; /* dont stop on a locked record */
else
{
i = 0;
d_setfree(AUTHOR_LIST, CURR_DB);
}
}
}

The d_csmset call makes the current member of author_list null, so that the first call to
d_findnm will return the first member. Integer i starts at -1 to indicate that there is no
current record lock to be cleared. When 20 records have been scanned, d_rlbset is called
to set the record lock of the current record (which is also the current member). If the lock
bit is already set (perhaps someone is updating it), i is decremented so that the file lock is
not freed until the current member can be locked. In order to work correctly, an author
record should not be disconnected from the author_list set if its record lock bit is set.

7.6.6 Other Considerations


Use of static data can greatly improve database access performance. Static data can only
be changed when a database is opened in exclusive access mode. Thus, to access static
data in shared mode, no locks are required and full virtual memory caching of the static
data is performed. Things that only periodically change, such as keyed data validation
tables and general ledger accounts, are good candidates for static definition.
Operations that involve processing all occurrences of a particular record type, but do not
require that the records be ordered, should utilize the sequential record scan functions
d_recfrst and d_recnext. These functions do not require the file to be locked.

7.7

One User Mode

The multi-user version can be used in two different one user modes. As with earlier
versions, a database can be opened in exclusive access mode by passing open type x as

Multi-User Database Control

7-27

the second argument on the d_open call. A "one user-only mode" is selected by passing
open type o to d_open.
Exclusive-access mode requires the presence of the lock manager. If no other users have
opened the selected database, the lock manager will grant exclusive access to the
database and will prevent any other access to that database until it has been closed.
Exclusive access is intended for use in a multi-user environment to update static tables or
perform other critical update operations (for example, a year-end purge).
One user-only access does not require the presence of the lock manager. Even if the lock
manager is present, no interaction will occur. In one-user mode, it is the applications
responsibility to make sure that one and only one user is accessing that database at a
time. This mode is intended for use in a one user environment where: 1) the transaction
processing and recovery features in the multi-user version are needed in a one user
application, or 2) a one user version of a multi-user application is to be distributed and a
single copy of the source is desired.
A program running in either one user or exclusive mode does not need to place any locks
on any files. Any calls to the lock functions will immediately return (with no error).
However, if transaction processing and logging are used, file locking will be fully
operational, except that the runtime cache will never need to be cleared.

7-28

Centura RDM Users Guide

Chapter 8
Interactive Database Access Utility
(ida and wida)
Centura RDM includes two interactive database access utilities: the ida utility, for
working with RDM databases running on non-Windows platforms, and wida, for
working with RDM databases running on a Windows platform. This chapter provides
information about using the ida utility in section 8.1 and information about using the
wida utility in section 8.2.

8.1

Using ida

8.1.1 The ida Utility


The Interactive Database Access utility (ida) is a tool for manipulating RDM databases. It
is an easy-to-use, menu-driven utility that allows you to:

Maintain an existing database

Access data stored in the database

Test a database design

Create and modify data

Learn to use RDM

ida has been designed for application developers and database administrators and
therefore is not suitable for most non-technical users.

8.1.1.1

Accessing ida

To access the ida utility:


1.

Log into your UNIX user account.

2.

Use the cd command to change to the directory that contains the database dictionary
file (dbname.dbd) and the data and key files. (For further information, see the note
that follows this procedure.)

Interactive Database Access Utility (ida and wida)

8-1

3.

To access ida, enter the following:


ida <Enter>

(For information about special command line options for opening ida, see Chapter 2
of the RDM Reference Manual.)
4.

When the ida title page appears, press any key to bring up the ida main menu.

Note: Usually, ida is executed from within the file directory that contains the database
dictionary file (dbname.dbd) and the data and key files. However, you can use the
Parameters Dictionary_path and Parameters Files_path commands from the Utility
menu to locate the database files before opening the database. Alternatively, you can use
the environment variables DBDPATH and DBFPATH to tell ida where the database files
are located, or you can check the rdm.ini file. See section 5.2.2, "Operational
Environment," for a complete discussion of RDM path environment variables.

8.1.1.2

The ida Main Menu

Fig. 8-1 shows the first ida menu, referred to as the main menu. This menu provides
access to all other ida menus.
IDA - RDM Interactive Database Access Utility
Open Access Initialize Close Parameters Quit
Open a RDM database

Fig. 8-1. ida Main Menu


All ida menus use the top three lines of each screen. Each menu includes the following:
1st line

Menu title

2nd line

A list of available commands, one of which is highlighted

3rd line

A description of the highlighted command

You can see what a command does by moving the highlight to that command. When a
command is highlighted, the description of that command appears on the 3rd line.

Moving the Highlight on a Menu


To move the highlight on a menu:

To the right, press either the <Space> or the <Tab> key.

To the left, press the <Backspace> key.

To leave the ida utility, you use the Quit command from the main menu. For more
information about using the commands on the ida main menu, including the Quit
command, see section 8.1.2.

8-2

Centura RDM Users Guide

8.1.1.3

Using ida: Concepts and Procedures

This section describes the concepts and procedures you will need in order to use the ida
utility. These concepts and techniques include messages from ida, executing a command
from an ida menu (from the 2nd line of the screen), choosing an option from a numbered
list (displayed below the top three lines), moving the highlight on a numbered list,
opening a database, accessing a submenu, exiting a submenu, and selecting a record to
modify.

Messages from ida


The last two lines of an ida screen may display a message from ida. A message may tell
you that a command has been completed or that there has been an input error or
database error. Messages are displayed in reverse video and require pressing a key to
return to the menu.

Executing a Command from a Menu


To execute a command from a menu:

Highlight the command and press <Enter>.


or
Type the first letter of the command.

Executing a command from an ida menu invokes a submenu, a numbered list, an


ida/RDM function, or displays information.

Choosing an Option from a Numbered List


Following the execution of commands such as Open, Scan, and Find, a numbered list of
available databases, key fields, records, or sets will be displayed. The entry that was last
selected will be highlighted or, initially, the first entry will be highlighted.
Fig. 8-2 shows an example of a submenu that offers a numbered option list.
Scan and view records based on database address
Scan First Last Next Previous X_exit
Scan and view records based on database address
SELECT RECORD TYPE:
0.
1.
2.
3.
4.
5.
6.

Author
INFO
BORROWER
INFOTEXT
KEY_WORD
INTERSECT
SYSTEM

Fig. 8-2. Example Selection List


Interactive Database Access Utility (ida and wida)

8-3

To choose an option from a numbered list:

Type the number of the option and press <Enter>.


or
Using the procedure for moving the highlight on a numbered list (described below),
highlight the option and press <Enter>.

Moving the Highlight on a Numbered List


When moving the highlight on a numbered list, you use a different procedure than you
do when you move the highlight on a menu.
To move the highlight on a numbered list:

Down the list, type the <d> key.

Up the list, type the <u> key.

Selection lists that extend beyond a single screen will either scroll or redisplay,
depending on the position of the highlighted selection.

Opening a Database
Although you can access ida and view the main menu, there is little you can do until you
open a database. (You can execute the Parameters and Quit commands, but the Access,
Initialize, and Close commands will not work without an open database.) If you are
new to ida, you can use the sample tims database (provided with RDM) to learn any of
the procedures described in this chapter.
To open a database:
1.

From the ida main menu, highlight and execute the Open command.

2.

On the Open a RDM database submenu, execute the command for the type of user
access you want. (If you are just learning to use ida, use the One_User command.)

3.

From the Select Database list, choose the database you want to open. When you
choose a database, the list disappears.

8-4

Centura RDM Users Guide

Accessing a Submenu
To perform most database operations, you will use the Access command on the main
menu. Selecting the Access command displays the Database Access Commands
submenu shown in Fig. 8-3.
Database Access Commands
Record Set Currency Transaction

Lock

Free

Miscellaneous

X_exit

Fig. 8-3. Database Access Commands Menu

Exiting a Submenu
When you exit a submenu, you go back to the previous menu. There are two ways to exit
a submenu:

On the 2nd line of the submenu, highlight the X_exit command and press <Enter>.
or
Press the <Esc> key.

Selecting a Record
Using ida, you can find a record by using the Keyscan command to find a keyword, or
you can use the Recscan command to find a record by using a database address. The
following procedure uses the Recscan command.
To select a record using Recscan:
1.

Access the Database Access Commands submenu (shown in Fig. 8-3).

2.

From that menu, highlight and execute the Record command.


The Record Manipulation Functions submenu displays (shown in Fig. 8-4).
Record Manipulation Functions
Keyscan Get Enter Modify Delete
Scan and view records based on key

Recscan

X_exit

Fig. 8-4. Record Manipulation Functions Menu


3.

From the Record Manipulation Functions submenu, highlight and execute the
Recscan command.
The Scan and view records based on database address submenu appears (shown in
Fig. 8-2).

4.

From the Scan and view records based on database address submenu, highlight and
execute the Scan command.

Interactive Database Access Utility (ida and wida)

8-5

5.

A numbered list titled SELECT RECORD TYPE displays. Type the number of the
record type you want to select.
The Scan and View Records submenu appears and displays a record (shown in
Fig. 8-5).
Scan and View Records
Next First Select X_exit
Display next page of records
RECORD:

AUTHOR

Page:

RECORD CONTENTS
1.
{"Martin, James"}
2.
{"Myers, G."}
3.
{"Teorey T. & Fry, J."}

Fig. 8-5. Scan and View Records Menu


6.

Highlight and enter the Select command. The highlight will move to the numbered
list.

7.

Choose an option from the numbered list. The record will be displayed in the ida
screen.

8.1.2 Using the Main Menu Commands


This section describes the commands on the ida main menu, shown in Fig. 8-1. For
instructions on using the main menu to execute commands and access submenus, see
section 8.1.1.2.

Open command
The Open command opens a database. If another database is currently open, it will first
be closed. After selecting the Open command, you must choose the One_User, Shared,
or Exclusive access option from the displayed submenu. A list of the databases
contained in the current (or DBDPATH) directory is then displayed. From this list, you
can select the database to be opened.

Access command
The Access command brings up the Database Access Commands submenu, which
provides a set of functions and submenus for manipulating a particular database. This
menu, described in section 8.1.4, includes record functions, set functions, currency
functions, transaction functions, and lock functions. The Access command may only be
called after a database has been opened.

8-6

Centura RDM Users Guide

Initialize command
This command, which corresponds to the d_initialize function, initializes the opened
RDM database. This command should only be used after a database has been opened for
exclusive access. It will destroy the contents of the database.

Close command
The Close command closes an opened database.

Parameters command
Executing the Parameters command accesses the Set RDM Operational Parameters
submenu. It also displays the current ida operational settings.
The Set RDM Operational Parameters submenu is shown in Fig. 8-6, followed by a
description of each of its commands. These commands are used to change the RDM
settings and cannot be used when a database is open.
Set RDM Operational Parameters
Dictionary_path Files_path Userid Pages Max_files Logging Chain X_exit

Fig. 8-6. Set RDM Operational Parameters Submenu


Dictionary_path
Sets the DBDPATH environment variable, which identifies the full directory path to
the .dbd file for the database to be accessed.
Files_path
Sets the DBFPATH environment variable, which identifies the full directory path to
the data and key files for the databases to be accessed.
Userid
Sets the user ID. If you do not have the DBUSERID environment variable defined,
you must use this command before opening the database in shared mode through
ida.
Pages
Sets the number of ida/RDM virtual memory database pages.
Max_files
Sets the maximum number of database files that ida/RDM can have open at one
time. This number should not be greater than the operating system limit, less three.

Interactive Database Access Utility (ida and wida)

8-7

Logging
Toggles the transaction logging option. The screen will indicate whether transaction
logging is on (enabled) or off (disabled).
Chain
Controls the use of the delete chain for storing newly created records. The display
will show whether delete chain usage is on (enabled) or off (disabled).

Quit command
Closes any opened database and ends the ida session. The environment variables
DBDPATH and DBFPATH are restored to their initial values.

8.1.3 Entering and Modifying Records


To edit or modify a database record, you use the Display/Edit Record submenu. Section
8.1.3.1 provides information about accessing the Display/Edit Record submenu, and
section 8.1.3.2 provides information about using the commands in that submenu.
Section 8.1.3.3 gives instructions for editing a data field, and section 8.1.3.4 provides
information about idas editing modes and describes idas field editing commands.

8.1.3.1

Accessing the Display/Edit Record Submenu

To access the Display/Edit submenu, use the procedures in section 8.1.1.3 to:

Open the database you want.

Access the Database Access Commands submenu.

Select a record from the database. (Even if you want to enter a new record into the
database, you will need to select an existing record in order to access the
Display/Edit Record submenu.)

Exit (back out of) the Scan and view records submenu to the Record Manipulation
Functions submenu.

From the Record Manipulation Functions submenu (Fig. 8-4), select Modify to
access the Display/Edit Record submenu.

When the Display/Edit Record submenu is accessed, the record to be entered or


modified is displayed. Header information identifies the name of the record, its length in
bytes, the total number of data fields that can be edited, the current page number, and
total pages of data fields for the record.
Following the header is the first page of fields. The name of the data field appears on the
left, and its contents appear on the right. An example display is shown in Fig. 8-7 below.

8-8

Centura RDM Users Guide

Display/Edit Record
Mode: COMMAND
Edit Init Next Prev Write Store_key Delete_key Owner Connect X_Exit
Edit record
FIELD: ID_CODE
EDIT:>sw001<
ID_CODE
INFO_TITLE
PUBLISHER
PUB_DATE
INFO_TYPE

TYPE: unique key char

SIZE: 16

>sw001<
>Software Reliability<
>Wiley<
>1976<
>0<

Fig. 8-7. An Example Display/Edit Record Screen


A field can be edited if it is not the sub-field of a struct.

8.1.3.2

Using the Display/Edit Record Submenu Commands

Fig. 8-8 shows the Display/Edit Record submenu commands.


Display/Edit Record
Edit Init Next Prev Write Store_key Delete_key Owner Connect X_exit

Fig. 8-8. The Display/Edit Record Submenu


The first line is the menu title, and the second line lists the menu commands. This section
describes each of these commands.

Edit command
Selecting this command invokes field-level editing of the displayed record. The field edit
commands are listed in Table 8-2. The first field is highlighted and displayed in the data
field edit area. Field editing is initially entered in Command mode. For information
about ida editing modes, see section 8.1.3.4.

Init command
Use this command to initialize a new record. Selecting this command clears the
displayed record and enters field editing (see section 8.1.3.4) in Insert mode.

Next command
If the displayed record type consists of more data fields than can be shown on one screen,
this command can be used to display the next page of fields. Note that when entering
data, each page of data fields must be entered before the record is stored. Use the Next
command to access each page.

Interactive Database Access Utility (ida and wida)

8-9

Prev command
Selecting this command displays the previous page of data fields. Each page of data
fields must be entered before the record is stored.

Write command
Selecting this command writes the entered or modified record to the database. If the
automatic set connection feature is enabled, then the record will also be connected to
each set of which it is a member and for which a current owner has previously been set.

Store_key command
This command is used to store optional keys in the key file. A selection list of optional
keys will be displayed. Select the one to be stored for the current record.

Delete_key command
This command is used to delete optional keys from the key file. A selection list of
optional keys will be displayed. Select the one to be deleted from the current record.

Owner command
This command is used to assign, from the current record, the current owner of the
selected set. It is provided here to facilitate data entry.

Connect command
Selecting this command connects the current record to the set selected from the displayed
list of sets. It is provided here to facilitate data entry.

8.1.3.3

Editing a Data Field

In the Display/Edit Record submenu, selecting the Edit or the Init command allows you
to edit a record one data field at a time. ida editing incorporates many of the UNIX vi
editor commands (see Table 8-2).
All editing is performed in the editing field. Just above the editing field, the name of the
field being edited is displayed. If this field already contains data, the data will be
displayed in the editing field. Arrows on either end of the editing field point inward if
all the data in the field fits on the screen, or outward in the direction where more data
can be found. The entire contents of the field are accessed by horizontally scrolling or
repositioning through the field, using cursor-positioning field edit commands.
You can move to different data fields by using the up and down arrow keys, or by
pressing <Enter> or <Tab> to move to the next field. Pressing <Enter> or <Tab> on the
last field, or pressing <Esc> at any point, will return you to the Display/Edit Record
submenu.
8-10

Centura RDM Users Guide

The format of the displayed data is similar to the format that would be used if the data
were statically initialized in a C variable declaration. Each item of an arrayed (nonstring) data field is separated by commas and specified in its natural sequence. Structure
fields must be enclosed by braces ({ }). Character strings do not need to be delimited by
quotation marks except when included as part of a struct field. Sub-fields of struct fields
cannot be edited independently, and they are displayed only in the struct field. All C
escape codes (for example, \n, \f, \r, \ddd) can be entered into character fields.
One-dimensional character arrays are always treated as strings, terminated by a null byte
(\0). Multi-dimensional character arrays will display the entire length of the field.
Fields of type DB_ADDR are displayed and entered as [f :r], where f is the file number
and r is the record number. As an example, [3:11717] is the database address of the
record located at slot number 11717 in file number 3.
Repeating data items in arrayed data fields are indicated with a d* prefix, where d is the
decimal number of repetitions, and "*" indicates a repeating field.
The following table lists some examples of the above requirements.
Table 8-1. Example Data Field Contents
Field Spec

Display

char str[255];
int array[10];
struct {
char name[15];
int age;
} children[7];
DB_ADDR tree[2];
char lines[10][10]

>This needs to be scrolled to see th>


>12,15,312,74,5,5*0<
>{"Joelle",6},{"Rebecca",4},{"Scott",2},{"Katie",1},3*{"",0}<

8.1.3.4

>[2:1377],[2:1381]<
>line 1\n\0\0\0line 2\n\0\0\0line3\n\>

Using Edit Modes and Field Edit Commands

The current editing mode is shown in the upper right corner of the screen. There are
three modes:

Command mode indicates that the field edit commands are enabled. Table 8-2 lists
the edit commands available in Command mode.

Insert mode is initiated by the i, a, and A commands, allowing data to be inserted


into the field. Pressing <Esc> returns to Command mode.

Replace mode (R command) allows a type-over capability, where characters under


the cursor are replaced by those typed at the keyboard. Pressing <Esc> returns to
Command mode.

Interactive Database Access Utility (ida and wida)

8-11

Table 8-2. ida Field Edit Commands and Descriptions


Command Description
Insert characters before the cursor.
i
Append characters after the cursor.
a
A

Append characters to the end of the field.

Replace one character.

Replace (types over) existing characters.

Move the cursor one character to the left.

Move the cursor one character to the right.

Move the cursor forward one "small" word, delimited by anything other than
letters, digits, or underscores.

Move cursor forward one "big" word, delimited by spaces.

Move the cursor back one small word.

Move the cursor back one big word.

Position the cursor at the beginning of the field.

Position the cursor at the end of the field.

Delete the character beneath the cursor.

Undo the last change.

f<c>

Find the next occurrence of character <c> to the right.

F<c>

Find the next occurrence of character <c> to the left.

;
/<s>

Repeat the last f or F command.


Search for the first occurrence of the string <s>.

Repeat the last "/" command.

Delete between cursor position and the position determined from the cursor
position command that immediately follows. For example, "df." will delete
from the next occurrence of character <c> to the right from the cursor
through the next ".".

Additionally, some field edit commands can be preceded by a command repetition


number. These commands are: h, l, w, W, b, B, x, f, and F. For example typing 30h
moves the cursor 30 characters to the left.
Table 8-3 lists the function keys (if available on your keyboard), that have been assigned
the above edit commands.

8-12

Centura RDM Users Guide

Table 8-3. Function Key Table


Edit Command
H

Function Key
<Left Arrow>

<Right Arrow>

<Home>

<End>

<Ins>

<Del>

<F1>

<F2>

<F3>

<F4>

<F5>

<F6>

<F7>

<F8>

<F9>

<F10>

8.1.4 Using the Access Menu Commands


This section describes all of the database access commands that are available when you
select the Access command from the ida main menu, shown in Fig. 8-1. Selecting the
Access command from the ida main menu accesses the Database Access Commands
submenu, shown earlier in Fig. 8-3.
The commands on Database Access Commands submenu are described in the following
sections of this chapter:
Section 8.1.4.1

Record command

Section 8.1.4.2

Set command

Section 8.1.4.3

Currency command

Section 8.1.4.4

Transaction command

Section 8.1.4.5

Lock command

Section 8.1.4.6

Free command

Section 8.1.4.7

Miscellaneous command

Interactive Database Access Utility (ida and wida)

8-13

8.1.4.1

Using the Access Record Commands

The Record command, selected from the Database Access Commands submenu,
accesses the Record Manipulation Functions submenu, from which you can select a set
of additional commands and submenus for managing records. This submenu is shown
in Fig. 8-9, followed by a description of each of its commands and their submenus.
Record Manipulation Functions
Keyscan Get Enter Modify Delete

Recscan

X_exit

Fig. 8-9. Record Manipulation Functions Submenu

Keyscan command
Selecting the Keyscan command accesses the Scan and View Record Based on Key
submenu, from which you can choose how to locate a record based on a key. This
submenu is shown in Fig. 8-10, followed by a description of its commands.
Scan and View Record Based on Key
Scan Keyfind First Last Next Previous

X_exit

Fig. 8-10. Scan and View Record Based on Key Submenu


Scan
Scans records based on a key field. A list of all key field names will be displayed,
from which you should select the field to be scanned. You will then be prompted to
enter the value of the key where the scan will begin.
The records located by the scan will be paged and displayed in a horizontal packed
format. This is similar to the format that would result if the struct variable
corresponding to the record were statically initialized in a C program. That is, it
would be enclosed in braces ({ }), with each sub-field grouping separated by commas.
For more information about the display of various RDM data types, see section
8.1.3.3.

8-14

Centura RDM Users Guide

Fig. 8-11 shows a sample record scan display.


Record: EMPLOYEE

Key: EMP_ID

Page: 1

ENTRY RECORD CONTENTS


1.
{"7901",{"Pfeil","Carl","L."},"MGR1"}
2.
{"7902",{"Rogers","Jim",""}, "MGR1"}
3.
{"7903",{"Fleagle","Jenifer","C."},"MGR2"}
4.
{"7904",{"Smith","Stephen","P."},"MGR1"}
5.
{"7906",{"Warren","Wayne","L."},"MGR1"}
6.
{"7907",{"Merilatt","Randall","L."},"MGR1"}
7.
{"8001",{"Bryant","John","W."},"MGR2"}
8.
{"8002",{"Willis","Kirt","L."},"MGR2"}
9.
{"8003",{"Mureen","Chris",""}, ENGR}
10.
{"8101",{"Ritchie","Gail","A."}, ENGR}
11.
{"8102",{"Rodovsky","Eliska",""}, ENGR}
12.
{"8102",{"Marsh","Kyle","G."}, ENGR}
13.
{"8103",{"Carlson","Bob","C."}, MGR1}
14.
{"8104",{"Kent","Sidney",""}, ENGR}

Fig. 8-11. A Sample Keyscan/Scan Display


Keyfind
Quickly finds and displays a record. When you select a key field from the displayed
list and enter a value, this command displays either the record associated with the
specified key value, or if the key is not found, the record associated with the next
key. Compound key and struct fields must be enclosed by braces ({ }). Character
strings do not need to be delimited by quotation marks except when included as part
of a struct field.
First
Finds and displays the record associated with the first key in the key file.
Last
Finds and displays the record associated with the last key in the key file.
Next
Finds and displays the record associated with the next key in the key file. If a Next
command causes a "no more keys" message at the end of a file, a subsequent Next
command will return the first key.
Previous
Finds and displays the record associated with the previous key in the key file. If a
Previous command causes a "no more keys" message at the end of a file, the next
Previous command will return the last key.

Interactive Database Access Utility (ida and wida)

8-15

Get command
Displays the record located at a specified database address. When prompted for the
database address, enter it as:
enter database address: [f:r]

where f is the file number and r is the record number. Refer to section 14.2.2, "Data File
Organization," for a description of database addresses.

Enter command
Enters new records into the database. From the displayed list, select the record type to be
entered. The Display/Edit Record submenu is then invoked. Section 8.1.3.2 shows the
Display/Edit Record submenu and describes its functions in detail.

Modify command
Invokes the Display/Edit Record submenu, which provides a set of tools for modifying
the current record. For detailed information about the Display/Edit Record submenu,
see section 8.1.3.2.

Delete command
Deletes the current record from the database. The record must have been previously
removed from all sets of which it was an owner or a member.

Recscan command
Invokes the Scan and View Record Based on Database Address command submenu.
The commands in this submenu use the d_recfrst, d_recnext, d_reclast and d_recprev
functions to locate the records, instead of the key traversal functions.
Scan and View Record Based on Database Address
Scan First Last Next Previous X_exit

Fig. 8-12. Scan and View Record Based on Database Address Submenu
Scan
Scans records based on their database address (their order is determined by their
physical appearance in a data file). A list of all record type names will be displayed,
from which you should select the type to be scanned.
The records located by the scan will be paged and displayed in the same horizontal
packed format as the Keyscan command. For more information about the display of
various RDM data types, see section 8.1.3.3.

8-16

Centura RDM Users Guide

First
Finds and displays the first record of the selected type in the data file.
Last
Finds and displays the last record of the selected type in the data file.
Next
Finds and displays the next record in the data file. When it reaches the end of the
file, it displays a "no more records" message.
Previous
Finds and displays the previous record in the data file. When it reaches the top of the
file, it displays a "no more records" message.

8.1.4.2

Using the Access Set Commands

Selecting the Set command from the Database Access Commands submenu accesses the
Set Manipulation Functions submenu, which provides a set of tools for managing sets.
This submenu is shown in Fig. 8-13, followed by a description of its functions.
Set Manipulation Functions
Scan Owner First Next Last Prev Connect Discon Total X_exit

Fig. 8-13. Set Manipulation Functions Submenu

Scan command
Scans and displays all member records connected to the current owner of a set. The set
to be scanned is selected from the displayed list of set names.
The records located by the scan will be paged and displayed in a horizontal packed
format. This is similar to the format that would result if the struct variable
corresponding to the record were statically initialized in a C program. That is, it would
be enclosed in braces ({ }), with each sub-field grouping separated by commas. For more
information about the display of various RDM data types, see section 8.1.3.3.

Owner command
Finds the owner of the current record, through the set selected from the displayed list of
set names. Note that this function serves a different purpose than the Owner function
under the Display/Edit Record submenu.

First command
Finds the first member connected to the current owner of the set selected from the
displayed list of set names.

Interactive Database Access Utility (ida and wida)

8-17

Next command
Finds the next member of a set. The first time (or after a "no more records" message),
Next displays the first member of the set.

Last command
Finds the last member connected to the current owner of the set selected from the
displayed list of set names.

Prev command
Finds the previous member of a set. The first time (or after a "no more records" message),
Prev displays the last member of the set. A Last or Next command must have preceded
the call to Prev.

Connect command
Connects the current record to the current owner of the set selected from the displayed
list of set names.

Discon command
Disconnects the current record from the set selected from the displayed list of set names.

Total command
Displays a count of the members connected to the current owner of the set selected from
the displayed list of set names.

8.1.4.3

Using the Access Currency Commands

The Currency command, selected from the Database Access Commands submenu,
accesses the Currency Table Manipulation Functions submenu (shown in Fig. 8-14 and
followed by a description of its functions).
Currency Table Manipulation Functions
Owner Member Record Auto_set Display

Timestamp

X_exit

Fig. 8-14. Currency Table Manipulation Functions Submenu

Owner command
Sets the current owner of the set selected from the displayed list of set names. This
function then invokes the Change Current Owner of Set submenu, from which you
select the record you wish to be made current. The submenu is shown in Fig. 8-15,
followed by a description of its functions.

8-18

Centura RDM Users Guide

Change Current Owner of Set


Record Owner Member Change

X_exit

Fig. 8-15. Change Current Owner of Set Submenu


Record
Changes the current owner of the selected set to the current record.
Owner
Changes the current owner of the previously selected set to the current owner of the
set selected from the displayed list of sets.
Member
Changes the current owner of the previously selected set to the current member of
the set selected from the displayed list of sets.
Change
Changes the current owner of the selected set to the database address entered in
response to the prompt:
enter database address: [f:r]

where f is the file number and r is the record number. Refer to section 14.2.2, "Data
File Organization," for a description of database addresses.

Member command
Sets the current member of the set selected from the displayed list of set names. It then
invokes the Change Current Member of Set submenu, shown in Fig. 8-16, to determine
the record to be made current.
Change Current Member of Set
Record Owner Member Change

X_exit

Fig. 8-16. Change Current Member of Set Submenu


Record
Changes the current member of the selected set to the current record.
Owner
Changes the current member of the previously selected set to the current owner of
the set selected from the displayed list of sets.
Member
Changes the current member of the previously selected set to the current member of
the set selected from the displayed list of sets.

Interactive Database Access Utility (ida and wida)

8-19

Change
Changes the current member of the selected set to the database address entered in
response to the prompt:
enter database address: [f :r]

where f is the file number and r is the record number.

Record command
Changes the current record. This selection invokes the Change Current Record
submenu, shown in Fig. 8-17, to determine the record to be made current.
Change Current Record
Owner Member Change

X_exit

Fig. 8-17. Change Current Record Submenu


Owner
Changes the current record to the current owner of the set selected from the
displayed list of set names.
Member
Changes the current record to the current member of the set selected from the
displayed list of set names.
Change
Changes the current record to the database address entered in response to the
prompt:
enter database address: [f :r]

where f is the file number and r is the record number.

Auto_set command
Toggles the automatic set connection flag within ida. When turned on, this flag causes
newly entered records to be connected automatically to the current owners of the sets for
which they are members.

Display command
Displays the currency tables, showing the record type and database addresses of the
current record and, for each set, the current owner and current member of that set. It also
indicates whether automatic set connection is enabled.

8-20

Centura RDM Users Guide

Timestamp command
Invokes the Timestamp Currency Functions submenu, shown in Fig. 8-18, for testing
timestamp statuses in the currency table.
Timestamp Currency Functions
Record Owner Member Set X_exit

Fig. 8-18. Timestamp Currency Functions Submenu


Record
Issues a message indicating the timestamp status of the current record.
Owner
Issues a message indicating the timestamp status of the current owner. Select the set
whose owners timestamp is to be checked from the displayed selection list.
Member
Issues a message indicating the timestamp status of the current member. Select the
set whose members timestamp is to be checked from the displayed selection list.
Set
Issues a message indicating the timestamp status of a set. Select the set whose
timestamp is to be checked from the displayed selection list.

8.1.4.4

Using the Access Transaction Commands

The Transaction command, selected from the Database Access Commands submenu,
controls the initiation and termination of transactions. It invokes the Transaction
Processing Functions submenu, shown below, from which a transaction can be started
(Begin), ended (End), or aborted (Abort).
Transaction Processing Functions
Begin End Abort X_exit

Fig. 8-19. Transaction Processing Functions Submenu

Begin command
Starts a transaction. You are prompted to enter the transaction identifier.

End command
Stops a transaction. It applies to the database files all changes made since the beginning
of the transaction.

Interactive Database Access Utility (ida and wida)

8-21

Abort command
Aborts the current transaction. It discards all changes made since the beginning of the
transaction.

8.1.4.5

Using the Access Lock Commands

The Lock command, selected from the Database Access Commands submenu, is used to
lock set types, record types, and key types, as well as the current record. It invokes the
Multiuser Set/Record Lock Functions submenu, shown in Fig. 8-20, from which you
select either record, set, key, or current locks. You then select the record, set, or key to be
locked from the displayed list of record, set, or key names defined in the database.
Multiuser Set/Record Lock Functions
Record Set Key Current Timeout

Display

X_exit

Fig. 8-20. Timestamp Currency Functions Submenu

Record command
Places a lock on the record type selected from the displayed list of records. A selection
list of lock types will be displayed, from which you should select the desired lock type.
This command can only be executed when the database is opened for shared access.

Set command
Places a lock on the set type selected from the displayed list of sets. A selection list of
lock types will be displayed, from which you should select the desired lock type. This
command can only be executed when the database is opened for shared access.

Key command
Places a lock on the key type selected from the displayed list of keys. A selection list of
lock types will be displayed, from which you should select the desired lock type. This
command can only be executed when the database is opened for shared access.

Current command
Sets the record lock bit of the current record.

Timeout command
Displays current timeout value in seconds and prompts user for the new value.

8-22

Centura RDM Users Guide

Display command
Displays the lock status for each set, record, and key type, indicating whether it is readlocked, read-locked with keep, write-locked, exclusively locked, or free. This command
can only be executed when the database is opened for shared access.

8.1.4.6

Using the Access Free Commands

The Free command, selected from the Database Access Commands submenu, is used to
free locked record, set, and key types, or to clear the current records lock bit. Free
invokes the Multi-user Set/Record Free Locks Functions submenu, shown in Fig. 8-21.
From here, you select which locks you want freed. If you are freeing a set, record, or key
lock, select the correct one from the displayed list of names defined in the database.
Multi-user Set/Record Free Locks Functions
Record Set Key All Current X_exit

Fig. 8-21. Multi-user Set/Record Free Locks Functions Submenu

Record command
Frees the lock for the record type selected from the displayed list of record types. This
command can only be executed when the database is opened for shared access and when
no transaction is active.

Set command
Frees the lock for the set type selected from the displayed list of set types. This command
can only be executed when the database is opened for shared access and when no
transaction is active.

Key command
Frees the lock for the key type selected from the displayed list of key types. This
command can only be executed when the database is opened for shared access and when
no transaction is active.

All command
Frees all set, record and key locks. It can only be executed when the database is opened
for shared access and when no transaction is active.

Current command
Clears the lock bit of the current record.

Interactive Database Access Utility (ida and wida)

8-23

8.1.4.7

Using the Access Miscellaneous Commands

The Miscellaneous command, selected from the Database Access Commands submenu,
invokes the Miscellaneous ida Functions submenu, shown in Fig. 8-22, for displaying
current database file and lock statuses.
Miscellaneous ida Functions
Files Locks X_exit

Fig. 8-22. Miscellaneous ida Functions Submenu

Files command
Displays status information pertaining to the database and all database files, as shown in
Table 8-4.

Locks command
Displays the lock status for each set, record, and key type, indicating whether it is readlocked, read-locked with keep, write-locked, exclusively locked, or free. This command
can only be executed when the database is opened for shared access.
Table 8-4. File Status Information (From the Miscellaneous Files Command)
Item Name
Database name

Description
The name of the database currently being accessed.

Access type

Exclusive, shared, or one-user access.

Transaction

The identifier of the active transaction.

FILE

The file number of the listed file.

SLOTS

The total number of allocated file slots (if data file) or pages (if key
file).

TYPE

The file type: either "data" or "key".

STATUS

File status: "opened" or "closed", "locked" or "free".

RW

The total number of read locks on the file within this application. A
file may be locked from different set/record locks. This value gives
the current total. It is displayed only when the database is opened
for shared access. A value of -1 indicates that the file is writelocked.

EX

The total number of exclusive locks on the file. A file may be


exclusively locked from different set/record locks. This value gives
the current total. It is displayed only when the database is opened
for shared access.

NAME

The name of the file including any current path names.

8-24

Centura RDM Users Guide

8.1.5 Cross-Referencing RDM Functions to ida Commands


The ida utility allows you to use a menu-driven interface instead of entering RDM
functions from the command line. Table 8-5 lists RDM functions and the corresponding
sequence of ida menu commands that produce the same result. This list is helpful when
learning how to use the various RDM functions. For complete information on the
operation of a particular RDM C function, refer to the detailed function descriptions in
the RDM Reference Manual.
In the following list, functions are grouped by type of operation. The function name is in
the left column, and the ida menu command sequence is in the right column.
Table 8-5. RDM Functions and Corresponding ida Command Sequences
Function

ida Menu Command Sequence


Database Administration Functions

d_setpages

Parameters Pages

d_setfiles

Parameters Max_files

d_dbdpath

Parameters Dictionary_path

d_dbfpath

Parameters Files_path

d_dbuserid

Parameters Userid

d_on_opt

Parameters Logging/Chain

d_off_opt

Parameters Logging/Chain

d_open

Open

d_close

Close

d_initialize

Initialize

d_initfile

no corresponding ida sequence

d_destroy

no corresponding ida sequence


Record Manipulation Functions

d_recread

Access Record Modify

d_recwrite

Access Record Modify Write

d_fillnew

Access Record Enter Write

d_makenew

no corresponding ida sequence

d_setkey

no corresponding ida sequence

d_delete

Access Record Delete

d_keystore

Access Record Enter/Modify Store_key

d_keydel

Access Record Enter/Modify Delete_key

Interactive Database Access Utility (ida and wida)

8-25

Table 8-5. RDM Functions and Corresponding ida Command Sequences (continued)
Function

ida Menu Command Sequence


Set Manipulation Functions

d_connect

Access Set Connect

d_discon

Access Set Discon

d_members

Access Set Total

d_isowner

no corresponding ida sequence

d_ismember

no corresponding ida sequence


Set Navigation Functions

d_findco

Access Set Owner

d_findfm

Access Set First

d_findlm

Access Set Last

d_findnm

Access Set Next

d_findpm

Access Set Prev


Key Field Access Functions

d_keyfrst

no corresponding ida sequence

d_keylast

no corresponding ida sequence

d_keyfind

Access Record Find

d_keynext

Access Record Next

d_keyprev

Access Record Prev

d_keyread

no corresponding ida sequence


Multi-User Database Control Functions

d_trbegin

Access Transaction Begin

d_trend

Access Transaction End

d_trabort

Access Transaction Abort

d_reclock

Access Lock Record

d_recfree

Access Free Record

d_setlock

Access Lock Set

d_setfree

Access Free Set

d_keylock

Access Lock Key

d_keyfree

Access Free Key

d_freeall

Access Free All

8-26

Centura RDM Users Guide

Table 8-5. RDM Functions and Corresponding ida Command Sequences (continued)
Function

ida Menu Command Sequence

d_rlbset

Access Lock Current

d_rlbclr

Access Free Current

d_timeout

Access Lock Timeout


Currency Control Functions

d_setro

Access Currency Record Owner

d_setrm

Access Currency Record Member

d_setor

Access Currency Owner Record

d_setom

Access Currency Owner Member

d_setoo

Access Currency Owner Owner

d_setmr

Access Currency Member Record

d_setmo

Access Currency Member Owner

d_setmm

Access Currency Member Member

d_crget

no corresponding ida sequence

d_crset

Access Currency Record Change

d_csmget

no corresponding ida sequence

d_csmset

Access Currency Member Change

d_csoget

no corresponding ida sequence

d_csoset

Access Currency Owner Change


Timestamp Functions

d_crstat

Access Currency Timestamp Record

d_costat

Access Currency Timestamp Owner

d_cmstat

Access Currency Timestamp Member

d_csstat

Access Currency Timestamp Set


Miscellaneous Control Functions

d_crtype

no corresponding ida sequence

d_cmtype

no corresponding ida sequence

d_cotype

no corresponding ida sequence

Interactive Database Access Utility (ida and wida)

8-27

8.2

Using wida

8.2.1 About the wida Utility


The Windows Interactive Database Access utility (wida) is a tool for manipulating RDM
databases. For those running RDM on a Windows platform, wida provides a graphical
user interface that allows you to:

Maintain an existing database

Access data stored in the database

Create and modify data

You can open more than one database in a wida window, and you may run more than
one wida window concurrently.

8.2.1.1

About Common Dialog Boxes

Many of the menu items call one or both of two common dialog boxes: the Records
dialog box and the Current Record dialog box. Note that when the Records dialog box
appears, the dialog box is not simply "Records". The name of the record type is included
as a prefix, and the scan type is included as a suffix. For example, if you are performing a
set scan on the AUTHOR record type, the title of the Records dialog box is this:
AUTHOR Records Set Scan
In this book, we will simply refer to this dialog box as the Records dialog box.

Records Dialog Box


The Records dialog box is used to display lists of records. It is used for key scans, record
scans, and set scans. To scroll up or down a screen within the list of records, click the
Page Up or Page Down button, respectively. To display a particular record, select a
record, and then click OK. That record becomes the current record, and it is displayed in
the Current Record dialog box. To exit the Records dialog box, click Cancel.

Current Record Dialog Box


The Current Record dialog box shows the field values for the current record. Each field
is displayed on a separate line. If there are more fields in the record than lines in the list
box, you can reach the additional fields by scrolling the list box. An example dialog box
is shown below.

8-28

Centura RDM Users Guide

Fig. 8-23. The Current Record dialog box


The Current Record dialog box has the following buttons:

The Edit button displays a dialog box that allows you to modify a field value within
the record. You first must select the field to modify before clicking this button. The
dialog box for modifying field values has these buttons:

The First button displays in the dialog box the first field in the record.

The Last button displays in the dialog box the last field in the record.

The Next button displays in the dialog box the next field in the record. If the
dialog box currently shows the last field in the record, clicking the button causes
it to display the first field in the record.

The Prev button displays in the dialog box the previous field in the record. If the
dialog box currently shows the first field in the record, clicking the button causes
it to display the last field in the record.

The OK button approves the field changes in this record. It exits this dialog box
and returns you to the Current Record dialog box. To make the changes to this
record permanent, you still will need to use the Current Record dialog box to
store the record.

The Cancel button invalidates the field changes in this record and returns you to
the Current Record dialog box.

The Delete button deletes the current record. A dialog box appears to ask whether
you want to proceed before the program deletes the record.

The Store button writes the record to the database. If it is a new record, the record is
added; if it is an existing record, the record is updated.

Interactive Database Access Utility (ida and wida)

8-29

The First button displays the first record in the current access method. If the dialog
box is displayed from a key operation, the First button displays the first record with
that key. If the dialog is reached by a set operation, the First button displays the first
member of the set. If the current record was obtained though a record scan, the First
button displays the first record of the current records type.

The Last button is the same as First button except that it displays the last record of a
requested operation.

The Next button displays the next record of a requested operation. If the current
record is the last record of that operation, the dialog box displays the first record of
that operation.

The Prev button displays the previous record of a requested operation. If the current
record is the first record of that operation, the dialog box displays the last record of
that operation.

The OK button clears the dialog box from the screen. If the record has been modified
or added without being stored first, a dialog box appears to ask whether you want to
store the record.

8.2.2 Using the File Menu Commands


This section describes the commands that are available in the File menu. To be able to
use this menu, you must have open one or more databases. The File menu is shown
below.

Fig. 8-24. The File Menu

8-30

Centura RDM Users Guide

Open Database
This command opens a database for manipulation. It only opens a database if no other
databases are open. If other databases are currently open, it displays a dialog box that
asks whether you want the program to close those databases automatically. If you
decline, the program stops without letting you open a database. Otherwise, the program
displays the Open dialog box, in which you specify the database to open and the
conditions under which the database is opened.
Note: To open a database without having to close other open databases, use the
Incremental Open command.
The Open dialog box contains the following:

Lists of files and directories for selecting the database (.dbd file) to open

Option buttons for opening the database in Shared, Exclusive, or One User mode

A check box to open the database in read-only mode

A text box for entering the database user identifier (Dbuserid) for this task, which is
required if you are opening the database in Shared or Exclusive mode

Close Database
This command closes all open databases. To close a single database while leaving other
databases open, use the Incremental Close command.

Incremental Open
This command opens a database without closing other open databases. It displays the
same Open dialog box as the Open Database command. The database that you open
becomes the current database.

Incremental Close
This command closes a database without closing other open databases. It displays a
dialog box in which you select the database to close. After you close that database, the
program displays a message that shows what the current database is.

Database Number
This command allows you to denote another open database the current database. It
displays a dialog box in which you select the database to be current.

Initialize Database
This command initializes or re-initializes the data and key files in an open database. The
command displays a dialog box in which you select the database. After you make your

Interactive Database Access Utility (ida and wida)

8-31

selection, you must confirm your action in a separate dialog box, because any stored data
in that database is deleted by the Initialize Database command.

Destroy Database
This command deletes the data and key files in an open database, but retains its database
dictionary file. The command displays a dialog box in which you select the database.

Quit
This command closes any open databases and then closes the wida window.

8.2.3 Using the Key Menu Commands


This section describes the commands that are available in the Key menu. To be able to
use this menu, you must have open one or more databases. The Key menu is shown
below:

Fig. 8-25. The Key Menu

Scan
This command allows you to view or edit a record from a list of records that are sorted
on a key. Choosing this command displays a dialog box with a list of key names. Select
the desired key, and click OK. A list of records, which is sorted by that key, is displayed
in the Records dialog box. Select a record, and click OK. The record is then displayed in
the Current Record dialog box.

8-32

Centura RDM Users Guide

First
This command shows the record that contains the first value (in sorted order) of a
selected key. Choosing this command displays a dialog box with a list of key names.
Select a key, and click OK. The program then displays the record that is first when the
records are sorted by the selected key.

Last
This command shows the record that contains the last value (in sorted order) of a
selected key. Choosing this command displays a dialog box with a list of key names.
Select a key, and click OK. The program then displays the record that is last when the
records are sorted by the selected key.

Next
This command shows the record that contains the next value (in sorted order) of a
selected key. Choosing this command displays a dialog box with a list of key names.
Select the desired key, and click OK. The next record in key order is displayed in the
Current Record dialog box. However, if the current record for the key is already the last
record for that key, only a message box with this information appears.

Previous
This command shows the record that contains the previous value (in sorted order) of a
selected key. Choosing this command displays a dialog box with a list of key names.
Select the desired key, and click OK. The previous record in key order is displayed in the
Current Record dialog box. However, if the current record for the key is already the first
record for that key, only a message box with this information appears.

Delete
This command deletes an optional key field in the current record. Choosing this
command displays a list of keys for that record. To delete a key, select it from the list,
and click OK. If the selected key is not an optional key, a message box appears with that
information.

Exist
This command tests whether an optional key field in the current record has been stored.
Choosing this command displays a list of keys for that record. To test a key, select it
from the list, and click OK. If the selected key is not an optional key, a message box
appears with that information.

Interactive Database Access Utility (ida and wida)

8-33

Store
This command stores an optional key field in the current record. Choosing this
command displays a list of keys for that record. To store a key, select it from the list, and
click OK. If the selected key is not an optional key, a message box appears with that
information.

Keybuild
This command rebuilds the key files in the current database. It corresponds to the
keybuild utility, which re-creates all key files in the current database by using the field
values that are stored in the data files.

8.2.4 Using the Set Menu Commands


This section describes the commands that are available in the Set menu. To be able to use
this menu, you must have open one or more databases. The Set menu is shown below.

Fig. 8-26. The Set Menu

Scan
This commands allows you to view or modify a member record in a set. Choosing this
command displays a dialog box with a list of set names. Select the set to scan, and click
the OK button. The set is scanned, and the records then display in the Records dialog
box. Select a record, and click OK. The record is displayed in the Current Record dialog
box.

8-34

Centura RDM Users Guide

First
This command shows the first member record in a set. Choosing this command displays
a dialog box with a list of set names. Select the set to scan, and click the OK button. The
first member of the set displays in the Current Record dialog box.

Last
This command shows the last member record in a set. Choosing this command displays
a dialog box with a list of set names. Select the set to scan, and click the OK button. The
last member of the set displays in the Current Record dialog box.

Next
This command shows the next member record in a set. Choosing this command displays
a dialog box with a list of set names. Select the set to scan, and click the OK button. The
next member of the set displays in the Current Record dialog box. However, if the
current set member is already the last set member, the program simply displays a dialog
box with this message.

Previous
This command shows the previous member record in a set. Choosing this command
displays a dialog box with a list of set names. Select the set to scan, and click the OK
button. The previous member of the set displays in the Current Record dialog box.
However, if the current set member is already the first set member, the program simply
displays a dialog box with this message.

Owner
This command finds the current owner of the current record in a set. Choosing this
command displays a dialog box with a list of set names. Select the set to scan, and click
the OK button. The sets owner record (stored as the current record) then displays in the
Current Record dialog box.

Connect
This command connects the current record to the current owner of a set. Choosing this
command displays a dialog box with a list of set names. Select the set to scan, and click
the OK button. The current record is connected to the set. If it is not a valid member of
the set, a message box appears with that information.

Disconnect
This command disconnects the current record from a set. Choosing this command
displays a dialog box with a list of set names. Select the set, and click OK. After

Interactive Database Access Utility (ida and wida)

8-35

selection, the current record is disconnected from the set. If the current record is not
connected to the set, then a message box appears with that information.

Members
This command displays the number of members that are in a set. Choosing this
command displays a dialog box with a list of set names. Select the set to scan, and click
the OK button. The total number of members in the set are displayed. This is obtained
with a d_members call.

Is Owner?
This command tests whether the current record is the owner of member records.
Choosing this command displays a dialog box with a list of set names. Select the set to
scan and click the OK button. A d_isowner function call is made to determine if the
current record has member records attached to it. A message box displays with the result
of the function call. If the current record is not of the same record type as the record type
of the set owner, a message box appears with this information.

8.2.5 Using the Record Menu Commands


This section describes the commands that are available in the Record menu. To be able to
use this menu, you must have open one or more databases. The Record menu is shown
below.

Fig. 8-27. The Record Menu

Scan
This command is used to select a record for viewing. Choosing this command displays a
list of record types. Select the record type that you want to see, and click the OK button.
8-36

Centura RDM Users Guide

The records of that record type are displayed in the Records dialog box. Select a record
to display, and click OK. That record becomes the current record, and field values for
that record are shown in the Current Record dialog box.

First
This command is used to view the first record of a selected record type. Choosing this
command displays a list of record types. Select the desired record type, and click OK.
The first record of that record type becomes the current record, and it is displayed in the
Current Record dialog box.

Last
This command is used to view the last record of a selected record type. Choosing this
command displays a list of record types. Select the desired record type, and click OK.
The last record of that record type becomes the current record, and it is displayed in the
Current Record dialog box.

Next
This command is used to view the next record of a selected record type. Choosing this
command displays a list of record types. Select the desired record type, and click OK.
The next record of that record type becomes the current record, and it is displayed in the
Current Record dialog box. However, if the current record of that record type is its last
record, only a message box with this information appears.

Previous
This command is used to view the previous record of a selected record type. Choosing
this command displays a list of record types. Select the desired record type, and click
OK. The previous record of that record type becomes the current record, and it is
displayed in the Current Record dialog box. However, if the current record of that
record type is its first record, only a message box with this information appears.

Enter new record


This command adds a new record of a selected record type. Choosing this command
displays a list of record types. Select the desired record, and click OK. The Current
Record dialog box is displayed for that record type with an empty record. After entering
any field values, click the Store button to write the record to the database. This record
becomes the current record.

Modify
This command modifies the current record. Choosing this command displays the current
record in the Current Record dialog box. For each field value that you want to change,

Interactive Database Access Utility (ida and wida)

8-37

select the field, and click Edit to display the dialog box in which you can specify another
value. After making the desired changes, click the Store button in the Current Record
dialog box to write the record to the database.

Delete
This command deletes the current record from the database. Choosing this command
requires you to confirm the action before the program actually deletes the record. If the
current record is currently the owner or a member of any sets, the deletion does not
occur, and an error message appears. To delete the record, you must use the Disconnect
& Delete command, which automatically disconnects the current record from any sets
before deleting the record.

Disconnect & Delete


This command deletes the current record from the database even if the record is an
owner or a member of a database. Choosing this command requires you to confirm the
action before the program actually performs the command. The command disconnects
the current record from any sets in which it is the owner or a member, to avoid problems
when the record is deleted.

8.2.6 Using the Currency Menu Commands


This section describes the commands that are available in the Currency menu. To be able
to use this menu, you must have open one or more databases. The Currency menu is
shown below.

Fig. 8-28. The Currency Menu

8-38

Centura RDM Users Guide

Set Current Owner


This command is used to specify the owner of a set. It displays a dialog box with 1) a list
box to select the set; 2) radio buttons to select the currency origination: the current record,
the current owner of another set, the current member of another set, or a database
address; and 3) a list box to select the set from which the current owner or member is
taken. If the current owner is chosen from the owner or member of another set, select the
appropriate set from the list box on the right. If the currency is fixed to a database
address, type the desired database address in the text box.

Set Current Member


This command is used to specify the member of a set. It displays a dialog box with 1) a
list box to select the set; 2) radio buttons to select the currency origination: the current
record, the current owner of another set, the current member of another set, or a database
address; and 3) a list box to select the set from which the current owner or member is
taken. If the current member is chosen from the owner or member of another set, select
the appropriate set from the list box on the right. If the currency is fixed to a database
address, type the desired database address in the text box.

Set Current Record


This command is used to specify the current record. It displays radio buttons to select
the currency origination: the current owner of another set, the current member of another
set, or a database address. If the current record is chosen from the owner or member of
another set, select the appropriate set from the list box. If the currency is fixed to a
database address, type the desired database address value in the text box.

Display Timestamp Status


This command displays the timestamp status of records and sets if the schema of the
current database contains timestamp statements. The command displays a dialog box
that contains radio buttons to select the timestamp information for the current record, the
current owner, or the current member. If a current owner or member is used, you also
must select the name of a set from the list box. To display the timestamp status for the
selected item, click OK; the status (either "Not Changed" or "Changed") is shown in the
text box.
You can check the timestamp status of different items repeatedly before exiting the
dialog box. To exit the dialog box, click Cancel.

Display Currency Tables


This command displays the currency tables in a list box. If the tables are longer than the
box can display, then the list box can be scrolled.

Interactive Database Access Utility (ida and wida)

8-39

8.2.7 Using the Transactions Menu Commands


This section describes the commands that are available in the Transactions menu. To be
able to use this menu, you must have open one or more databases. The Transactions
menu is shown below.

Fig. 8-29. The Transactions Menu

Begin
Choosing this command displays a dialog box with an edit box to name the transaction.
It calls d_trbegin to start a transaction.

End
Choosing this command calls d_trend to end a transaction.

Abort
Choosing this command calls d_trabort to abort a transaction.

8.2.8 Using the Locks Menu Commands


This section describes the commands that are available in the Locks menu. To be able to
use this menu, you must have open one or more databases. The Locks menu is shown
below.

8-40

Centura RDM Users Guide

Fig. 8-30. The Locks Menu

Lock Types
Choosing Lock Types from the Locks menu displays the Lock Record, Set or Key Type
dialog box. In this dialog box, a list box initially shows the record types in the current
database and indicates whether the lock status is f for free, r for read lock, w for write
lock, x for exclusive lock, or k for keep lock.
The option buttons in the Lock section of the dialog box control whether the list box
displays record locks, set locks, or key locks. To display a different type, click the option
button you want.

Free Types
Choosing Free Types from the Locks menu displays the Free Record, Set or Key Type
dialog box, shown below. In this dialog box, a list box shows the record types in the
current database and indicates whether the lock status is f for free, r for read lock, w for
write lock, x for exclusive lock, or k for keep lock.
As with the option above, this command displays a list box with the current lock values.
Radio buttons control whether the list displays record locks, key locks, or set locks.
Select the type of object and the object, and then free the lock by pressing the Free button.
You can also select the Free All button to free all locks on all objects.

Set Record Lock Bit


Choosing this command calls d_rlbset for the current record.

Interactive Database Access Utility (ida and wida)

8-41

Clear Record Lock Bit


Choosing this command calls d_rlbclr for the current record.

Test Record Lock Bit


Choosing this command calls d_rlbtst for the current record.

Display Lock Status


Choosing this command displays a list box with the current lock values: f for free, r for
read lock, w for write lock, x for exclusive lock, and k for keep lock. Radio buttons
control whether the list displays record, key, or set locks.

8.2.9 Using the Special Menu Commands


This section describes the commands that are available in the Special menu. The Special
menu is shown below.

Fig. 8-31. The Special Menu

Cache Pages
Choosing this command displays a dialog box with an edit box for the cache pages and
one for the overflow index pages to use. This can only be done before a database is
opened.

File Handles
Choosing this command displays an edit box to set the maximum number of data and
key files that RDM may have open for this task.

8-42

Centura RDM Users Guide

Close Handles
Choosing this command closes all files that RDM is currently holding open.

TAF and LOG File Paths


Choosing this command allows you to change the names of the transaction activity file
(TAF) and log file for the database. You may include directory paths with each name.
This command can be performed only if all databases are closed.

Lock Manager
Choosing this command brings up a dialog box that allows you to select a
communication type (protocol) and name for communicating with the lock manager.
This command can be performed only if all databases are closed.

8.2.10 Using the Options Menu


This section describes the flags that can be switched on and off by using the Options
menu. The Options menu is shown below, including the default settings for each flag. If
there is a check mark next to the option name, the option is on. Otherwise, the option is
off.

Fig. 8-32. The Options Menu


Using this menu is the equivalent of calling the d_on_opt function or the d_off_opt
function (whichever changes the option setting) for the menu item that you selected.
Each menu item is listed and described below, and the corresponding C constant is
shown in parentheses after the name of the menu item. For more details about these
flags, see the vista.h header file and the d_off_opt entry in the RDM Reference Manual.

Interactive Database Access Utility (ida and wida)

8-43

Closefiles
(CLOSEFILES) When this option is on, RDM closes files automatically after all input and
output is completed. Otherwise, RDM leaves those files open. The default value for this
option is off.

Delete Chain
(DCHAINUSE) When this option is on, RDM allocates any new records from the delete
chain before any new pages are added. Otherwise, RDM allocates new records to the
end of the file. The default value for this option is on.

Delete Log
(DELETELOG) When this option is on, RDM deletes the database log file automatically
when the database is closed. Otherwise, the log file is kept. The default value for this
option is off.

Ignorecase
(IGNORECASE) When this option is on, RDM sorts strings without regard to case.
Otherwise, the sorting of strings is case-sensitive. The default value for this option is off.

Prealloc
(PREALLOC_CACHE) When this option is on, RDM allocates the entire cache when a
database is opened. The default value for this option is off. This option can be changed
only if all databases are closed.

Readonly
(READONLY) When this option is on, any databases that you open can be read but not
modified. Otherwise, you have full access to the opened databases. (Note that even if
this option is off, you can choose to open individual databases in read-only mode.) The
default value for this option is off. This option can be changed only if all databases are
closed.

Remotesync
(REMOTESYNC) When this option is on, RDM locks a file automatically whenever it is
accessed. The default value for this option is off.

Syncfiles
(SYNCFILES) When this option is on, RDM forces file commits whenever a transaction is
ended, so that the files remain synchronized. Otherwise, the transaction remains in the
system cache. The default value for this option is on. This option can be changed only if
all databases are closed.
8-44

Centura RDM Users Guide

Transaction Logging
(TRLOGGING) When this option is on, RDM automatically logs all transactions.
Otherwise, no transaction logging is done. The default value for this option is on. This
option can be changed only if all databases are closed.

TxTest
(TXTEST) When this option is on, RDM can test how the recovery of transactions is
working. Otherwise, RDM is unable to test transaction recovery. The default value for
this option is off.

8.2.11 Cross-Referencing wida Commands to RDM Functions


The wida utility allows you to use a menu-driven GUI interface to examine how RDM
functions operate. Table 8-6 lists wida menu commands and the corresponding RDM
function or functions that produce the same result. This list is helpful when learning
how to use the various RDM functions. For complete information on the operation of a
particular RDM C function, refer to the detailed function descriptions in the RDM
Reference Manual.
In the following list, the cross-references are grouped by menu. The menu commands
are in the left column, and the corresponding RDM functions are in the right column.
Table 8-6. wida Commands and Corresponding RDM Functions
wida Command

RDM Function
File Menu

Open Database

d_open

Close Database

d_close

Incremental Open

d_iopen

Incremental Close

d_iclose

Database Number

d_setdb

Initialize Database

d_initialize

Destroy Database

d_destroy

Exit

N/A
Key Menu

Scan

d_keyfrst, d_keynext

First

d_keyfrst

Last

d_keylast

Next

d_keynext

Display Currency Table

d_crget, d_csmget, d_csoget

Interactive Database Access Utility (ida and wida)

8-45

Table 8-6. wida Commands and Corresponding RDM Functions (continued)


wida Command

RDM Function

Previous

d_keyprev

Delete

d_keydel

Exist

d_keyexist

Store

d_keystore

Keybuild

d_keybuild

Scan

Set Menu
d_findfm, d_findnm

First

d_findfm

Last

d_findlm

Next

d_findnm

Previous

d_findpm

Owner

d_findco

Connect

d_connect

Disconnect

d_discon

Members

d_members

Is Owner?

d_isowner

Scan

Record Menu
d_recfrst, d_recnext

First

d_recfrst

Last

d_reclast

Next

d_recnext

Previous

d_recprev

Enter new record

d_fillnew

Modify

d_recwrite

Delete

d_delete

Disconnect & Delete

d_disdel

Set Current Owner

Currency Menu
d_setom, d_setoo, d_setor, d_csoset

Set Current Member

d_setmm, d_setmo, d_setmr, d_csmset

Set Current Record

d_setrm, d_setro, d_crset

Display Timestamp Status

d_cmstat, d_costat, d_crstat, d_csstat

Display Currency Table

d_crget, d_csmget, d_csoget

8-46

Centura RDM Users Guide

Table 8-6. wida Commands and Corresponding RDM Functions (continued)


wida Command

RDM Function
Transactions Menu

Begin

d_trbegin

End

d_trend

Abort

d_trabort
Locks Menu

Lock Types

d_reclock, d_setlock, d_keylock

Free Types

d_recfree, d_setfree, d_keyfree

Set Record Lock Bit

d_rlbset

Free Record Lock Bit

d_rlbclr

Test Record Lock Bit

d_rlbtst

Display Lock Status

d_internals
Special Menu

Cache Pages

d_setpages

File Handles

d_setfiles

Close Handles

d_closeall

TAF & LOG Paths

d_dblog, d_dbtaf

Lock Manager

d_lockcomm
Options Menu

Closefiles

d_on_opt, d_off_opt

Delete Chain

d_on_opt, d_off_opt

Delete Log

d_on_opt, d_off_opt

Ignorecase

d_on_opt, d_off_opt

Prealloc

d_on_opt, d_off_opt

Readonly

d_on_opt, d_off_opt

Remotesync

d_on_opt, d_off_opt

Syncfiles

d_on_opt, d_off_opt

Transaction Logging

d_on_opt, d_off_opt

TxTest

d_on_opt, d_off_opt

About wida

Help Menu
N/A

Interactive Database Access Utility (ida and wida)

8-47

Chapter 9
RDM Unicode Support
9.1

Unicode Support at the Compiler and OS Level

Support for Unicode varies widely for different operating systems; consequently, these
differences affect the levels of support available in RDM. Currently Unicode support is
very complete for Windows NT, but support in UNIX is much more limited.
On Win32 all library functions exist both as ANSI and as Unicode versions; for example,
two versions exist for all I/O and GUI functions. This means that as an RDM user, you
can write applications that use only Unicode strings, and may therefore want to specify
paths, user IDs, etc., in Unicode. Thus for Win32, we need an RDM library in which all
string arguments are Unicode strings.
Note: "Win32" refers to Windows NT not Windows 95 or 98, which do not support
Unicode.
On UNIX, Unicode string manipulation functions are provided, but I/O functions are
not. Some display functions, such as puts() and gets(), have Unicode equivalents, but not
all. This level of support makes it unlikely that as an RDM user, you will write
applications that use only Unicode strings, or that you will require an RDM library with
Unicode string arguments.
The most common standard for storing international character sets on UNIX is UTF-8
(see note below). This is an encoding standard that provides a method for mapping
Unicode characters to multi-byte sequences, so that they can be stored as conventional
8-bit character strings. RDM 5.0 supports UTF-8 on platforms where the standard is
available.
Note: The acronym UCS stands for "Universal Character Set". The set was developed
jointly by the Unicode Consortium and the International Organization for
Standardization (ISO). UTF is an acronym for "UCS Transformation Format".

String Fields in the Database


Regardless of whether the RDM library accepts Unicode or ANSI string arguments, or
does internal string manipulation in Unicode, a need may exist for Unicode string fields
in a database on any platform that supports Unicode at any level.
All existing versions of RDM are capable of storing Unicode strings, which are arrays of
unsigned shorts, ints or longs (according to platform) all of which RDM has always

RDM Unicode Support

9-1

been able to store. However, if these fields are defined as keys, RDM may not sort them
as required. Earlier versions of RDM have sorted strings by their binary values, but
Unicode strings should be sorted according to a sequence which can be more complex.
String collation functions, such as _wcsnicoll in Win 32, are provided in the OS for doing
locale-specific collation of Unicode strings. Thus RDM must support Unicode string
fields as a separate type from their underlying data types. Apart from their size, Unicode
string fields should be treated in much the same way as regular, char string fields.

Definitions
The data type used for Unicode characters is called wchar_t on all the systems supported
by RDM. (Most of these systems also define _WCHAR_T, which is the equivalent of
wchar_t.) Unfortunately, the definition of wchar_t is not the same across all platforms:
Table 9-1. OS Definitions for wchar_t
Platform

wchar_t Definition

Win32

unsigned short

Solaris

long

Unixware

long

HPUX

unsigned int

All of the platforms in the table above provide Unicode equivalents of string handling
functions such as strcpy(), strcmp(), etc. Typically, these functions are named wcscpy(),
wcscmp(), etc. In addition, Win32 provides macros and typedefs (in tchar.h), which
allow the user to write code that can be compiled for Unicode or ANSI string handling;
UNIX does not provide these. Win32 programs (such as RDM) that use these macros
must define the symbol _UNICODE at compile time if Unicode is required.

Conversion between ANSI and Unicode


All platforms supported by RDM offer functions for conversion between Unicode and
ANSI strings. English language strings in Unicode, or any strings using just the ANSI
character set, can of course be converted to ANSI and back, without loss of data.
Unicode strings representing non-Latin characters, such as Chinese or Japanese
characters, can be converted into multi-byte character strings, but the conversion may
involve loss of data; converting them back to Unicode may not produce the original
string.
Full Unicode support in RDM therefore requires that Unicode strings never be converted
internally into multi-byte or ANSI strings, even if they are subsequently converted back
to Unicode. All internal string handling must be accomplished with Unicode variables.
9-2

Centura RDM Users Guide

Note also that filenames on Windows NT are in Unicode. On an English version of NT


this is not very obvious, but some versions of NT (for example, from the Far East) may
support filenames that can only be represented in Unicode.

9.2

RDM 5.0 Implementation

RDM 5.0 provides two levels of support for Unicode:


1.

Unicode data fields (data type wchar_t), supported on all platforms

2.

Unicode library functions, with Unicode string arguments and full internal string
handling in Unicode, supported on Win32 only.

To enable the first level of support, the preprocessor symbol UNICODE_DATA must be
defined when RDM is compiled. This symbol is defined automatically in vista.h, on all
platforms.
To enable the second level of support, the preprocessor symbol UNICODE must be
defined when RDM is compiled. This symbol is not defined by default on any platform,
and should only be defined for Win32. If it is defined on any other platform a compiler
error will result. The batch files and makefiles supplied with RDM for Win32 will define
the preprocessor symbol UNICODE if an environment variable of the same name is set.
Thus before running the batch files, type the following:
set UNICODE=1

RDM 5.0 on UNIX


For UNIX, RDM 5.0 provides only level 1 above, that is, Unicode (wchar_t) database
fields.
RDM 5.0 also allows Unicode strings to be stored in (char) fields, using UTF-8 format.
Provided the runtime locale is set correctly, and the RDM runtime option MBSSORT is
enabled, key fields containing UTF-8 strings will be sorted correctly.

RDM Unicode Support

9-3

RDM 5.0 on Win32


On Win32, you can build an ANSI version of the RDM 5.0 DLL, supporting Unicode
database fields only (level 1 above). Or you can build a Unicode version, with full
Unicode support (levels 1 and 2 above).
Because the APIs are not the same, these two DLLs have different filenames:
ANSI DLL:

rdm50.dll

Unicode DLL:

rdm50u.dll

The functionality of the two DLLs should be identical, except for Unicode support. There
is no advantage in using the Unicode DLL in an application that does not manipulate
foreign language data.
RDM 5.0 for Win32 includes two complete sets of binaries (all DLLs, LIBs and programs),
a Unicode set, and an ANSI set. The functionality of the utility programs is the same
and, except for the Lock Manager, they are interchangeable. For example, it makes no
difference whether a Unicode or an ANSI version of dbcheck.exe is run; the output
should be identical.
The Unicode and ANSI Lock Manager programs are not interchangeable, because of
differences in message formats (see below). This means that applications that use the
Unicode DLL (rdm50u.dll) must also use the Unicode Lock Manager (lmwu.exe).
Applications that use the ANSI DLL (rdm50.dll) must use the ANSI Lock Manager
(lmw.exe).
To make the Unicode programs distinguishable from the ANSI ones, their filenames
include the letter "u", as shown below. Also, the word "Unicode" appears in the version
string they display when they are run.

9-4

Centura RDM Users Guide

Table 9-2. Unicode and ANSI Program Names


Win32 ANSI program name:

Win32 Unicode program name:

adstatus.exe

N/A

dal.exe

dalu.exe

datdump.exe

datdumpu.exe

dbcheck.exe

dbchecku.exe

dbclrlb.exe

dbclrlbu.exe

dbedit.exe

dbeditu.exe

dbexp.exe

dbexpu.exe

dbimp.exe

dbimpu.exe

dbrev.exe

dbrevu.exe

dchain.exe

dchainu.exe

ddlp.exe

ddlpu.exe

initdb.exe

initdbu.exe

keybuild.exe

keybldu.exe

keydump.exe

keydumpu.exe

keypack.exe

keypacku.exe

lmclear.exe

lmclearu.exe

lmw.exe

lmwu.exe

prdbd.exe

prdbdu.exe

w_query.exe

w_queryu.exe

wconsole.exe

wconsolu.exe

wida.exe

widau.exe

Unicode Data Fields


In RDM 5.0 (on all platforms), the ddlp utility recognizes the data type wchar_t for
database fields. In the database dictionary (DBD file) these fields are represented by the
character "C" similar to lowercase "c" for char fields. The size of these fields is of course
system dependent. On Win32 a wchar_t is two bytes in size, and on UNIX its size is 4

RDM Unicode Support

9-5

bytes. Unfortunately, this leads to an incompatibility between data on different


platforms. (Note that differences in byte ordering also caused incompatibilities in earlier
versions of RDM.)
The Country Table is not used in sorting Unicode data. This feature, which has existed in
RDM since version 3.0, allows the application to redefine the sorting order of char data,
and is used in European language applications, where characters such as , , etc., are
not sorted by their ASCII values. Since these characters are sorted correctly by the
Unicode string collation functions, there is no need for any mechanism such as the
Country Table. The "ignorecase" option (specified in file vista.ctb, or through function
d_on_opt) is, however, recognized when Unicode database fields are sorted.
Note that the Country Table is still usable with char fields in RDM 5.0.

Function Prototypes
In general, RDM functions that take (char *) string arguments in non-Unicode versions of
RDM take (wchar_t *) string arguments in the Win32 Unicode DLL. A Win32 application
that calls RDM functions such as dt_dbuserid or dt_dbdpath must supply (wchar_t *)
arguments if it uses the Unicode version of the RDM library.
If the functions in the ANSI and Unicode versions of the RDM DLL had the same names,
there would be a risk of application developers accidentally using the wrong library.
This mistake would probably not be detected until the program crashed, and the cause of
the crash might not be obvious. Therefore, a function naming strategy has been adopted
in RDM similar to that used by Microsoft in its Windows DLLs. Unicode function names
bear the suffix "W", while ANSI function names bear the suffix "A". See the following
example.
ANSI prototypes:
int dt_dbuseridA(const char *, DB_TASK *);
int dt_dbdpathA(const char *, DB_TASK *);

Unicode prototypes:
int dt_dbuseridW(const wchar_t *, DB_TASK *);
int dt_dbdpathW(const wchar_t *, DB_TASK *);

9-6

Centura RDM Users Guide

The application developer can use the same function names as in previous versions of
RDM, for example, dt_dbuserid and dt_dbdpath. Macro definitions are provided in the
RDM include files that map these names to the actual function names, dependant on
whether UNICODE is defined at compile time. See below:
#ifdef UNICODE
#define dt_dbuserid dt_dbuseridW
#else
#define dt_dbuserid dt_dbuseridA
#endif

#ifdef UNICODE
#define dt_dbdpath dt_dbdpathW
#else
#define dt_dbdpath dt_dbdpathA
#endif

All other RDM function prototypes follow this same pattern. Thus the application
developer is prevented from passing the wrong string type to an RDM function, (by
compiler errors), and prevented from linking to the wrong library (by linker errors).
Note that the database open mode in dt_open, and the lock status characters in
d_reclock, d_setlock, etc., are defined as char in all versions of RDM. These arguments
have not been redefined as wchar_t in the Unicode implementation, as they can only ever
take certain pre-defined values ("o", "s" or "x" for the open-mode), which can always be
represented in char variables.
On UNIX, where no Unicode library is provided, the function prototypes are the same as
for RDM 4.5.

9.3

RDM for Win32

9.3.1 db_QUERY and db_REVISE


All functions with string arguments in the db_QUERY library also now take (wchar_t *)
strings in the Unicode version. This means that all SQL statements must be passed as
(wchar_t *) strings in the Unicode version. See the db_QUERY Users Guide for more
information.
db_REVISE also recognizes (char *) and (wchar_t *) strings, and handles them both the
same way, performing string conversions where necessary. This means that db_REVISE
can be used to convert non-Unicode string fields in a source database into Unicode string
fields in a destination database.

RDM Unicode Support

9-7

9.3.2 Utilities and Win32


Unicode versions of all the RDM utilities are provided in RDM 5.0 for Win32. In most
cases these behave the same as their non-Unicode equivalents, except that they use the
Unicode DLL instead of the ANSI one.
Both Unicode and ANSI versions of all the utility programs support wchar_t fields as
well as char fields. With a program such as datdump, which displays the contents of
database fields, string fields are converted to the native string type when displayed. That
is, if you compile datdump for Unicode, when the utility displays string fields, it must
convert the fields to Unicode, whether they are ANSI or Unicode. Likewise, if you
compile datdump for ANSI, it must convert all string fields to ANSI. Thus ANSI
versions of the utilities may not be able to display the contents of Unicode fields
correctly.
Some of the utilities, notably dbimp and dbexp, read or write text files. The Unicode
implementations of these programs offer the choice of ANSI or Unicode input and
output, the default being ANSI. Unicode I/O is enabled through the "-u" command line
option, requiring input files in Unicode text format, and producing Unicode text files as
output. These files are not readable by most software, but some programs such as
MS Word can read and write them.
The ANSI implementations of dbimp and dbexp only support ANSI input and output.

9.3.3 ddlp and DBD File Compatibility


In a Unicode system, application developers may want to define databases with Unicode
filenames, field names, record names, etc. Since Microsoft VC 5.0 and 6.0 are capable of
compiling source code written in Unicode, you may wish to take advantage of this
feature to name variables, fields, etc. Even if the application source code does not contain
Unicode names, a need may still exist for Unicode filenames in the database definition.
In RDM 5.0 for Win32, the Unicode version of ddlp recognizes a command line option
"-u", meaning that the DDL schema is in Unicode text, and that the C header file
generated should also be in Unicode text. The database filenames in the database
dictionary (DBD file) will also be represented in Unicode text (wchar_t arrays, up to 256
characters long).
If the "-u" option is used then a DBD file will be generated in RDM version 5.00 format,
which is different from the format of 3.00 and subsequent versions. The RDM 5.0 DLL is
able to read DBD files in either format, but the new format will not be readable by older
versions of RDM.

9-8

Centura RDM Users Guide

The following DBD formats now exist:


v3.00

Used by all versions of RDM from 3.0 to 4.5, with ANSI filenames up to 48
characters long

v3.01

Previously only recognized in RDM/Vx 4.9.3, with VxWorks-specific DDL


extensions

v5.00

ANSI filenames up to 256 characters long, and v3.01 extensions

u5.00

Unicode filenames up to 256 characters long, and v3.01 extensions

These DBD formats are supported by RDM versions as shown in the table below:
v3.00

v3.01

v5.00

RDM 3.0 to 4.5

RDM 4.9.3

RDM 5.0 ANSI

RDM 5.0
Unicode

u5.00

9.3.4 The Lock Manager and Win32


The Win32 Unicode version of the Lock Manager, like the other Unicode versions of
RDM, does all internal string handling in wchar_t strings. Filenames and user IDs are
held in wchar_t strings, and all messages sent between the Lock Manager and the
runtime library that contain strings use Unicode, not ANSI.
This means that Unicode and non-Unicode versions of RDM and the Lock Manager are
not inter-operable. They can be used at different times on the same databases, but not at
the same time in multi-user mode. See the section below on compatibility.

Non-Unicode Interfaces
The network protocols used for Lock Manager communication on Win32 generally do
not support Unicode. This means that, in the Unicode implementation of RDM, the Lock
Manager name has to be converted to ANSI before it is passed to the network protocol.
The same restriction may also apply to user IDs. Therefore it is a good practice to use
names which can be converted to ANSI.

RDM Unicode Support

9-9

9.4

Other Compatibility Issues

Besides the DBD file and Lock Manager communication (see above), the following data
structures can be shared by RDM applications on a network. These structures contain
character strings which, in Unicode versions, will be wchar_t strings:

TAF file (RDM 4.5 ).


short
short
char
short
char

Contents listed below:

lmc_type;
user_count;
lmc_lockmgrn[48];
cnt;
files[9][48];

DBL file (General Lock Manager only).

Contains filenames and user IDs.

All these data structures are incompatible between Unicode and ANSI versions of RDM.

9.4.1 Is Compatibility Necessary?


It is unlikely that a database would ever need to be accessed by both Unicode and
non-Unicode versions of RDM. If Unicode is required at all, then it will be required in all
applications using the database.
Unfortunately, Unicode support on Windows 95 and Windows 98 is so limited that only
the non-Unicode version of RDM will be usable on these platforms. However, if an
application must run on these platforms, and must use ANSI/multi-byte strings, it is
likely that applications running on Windows NT machines sharing the same database
would also use ANSI/multi-byte strings; otherwise, incompatibilities would exist in the
data stored by the application.
Our projection then is that compatibility is not required. However, it is necessary to
ensure that the mixing of Unicode and non-Unicode implementations will result in
orderly behavior. That is, the result must be an error message, and not database
corruption or a crash in RDM or the Lock Manager. It must therefore be possible to
distinguish between Unicode and non-Unicode versions of the above data structures
before any attempt is made to process their contents. Also, they should be
distinguishable in a way that will force prior versions of RDM to reject immediately
Unicode DBD files, Lock Manager messages, TAF, or DBL files.

9.4.2 Detecting Incompatibilities


The Unicode version of the Lock Manager will refuse connections from non-Unicode
implementations of the runtime library, and ANSI versions of the Lock Manager
(including RDM 4.5) will likewise refuse connections from Unicode implementations of
the runtime library.

9-10

Centura RDM Users Guide

The TAF file includes a flag (in the upper half-byte of the lmc_type element), which is set
if the TAF file was generated by a Unicode RDM library. This enables RDM 5.0, as well
as prior versions, to reject incompatible TAF files. Thus, when differences exist in the
position of the cnt element, you avoid the risk of triggering an unnecessary
auto-recovery.
The version number stored in the DBL file (DBL_VER) is also different for Unicode and
non-Unicode implementations, again allowing all versions of RDM to reject incompatible
DBL files.

9.5

Unicode Prototypes for Specific Functions

The prototypes for approximately one third of the RDM library functions are different in
the Unicode version than in the standard version. These are all functions containing
char* data types. In the majority of these, char* becomes wchar_t* and these are shown
in List One below. Several functions that take the char* data type, however, do not
change in the Unicode version. These are found in List Two below.
Note: Unicode and non-Unicode function prototypes may not be mixed. For those
functions that change for Unicode, only char* is available in an ASCII RDM runtime, and
only wchar_t* is available in a Unicode RDM runtime.
List One
See the list below for functions taking the char data type, which have a separate
prototype for Unicode (char changes to wchar_t):
d_checkid

d_dbtmp

d_open

d_ctbpath

d_dbuserid

d_rdmini

d_dbdpath

d_destroy

d_rdmve

d_dbfpath

d_iopen

d_recover

d_dblog

d_lmclear

d_renfile

d_dbnum

d_lmstat

d_trbegin

d_dbtaf

d_lockmgr

RDM Unicode Support

9-11

List Two
The functions listed below take the char data type, but do not have a separate prototype
for Unicode (char remains char):
d_keylock

d_reclstat

d_keylstat

d_setlock

d_mapchar

d_setlstat

d_open

d_trlog

d_reclock
Note that one function, d_open, appears on both lists. Its prototype is shown below:
int EXTERNAL_FIXED d_open(P1(CONST DB_TCHAR DB_FAR *)
Pi(CONST char DB_FAR *));

9-12

Centura RDM Users Guide

Chapter 10
File Transfer Utilities (dbimp, dbexp)
10.1 Introduction
RDM stores all its data in a special-purpose format. This format is specific to RDM, and
all data in an RDM database must have been created by the RDM runtime functions. In
the development of a system, data often already exists in a format other than that used by
RDM, the most common being ASCII format. RDM cannot operate directly on ASCII text
files. This chapter provides information about RDMs dbimp and dbexp utilities, which
transfer data from an ASCII text file into RDM. For information about the way that RDM
handles Unicode text files, see Chapter 9.
It is possible to write RDM applications to read data from a text file and enter it into
RDM records, or vice versa. Entering bulk data from an external source into a database is
called importing. Reading data from RDM and writing it in a different format is called
exporting. To accomplish these tasks, two general-purpose utilities are provided as a
part of the RDM tool set. The utility that imports data to an RDM database is called
dbimp. The utility that exports data is called dbexp.
These utilities use ASCII text files as the standard external representation of data. These
files can be created or modified by text editors or string manipulation programs. Most
database management systems have the ability to export data into ASCII (see Figure
10-1).
Both dbexp and dbimp view an ASCII record as one line of text, terminated by a newline
character (and Enter character on some computers), with fields separated by a standard
separator character. Our utilities use the comma as a separator character. . Numeric
fields are represented by ASCII digits, in base 10. Character fields are represented by
ASCII alphanumeric characters, optionally enclosed by double quotation marks. The
fields (or records) are not fixed-length.

File Transfer Utilities (dbimp, dbexp)

10-1

dbexp

dbimp

ASCII
Text Files

RDM
Database

Foreign
DBMS

RDM
Database

Text
Editor

Fig. 10-1. Importing and Exporting Data


All ASCII records in one file must be of the same type. This means that there are the
same number of fields on each line, and the same sequence of field types is maintained
from line to line. For example, if one record has a numeric field followed by two
character fields, all records must have this format. One character field followed by two
numeric fields is not permitted. All output from dbexp will be created in the same
format. All input read by dbimp is expected in this format. The following text shows six
records of the same record type, each containing seven fields. The first two fields and the
last field are numeric, while all the other fields are character strings. (The NULL field
represents no owner pointer for the set article_list as declared in the tims.ddl.)
2,0,"db001","Database Design","McGraw Hill","1983",0
6,0,"db002","An Intro...","Addison Wesley","1981",0
11,0,"db003","Microcomputer ...","McGraw Hill","1985",0
16,0,"db004","Computer ...","Prentice Hall","1977",0
19,0,"db005","Fundamental ...","Yourdan","1981",0

The file format above was created using the following:


dbexp -m tims info

10-2

Centura RDM Users Guide

A second record type shown below would be stored in a different text file:
0:2,"4GL"
0:3,"languages"
0:4,"reliability"
0:5,"debugging"
0:6,"testing"
0:7,"database design"

The above file format was created using:


dbexp -r tims info

10.2 Exporting Data


The RDM exporting utility, dbexp, will convert all instances of selected record types into
ASCII text files. You can select all the record types in the database for export. The
resulting text files can in turn be used by the import utility, dbimp, by a text editor, or by
any other text manipulation software. Since ASCII text is well suited for transmission to
other platforms, this feature allows databases to be moved to computers of different
types.
An example execution of dbexp might look like the example below:
dbexp tims info

This would export data from the info record type of the tims database. The info record
type looks like the following:
record info {
unique key char id_code[16];
char info_title[80];
char publisher[32];
char pub_date[12];
int info_type;
}

The file created by dbexp would be named info.txt and would contain records created
from the contents of the corresponding RDM data file, as follows:
"db001","Database Design","McGraw Hill","1983",0
"db002","An Intro...","Addison Wesley","1981",0
"db005","Fundamental ...","Yourdan","1981",0

The dbexp utility is invoked as follows:


dbexp [-r] [-m] [-n] [-d] [-u] [-s "<char>"] [-e "<char>"] dbname [rtype...]
When no record types (rtype) are listed following the database name (dbname), dbexp will
export all record types in the database. If one or more record types are listed, only those
record types will be exported.

File Transfer Utilities (dbimp, dbexp)

10-3

The -s option indicates that the following argument is a character, enclosed in quotes, to
be used as a separator character. The default is a comma. For example, if a vertical bar
character were desired, the following command could be used:
dbexp -s "|" tims info

The resulting file would contain the data below:


"db001"|"Database Design"|"McGraw Hill"|"1983"|0
"db002"|"An Intro..."|"Addison Wesley"|"1981"|0
"db005"|"Fundamental ..."|"Yourdan"|"1981"|0

The -e option changes the escape character (default is backslash), which is to be used in
front of each quotation mark character contained within a character string, or each
backslash character contained in a string. For example, if a field contains the following
string:
Your "filing cabinet" is called C:\DRAWERS.

dbexp would convert the string into the following format as it is written into the ASCII
file:
"Your \"filing cabinet\" is called C:\\DRAWERS."

You may wish to change the escape character if text in your database contains many
backslashes. This would prevent each backslash from becoming a double backslash.
Note, however, that if the exported data will be used as input to dbimp, the same escape
character must be specified in the dbimp command.
The -r option causes dbexp to include the records database address (see section 14.2.2,
"Data File Organization") as the first field in each ASCII record. For example:
dbexp -r tims info

will cause the records to appear as follows:


1:3,"db001","Database Design","McGraw Hill","1983",0
1:7,"db002","An Intro...","Addison Wesley","1981",0
1:20,"db005","Fundamental ...","Yourdan","1981",0

Since the database address of each record is unique, this field can be used as a unique
identifier of each record. The import utility can take advantage of this field.
The -m option causes set membership information to be included with each record. This
information consists of a list of database addresses, which are placed after the records
own database address (if -r is specified) and before the ASCII data fields. One database
address field is created for each set for which this record type is a member. The value of
each field is the database address of the owner record for that set. If the record is not
connected to the set, the field value is zero.

10-4

Centura RDM Users Guide

The -n option is a silent option; there is no output to stdout. The -d option causes a
database address to be printed as long integers, rather than in the standard format. Note
that a database address may appear as a very large number (the maximum is
4,294,967,295) because of the internal format of a database address.
The order of the database address fields is the same as the order of the sets in the DDL. If
a record is a member of three sets, three database addresses would be included in each
ASCII record. The first database address would represent the owner of the first set in the
schema that lists this record type as a member. This ordering information is important
when using the import utility to recreate the set connections, because it can be used to
create a logical connection between fields with identical values.
The command below:
dbexp -r -m tims info

would create the following:


1:18,1:1,NULL,"db001","Fourth-Gen...","Prentice-Hall","1985",0
1:19,1:1,NULL,"db002","Fourth-Gen...","Prentice-Hall","1986",0
1:20,1:2,NULL,"sw001","Software Rel...","Wiley-Interscience","1976",0

The info record type is a member of two sets. This data has been connected in the first
set (has_published), but not in the second (articles), as indicated by the NULL in the
third field.

10.3 Importing Data


This section describes the usage of the RDM import utility, dbimp. The purpose of
dbimp is to import data from an ASCII-formatted file into an RDM database. The import
utility is simple enough to allow great quantities of raw ASCII data to be entered into an
RDM database with very little specification. With more complex requirements, dbimp
can be instructed to perform mappings between the input data and RDM records and to
make set connections based upon matching field values.
All instructions to dbimp are placed into a text file in the form of an import specification
language (ISL). An ISL specification identifies the database and the files containing
ASCII data to be imported. It also contains mappings between the ASCII data fields and
the RDM record fields. Figure 10-2 shows the general operation of dbimp.

File Transfer Utilities (dbimp, dbexp)

10-5

dbimp

Import
Specification

ASCII Text

ASCII Text

RDM
Database

Fig. 10-2. Import Utility Usage


ASCII text files can be created by a wide variety of software programs, including dbexp,
text editors, and most other DBMS products.
Databases that are built with certain restrictions (see section 10.4, "Using Export and
Import Together") can be exported, then imported again without losing any information.
This allows simple restructuring of a database. Also, a database in ASCII format can be
transferred to another computer and then imported into an RDM database, even though
the source and target computers have different processors and internal representations of
data.

10.3.1 Import Program Usage


The full definition of the usage of dbimp is shown below.
dbimp [-n] [-u] [-s "<char>"] [-e "<char>"] [-kn] [-pn] impspec
The -s and -e specify alternate separator characters and escape characters for the ASCII
file. For examples, refer to the discussion of these characters in section 10.2. If dbexp has
been used to create the text files that are to be imported, any alternate separator or escape
characters specified on the dbexp command line should also be used on the dbimp
command line.
The -n option is a "no print" request. By default, dbimp will display each record of ASCII
text and any warning messages to standard output. If no such output is desired, this
option will turn it off.
The -u option enables Unicode I/O. For further information about Unicode files, see
Chapter 9.
The -kn option makes n the key size in the created record index (see section 10.3.2,
example 2). By default, n is 25. If your data requires more characters to be unique, you

10-6

Centura RDM Users Guide

can specify up to 228 characters. Note that the larger the number, the larger the
temporary key file needs to be. To decrease the size of the CRI keys, use a value of n less
than 25.
The -pn option makes dbimp call d_setpages with n as the number for the database
pages. By default, n is 17. To increase performance, increase n. To save on memory, n
may be set as low as five.
The import specification language is contained in the file impspec. This is a text file
containing the specification that has been written by the dbimp user. It may have any
legal file name, but we recommend the following naming convention:
dbname.imp
The suffix of .imp will distinguish this file as an import specification for the database
dbname.

10.3.2 Import Specification Language


This section fully defines the usage and syntax of the import specification language. The
examples in the following paragraphs introduce the languages features in a stepwise
manner, with growing complexity. The complete grammar is given at the end of this
section.

Example One: Simple family information database


The first example contains the following elements: a set of person names in the ASCII text
file person.asc:
"Warner","Micah Wayne",9761101
"Warner","Jesse David",9800706
"Warner","Wayne Lawrence",9540530
"Wood","Jennifer Ann",9531214
"Warner","Paul Russell",9860904

and an RDM record definition in a database named tree:


record person {
char p_last[20];
char p_first[30];
long p_birth;
compound key p_name {
p_first;
p_last;
}
}

The goal is to import the ASCII records into the RDM records. The first ASCII field is a
last name, the second is a first and middle name, and the third is an encoded birth date
(format YYY MM DD, where 1000 must be added to the year). The fields in the RDM

File Transfer Utilities (dbimp, dbexp)

10-7

record happen to be in the same order. Our import specification will be stored in file
tree.imp, and will contain the following statements:
database tree;
foreach "person.asc" {
record person {
field p_last = 1;
field p_first = 2;
field p_birth = 3;
}
}
end;

The import utility is invoked as follows:


dbimp tree.imp

The output would look something like the box below:


Database Import Utility
For RDM Version 5.0
Copyright (C) 1984-2000 Centura Corporation, All Rights Reserved
Compilation complete
Starting data import
"Warner","Micah Wayne",9761101
"Warner","Jesse David",9800706
"Warner","Wayne Lawrence",9540530
"Wood","Jennifer Ann",9531214
"Warner","Thomas James",9850404
"Warner","Paul Russell",9860904
Successful import

Note that there are two phases in the execution of the import utility. The first phase is
the compilation phase, where the import specification is read and compiled. If there are
any errors or warnings in the specification, messages will be printed before the
"Compilation complete" message, and the import will be terminated. The specification
must compile correctly before the utility will open and update the database. This second
phase is the import phase. Its activity is logged between the "Starting data import" and
"Successful import" messages. Normal output is a copy of the input records. If there are
any problems during the import, error and warning messages will appear between the
input records. Often, the warnings can be ignored, but all should be examined for
potential problems in the input data.
This first example has illustrated the use of five import specification statements:
database, foreach, record, field, and end.
The database statement identifies the database to be opened and updated. Records may
exist in a database if they will not collide with unique keys that are being imported.
Existing records will not be altered by the import, nor can they be accessed; the new data
will be completely disjoint from existing data.

10-8

Centura RDM Users Guide

The foreach statement specifies an ASCII text file (within quotation marks), followed by
a block of statements enclosed in braces. It may be interpreted as saying, "for each line in
this file, perform the following operations." During the import phase of the utility, it will
repeatedly read one line from the named file and process its contents according to the
enclosed statements. When the last line of text has been read, the statement following the
closing brace will be executed. In this simple example, the next statement is an end
statement.
The record statement names an RDM record type, followed by a block of statements
enclosed in braces. Each time the record statement is executed, a record of the named
type is conditionally created. There is a way to skip the creation of a record if a record
with the same contents has already been created. This capability will be discussed below.
In this example, a record will be created for each input line of text.
A field statement defines a mapping between an RDM record field (named left of the
equals sign), and an ASCII field (identified by its numeric position in the record). The
input field is converted into the type of the RDM field. In this example, the first and
second fields in the input record are converted into strings (by adding a null terminator
following the last character), and placed into the p_last and p_first fields. Then the third
input field is converted into a long integer, and placed into the p_birth field. The record
is actually created with the d_fillnew function, so that all keys are automatically created
along with the record.
The field statement implements the mapping between the ASCII and RDM records. For
each record statement, zero or more field statements may be used, not to exceed the
number of fields defined in the record. Not all fields in the RDM record require a field
statement. Unspecified fields are zero-filled. Likewise, it is not necessary to use all
ASCII fields in a field statement. The ordering of the fields is irrelevant.
If dbimp is unable to fully convert the input data into the RDM field type, it will print a
warning message, do the best it can, and go on. All other fields are filled. For example,
the length of the text in an input field may be longer than the space allowed for it in the
record. The utility will fill the RDM field to its maximum length, and ignore any
remaining characters.

Example Two: Simple library database


Example two will illustrate the conditional creation of records. Suppose that the input
text contains redundant data, as follows:
"Knuth, D.",1968,"Fundamental Algorithms"
"Ullman, J.",1982,"Principles of Database Systems"
"Knuth, D.",1969,"Seminumerical Algorithms"
"Knuth, D.",1973,"Searching and Sorting"

File Transfer Utilities (dbimp, dbexp)

10-9

Your schema will not contain redundant data but will instead utilize a set construct:
record author {
key char name[32];
}
record book {
char title[52];
long pub_date;
}
set published {
order ascending;
owner author;
member book by pub_date;
}

In this example, each line of text contains parts of two record types. This implies that
two record statements should be included within the one foreach statement. The
resulting database should contain four book records, but only two author records. The
first author record should be connected, via the published set, to three book records,
while the second author record should be connected to only one. The following import
specification will do just that:
database books;
foreach "books.asc" {
record author {
create on 1;
field name = 1;
}
record book {
field title = 3;
field pub_date = 2;
}
connect published;
}
end;

In this example, two records are conditionally created for each ASCII text line. The
create on statement is used to make sure that a new author record is created only if an
identical record has not already been created. Another statement, connect, is used to
perform a d_connect function between the two records created in the loop.
The create on statement causes dbimp to search its internal created record index (CRI)
for the existence of a record with the same record type and field value. The field value
stored in the CRI may or may not be stored in the record itself. In this example, the field
used in the create on statement is also used in the record. Other import specifications
may use the field values only to establish connections, and not for storage in the RDM
record.
If the create on statement searches the CRI for a matching record type and field value
and does not find it, it will create the record and an entry in the CRI, storing the database
address of the created record in the CRI entry. If it finds a match, it does not create a new

10-10

Centura RDM Users Guide

record, but uses the database address stored in the entry to represent the record that
would have been created.
The import utility maintains another internal list, called current of record type (CRT).
This is a currency table similar to the current set, owner, and member tables maintained
by the RDM runtime functions. Whenever a record is created, the database address of
that record is stored as the current record of its type. The connect statement will search
the schema tables for the correct owner and member types, then extract the database
addresses of those types from the CRT table. If there are no current records of both
types, dbimp will not attempt a connection, and will skip to the next iteration of the
foreach loop. Because only one record of each type is being tracked, dbimp cannot
connect recursive sets; that would require two records of that one type to be tracked.
We will perform the above example, showing the CRI and CRT list at key points. The
statement to be executed is shown, followed by a description of the actions performed by
dbimp in processing the statement.
Statement:
foreach "books.asc" {

Read the first line of books.asc into memory:


"Knuth, D.",1968,"Fundamental Algorithms"

Statement:
record author {
create on 1;

Search CRI (which is empty) for match.


Create the record (database address = [0:1]).
Create entry in CRI:
key={author,"Knuth, D."}, data=[0:1]

Save CRT:
author:
book:

[0:1]
NULL_DBA

Statement:
field name = 1;

The name field in author record is set to "Knuth, D".

File Transfer Utilities (dbimp, dbexp)

10-11

Statement:
record book {
field title = 3;
field pub_date = 2;
}

Unconditionally create book record ([1:1]). No entry created in CRI. Save CRT:
author:
book:

[0:1]
[1:1]

Field title set to "Fundamental Algorithms". Field pub_date set to 1968.


Statement:
connect published;

Determine that author is owner, book is member. Make current book, [1:1], the current
record. Make current author, [0:1], the current owner of set published. Call
d_connect(PUBLISHED).
Statement:
foreach "books.asc" {

Read the second line of books.asc into memory:


"Ullman, J.",1982,"Principles of Database Systems"

Statement:
record author {
create on 1;
field name = 1;
}

Search CRI for match (no match). Create author record (database address [0:2]), and add
it to the CRI:
key={author,"Knuth, D."}, data=[0:1]
key={author,"Ullman, J."}, data=[0:2]

Update CRT:
author:
book:

[0:2]
[1:1]

Store "Ullman, J." in name field.

10-12

Centura RDM Users Guide

Statement:
record book {
field title = 3;
field pub_date = 2;
}

Unconditionally create book record ([1:2]). No entry is created in the CRI. Save CRT:
author:
book:

[0:2]
[1:2]

Set field title to "Principles of Database Systems". Set field pub_date to 1982.
Statement:
connect published;

Determine that author is owner, book is member. Make current book, [1:2], the current
record. Make current author, [0:2], the current owner of set published. Call
d_connect(PUBLISHED).
Statement:
foreach "books.asc" {

Read the third line of books.asc into memory:


"Knuth, D.",1969,"Seminumerical Algorithms"

Statement:
record author {
create on 1;

Search CRI for match on: {author,"Knuth, D."}. Match is found; set CRT:
author:
book:

[0:1]
[1:1]

Statement:
field name = 1;

Statement skipped.
Statement:
record book {
field title = 3;
field pub_date = 2;
}

File Transfer Utilities (dbimp, dbexp)

10-13

Unconditionally create book record ([1:3]). No entry is created in the CRI. Save CRT:
author:
book:

[0:1]
[1:3]

Field title is set to "Seminumerical Algorithms". Field pub_date is set to 1969.


Statement:
connect published;

Determine that author is owner, book is member. Make current book, [1:3], the current
record. Make current author, [0:1], the current owner of set published. Call
d_connect(PUBLISHED).
The last iteration of the foreach loop will have the same effect as the third, where a third
book record is connected to the first author record.

Example Three: Full family tree database


Our final example demonstrates the use of the remaining two import specification
language statement types. The first is called update on, and is used to find an existing
CRI entry and update the existing record with new field values. This statement will
create the record for which there is not already a CRI entry. The last statement is called
find on, and is used to locate a record that has already been created with a create on or
update on statement, and make it the current record of type. It is used to locate records
that will be involved in connect statements. Note that update on and find on cannot
detect the presence of a record that existed in the database prior to this import!
This example is an expansion of Example One above, which represents a family tree.
Figure 10-3 shows the schema for building a family tree database.

Person

Husband

Wife

Offspring

Marriage
Fig. 10-3. Family Tree Schema

10-14

Centura RDM Users Guide

The data definition language for this schema follows:


database tree {
data file "tree.dat" contains person, marriage;
key file "tree.key" contains p_num, p_name;
record person {
unique key int p_num;
char p_last[20];
char p_first[30];
long p_birth;
long p_death;
compound key p_name {
p_last;
p_first;
}
}
record marriage {
long m_date;
long m_term;
}
set husband {
order ascending;
owner person;
member marriage by m_date;
}
set wife {
order ascending;
owner person;
member marriage by m_date;
}
set offspring {
order ascending;
owner marriage;
member person by p_birth;
}
}

The input data contains field-value relationships that will be converted into set
relationships during the import. There are two data files: one for definitions of people in
the tree and a second for the definitions of marriages in the tree. One person may be
either a husband or wife in a marriage, and a person may be the offspring of a marriage.
The definitions of the person fields in file person.asc are as follows:
1.

Numerical reference to the marriage from which this person is the offspring.

2.

Unique numerical identifier of this person.

3.

Persons last name.

4.

Persons first and middle name.

5.

Persons birth date, if known.

6.

Persons death date, if applicable and known.

The marriage.asc file contains fields defined as follows:

File Transfer Utilities (dbimp, dbexp)

10-15

1.

Unique numerical identifier of this marriage.

2.

Reference to the person record of husband.

3.

Reference to the person record of wife.

4.

Marriage date.

5.

Marriage termination date, if applicable and known.

See the sample data below:


File: person.asc
2,1,"Warner","Micah Wayne",9761101,0
2,3,"Warner","Jesse David",9800706,0
5,4,"Warner","Wayne Lawrence",9540530,0
5,6,"Warner","Walter Bartlett",9560226,0
5,7,"Warner","Laurel Ann",9590520,0
5,8,"Warner","Roger James",9601025,0
10,9,"Warner","Lawrence James",9270603,0
12,11,"Warner","Clarence R.",9010313,9270516
14,13,"James","Pauline May",9040723,0
16,15,"Morgan","Leslie Bartlet",8971128,0
18,17,"Carte","Dorothy Lois",8890802,0
20,19,"Morgan","Elizabeth Jane",9330412,0
22,21,"Wood","Jennifer Ann",9531214,0
22,23,"Kepler","Michael",0,0
22,24,"Martin","Dinah",0,0
22,25,"Pools","Janice",0,0
22,26,"Adams","Judy",0,0
2,27,"Warner","Thomas James",9850404,0
2,28,"Warner","Paul Russell",9860904,0
30,29,"Kepler","Patrick Michael",9870509,0

File: marriage.asc
2,4,21,9731215,0
5,9,19,9511013,0
10,11,13,9260313,9270561
20,15,17,9290324,0
30,23,7,9841013,0
31,8,24,9840512,0
32,9,25,9740000,0
33,9,26,9820000,0

As these data are imported, we want to be able to connect each person record to the
marriage record(s) it is related to in two ways. A person may be a spouse in one
marriage, and may be the offspring of another marriage. In each line of ASCII person
data is a unique identifier of the person, plus the identifier of the marriage of which this
person is the offspring. Hence it is possible to create up to two records for each line of
person data. As the person and marriage records are created or found, the offspring set
can be connected.
The loop through person.asc will cause all person and marriage records to be created,
and all offspring connections to be made. A loop through marriage.asc will allow each
10-16

Centura RDM Users Guide

marriage record to be found and updated with full information about the marriage. It
will also allow the husband and wife set connections to be made.
The following import specification demonstrates the update on and find on statements,
as it updates marriage information and creates husband and wife connections, both in the
second foreach loop.
database tree;
foreach "person.asc" {
record person {
create on 2;
field p_num = 2;
field p_last = 3;
field p_first = 4;
field p_birth = 5;
field p_death = 6;
}
record marriage {
create on 1;
}
connect offspring;
}
foreach "marriage.asc" {
record marriage {
update on 1;
field m_date = 4;
field m_term = 5;
}
record person {
find on 2;
}
connect husband;
record person {
find on 3;
}
connect wife;
}
end;

File Transfer Utilities (dbimp, dbexp)

10-17

Import Specification Language Definition


Import Specification
database dbname ;
foreach_loop
...
end ;
The database named dbname is opened, and all record, field, and set type names are read
into memory for verification against the names included in this specification. The
database is located with the DBDPATH and DBFPATH environment variables, if
defined. If there is an rdm.ini file in the current directory, it is used. Otherwise the
database dictionary and files are expected to be in the current directory. Then each
foreach_loop is executed in order.
Foreach Loop
foreach input_file {
import_statement
...
}

Read each line of ASCII text from input_file and make the text available to the import
statements enclosed in the loop. When an end-of-file is detected in input_file, exit the
loop and execute the next statement.
Import Statement
foreach_loop | record_statement | connect_statement

Note that a foreach_loop can contain a foreach_loop. This will cause an inner input_file
to be read and processed repetitively. Any number of import_statements may be
included within one foreach_loop.
Record Statement
record recname {
[ handling ]
[ field_statement ]
...
}

Depending on the handling, create record type recname, read it to be updated, or find a
previously created record instance. If field_statements are present, convert the ASCII
data into the proper types, and copy the values into the record.

10-18

Centura RDM Users Guide

Handling
create on field_number ;
or
update on field_number ;
or
find on field_number ;
If the handling is create on, search the created record index (CRI) for a record of the same
type and field value. If found, make the existing record the current of record type (CRT)
and do not create a new record and ignore any field_statements. If not found, create a
new record, enter its type and field value into the CRI, make it the new CRT, and
perform the following field_statements, if present.
If update on, search the CRI for a record of the same type and field value. If such a
record is found, read in the existing contents of the record and update them from the
following field_statements. Otherwise, create a new record and enter it into the CRI.
Make the record the CRT.
If find on, search the CRI for a record of the same type and field value. If found, make it
the CRT. Otherwise, nullify the CRT for this record type. Ignore any field_statements
that follow.
Field Statement
field field_name = [input_file.]field_number ;
Convert the ASCII data in field field_number into the type defined in the schema for field
field_name, and copy the value into the record being created.
If more than one foreach_loop level exists, data can be used from any active line of ASCII
text. The default text comes from the inner-most loop. To refer to other active lines of
text, precede the field number with the input_file. For example:
foreach "invoice.asc" {
...
foreach "item.asc" {
record item {
...
field inv_no = "invoice.asc".1;
field item_no = 1;
...

The field_name may be composed of a structure name and an element name, if the field is
in a structured field. The structure name and element name may be subscripted, if they
are defined as arrays.
If a partial specification is given (for example the structure name only, with no element),
the whole structure is implied. The field_number points to the first field that will be used,

File Transfer Utilities (dbimp, dbexp)

10-19

with the others immediately following. For example, a record type may be defined with
the following field:
struct {
char street[20];
char city[20];
long zip
} address;

Then, the following groups of statements are equivalent:


field street = 2;
field city = 3;
field zip = 4;
field address.street = 2;
field address.city = 3;
field address.zip = 4;
field address = 2;

Arrays are handled similarly. If a complete reference is given, only one field value is
used. If a partial reference is given, the field numbers following the field_number in the
statement are utilized to satisfy the assignment. Consider the following field definition:
struct {
int code;
long message[10];
int marker;
} packet[3];

The following examples demonstrate the number of input fields automatically


referenced:
field statement
field message = 2;
field message[3] = 5;
field packet[0].message = 2;
field packet[2].marker = 36;
field packet[1] = 13;
field packet = 1;

number of input fields


10
1
10
1
12
36

Character strings are treated differently than other types of arrays. The last dimension in
a character field definition represents the length of a string, which is read from just one
ASCII field. If a character field definition contains more than one dimension, it is
assumed to be an array (or matrix) of character strings. The only exception to this rule is
when the last dimension is one. This defines the field as binary data, which is to be
interpreted as hexadecimal data in the input text (see section 10.3.3, "Data Conversion").
An example multi-dimensional character string field follows:

10-20

Centura RDM Users Guide

char memo[20][80];

A field statement using only the name memo, with no subscripts, would imply that 20
fields would be read from an ASCII record, each containing strings up to 80 characters
long. If the statement used one subscript, then one text field would be read into the RDM
field. Using two subscripts with the name would be invalid.
Connect Statement
connect setname ;
Look up the owner and member types in the database dictionary. If the CRT table
contains database addresses of these types, make the owner type the current owner of set
setname, and make the member type the current record. Then perform a d_connect
function with set setname. If owner and member do not exist as the CRT, then do not
perform the connect. If the current record is already connected to the set, ignore the
connect.

10.3.3 Data Conversion


When an ASCII field is selected by a field statement to be assigned to an RDM field,
dbimp does two things. First, it scans the ASCII text until it finds the specified field and
makes a copy of the field. Second, it attempts to convert those ASCII characters into the
target data type.
Note: Full Unicode support in RDM requires that Unicode strings never be converted
internally into multi-byte or ANSI strings, even if they are subsequently converted back
to Unicode. To produce a Unicode file, use the -u flag in your field statement. For
further information about Unicode files, see Chapter 9.
To find the selected field number N, dbimp scans the input line, looking for N-1
separator characters (usually commas). A comma that appears within a set of quotation
marks or is preceded with an escape character (default "\") is not counted. The length of
a field spans from the character following a comma through the character preceding the
next comma. Blanks are significant. Quotation mark characters, if used, will define the
actual beginning and ending of a string, even if there are leading or trailing blanks. If a
field contains a number preceded by blanks, the blanks will be ignored. Null fields may
be represented by a pair of quotation mark characters or by adjacent commas.
After the field contents have been located and copied from the ASCII text, dbimp
converts it into the target type. If the target type is a character string, dbimp copies it
into the target field directly, truncating it if it is too long. If the target type is numeric, the
input field is given to the standard C library function called sscanf. The format
specification provided to sscanf depends on the target type. If the target type is a single
byte character, or an integer, short, or long, then the format will be %ld, which will
convert the ASCII field into a long variable. Then the long variable is shortened, if

File Transfer Utilities (dbimp, dbexp)

10-21

necessary, and assigned to the actual target data type. If the target type is float or
double, the format will be %lf, which will convert the string into a double type variable.
It is then assigned to the actual target data type.
Note: Single-byte character fields can be imported as their ASCII value in decimal or
octal or as the character. The standard C escaped characters are also supported.
Binary data is defined when the last dimension of a character field is 1. See the example
below.
char picture[256][1];

Since a standard C character string cannot be represented by one character, RDM will
interpret this type of definition as binary data without null terminators. The input string
expected by dbimp will consist of a string of hexadecimal values, two characters per
hexadecimal byte value, with no blanks between them. For example, to read the string
"Hello world" (including the null terminator) into a binary field 12 characters long, the
input field should be:
48656c6c6f20776f726c6400

The export utility, dbexp, will create this representation from any binary fields.

10.4 Using Export and Import Together


The export and import utilities have been designed to operate on the same intermediate
form of data: the ASCII text file. Because of this, it is possible to use the output of dbexp
as the input to dbimp. This process, called a database transfer, facilitates moving a
database to another computer. It also allows you to change a schema, although you will
find db_REVISE a more powerful tool for this task.
To perform either function, the combination of the ASCII data and the schema must
contain enough information to be able to fully reconstruct the database. Not all
information stored in a database can be retained through a transfer. Certain types of
information must be avoided if it is important to be able to transfer the database by using
dbimp and dbexp.
Note the following two restrictions concerning transferable databases:
1. dbimp cannot maintain the original set ordering for orders first, next, or last.
2. For all sets, the owner and member must be different record types.
RDM sets often contain vital information in their ordering. A set that is defined as "order
last" will often maintain a chronological ordering on the set members. A set defined as
"order next" will often have an ordering that is determined by an application program.
But, as noted above, dbimp will not maintain first, next, or last original set ordering.
Thus the first condition for a fully transferable database is that it does not depend on the

10-22

Centura RDM Users Guide

ordering of any of these types of sets. Both ascending and descending set types will be
transferred, because they are sorted during the d_connect call performed by dbimp.
Alternatively, you might consider using the ASCII file output capability of db_QUERY
for exporting your data. db_QUERY can maintain the original set ordering.
The second restriction exists because dbimp has no mechanism to perform connections
where both owner and member are the same type of record (recursive sets). Note that
these types of sets may exist in the database; they just cannot be re-connected during an
import.

File Transfer Utilities (dbimp, dbexp)

10-23

Chapter 11
Database Access Language (dal)
11.1 Introduction
The Database Access Language (dal) is intended as a tool for interactive or batch
manipulation of an RDM database.
dal allows you to execute a subset of the RDM runtime functions, either interactively at
your terminal, or in batch mode from a batch file. dal commands are the RDM runtime
functions (without the d_ prefix), plus a few additional commands. dal is an interpretive
language using variables that are defined as records, fields, database addresses, or
integers. The RDM functions are accessed by issuing statements very similar to the C
function calling conventions (with some exceptions, as noted below).

11.2 Using dal


You can activate dal either interactively or as a batch file.
To execute dal interactively:
1.

Type in the following command:


dal

2.

Then at the d_ prompt, begin typing dal commands.

To execute dal in a batch mode:


Write dal commands in a file (procfile), and use the filename as a parameter to
the following dal command:
dal procfile
Each supported RDM function can be called through dal by issuing a C-like command
(without the d_ ):
open("mydb","o");

Database Access Language (dal)

11-1

11.3 General dal Syntax


Commands can be entered into dal using a relatively free format. All dal commands
terminate with a semicolon. If you fail to type the semicolon, you may still be able to
type it on the next line, as dal usually will not process the command until it sees the
semicolon. dal recognizes C-style comments (/* this is a comment */). In addition, any
characters on a line after a pound sign (#) are ignored. You may place more than one
command per line, as long as each is terminated with the semicolon. String constants are
enclosed in double quotes. Escape sequences are not supported within strings.

11.4 Differences between dal and C Conventions


The syntax of dal is somewhat different from the standard C calling convention. You
need to be aware of these differences to avoid confusion, especially if you are using RDM
for the first time, and using dal to learn RDM. The differences are explained below.

Where the C calling conventions dictate a pointer argument, dal does not. Look at
the following example of an RDM C function call.
d_fillnew(person, &per);

The input to dal would appear as follows:


fillnew(person, per);

/* No & before per */

dal supports character array constants, but not numeric constants. If you need to
pass a numeric value to an RDM function, you must first assign the value to a
variable, and then pass the variable to the function call.

Where a database constant is passed to an RDM function, you may use lowercase
letters (for example, person instead of PERSON).

11-2

Centura RDM Users Guide

11.5 Supported RDM Functions


The following RDM functions are recognized by dal. No database number is allowed in
the parameters lists, because dal must operate on one database at a time.
Table 11-1. RDM Functions Recognized by dal
d_close
d_cmtype
d_connect
d_cotype
d_crget
d_crread
d_crset
d_crtype
d_crwrite
d_csmget
d_csmread
d_csmset
d_csmwrite
d_csoget
d_csoread
d_csoset
d_csowrite
d_ctbpath
d_dbdpath
d_dbfpath
d_dblog
d_dbtaf

d_dbuserid
d_delete
d_destroy
d_discon
d_disdel
d_fillnew
d_findco
d_findfm
d_findlm
d_findnm
d_findpm
d_freeall
d_initfile
d_initializ
d_ismember
d_isowner
d_keydel
d_keyexist
d_keyfind
d_keyfree
d_keyfrst
d_keylast

Database Access Language (dal)

d_keylock
d_keynext
d_keyprev
d_keyread
d_keystore
d_lock
d_makenew
d_members
d_off_opt
d_on_opt
d_rdcurr
d_recfree
d_recfrst
d_reclast
d_reclock
d_recnext
d_recprev
d_recread
d_recset
d_recwrite
d_renfile
d_rlbclr

d_rlbset
d_rlbtst
d_setfiles
d_setfree
d_setkey
d_setlock
d_setmm
d_setmo
d_setmr
d_setom
d_setoo
d_setor
d_setpages
d_setrm
d_setro
d_timeout
d_trabort
d_trbegin
d_trend
d_wrcurr

11-3

11.6 dal-Specific Commands


This section describes how variables are defined for dal and explains the dal-specific
commands that help make the utility more useful as a learning and prototyping tool.

def_rec, def_fld
Variables are defined in one of two ways:
Implicitly :
A variable can be created from the context of a statement. The statement below
causes a variable named "per" to be defined as the same type as the current record.
keyfind(pers_name,"Norm");
recread(per);

The next statement causes a variable named "addr" to be defined as a field with the
same type as the "pers_addr" field in the schema.
crread(pers_addr,addr);

The following statement causes a variable named "dba" to be defined as type


DB_ADDR.
crget(dba);

Explicitly :
Two functions are provided to explicitly create and type record or field variables:
def_rec(rec_type,var_name);

or
def_fld(fld_type,var_name);

def_rec creates a variable (named var_name) that is defined with the same type as
the record specified by rec_type. def_fld creates a variable (named var_name) that is
defined with the same type as the field specified by fld_type.

11-4

Centura RDM Users Guide

abort
Exit dal immediately without closing database

Summary
abort;

Description
This command causes dal to stop immediately without closing the database. Any data
remaining in the RDM cache will not be written to the database. If you have created only
a few changes or additions (such that all the data fits into the cache), then none of your
work will be saved. However, be aware that indiscriminate use of the abort command
can lead to database corruption in the event that some changes get written to disk while
the remaining are lost when you abort. You must be concerned about this only if you are
not using transactions.

curr
Print the currency tables.

Summary
curr;

Description
This command causes dal to print out the currency tables, showing current database,
current record, and current owners and members for each set.

exit
Exit dal.

Summary
exit;

Description
This command calls d_close to close the database, and exit with a code of zero (that is,
call exit).

Database Access Language (dal)

11-5

input
Read values into a variable.

Summary
input [(filename)] var_name [,var_name ]...;

Description
This command reads variable values from the keyboard or a file. If a variable is a record,
then the individual field values will be requested with separate prompts. If a file name is
specified for input, one line from the file will be read for each variable listed. File names
must be enclosed in quotes. Fields within a line are in fixed format with the following
lengths for different field types:
Char

Length specified in schema

int

short

long

10

float

10

double

10

Note that these widths are the same as those created by the print command.

Examples
open("tims","o");
def_rec(author,a);
input a;
fillnew(author,a);
input ("auth.imp");
fillnew(author,a);

/* Get data from terminal */;


/* Get data from file */;

Diagnostics
Errors can occur when input reads from a file and the line lengths in the file are
inconsistent.

11-6

Centura RDM Users Guide

print
Print values from a variable list.

Summary
print [(filename)] var_name [,var_name ...];

Description
This command prints one line of data to the terminal or to a file. If a variable is a record,
then the individual field values will be printed, with no spaces between the values, each
field width being determined by the field type (see table under input). Literal strings
may be included in the var_name list. If a file name is specified for output, one line will
be written to the file for each print command. File names must be enclosed in quotes. If
an output file is used within an input command, the file is re-opened for input.

Examples
open("tims","o");
findfm(author_list);
recread(a);
print "author:",a;
crget(dba);
print("author.lst") "dba:",dba,"author:",author;

rewind
Rewind (or reset back to the beginning of) a file.

Summary
rewind "filename";

Description
This command rewinds a file. If the file was opened for reading, then subsequent reads
will start from the beginning (that is, the first line will be reread). If the file was opened
for writing, it will be truncated and all previous data will be lost.

Database Access Language (dal)

11-7

schema
Print schema information.

Summary
schema [spec];

Description
This command prints information about a database schema, including the record types,
field types, and set information. The schema command with no arguments produces a
list of the record names and set names. If spec is a record, then detailed information
about the record is printed, including a list of the fields, and the field information for
each field. If spec is a field name, then the type and length is printed. Additionally, if the
field is a key, then the kind of key, and the key file containing the key is printed. If spec is
a set name, then order, owner type, member type(s), and sorting information is printed.

whileok
Repeat statements while (db_status == S_OKAY).
Summary
whileok {
statements;
.
.
}

Description
This command functions in the same manner as the following C code:
while (db_status == S_OKAY) {
statements;
...
}

Note that whileok statements can be nested.

11-8

Centura RDM Users Guide

Examples
/* List all authors and their publications */
open("tims","o");
findfm(author_list);
whileok {
recread(a);
print "Author:",a;
setor(has_published);
findfm(has_published);
whileok {
recread(b);
print "Published:",b;
findnm(has_published);
}
findnm(author_list);
}

11.7 dal Limitations


The following is a list of RDM functions and functionalities not supported by dal:

Group locking function (that is, d_lock())

Timestamping functions

Currency functions (d_rdcurr(), d_rerdcurr(), and d_wrcurr())

File rename functions (d_renfile() and d_renclean())

Alternate initialization file location (d_rdmini())

In addition,

dal does not support multiple databases.

dal does not support arrays.

Database Access Language (dal)

11-9

Chapter 12
Database Editor (dbedit)
12.1 Introduction
The low-level database editor (called dbedit) allows any RDM database to be changed
and repaired by an operator who is trained in its use. Anyone who uses dbedit must be
familiar with the binary format of RDM data files as described in Chapter 14, "File
Formats and Dictionary Tables."
Caution: Improper use of dbedit can cause severe damage to a database.
dbedit, together with dbcheck, is most useful for finding and correcting errors in set
pointers and other overhead fields. Also, if any corruption exists in page zero of a data
file, dbedit can correct it. All other areas of database update or repair should be handled
through the runtime library, or through ida, dchain, or keybuild. For example, dbedit
can alter the value of a data field, but it is best to use ida for such a task because ida will
maintain database consistency (for example, by changing a key value to match the
changed field).
dbedit can perform updates to a data file regardless of the internal consistency of the file.
While the runtime library and ida must be able to successfully open a full database,
dbedit can operate on a file-by-file basis, and will not assume that any fields in the data
file are valid.
dbedit is line-oriented, instead of full screen-oriented. It is driven by a set of commands
that are read from standard input, and will print all information to standard output.

12.2 Usage of dbedit


To edit a database, the database must reside in the current directory. The following
command will invoke dbedit:
dbedit dbname
If dbedit finds a file named dbname.dbd, it will read the dictionary into memory and
respond with the prompt:
dbedit>

If a system record exists, it will become the initial current record. If no system record
exists, the initial current record will be database address [0:1]. If no records exist in file 0,
there will be no initial current record.
Database Editor (dbedit)

12-1

Because of the low-level nature of dbedit, it will not use the RDM environment variables,
such as DBDPATH. Nor will it use the rdm.ini file.
dbedit operates in one of two modes: interpreted or non-interpreted () modes. In the
interpreted mode, dbedit will display a records contents according to its type. It
displays set and member pointers in our standard database address representation. It
indicates whether optional keys are set, and displays field values in the format used by
ida. Navigation with dbedit means moving from one record to another. There will
almost always be a "current record." Edits made to a record will be written to the file
when the editor moves to a new current record.
The non-interpreted mode is entered by typing:
dbedit> edit hex

which responds with the prompt:


hex>

In this mode, no notion exists of current record. All data is displayed and edited as
hexadecimal bytes. All edits are written to the data file when the hex edit mode is ended.

12.3 Information Display


Three commands are available to print dbedit or database information:
help
display
show
The help command prints a short list of dbedit commands.
help | ?
This command lists the current file name and current records database address. It does
not list the hex edit commands unless in hex edit mode.
The display command displays the current record.
display [type | dba | ts | opt | set [setname] | mem [setname] | fld [fldname]]
The current record is displayed in a format that shows both the hexadecimal and textual
representation of the record. The textual display is similar to that used by ida or
datdump. An example is shown in Figure 12-1.
The scope of the display may be restricted by adding a second keyword to the command.
Each keyword represents one section of the full record display, and will cause only that
section to be displayed. These subsections are:
type

12-2

The record type

Centura RDM Users Guide

dba

The record database address

ts

The record creation and update timestamp

opt

The optional key bit map

set

The set owner pointers

mem

The set member pointers

fld

The data fields

005344: 01 00

Record Type
INFO (1)

005346: 12 00 00 01

Database Address
[1:18]

005350: 00 00 00 00 00 00 00 00 00 00 00 00
005362: 00 00 00 00 00 00 00 00 00 00 00 00
005374: 01 00 00 00 29 00 00 01 29 00 00 01
005386: 02 00 00 00 1d 00 00 00 1e 00 00 00

005398: 01 00 00 01 28 00 00 01 13 00 00 01
005410: 00 00 00 00 00 00 00 00 00 00 00 00

005422: 64 62 30 30 31 00 00 00 00 00 00 00
00 00 00 00
005438: 46
61
67
50
00
00
00

6f
74
65
72
00
00
00

75
69
73
69
00
00
00

72
6f
20
6e
00
00
00

74
6e
56
63
00
00
00

68
20
6f
69
00
00
00

2d
4c
6c
70
00
00
00

47
61
20
6c
00
00
00

65
6e
31
65
00
00

6e
67
20
73
00
00

65
75
2d
00
00
00

72
61
20
00
00
00

005518: 50 72 65 6e 74 69 63 65 2d 48 61 6c
6c 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
005550: 31 39 38 35 00 00 00 00 00 00 00 00
005562: 00 00

Set Owner Pointers (C/F/L)


0 [0:0] [0:0]
ARTICLE_LIST
0 [0:0] [0:0]
LOANED_BOOKS
1 [1:41] [1:41]
ABSTRACT
2 [0:29] [0:30]
INFO_TO_KEY
Set Member Pointers (O/P/N)
[1:1] [1:40] [1:19]
HAS_PUBLISHED
[0:0] [0:0] [0:0]
ARTICLE_LIST
Field ID_CODE
db001
Field INFO_TITLE
Fourth-Generation Language
s Vol 1 - Principles

Field PUBLISHER
Prentice-Hall
Field PUB_DATE
1985
Field INFO_TYPE
0

Fig. 12-1. Display of Current Record

Database Editor (dbedit)

12-3

In addition, the set, mem, and fld keywords may be further restricted with the name of
one owner set, member set, or field.
The show command displays schema information, such as lists of sets, records, or keys.
show {fld [fldname] | file [filename] | key [keyname] | record [recname] |
set [setname]}
The show fld command lists all fields in the database, or, if fldname is given, shows that
field only.
The show file command lists the names of all files in the database, or, if filename is given,
shows the record types or key types contained in the file.
The show key command lists all keys in the database, or, if keyname is given, shows that
key only. Each key will be displayed as a field.
The show record command lists the names of all record types in the database, or, if
recname is given, shows that record type in the format shown in Figure 12-2.
Record Type: INFO (1)
Contained in file: tims.d02
Record Length: 220
Offset to Data: 78
Flags:
Fields:
unique key char ID_CODE[16]
char INFO_TITLE[80]
Flags: SORTFLD
char PUBLISHER[32]
char PUB_DATE[12]
int INFO_TYPE

Fig. 12-2. Show Record Info


The show set command lists the names of all set types in the database, or, if setname is
given, shows that set type in the format shown in Figure 12-3.
Set Type: HAS_PUBLISHED (1)
Order: Ascending
By Field(s): INFO_TITLE
Owner: AUTHOR (0)
Member(s): INFO (1)
Flags:

Fig. 12-3. Show Set Has_published

12-4

Centura RDM Users Guide

12.4 Navigation
Movement through the database is accomplished with the goto command. This
command is used to set the current record and has several forms.
goto {dba | nextrec | prevrec }
goto {first | last} setname
goto {own | prev | next} setname
goto {file {filenum | filename}}
The most basic goto command allows you to set the current to a specified database
address as shown in the following example:
goto 2:345

The goto nextrec and goto prevrec commands allow you to move sequentially through
the current data file one record slot at a time. If the current record is the first record in a
file, then goto prevrec will produce an error message, and the current record will remain
unchanged. If the current record is the last record in a file, then goto nextrec will also
produce an error message, and the current record will remain unchanged.
Set pointers contained in the current record may be referenced to set the current record to
the first or last member using the goto first and goto last commands. The specified
setname must be a set for which the current record is an owner.
Set member pointers contained in the current record may be referenced to set the current
record to the owner (goto own), next (goto next), or previous (goto prev) member of the
specified setname.
If an invalid slot is formed by any of the above forms of the goto, an error is printed, and
no action is taken. It is legal to go to a database address that is beyond the current size of
a data file. Such a record is initially filled with zeroes unless the file already has readable
contents at the selected location. A warning message is printed if a selected slot is more
than two pages beyond the current end of the database (as indicated in page zero).
A data file may be selected with the goto file command. It may be selected by specifying
either a file number or file name. When a new file is selected, there will be no current
record. A goto nextrec will select the first record, and goto prevrec will select the last
record. Until there is a current record, only the page zero of the file may be edited.

Database Editor (dbedit)

12-5

12.5 Editing
The edit command is used to specify that a portion of the current record slot or page zero
is to be modified. All edits are performed in memory and are reflected in subsequent
display commands. An edited record is written to the database on execution of a
following goto or exit command. Unwanted edits on the current record may be
discarded by issuing a reread command. The complete syntax of the edit command is
shown below.
edit type
edit {first | last | count} setname
edit {own | prev | next} setname
edit dba
edit opt
edit {dchain | nextslot}
edit hex

12.5.1 Editing Record Types


The edit type command allows you to alter the record type identification number. The
current type is printed (both numerically and symbolically). The new record type may
be entered as a number or name. All subsequent displays and interpretations of the
current record are based on the new type. The record type must be one that is included
in the current file, or the display command is unable to display the record.
The record type may contain an embedded record lock bit (RLB). The bit will show in
the numeric display as a 40 in the high-order byte of the record type. Textually, the
notation "- RLB" will appear following the name of the record type. The RLB may be
cleared by entering a new (or the same) record type. It may be set by entering 40 as the
high-order byte of the type.

12.5.2 Editing Set and Member Pointers


Individual parts of the set and member pointers may be edited by naming the part (for
example, count or next) and set name, setname.
The current value is displayed. The new value may be entered in the standard database
address format as shown in the following example:
dbedit> edit first author_list
Current value is [1:15]
New value? 1:18
dbedit>

If no change is desired, simply press <Enter>.

12-6

Centura RDM Users Guide

12.5.3 Editing the Database Address


The database address portion of a record (bytes 2-5) may be edited using the edit dba
command. The existing database address value is printed. The new value may be
entered in standard database address format.
If the current record slot is a deleted record, the database address portion contains the
slot number of the next slot on the delete chain. Because this is not a database address
but a slot number, edits to delete chain entries should be specified with file number 0 (for
example, 0:25).

12.5.4 Editing the Optional Key Bits


When an optional key is stored, a bit is set in the data record to represent its presence in
the key file. These bits may be changed using the edit opt edit command. The bit map
(in hexadecimal) is displayed together with the names of all optional keys in the record
type. Beside each key name is a notation indicating whether the key is stored
(- STORED) or not (- NOT STORED):
dbedit> edit opt
40
PUBLISHER - NOT STORED
INFO_TYPE - STORED
New value?publisher,info_type

The new value may be entered as a bit map (in hexadecimal), or as a list of the key names
(comma separated) that are to be set. Note that any changes performed here will require
the use of keybuild in order to make the data files consistent with the key files. In the
above example, both the publisher and info_type optional key flags will be set.

12.5.5 Editing Page Zero


The first two long integers in page zero of the current file (the file containing the current
record) may be edited using the edit dchain and edit nextslot commands. Both of these
commands display the current value and prompt for the new one. They are written to
the file immediately. Note that the values are slot numbers, not database addresses, and
do not take file numbers.

12.5.6 General Hexadecimal Editing


To allow the operator to make changes to the database not covered in other commands,
dbedit provides the ability to edit a file as a stream of hexadecimal bytes. In this mode
you can:

Display any number of lines in both hexadecimal and ASCII

Move to any byte position in the file

Search forward and backward for a pattern

Replace characters on a byte-for-byte basis in either hexadecimal or ASCII

Database Editor (dbedit)

12-7

The hexadecimal editing mode is initiated by entering the edit hex command. When in
this mode, the prompt is changed to:
hex>

To exit the hexadecimal edit mode, enter the command:


hex> end
dbedit>

When hexadecimal edit mode is entered, changes that were made to the current record
are written to the database, and the current position in the file becomes the file address of
the current record. The changes made in hexadecimal edit mode are written to the
database by the end command. To cancel the changes and return to dbedit mode, enter
cancel.
After ending hexadecimal edit mode, the current record is returned to its original slot,
unless the current file position lies within a different record, in which case dbedit will
prompt you to see if your current record should be changed to this new position, or if
you want to return to the original current record.
Table 12-1 describes the commands that can be used in hex edit mode.
Table 12-1. Hex Mode Commands
Command

Definition

print N

Print N lines (both hexadecimal and ASCII representation).


If N is absent, print one line.

+N

Move forward N characters. If N is absent, move one character.

-N

Move backward N characters. If N is absent, move one character.

=N

Move to address N, where N is a hexadecimal number between 0


and FFFFFFFF.

>N

Move forward N lines. If N is absent, move one line.

<N

Move backward N lines. If N is absent, move one line.

>>STRING

Search forward for STRING. STRING may be either an ASCII string


within quotes ("string"), or hexadecimal bytes (73 74 72 69 6E 67).

<<STRING

Search backward for STRING.

write STRING

Write STRING into current position.

cancel

Erase all edits since entering hex edit mode.

end

End hex edit mode.

help

Print a short list of these commands. Alias is ?.

12-8

Centura RDM Users Guide

12.6 Diagnostics
Illegal changes to a database will be screened, whenever possible, before they are made.
For example, if a record type is changed to a type not contained in the current file, the
change will not be allowed (except in hexadecimal edit mode).
Since dbedit allows updates to set instances, it will be important to know if a change has
corrected a problem in the chain of database addresses forming the set instance. For this
purpose, the verify command can be used to traverse an entire set instance to check
owner, previous, next, first, and last pointer consistency. It will perform a check similar
to that done by the dbcheck utility. The name of the set must be identified with the
following command:
verify setname

12.7 Miscellaneous
The exit command will end your dbedit session. If the current record was modified, it is
written to the database before exiting.
The reread command causes the current record to be read from the database. This has
the effect of canceling any updates made to the record in the buffer.
To eliminate the titles in the display output, the notitles command can be issued. The
resulting output is shorter, but readable to the experienced operator. By default, titles
will be printed. The titles command can be used to cancel the notitles command.
To eliminate the data fields in the display output, the nofields command can be issued.
The resulting output will only contain the overhead information (record type,
DB_ADDR, set pointers, etc.). This can be useful when the data in the record is correct,
but there are problems with the overhead information. By default, fields will be printed.
The fields command may be used to cancel the nofields command.
All database addresses and counts will be displayed in decimal format unless otherwise
requested. To change the display format, the base command may be issued.
base {10 | 16}
Only base 10 (decimal) and base 16 (hexadecimal) are recognized.
Any editor command or keyword may be abbreviated to a non-ambiguous set of
characters. If more than the required number of characters is entered as a command,
they must correctly spell the intended command. If an ambiguous set of characters is
entered, an error message is displayed stating that more characters must be entered.

Database Editor (dbedit)

12-9

12.8 Command Summary


A syntax summary for each of the dbedit commands is shown in the table below.
base {10 | 16}
display [type | dba | ts | opt]
display {set [setname] | mem [setname] | fld [fldname]}
edit type
edit {first | last | count} setname
edit {own | prev | next} setname
edit {dba | opt | dchain | nextslot}
edit hex
exit
goto {dba | nextrec | prevrec }
goto {first | last | own | prev | next} setname
goto {file {filenum | filename}}
help | ?
nofields
notitles
reread
show {field [fieldname] | file [filename] | key [keyname]}
show {record [recordname] | set [setname]}
fields
titles
verify setname

12-10

Centura RDM Users Guide

Chapter 13
Maintenance Utilities
13.1 Introduction
This chapter describes the use of additional utility programs that are part of the basic
RDM system. These utilities support database maintenance and administration tasks.
They are listed in Table 13-1 below.
Table 13-1. RDM Utilities
Utility

Definition

datdump
dbcheck
dchain
initdb
keybuild
keydump
keypack
prdbd
dbclrlb

Formatted Data File Dump Utility


Database Consistency Check Utility
Delete Chain Sort Utility
Database Initialization Utility
Key File Build Utility
Formatted Key File Dump Utility
Key File Packing Utility
Database Dictionary Print Utility
Clear Lock Bit Utility

13.2 Formatted Data File Dump Utility (datdump)


The datdump utility displays a formatted dump of the contents of an RDM data file. In
addition to the data field contents, datdump displays all of the information in the record
header, including the record id, database address, record lock bit setting, stored optional
keys, timestamp values, set pointers, and member pointers.
This utility is particularly useful in gaining an understanding of the structure of an RDM
data file as described in section 14.2.2, "Data File Organization." The datdump utility is
executed as follows:
datdump [-h] [-x] [-f] [-rslotno] dbname datfile
where datfile is the name of the data file in database dbname whose contents will be
displayed. If the -h option is specified, only the record header information is printed. If
the -x option is specified, the report produces a hex dump but no formatted dump of

Maintenance Utilities

13-1

each record. If the -f option is specified, a formatted dump is printed but no hex dump is
printed. If none of these options are specified then the result is a full dump including
header, data fields, and hex record dump. The -r option can be used to instruct datdump
to dump only the contents of the record at the specified slot number, slotno, in datfile. The
report is written to file stdout and can be redirected as needed.

13.3 Database Consistency Check Utility (dbcheck)


The dbcheck utility checks the consistency of a database by validating the location and
key values associated with each record and key in the data and key files. The position of
each record in a data file is verified, and each key field is checked to ensure that it exists.
For each key in a key file, the key field contents in the associated record are checked to
ensure that they match the data stored in the key file. (The consistency of optional key
fields can only be guaranteed for optional keys that exist; missing optional keys cannot
be reported.) All locked record occurrences (that is, set Record Lock Bits) will also be
reported by dbcheck.
The dbcheck utility can (optionally) perform set consistency checking. Set membership
consistency verifies that:
1.
2.
3.

The member and owner record types are valid


The membership count is correct
The doubly linked lists are properly formed

Key file structure consistency checks performed (optionally) verify that:


1.
2.
3.
4.

All B-tree pages are either in the B-tree or are deleted


All B-tree null child pointers are at the same tree level
B-tree key order is correct
Duplicate keys are correct

In addition, dbcheck can also verify the consistency of timestamps.


The dbcheck utility has several parameters (see Chapter 2, "Utility Descriptions," of the
RDM Reference Manual for the full definition), but the most common method to invoke it
is shown below:
dbcheck {[-s] [-k] [-dk] [-kd] [-a][-ts] [-r#] [-p#] [-f#] [-t] [-c] } dbname [dbfile...]
The name of the database to be checked is dbname, and dbfile is the name of one or more
files within dbname to be checked. If no files are specified, the consistency of the entire
database is checked. The -s option enables the checking of set consistency. The -k option
performs key file structure checking. The -dk option checks that the key file contains the
key for each key field in each data file. The -kd option checks that a record exists for each
key in each key file. The -ts option performs timestamp consistency checks. All of these
options are turned on by the -a option.

13-2

Centura RDM Users Guide

The -r# option reports every # percentage completed to file stderr. The -p# option sets
to # the number of pages in the cache for use by dbcheck. The -f# option sets to # the
number of open files for dbcheck. The -t option prints a traceback of the B-tree when a
key file inconsistency is detected. The -c option prints a count of the objects scanned in
the check.
Database inconsistencies will be reported with a message describing the nature of the
error and the database address of the record involved in the inconsistency.

13.4 Delete Chain Sort Utility (dchain)


The dchain utility sorts the deleted record slots on the delete chain into database address
order. The purpose is to increase the probability that newly created records in the same
file will be placed close together. The extent of any performance improvement, however,
will depend upon the application. Its most likely use would be after a periodic purge of
particular record types that tend to be entered together, as they would leave many
contiguous record slots on the delete chain. This utility is invoked as follows:
dchain dbname [dbfile]
where dbname is the name of the database and dbfile is the name of one or more data files
in dbname whose delete chain is to be sorted. If no files are listed then all data files in
dbname will be processed.

13.5 Database Initialization Utility (initdb)


A database must be initialized before any data can be stored in it. This initialization can
be done dynamically through function calls, through use of ida, or by using utility
initdb. Execute initdb as follows:
initdb [-y] dbname
where dbname is the name by which the database to be initialized is defined in the
database statement in DDL specification. The program will display the names of the
database files and prompt you for confirmation. If you reply with a y, then the files are
reinitialized; otherwise the program terminates. If the -y option is specified, then
initialization will proceed without displaying the file names and confirmation prompt.

13.6 Key File Build Utility (keybuild)


Utility keybuild will rebuild all key files for a database. It rebuilds the key files by first
reinitializing the file, and then sequentially reading all records from each data file and recreating each key field from the contents of the record.

Maintenance Utilities

13-3

The keybuild utility can be used to re-create the key files when there is a key file
inconsistency (for example, as reported by dbcheck). It can also construct new key files
after you have added or removed key attributes from fields in your DDL specification.
For example, if you make an existing key field a non-key, or change a non-key to a key
field in your DDL, you can run keybuild to rebuild the key files for the new schema.
You can also use keybuild to reassign key fields to different key files.
Optional keys are re-created by keybuild from the optional key stored bit flags contained
in the record header. To run keybuild, enter the following command line:
keybuild dbname
where dbname is the name of the database whose key files are to be rebuilt.

13.7 Formatted Key File Dump Utility (keydump)


Utility keydump will display a formatted dump of a database key file. The B-tree
organization of an RDM key file dump is described in section 14.2.3, "Key File
Organization." keydump can assist you in learning how these files are structured. It is
invoked as follows:
keydump [-h] dbname keyfile
where keyfile is the name of the key file in database dbname whose contents will be
displayed. If the -h option is specified, the key values are printed in hexadecimal;
otherwise the contents are displayed as formatted for the data type of the key field. The
report is written to standard output and can be redirected as needed.

13.8 Key File Pack Utility (keypack)


B-tree sorting algorithms allow for dynamic insertion and deletion of keys in B-tree
nodes (see section 14.2.3, "Key File Organization"). It is the nature of these algorithms to
leave approximately 20 to 30 percent of the file unused. For applications that have
frequent key updates, this is required overhead. Other applications may build their key
files first, then use them primarily for lookups. In such applications, where the keys will
not be changing, it is possible to run keypack to fill each node in the B-tree, thereby
reducing the number of nodes required in the key file. This results in significant savings
in disk space and lookup times in large databases.
The keypack utility has several parameters (see Chapter 2, "Utility Descriptions," of the
RDM Reference Manual for the full definitions). The utility is invoked as follows:
keypack [-unum] [-o|-x] [-t path] [-b path] [-k path] [-pnum] [-mx] dbname [keyfile]
where dbname is the name of the database whose key files are to be packed. All key files
will be packed unless a specific key file, keyfile, is specified. The -u option specifies the

13-4

Centura RDM Users Guide

number of key slots per node to be left unfilled. If the key file is to be modifiable, num
must be 1 or greater (default is 1). If num is 0, the key fields contained in the key file
must all be declared in static records (see section 4.2.5, "Record Declarations").
Option -o opens the database in one-user mode; option -x opens the database in exclusive
access mode. Option -t specifies the location (path) of the temporary packed key file.
When finished, the original key file is deleted and the temporary packed key file is
renamed to the original key file name.
Option -b specifies the path where a backup of the original key files will be copied.
Option -k specifies the path where the packed key files will be placed. Option -p sets
pages in the RDM cache to num.

13.9 Database Dictionary Print Utility (prdbd)


The prdbd utility displays the contents of the database dictionary file (dbname.dbd).
prdbd will report the default database page size and each entry in the file table, record
table, field table, set table, member table, sort field table, and key table.
Section 14.3, "Database Dictionary Table Structure," describes in detail the organization of
an RDM dictionary. This utility can be used to help you understand and make use of the
dictionary in your own applications.
To run prdbd, enter the following command:
prdbd [-c] dbname
where dbname is the name of the database whose dictionary will be displayed. Option -c
specifies that symbolic names be omitted from the report. The report will be written to
standard output and can be redirected as desired.

13.10 Clear Lock Bit Utility (dbclrlb)


The dbclrlb utility clears any set lock bits in the specified data files. If no data files are
specified, all lock bits in the database are cleared, including those on deleted and
undeleted records.
To run dbclrlb, enter the following command:
dbclrlb dbname [data_files]
where dbname is the name of the database whose lock bits will be cleared. All files will be
cleared unless files are specified with data_files.

Maintenance Utilities

13-5

Chapter 14
File Formats and Dictionary Tables
14.1 Introduction
This chapter describes in detail the physical organization of RDM data and key files, the
structure of the runtime dictionary and currency tables, and some source code
implementation details. Although an understanding of this information is not necessary
to make effective use of RDM, it can be helpful in making better use of the system.
You may want to write utilities or functions that use this information. For example, the
file structure information could allow you to write utilities that can read through a database and update all occurrences of a certain field type. Please note, however, that while
the RDM runtime is in operation, it is not safe for an application to directly change any
database file other than through the use of RDM functions. Any updates to RDM files or
global tables during runtime execution are made at your own risk.
The information in this chapter can also be useful when making decisions about the
design of a database, since the trade-offs will be better understood. Licensed source code
users will be able to use this information to better understand the source code.

14.2 Database File Organization


This section describes the structure of RDM files. Certain properties of all RDM files are
the same; these are discussed in section 14.2.1, followed by individual descriptions of
RDM data and key files.

File Formats and Dictionary Tables

14-1

14.2.1 General File Structure


Figure 14-1 shows the units of storage used by RDM. A database is composed of one or
more files. A file contains one or more pages. Each page is divided into equal numbers
of slots, which contain records (in a data file) or keys (in a key file).

Database

File

Page

Slot

Fig. 14-1. Units of an RDM Database


All RDM files are viewed as an array of fixed-length pages. The length of a page may
vary from file to file, but within each file, all pages are the same length. All RDM
database input and output reads and writes full pages of data, even though the user level
functions operate on records and keys.
Table 14-1. Page Zero Contents
Offset
0
4

Length
4
4

Name
dchain
next

Contents
Head of the delete chain
Next available space in the file

timestamp

Next timestamp value

12

cdate

Database creation date and time

16

bdate

Last database backup date and time

20

21

version

Version of RDM software (in ASCII)


that created the file.

Pages are numbered, starting with page zero. Page zero is the file header, which only
stores file status information. No user data is stored in page zero of any file. Because of
this, the contents of page zero after the bdate field are subject to change without notice.
Table 14-1 identifies the contents of page zero.

14-2

Centura RDM Users Guide

Byte
offset
0
20

dchain

timestamp

next

R D M

5 . 0 . 0

cdate

bdate

[ 0 1 - F e b - 2 0 0 0 ]

Fig. 14-2. Page Zero


The first four bytes of all pages numbered one and above contain a long integer which
serves as a date/time stamp of the last time the page was updated and written to the
database. The remainder of each page is divided into equal-length slots. The size of the
slots is based on the maximum record or key size that must be stored in the file. Figure
14-3 shows the general layout of one RDM file.
Page

header

update time

update time

update time

reserved

slots

slots

slots

Fig. 14-3. RDM File Structure


The fixed-length scheme of structuring pages and slots may create some wasted space in
a file (see section 4.4.2, "Physical Design Considerations"), but its benefits in performance
and simplicity outweigh this concern. Calculations to locate the exact page and slot
number of a record are quick, and management of the space left by record deletions is
simple. Because the disk space never becomes fragmented, there is rarely a need to
reorganize a database for the purpose of compacting records. New pages are either
allocated from the end of each file (next) or from a chain of deleted (dchain) data file
record slots or key file pages.

14.2.2 Data File Organization


This section discusses the characteristics of an RDM file that is designated for storage of
data records. All characteristics of the general file structure (see section 14.2.1, "General
File Structure") apply in addition to those discussed here.
In a data file, the first two page zero entries contain record slot addresses. Individual
record slots are allocated from the delete chain or from the end of the file. The dchain
entry points to the first record slot on the delete chain and the next entry contains the
number of the next available slot at the end of the file.

File Formats and Dictionary Tables

14-3

Database Addresses
Every record slot within a database is uniquely named and addressed by a four-byte
structure called a database address. A database address is composed of a file number
and a slot number. Figure 14-4 shows the structure of a database address.

sl ot

file

Fig. 14-4. Database Address


The file number is an unsigned value between zero and 255 and identifies the file where
the record is stored. It is used as an index into the file table, discussed in section 14.3.2,
"File Table." The slot number is an unsigned value between one and 16,777,215 (there is
no slot zero). This establishes the maximum number of records that can be stored in one
file (with a three-byte slot number). Note that the number of slots can be increased by
reassigning the bits used for the file number and slot number. This would decrease the
maximum number of files that could be referenced.
Slot number zero does not exist and hence is used as a null database address value. By
convention, both the file and record numbers are set to zero (0L) to indicate that a
database address variable does not point to any valid record.
Whenever a record is created, it is assigned to a slot, and given the slots database
address for its lifetime. The database address of a record occurrence will not change.
Given a database address, the physical location on the file can be calculated directly. The
file number portion of the database address is used to obtain the number of slots per
page (slots_per_page), the slot size (slsize), and the page size (pgsize). The page is
calculated as:
page = ( (slot number - 1) / slots_per_page ) + 1
and the offset within a page is:
offset = slsize * ( ( slot number - 1 ) % slots_per_page ) + 4
where the addition of four is required because of the four-byte update date/time at the
beginning of the page.
The physical address then becomes:
address = page * pgsize + offset.
In the remainder of this chapter, we will use the following notation for database
addresses: [file number:slot number]. For example, [3:35] will refer to slot 35 in file
number 3. A null database address, then, is [0:0]. In figures, the brackets will be left off.

14-4

Centura RDM Users Guide

Set and Member Pointers


The implementation of variable-length sets using fixed-length records is accomplished by
creating linked lists of database addresses. Record types that are owners of sets will
contain within each record a 12-byte area (or 16-byte if timestamped), which uses database addresses to point to the first and last members of the set, and which contains a
count of the members. These 12- or 16- byte segments are referred to as set pointers. For
each set type owned by the record type, one set pointer will exist in the record header.
Table 14-2 shows the structure of set pointers.
Table 14-2. Set Pointer Contents
Offset
0

Length
4

Contents
Count of members in set

Database address of first member

Database address of last member

12

Optional last update timestamp

member count

first member

last member

12
update timestamp

Fig. 14-5. Set Pointer


If the count field in the set pointer is zero, then the set instance owned by the record is
empty (it has no members).
When a record type is the member of one or more sets, it will contain a 12-byte member
pointer for each set of which it is a member. A member pointer contains the database
addresses of the owner record, previous member record, and next member record. Table
14-3 shows the structure of a member pointer.

File Formats and Dictionary Tables

14-5

Table 14-3. Member Pointer Contents


Offset
0

Length
4

Contents
Database address of owner record

Database address of previous member

Database address of next member

4
owner

previous member

next member

Fig. 14-6. Member Pointer


Figure 14-7 shows the logical structure of a set instance containing three members.

Fig. 14-7. Three Member Set Instance


Since the members of a particular set can be of different record types, the member record
occurrences may reside in different files. Figure 14-8 shows a possible physical
arrangement of the same set instance. This example shows that the owner record and
first member record are on the same file. They may or may not be the same record types.
The second and third member records are in a different file and therefore must be
different record types.

14-6

Centura RDM Users Guide

file 3

owner record
slot 35

file 7

3:258

7:650

3:35

3:258

7:650

member record 2
slot 116

3:35

0:0

7:116

3:35

7:116

0:0

member record 3
slot 650

member record 1
slot 258

Fig. 14-8. Physical Structure of Set Instance

Data Record Organization


When a record is written to a database slot, it contains much more than just the field
values. Table 14-4 shows the structure of a record.
Table 14-4. Record Contents
Offset
0

Length
2

Contents
Record type (index into record table)

Database address of this record

Creation timestamp (if timestamped)

10

(table)

variable

One-byte set of optional key flags for every eight


optional keys declared in record

(table)

variable

12- or 16-byte sets of set pointers

(table)

variable

12-byte sets of member pointers

(table)

variable

Field values

File Formats and Dictionary Tables

Last update timestamp (if timestamped)

14-7

bit 0: delete flag


bit 1: record lock bit

Byte
offset
0

id

database address

creation timestamp

10

update timestamp
optional key flags

(table)

set pointers ...

(table)

member pointers ...

(table)

data field constants

Fig. 14-9. Physical Record Organization

14-8

Centura RDM Users Guide

In Table 14-4, some offsets are defined as table values. These are offsets that vary
according to the record type. The first six bytes are fixed, always containing the delete
flag, record lock bit, record type and database address. These are altered when records
are deleted (see section 14.2.2, "Data File Organization").
The two highest-order bits in the record id are used for other purposes. The remaining
14 bits contain the actual record id. The highest order bit is turned on when the record is
deleted because the whole word is complemented (see the next section). The next highest
bit is turned on when a record lock is applied.
The record id is a number that is used as an index into the record table, which is detailed
in section 14.3, "Database Dictionary Table Structure."
The database address field contains the physical address of the record. This is used for
consistency checking. If the record is deleted, this field will contain the slot number of
the next record in the delete chain.
A timestamped record will contain a four-byte creation timestamp and a four-byte last
update timestamp. If a record is not timestamped, this extra space is not allocated.
If a set is not timestamped, the set pointers will be 12 bytes long. If it is timestamped,
they will be 16 bytes long.
One byte of optional key stored bit flags is allocated for every eight optional keys
declared in the record type. If no optional keys are declared, no space is allocated.
All portions of a record except the first six bytes are optional (a record is not required to
have any data fields).

Delete Chain
When a record is deleted, RDM complements the record id (the first two bytes), and
places the slot at the beginning of a linked list called the delete chain. A complemented
value will always be negative and have a one in the highest order bit, which is used to
detect that the record has been deleted.
A pointer to the head of the delete chain is in the header of each data file (the first four
bytes of page zero). Each slot in the list contains, in the third through sixth bytes, the slot
number of the next slot in the list. The last slot contains a null slot number (0).

File Formats and Dictionary Tables

14-9

Figure 14-10 shows the logical structure of a delete chain containing three deleted record
slots.

Page 0

deleted record slots

Fig. 14-10. Example Data File Delete Chain


The physical locations of the slots in the delete chain are not ordered by their position in
the chain. The order of deletion determines their physical order. You could think of the
delete chain as an abstract stack object or a last-in-first-out list. During record creation,
record slots are consumed from the delete chain before new slots are allocated. The
records are removed from the head of the chain. The DCHAINUSE runtime option will
enable and disable use of deleted record slots during record creation (see "Option
Settings" in section 5.2.4).

14.2.3 Key File Organization


In a key file, the first two entries in page zero contain page numbers. As discussed
below, a B-tree allocates or discards full pages at a time, so the delete chain header points
to a page, and the next pointer contains the page number of the next page to be allocated
from the end of the key file.

Node Structure
A node, as used here, is a term that is synonymous with a page of an RDM key file. The
term is descriptive of its usage in a tree structure composed of nodes.
As in all RDM pages, a node starts with a four-byte integer that stores the time of last
update. Following that is a two-byte integer containing the number of currently used
slots in the node. The remainder of a node consists of a sorted array of fixed-length key
slots, followed by a single node pointer referred to as the orphan pointer.
The orphan pointer is the number of the node containing keys greater than the highest
key in this node. The maximum number of key slots that may be in one node is
determined by the slot size and node (page) size.

14-10

Centura RDM Users Guide

Table 14-5 shows the general layout of one node in a B-tree.


Table 14-5. Key File Node Structure
Offset
0

Length
4

variable

variable

Contents
Time of last update
Number of used slots in node
Slot space
Orphan pointer

Byte offset
0

last update time

used slots

key slots

Fig. 14-11. B-Tree Node

File Formats and Dictionary Tables

14-11

Key Slot Structure


Besides the key value itself, used slots contain additional control information used in the
maintenance of the B-tree, as shown in Table 14-6.
Table 14-6. Key Slot Structure
Offset
0

Length
4

variable

variable

Contents
Pointer to child node
Key prefix
Key contents
Database address of source record

Byte offset
0

4
child node

prefix

key contents

database address

Fig. 14-12. Key Slot


The child pointer is a node number of a node whose key values are less than the key
stored in this slot. If there is no child node, this field contains a null node pointer (-1L).
A node that has no child nodes is called a leaf node.
The prefix field is an integer value that is assigned by ddlp, and is unique for each key
type. It is used in sorting the keys so that different key types will be kept completely
distinct when stored in the same key file.
The key contents are a copy of the fields from the data record. If the key is a struct or
compound key, full copies of all subfields are stored here in the order in which they
occur in the key definition.
The last field in a key slot is the database address of the keys associated data record. The
field values stored in the key should always match the field values stored in this data
record. This can be confirmed by using dbcheck.

B-Tree Organization
As stated above, the used key slots in a node are sorted. Also, if a child pointer in a key
slot is not null, the node pointed to by the child pointer contains another set of sorted
keys, all of which precede the key value in the slot.

14-12

Centura RDM Users Guide

A B-tree starts with a root node. The root node is the entry point into a B-tree and is
always page one in a key file. Figure 14-13 shows a B-tree containing 11 nodes, with the
root node at the upper right.
4
0100
0200
0300
0400

4
0010
0020
0030
0040

2
-1 0201
-1 0203
-1
-1
-1

4
0110
0120
0130
0140

4
-1
-1
-1
-1
-1

0211
0212
0213
0214

4
0310
0320
0330
0340

0210
0220
0230
0240

3
-1 0222
-1 0223
-1 0226
-1
-1

2
-1 0231
-1 0234
-1
-1
-1

0410
0420
0430
0440

4
-1
-1
-1
-1
-1

0241
0243
0246
0247

Fig. 14-13. Example B-Tree


Note that the used slots field, shown at the top of the node, identifies the number of keys
in the node, even though there may be room for many more keys in the node.
Note also that there is one more child pointer in a node then there are keys. This last
child pointer is called an orphan pointer and points to a node containing keys that
succeed the key value in the last filled key slot in this node. It is called an orphan
because it has no key value associated with it.

File Formats and Dictionary Tables

14-13

The maximum number of key slots that may be filled in a node is computed as:
maximum slots = (page size - 10) / slot size
where 10 is the sum of the node header, containing the update time (four bytes), used
slots count (two bytes), and the orphan pointer (four bytes).
When the root node in the B-tree is filled to its maximum size, it will split into three
nodes: the original root node, which will contain only one key, and the two nodes at the
next level in the tree, which will contain the remainder of the keys from the original root
node.
As a B-tree grows, the non-root nodes will also be filled. As each node fills, it will split
into two nodes. Rather than leaving one key in the node and creating two child nodes (as
is done with the root node), the one remaining (middle) key is inserted into the node in
the next level up in the tree. Hence the two new nodes created by splitting one node are
at the same level in the tree, and the tree remains balanced.
If enough nodes at a lower level split, the root node will again become filled with keys,
and need to split. It will split again in the same way, leaving two nodes just beneath it.
This action increases by one the number of levels in the tree. This is important because,
at most, one database read is required per level in the B-tree. The more levels in a B-tree,
the more input and output are required in using it. Fewer levels are needed as more key
slots per node are available.
Just as the addition of keys to the B-tree causes additional nodes to be used, the deletion
of keys will eventually cause nodes to be emptied and discarded. During key deletion,
two nodes may combine into one node. This operation is effectively the inverse of a node
split. The unused node is placed into the key files delete chain.

Delete Chain
When a node is discarded during a key deletion, it is placed at the head of the delete
chain. As new nodes are required, they are first taken from the delete chain and then, if
the delete chain is empty, assigned from the end of the file.
The delete chain pointer is stored in the first four bytes of page zero in a key file. If the
delete chain header does not contain a null node pointer (-1L), it contains the node
number of the first node in the chain. Each node in the chain will contain the node
number of the next node in bytes four through seven. The last node in the chain will
contain a null as the pointer to the next node.

14-14

Centura RDM Users Guide

Figure 14-14 shows how a delete chain in a key file may appear.

page 0
-1

Fig. 14-14. Example Key File Delete Chain

14.3 Database Dictionary Table Structure


This section describes the structure of the tables that RDM uses to access and modify the
contents of the files discussed in the previous section.
The source code for the definitions given below is in the RDM header file dbtype.h. The
table structure definitions are given using C typedef statements.
A common type definition that is used in the table definitions is DB_SHORT. This is
used instead of the standard int when a 16-bit integer is required. The type definition of
DB_SHORT will always be set (in vista.h) to the native 16-bit type for a machine
(normally short).

File Formats and Dictionary Tables

14-15

14.3.1 Contents of the Dictionary File


The dictionary file is created by ddlp and contains the tables that are created from a DDL
file. The name of the dictionary file is the database name followed by .dbd.
The dictionary file contains the following information in the order described:
name
version
byte offset
0
length 6
contents RDM version number
name
page_size
byte offset
6
length 2
contents Maximum size of database page
name
size_ft
byte offset
8
length 2
contents Number of file table entries
name
size_rt
byte offset
10
length 2
contents Number of record table entries
name
size_fd
byte offset
12
length 2
contents Number of field table entries
name
size_st
byte offset
14
length 2
contents Number of set table entries
name size_mt
byte offset
16
length 2
contents Number of member table entries

14-16

Centura RDM Users Guide

name
size_srt
byte offset
18
length 2
contents Number of sort table entries
name size_kt
byte offset
20
length 2
contents Number of key table entries
name
file_table
byte offset
22
length fallen = size_ft * sizeof(FILE_ENTRY)
contents File definitions table
name
record table
byte offset
fallen + 22
length rlen = size_rt * sizeof(RECORD_ENTRY)
contents Record definitions table
name
file_table
byte offset
fallen + rlen + 22
length fallen = size_fd * sizeof(FIELD_ENTRY)
contents Field definitions table
name
settable
byte offset
fallen + rlen + fallen + 22
length stolen = size_st * sizeof(SET_ENTRY)
contents Set definitions table
name
member table
byte offset
fallen + rlen + fallen + stolen + 22
length melon = size_mt * sizeof(MEMBER_ENTRY)
contents Set member table
name
sort table
byte offset
melon + fallen + rlen + fallen + stolen + 22
length strlen = size_srt * sizeof(SORT_ENTRY)
contents Set sort fields table
name
key table
byte offset
strlen + melon + fallen + rlen + fallen + stolen + 22
length size_kt * sizeof(KEY_ENTRY)
contents Compound key field table

The end of the table space in the dictionary file contains the record, field, and set names
in ASCII format. The names are variable in length and separated with new line charac-

File Formats and Dictionary Tables

14-17

ters. The size_rt record names are listed first, followed by the size_fd field names and
the size_st set names.
The runtime function, d_open, will allocate memory for the seven tables and read them
into memory from the dictionary file. The size of the tables as reported by ddlp is the
amount of required memory.
The dictionary tables for a database contain several references to each other. For example, the record table points to a range of definitions of fields within the field table. Each
field definition will also contain a reference back to the record table. Each table is an
array of structures, and each inter-table reference is an index into an array, which can be
used to directly access the definition. The following sections define the table elements,
and section 14.3.9, "Dictionary Tables Example," summarizes them with an example.

14.3.2 File Table


The file table contains information about all data and key files in a database. One entry is
used for each file. If transaction logging is active, then an additional entry, the transaction log file, is added to the file table during the database open. The file table contains no
references to other tables, but is referenced by the record and field tables. The file_table
declaration is given below.
typedef struct {
char
DB_SHORT
char
char
DB_SHORT
DB_SHORT
DB_SHORT
DB_SHORT
} FILE_ENTRY;

ft_name[FILENMLEN];
ft_desc;
ft_status;
ft_type;
ft_slots;
ft_slsize;
ft_pgsize;
ft_flags;

ft_name contains the file name in an ASCII string. The name may have path or drive
information embedded in it. The maximum length of the field, FILENMLEN, is 48
characters.
ft_desc contains the file descriptor returned by the open call. If the file is not open, the
value will be zero. This element is modified every time the ft_status element is modified.

14-18

Centura RDM Users Guide

ft_status contains the current status of the file; either open or closed. It is used during
runtime file opening and closing. The possible values are:
o = opened
c = closed
ft_type is the file type, with possible values:
d = data file
k = key file
o = overflow (transaction log) file
ft_slots contains the number of record or key slots on one page in this file.
ft_slsize contains the slot size, in bytes, of the slots in this file.
ft_pgsize contains the page size, in bytes, used for this file.
ft_flags is a bit map for the file options. See dbtype.h for a list.

14.3.3 Record Table


The record table contains one entry for each record type defined in the schema for this
database. All size information about the record is stored, along with references to field
table entries that define the fields included in the record. The record table references the
file and field tables, and is referenced by the field, set, and member tables. The declaration of record_table is shown below.
typedef struct {
DB_SHORT
DB_SHORT
DB_SHORT
DB_SHORT
DB_SHORT
DB_SHORT
} RECORD_ENTRY;

rt_file;
rt_len;
rt_data;
rt_fields;
rt_fdtot;
rt_flags;

rt_file is a reference to the file table entry that defines the file containing this record type.
rt_len is the total length of the record. If this record is the largest in its file, the value of
file_table[rt_file].ft_slsize is equal to rt_len. This value is required, however, because
files can also contain smaller records within the full slot size.
rt_data is the offset from the start of the record to the first data field.
rt_fields is the index of the first field definition in the field table.
rt_fdtot is a count of the number of fields in this record type.

File Formats and Dictionary Tables

14-19

rt_flags is a bit map for the record options. See dbtype.h for a list.

14.3.4 Field Table


The field table contains one entry for each field defined in the schema. It also contains
one entry for each compound key defined. It fully defines each fields data type and
length, as well as array dimension limits.
The field table references the record, file, and key tables, and is referenced by the record,
key, and sort tables. The field_table declaration is given below.
typedef struct {
char
fd_key;
char
fd_type;
DB_SHORT
fd_len;
DB_SHORT
fd_dim[MAXDIMS];
DB_SHORT
fd_keyfile;
DB_SHORT
fd_keyno;
DB_SHORT
fd_ptr;
DB_SHORT
fd_rec;
DB_SHORT
fd_flags;
} FIELD_ENTRY;

fd_key defines the type of key that this field is:


n = not a key
d = non-unique key (duplicates allowed)
u = unique key
fd_type defines the data type of this field:
c = char
C = wchar_t (Unicode)
s = short
i = int
l = long
d = DB_ADDR
f = float
F = double
g = grouped (struct)
k = compound key

14-20

Centura RDM Users Guide

The g (grouped), and k (compound key) fields have no data of their own, as the rest
of the field types do.
A group of fields is ordered in a specific way. First, the group definition occurs, then
the elements of the group occur, each having a flag set (see fd_flags) indicating that
they are group elements. The group ends when there is a field without this flag set,
or at the end of the table.
If the field is flagged as a compound key field (k), it will always follow the normal
field definitions in a record. This compound key field redefines the purpose of
fd_ptr so that it points to an entry in the key table rather than marking the byte offset
from the start of the record to the contents of this field. (see section 14.3, "Database
Dictionary Table Structure").
fd_len is the length of the field in bytes. If the field is an array, this length is the basic
data type length times the dimensions of the array.
fd_dim[MAXDIMS] is a three-element (MAXDIMS is three) array containing the values
of any declared dimensions. By default, all are zeros. If one dimension is declared with
the field type, then fd_dim[0] will contain that value, and the others will remain zero.
If this field is a key field (fd_key is "d" or "u"), then fd_keyfile is an index into the file
table that references the key file that contains this field.
fd_keyno is the key prefix number, which is stored in the first two bytes of each key of
this type (see section 14.2.3, "Key File Organization").
fd_ptr is the byte offset from the start of the record to the contents of this field in a
record. If this field type is k (compound key), this is an index into the key table of the
first field definition of the compound key.
fd_rec is an index into the record table of the record that contains this field.
fd_flags is a bit map for field options. The high-order six bits store non-zero optional
key numbers. The low-order 10 bits store the options for the field.

File Formats and Dictionary Tables

14-21

14.3.5 Set Table


The set table contains one entry for every set defined in the schema. It defines the set
ordering and the position of the set pointers in the record. Since there may be many
members, the member record types for this set type are defined in the member table,
which is referenced by this table. The set table references the member and record tables,
and is referenced only by the sort table. The set_table declaration is given below.
typedef struct {
DB_SHORT
st_order:
DB_SHORT
st_own_rt;
DB_SHORT
st_own_ptr;
DB_SHORT
st_members;
DB_SHORT
st_memtot;
DB_SHORT
st_flags;
} SET_ENTRY;

st_order defines the set ordering:


f = order first
l = order last
a = order ascending
d = order descending
n = order next
st_own_rt is an index to the record table of the record type owning the set type.
st_own_ptr is the offset in the record of the set pointers used for this set.
st_members is an index into the member table of the first set member definition.
st_memtot is the total number of member record types in this set.
st_flags is a bit map for set options. See dbtype.h for a list.

14-22

Centura RDM Users Guide

14.3.6 Member Table


The member table contains one entry for each set member in a database. Since one set
may contain multiple members, the set table will point to a range of consecutive entries
in the member table. Since a set member may be sorted by multiple fields, each member
entry may point to a range of consecutive entries in the sort table.
The member table references the record and sort tables, and is referenced by the set table.
typedef struct {
DB_SHORT
DB_SHORT
DB_SHORT
DB_SHORT
} MEMBER_ENTRY;

mt_record;
mt_mem_ptr;
mt_sort_fld;
mt_totsf;

mt_record is an index into the record table of the member record type.
mt_mem_ptr is the offset, in the record, of the member pointers.
mt_sort_fld is an index into the first entry of the sort table of a sort field definition, if the
set is sorted.
mt_totsf is the number of sort table entries used by this set member. This contains zero if
the set is not sorted.

14.3.7 Sort Table


The sort table contains one entry for each field that is referenced in an order by clause in
a set definition. The list of sorting fields occurs in the set definition, following the
naming of a member record type. The member table refers to a range of entries in the
sort table in order to locate the field table entries involved in sorting.
typedef struct {
DB_SHORT
se_fld;
DB_SHORT
se_set;
} SORT_ENTRY;

se_fld is an index into the field table of one field definition involved in the field sort.
se_set is an index into the set table of the set type that owns this sorted list of members.

14.3.8 Compound Key Table


The compound key table contains one entry for each field listed in each compound key
statement. One compound key statement may list several fields. For each compound
key statement, there is one entry in the field table, which points to a range of entries in

File Formats and Dictionary Tables

14-23

the compound key table. This range of entries is used to form a single key from the fields
referenced by the key table entries.
Each entry in this table refers to the compound key and an associated field, the position
of the field in the key, and whether the field is ascending or descending.
typedef struct {
DB_SHORT
kt_key;
DB_SHORT
kt_field;
DB_SHORT
kt_ptr;
DB_SHORT
kt_sort;
} KEY_ENTRY;

kt_key is an index into the field table of the compound key definition in which this entry
is included.
kt_field is an index into the field table of a field used in the compound key.
kt_ptr is an offset from the start of the actual key to where the contents of this field
begins.
kt_sort is the sorting order of this field. The possible values are:
a = ascending
d = descending

14-24

Centura RDM Users Guide

14.3.9 Dictionary Tables Example


This section provides a simple example of a schema and shows the tables that are
generated as a result. This short example contains most of the elements of an RDM
schema, and uses all seven table types. The text of the schema is:
database mgrs {
data file "data" contains manager, dept;
key file "keys" contains name, emp_no;
record manager {
key long emp_no;
char last_name[20];
char first_name[20];
compound optional key name {
last_name ascending;
first_name ascending;
}
}
record dept {
char title[10];
int loc_code;
float budget;
}
set manages {
order ascending;
owner manager;
member dept by title, loc_code;
}
}

The prdbd utility can be used to print the contents of the dictionary tables. The report
from a run of prdbd -c on the above DDL specification is shown below.

File Formats and Dictionary Tables

14-25

RDM Version 5.0


Database Dictionary Tables for Database: mgrs
REQUIRED MEMORY: 328 BYTES

-----------------------------------------------------------------FILE TABLE:
file des sta type slots sl sz pg sz
---- --- --- ---- ----- ----- ----0
0
c
d
15
64 1024
1
0
c
k
20
50 1024

flgs
---0000
0000

name
---data
keys

-----------------------------------------------------------------RECORD TABLE:
[#]first
tot
[#]record
file
len data
field
flds flags
-------------- ---------- ---- ---- --------------- ---- ----[ 0]MANAGER
data.d00
63
19 [ 0]EMP_NO
3 0010
[ 1]DEPT
data.k01
34
18 [ 4]TITLE
3 0000
-----------------------------------------------------------------FIELD TABLE:
key
key record
[#]field
key type len file num offset [#]record
flags dims
--------------- --- ---- --- ------ --- ------ -------------- ----- ---[ 0]EMP_NO
d
l
4 keys.k
0
19 [ 0]MANAGER
0000
[ 1]LAST_NAME
n
c 20
0
23 [ 0]MANAGER
0010 [20]
[ 2]FIRST_NAME
n
c 20
0
43 [ 0]MANAGER
0010 [20]
[ 3]NAME
d
k 40 keys.k
1
0 [ 0]MANAGER
0400
[ 4]TITLE
n
c 10
0
18 [ 1]DEPT
0001 [10]
[ 5]LOC_CODE
n
i
2
0
28 [ 1]DEPT
0001
[ 6]BUDGET
n
f
4
0
30 [ 1]DEPT
0000

(Continued)

14-26

Centura RDM Users Guide

(Continued)

-----------------------------------------------------------------SET TABLE:
[#]owner
own ptr first total
[#]set
order
record
offset member members flags
--------------- ----- -------------- ------- ------ ------- ----[ 0]MANAGES
a [ 0]MANAGER
7
0
1 0000
-----------------------------------------------------------------MEMBER TABLE:
mem ptr
mem #
[#]record
offset
----- -------------- ------0 [ 1]DEPT
6

# of 1st
sort fld
-------0

total
sort flds
--------2

-----------------------------------------------------------------SORT TABLE:
sort #
-----0
1

[#]field
--------------[ 4]TITLE
[ 5]LOC_CODE

[#]set
--------------[ 0]MANAGES
[ 0]MANAGES

-----------------------------------------------------------------COMPOUND KEY TABLE:


key #
----0
1

[#]compound
key field
--------------[ 3]NAME
[ 3]NAME

[#]component
field
--------------[ 1]LAST_NAME
[ 2]FIRST_NAME

ptr
--0
20

order
----a
a

Figure 14-15 shows the values that would be contained in the dictionary tables for this
database. The values correspond to the element definitions contained in the above
sections. The table interrelationships are also shown.

File Formats and Dictionary Tables

14-27

file_table:

record_table:

0: data 0
1: keys 1

d
k

c
c

0: 0
1: 0

15 64 1024 0000
20 50 1024 0000

file_table
entry

set_table:
0: a

63 19 0
34 18 4

record_table
entry

number of
member_table
entries

first
member_table
entry

first
sort_table
entry

field_table:
0:
1:
2:
3:

d
n
n
d

l
c
c
k

4 0 1
20 20 0
20 20 0
40 0 1

0
0
0
1

19 0
23 0
43 0
0 0

0000
0010
0010
0400

0
0
0

18 1
28 1
30 1

0001
0001
0000

key_table entry
(compound key fields only)

member_table:
0: 1 6
0 2
record_table
entry

number of
field_table
entries

first
field_table
entry

1 0000

3 0010
3 0000

4:
5:
6:
number of
sort_table
entries

n
n
n

c
i
f

10 10 0
2 0 0
4
0 0

record_table
entry

file_table entry
(key fields only)

key_table:
sort_table:
0:
1:

4
5

0:
1:

0
0
set_table
entry

field_table
entry of
compound key

field_table
entry

3
3

1 0
2 20

a
a

field_table
entry of
data field

Fig. 14-15. Dictionary Table Interrelationships

14-28

Centura RDM Users Guide

14.3.10 Database Table


The database table is not contained in the database dictionary file because it contains
information that pertains to multiple database usage.
When multiple databases are opened, the various dictionary tables are, in effect, concatenated into larger tables so that they appear to represent one large database. The
inter-table references are all offset to point directly to their new positions in the tables.
When an RDM runtime function is called, first the current database number is
determined (if not supplied in the call). Using the current database number as an index
into the database table, the offsets to the starting positions in the tables for that database
are obtained. If any adjustments are necessary to the function parameters, the offset
values stored in this table will be used. For example, a record type might be passed to
d_fillnew that would require translation to a higher number if the current database is not
the first one.
The structure of the database table is as follows:
typedef struct {
DB_SHORT
size_ft;
DB_SHORT
ft_offset;
DB_SHORT
size_rt;
DB_SHORT
rt_offset;
DB_SHORT
size_fd;
DB_SHORT
fd_offset;
DB_SHORT
size_st;
DB_SHORT
st_offset;
DB_SHORT
size_mt;
DB_SHORT
mt_offset;
DB_SHORT
size_srt;
DB_SHORT
srt_offset;
DB_SHORT
size_kt;
DB_SHORT
kt_offset;
DB_SHORT
key_offset;
DB_ADDR
sysdba;
DB_ADDR
curr_dbt_rec;
DB_ULONG
curr_dbt_ts;
DB_SHORT
page_size;
char
db_path[PATHLEN];
char
db_name[DBNMLEN];
} DB_ENTRY;

size_ft is the number of elements in this databases file table.


ft_offset is the index in the global file table to the first element of this databases file table.
size_rt is the number of elements in this databases record table.
rt_offset is the index in the global record table to the first element of this databases
record table.

File Formats and Dictionary Tables

14-29

size_fd is the number of elements in this databases field table.


fd_offset is the index in the global field table to the first element of this databases field
table.
size_st is the number of elements in this databases set table.
st_offset is the index in the global set table to the first element of this databases set table.
size_mt is the number of elements in this databases member table.
mt_offset is the index in the global member table to the first element of this databases
member table.
size_srt is the number of elements in this databases sort table.
srt_offset is the index in the global sort table to the first element of this databases sort
table.
size_kt is the number of elements in this databases key table.
kt_offset is the index in the global key table to the first element of this databases key
table.
key_offset is the relative offset of this databases key sequence numbers. This is used
during key manipulation.
sysdba is the database address of the system record for this database.
curr_dbt_rec is the current record for this database.
curr_dbt_ts is the timestamp of the current record for this database.
page_size is the largest page size used in this database.
db_path[PATHLEN] is the path to a database, and is included only if the database is not
in the current directory. The total length of DBNMLEN plus PATHLENN must be 48
characters or less.
db_name[DBNMLEN] is the name of this database. No path is included here.

14.3.11 Contents of the Header File


When ddlp compiles a schema file, it produces the dictionary file and a header file. The
header file contains record struct declarations, compound key struct declarations, and
constant definitions for each file id, record, field, and set name in the database.
An application program may use a constant without understanding its numeric value,
but the RDM runtime functions must interpret it to make sure it is the right kind of
constant for the function being used. (For example, you cannot send a record type
constant to function d_findnm.)

14-30

Centura RDM Users Guide

The record type constants are used to index into the record table. As defined, they have a
value of RECMARK (10000) added to them, which must be subtracted if the record table
is to be referenced from it.
The field type constants index into the record table and an offset within the record type.
The record type is encoded into the field type constant as follows:
field type constant = record type * 1000L + field offset
The 1000L is defined by a constant named FLDMARK. Because the field type constant
includes the record index and field offset, new field types can be added to existing record
types without changing the field type constants for other record types. The field type
constant can be decoded as follows:
record id

= field type constant / FLDMARK

offset

= field type constant % FLDMARK

field type

= offset + record_table[record id].rt_fields

The set type constants index into the set table. As defined, they have a value of
SETMARK (20000) added to them, which must be subtracted if the set table is to be
referenced.

File Formats and Dictionary Tables

14-31

14.4 Currency Tables


The currency tables are implemented in RDM as arrays of database addresses. The most
commonly accessed currency is the current record, which is implemented with a "global"
variable containing one database address.
The current owner and current member of each set are stored in arrays of database
addresses.
The number of elements required in the set currency arrays is size_st (see section 14.3.1,
"Contents of Dictionary File"). The tables are allocated dynamically during the database
open.

14.5 Source Code Details


14.5.1 Function Prototyping
Function prototyping is contained in two function prototype header files, which reside in
the include directory:
proto.h

Prototypes all system-level RDM functions (such as dio_read,


which is included with the source version)

dproto.h

Prototypes all user-level functions (for example, d_open)

dproto.h is automatically included by vista.h. To use proto.h (which you should only
include if you are making calls to system-level RDM functions) you must include
dbtype.h, which in turn requires you to first include vista.h. The function prototype files
define the function type. If you define the constant LINT_ARGS, then the prototype files
will also define the types of the arguments to the functions. If your C compiler does not
support the const keyword (part of the ANSI standard) then define the constant
NO_CONST.
The header file vista.h contains the definition of two macros called P1 and Pi, which
expand argument definitions if the LINT_ARGS switch is defined. If LINT_ARGS is
not defined, the macros turn into null comments. This allows compilers that do not yet
recognize function prototypes to compile RDM source code.

14-32

Centura RDM Users Guide

14.5.2 Pascal Calling Conventions


The Pascal calling convention (_pascal) differs from the standard C calling convention
(_cdecl) in two main ways. First, function parameters are pushed onto the stack from left
to right instead of right to left, and, second, the called function (rather than the calling
function) pops the stack. Code that uses the Pascal convention is both smaller and faster.
On the other hand, the Pascal convention does not allow variable numbers of parameters
to one function, as is common with C functions like printf.
Some C compilers support both conventions. Needless to say, a function that expects to
be called with the Pascal convention must be called with the Pascal convention, or the
stack will immediately become corrupted. Function prototyping is the mechanism used
to ensure that both caller and called use the same convention.
The RDM function prototypes are coded with macros in such a way that either
convention may be selected during compilation. The form of a typical function prototype
is as follows:
int INTERNAL_FIXED key_locpos(P1(CONST char DB_FAR *) Pi(DB_ADDR DB_FAR
*));

If this definition is compiled with the appropriate compiler labeling switch turned on,
INTERNAL_FIXED becomes pascal. If WINDOWS is turned on, DB_FAR becomes far.
If LINT_ARGS is turned on, P1(CONST char DB_FAR *) becomes const char far *. If
NO_CONST is not defined, CONST becomes const. Thus, the compile line below,
cl ... -DLINT_ARGS -DWINDOWS -DMSC ...

resolves the prototype definition into the following ,


int pascal key_locpos(const char far *, DB_ADDR far *);

Programming a DLL for Windows requires the use of the Pascal convention. Other
compilers that support the convention can be made to use it also with some simple code
changes in vista.h.

File Formats and Dictionary Tables

14-33

Glossary of
Database Terms
Alias

An alternative name used to identify a database object.

Application Programming
Interface (API)

A set of functions that a program uses to access a database.

Application

A program written by or for a user that applies to the users


work. A program or set of programs that perform a task.
For example, a payroll system.

Argument

A value entered in a command that defines the data to


operate on or that controls execution. Also called parameter

Arithmetic expression

An expression that contains operations and parameters that


can be reduced to a single numeric value.

Arithmetic operator

A symbol used to represent an arithmetic operation, such as


the plus sign (+) or the minus sign (-).

ASCII file

A document file in ACSII format, containing characters,


spaces, punctuation, carriage returns, and sometimes tabs
and an end-of file marker, but no formatting information.

Audit file

A log file that records output from an audit operation.

Authorization

The right granted to a user to access a database.

B-tree

A fast data-indexing method that organizes the index into a


multi-level set of nodes. Each node contains a sorted array
of key values (the indexed data).

Back up

To copy information onto a diskette, fixed disk, or tape for


record keeping or recovery purposes.

Buffer

An in-memory store of data read from a disk file, in which


database operations are performed.

Cache

A set of buffers used to optimize database input and output


operations through virtual memory processing. All RDM
database input and output is performed using a cache.

Case sensitive

A condition in which names must be entered in a specific


lower-case, upper-case, or mixed-case format to be valid.

Character

A letter, digit, or special character (such as a punctuation


mark) that is used to represent data.

Character string

A sequence of characters treated as a unit.

Glossary of Database Terms

Gloss-1

Checkpoint

A point at which database changes older than the last


checkpoint are flushed to disk. Checkpoints are needed to
ensure crash recovery

Client

A computer that accesses shared resources on other


computers running as servers on the network. Also called
front-end.

Column

See Field.

Command

A user request to perform a task or operation. A command


can include limits or specific terms for its execution, such as
a query for names and addresses in a single zip code.
Sometimes called statement.

Commit

The point at which database changes made during a single


transaction are actually written to the database files.

Compound key

A key field composed of any combination of fields (not


necessarily contiguous) from a record. Each field of a
compound key may be stored in ascending or descending
order.

Concurrency

The shared use of a database by multiple users or


application programs at the same time. Multiple users can
execute database transactions simultaneously without
interfering with each other. The database software ensures
that all users see correct data and that all changes are made
in the proper order.

Configure

To define the features and settings for a database server or


its client applications.

Connect

The process of inserting a member record occurrence into a


set occurrence.
Also, to provide a valid user id and password to log onto a
database.

Consistency

A state that guarantees that all data encountered by a


transaction does not change for the duration of a command.
Consistency ensures that uncommitted updates are not seen
by other users.

Constant

Specifies an unchanging value. Also called literal.

Cooperative processing

Processing that is distributed between a client and a server


in a such a way that each computer works on the parts of
the application that it is best at handling.

Gloss-2

Centura RDM Users Guide

Currency tables

A table of database addresses maintained by the RDM


runtime system for controlling record access and set
navigation. The currency tables consist of the current member
table, current owner table, and the current record.

Current database

The database that is currently accessible by the RDM


runtime functions when multiple databases have been
opened. The current database is changed by the database
number function argument or by function d_setdb.

Current member

Contains, for each set, the database address of a record


occurrence that is a valid member of that set. Usually, the
current member of a set is the last record accessed using a set
navigation function (d_findfm, d_findlm, d_findnm, or
d_findpm).

Current owner

Contains for each set, the database address of a record


occurrence that is a valid owner of that set. Usually, the
current owner of a set is established using the set navigation
function d_findco or by using a currency manipulation
function.

Current record

Contains the database address of the most recently accessed


record occurrence.

Data dictionary

See Dictionary.

Data field

See Field.

Data file

An RDM file defined in a DDL specification that contains


occurrences of one or more record types.

Database

An organized collection of related files.

Database administrator

A person responsible for the design, planning, installation,


configuration, control, management, maintenance, and
operation of a database management system and its
supporting network.

Database address

The location in the database of a record occurrence.

Database Definition
Language

A programming-like language used to define


the structure and content of a database. RDMs Database
Definition Language has been designed to be used with the C
programming language.

Database management
system

A software system that manages the creation, organization,


and modification of a database and access to data stored
within it. A DBMS provides centralized control, data
independence, and complex physical structures for efficient
access, integrity, recovery, concurrency, and security.

Glossary of Database Terms

Gloss-3

Database server

A DBMS that a user interacts with through a client


application on the same or a different computer. Also called
engine.

DBMS

See Database management system.

DDL

See Database Definition Language.

Deadlock

A situation in which multiple processes accessing the same


database each hold locks needed by the other processes in
such a way that none of the processes can proceed.

Default

An attribute, value, or setting that is assumed when none is


explicitly specified.

Delete chain

A linked list containing deleted records to be reused when a


new record is created.

Delimiter

A character that groups or separates items in a command.

Dependent table

The table containing the foreign key.

Dictionary

A repository containing a definition of the content and


structure of a database. It is used by the RDM runtime
library functions for accessing and manipulating
information from that database.

Disconnect

The process of removing a member record from a set


occurrence.

DLL

See Dynamic link library.

Dynamic link library

A program library written in C or assembler that contains


related modules of compiled code. The functions in a DLL
are not read until run-time (dynamic linking).

Duplicates

An option used when creating an index for a table that


specifies whether duplicate values are allowed for a key.

Engine

See Database server.

Entity

See Field.

Environment variable

A programmer-specified operating system parameter that is


used to identify configuration information to the runtime
system.

Exclusive Lock

An exclusive lock allows only one user to have a lock on a


page at a time. An exclusive lock prevents another user
from acquiring a lock until the exclusive lock is released.
Exclusive locks are placed when a page is to be modified.
An exclusive lock differs from a shared lock because it does
not permit another user to place any type of lock on the
same data.

Gloss-4

Centura RDM Users Guide

Expression

An item or a combination of items and operators that yield a


single value. Examples are arithmetic expressions built with
operators such as + or - that yield the result of performing
the operation and functions which yield the value of the
function for its argument.

Field

Also called data field, it represents the basic unit of


information storage in a database and is always defined to
be an element of a record. A field has associated with it
attributes such as name, type (for example, char or int), and
length. Other terms used for field include: attribute, entity,
or column.

File

The primary physical storage unit into which a database is


organized. In RDM, files are used to store records and keys.

File server

A computer that allows network users to store and share


information.

Floating point

A number represented as a number followed by an


exponent designator (such as 1.234E2, -5.678E2, or 1.234E-2).
Also called E-notation or scientific notation.

Function

A predefined operation that returns a single value per row


in the output result table.

Grant

That act of a system administrator to permit a user to make


specified use of a database. A user may be granted access to
an entire database or specific portions, and have unlimited
or strictly-limited power to display, change, add, or delete
data.

Graphical User Interface


(GUI)

A graphics-based user interface with windows, icons,


pull-down menus, a pointer, and a mouse. Microsoft
Windows is an example of a graphical user interface.

Hierarchical database
model

A data representation in which the relationships


between record types are formed from parent-child
structures, such that a record type may have many child
relationships but only one parent relationship.

Identifier

The name of a database object.

Index

A set of key values through which rapid retrieval of a


record is provided, similar to the index of a book. The term
is often used synonymously with key file.

Key file

A file that only contains keys. It may, in fact, contain more


than one index because multiple key types can be contained
in a single RDM key file.

Glossary of Database Terms

Gloss-5

Key scan

The process of performing an ordered traversal through all


(or a subset of all) occurrences of a given key field.

Key

A field through which rapid and/or sorted access to a record


is desired.

Keyword

One of the predefined words in a command language.

LAN

See Local area network.

Local area network

A collection of connected computers that share data and


resources, and access other networks or remote hosts.
Usually, a LAN is geographically confined and
microcomputer-based.

Lock

A multi-user database synchronization mechanism, used to


prevent simultaneous updates to shared data. Locks can be
applied to the entire database, to files, or to record
occurrences.

Logging

The process of making a copy of the database changes made


during a transaction prior to a commit. Logging is used to
support the ability to perform a recovery in the event a
failure occurs during a commit.

Logical operator

A symbol for a logical operation that connects expressions


in a WHERE or HAVING clause. Examples are AND, OR,
and NOT. An expression formed with logical operators
evaluates to either TRUE or FALSE. Logical operators
define or limit the information sought. Also called Boolean
operator.

Many-to-many relationship A relationship between two record types, A and B, such that
for each occurrence of type A, there are many related
occurrences of type B and, for each occurrence of type B,
there are many related occurrences of type A. In RDM,
many-to-many relationships can be implemented using two
one-to-many sets through a third, intermediate record type.
Mathematical function

An operation such as finding the average, minimum, or


maximum value of a set of values.

Member of set

See Set.

Member pointer

Stores set membership linkage information. There is one


member pointer stored with a record per set for which the
record is a member. Each one contains the database addresses
of the owner record, previous member in the set, and next
member in the set.

Multi-user

The ability of a computer system to provide its services to


more than one user at a time.

Gloss-6

Centura RDM Users Guide

Navigation

The process of retrieving records from a database by


moving through various set occurrences.

Network database model

A data representation in which the relationships are


explicitly defined and maintained through sets.

Node

A component of a B-tree, consisting of a page of sorted keys


stored in a key file.

Null

A value that indicates the absence of data. Null is not


considered equivalent to zero or to blank. A value of null is
not considered to be greater than, less than, or equivalent to
any other value, including another value of null.

Numeric constant

A fixed value that is a constant.

ODBC

See Open Database Connectivity.

One-to-many relationship

A relationship between two record types, A and B, such that


for each occurrence of type A, there are many related
occurrences of type B and, for each occurrence of type B,
there is only one related occurrence of type A.

Open Database
Connectivity

A Microsoft standard, which is an application programming


interface (API) specification written by Microsoft. It calls
for all client applications to write to the ODBC standard API
and for all database vendors to provide support for it. It
then relies on third-party database drivers or access tools
that conform to the ODBC specification to translate the
ODBC standard API calls generated by the client
application into the database vendors proprietary API calls.

Operator

A symbol or word that represents an operation to be


performed on the values on either side of it. Examples of
operators are arithmetic (+, -, *, /), relational (=, !=, >, <, >=,
<=), and logical (AND, OR, NOT).

Owner of set

See Set.

Page

Files are blocked into contiguous fixed-length segments


called pages. A page is the unit of database I/O performed in
RDM.

Password

A sequence of characters that must be entered to connect to


a database. Associated to each password is a user id.

Path name

The sequence of directories in a hierarchical file system that


must be traversed to locate a particular file.

Picture

A string of characters used to format data for display.

Glossary of Database Terms

Gloss-7

Pointer

In a database, a pointer is data stored in a record occurrence


that provides the necessary information for locating related
record occurrences. In a C program, a pointer is a variable
that contains a memory address.

Precedence

The default order in which operations are performed in an


expression.

Privilege

A capability given to a user to perform an action.

Process

An independently executing task or program. An


individual execution of an RDM application program.

Queue

A first-in-first-out waiting list. Lock requests for a locked


resource will be placed at the end of a queue. When the
locked resource becomes available, the first lock request on
the queue will be granted.

Read lock

Allows other programs to read but not update the locked


files.

Record occurrence

One individual instance in a database of a record of a


particular type. A database consists of many occurrences of
many different record types. For example, an employee
record type may consist of the fields name, employee_id,
job_title, and pay. An employee record occurrence could be
"name: Jones, Jim; employee_id: c87101, job_title: engr, pay:
3400".

Record type

A named collection of related fields that are stored and


accessed as a unit. See also Record occurrence.

Record

Used synonymously with record type or record occurrence


depending on the context in which the term is used.

Recovery

The process of completing the transaction of a process that


failed during a commit.

Redundant data

Identical data that is stored in multiple locations in a


database. Typically used to form relationships between
tables in a relational database management system.

Referential integrity

Guarantees that all references from one database table to


another are valid and accurate. Referential integrity
prevents problems that occur because of changes in one
table that are not reflected in another.

Gloss-8

Centura RDM Users Guide

Relational database model A data representation in which a database is viewed as


consisting of two-dimensional tables, each composed of one
or more columns. Inter-table relationships are defined
through use of common column names and data. Tables
and columns are analogous to RDM records and fields,
respectively.
Relational operator

A symbol (such as =, >, or <) used to compare two values.


Also called comparison operator.

Restore

Copying a backup of a database or its log files to a database


directory.

Revoke

The act of withdrawing a users permission to access a


database.

Rollback

To restore a database to the condition it was in at its last


commit. A rollback cancels a transaction and undoes any
changes that it made to the database. All locks are freed
unless cursor-context preservation is on.

Root node

The top or start node of a B-tree.

Runtime system

The RDM C language library functions that perform all of


the database access required by an application program
while it is executing.

Scale

The number of digits to the right of the decimal point in a


number.

Schema

A conceptual model of the structure of a database that


defines the data contents and relationships. A database
definition language specification is an implementation of a
particular schema.

Set

Specifies a one-to-many relationship between record types.


One occurrence of the owner record type is related to many
occurrences of a member record type. Also called a set type.

Set occurrence

An individual instance of a set in which one owner record


occurrence has one or more member record occurrences
connected to it.

Set pointer

Stores set ownership linkage information. There is one set


pointer stored with a record per set for which the record is
an owner. Each one contains a count of the number of
members in the set, the database address of the first member
record occurrence, and the database address of the last
member record occurrence in the set.

Glossary of Database Terms

Gloss-9

Set scan

The process of performing an ordered traversal through all


(or a subset of all) member record occurrences of a given set
occurrence.

Single-user

A computer system that can only provide its services to one


user at a time.

Slot

A position in a data or key file for storage of a single record


or key occurrence.

Static record

A record type containing only data that seldom, if ever,


changes.

Stored procedure

A precompiled procedure that is stored on the backend for


future execution.

String

A sequence of characters treated as a unit of data.

String delimiter

A symbol used to enclose a string constant. The symbol is


the single quotation mark ().

Synchronization

The process of ensuring that, in a multi-user database


environment, updates to shared data are performed serially,
one user at a time.

Syntax

The rules governing the structure of a command.

System record

A special record type used to define the "top" record in a


network database. There is only one occurrence of the
system record. It allows the definition of a set owned by the
system so that access to records through set relationships
can be achieved.

Table

See Relational database model.

Timeout

An event that occurs when a lock request has waited on a


queue longer than a pre-determined amount of time. It is
used to avoid deadlock.

Timestamping

A multi-user database technique that allows a process to


detect deletions and updates made by other processes.

Transaction activity file

A database family-wide RDM file that stores the names of


all log files currently involved in a transaction commit. It
provides for automatic recovery in the event the lock
manager fails, or for single-user configurations.

Transaction

A group of related database changes that are written to the


database as a single unit during a commit. The logical
consistency of a database is maintained by placing all
related updates within transactions.

Gloss-10

Centura RDM Users Guide

Unicode

A 16-bit character encoding standard developed by the


Unicode Consortium. By using two bytes to represent each
character, Unicode enables almost all written languages to
be represented using a single character set.

Value

Data assigned to a field, constant, variable, or argument.

Variable

A data item that can assume any of a given set of values.

Virtual memory

A database page input/output management technique that


keeps the most recently and most often accessed database
pages in memory during execution of a database application
program. It reduces the amount of required actual disk
I/O, resulting in improved performance.

Glossary of Database Terms

Gloss-11

Index
#define constants 4-19
#include 5-42

begin transaction 6-3


block size 4-3

A
-abcc
ddlp argument 4-21
-amsc
ddlp argument 4-21
abnormal termination
recovery 6-5
abort transaction 6-3
access
methods
indexed 2-2, 2-9, 2-10
network 2-10
sequential 2-10
performance optimization 4-36
requirements 6-6
sequential 5-31
alignment of data fields 4-11, 4-17
alignment of ddlp 4-20
archive logging 5-14, 6-7
disabling 5-14
arrays 4-10
and dal 11-9
ASCII file transfer 10-1
ASCII text
converting with dbimp 10-21
exporting with dbexp 3-4, 10-3
importing with dbimp 3-4
redefining with RDM 5-50
attribute 2-8
defined 2-1
automatic recovery 6-6

C
cache 5-13, 6-4
overflow 6-5
case insensitivity 5-50
Centura
Web home page 1-5
character arrays 4-10
character sets
international 5-50
checking account example 2-1, 2-6, 2-8,
4-3, 4-6, 4-11, 4-17, 4-18, 4-23, 5-19,
5-24
key fields 4-23, 4-25
record declarations 4-8
timestamping 4-4
child pointer 14-12
class 4-13
CLOSEFILES option 5-14
closing a database 5-4
coded fields
validation of 5-19
collating sequence 5-50
column 2-8
defined 2-1
comments
RDM DDL 3-9
commit 6-1, 6-6
compiling 3-19, 4-17
compound key 4-12, 4-24, 5-22
declaration syntax 4-12
table 14-23
connect command 8-10
consistency of a database 13-2
console
definition of 3-5
context switching 5-47
control information

B
B-tree
indexing method 2-2, 4-22
node 14-10
root node 14-12

Centura RDM Users Guide

Index-1

space requirements 4-32


corrupted database, repair 12-1
country table 5-50
crash
recovery 6-5
creation of data 5-34, 7-19
CTBPATH 5-50
in context switching 5-47
currency
control functions 5-17
setting 5-16
currency menu 8-38
display currency tables option 8-39
set current member option 8-39
set current owner option 8-39
set current record option 8-39
timestamp option 8-39
currency tables 5-15
access 5-17
current database 5-44
current member 5-15
current owner 5-15
current record 5-15
global variables 14-32
manipulation 5-17
timestamps 7-14
current member 2-10
current owner 2-10
current record 2-10
current record dialog box 8-28
D
d_ function names
using instead of dt_ 5-49
d_checkid 5-3
d_close 3-15, 5-3, 5-4, 5-45, 8-25
d_closeall 5-3, 5-13
d_cmstat 7-14, 8-27
d_cmtype 7-8, 8-27
d_connect 5-34, 5-38, 8-26
d_costat 7-14, 8-27
d_cotype 7-8, 8-27
d_crget 5-17, 5-33, 7-15, 8-27

Index-2

d_crread 5-18, 5-33, 7-8


d_crset 5-17, 5-33, 7-15, 8-27
d_crstat 7-14, 8-27
d_crtype 8-27
d_crwrite 5-34, 5-38
and d_makenew 5-34
d_csmget 5-17, 7-15, 8-27
d_csmread 5-18, 5-33, 7-8
d_csmset 5-17, 7-15, 8-27
d_csmwrite 5-38
d_csoget 5-17, 7-15, 8-27
d_csoread 5-18, 5-33, 7-8
d_csoset 5-17, 7-15, 8-27
d_csowrite 5-38
d_csstat 7-14, 8-27
d_ctbpath 5-3, 5-50
d_curkey 5-18
d_dbdpath 5-3, 5-10, 8-25
d_dbfpath 5-3, 5-10, 8-25
d_dblog 5-3, 5-10, 6-6, 7-3
d_dbtaf 5-3, 5-10, 6-2, 6-6, 7-4
d_dbtmp 5-3
d_dbuserid 5-3, 5-9, 5-10, 6-2, 7-3, 8-25
d_decode_dba 5-18, 5-33, 5-50
d_delete 3-16, 5-39, 8-25
d_destroy 5-3, 5-11, 8-25
d_discon 5-38, 5-39, 8-26
d_disdel 5-39
d_encode_dba 5-18, 5-33, 5-50
d_fillnew 3-16, 5-34, 8-25
and compound keys 4-13
and d_makenew 5-35
d_findco 5-18, 5-24, 8-26
d_findfm 5-18, 8-26
d_findlm 5-18, 8-26
d_findnm 5-18, 8-26
d_findpm 5-18, 8-26
d_freeall 7-5, 7-7, 8-26
d_gtscm 7-15
d_gtsco 7-15
d_gtscr 7-15
d_gtscs 7-15
d_iclose 5-3, 5-45

Centura RDM Users Guide

d_initfile 5-3, 5-12, 8-25


and fileid 4-5
d_initialize 5-3, 5-11, 8-25
d_iopen 5-3, 5-44, 5-45
d_ismember 8-26
d_isowner 8-26
d_keydel 5-39, 8-25
and optional key values 4-10
d_keyfind 3-16, 5-18, 8-26
d_keyfree 7-5, 7-7, 7-9, 8-26
d_keyfrst 5-18, 8-26
d_keylast 5-18, 8-26
d_keylock 7-5, 7-10, 8-26
d_keylstat 7-5, 7-7, 7-12
d_keynext 3-18, 5-18, 8-26
d_keyprev 5-18, 8-26
d_keyread 3-18, 5-18, 8-26
d_keystore 5-34, 8-25
and optional key values 4-10
and optional keys 4-13, 4-25, 5-35
d_lock 7-5, 7-7, 7-11
and dal 11-9
d_lockcomm 3-14, 5-3
d_lockmgr 5-3, 5-10
d_locktimeout 7-5
d_makenew 5-34, 8-25
and compound keys 4-13
and d_crwrite 5-34
and d_fillnew 5-35
d_mapchar 5-54
d_members 7-8, 8-26
d_off_opt 5-3, 5-14, 8-25
d_on_opt 5-3, 5-14, 5-54, 8-25
d_open 3-15, 4-3, 5-3, 5-4, 5-44, 7-28,
8-25
and multiple databases 5-5
and partial path names 5-6
overriding environmental variables
5-8
shared access mode 7-4
d_rdcurr
and dal 11-9
d_rdmini 5-3

Centura RDM Users Guide

and dal 11-9


d_recfree 7-5, 7-7, 7-9, 8-26
d_recfrst 5-18, 5-31, 7-8
and d_recnext loop 5-32
d_reclast 5-18, 5-32, 7-8
d_reclock 7-5, 7-10, 8-26
d_reclstat 7-5, 7-7, 7-11
d_recnext 5-18, 5-32, 7-8
d_recprev 5-18, 5-32, 7-8
d_recread 3-16, 3-17, 5-18, 5-33, 7-8, 8-25
d_recset 5-18
d_recstat 7-14
d_recwrite 5-38, 8-25
tips 5-38
d_renclean 5-3, 5-11
d_renfile 5-3, 5-10, 5-11
and dal 11-9
and fileid 4-5
d_rerdcurr
and dal 11-9
d_rlbclr 7-17, 8-27, 8-42
d_rlbset 7-17, 8-27, 8-41
d_rlbtst 7-17, 7-18, 8-42
d_set_dberr 5-43
d_setdb 5-46
d_setfiles 5-3, 5-12, 8-25
d_setfree 7-5, 7-7, 7-9, 8-26
d_setkey 5-34, 8-25
d_setlock 7-5, 7-10, 8-26
d_setlstat 7-5, 7-7, 7-11
d_setmm 5-17, 8-27
d_setmo 5-17, 8-27
d_setmr 5-17, 8-27
d_setom 5-17, 8-27
d_setoo 5-17, 8-27
d_setor 5-17, 8-27
d_setpages 5-3, 5-13, 8-25
arguments 6-5
d_setrm 5-17, 8-27
d_setro 5-17, 8-27
d_setXY naming convention 5-16
d_stscm 7-15
d_stsco 7-15

Index-3

d_stscr 7-15
d_stscs 7-15
d_timeout 7-5, 7-7, 7-9
d_trabort 6-3, 8-26, 8-40
and lock bit settings 7-17
d_trbegin 6-3, 6-4, 7-10, 8-26, 8-40
d_trend 6-3, 6-4, 8-26, 8-40
d_wrcurr
and dal 11-9
dal 3-7, 11-1
commands
abort 11-5
curr 11-5
def_fld 11-4
def_rec 11-4
exit 11-5
input 11-6
print 11-7
rewind 11-7
schema 11-8
whileok 11-8
definition of 3-3
variables 11-4
data
entry 7-19
exporting 10-22
importing 10-5, 10-22
integrity 7-2
model 2-3
hierarchical 2-8
network 2-4
relational 2-8, 2-9
transfer 10-1
data fields
declaration syntax 4-9
defined 2-1
key 4-10
data file 2-11, 4-5
dump utility 13-1
structure 14-3
database
control functions 5-2
defined 2-1

Index-4

errors
preventing 7-13
initialization 3-2
modular 4-31
repair of corrupted 12-1
temporary 4-31
Database Access Language. See dal
database address 4-10, 5-15, 14-4
file number 14-4
slot number 14-4
Database Definition Language. See
DDL.
database design 4-1, 14-1 to 14-33
example 4-36
logical design considerations 4-22
multiple database usage 4-31
physical design considerations 4-32
use of keys 4-22
use of sets 4-26
database editor 12-1
database initialization 5-11, 13-3
database manipulation 5-1
database models
combined 2-9
hierarchical 2-8
network 2-4
relational 2-4
database name 4-3
length of 4-3
truncation 4-3
database statement 4-3
database table 14-29
database transfer 10-22
restrictions 10-22
datdump 5-51, 13-1
and Unicode 9-8
definition of 3-5
DB_ADDR 4-10, 8-11
db_QUERY 1-2
and Unicode 9-7
definition of 3-5
in context switching 5-48
db_REVISE 1-2

Centura RDM Users Guide

and Unicode 9-7


definition of 3-5
used to convert ddlp 4-21
DB_SHORT 14-15
db_status 5-42
DB_TASK parameter 5-48
dbcheck 7-18, 13-2, 14-12
and dbedit 12-1
definition of 3-4
dbclrlb 3-3, 7-18, 13-5
DBD files
and Unicode 9-8
DBDPATH 5-5, 5-6, 8-2
in context switching 5-47
dbedit 12-1
and environment variables 12-2
definition of 3-4
dbedit commands
base 12-9
display 12-2
edit 12-6
exit 12-9
fields 12-9
goto 12-5
help 12-2
hex 12-7
nofields 12-9
notitles 12-9
reread 12-9
show 12-4
titles 12-9
verify 12-9
dberr 5-42
dbexp 10-1, 10-3
definition of 3-4
with dbimp 10-22
DBFPATH 5-5, 5-6, 8-2
in context switching 5-47
dbimp 10-1, 10-5
and set ordering 10-22
and set record types 10-22, 10-23
and Unicode 9-8
definition of 3-4

Centura RDM Users Guide

with dbexp 10-22


DBL files
and Unicode 9-10, 9-11
DBLOG 5-9, 6-2, 6-6, 7-3
dbn parameter 5-45
dbname 4-3
dbname.dbd 5-4, 8-1, 8-2, 14-16
dbname.h 5-45
DBNMLEN 14-30
DBTAF 5-9, 6-2, 6-6, 7-4
dbtype.h 14-15
DBUSERID 5-9, 6-2, 7-3
in context switching 5-47
dbuserid.log 6-2
dchain 13-3
DCHAINUSE 14-10
DDL
comments 4-2
compound key 4-12
cross-reference
records, fields, sets 4-17
data file statement 4-5
database statement 4-3
field statement 4-10
identifiers 4-2
key file statement 4-5
ordering of statements 4-2
record statement 4-7
set statement 4-14
timestamp statement 4-4
DDL processor 3-6
ddlp 3-7, 3-10, 4-13, 14-16
alignment of 4-20
and compound keys 5-23
and Unicode 9-8
case sensitivity 4-18
definition of 3-1
duplicate field names 4-17
file structure report 4-34
operation 4-16
syntax 4-16
deadlock 7-9
avoiding 6-4, 7-9, 7-11

Index-5

delete chain 14-9


enabling/disabing use of 5-14
key file 14-14
sort utility 13-3
Delete_key command 8-10
deletion of data 5-39, 7-21
dialog boxes 8-28
dictionary 2-2, 2-11, 3-1, 3-11, 4-16, 13-5
file 14-16
name 4-3
table structure 14-15
direct access functions 5-18
and currency 5-32
listed 5-31
directory separator character 5-9
directref 4-10
DLL
Microsoft Windows 14-33
dproto.h 14-32
dt_ 5-48
dt_closetask 5-48
dt_newcache 5-48
dt_opentask 5-48

system 5-42
user 5-42
escape characters 10-6
examples
checking account 2-1, 2-6, 2-8, 4-1,
4-3, 4-4, 4-6, 4-8, 4-11, 4-17, 4-18,
4-23, 4-25, 5-19, 5-24
DDL specification 4-1
family information database 10-7
full family tree database 10-14
library database 10-9
m.o. (modus operandi) 5-20
tims 3-8, 4-36, 5-4, 5-16, 5-22, 5-26,
5-35, 5-39, 6-1, 7-4, 7-5, 7-19, 7-21,
7-23, 7-24, 7-25, 7-26, 10-3
vehicle make 4-23
exclusive locks
freeing 7-9
exporting
and importing 10-22
definition of 10-1
maintaining set information 10-4
string conversion 10-4

E
edit command 8-9
efficiency
data entry 7-19
tips 4-33
end transaction 6-3
entity
defined 2-1
environment
control functions 5-9
files 5-4, 5-12, 5-14
path name 5-5
variables 5-5
error codes
function status codes 5-42
system error codes 5-42
user error codes 5-42
errors
reporting 5-42

F
failure
recovery 6-5
family information database 10-7
family tree database example 10-14
field 4-10
declaration 4-10
defined 2-1
field name constants 4-20
field names
restrictions 4-10
field table 14-20
file 2-1
declaration 4-5
defined 2-1
dictionary 5-5
format 10-1
header 14-2
identifier 4-5

Index-6

Centura RDM Users Guide

initialization 5-12
key file structure 14-10
lock types 7-7
locking 7-4
tips 7-18
names 4-5
maximum length 4-5
node 14-10
number open 5-12
page 14-10
length 14-2
sizes 4-36
report
structure 4-34
slot size 14-3
structure 4-32, 14-2
structure report 4-16, 4-34
substitution of 5-10
table 14-18
transfer 10-1
file menu 8-30
find functions 5-24
function prototyping 14-32
function statuses 5-42
G
GLOBALALLOCS 5-15
grouped lock request 7-10
H
header file 3-7, 3-11, 4-7, 4-18, 4-20,
14-30
file name 4-3
hex edit mode 12-2
hexadecimal editing 12-2
hierarchical database model 2-8
I
ida 3-7, 5-51, 5-55, 8-1
database access commands
Currency 8-18
Free 8-23
Lock 8-22
Misc 8-24

Centura RDM Users Guide

Record 8-14
Set 8-17
Transaction 8-21
definition of 3-3
field editing 8-10
function cross-reference 8-25
record manipulation functions 8-14
utility commands
Access 8-6
Close 8-7
Initialize 8-7
Open 8-6
Parameters 8-7
Quit 8-8
timestamping 7-13
import specification
language 10-7
statements 10-8, 10-9
connect 10-10
create on 10-10
find on 10-14
update on 10-14
importing
and exporting 10-22
definition of 10-1
string conversion 10-4
importing data
restrictions on ASCII files 10-2
index, definition 2-2
indexed access 2-10
init command 8-9
initdb 3-7, 3-12, 13-3
definition of 3-2
integrity of data 7-2
Interactive Database Access. See ida
international character sets 5-50
intersection record 4-27
K
keep locks 7-10
key
defined 2-2
duplicate 4-10

Index-7

field 2-11
maximum length 4-10
optional 4-10
placement of 4-33
primary 5-33
rebuilding 13-3
retrieval 5-18
scan 2-2
unique 4-10
usage 4-22
usage for data retrieval 5-19
key file 2-2, 2-11, 4-5
dump utility 13-4
node 14-10
packing utility 13-4
page 14-10
structure 14-10
key menu 8-32
keybuild 13-3
definition of 3-4
keydump 5-51, 13-4
definition of 3-5
keypack 13-4
definition of 3-4
keys
compound 5-22
validation of coded fields 5-19
keywords
printing with pr_keywords 5-28
L
leaf node 14-12
library database example 10-9
linked list 4-14
linking 3-19
LINT_ARGS 14-32
lmclear
definition of 3-3
LocalAlloc 5-15
lock 7-1
advisory 7-17
downgrading 7-10
exclusive

Index-8

freeing 7-9
file 7-4, 7-18
granting 7-10
grouped request 7-10
manager 7-3
read 7-8
record 7-17, 7-23
request 7-3
request packet 7-20
static record 7-12
status 7-7, 7-11
timeout 7-9
types of 7-7
upgrading 7-10
write 7-9
lock bit
and d_trabort 7-17
clearing 7-17
setting 7-17
testing 7-18
within transactions 7-17
lock manager 3-7
and Unicode 9-9
definition of 3-3
single-user modes 7-27, 7-28
LOCK_REQUEST 7-11
locks menu, free types option 8-41
log file 5-9, 7-3
M
m.o. (modus operandi) example 4-24,
5-20
many-to-many 4-26, 5-25, 5-26
and intersection records 4-27
member 2-4 to 2-7, 4-14
pointer 14-5
space requirements 4-32
member table 14-23
memory 3-10, 4-16, 5-4, 5-13
Microsoft Windows
allocating memory in 5-15
modification of data 5-38, 7-22
modular database 4-31

Centura RDM Users Guide

multiple database access 4-31, 5-44,


14-29
accessing 5-45
opening 5-44
multi-user control 7-1
data deletion 7-21
data entry 7-19
data modification 7-22
deadlock 7-9
environment 7-3
file locking 7-4
guidelines 7-18
record locking 7-17
timestamping 7-12
user id 7-3
N
navigation 5-15, 5-23
nested structures 4-21
network database model
compared with relational 2-9
defined 2-4
next command 8-9
NO_CONST 14-32
node 14-10
notational conventions 1-4
Novell 6-7
null byte 4-10
O
one-to-many 2-4, 4-14
one user mode 7-28
open files limit 5-12
opening database 5-4
operational flow 3-6
option settings 5-14
d_off_opt 5-14
d_on_opt 5-14
optional keys 4-10, 4-25
d_keystore 5-35
options menu 8-43
orphan pointer 14-13
owner 2-4 to 2-8, 4-14

Centura RDM Users Guide

owner command 8-10


P
page buffers 5-13
size 4-36
page size 4-3, 4-5, 4-36
default 4-3
determining optimal 4-36
page zero contents 14-2
Parameters Dictionary_path 8-2
Parameters Files_path 8-2
Pascal calling convention 14-33
path name 4-5, 5-5
path specifications 5-6
overriding default drive 5-7
overriding defaults with d_open 5-8
using defaults 5-7
PATHLENN 14-30
pgsize parameter 4-3
pointer
child 14-12
orphan 14-13
prdbd 13-5, 14-25
definition of 3-5
used to examine ddlp alignment 4-20
prev command 8-10
primary key 5-33
process 7-3
programming errors 5-42
proto.h 14-32
R
range checking 5-19
RDM directory structure 3-19
rdm.ini 5-4, 5-9, 5-50, 5-55, 6-2, 6-6, 7-3,
7-4, 12-2
read lock 7-8
README.TXT file 1-4
rebuilding key files 13-3
record
creation
delete chain use 14-10
DDL declaration 4-7

Index-9

defined 2-1
lock 7-23
lock bit 7-17
and d_trabort 7-17
clearing 7-17
setting 7-17
testing 7-18
within transactions 7-17
locking 7-17, 7-23
name
case sensitivity 4-7
constants 4-20
occurrence 2-1
new 5-34
placement of 4-33
static 7-12, 7-27
structure 14-7
table 14-19
type 2-1, 2-10, 2-11
unused space 4-35
variable-length 4-29, 5-26
record menu 8-36
records dialog box 8-28
recovery 6-1
automatic 6-6
external 6-6
redundant data 2-6
data access performance 4-39
eliminating 2-10
relatedto 4-10
relational database model 2-8, 2-9
retrieval
of data 5-18
of text 5-31
rlb_status 7-18
ROM 1-2
root node 14-13
row 2-8
runtime
control 5-12
library 3-7, 3-19, 5-1
definition of 3-3

Index-10

S
S_DBOPEN 5-4
S_DELETED 7-8, 7-14
S_DUPLICATE 3-16, 4-10
S_EOS 5-37
S_INVDB 5-44
S_LOCKED 7-17, 7-18
S_NOMEMORY 5-4, 5-13
S_NOSPACE 5-42
S_NOTFOUND 3-16, 5-42
S_NOTLOCKED 7-16, 7-17
S_OKAY 5-1, 7-14
S_RECOVERY 6-7
S_TIMESTAMP 7-16
S_TRACTIVE 6-3
S_TRNOTACT 7-9
S_UNAVAIL 7-4, 7-9, 7-17
S_UNLOCKED 7-18
S_UPDATED 7-14
schema 2-2, 3-1
changing 10-22
diagrams 2-5
separator characters 10-6
sequential access 2-10
sequential access functions
and currency 5-32
listed 5-31
set
declaration syntax 4-14
defined 2-4
many-to-many 4-26, 5-25, 5-26
member 2-5
multiple member 4-30, 5-26
name constants 4-20
navigation 5-15, 5-18, 5-23
ordering 4-14, 10-22
owner 2-5
pointer
space requirements 4-32
usage 4-26, 5-23
set member pointer 14-5
set menu 8-34

Centura RDM Users Guide

set pointer 14-5


set table 14-22
sharecache 5-48
shared access mode 7-4
slot size 14-3
sort table 14-23
sorting 4-14
case-insensitive 5-14, 5-53
space requirements
control information 4-32
special menu 8-42
SQL 3-5
static attribute 7-12
static record 4-7, 7-12, 7-27
status codes 5-42
store_key command 8-10
strings 4-10
struct 4-7, 4-13, 4-18, 8-9, 8-11, 8-15
sub-fields 4-10, 8-11
substituting database files 5-10
system components 3-1
system record 2-10, 4-6, 4-14
creation 4-14
T
table 2-8
defined 2-1
TAF files 6-2, 6-6, 7-4
and Unicode 9-10, 9-11
task switching 5-47
temporary database 4-31
text editor 4-2
timeout 7-3, 7-9
timestamp
currency functions 7-15
space requirements 4-32
status functions 7-14
timestamping 7-12
overhead 7-14
tims
database examples 5-5
DDL specification 4-40

Centura RDM Users Guide

example 3-8, 4-36, 5-4, 5-16, 5-22, 5-26,


5-35, 5-39, 6-1, 7-4, 7-5, 7-19, 7-21,
7-23, 7-24, 7-25, 7-26, 10-3
tims.h 3-19
transaction
abort 6-3
activity file 5-9, 7-4
archive log 6-7
begin 6-3
commit 6-1, 6-6
definition of 6-1
end 6-3
logging 6-1
disabling 5-14
no nesting 6-3
overflow 6-4
rate 4-25
recovery 6-5
transaction activity file. See TAF files
transaction processing 6-3
trlog.c 6-7
U
Unicode
ANSI conversion 9-2
compatibility 9-10
data fields 9-5
function names 9-6
implementation 9-3
prototype functions 9-11 to 9-12
RDM support 9-1 to 9-12
string fields 9-1
wchar_t data type 9-2
unique key 4-10, 4-23
UNIX
Unicode support 9-1
unlocked reads 7-8
unused page space 4-35
user identifier 5-9, 7-3
userid.log 5-4
utilities
and Unicode 9-8
console 3-5

Index-11

d_open 5-8
dal 3-3, 3-7, 11-1
datdump 3-5, 13-1
dbcheck 3-4, 13-2, 14-12
and dbedit 12-1
dbclrlb 13-5
dbedit 3-4, 12-1
and environment variables 12-2
base 12-9
display 12-2
edit 12-6
exit 12-9
goto 12-5
help 12-2
hex 12-7
nofields 12-9
notitles 12-9
reread 12-9
show 12-4
verify 12-9
dbexp 3-4, 10-1, 10-3
with dbimp 10-22
dbimp 3-4, 10-1, 10-5
and set ordering 10-22
with dbexp 10-22
dchain 13-3

Index-12

ddlp 3-1, 3-7, 14-16


ida 3-3, 3-7, 8-1
initdb 3-2, 3-7, 13-3
keybuild 3-4, 13-3
keydump 3-5, 13-4
keypack 3-4, 13-4
prdbd 3-5, 13-5, 14-25
wida 8-28
V
variable-length records 4-29, 5-26
vehicle make example 4-23, 5-19
virtual memory 5-13
vista.ctb 5-4, 5-50, 5-53
vista.h 3-7, 3-13, 3-19, 5-42
vista.taf 5-4, 5-9, 6-2
W
wida
function cross-reference 8-45
wida dialog boxes 8-28
Windows Interactive Database Access.
See wida
write command 8-10
write lock 7-9

Centura RDM Users Guide