Appendix C - C Examples

This Appendix contains examples in C using direct Adabas calls.

This document covers the following topics:


C Example

The Adabas file defined in Appendix B is used in this example.

/************* ADABAS  ************* (C) Copyright Software AG 2005
*
* File       : c_example.c
* Description: Example for ADABAS calls from C programs
*
*
*************************************************************************/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <adabasx.h>                /* include adabas definitions */



#define NULLPTR ((char *) 0)       /* define for NULL-pointer */

int dbid;                          /* default database */
int emp_file ;                     /* filenumber       */


#define FMTBUF  "LB1,4,F."         /* FB: get first salary field */
#define FBLEN   8                  /* format buffer's length    */


#define SEABUF  "BC,5."            /* SB: search NAME equal to  */
#define SBLEN   5                  /* search buffer's length    */


#define VALBUF  "SMITH"            /* VB: name to search for    */
#define VBLEN   5                  /* value buffer's length     */


#define RBLEN   4                  /* record buffer's length    */
#define IBLEN   4                  /* ISN buffer's length       */


char openrb[100];                    /* record buffer used for OPEN */

/*
        +----------------+
        ! define buffers !
        +----------------+
*/

static CB_PAR  cb;         /* control block */

static int     isn_buffer;     /* ISN buffer (1 ISN) */

static int     rb_salary;          /* record buffer (for salary field) */

/*************************************************************************/
/**                 Module Local Functions                              **/
/*************************************************************************/

int      usage ();
int      open_database ();
int      close_database();
void     response ();
int      update_record();
int      find_record();
int      issue_bt ();



usage()
{
    printf("usage: c_example <dbid> <employees file number>\n");
    exit(1);
}


/*
        +------------------+
        !   Main program   !
        +------------------+
*/

int main (int argc, char **argv )
{
   register int   upd = 0;          /* update counter */
   register int   old_salary;           /* saving salary field */


   printf ("\nSoftware AG - C example program for calling ADABAS\n\n") ;

   if (argc==3)
   {
       if (sscanf (argv[1],"%d",&dbid)==0)
       usage ();
       if (sscanf (argv[2],"%d",&emp_file)==0)
       usage ();
   }
   else
       usage();

   /*--------------*/
   /* Open session */
   /*--------------*/
   if ( open_database() != ADA_NORMAL )
      response ();              /* open command failed */
   else
   {
      /*--------------------------------------*/
      /* Search all persons with name = SMITH */
      /*--------------------------------------*/
      if ( find_record () == ADA_NORMAL )
      {
         printf ("Found  %ld records with name %s, increase salary by 10 %%\n",
         cb.cb_isn_quantity, VALBUF);

         while ( cb.cb_return_code == ADA_NORMAL  &&  cb.cb_isn_quantity != 0 )
         {
            old_salary = rb_salary;
            rb_salary += rb_salary / 10;

        /*-------------------------*/
        /* Increase salary by 10 % */
        /*-------------------------*/
            if ( update_record () != ADA_NORMAL )
               cb.cb_isn_quantity = 0;
            else
            {
               upd++;
               printf
                  ("%3d. ISN = %8d  old salary = %10ld   new salary = %10ld\n",
                    upd, cb.cb_isn, old_salary, rb_salary);

           /*-----------------*/
           /* Get next record */
           /*-----------------*/
               find_record ();
            }
         }
      }

      if ( cb.cb_return_code != ADA_NORMAL )    /* if response given: */
      {
         response ();               /* display response code */
         cb.cb_return_code = ADA_NORMAL;

         if ( upd != 0 )            /* if updates done */
     {
            if ( issue_bt () == ADA_NORMAL )    /* backout transaction */
               upd = 0;
            else
               response ();         /* BT failed */
     }
      }

      if ( close_database () != ADA_NORMAL )
         response ();
   }
}


/*
        +------------------------+
        ! Open the database for  !
        ! updating the EMPLOYEES !
        ! file                   !
        +------------------------+
*/

