c-core/10_core/core10Example_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 "core10_structs.h"
 
/* Generated catalog definition to be used with the RDM rdm_dbSetCatalog() API
 */
#include "core10_cat.h"
 
const char *const description = "Demonstrates using an index for ordering";
const RDM_CMDLINE_OPT opts[] = {{NULL, NULL, NULL, NULL}};
 
RDM_RETCODE insertArtist (
    RDM_DB hDB,             
    const char *artistName) 
{
    RDM_RETCODE rc;
 
    rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
    print_error (rc);
    if (rc == sOKAY)
    {
        ARTIST artist_rec;
 
        artist_rec.artistid = 0;
        strncpy (artist_rec.name, artistName, sizeof (artist_rec.name));
        rc = rdm_dbInsertRow (
            hDB, TABLE_ARTIST, &artist_rec, sizeof (artist_rec), NULL);
        print_error (rc);
 
        if (rc == sOKAY)
            rc = rdm_dbEnd (hDB);
        else
            rc = rdm_dbEndRollback (hDB);
 
        print_error (rc);
    }
 
    return rc;
}
 
RDM_RETCODE insertAlbum (
    RDM_DB hDB,             
    const char *artistName, 
    const char *albumTitle, 
    const char **trackList, 
    size_t listSize)        
{
    RDM_RETCODE rc;
    ALBUM album_rec;
    RDM_CURSOR albumCursor = NULL;
    RDM_CURSOR artistCursor = NULL;
    ARTIST_NAME_KEY artistKey;
 
    rc = rdm_dbStartUpdate (hDB, RDM_LOCK_ALL, 0, NULL, 0, NULL);
    print_error (rc);
    if (rc == sOKAY)
    {
        strncpy (artistKey.name, artistName, sizeof (artistKey.name));
        rc = rdm_dbGetRowsByKeyAtKey (
            hDB, KEY_ARTIST_NAME, &artistKey, sizeof (artistKey),
            &artistCursor);
        print_error (rc);
 
        if (rc == sOKAY)
        {
            strncpy (album_rec.title, albumTitle, sizeof (album_rec.title));
            album_rec.albumid = 0;
            album_rec._artistid_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_ARTISTID, artistCursor);
            print_error (rc);
        }
        if (rc == sOKAY)
        {
            int ii;
 
            for (ii = 0; ii < (int) listSize; ii++)
            {
                TRACK track_rec;
                RDM_CURSOR trackCursor = NULL;
 
                strncpy (
                    track_rec.title, trackList[ii], sizeof (track_rec.title));
                track_rec._albumid_has_value =
                    RDM_FALSE/* Mark the row as unlinked */
                rc = rdm_dbInsertRow (
                    hDB, TABLE_TRACK, &track_rec, sizeof (track_rec),
                    &trackCursor);
                print_error (rc);
 
                if (rc == sOKAY)
                {
                    /* associate the added row to the artist */
                    rc = rdm_cursorLinkRow (
                        trackCursor, REF_TRACK_ALBUMID, albumCursor);
                    print_error (rc);
 
                    rdm_cursorFree (trackCursor);
                }
            }
            if (albumCursor)
                rdm_cursorFree (albumCursor);
        }
 
        if (rc == sOKAY)
            rc = rdm_dbEnd (hDB);
        else
            rc = rdm_dbEndRollback (hDB);
 
        print_error (rc);
    }
    return rc;
}
 
