c-core/03_core/core03Example_main.c
/*
 * 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.
 */
 
#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 "core03_structs.h"
 
/* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
 */
#include "core03_cat.h"
 
const char *const description =
    "Demonstrates associating rows in one table with a row in another table";
const RDM_CMDLINE_OPT opts[] = {{NULL, NULL, NULL, NULL}};
 
RDM_RETCODE insertArtist (
    RDM_DB hDB,               
    const char *artistName,   
    RDM_CURSOR *artistCursor) 
{
    RDM_RETCODE rc;
    ARTIST artist_rec;
 
    artist_rec.id = 0;
    strncpy (artist_rec.name, artistName, sizeof (artist_rec.name));
    rc = rdm_dbInsertRow (
        hDB, TABLE_ARTIST, &artist_rec, sizeof (artist_rec), artistCursor);
    print_error (rc);
    return rc;
}
 
RDM_RETCODE insertAlbums (
    RDM_DB hDB,              
    RDM_CURSOR artistCursor, 
    const char **albumList,  
    size_t listSize)         
{
    RDM_RETCODE rc = sOKAY;
    int ii;
 
    for (ii = 0; ii < (int) listSize; ii++)
    {
        ALBUM album_rec;
        RDM_CURSOR albumCursor = NULL;
 
        strncpy (album_rec.title, albumList[ii], sizeof (album_rec.title));
        album_rec._id_has_value = RDM_FALSE/* Mark the row as unlinked */
        rc = rdm_dbInsertRow (
            hDB, TABLE_ALBUM, &album_rec, sizeof (album_rec), &albumCursor);
        print_error (rc);
 
        if (rc == sOKAY)
        {
            /* associate the added row to the artist */
            rc = rdm_cursorLinkRow (albumCursor, REF_ALBUM_ID, artistCursor);
            print_error (rc);
 
            rdm_cursorFree (albumCursor);
        }
    }
    return rc;
}
 
RDM_RETCODE readAllAlbums (
    RDM_DB hDB) 
{
    RDM_RETCODE rc;
    RDM_CURSOR artistCursor = NULL;
    RDM_CURSOR albumCursor = NULL;
 
    rc = rdm_dbStartRead (hDB, RDM_LOCK_ALL, 0, NULL);
    print_error (rc);
 
    if (rc == sOKAY)
    {
        /* read the ARTIST table in table order */
        rc = rdm_dbGetRows (hDB, TABLE_ARTIST, &artistCursor);
        print_error (rc);
    }
 
    if (rc == sOKAY)
    {
        for (rc = rdm_cursorMoveToFirst (artistCursor); rc == sOKAY;
             rc = rdm_cursorMoveToNext (artistCursor))
        {
            char Artist[RDM_COLUMN_SIZE (ARTIST, name)];
 
            /* We found an artist row, read the contents */
            rc = rdm_cursorReadColumn (
                artistCursor, COL_ARTIST_NAME, Artist, sizeof (Artist), NULL);
            print_error (rc);
 
            if (rc == sOKAY)
            {
                printf ("\nArtist: %s\n", Artist);
                /* read the album rows associated with the artist*/
                rc = rdm_cursorGetMemberRows (
                    artistCursor, REF_ALBUM_ID, &albumCursor);
                print_error (rc);
 
                if (rc == sOKAY)
                {
                    printf ("\nAlbums:");
                    for (rc = rdm_cursorMoveToFirst (albumCursor); rc == sOKAY;
                         rc = rdm_cursorMoveToNext (albumCursor))
                    {
                        char Title[RDM_COLUMN_SIZE (ALBUM, title)];
 
                        /* We found an album row, read the contents*/
                        rc = rdm_cursorReadColumn (
                            albumCursor, COL_ALBUM_TITLE, Title, sizeof (Title),
                            NULL);
                        print_error (rc);
 
                        if (rc == sOKAY)
                        {
                            printf ("\t%s\n", Title);
                        }
                    }
                    /* We expect rc to be sENDOFCURSOR when we break out of the
                     * loop */
                    if (rc == sENDOFCURSOR)
                    {
                        rc = sOKAY/* change status to sOKAY because
                                        sENDOFCURSOR was expected. */
                    }
                    else
                    {
                        print_error (rc);
                    }
                }
            }
        }
        /* We expect rc to be sENDOFCURSOR when we break out of the loop */
        if (rc == sENDOFCURSOR)
        {
            rc = sOKAY/* change status to sOKAY because sENDOFCURSOR was
                            expected. */
        }
        else
        {
            print_error (rc);
        }
        if (albumCursor)
            rdm_cursorFree (albumCursor);
        if (artistCursor)
            rdm_cursorFree (artistCursor);
 
        rdm_dbEnd (hDB);
    }
    return rc;
}
 
static const char *doors_albums[] = {"The Doors""Strange Days",
                                     "Waiting for the Sun"};
 