int open_database ()
{


   cb.cb_cmd_code[0] = 'O';
   cb.cb_cmd_code[1] = 'P';

   sprintf(openrb,"UPD=%d.",emp_file);

   cb.cb_rec_buf_lng = strlen(openrb);
   do
   {
      CB_SET_FD(&cb,dbid,0);
      adabas ( &cb , NULLPTR , openrb, NULLPTR, NULLPTR, NULLPTR );
   }
   while ( cb.cb_return_code == ADA_TABT );

   cb.cb_isn_quantity = 0;
   cb.cb_isn_ll = 0;

   return ( cb.cb_return_code );
}


/*
        +--------------------------------+
        !  Close the database and give   !
        !  implicit end of transaction.  !
        +--------------------------------+
*/

int close_database ()
{
   CB_SET_FD(&cb,dbid,0);

   cb.cb_cmd_code[0] = 'C';
   cb.cb_cmd_code[1] = 'L';

   adabas ( &cb, NULLPTR, NULLPTR, NULLPTR, NULLPTR, NULLPTR );

   return ( cb.cb_return_code );
}


/*
        +--------------------------------+
        ! Call ADABAS to find all people !
        ! named SMITH and read them      !
        +--------------------------------+
*/

int find_record ()
{

   CB_SET_FD(&cb,dbid,emp_file);

   if ( cb.cb_isn_quantity == 0 )       /* if first call:       */
   {                        /*   search records and */
      cb.cb_cmd_code[0]  = 'S';         /*   read first one     */
      cb.cb_cmd_code[1]  = '4';
      cb.cb_cmd_id[0]    = 'F';
      cb.cb_cmd_id[1]    = 'I';
      cb.cb_cmd_id[2]    = 'N';
      cb.cb_cmd_id[3]    = 'D';

      cb.cb_fmt_buf_lng  = FBLEN;
      cb.cb_rec_buf_lng  = RBLEN;
      cb.cb_sea_buf_lng  = SBLEN;
      cb.cb_val_buf_lng  = VBLEN;
      cb.cb_isn_buf_lng  = IBLEN;       /* read 1. record by search */
   }
   else                     /* if subsequent call: */
   {                        /*   read next record  */
      cb.cb_cmd_code[0] = 'L';
      cb.cb_cmd_code[1] = '4';
      cb.cb_cop2         = ADA_GET_NEXT;    /* activate get-next option */
   }

   adabas ( &cb , FMTBUF , &rb_salary , SEABUF , VALBUF , &isn_buffer );

   if ( cb.cb_return_code == ADA_EOF )
   {
      cb.cb_return_code   = ADA_NORMAL;     /* indicate success */
      cb.cb_isn_quantity  = 0;          /* force termination of loop */
   }
   return ( cb.cb_return_code );
}



/*
        +----------------------------+
        ! Change the value of salary !
        !  and update the record     !
        +----------------------------+
*/

int update_record ()
{
   CB_SET_FD(&cb,dbid,emp_file);

   cb.cb_cmd_code[0] = 'A';
   cb.cb_cmd_code[1] = '1';
   cb.cb_cop1 = cb.cb_cop2 = ' ';

   adabas ( &cb , FMTBUF , &rb_salary, NULLPTR, NULLPTR, NULLPTR );

   return ( cb.cb_return_code );
}



/*
        +-----------------------+
        !  printf response code  !
        +-----------------------+
*/

void response ()
{
   printf ("** Response code %d from ADABAS for Command %-2.2s\n",
            cb.cb_return_code , cb.cb_cmd_code);
   printf ("** Additions2 %d %d\n",
            cb.cb_add2[2] , cb.cb_add2[3]);

}



/*
        +--------------------+
        !  Issue BT command  !
        +--------------------+
*/

