core12Example_main.c

Transaction abort. Commit one transaction, then begin another transaction and abort it. Navigate through created records to see only committed records. This example needs a compiled schema, core12.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 core12 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 "core12_structs.h"
/* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
*/
#include "core12_cat.h"
const char *const description = "Demonstrates transaction commit/rollback";
const RDM_CMDLINE_OPT opts[] = {{NULL, NULL, NULL, NULL}};
/*
* \mainpage Core12 Popcorn Example
*
* Each time you run this example:
* \li The database is initialized (all existing contents removed)
* \li A transaction is started
* \li Several NA offices are added to the database
* \li All offices in the database are displayed (including uncommitted)
* \li The transaction is committed
* \li All offices in the database are displayed (all now committed)
* \li Another transaction is started
* \li Several EMEA offices are added to the database
* \li All offices in the database are displayed (including uncommitted)
* \li The transaction is rolled back
* \li All offices in the database are displayed (uncommitted EMEA offices
* are no longer in the database)
*
* \par Table of Contents
*
* - \subpage hDB
* - \subpage hPGMfunc
*
* For additional information, please refer to the product documentation at
* http://docs.raima.com/.
*
* \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 core12.sdl.
*
* \include core12.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 core12.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 Initialize the RDM runtime library for use in the core12 example
*
* This function initializes the RDM Transactional File Server (TFS) to use
* the EMBEDED TFS implementation. It also allocates a database handle
* and opens the "core12" database in exclusive mode.
* Exclusve mode does not require database locks or transactions.
*
* @return Returns RDM_RETCODE status code (sOKAY if successful)
*/
RDM_RETCODE openEmptyDatabase (
RDM_TFS *pTFS, /*< [out] Pointer to the RDM TFS handle */
RDM_DB *pDB) /*< [out] Pointer to the RDM database handle */
{
rc = rdm_rdmAllocTFS (pTFS);
if (rc == sOKAY)
{
rc = rdm_tfsInitialize (*pTFS);
if (rc == sOKAY)
{
rc = rdm_tfsAllocDatabase (*pTFS, pDB);
if (rc == sOKAY)
{
/*
* Associate the compiled catalog with the DB handle.
* If the database does not exist on open, it will be created
* in the default DOCROOT directory.
*/
rc = rdm_dbSetCatalog (*pDB, core12_cat);
if (rc == sOKAY)
{
rc = rdm_dbOpen (*pDB, "core12", RDM_OPEN_EXCLUSIVE);
}
if (rc == sOKAY)
{
*pDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
}
if (rc == sOKAY)
{
rdm_dbEnd (*pDB);
}
/* If any of the above DB operations failed, free the DB handle
*/
if (rc != sOKAY)
{
rdm_dbFree (*pDB);
}
}
}
/* If any of the above DB operations failed, free the TFS handle */
if (rc != sOKAY)
{
rdm_tfsFree (*pTFS);
}
}
return rc;
}
/* \brief Cleanup the RDM runtime library
*
* This functions closes all open databases and cleans up the RDM TFS and
* database handles used in the core20 example.
*
* @return Returns an \c RDM_RETCODE code (\b sOKAY if successful)
*/
void cleanup (
RDM_TFS hTFS, /*< [out] Pointer to the TFS handle to be terminated */
RDM_DB hDB) /*< [out] Pointer to the DB handle to be terminated */
{
/* close the database */
/* free the database handle */
rdm_dbFree (hDB);
/* free the TFS handle */
rdm_tfsFree (hTFS);
}
/* \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;
RDM_CURSOR cursor = NULL;
/* 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 */
rc = rdm_cursorReadRow (cursor, &office_rec, sizeof (office_rec), NULL);
printf ("%s\n", office_rec.name);
}
/* free the cursor if it was allocated */
if (cursor)
rdm_cursorFree (cursor);
/* Expect rc to be sENDOFCURSOR when we exit the loop */
if (rc == sENDOFCURSOR)
{
rc = sOKAY;
}
return rc;
}
RDM_RETCODE insertOffices (RDM_DB hDB, const char **officeList, size_t listSize)
{
OFFICE office_rec;
int ii;
for (ii = 0; ii < (int) listSize; ii++)
{
strncpy (office_rec.name, officeList[ii], sizeof (office_rec.name));
hDB, TABLE_OFFICE, &office_rec, sizeof (office_rec), NULL);
}
return rc;
}
static const char *na_office_names[] = {"Seattle", "Boise", "San Francisco",
"Dallas"};
static const char *emea_office_names[] = {"Paris", "London", "Dublin", "Zurich",
"Madrid"};
/* \brief Macro to determine number of elements in an array of ptrs */
#define RLEN(x) (sizeof (x) / sizeof (x[0]))
/* \brief Main function for core12 example
*
* The function initializes the RDM environment and runs the create, read
* operations.
*
* @return Returns the RDM_RETCODE on exit.
*/
int main_core12 (int argc, const char *const *argv)
{
RDM_TFS hTFS;
RDM_DB hDB;
rc = rdm_cmdlineInit (&cmd, argc, argv, description, opts);
if (rc != sCMD_USAGE)
if (rc == sOKAY)
{
rc = openEmptyDatabase (&hTFS, &hDB);
if (rc == sOKAY)
{
rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
if (rc == sOKAY)
{
insertOffices (hDB, na_office_names, RLEN (na_office_names));
printf ("\nAll Offices before transaction commit.\n");
display_offices (hDB);
rdm_dbEnd (hDB);
if (rc == sOKAY)
{
/* Display all offices */
printf ("\nAll Offices after transaction commit.\n");
display_offices (hDB);
}
}
if (rc == sOKAY)
{
rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
if (rc == sOKAY)
{
insertOffices (
hDB, emea_office_names, RLEN (emea_office_names));
printf ("\nAll Offices before transaction commit.\n");
display_offices (hDB);
rc = rdm_dbEndRollback (hDB);
/* Display all offices */
printf ("\nAll Offices after transaction rollback.\n");
display_offices (hDB);
}
}
}
cleanup (hTFS, hDB);
}
return (int) rc;
}
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_rdmAllocTFS(RDM_TFS *phTFS)
Allocate a TFS handle.
RDM_RETCODE rdm_dbEnd(RDM_DB db)
End a transactional operation.
@ sCMD_USAGE
Definition: rdmretcodetypes.h:72
RDM_RETCODE rdm_dbDeleteAllRowsFromDatabase(RDM_DB db)
Remove all rows from a database.
struct RDM_CURSOR_S * RDM_CURSOR
Definition: rdmtypes.h:306
RDM_RETCODE rdm_cursorReadRow(RDM_CURSOR cursor, void *colValues, size_t bytesIn, size_t *bytesOut)
Read all columns from a row.
@ RDM_OPEN_EXCLUSIVE
Definition: rdmtypes.h:254
The buffer used by the command line parser to hold state information.
Definition: rdmcmdlinetypes.h:85
RDM_RETCODE rdm_dbClose(RDM_DB db)
Close the database associated with a database handle.
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_dbSetCatalog(RDM_DB db, const char *catalog)
Associate a catalog with an allocated database.
RDM_RETCODE rdm_dbFree(RDM_DB db)
Free a database handle.
RDM_RETCODE rdm_dbOpen(RDM_DB db, const char *dbNameSpec, RDM_OPEN_MODE mode)
Open an existing RDM database using the specified database handle.
#define print_error(rc)
Definition: example_fcns.h:34
@ sOKAY
Definition: rdmretcodetypes.h:96
Generic usage function option record.
Definition: rdmcmdlinetypes.h:32
RDM_RETCODE rdm_cursorFree(RDM_CURSOR cursor)
Free an RDM_CURSOR.
RDM_RETCODE rdm_tfsAllocDatabase(RDM_TFS tfs, RDM_DB *pDb)
Allocate memory for a new RDM db.
#define RDM_STARTUP_EXAMPLE(name)
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:305
RDM_RETCODE rdm_tfsFree(RDM_TFS hTFS)
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.
@ sENDOFCURSOR
Definition: rdmretcodetypes.h:59
Internal RDM Startup API used by startup macros.
RDM_RETCODE
RDM status and error return codes.
Definition: rdmretcodetypes.h:44
RDM_RETCODE rdm_tfsInitialize(RDM_TFS tfs)
Initialize a RDM_TFS instance.