/* Result Sets Interface */ #ifndef SQL_CRSR # define SQL_CRSR struct sql_cursor { unsigned int curocn; void *ptr1; void *ptr2; unsigned long magic; }; typedef struct sql_cursor sql_cursor; typedef struct sql_cursor SQL_CURSOR; #endif /* SQL_CRSR */ /* Thread Safety */ typedef void * sql_context; typedef void * SQL_CONTEXT; /* Object support */ struct sqltvn { unsigned char *tvnvsn; unsigned short tvnvsnl; unsigned char *tvnnm; unsigned short tvnnml; unsigned char *tvnsnm; unsigned short tvnsnml; }; typedef struct sqltvn sqltvn; struct sqladts { unsigned int adtvsn; unsigned short adtmode; unsigned short adtnum; sqltvn adttvn[1]; }; typedef struct sqladts sqladts; static struct sqladts sqladt = { 1,1,0, }; /* Binding to PL/SQL Records */ struct sqltdss { unsigned int tdsvsn; unsigned short tdsnum; unsigned char *tdsval[1]; }; typedef struct sqltdss sqltdss; static struct sqltdss sqltds = { 1, 0, }; /* File name & Package Name */ struct sqlcxp { unsigned short fillen; char filnam[7]; }; static const struct sqlcxp sqlfpn = { 6, "vb1.pc" }; static unsigned long sqlctx = 4611; static struct sqlexd { unsigned int sqlvsn; unsigned int arrsiz; unsigned int iters; unsigned int offset; unsigned short selerr; unsigned short sqlety; unsigned int occurs; const short *cud; unsigned char *sqlest; const char *stmt; sqladts *sqladtp; sqltdss *sqltdsp; void **sqphsv; unsigned int *sqphsl; int *sqphss; void **sqpind; int *sqpins; unsigned int *sqparm; unsigned int **sqparc; unsigned short *sqpadto; unsigned short *sqptdso; void *sqhstv[5]; unsigned int sqhstl[5]; int sqhsts[5]; void *sqindv[5]; int sqinds[5]; unsigned int sqharm[5]; unsigned int *sqharc[5]; unsigned short sqadto[5]; unsigned short sqtdso[5]; } sqlstm = {10,5}; // Prototypes extern "C" { void sqlcxt (void **, unsigned long *, struct sqlexd *, const struct sqlcxp *); void sqlcx2t(void **, unsigned long *, struct sqlexd *, const struct sqlcxp *); void sqlbuft(void **, char *); void sqlgs2t(void **, char *); void sqlorat(void **, unsigned long *, void *); } // Forms Interface static const int IAPSUCC = 0; static const int IAPFAIL = 1403; static const int IAPFTL = 535; extern "C" { void sqliem(char *, int *); } typedef struct { unsigned short len; unsigned char arr[1]; } VARCHAR; typedef struct { unsigned short len; unsigned char arr[1]; } varchar; /* cud (compilation unit data) array */ static const short sqlcud0[] = {10,4130,0,0,0, 5,0,0,1,0,0,32,62,0,0,0,0,0,1,0, 20,0,0,2,0,0,27,100,0,0,4,4,0,1,0,1,9,0,0,1,9,0,0,1,10,0,0,1,10,0,0, 51,0,0,3,95,0,4,126,0,0,5,1,0,1,0,2,9,0,0,2,9,0,0,2,9,0,0,2,9,0,0,1,9,0,0, 86,0,0,4,0,0,32,156,0,0,0,0,0,1,0, }; /* * vb1.pc * * Prompts the user for a branch number, * then queries the branch table for the branch's * address, phone and fax. * 2003, Siegfried Nijssen (snijssen@liacs.nl) */ #include #include #include #include #include #include // Define constants for VARCHAR lengths. #define UNAME_LEN 20 #define PWD_LEN 40 //* Declare variables. /* EXEC SQL BEGIN DECLARE SECTION; */ /* VARCHAR username[UNAME_LEN]; */ struct { unsigned short len; unsigned char arr[20]; } username; /* VARCHAR password[PWD_LEN]; */ struct { unsigned short len; unsigned char arr[40]; } password; // Define a host structure for the output values of a SELECT statement. struct { /* VARCHAR branch_no[10]; */ struct { unsigned short len; unsigned char arr[10]; } branch_no; /* VARCHAR address[60]; */ struct { unsigned short len; unsigned char arr[60]; } address; /* VARCHAR phone[13]; */ struct { unsigned short len; unsigned char arr[13]; } phone; /* VARCHAR fax[13]; */ struct { unsigned short len; unsigned char arr[13]; } fax; } branchrec; // Input host variable. /* VARCHAR branch_no[10]; */ struct { unsigned short len; unsigned char arr[10]; } branch_no; /* EXEC SQL END DECLARE SECTION; */ // Declare error handling function. void sql_error(char *msg) { char err_msg[128]; size_t buf_len, msg_len; /* EXEC SQL WHENEVER SQLERROR CONTINUE; */ /* after executing this line, sql_error is no longer used as * error handling function. In this way, infinite * recursion is avoided if the next SQL statement * in this function fails. */ // Print the error message: cout << msg << endl; buf_len = sizeof (err_msg); sqlglm(err_msg, &buf_len, &msg_len); cout << msg_len << "*" << err_msg << endl; // Make sure the database is consistent: /* EXEC SQL ROLLBACK RELEASE; */ { struct sqlexd sqlstm; sqlstm.sqlvsn = 10; sqlstm.arrsiz = 0; sqlstm.sqladtp = &sqladt; sqlstm.sqltdsp = &sqltds; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )5; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca; sqlstm.sqlety = (unsigned short)256; sqlstm.occurs = (unsigned int )0; sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); } // Stop the program. exit(EXIT_FAILURE); } void main() { char temp_char[32]; /* strings are of type VARCHAR in Oracle and not \0 * terminated. We use this temporary variable * whenever a \0 terminated string is necessary. */ cout << "Enter your ORACLE username: " << endl; cin >> temp_char; /* Connect to ORACLE-- * Copy the username into the VARCHAR. */ strncpy((char *) username.arr, temp_char, UNAME_LEN); // Set the length component of the VARCHAR. This is always required! username.len = (unsigned short) strlen((char *) username.arr); cout << "Enter your ORACLE password: " << endl; cin >> temp_char; // Copy the password. strncpy((char *) password.arr, temp_char, PWD_LEN); password.len = (unsigned short) strlen((char *) password.arr); // Register sql_error() as the error handler. */ /* EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--\n"); */ /* Connect to ORACLE. Program will call sql_error() * if an error occurs when connecting to the default database. */ /* EXEC SQL CONNECT :username IDENTIFIED BY :password; */ { struct sqlexd sqlstm; sqlstm.sqlvsn = 10; sqlstm.arrsiz = 4; sqlstm.sqladtp = &sqladt; sqlstm.sqltdsp = &sqltds; sqlstm.iters = (unsigned int )10; sqlstm.offset = (unsigned int )20; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca; sqlstm.sqlety = (unsigned short)256; sqlstm.occurs = (unsigned int )0; sqlstm.sqhstv[0] = ( void *)&username; sqlstm.sqhstl[0] = (unsigned int )22; sqlstm.sqhsts[0] = ( int )22; sqlstm.sqindv[0] = ( void *)0; sqlstm.sqinds[0] = ( int )0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqadto[0] = (unsigned short )0; sqlstm.sqtdso[0] = (unsigned short )0; sqlstm.sqhstv[1] = ( void *)&password; sqlstm.sqhstl[1] = (unsigned int )42; sqlstm.sqhsts[1] = ( int )42; sqlstm.sqindv[1] = ( void *)0; sqlstm.sqinds[1] = ( int )0; sqlstm.sqharm[1] = (unsigned int )0; sqlstm.sqadto[1] = (unsigned short )0; sqlstm.sqtdso[1] = (unsigned short )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqphss = sqlstm.sqhsts; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqpins = sqlstm.sqinds; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlstm.sqpadto = sqlstm.sqadto; sqlstm.sqptdso = sqlstm.sqtdso; sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) sql_error("ORACLE error--\n"); } cout << "Connected to ORACLE as user: " << username.arr << endl; /* Loop, asking for branch IDs */ do { cout << "Enter branch number: (0 to quit) "; cin >> temp_char; if ( strcmp ( temp_char, "0" ) == 0 ) break; // stop the while loop // Fill in branch_no that we will use in the query. strncpy((char *) branch_no.arr, temp_char, 10); branch_no.len = (unsigned short) strlen((char *) branch_no.arr); /* Branch to the notfound label when the * 1403 ("No data found") condition occurs. * Although labels are required here, this does not mean that * using labels in general is good programming practice! * You are only allowed to use labels as target for an SQL GOTO statement. */ /* EXEC SQL WHENEVER NOT FOUND GOTO notfound; */ /* EXEC SQL SELECT branch_no, address, phone, fax INTO :branchrec FROM Branch WHERE branch_no = :branch_no; */ { struct sqlexd sqlstm; sqlstm.sqlvsn = 10; sqlstm.arrsiz = 5; sqlstm.sqladtp = &sqladt; sqlstm.sqltdsp = &sqltds; sqlstm.stmt = "select branch_no ,address ,phone ,fax into :s1 ,:s2 ,:s3 \ ,:s4 from Branch where branch_no=:b1"; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )51; sqlstm.selerr = (unsigned short)1; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca; sqlstm.sqlety = (unsigned short)256; sqlstm.occurs = (unsigned int )0; sqlstm.sqhstv[0] = ( void *)&branchrec.branch_no; sqlstm.sqhstl[0] = (unsigned int )12; sqlstm.sqhsts[0] = ( int )0; sqlstm.sqindv[0] = ( void *)0; sqlstm.sqinds[0] = ( int )0; sqlstm.sqharm[0] = (unsigned int )0; sqlstm.sqadto[0] = (unsigned short )0; sqlstm.sqtdso[0] = (unsigned short )0; sqlstm.sqhstv[1] = ( void *)&branchrec.address; sqlstm.sqhstl[1] = (unsigned int )62; sqlstm.sqhsts[1] = ( int )0; sqlstm.sqindv[1] = ( void *)0; sqlstm.sqinds[1] = ( int )0; sqlstm.sqharm[1] = (unsigned int )0; sqlstm.sqadto[1] = (unsigned short )0; sqlstm.sqtdso[1] = (unsigned short )0; sqlstm.sqhstv[2] = ( void *)&branchrec.phone; sqlstm.sqhstl[2] = (unsigned int )15; sqlstm.sqhsts[2] = ( int )0; sqlstm.sqindv[2] = ( void *)0; sqlstm.sqinds[2] = ( int )0; sqlstm.sqharm[2] = (unsigned int )0; sqlstm.sqadto[2] = (unsigned short )0; sqlstm.sqtdso[2] = (unsigned short )0; sqlstm.sqhstv[3] = ( void *)&branchrec.fax; sqlstm.sqhstl[3] = (unsigned int )15; sqlstm.sqhsts[3] = ( int )0; sqlstm.sqindv[3] = ( void *)0; sqlstm.sqinds[3] = ( int )0; sqlstm.sqharm[3] = (unsigned int )0; sqlstm.sqadto[3] = (unsigned short )0; sqlstm.sqtdso[3] = (unsigned short )0; sqlstm.sqhstv[4] = ( void *)&branch_no; sqlstm.sqhstl[4] = (unsigned int )12; sqlstm.sqhsts[4] = ( int )0; sqlstm.sqindv[4] = ( void *)0; sqlstm.sqinds[4] = ( int )0; sqlstm.sqharm[4] = (unsigned int )0; sqlstm.sqadto[4] = (unsigned short )0; sqlstm.sqtdso[4] = (unsigned short )0; sqlstm.sqphsv = sqlstm.sqhstv; sqlstm.sqphsl = sqlstm.sqhstl; sqlstm.sqphss = sqlstm.sqhsts; sqlstm.sqpind = sqlstm.sqindv; sqlstm.sqpins = sqlstm.sqinds; sqlstm.sqparm = sqlstm.sqharm; sqlstm.sqparc = sqlstm.sqharc; sqlstm.sqpadto = sqlstm.sqadto; sqlstm.sqptdso = sqlstm.sqtdso; sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode == 1403) goto notfound; if (sqlca.sqlcode < 0) sql_error("ORACLE error--\n"); } /* Print data. * The branchrec.address VARCHAR is not \0 terminated. We have * to make it \0 terminated first to print it. */ branchrec.address.arr[branchrec.address.len] = '\0'; cout << "Address: " << branchrec.address.arr << endl; branchrec.phone.arr[branchrec.phone.len] = '\0'; cout << "Phone: " << branchrec.phone.arr << endl; branchrec.fax.arr[branchrec.fax.len] = '\0'; cout << "Fax: " << branchrec.fax.arr << endl; // Continue the loop, the other lines in this loop are // for error handling: continue; notfound: cout << endl << "Not a valid branch number - try again." << endl; } while ( true ); // continue after an invalid branch number. // Disconnect from ORACLE. /* EXEC SQL ROLLBACK WORK RELEASE; */ { struct sqlexd sqlstm; sqlstm.sqlvsn = 10; sqlstm.arrsiz = 5; sqlstm.sqladtp = &sqladt; sqlstm.sqltdsp = &sqltds; sqlstm.iters = (unsigned int )1; sqlstm.offset = (unsigned int )86; sqlstm.cud = sqlcud0; sqlstm.sqlest = (unsigned char *)&sqlca; sqlstm.sqlety = (unsigned short)256; sqlstm.occurs = (unsigned int )0; sqlcxt((void **)0, &sqlctx, &sqlstm, &sqlfpn); if (sqlca.sqlcode < 0) sql_error("ORACLE error--\n"); } exit(EXIT_SUCCESS); }