int issue_bt ()
{
   CB_SET_FD(&cb,dbid,0);

   cb.cb_cmd_code[0] = 'B';
   cb.cb_cmd_code[1] = 'T';
   cb.cb_cop1 = cb.cb_cop2 = ' ';

   adabas ( &cb, NULLPTR, NULLPTR, NULLPTR, NULLPTR, NULLPTR );

   return ( cb.cb_return_code );
}

C Example for LOB Processing

This example works with any file that contains an elementary LOB field; the database ID, file number and name of the LOB field can be passed to the program as parameters.

/************* ADABAS  ************* (C) Copyright Software AG 2006 **********
*
* File       : lob_example.c
*
* Description: Example for ADABAS calls from C programs
*
*          This is an example how read and write large objects in a database
*          or to read an object from a database
*
*          Parameters:
*           function (add_lob or read_lob)
*           Database-ID
*           Filenr
*           Isn
*           fieldname
*           filename
*
*           The add_lob function reads a disk file and adds or updates the
*           content of a specified field in a database. This is done by an
*           ADABAS A1 call.
*           The record must exist and the given field is updated.
*
*           The read_lob function does two L1 calls to retrieve the size and
*           the content of a given field in a database. The content is then
*           written to a disk file.
*
*
*           adabasx()is required for buffers greater than 64 K.
*           The buffers are described by ABD structures (ADABAS Buffer
*           descritpions) that are passed as arguments to adabasx.
*           More than one pair of ABDs for record and format buffer can be used.
*           (See function add_lob)
*           This means that not all data has to be in one continuous memory
*           area.The ABDs are initialized by the SETABD macros.
*
*
*****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "adabasx.h"        /* include adabas definitions */


/* opening the database */
void open_database( int dbid );

/*close the database */
void close_database( int dbid );

/*usage descriptions */
void usage( );

/* display response code */
void response( ACBX *cbx );

/* read from database */
void read_lob( int dbid, int filenr, int isn, char *filename, char *field );

/* write in the database */
void add_lob( int dbid, int filenr, int isn, char *filename, char *field );

/* read from the file */
int  read_file( char *filename, void **obj);

/* write LOB to file */
void write_file( char *filename, char *obj, unsigned int objsize  );


int main ( int argc, char **argv )
/*
    Main function
    read the argument and pass control to one of the functions
*/

{
    int filenr, dbid, isn;    /* variables for adabas call        */
    char * command = NULL;      /* command to execute (read/write)*/
    char * filename = NULL;     /* filename                       */
    char *field;          /* field of the database                */

    printf("\nSoftware AG - C example program for calling ADABAS with large");
    printf(" objects\n\n    add/read a large object to/from a record \n\n");

    if( argc != 7 )
        usage( );
    else
    {
        command = &argv[1][0];

        if( ( strcmp( command ,"add_lob") != 0 )
              && ( strcmp( command, "read_lob") != 0 ) )
        {
            usage ( );
        }

        if( sscanf( argv[2],"%d",&dbid ) == 0 )
            usage( );

        if( sscanf (argv[3],"%d",&filenr ) == 0 )
            usage( );

        if( sscanf (argv[4],"%d",&isn ) == 0 )
            usage( );

        field = argv[5];


        filename = argv[6];
    }

    open_database( dbid );      /* Open database            */

                    /* read in the database         */
    if( strcmp( command, "add_lob" ) == 0 )
        add_lob( dbid, filenr, isn, filename, field );
    else                /* Write from database          */
        read_lob( dbid, filenr, isn, filename, field );

    close_database( dbid );     /* Close database           */

}



void usage( )
/*----------------------------------------
    Display how the program has to be used
------------------------------------------*/
{
printf("usage:\n");
printf("    lob_example (add_lob | read_lob) <dbid> <file> <isn> <field> <file name>");
printf("\n\n");
printf("    add_lob  : Read an object from <file name> and update <field> in record\n");
printf("    read_lob : Read from database, save to file on disk\n");
printf("    dbid     : Number of ADABAS database\n");
printf("    file     : Number of file\n");
printf("    isn      : ISN of record to be updated/read\n");
printf("    field    : Field where object is (to be) stored\n");
printf("    file name: Name of the disk file to be read or written\n\n");
printf("    ie.: lob_example add_lob 12 9 1100 RA picture.jpg \n");
printf("    ie.: lob_example read_lob 12 9 1100 RA picture.jpg\n");
    exit(1);
}