RDM_RETCODE readInfoForTrack (RDM_DB hDB, const char *trackName)
{
    RDM_RETCODE rc;
 
    rc = rdm_dbStartRead (hDB, RDM_LOCK_ALL, 0, NULL);
    print_error (rc);
 
    if (rc == sOKAY)
    {
        RDM_CURSOR cursor = NULL;
        RDM_CURSOR artistCursor = NULL;
        RDM_CURSOR albumCursor = NULL;
        TRACK_TITLE_KEY trackKey;
        char albumTitle[RDM_COLUMN_SIZE (ALBUM, title)];
        char trackTitle[RDM_COLUMN_SIZE (TRACK, title)];
        char artistName[RDM_COLUMN_SIZE (ARTIST, name)];
        RDM_ROWID_T saveAlbumId;
 
        /* Find the request track using the track TITLE index */
        strncpy (trackKey.title, trackName, sizeof (trackKey.title));
        rc = rdm_dbGetRowsByKeyAtKey (
            hDB, KEY_TRACK_TITLE, &trackKey, sizeof (trackKey), &cursor);
        rc = rdm_cursorReadColumn (
            cursor, COL_TRACK_TITLE, trackTitle, RDM_COLUMN_SIZE (TRACK, title),
            NULL);
        printf ("\nInformation about the track \"%s\"\n", trackTitle);
 
        rc = rdm_cursorGetOwnerRow (cursor, REF_TRACK_ALBUMID, &albumCursor);
        rc = rdm_cursorReadColumn (
            albumCursor, COL_ALBUM_TITLE, albumTitle,
            RDM_COLUMN_SIZE (ALBUM, title), NULL);
        rc = rdm_cursorReadColumn (
            albumCursor, COL_ALBUM_ALBUMID, &saveAlbumId, sizeof (saveAlbumId),
            NULL);
        printf ("The track is from the album \"%s\"\n", albumTitle);
 
        rc = rdm_cursorGetOwnerRow (
            albumCursor, REF_ALBUM_ARTISTID, &artistCursor);
        rc = rdm_cursorReadColumn (
            artistCursor, COL_ARTIST_NAME, artistName,
            RDM_COLUMN_SIZE (ARTIST, name), NULL);
        printf ("The artist on the track is \"%s\"\n", artistName);
 
        printf ("\nHere are other albums by \"%s\"\n", artistName);
        rc =
            rdm_cursorGetSiblingRows (albumCursor, REF_ALBUM_ARTISTID, &cursor);
        for (rc = rdm_cursorMoveToFirst (cursor); rc == sOKAY;
             rc = rdm_cursorMoveToNext (cursor))
        {
            ALBUM album_rec;
 
            rc = rdm_cursorReadRow (
                cursor, &album_rec, sizeof (album_rec), NULL);
            if (album_rec.albumid == saveAlbumId)
                continue;
            printf ("\t%s\n", album_rec.title);
        }
 
        if (cursor)
            rdm_cursorFree (cursor);
        if (artistCursor)
            rdm_cursorFree (artistCursor);
        if (albumCursor)
            rdm_cursorFree (albumCursor);
 
        /* 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);
        }
 
        rdm_dbEnd (hDB);
    }
 
    return rc;
}
 
/* Track data to insert */
static const char *the_doors_tracks[] = {"Break on Through (To the Other Side)",
                                         "Soul Kitchen",
                                         "The Crystal Ship",
                                         "Twentieth Century Fox",
                                         "Alabama Song (Whisky Bar)",
                                         "Light My Fire",
                                         "Back Door Man",
                                         "I Looked at You",
                                         "End of the Night",
                                         "Take It as It Comes",
                                         "The End"};
 
static const char *strange_days_tracks[] = {"Strange Days",
                                            "You're Lost Little Girl",
                                            "Love Me Two Times",
                                            "Unhappy Girl",
                                            "Horse Latitudes",
                                            "Moonlight Drive",
                                            "People Are Strange",
                                            "My Eyes Have Seen You",
                                            "I Can't See Your Face in My Mind",
                                            "When the Music's Over"};
 
static const char *waiting_tracks[] = {
    "Hello, I Love You",    "Love Street",     "Not to Touch the Earth",
    "Summer's Almost Gone""Wintertime Love""The Unknown Soldier",
    "Spanish Caravan",      "My Wild Love",    "We Could Be So Good Together",
    "Yes, the River Knows""Five to One"};
 
static const char *the_rolling_stones_tracks[] = {
    "Not Fade Away",
    "Route 66",
    "I Just Want to Make Love to You",
    "Honest I Do",
    "Now I've Got a Witness",
    "Little by Little",
    "I'm a King Bee",
    "Carol",
    "Tell Me",
    "Can I Get a Witness",
    "You Can Make It If You Try",
    "Walking the Dog"};
 
static const char *out_of_our_heads_tracks[] = {
    "She Said Yeah",
    "Mercy, Mercy",
    "Hitch Hike",
    "That's How Strong My Love Is",
    "Good Times",
    "Gotta Get Away",
    "Talkin' Bout You",
    "Cry to Me",
    "Oh, Baby (We Got a Good Thing Going)",
    "Heart of Stone",
    "The Under Assistant West Coast Promotion Man",
    "I'm Free"};
 
static const char *beggars_banquet_tracks[] = {
    "Sympathy for the Devil""No Expectations""Dear Doctor",
    "Parachute Woman",        "Jig-Saw Puzzle",  "Street Fighting Man",
    "Prodigal Son",           "Stray Cat Blues""Factory Girl",
    "Salt of the Earth"};
 
static const char *tattoo_you_tracks[] = {"Start Me Up",
                                          "Hang Fire",
                                          "Slave",
                                          "Little T&A",
                                          "Black Limousine",
                                          "Neighbours",
                                          "Worried About You",
                                          "Tops",
                                          "Heaven"};
 
static const char *bleach_tracks[] = {
    "Blew",      "Floyd The Barber""About a Girl",   "School",
    "Love Buzz""Paper Cuts",       "Negative Creep""Scoff",
    "Swap Meet""Mr. Moustache",    "Sifting"};
 
static const char *nevermind_tracks[] = {"Smells Like Teen Spirit",
                                         "In Bloom",
                                         "Come as You Are",
                                         "Breed",
                                         "Lithium",
                                         "Polly",
                                         "Territorial Pissings",
                                         "Drain You",
                                         "Lounge Act",
                                         "Stay Away",
                                         "On a Plain",
                                         "Something in the Way",
                                         "Endless, Nameless"};
 
static const char *in_utero_tracks[] = {
    "Serve the Servants",
    "Scentless Apprentice",
    "Heart-Shaped Box",
    "Rape Me",
    "Frances Farmer Will Have Her Revenge on Seattle",
    "Dumb",
    "Very Ape",
    "Milk It",
    "Pennyroyal Tea",
    "Radio Friendly Unit Shifter",
    "tourette's",
    "All Apologies"};
 
#define RLEN(x) (sizeof (x) / sizeof (x[0]))
 
RDM_RETCODE insertAllAlbums (
    RDM_DB hDB) 
{
    RDM_RETCODE rc;
 
    rc = insertAlbum (
        hDB, "The Doors""The Doors", the_doors_tracks,
        RLEN (the_doors_tracks));
 
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Doors""Strange Days", strange_days_tracks,
            RLEN (strange_days_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Doors""Waiting for the Sun", waiting_tracks,
            RLEN (waiting_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Rolling Stones""The Rolling Stones",
            the_rolling_stones_tracks, RLEN (the_rolling_stones_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Rolling Stones""Out of our Heads",
            out_of_our_heads_tracks, RLEN (out_of_our_heads_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Rolling Stones""Beggars Banquest",
            beggars_banquet_tracks, RLEN (beggars_banquet_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "The Rolling Stones""Tattoo You", tattoo_you_tracks,
            RLEN (tattoo_you_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "Nirvana""Bleach", bleach_tracks, RLEN (bleach_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "Nirvana""Nevermind", nevermind_tracks,
            RLEN (nevermind_tracks));
    }
    if (rc == sOKAY)
    {
        rc = insertAlbum (
            hDB, "Nirvana""In Utero", in_utero_tracks,
            RLEN (in_utero_tracks));
    }
 
    return rc;
}
 
RDM_RETCODE insertAllArtists (
    RDM_DB hDB) 
{
    RDM_RETCODE rc;
 
    rc = insertArtist (hDB, "The Doors");
 
    if (rc == sOKAY)
    {
        rc = insertArtist (hDB, "The Rolling Stones");
    }
    if (rc == sOKAY)
    {
        rc = insertArtist (hDB, "Nirvana");
    }
 
    return rc;
}
 
int main_core10 (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, "core10", core10_cat);
        if (rc == sOKAY)
        {
            rc = insertAllArtists (hDB);
        }
        if (rc == sOKAY)
        {
            rc = insertAllAlbums (hDB);
        }
 
        if (rc == sOKAY)
        {
            rc = readInfoForTrack (hDB, "Love Street");
        }
 
        if (rc == sOKAY)
        {
            rc = readInfoForTrack (hDB, "Carol");
        }
 
        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_cursorGetSiblingRows(RDM_CURSOR memberCursor, RDM_REF_ID refId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with siblings.
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.
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
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
RDM_RETCODE rdm_dbGetRowsByKeyAtKey(RDM_DB db, RDM_KEY_ID keyId, const void *keyValue, size_t len, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with a row set that is ordered by key value and is initially positioned at th...
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_dbEndRollback(RDM_DB db)
End and rollback a transactional operation.
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.
uint64_t RDM_ROWID_T
Definition: rdmrowidtypes.h:21
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
RDM_RETCODE rdm_cursorGetOwnerRow(RDM_CURSOR memberCursor, RDM_REF_ID refId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with a set owner.
#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