/******************************************************************************
**
** Source File Name = largevol.sqc
**
** Licensed Materials - Property of IBM
**
** (C) COPYRIGHT International Business Machines Corp. 1997
** All Rights Reserved.
**
** US Government Users Restricted Rights - Use, duplication or
** disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**
** PURPOSE: This sample program demonstrates the extracting large
** volumes of data from several separate queries, one at
** each node. Each query generates the local result set
** that can be redirected to a file and merged into a single
** result set. (On AIX, you can use a advantage of NFS
** (Network File System) to automate such merging.)
**
** EXTERNAL DEPENDENCIES :
** - Ensure existence of database for precompile purposes.
** - Precompile with the SQL precompiler (PREP in DB2)
** - Bind to a database (BIND in DB2)
** - Compile and link with the IBM Cset++ compiler (AIX and OS/2)
** or the Microsoft Visual C++ compiler (Windows)
** or the compiler supported on your platform.
**
*******************************************************************************/
#define _POSIX_SOURCE
#define INCL_32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sqlenv.h>
#include <errno.h>
#include <sys/access.h>
#include <sys/flock.h>
#include <unistd.h>
#define BUF_SIZE 1500000 /* Local buffer to store the fetched records */
#define MAX_RECORD_SIZE 80 /* >= size of one written record */
int main(int argc, char *argv[]) {
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
char dbname[10]; /* Database name (argument of the program) */
char userid[9];
char passwd[19];
char first_name[21];
char last_name[21];
char job_code[11];
EXEC SQL END DECLARE SECTION;
struct flock unlock ; /* structures and variables for handling */
struct flock lock ; /* the NFS locking mechanism */
int lock_command ;
int lock_rc ;
int iFileHandle ; /* output file */
int iOpenOptions = 0 ;
int iPermissions ;
char * file_buf ; /* pointer to the buffer where the fetched
records are accumulated */
char * write_ptr ; /* position where the next record is written */
int buffer_len = 0 ; /* length of used portion of the buffer */
/* Initialization */
lock.l_type = F_WRLCK; /* An exclusive write lock request */
lock.l_start = 0; /* To lock the entire file */
lock.l_whence = SEEK_SET;
lock.l_len = 0;
unlock.l_type = F_UNLCK; /* An release lock request */
unlock.l_start = 0; /* To unlock the entire file */
unlock.l_whence = SEEK_SET;
unlock.l_len = 0;
lock_command = F_SETLKW; /* Set the lock */
iOpenOptions = O_CREAT; /* Create the file if not exist */
iOpenOptions |= O_WRONLY; /* Open for writing only */
/* Connect to the database */
if (argc == 3) {
strcpy( dbname, argv[2] ); /* get database name from the argument */
EXEC SQL CONNECT TO :dbname IN SHARE MODE ;
if ( SQLCODE != 0 ) {
printf( "Error: CONNECT TO the database failed. SQLCODE = %ld\n",
SQLCODE );
exit(1);
}
}
else if ( argc == 5 ) {
strcpy( dbname, argv[2] ); /* get database name from the argument */
strcpy (userid, argv[3]);
strcpy (passwd, argv[4]);
EXEC SQL CONNECT TO :dbname IN SHARE MODE USER :userid USING :passwd;
if ( SQLCODE != 0 ) {
printf( "Error: CONNECT TO the database failed. SQLCODE = %ld\n",
SQLCODE );
exit( 1 );
}
}
else {
printf ("\nUSAGE: largevol txt_file database [userid passwd]\n\n");
exit( 1 ) ;
} /* endif */
/* Open the input file with the specified access permissions */
if ( ( iFileHandle = open(argv[1], iOpenOptions, 0666 ) ) == -1 ) {
printf( "Error: Could not open %s.\n", argv[2] ) ;
exit( 2 ) ;
}
/* Set up error and end of table escapes */
EXEC SQL WHENEVER SQLERROR GO TO ext ;
EXEC SQL WHENEVER NOT FOUND GO TO cls ;
/* Declare and open the cursor */
EXEC SQL DECLARE c1 CURSOR FOR
SELECT firstnme, lastname, job FROM employee
WHERE workdept IS NOT NULL
AND NODENUMBER(lastname) = CURRENT NODE;
EXEC SQL OPEN c1 ;
/* Set up the temporary buffer for storing the fetched result */
if ( ( file_buf = ( char * ) malloc( BUF_SIZE ) ) == NULL ) {
printf( "Error: Allocation of buffer failed.\n" ) ;
exit( 3 ) ;
}
memset( file_buf, 0, BUF_SIZE ) ; /* reset the buffer */
buffer_len = 0 ; /* reset the buffer length */
write_ptr = file_buf ; /* reset the write pointer */
/* For each fetched record perform the following */
/* - insert it into the buffer following the */
/* previously stored record */
/* - check if there is still enough space in the */
/* buffer for the next record and lock/write/ */
/* unlock the file and initialize the buffer */
/* if not */
do {
EXEC SQL FETCH c1 INTO :first_name, :last_name, :job_code;
buffer_len += sprintf( write_ptr, "%s %s %s\n",
first_name, last_name, job_code );
buffer_len = strlen( file_buf ) ;
/* Write the content of the buffer to the file if */
/* the buffer reaches the limit */
if ( buffer_len >= ( BUF_SIZE - MAX_RECORD_SIZE ) ) {
/* get excl. write lock */
lock_rc = fcntl( iFileHandle, lock_command, &lock );
if ( lock_rc != 0 ) goto file_lock_err;
/* position at the end of file */
lock_rc = lseek( iFileHandle, 0, SEEK_END );
if ( lock_rc < 0 ) goto file_seek_err;
/* write the buffer */
lock_rc = write( iFileHandle,
( void * ) file_buf, buffer_len );
if ( lock_rc < 0 ) goto file_write_err;
/* release the lock */
lock_rc = fcntl( iFileHandle, lock_command, &unlock );
if ( lock_rc != 0 ) goto file_unlock_err;
file_buf[0] = '\0' ; /* reset the buffer */
buffer_len = 0 ; /* reset the buffer length */
write_ptr = file_buf ; /* reset the write pointer */
}
else {
write_ptr = file_buf + buffer_len ; /* next write position */
}
} while (1) ;
cls:
/* Write the last piece of data out to the file */
if (buffer_len > 0) {
lock_rc = fcntl(iFileHandle, lock_command, &lock);
if (lock_rc != 0) goto file_lock_err;
lock_rc = lseek(iFileHandle, 0, SEEK_END);
if (lock_rc < 0) goto file_seek_err;
lock_rc = write(iFileHandle, (void *)file_buf, buffer_len);
if (lock_rc < 0) goto file_write_err;
lock_rc = fcntl(iFileHandle, lock_command, &unlock);
if (lock_rc != 0) goto file_unlock_err;
}
free(file_buf);
close(iFileHandle);
EXEC SQL CLOSE c1;
exit (0);
ext:
if ( SQLCODE != 0 )
printf( "Error: SQLCODE = %ld.\n", SQLCODE );
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL CONNECT RESET;
if ( SQLCODE != 0 ) {
printf( "CONNECT RESET Error: SQLCODE = %ld\n", SQLCODE );
exit(4);
}
exit (5);
file_lock_err:
printf("Error: file lock error = %ld.\n",lock_rc);
/* unconditional unlock of the file */
fcntl(iFileHandle, lock_command, &unlock);
exit(6);
file_seek_err:
printf("Error: file seek error = %ld.\n",lock_rc);
fcntl(iFileHandle, lock_command, &unlock); /* unconditional unlock of the file */
exit(7);
file_write_err:
printf("Error: file write error = %ld.\n",lock_rc);
fcntl(iFileHandle, lock_command, &unlock); /* unconditional unlock of the file */
exit(8);
file_unlock_err:
printf("Error: file unlock error = %ld.\n",lock_rc);
fcntl(iFileHandle, lock_command, &unlock); /* unconditional unlock of the file */
exit(9);
}