void open_database( int dbid )

/*-------------------------------------------------
  Open the database

  This call is done with conventional adabas
  function.
  All other calls are done via adabasx to show that
  The two types of calls can be mixed.
-------------------------------------------------*/

{

    CB_PAR cb;                          /* Control block        */
    char *open_rb = ".";

    memset(&cb,0,sizeof(cb));

    cb.cb_call_type=0;

    cb.cb_cmd_code[0] = 'O';            /* open options         */
    cb.cb_cmd_code[1] = 'P';
    CB_SET_FD(&cb,dbid,0);
    adabas( &cb, 0, open_rb , 0 ,0 ,0); /* adabas call          */


    if( cb.cb_return_code != 0 )
    {
        printf("Open of Database %d failed with response %d\n",
        dbid,
        cb.cb_return_code );
        exit(1);
    }
}


void read_lob( int dbid, int filenr, int isn, char *filename, char *field )
/*--------------------------------------------+
  Read a large object from database
  two L1 calls are done:
  the first to determine the size of the object.
  then a buffer with this size is allocated.
  the second reads the actual object.
+---------------------------------------------*/
{
#define abdcount 4
    char i=0;
    ACBX cbx;                   /* Control block                    */
    ABD  object_fb_abd;         /* Format buffer ABD for the object */
    ABD  object_rb_abd;         /* Record buffer ABD for the object */
    ABD  object_size_fb_abd;    /* Format buffer ABD for the size   */
    ABD  object_size_rb_abd;    /* Record buffer ABD for the size   */

    ABD* pabd[abdcount];        /* ABD array for Adabas call        */

    char size_fb[20];           /* format buffer for size           */
    char object_fb[30];         /*format buffer to retrieve the     */
                                /*object itself                     */
    unsigned int object_size;   /*The 4-Byte integer object_size    */
                                /*is our record buffer              */
                                /*for the first call                */
    unsigned int object_size_chk;/*store the size to check if object*/
                                /*changed between the calls         */



    SETACBX ( &cbx );

    cbx.acbxdbid   = dbid;
    cbx.acbxfnr    = filenr;
    cbx.acbxisn    = isn;
    cbx.acbxcmd[0] = 'L';       /* Command code         */
    cbx.acbxcmd[1] = '1';

    /*Initialize the abds*/
    pabd[0] = &object_size_fb_abd;
    pabd[1] = &object_size_rb_abd;
    pabd[2] = &object_fb_abd;
    pabd[3] = &object_rb_abd;

    /*Initialize abd*/
    for (i=0 ;i< abdcount;i++)
    {
        SETABD  ( pabd[i] );
        pabd[i]->abdloc = ABDQIND;
    /*  ABDQIND means that the buffer is found at abdaddr   */
    }

    object_size_fb_abd.abdid    = ABDQFB;
    sprintf( size_fb, "%sL.", field );
    object_size_fb_abd.abdaddr  = size_fb;
    object_size_fb_abd.abdsend  =
    object_size_fb_abd.abdsize  = strlen( size_fb );


    object_size_rb_abd.abdid    = ABDQRB;
    object_size_rb_abd.abdaddr  = &object_size;
    object_size_rb_abd.abdsize  = sizeof(object_size);

    adabasx ( &cbx, 2 , pabd );
    response( &cbx );

    printf("Size of Object in Database :%d     \n\n",object_size);
    if (object_size)
    {
        object_fb_abd.abdid    = ABDQFB;

        sprintf( object_fb, "%s,*.", field );
        object_fb_abd.abdaddr  = object_fb;
        object_fb_abd.abdsend = object_fb_abd.abdsize  = strlen(object_fb);

        object_rb_abd.abdid    = ABDQRB;


        do {
            object_size_chk=object_size;

            /*Now the memory for the object is allocated                */
            /*and the object itself is read by a second call            */
            /*the lenth is read again to verify that it is unchanged    */
            object_rb_abd.abdsize  = object_size_chk;
            if (object_rb_abd.abdaddr)
                free(object_rb_abd.abdaddr);
            object_rb_abd.abdaddr  = malloc ( object_size_chk);
            if (object_rb_abd.abdaddr)
            {
                adabasx ( &cbx , 4 , pabd );    /* Adabas call  */
                response( &cbx );

            }
            else
            {
                printf ("*** Memory allocation for Record Buffer failed");
                close_database(dbid);
                exit (-1);
            }
         } while (object_size>object_size_chk&&object_size);
    }
    if (object_size)
    {
write_file( filename, object_rb_abd.abdaddr, (unsigned int)object_rb_abd.abdsize );
printf("Object from field %s ISN %d file %d Database %d successfully written\nto file %s\n\n",
field,isn,filenr,dbid,filename);
    }
    else
    {
printf("No Object found in field %s ISN %d file %d Database %d\n",
field,isn,filenr,dbid);
printf("No file written\n\n");
    }

}



