/****************************************************************************** ** ** 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); }