Multiple databases. Create and initialize two databases. Populate them. Incrementally open them in the same task. Use 'database number' to demonstrate usage of both databases from same task. This example needs a compiled schema, core08.sdl.

* Raima Database Manager
* Copyright (c) 2019 Raima Inc., All rights reserved.
* Use of this software, whether in source code format, or in executable,
* binary object code form, is governed by the Raima LICENSE which
* is fully described in the LICENSE.TXT file, included within this
* distribution of files.
/* \file
* \brief Source code for the RDM core08 example
#include <stdio.h>
#include <string.h>
#include "example_fcns.h"
#include "rdm.h"
#include "rdmstartupapi.h"
/* Generated \c struct and \c typedef definitions to be used with the RDM APIs
#include "core08_structs.h"
/* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
#include "core08_cat.h"
const char *const description = "Demonstrates using an index for ordering";
const RDM_CMDLINE_OPT opts[] = {{NULL, NULL, NULL, NULL}};
* \mainpage Core08 Popcorn Example
* Each time you run this example:
* \li The database is initialized (all existing contents removed)
* \li Several new offices are added to the NA database
* \li Several new offices are added to the EMEA database
* \li Data is queried from the NA office
* \li Data is queried from the EMEA office
* \par Table of Contents
* - \subpage hDB
* - \subpage hPGMfunc
* For additional information, please refer to the product documentation at
* \page hDB Database Schema
* \par Database Schema Definition
* The DDL (Database Definition Language) specification for the database used
* in this example is located in the file \c core08.sdl.
* \include core08.sdl
* The schema was compiled using the RDM rdm-compile utility with the -s option
* to generate C-structures for interfacing with the database.
* \code rdm-compile -s core08.sdl \endcode
* Each of these functions returns an integer status code, where the
* value sOKAY indicates a successful call.
* The actual databases will be stored in a directories named 'na_sales_db' and
* 'emea_sales_db' in the project directory.
* \page hPGMfunc Program Functions
* For simplicity, this example does not check all return codes, but good
* programming practices would dictate that they are checked after each
* RDM call.
* \li openEmptyDatabase() - \copybrief openEmptyDatabase
* \li display_offices() - \copybrief display_offices
* \li main() - \copybrief main
/* \brief Display the contents of the database
* This function displays the contents of the database.
* Exclusve mode does not require database locks or transactions.
* @return Returns RDM_RETCODE status code (sOKAY if successful)
RDM_RETCODE display_offices (RDM_DB hDB) /*< [in] Database handle to be used */
OFFICE office_rec;
rc = rdm_dbStartRead (hDB, RDM_LOCK_ALL, 0, NULL);
if (rc == sOKAY)
/* The following cursor association call will allocate the cursor
* if the cursor is set to NULL. This short-cut can eliminate the
* requirement to call rdm_dbAllocCursor() before using the cursor
* in this function */
rc = rdm_dbGetRowsByKey (hDB, KEY_OFFICE_NAME, &cursor);
for (rc = rdm_cursorMoveToFirst (cursor); rc == sOKAY;
rc = rdm_cursorMoveToNext (cursor))
/* Read and display the current person record */
cursor, &office_rec, sizeof (office_rec), NULL);
printf ("%s\n",;
/* free the cursor if it was allocated */
if (cursor)
rdm_cursorFree (cursor);
/* Expect rc to be S_NOTFOUND when we exit the loop */
if (rc == sENDOFCURSOR)
rc = sOKAY;
rdm_dbEnd (hDB);
return rc;
RDM_RETCODE insertOffices (RDM_DB hDB, const char **officeList, size_t listSize)
OFFICE office_rec;
rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
if (rc == sOKAY)
int ii;
for (ii = 0; ii < (int) listSize; ii++)
strncpy (, officeList[ii], sizeof (;
hDB, TABLE_OFFICE, &office_rec, sizeof (office_rec), NULL);
if (rc == sOKAY)
rc = rdm_dbEnd (hDB);
rc = rdm_dbEndRollback (hDB);
return rc;
static const char *na_office_names[] = {"Seattle", "Boise", "San Francisco",
static const char *emea_office_names[] = {"Paris", "London", "Dublin", "Zurich",
/* \brief Macro to determine number of elements in an array of ptrs */
#define RLEN(x) (sizeof (x) / sizeof (x[0]))
/* \brief Main function for core08 example
* The function initializes the RDM environment and runs the create, read
* operations.
* @return Returns the RDM_RETCODE on exit.
int main_core08 (int argc, const char *const *argv)
rc = rdm_cmdlineInit (&cmd, argc, argv, description, opts);
if (rc != sCMD_USAGE)
if (rc == sOKAY)
rc = exampleAllocTFS (&hTFS);
/* Open the NA database for exclusive access, this will create the
* database dictionary. */
if (rc == sOKAY)
hTFS, &hNADB, "core08NA", core08_cat);
/* Open the EMEA database, this will create the database
* dictionary. */
if (rc == sOKAY)
hTFS, &hEMEADB, "core08EMEA", core08_cat);
/* create records in the NA database */
if (rc == sOKAY)
rc = insertOffices (hNADB, na_office_names, RLEN (na_office_names));
/* create records in the EMEA database */
if (rc == sOKAY)
rc = insertOffices (
hEMEADB, emea_office_names, RLEN (emea_office_names));
/* Display all offices in North America */
printf ("\nNorth American Offices\n");
if (rc == sOKAY)
rc = display_offices (hNADB);
/* Display All offices in EMEA */
printf ("\nEMEA Offices\n");
if (rc == sOKAY)
rc = display_offices (hEMEADB);
/* close the database */
rdm_dbFree (hEMEADB);
rdm_dbFree (hNADB);
rdm_tfsFree (hTFS);
return 0;
RDM_RETCODE rdm_cursorMoveToFirst(RDM_CURSOR cursor)
Position a cursor to the first row in the collection.
RDM_RETCODE rdm_cursorMoveToNext(RDM_CURSOR cursor)
Position a cursor to the next row in the collection.
Header for the native RDM Runtime API.
RDM_RETCODE rdm_dbEnd(RDM_DB db)
End a transactional operation.
Definition: rdmretcodetypes.h:72
Definition: rdmtypes.h:304
RDM_RETCODE rdm_dbStartRead(RDM_DB db, const RDM_TABLE_ID *tableIds, uint32_t numTableIds, RDM_TRANS *pTrans)
Get read locks.
RDM_RETCODE rdm_cursorReadRow(RDM_CURSOR cursor, void *colValues, size_t bytesIn, size_t *bytesOut)
Read all columns from a row.
The buffer used by the command line parser to hold state information.
Definition: rdmcmdlinetypes.h:85
#define exampleOpenNextEmptyDatabase(tfs, db, name, catalog)
Definition: example_fcns.h:45
RDM_RETCODE rdm_dbGetRowsByKey(RDM_DB db, RDM_KEY_ID keyId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with a row set based on a key.
RDM_RETCODE rdm_dbFree(RDM_DB db)
Free a database handle.
#define print_error(rc)
Definition: example_fcns.h:34
Definition: rdmretcodetypes.h:96
Generic usage function option record.
Definition: rdmcmdlinetypes.h:32
RDM_RETCODE rdm_cursorFree(RDM_CURSOR cursor)
Definition: rdmstartuptypes.h:73
RDM_RETCODE rdm_dbEndRollback(RDM_DB db)
End and rollback a transactional operation.
#define RLEN(x)
Definition: example_fcns.h:51
RDM_RETCODE rdm_dbInsertRow(RDM_DB db, RDM_TABLE_ID tableId, const void *colValues, size_t bytesIn, RDM_CURSOR *pCursor)
Insert a new row into a table at the specified rowId.
struct RDM_TFS_S * RDM_TFS
RDM TFS Handle.
Definition: rdmtfstypes.h:21
RDM_RETCODE rdm_cmdlineInit(RDM_CMDLINE *cmd, int32_t argc, const char *const argv[], const char *description, const RDM_CMDLINE_OPT *opts)
Initialize an RDM_CMDLINE buffer and validate the command line.
struct RDM_DB_S * RDM_DB
Definition: rdmtypes.h:303
Terminate a TFS service.
#define RDM_LOCK_ALL
Definition: rdmtypes.h:170
RDM_RETCODE rdm_dbStartUpdate(RDM_DB db, const RDM_TABLE_ID *writeTableIds, uint32_t numWriteTableIds, const RDM_TABLE_ID *readTableIds, uint32_t numReadTableIds, RDM_TRANS *pTrans)
Get write locks.
Definition: rdmretcodetypes.h:59
Internal RDM Startup API used by startup macros.
RDM status and error return codes.
Definition: rdmretcodetypes.h:44