void write_file( char *filename, char *obj, unsigned int objsize  )
/*--------------------------------------------
    write LOB to disc file
---------------------------------------------*/
{
    FILE * fd;
    struct stat st;        /* to specify the exists of the file */

    if(stat(filename , &st) > 0)
    {
        printf("The file %s already exists!\n\n", filename);
        exit( 1 );
    }
                    /* open the file            */
    if( ( fd = fopen( filename, "wb+" ) ) == NULL )
    {
        printf("File %s could not be opened for writing!\n\n", filename);
        exit( 1 );
    }
                    /* write in the file        */
    else if ( fwrite ( obj, 1, objsize, fd ) < 0 )
    {
        printf("Cannot write to file %s\n\n", filename);
        exit( 1 );
    }
    fclose(fd);
}



void add_lob( int dbid, int filenr, int isn, char *filename, char *field)
/*----------------------------------------------------------
    add a large object to a record in a  database.
    for demonstration purposes two pairs of record and format
    buffer segments are used:
    one pair is used to specify the size of the object
    one pair is used for the object itself
 ----------------------------------------------------------*/
{
#define abdcount 4
    char i=0;
    ACBX cbx;                   /* Control block                    */
    ABD  object_fb_abd;         /* Format buffer ABD for the object */
    ABD  object_rb_abd;         /* Record buffer ABD for the object */
    ABD  object_size_fb_abd;    /* Format buffer ABD for the size   */
    ABD  object_size_rb_abd;    /* Record buffer ABD for the size   */

    ABD* pabd[abdcount];        /* ABD array for Adabas call        */

    char size_fb[20];           /* format buffer for size           */
    char object_fb[20];         /* format buffer for content        */
    int object_size;


    SETACBX ( &cbx );           /* Initialing abds                  */
    cbx.acbxdbid = dbid;
    cbx.acbxfnr  = filenr;
    cbx.acbxisn  = isn;
    cbx.acbxcmd[0] = 'A';       /* Record Update                    */
    cbx.acbxcmd[1] = '1';
    cbx.acbxcop1   = 'H';       /* Hold status database             */


    pabd[0] = &object_size_fb_abd;
    pabd[1] = &object_fb_abd;
    pabd[2] = &object_size_rb_abd;
    pabd[3] = &object_rb_abd;

    /*Initialize abd*/
    for (i=0 ;i< abdcount;i++)
    {
        SETABD  ( pabd[i] );
        pabd[i]->abdloc = ABDQIND;
    /*  ABDQIND means that the buffer is found at abdaddr           */
    }

    /*the object is stored in a pair of rb and fb                   */
    object_fb_abd.abdid     = ABDQFB;
    object_fb_abd.abdaddr   = object_fb;
    sprintf (object_fb,"%s,*.",field);
    object_fb_abd.abdsend = object_fb_abd.abdsize = strlen(object_fb);
    strlen(object_fb);

    object_rb_abd.abdid    = ABDQRB;
    /*store the size of the object in the abdsize field             */
    /*this field is also used as the second record buffer segment*/

    object_size = (int)read_file( filename, &object_rb_abd.abdaddr);
    object_rb_abd.abdsend = object_rb_abd.abdsize = object_size ;

    printf("** Size of Object to add:%d     \n\n",object_rb_abd.abdsize);


    /*the size of the object is stored in a separate pair           */

    object_size_fb_abd.abdid  = ABDQFB;
    object_size_fb_abd.abdaddr=size_fb;
    sprintf (size_fb,"%sL.",field);
    object_size_fb_abd.abdsend = object_size_fb_abd.abdsize
        = strlen(size_fb);

    object_size_rb_abd.abdid = ABDQRB;
    object_size_rb_abd.abdsend = object_size_rb_abd.abdsize
        = sizeof(object_size);

    object_size_rb_abd.abdaddr=&object_size;

    adabasx ( &cbx , abdcount,  pabd );    /* Adabas call           */

    response( &cbx );

printf("Object successfully added/updated in field %s ISN %d file %d Database %d\n\n",
 field,isn,filenr,dbid);

#undef abdcount
}