static const char *stones_albums[] = {"The Rolling Stones""Out of Our Heads",
                                      "Beggars Banquet""Tattoo You"};
 
static const char *nirvana_albums[] = {"Bleach""Nevermind""In Utero"};
 
RDM_RETCODE insertAllArtists (RDM_DB hDB)
{
    RDM_RETCODE rc;
    RDM_CURSOR artistCursor = NULL;
 
    rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
    print_error (rc);
    if (rc == sOKAY)
    {
        rc = insertArtist (hDB, "The Doors", &artistCursor);
        print_error (rc);
 
        if (rc == sOKAY)
        {
            rc = insertAlbums (
                hDB, artistCursor, doors_albums,
                (sizeof (doors_albums) / sizeof (char *)));
        }
 
        /* if insert of both Artist and Album are ok,
         * commit the transaction, otherwise roll it back */
        if (rc == sOKAY)
            rc = rdm_dbEnd (hDB);
        else
            rc = rdm_dbEndRollback (hDB);
    }
 
    rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
    print_error (rc);
    if (rc == sOKAY)
    {
        rc = insertArtist (hDB, "The Rolling Stones", &artistCursor);
        if (rc == sOKAY)
        {
            rc = insertAlbums (
                hDB, artistCursor, stones_albums,
                (sizeof (stones_albums) / sizeof (char *)));
        }
 
        /* if insert of both Artist and Album are ok,
         * commit the transaction, otherwise roll it back */
        if (rc == sOKAY)
            rc = rdm_dbEnd (hDB);
        else
            rc = rdm_dbEndRollback (hDB);
    }
 
    rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
    print_error (rc);
    if (rc == sOKAY)
    {
        rc = insertArtist (hDB, "Nirvana", &artistCursor);
        if (rc == sOKAY)
        {
            rc = insertAlbums (
                hDB, artistCursor, nirvana_albums,
                (sizeof (nirvana_albums) / sizeof (char *)));
        }
 
        /* if insert of both Artist and Album are ok,
         * commit the transaction, otherwise roll it back */
        if (rc == sOKAY)
            rc = rdm_dbEnd (hDB);
        else
            rc = rdm_dbEndRollback (hDB);
    }
    return rc;
}
 
int main_core03 (int argc, const char *const *argv)
{
    RDM_TFS hTFS;
    RDM_DB hDB;
    RDM_RETCODE rc;
 
    rc = rdm_cmdlineInit (&cmd, argc, argv, description, opts);
    if (rc != sCMD_USAGE)
        print_error (rc);
    if (rc == sOKAY)
    {
        rc = exampleOpenEmptyDatabase (&hTFS, &hDB, "core03", core03_cat);
        if (rc == sOKAY)
        {
            rc = insertAllArtists (hDB);
            if (rc == sOKAY)
            {
                rc = readAllAlbums (hDB);
            }
            exampleCleanup (hTFS, hDB);
        }
    }
 
    return (int) rc;
}
 
#define RDM_COLUMN_SIZE(table, column)
Macro for getting the size of a column in the struct definition.
Definition: rdmtypes.h:197
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_FALSE
Definition: psptypes.h:59
RDM_RETCODE rdm_dbEnd(RDM_DB db)
End a transactional operation.
@ sCMD_USAGE
Definition: rdmretcodetypes.h:71
struct RDM_CURSOR_S * RDM_CURSOR
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.
The buffer used by the command line parser to hold state information.
Definition: rdmcmdlinetypes.h:85
RDM_RETCODE rdm_cursorLinkRow(RDM_CURSOR cursor, RDM_REF_ID refId, RDM_CURSOR cursorOwner)
Link a row to an owner.
@ sOKAY
Definition: rdmretcodetypes.h:95
Generic usage function option record.
Definition: rdmcmdlinetypes.h:32
RDM_RETCODE rdm_cursorFree(RDM_CURSOR cursor)
Free an RDM_CURSOR.
#define RDM_STARTUP_EXAMPLE(name)
Definition: rdmstartuptypes.h:73
RDM_RETCODE rdm_dbGetRows(RDM_DB db, RDM_TABLE_ID tableId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with rows based on a table id.
RDM_RETCODE rdm_dbEndRollback(RDM_DB db)
End and rollback a transactional operation.
RDM_RETCODE rdm_cursorGetMemberRows(RDM_CURSOR ownerCursor, RDM_REF_ID refId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with members.
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.
RDM_RETCODE rdm_cursorReadColumn(RDM_CURSOR cursor, RDM_COLUMN_ID columnId, void *columnValue, size_t bytesIn, size_t *bytesOut)
Read a single column from a table row.
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
#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:58
Internal RDM Startup API used by startup macros.
RDM_RETCODE
RDM status and error return codes.
Definition: rdmretcodetypes.h:43