/* #define DEBUG */
/* #define DEBUG2 */
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include "sqlca.h"
#define SQL_NO_DATA_FOUND 1403
#define SQL_FETCH_OUT_OF_SEQUENCE -1002
#define SQL_ORACLE_INITIALIZATION_OR_SHUTDOWN_IN_PROGRESS -1033
#define SQL_ORACLE_NOT_AVAILABLE -1034
#define SQL_UNABLE_TO_EXTEND_INDEX -1654
#define SQL_UNIQUE_CONSTRAINT_VIOLATED -1
#define SQL_NOT_CONNECTED_TO_ORACLE -3114
#define SQL_END_OF_FILE_ON_COMMUNICATION_CHANNEL -3113
#define GO 0
#define NOGO 1
int sql_error();
int unpad();
char *field();
char *hhmmss();
void signal_handler();
char *right_trim();
char *string_cat();
EXEC SQL BEGIN DECLARE SECTION;
#define UNAME_LEN 20
#define PWD_LEN 40
VARCHAR username[UNAME_LEN]; /* VARCHAR is an Oracle-supplied struct */
varchar password[PWD_LEN]; /* varchar can be in lower case also. */
VARCHAR dynamic_statement[2000];
char owner_name[30];
char table_name[30];
char table_column_name[50][30]; /* Up to 50 columns per table */
char table_data_type[50][30]; /* Up to 50 columns per table */
char table_data_int[50]; /* Data type represented as integer */
char table_nullable[50][5]; /* Up to 50 columns per table */
int number_of_columns_in_table;
char index_name[10][30]; /* Up to 10 unique indexes per table */
char index_column_name[50][30]; /* Up to 50 columns per index */
int index_column_position[50]; /* Up to 50 columns per index */
int number_of_columns_in_index;
int column_number_within_index[50];
char row_count[80];
EXEC SQL END DECLARE SECTION;
/******************************************************************************/
/* */
/* Bit values of exit_code, OR'ed together: */
/* */
/* 1 = Access to file */
/* 2 = Header record */
/* 4 = Column or index error */
/* 8 = Error in input data */
/* 16 = Error in database data */
/* 32 = Trailer record */
/* 64 = Oracle error */
/* 128 = Unexpected Interruption */
/* */
/******************************************************************************/
static exit_code = 0;
main(argc,argv)
int argc;
char *argv[];
{
FILE *in;
char buffer[4098];
char *result;
char *pointer;
char *left_pointer;
char *right_pointer;
int action;
int count;
int i;
int j;
int k;
int x;
int length;
int go_nogo_flag = GO;
int rows_added = 0;
int rows_deleted = 0;
int rows_not_committed = 0;
int commitment_threshold = 2000;
unsigned long final_row_count_specified;
unsigned long actual_final_row_count;
fprintf(stdout,
"%s START %s, VERSION OF WEDNESDAY, MARCH 20, 2002, COMPILED ON %s AT %s\n",
hhmmss(), argv[0], __DATE__, __TIME__);
fflush(stdout);
/**************************************************************************/
/* */
/* Tell UNIX to have our signal handler handle all interruptions. */
/* */
/**************************************************************************/
for (i=0;i<40;i++)
{
signal(i,signal_handler);
}
/**************************************************************************/
/* */
/* Tell the Oracle Precompiler to insert a check for sqlcode after */
/* every interface to Oracle and call sql_error() if sqlcode is */
/* not zero. */
/* */
/**************************************************************************/
EXEC SQL WHENEVER SQLERROR DO sql_error(__FILE__,__LINE__);
/**************************************************************************/
/* */
/* Establish initial connection to the Oracle Database Engine. */
/* */
/**************************************************************************/
strncpy((char *)username.arr, "username goes here", UNAME_LEN);
username.len = strlen((char *) username.arr);
strncpy((char *)password.arr, "password goes here", PWD_LEN);
password.len = strlen((char *) password.arr);
EXEC SQL CONNECT :username IDENTIFIED BY :password;
if (sqlca.sqlcode == 0)
{
fprintf(stdout,"%s CONNECTED TO ORACLE AS USER %s\n",hhmmss(),username.arr);
fflush(stdout);
}
else
{
sql_error(__FILE__,__LINE__);
/*
exit(253);
*/
}
/**************************************************************************/
/* */
/* Process all files specified in the argument list. */
/* */
/**************************************************************************/
for (i=1;i<argc;i++)
{
go_nogo_flag = GO;
/**********************************************************************/
/* */
/* Get Owner Name */
/* */
/**********************************************************************/
strcpy(buffer,argv[i]);
right_pointer = strchr(buffer,'.');
if (right_pointer)
{
/******************************************************************/
/* */
/* Get Table Name */
/* */
/******************************************************************/
*right_pointer = 0;
strcpy(owner_name,buffer);
left_pointer = right_pointer + 1;
right_pointer = strchr(left_pointer,'.');
if (right_pointer)
{
*right_pointer = 0;
strcpy(table_name,left_pointer);
}
else
{
fprintf(stdout,
"%s ERROR: SECOND PERIOD NOT FOUND IN ARGUMENT[%d]: %s\n",
hhmmss(), i, buffer);
fflush(stdout);
exit_code |= 1; /* Error in file name */
continue;
}
}
else
{
fprintf(stdout,
"%s ERROR: FIRST PERIOD NOT FOUND IN ARGUMENT[%d]: %s\n",
hhmmss(), i, buffer);
fflush(stdout);
exit_code |= 1; /* Error in file name */
continue;
}
/**********************************************************************/
/* */
/* Open Data Input File */
/* */
/**********************************************************************/
in = fopen(argv[i],"r");
if (!in)
{
fprintf(stdout,"%s ERROR %d TRYING TO OPEN %s: %s\n",
hhmmss(), errno, argv[i], strerror(errno));
fflush(stdout);
exit_code |= 1;
continue;
}
/**********************************************************************/
/* */
/* Read header record in order to */
/* A. verify if DELTA */
/* B. get table name, */
/* C. get final row count. */
/* */
/**********************************************************************/
result = fgets(buffer,sizeof(buffer),in);
if (result)
{
fprintf(stdout,"%s START PROCESSING FILE %s\n",
hhmmss(), argv[i]);
fflush(stdout);
}
else
{
fprintf(stdout,"%s ERROR TRYING TO READ HEADER RECORD FROM %s\n",
hhmmss(), argv[i]);
fflush(stdout);
fclose(in);
continue;
}
if (memcmp(buffer,"$~DELTA~",8) == 0)
{
#ifdef DEBUG
fprintf(stdout,"%s WE HAVE A DELTA\n", hhmmss());
fflush(stdout);
#endif
}
else
{
fprintf(stdout,"%s ERROR: HEADER RECORD DOES NOT CONTAIN DELTA\n",
hhmmss());
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
fflush(stdout);
fclose(in);
exit_code |= 2;
continue;
}
pointer = field(buffer,8);
if (pointer)
{
sscanf(pointer,"%ld",&final_row_count_specified);
fprintf(stdout,"%s FINAL ROW COUNT SHOULD BE %ld\n",
hhmmss(), final_row_count_specified);
}
else
{
fprintf(stdout,"%s ERROR: HEADER RECORD DOES NOT CONTAIN FINAL ROW COUNT\n",
hhmmss());
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
fflush(stdout);
fclose(in);
exit_code |= 2;
continue;
}
if (memcmp(owner_name,"REF_",4) != 0)
{
fprintf(stdout,"%s ERROR: OWNER NAME %s DOES NOT BEGIN WITH REF_\n",
hhmmss(), owner_name);
fflush(stdout);
fclose(in);
exit_code |= 2; /* Incorrect table name */
continue;
}
pointer = strchr(buffer,'.');
if (pointer)
{
if (memcmp(pointer+5,&table_name[4],4))
{
fprintf(stdout,"%s ERROR: HEADER TABLE NAME %4.4s DOES NOT MATCH FILE NAME %4.4s\n",
hhmmss(), pointer, table_name);
fclose(in);
exit_code |= 2; /* Incorrect table name */
continue;
}
}
if (memcmp(table_name,"REF_",4) != 0)
{
fprintf(stdout,"%s ERROR: TABLE NAME %s DOES NOT BEGIN WITH REF_\n",
hhmmss(), table_name);
fflush(stdout);
fclose(in);
exit_code |= 2; /* Incorrect table name */
continue;
}
fprintf(stdout,"%s START PROCESSING OWNER %s, TABLE %s\n",
hhmmss(), owner_name, table_name);
fflush(stdout);
/**********************************************************************/
/* */
/* Get the unique index(es) for table_name within database_name */
/* and respond if there are no unique indexes. */
/* */
/**********************************************************************/
sprintf((char *)dynamic_statement.arr,
"select index_name from all_indexes where UNIQUENESS='UNIQUE' and owner='%s' and table_name='%s'",
owner_name, table_name);
dynamic_statement.len = (unsigned short)strlen((char *)dynamic_statement.arr);
#ifdef DEBUG
fprintf(stdout,"%s EXEC SQL %d %s\n",
hhmmss(), dynamic_statement.len, dynamic_statement.arr);
fflush(stdout);
#endif
EXEC SQL PREPARE get_index_names FROM :dynamic_statement;
EXEC SQL DECLARE index_name_cursor CURSOR for get_index_names;
EXEC SQL OPEN index_name_cursor;
for (j=0;;j++)
{
EXEC SQL FETCH index_name_cursor INTO :index_name[j];
if (sqlca.sqlcode == SQL_NO_DATA_FOUND) break;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
unpad(index_name[j],sizeof(index_name[j]));
#ifdef DEBUG
fprintf(stdout,"%s UNIQUE INDEX NAME[%d] = %s\n",
hhmmss(), j, index_name[j]);
fflush(stdout);
#endif
}
if (j == 0)
{
fprintf(stdout,"%s ERROR: TABLE %s HAS NO UNIQUE INDEX\n",
hhmmss(), table_name);
fflush(stdout);
fclose(in);
exit_code |= 4; /* No unique index */
continue;
}
/**********************************************************************/
/* */
/* Now that we have at least one (1) unique index, get the */
/* column names and column positions of the first unique index. */
/* Why first? Because any unique index will do. */
/* */
/**********************************************************************/
sprintf((char *)dynamic_statement.arr,
"select column_name,column_position from all_ind_columns where index_owner='%s' and index_name='%s'",
owner_name, index_name[0]);
dynamic_statement.len = (unsigned short)strlen((char *)dynamic_statement.arr);
#ifdef DEBUG
fprintf(stdout,"%s EXEC SQL %d %s\n",
hhmmss(), dynamic_statement.len, dynamic_statement.arr);
fflush(stdout);
#endif
EXEC SQL PREPARE get_index FROM :dynamic_statement;
EXEC SQL DECLARE index_cursor CURSOR for get_index;
EXEC SQL OPEN index_cursor;
for (j=0;;j++)
{
EXEC SQL FETCH index_cursor INTO :index_column_name[j], :index_column_position[j];
if (sqlca.sqlcode == SQL_NO_DATA_FOUND) break;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
unpad(index_column_name[j],sizeof(index_column_name[j]));
#ifdef DEBUG
fprintf(stdout,"%s INDEX_COLUMN_NAME[%d]=%s, INDEX_COLUMN_POSITION[%d]=%d\n",
hhmmss(), j, index_column_name[j], j, index_column_position[j]);
fflush(stdout);
#endif
}
EXEC SQL CLOSE index_cursor;
number_of_columns_in_index = j;
if (number_of_columns_in_index <= 0)
{
fprintf(stdout,"%s ERROR: TABLE %s HAS NO INDEX\n",
hhmmss(), table_name);
fflush(stdout);
fclose(in);
exit_code |= 4; /* No columns in index */
continue;
}
/**********************************************************************/
/* */
/* Get the column names within this table. */
/* */
/**********************************************************************/
sprintf((char *)dynamic_statement.arr,
"select column_name,data_type,nullable from all_tab_columns where owner='%s' and table_name='%s' order by column_id",
owner_name, table_name);
dynamic_statement.len = (unsigned short)strlen((char *)dynamic_statement.arr);
#ifdef DEBUG
fprintf(stdout,"%s EXEC SQL %d %s\n",
hhmmss(), dynamic_statement.len, dynamic_statement.arr);
fflush(stdout);
#endif
EXEC SQL PREPARE get_columns FROM :dynamic_statement;
EXEC SQL DECLARE column_cursor CURSOR for get_columns;
EXEC SQL OPEN column_cursor;
for (j=0;;j++)
{
EXEC SQL FETCH column_cursor INTO :table_column_name[j],:table_data_type[j],:table_nullable[j];
if (sqlca.sqlcode == SQL_NO_DATA_FOUND) break;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
unpad(table_column_name[j],sizeof(table_column_name[j]));
unpad(table_data_type[j],sizeof(table_data_type[j]));
unpad(table_nullable[j],sizeof(table_nullable[j]));
if (strcmp(table_data_type[j],"VARCHAR2")==0)table_data_int[j]=1;
else if (strcmp(table_data_type[j],"NUMBER")==0)table_data_int[j]=2;
else if (strcmp(table_data_type[j],"DATE")==0)
{
length = strlen(table_column_name[j]);
if (memcmp(&table_column_name[j][length-3],"_TM",3)==0)
{
table_data_int[j]=4;
}
else table_data_int[j]=3;
}
else table_data_int[j]=9;
/******************************************************************/
/* */
/* table_allow_0 is really table_nullable because bad_words.sh */
/* interprets "null" as a bad word. */
/* */
/******************************************************************/
#ifdef DEBUG
fprintf(stdout,"%s COLUMN_NAME[%d]=%s, DATA_TYPE[%d]=%s, ALLOW_0[%d]=%s, DATA_INT[%d]=%d\n",
hhmmss(),
j, table_column_name[j],
j, table_data_type[j],
j, table_nullable[j],
j, table_data_int[j]);
fflush(stdout);
#endif
}
EXEC SQL CLOSE column_cursor;
number_of_columns_in_table = j;
if (number_of_columns_in_table <= 0)
{
fprintf(stdout,"%s ERROR: TABLE %s HAS NO COLUMNS\n",
hhmmss(), table_name);
fflush(stdout);
fclose(in);
exit_code |= 4; /* No columns in table */
continue;
}
/**********************************************************************/
/* */
/* Correspond each of the column names in the index with the */
/* position of that column in the table. */
/* */
/**********************************************************************/
for(j=0;j<number_of_columns_in_index;j++)
{
for(k=0;k<number_of_columns_in_table;k++)
{
if (strcmp(index_column_name[j],table_column_name[k]) == 0)
{
#ifdef DEBUG
fprintf(stdout,"%s INDEX COLUMN %d, %s, IS TABLE COLUMN %d\n",
hhmmss(), j+1, index_column_name[j], k+1);
fflush(stdout);
#endif
break;
}
}
if (k == number_of_columns_in_table)
{
fprintf(stdout,
"%s LOGIC ERROR: INDEX COLUMN NAME %s NOT FOUND IN TABLE COLUMN NAMES\n",
hhmmss(), index_column_name[j]);
fflush(stdout);
column_number_within_index[j] = -1;
exit_code |= 4; /* Columns in index not matched with columns in table */
go_nogo_flag = NOGO;
}
else
{
column_number_within_index[j] = k;
}
}
/**********************************************************************/
/* */
/* If fatal errors have been encountered with this file, go to the */
/* next one, if any. */
/* */
/**********************************************************************/
if (go_nogo_flag == NOGO)
{
fprintf(stdout,
"%s FATAL ERROR(S) ENCOUNTERED; DISCONTINUE FURTHER PROCESSING OF FILE %s\n",
hhmmss(), argv[i]);
fflush(stdout);
fclose(in);
continue;
}
/**********************************************************************/
/* */
/* Read each subsequent record and add or delete as necessaary. */
/* */
/**********************************************************************/
rows_added = 0;
rows_deleted = 0;
rows_not_committed = 0;
while (fgets(buffer,sizeof(buffer),in))
{
if (memcmp(buffer,"A~",2) == 0)
{
/**************************************************************/
/* */
/* Attempt to add (insert) record from table in database */
/* and respond if already there. */
/* */
/**************************************************************/
#ifdef DEBUG2
fprintf(stdout,"%s ADD RECORD %-50.50s\n", hhmmss(), buffer);
fflush(stdout);
#endif
sprintf((char *)dynamic_statement.arr,
"INSERT INTO %s.%s (", owner_name, table_name);
for(j=0;j<number_of_columns_in_table;j++)
{
strcat((char *)dynamic_statement.arr,table_column_name[j]);
if (j < number_of_columns_in_table - 1)
{
strcat((char *)dynamic_statement.arr,", ");
}
else
{
strcat((char *)dynamic_statement.arr,") ");
}
}
strcat((char *)dynamic_statement.arr,"VALUES (");
for(j=0;j<number_of_columns_in_table;j++)
{
pointer = field(&buffer[2],j+1);
if (pointer)
{
if (table_data_int[j] == 3)
{
if (memcmp(pointer," ",8) == 0)
{
strcat((char *)dynamic_statement.arr,"to_date(NULL, 'YYYY-MM-DD')");
}
else
{
strcat((char *)dynamic_statement.arr,"to_date('");
strcat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"', 'YYYY-MM-DD')");
}
}
else if (table_data_int[j] == 4)
{
strcat((char *)dynamic_statement.arr,"to_date('");
strcat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"', 'HH24.MI.SS')");
}
else
{
right_trim(pointer,table_nullable[j]);
if (*pointer)
{
strcat((char *)dynamic_statement.arr,"'");
string_cat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"'");
}
else
{
strcat((char *)dynamic_statement.arr,"NULL");
}
}
if (j < number_of_columns_in_table - 1)
{
strcat((char *)dynamic_statement.arr,", ");
}
else
{
strcat((char *)dynamic_statement.arr,")");
}
}
else
{
fprintf(stdout,"%s ERROR: NOT ENOUGH COLUMNS TO ADD ROW:\n",
hhmmss());
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
fflush(stdout);
exit_code |= 8; /* Error in input data */
break;
}
}
dynamic_statement.len =
(unsigned short)strlen((char *)dynamic_statement.arr);
#ifdef DEBUG2
fprintf(stdout,"%s EXEC SQL %d %s\n",
hhmmss(),
dynamic_statement.len, dynamic_statement.arr);
fflush(stdout);
#endif
EXEC SQL PREPARE insert_command FROM :dynamic_statement;
/**************************************************************/
/* */
/* Execute the insert command. */
/* */
/**************************************************************/
while(1)
{
EXEC SQL EXECUTE insert_command;
break;
}
if (sqlca.sqlcode == SQL_UNIQUE_CONSTRAINT_VIOLATED)
{
fprintf(stdout,
"%s ERROR: DATA IN KEY OF RECORD TO BE ADDED IS ALREADY IN TABLE %s.%s\n",
hhmmss(), owner_name, table_name);
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
dynamic_statement.arr[dynamic_statement.len] = 0;
fprintf(stdout,"%s ERROR: %s\n", hhmmss(), dynamic_statement.arr);
fflush(stdout);
exit_code |= 16; /* Error in database data */
}
else if (sqlca.sqlcode)
{
action = sql_error(__FILE__,__LINE__);
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
if (action == 1)
{
fprintf(stdout,
"%s FATAL ORACLE ERROR %d PROCESSING FILE %s, TABLE %s, TRYING TO ADD %s\n",
hhmmss(), sqlca.sqlcode, argv[i], table_name, buffer);
fflush(stdout);
fclose(in);
continue;
}
}
else
{
rows_added++;
rows_not_committed++;
}
}
else if (memcmp(buffer,"D~",2) == 0)
{
/**************************************************************/
/* */
/* Attempt to delete record from table in database and */
/* respond if not there. */
/* */
/**************************************************************/
#ifdef DEBUG2
fprintf(stdout,"%s DELETE RECORD %-50.50s\n",
hhmmss(), buffer);
fflush(stdout);
#endif
sprintf((char *)dynamic_statement.arr,
"DELETE FROM %s.%s WHERE", owner_name, table_name);
for(j=0;j<number_of_columns_in_index;j++)
{
if (j > 0)
{
strcat((char *)dynamic_statement.arr," AND");
}
strcat((char *)dynamic_statement.arr," ");
strcat((char *)dynamic_statement.arr,index_column_name[j]);
pointer = field(&buffer[2],column_number_within_index[j]+1);
if (pointer)
{
/******************************************************/
/* */
/* We do not need to check to see if the data is */
/* NULL, as we did for adding a DATE column, */
/* because a column of an index must never be NULL. */
/* */
/******************************************************/
if (table_data_int[column_number_within_index[j]] == 3)
{
strcat((char *)dynamic_statement.arr,"=to_date('");
strcat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"', 'YYYY-MM-DD')");
}
else if (table_data_int[column_number_within_index[j]] == 4)
{
strcat((char *)dynamic_statement.arr,"=to_date('");
strcat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"', 'HH24.MI.SS')");
}
else
{
right_trim(pointer,table_nullable[column_number_within_index[j]]);
if (*pointer)
{
strcat((char *)dynamic_statement.arr,"='");
string_cat((char *)dynamic_statement.arr,pointer);
strcat((char *)dynamic_statement.arr,"'");
}
else
{
strcat((char *)dynamic_statement.arr," IS NULL");
}
}
}
else
{
fprintf(stdout,"%s ERROR: NOT ENOUGH KEY DATA TO DELETE ROW:\n",
hhmmss());
fprintf(stdout,"%s ERROR: %s",
hhmmss(), buffer);
fflush(stdout);
exit_code |= 8; /* Error in input data */
break;
}
}
dynamic_statement.len =
(unsigned short)strlen((char *)dynamic_statement.arr);
#ifdef DEBUG2
fprintf(stdout,"%s EXEC SQL %d %s\n",
hhmmss(),
dynamic_statement.len, dynamic_statement.arr);
fflush(stdout);
#endif
EXEC SQL PREPARE delete_command FROM :dynamic_statement;
/**************************************************************/
/* */
/* Execute the delete command. I have not, yet, figured out */
/* how to prevent the Pro C precompiler from inserting a */
/* break statement when the data is not found. That is why */
/* I have a loop with a break; */
/* */
/**************************************************************/
while(1)
{
EXEC SQL EXECUTE delete_command;
break;
}
if (sqlca.sqlcode == SQL_NO_DATA_FOUND)
{
fprintf(stdout,"%s ERROR: RECORD TO BE DELETED NOT IN TABLE %s.%s\n",
hhmmss(), owner_name, table_name);
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
fflush(stdout);
dynamic_statement.arr[dynamic_statement.len] = 0;
fprintf(stdout,"%s ERROR: %s\n", hhmmss(), dynamic_statement.arr);
fflush(stdout);
exit_code |= 16; /* Error in database data */
}
else if (sqlca.sqlcode)
{
action = sql_error(__FILE__,__LINE__);
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
if (action == 1)
{
fprintf(stdout,
"%s FATAL ORACLE ERROR %d PROCESSING FILE %s, TABLE %s, TRYING TO DELETE %s\n",
hhmmss(), sqlca.sqlcode, argv[i], table_name, buffer);
fflush(stdout);
fclose(in);
continue;
}
}
else
{
rows_deleted++;
rows_not_committed++;
}
}
else if (memcmp(buffer,"$~TRAIL~",8) == 0)
{
/**************************************************************/
/* */
/* Commit remaining rows. */
/* */
/**************************************************************/
fprintf(stdout,"%s %4d ROWS WILL NOW BE COMMITTED TO TABLE %s.%s\n",
hhmmss(), rows_not_committed, owner_name, table_name);
fflush(stdout);
EXEC SQL COMMIT WORK;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
fprintf(stdout, "%s TRAILER RECORD ENCOUNTERED\n",
hhmmss());
/**************************************************************/
/* */
/* Verify add row counts. */
/* */
/**************************************************************/
pointer = field(buffer,5);
if (pointer)
{
x = atoi(pointer);
if (x == rows_added)
{
fprintf(stdout, "%s ADD ROW COUNTS MATCH %d = %d\n",
hhmmss(), x, rows_added);
}
else
{
fprintf(stdout,
"%s ERROR: ADD ROW COUNTS DO NOT MATCH: SPECIFIED = %d, ACTUAL = %d\n",
hhmmss(), x, rows_added);
exit_code |= 32;
}
}
else
{
fprintf(stdout,
"%s ERROR: TRAILER RECORD DOES NOT CONTAIN ADD ROW COUNT\n",
hhmmss());
fprintf(stdout, "%s ERROR: %s\n", hhmmss(), buffer);
exit_code |= 32;
}
/**************************************************************/
/* */
/* Verify delete row counts. */
/* */
/**************************************************************/
pointer = field(buffer,7);
if (pointer)
{
x = atoi(pointer);
if (x == rows_deleted)
{
fprintf(stdout, "%s DELETE ROW COUNTS MATCH %d = %d\n",
hhmmss(), x, rows_deleted);
}
else
{
fprintf(stdout,
"%s ERROR: DELETE ROW COUNTS DO NOT MATCH: SPECIFIED = %d, ACTUAL = %d\n",
hhmmss(), x, rows_deleted);
exit_code |= 32;
}
}
else
{
fprintf(stdout,
"%s ERROR: TRAILER RECORD DOES NOT CONTAIN DELETE ROW COUNT\n",
hhmmss());
fprintf(stdout, "%s ERROR: %s\n", hhmmss(), buffer);
exit_code |= 32;
}
/**************************************************************/
/* */
/* Verify final row counts. */
/* */
/**************************************************************/
sprintf((char *)dynamic_statement.arr,
"SELECT COUNT (*) FROM %s.%s",
owner_name, table_name);
dynamic_statement.len = (unsigned short)strlen((char *)dynamic_statement.arr);
EXEC SQL PREPARE get_row_count FROM :dynamic_statement;
EXEC SQL DECLARE row_count_cursor CURSOR for get_row_count;
EXEC SQL OPEN row_count_cursor;
EXEC SQL FETCH row_count_cursor INTO :row_count;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
sscanf(row_count,"%ld",&actual_final_row_count);
if (actual_final_row_count == final_row_count_specified)
{
fprintf(stdout,"%s FINAL ROW COUNTS MATCH %ld = %ld\n",
hhmmss(),
final_row_count_specified,
actual_final_row_count);
}
else
{
fprintf(stdout,
"%s ERROR: FINAL ROW COUNTS DO NOT MATCH: SPECIFIED = %ld, ACTUAL = %ld\n",
hhmmss(),
final_row_count_specified,
actual_final_row_count);
exit_code |= 32;
}
fprintf(stdout, "%s DONE PROCESSING FILE %s\n",
hhmmss(), argv[i]);
fflush(stdout);
fclose(in);
in = 0;
break;
}
else
{
fprintf(stdout,"%s ERROR: DATA RECORD IS NEITHER A~ NOR D~ NOR $~TRAIL~\n",
hhmmss());
fprintf(stdout,"%s ERROR: %s", hhmmss(), buffer);
fflush(stdout);
fclose(in);
exit_code |= 8; /* Error in input data */
break;
}
/******************************************************************/
/* */
/* Commit every so many records in order to free up buffers. */
/* */
/******************************************************************/
if (rows_not_committed >= commitment_threshold)
{
fprintf(stdout,"%s %4d ROWS WILL NOW BE COMMITTED TO TABLE %s.%s\n",
hhmmss(), rows_not_committed, owner_name, table_name);
fflush(stdout);
EXEC SQL COMMIT WORK;
if (sqlca.sqlcode == 0)
{
rows_not_committed = 0;
}
else
{
sql_error(__FILE__,__LINE__);
}
}
}
/**********************************************************************/
/* */
/* Commit whatever records remain, if any. */
/* */
/**********************************************************************/
EXEC SQL COMMIT WORK;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
/**********************************************************************/
/* */
/* If we drop through the while(fgets()) loop and the input file is */
/* still open, then we did ***NOT*** encounter a trailer record. */
/* */
/**********************************************************************/
if (in)
{
fclose(in);
fprintf(stdout,
"%s ERROR: TRAILER RECORD NOT ENCOUNTERED; %d ROWS ADDED, %d ROWS DELETED\n",
hhmmss(), rows_added, rows_deleted);
fprintf(stdout,
"%s DONE PROCESSING FILE %s\n",
hhmmss(), argv[i]);
fflush(stdout);
exit_code |= 32;
}
}
/**************************************************************************/
/* */
/* Disconnect from database engine. */
/* */
/**************************************************************************/
EXEC SQL COMMIT WORK RELEASE;
if (sqlca.sqlcode) sql_error(__FILE__,__LINE__);
fprintf(stdout,"%s END %s\n", hhmmss(), argv[0]);
fflush(stdout);
exit(exit_code);
}
int sql_error(file, line)
char *file;
int line;
{
char temp[512];
sprintf(temp,"%s %%-10.10s %%4d ERROR: %%5d %%-%d.%ds",
hhmmss(), sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrml);
fprintf(stdout, temp, file, line, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
if (!strchr(sqlca.sqlerrm.sqlerrmc,'\n')) fprintf(stdout,"\n");
fflush(stdout);
sprintf(temp,"%s %%-10.10s %%4d ERROR: %%-%d.%ds",
hhmmss(),
dynamic_statement.len,
dynamic_statement.len);
fprintf(stdout, temp, file, line, dynamic_statement.arr);
if (!strchr((char *)dynamic_statement.arr,'\n')) fprintf(stdout,"\n");
fflush(stdout);
exit_code |= 64; /* Oracle error */
switch (sqlca.sqlcode)
{
case SQL_UNABLE_TO_EXTEND_INDEX: return(1);
case SQL_NOT_CONNECTED_TO_ORACLE:
case SQL_END_OF_FILE_ON_COMMUNICATION_CHANNEL:
fprintf(stdout,"%s CATASTROPHIC ERROR, EXITING ENTIRE PROGRAM\n",
hhmmss());
fflush(stdout);
exit(254);
default: return(0);
}
exit(255);
}
int unpad(string,length)
char string[];
int length;
{
int i;
for (i=length-1; i >= 0; i--)
{
if (string[i] == ' ') string[i] = 0;
}
return(0);
}
char *field(string,number)
char *string;
int number;
{
static char answer[1024];
char *left_pointer;
char *right_pointer;
int i;
if (number <= 0) return((char *)0);
right_pointer = string - 1;
for(i=0;i<number;i++)
{
left_pointer = right_pointer + 1;
right_pointer = strchr(left_pointer,'~');
if (right_pointer)
{
continue;
}
else
{
return((char *)0);
}
}
*right_pointer = 0;
strcpy(answer,left_pointer);
*right_pointer = '~';
return(answer);
}
char *hhmmss()
{
time_t time_now;
struct tm *time_pointer;
static char time_formatted[10];
time(&time_now);
time_pointer = localtime(&time_now);
sprintf(time_formatted,"%02d:%02d:%02d",
time_pointer->tm_hour,
time_pointer->tm_min,
time_pointer->tm_sec);
return(time_formatted);
}
void signal_handler(signal_received)
int signal_received;
{
if (signal_received == 20)
{
fprintf(stdout,"%s SIGNAL %d RECEIVED; CONTINUE\n", hhmmss(), signal_received);
fflush(stdout);
return;
}
else
{
fprintf(stdout,"%s SIGNAL %d RECEIVED; EXIT GRACEFULLY\n", hhmmss(), signal_received);
fflush(stdout);
exit_code |= 128;
exit(exit_code);
}
}
char *right_trim(string,nullable_flag)
char *string;
char *nullable_flag;
{
int i;
for(i = strlen(string) - 1; i >= 0; i--)
{
if (string[i] != ' ') break;
string[i] = 0;
}
if ((nullable_flag[0] == 'N') && (string[0] == 0))
{
string[0] = ' ';
string[1] = 0;
}
return(string);
}
char *string_cat(destination,source)
char *destination;
char *source;
{
char *here, *there;
/**************************************************************************/
/* */
/* Find end of destination string. */
/* */
/**************************************************************************/
there = destination;
while (*there)
{
there++;
}
here=source;
while (*here)
{
if (*here == '\'')
{
*there = '\'';
there++;
}
*there = *here;
here++;
there++;
}
*there = 0;
return(destination);
}