int  read_file( char *filename, void **obj)
/*------------------------------------
 allocate memory for the record buffer and
 read a file into it
+--------------------------------------*/
{
    unsigned int filelength;
    FILE * fd;
    struct stat st;

    /*  determine the length of  file    */

    if( stat(filename , &st) < 0 )
    {
        printf("The file %s doesn't exist!\n\n", filename);
        exit (1);
    }


    if( ( filelength = st.st_size ) < 0 )
    {
        printf("File % could not be opened!\n\n", filename);
        exit( 1 );
    }

                    /* open the file            */
    if( !filename || ( fd = fopen( filename, "rb" ) ) == NULL )
    {
        printf("File % could not be opened!\n\n", filename);
        exit( 1 );
    }


    if (!(*obj=malloc (filelength)))
    {
        printf("Could not allocate memory\n\n");
        exit( 1 );
    }

    filelength=fread( *obj, sizeof(char), filelength / sizeof(char), fd );

    fclose ( fd );

    if( filelength < 0 )
    {
        printf("Could not read  from the file: %s\n\n", filename);
        exit( 1 );
    }

    return  filelength;
}


void close_database( int dbid )
/*----------------------------+
  Close the session and give
  implicit end of transaction.
+----------------------------*/

{
    ACBX cbx;               /* Control block            */

    SETACBX( &cbx );        /* Initialize the Control      Block*/
    cbx.acbxcmd[0] = 'C';       /* put close option         */
    cbx.acbxcmd[1] = 'L';
    cbx.acbxdbid = dbid;

    adabasx( &cbx , 0 , NULL);      /* adabas call              */

    response( &cbx );

    if( cbx.acbxrsp != 0 )
         printf("** Close failed with response %d\n\n", cbx.acbxrsp);
}





void response( ACBX *cbx )
/*-----------------+
print response code
+------------------*/

{
    if( cbx->acbxrsp != 0)
    {
        printf("** Response code from ADABAS for Command %-2.2s:     %d\n\n",
        cbx->acbxcmd, cbx->acbxrsp);
        if( cbx->acbxrsp == ADA_LOBERR)
        {
            printf("** subcommand response %d\n\n",cbx->acbxerrc);
        }
        if ( cbx->acbxrsp != ADA_ANACT)
        {
                close_database(cbx->acbxdbid);
        }
        exit( 1 );
    }

}