/* SQLSRV$DYNAMIC.C * * Copyright (c) 1990,1996 by Oracle Corporation. All rights reserved. * * This module is part of an application program that demonstrates * Oracle SQL/Services. It is provided for instructional purposes only. * * This module contains the following routines: * * create_association * * Creates an Oracle SQL/Services client/server association. Checks * command line argument vector for names of server system, account, * password, and service name. If not present, prompts user. * * release_association * * Terminates an Oracle SQL/Services client/server association. * * execute_statement * * Accepts a string containing a dynamically executable SQL statement * from the other module (SQLSRV$DRIVER). If parameter markers are * present, it calls get_params. If the statement is a SELECT, it opens * a cursor, fetches rows, and displays them. If the statement is not a * SELECT, it executes the statement. * * get_params * * For each parameter marker in the SQL statement, get_params checks the * data type and inputs data from the terminal. * * display_select_list * * Display the data value of each select list item in the SQL statement. * * hande_error * * Handle an error from the Oracle SQL/Services client API by calling the * report_error routine to display the error message, then releasing * the association and exiting the sample application if the error * is non-recoverable. * * report_error * * Retrieves the error message returned by the server, if any. * Displays the error message text if present; otherwise, retrieves * the major and minor error codes and calls report_sqlsvcs_error to * display the error message associated with the Oracle SQL/Services * client API error code. * * report_sqlsvcs_error * * Displays an error message corresponding to an Oracle SQL/Services * client API error status. * * get_vms_password * * Prompts for the user password on VMS without echoing the password to * the screen. */ #include #include #include #if defined ( SQLSRV_LOCAL_INCLUDES ) #include "sqlsrv.h" /* Oracle SQL/Services structure definitions. */ #else #include /* Oracle SQL/Services structure definitions. */ #endif #if defined (__osf__) #include #endif #ifdef VMS #include #include #include #define SQLSRV_TXTPWDSIZ 34 #endif /* External function prototypes */ void getline ( char *prompt, char *line ); #if defined (_WINDOWS) || defined (WIN32) void getpwd ( char *prompt, char *password ); #endif /* Global function prototypes */ int create_association ( int argc, char *argv[], ASSOCIATE_ID *assoc_id, CHARPTR error_buf, int error_buf_len ); int release_association ( ASSOCIATE_ID assoc_id ); int execute_statement ( ASSOCIATE_ID assoc_id, char *sql_statement ); /* Local function prototypes */ static int get_params ( ASSOCIATE_ID assoc_id, SQLDA_ID param_sqlda ); static int display_select_list ( ASSOCIATE_ID assoc_id, SQLDA_ID select_sqlda ); static void handle_error ( ASSOCIATE_ID assoc_id ); static int report_error ( ASSOCIATE_ID assoc_id ); static void report_sqlsvcs_error ( SQS_LONGWORD major_error, SQS_LONGWORD minor_error_1, SQS_LONGWORD minor_error_2 ); #ifdef VMS static void get_vms_password ( char password[] ); #endif int create_association ( int argc, /* argument count */ char *argv[], /* argument vector */ ASSOCIATE_ID *assoc_id, /* address of association id */ CHARPTR error_buf, /* alternate error buffer */ int error_buf_len /* size of alternate error buffer */ ) { struct ASSOCIATE_STR associate_str; /* Association structure. */ char node_name[32]; /* Node name. */ char user_name[32]; /* Server account username. */ char password[34]; /* Server account password. */ char xptnam[32]; /* Network transport name. */ char service_name[32]; /* Service name. */ int xpt; /* Network transport. */ int sts; /* Return status value. */ int i; /* Prompt for server node name if not in argument vector */ if (argc > 1) { strcpy(node_name, argv[1]); } else { #if defined (VMS) || defined (__osf__) || defined(MSDOS) || defined(WINDOWS) getline( "Server node OR Oracle SQL*Net service name: ", node_name ); #else getline( "Server node: ", node_name ); #endif } /* Prompt for transport if not in argument vector (TCP/IP-only on Sun) */ if (argc > 2) { strcpy(xptnam, argv[2]); } else { #if !defined( sparc ) && !defined ( OS2 ) getline("Network Transport: ", xptnam); #else strcpy(xptnam, "t" ); #endif } /* Set the transport; let Oracle SQL/Services choose it if not specified. */ xpt = SQLSRV_XPT_NOT_CHOSEN; switch( xptnam[0] ) { case 'T': case 't': xpt = SQLSRV_XPT_TCPIP; break; case 'D': case 'd': xpt = SQLSRV_XPT_DECNET; break; #if defined( MPW) || defined( THINK_C) case 'A': case 'a': xpt = SQLSRV_XPT_ATK; break; #endif #if defined (VMS) || defined (__osf__) || defined(MSDOS) || defined(WINDOWS) case 'S': case 's': xpt = SQLSRV_XPT_SQLNET; break; #endif #if defined(MSDOS) || defined(WINDOWS) case 'N': case 'n': xpt = SQLSRV_XPT_SPXIPX; break; #endif default: /* If the user doesn't choose a transport, then use DECNET */ /* everywhere except on the MAC and Solaris. On the MAC, leave */ /* it as SQLSRV_XPT__NOT_CHOSEN to use the transport selected */ /* using the control panel. On Solaris always use TCP/IP. */ #if defined ( sparc ) xpt = SQLSRV_XPT_TCPIP; #elif !defined( MPW) && !defined( THINK_C) xpt = SQLSRV_XPT_DECNET; #endif break; } /* end switch( xptnam[0] ) */ /* Prompt for user name if not in argument vector */ if (argc > 3) { strcpy(user_name, argv[3]); } else { getline("Server account name: ", user_name); } /* Prompt for password if not in argument vector */ if (argc > 4) { strcpy(password, argv[4]); } else { #if defined (_WINDOWS) || defined (WIN32) getpwd("Server account password: ", password); #elif defined (__osf__) initscr(); addstr("Server account password: "); noecho(); getstr( password ); echo(); endwin(); #elif defined (VMS) get_vms_password(password); #else getline("Server account password: ", password); #endif } /* Prompt for service name if not in argument vector, unless the user */ /* selected the Oracle SQL*net transport. */ if (xpt == SQLSRV_XPT_SQLNET) { strcpy(service_name, ""); } else { if (argc > 5) { strcpy(service_name, argv[5]); } else { getline("Service name [GENERIC]: ", service_name ); if (strlen(service_name) == 0 ) { strcpy(service_name, "GENERIC" ); } } } /* Reject extraneous arguments */ if (argc > 6) { for (i = 6; i < argc; i++) { printf("Extraneous argument ignored: %s\n", argv[i]); } } /* Set up association structure */ associate_str.VERSION = SQLSRV_V700; /* Structure version number */ associate_str.CLIENT_LOG = 0; /* Disable client logging. */ associate_str.SERVER_LOG = 0; /* Obsolete */ associate_str.LOCAL_FLAG = 0; /* Obsolete */ associate_str.MEMORY_ROUTINE = NULL; /* Use default memory rtns. */ associate_str.FREE_MEMORY_ROUTINE = NULL; /* Use default memory rtns. */ associate_str.ERRBUFLEN = error_buf_len; /* Alternate err buf length */ associate_str.ERRBUF = error_buf; /* Alternate error buffer */ associate_str.class_name = (CHARPTR)service_name; /* Service name */ associate_str.xpttyp = xpt; /* Transport type */ associate_str.attach = NULL; /* No SQL ATTACH statement */ associate_str.declare = NULL; /* No SQL DECLARE statement */ associate_str.appnam = (CHARPTR)"Sample App"; /* Our application name */ /* Connect with the server and establish an association. */ sts = sqlsrv_associate( node_name, /* node name. */ user_name, /* user name. */ password, /* password. */ NULL, /* protocol read buffer. */ NULL, /* protocol write buffer. */ 0, /* read buffer size. */ 0, /* write buffer size. */ NULL, /* let Oracle SQL/Services allocate SQLCA */ &associate_str, /* ASSOCIATE structure. */ assoc_id /* Association ID. */ ); /* Check completion status of new association */ if (sts != SQL_SUCCESS) { /* * Association failed. If the Association ID is non-NULL, then * report the error using the report_error routine, which displays * any additional error message text, then release the resources * allocated to the association in the client. Otherwise, call the * report_sqlsvcs_error to display the error message corresponding * to the Oracle SQL/Services client API error returned by * sqlsrv_associate. */ if (*assoc_id != NULL) { report_error(*assoc_id); sqlsrv_release( *assoc_id, /* association ID. */ NULL /* reserved argument. */ ); } else { report_sqlsvcs_error((SQS_LONGWORD)sts, 0, 0); } } /* Return status to driver module */ return sts; } /* create_association */ int release_association ( ASSOCIATE_ID assoc_id /* association ID */ ) { int sts; /* Return status value. */ /* Release the association. */ sts = sqlsrv_release( assoc_id, /* association ID. */ NULL /* reserved argument. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); } /* Return status to driver module */ return sts; } /* release_association */ int execute_statement ( ASSOCIATE_ID assoc_id, /* association ID */ char *sql_statement /* SQL statement to execute */ ) { /* Variables and structures for Oracle SQL/Services API */ int sts; /* return status value. */ SQS_LONGWORD statement_id; /* Prepared statement id. */ char *cursor_name = "SEL"; /* Cursor name for SELECTs. */ SQLDA_ID param_sqlda; /* Parameter marker SQLDA. */ SQLDA_ID select_sqlda; /* Select list SQLDA. */ SQS_LONGWORD sqlerrd_array[6]; /* SQLERRD array for errors */ SQS_LONGWORD statement_type; /* Statement type. */ /* Many simple SQL statements do not use parameter marker or select list */ /* SQLDAs and are typically executed using sqlsrv_execute_immediate. */ /* This behavior can be overridden in this sample application simply by */ /* typing the SQL statement in upper-case. */ if (strncmp( sql_statement, "attach", strlen( "attach" ) ) == 0 || strncmp( sql_statement, "connect", strlen( "connect" ) ) == 0 || strncmp( sql_statement, "disconnect", strlen( "disconnect" ) ) == 0 || strncmp( sql_statement, "declare", strlen( "declare" ) ) == 0 || strncmp( sql_statement, "commit", strlen( "commit" ) ) == 0 || strncmp( sql_statement, "rollback", strlen( "rollback" ) ) == 0 || strncmp( sql_statement, "set", strlen( "set" ) ) == 0 ) { sts = sqlsrv_execute_immediate( assoc_id, /* association ID. */ 0, /* database id, must be zero. */ sql_statement /* SQL statement. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } return SQL_SUCCESS; } /* Call the sqlsrv_prepare routine to prepare the SQL statement and to */ /* write parameter marker and select list information into the SQLDA */ /* structures. If you pass NULL pointers to the parameter marker SQLDA */ /* and the select list SQLDA, sqlsrv_prepare allocates and initializes */ /* the structures if they are required. You can also allocate memory */ /* for the parameter marker and select list SQLDAs and supply the */ /* addresses, in which case sqlsrv_prepare initializes them. */ select_sqlda = NULL; param_sqlda = NULL; sts = sqlsrv_prepare( assoc_id, /* association ID. */ 0, /* database id, must be zero. */ sql_statement, /* SQL statement. */ &statement_id, /* to receive prepared statement id */ ¶m_sqlda, /* to receive parameter marker SQLDA */ &select_sqlda /* to receive select list SQLDA */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* The call to sqlsrv_prepare succeeded. Retrieve the SQLERRD array so */ /* we can determine the statement type from SQLERRD[1]. */ sts = sqlsrv_sqlca_sqlerrd( assoc_id, /* association ID. */ sqlerrd_array /* to receive SQLERRD array */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } statement_type = sqlerrd_array[1]; /* If sqlsrv_prepare allocated a parameter marker SQLDA, the SQL */ /* statement contains parameter markers, in which case we must allocate */ /* memory for the data and indicator variables, then prompt for the */ /* parameter marker values. NOTE: if the application preallocated the */ /* parameter marker SQLDA, then use (param_sqlda.SQLD > 0) to test for */ /* the presence of parameter markers here. */ if (param_sqlda != NULL) { sts = sqlsrv_allocate_sqlda_data( assoc_id, /* association ID. */ param_sqlda /* Parameter marker SQLDA. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } sts = get_params(assoc_id, param_sqlda); if (sts != SQL_SUCCESS) { sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } } /* If sqlsrv_prepare allocated a select list SQLDA, the statement is */ /* either a SELECT, singleton-SELECT, or a CALL statement that has */ /* output or input/output arguments, in which case we must allocate */ /* memory for the data and indicator variables. NOTE: if the application */ /* preallocated the select list SQLDA, then use (select_sqlda.SQLD > 0) */ /* to test for the presence of select list items here. */ if (select_sqlda != NULL) { sts = sqlsrv_allocate_sqlda_data( assoc_id, /* association ID. */ select_sqlda /* Select list SQLDA. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } } /* If the statement is a SELECT statement, (statement_type == 1), then */ /* open a cursor, fetch and display the result table, and close the */ /* cursor; otherwise, execute the statement and display any results. */ if (statement_type == 1) { /* Open the cursor */ sts = sqlsrv_open_cursor( assoc_id, /* association id */ cursor_name, /* cursor name */ statement_id, /* statement ID */ param_sqlda /* parameter marker SQLDA */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } /* fetch and display all the rows in the result table */ printf("------ BEGIN RESULT TABLE ------\n"); do { sts = sqlsrv_fetch( assoc_id, /* association id */ cursor_name, /* cursor name */ 0, /* scroll option */ 0L, /* position */ select_sqlda /* select list SQLDA */ ); switch (sts) { case SQL_SUCCESS: sts = display_select_list(assoc_id, select_sqlda); printf("---------- END OF ROW ----------\n"); break; case SQL_EOS: printf("------- END RESULT TABLE -------\n"); break; default: handle_error(assoc_id); break; } } while (sts == SQL_SUCCESS); /* Close the cursor */ sts = sqlsrv_close_cursor( assoc_id, /* association id */ cursor_name /* cursor name */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } } else { /* The SQL statement is not a SELECT and can be executed now. Note */ /* that sqlsrv_execute_in_out can handle all executable statements, */ /* whether or not they have any select list items, or out or in/out */ /* arguments. */ sts = sqlsrv_execute_in_out( assoc_id, /* association ID. */ 0, /* database_id, must be zero. */ statement_id, /* Prepared statement id. */ SQLSRV_EXE_W_DATA, /* Normal non-batched execute mode. */ param_sqlda, /* Parameter marker SQLDA. */ select_sqlda /* Select list SQLDA. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); sqlsrv_release_statement(assoc_id, 1, &statement_id); return sts; } /* Display results, if any. */ if (select_sqlda != NULL) { printf("--------- SELECT LIST SQLDA ---------\n"); display_select_list(assoc_id, select_sqlda); printf("------- END SELECT LIST SQLDA -------\n"); } } /* Release the SQL statement resources */ sts = sqlsrv_release_statement( assoc_id, /* association ID. */ 1, /* number of statement id's. */ &statement_id /* statement id array. */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* Return status to driver module */ return SQL_SUCCESS; } /* execute_statement */ static int get_params ( ASSOCIATE_ID assoc_id, /* Associate ID. */ SQLDA_ID param_sqlda /* Parameter marker SQLDA. */ ) { int sts; /* Return status value. */ char colname[ 32 ]; /* Column name */ short colnamlen; /* Length of column name */ short coltyp; /* Column data type */ unsigned short int collen; /* Column length */ short colscl; /* Column scale or sub-type */ CHARPTR coldata; /* Pointer to column data */ SHORTPTR nullp; /* Pointer to indicator */ short i; /* Loop counter */ unsigned short int len; /* Length of user data */ CHARPTR varchar_ptr; /* Pointer to VARCAR data */ unsigned short int maxlen; /* Maximum input length */ char lcldata[ 80 ]; /* Input buffer */ /* SQLD contains the number of parameter markers */ for (i = 0; i < sqlsrv_sqlda_sqld( param_sqlda ); i++) { /* Get the column name */ sts = sqlsrv_sqlda_column_name( param_sqlda, /* parameter marker SQLDA */ i, /* column index number */ colname, /* to receive column name */ &colnamlen /* to receive column name length */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* Reference the SQLDATA and SQLIND for this column */ sts = sqlsrv_sqlda_ref_data( param_sqlda, /* parameter marker SQLDA */ i, /* column index number */ &coltyp, /* to receive column data type */ &collen, /* to receive column length */ &colscl, /* to receive column scale/type */ &coldata, /* to receive column data ptr. */ &nullp, /* to receive column ind. ptr. */ NULL /* reserved argument */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* maximum length for prompted values is 80 bytes. */ maxlen = (collen > 80) ? 80 : collen; /* Data type-specific length processing */ switch (coltyp) { case SQLSRV_GENERALIZED_DATE: /* Length includes space for NULL-terminator */ maxlen--; break; case SQLSRV_GENERALIZED_NUMBER: /* Length doesn't include 5 extra bytes for numbers */ /* expressed in scientific notation */ maxlen += 5; break; } /* loop until we get valid data for the parameter marker */ do { printf("Enter value for: %s\n", colname); printf("Maximum length is: %d\n", maxlen); if (coltyp == SQLSRV_GENERALIZED_DATE ) { printf("Format is: ccyymmddhhmissff\n"); } printf("Enter 'NULL' for null value\n"); getline("DATA> ", lcldata); len = strlen(lcldata); if (len == 0) { printf("Value required, please reenter.\n"); continue; } if (len > maxlen) { printf("Value too long, please reenter.\n"); continue; } /* check for a NULL value */ if (!strcmp(lcldata, "NULL")) { /* Set null-indicator to -1 to indicate a null value */ *nullp = -1; } else { /* Set null-indicator to 0 to indicate the presence of data */ *nullp = 0; /* process based on the data type of the parameter marker */ switch(coltyp) { case SQLSRV_ASCII_STRING: /* fixed-length string: copy the data to the */ /* SQLDATA memory; pad with spaces if necessary */ memcpy( (SCHARPTR)coldata, lcldata, len ); if (len < maxlen) { memset( (SCHARPTR)coldata+len, ' ', maxlen-len ); } break; case SQLSRV_GENERALIZED_NUMBER: case SQLSRV_GENERALIZED_DATE: case SQLSRV_INTERVAL: /* null-terminated strings: just use strcpy to */ /* copy the data value and the null-terminator */ strcpy( (SCHARPTR)coldata, lcldata ); break; case SQLSRV_VARCHAR: /* variable-length data with length field: write */ /* the length into the leading 16-bit length field */ /* of the buffer, then advance the pointer over */ /* the length to the beginning of the data and */ /* copy the data */ varchar_ptr = coldata; *(unsigned short int *)varchar_ptr = len; varchar_ptr += sizeof(unsigned short int); memcpy( (SCHARPTR)varchar_ptr, lcldata, len ); break; default: /* Unknown/unsupported data type */ printf("Unknown or unsupported data type: %d\n", coltyp); break; } /* switch */ } /* else */ } while (len == 0 || len > maxlen); /* De-reference the SQLDATA and SQLIND for this column */ sts = sqlsrv_sqlda_unref_data( param_sqlda, /* parameter marker SQLDA */ i /* column index number */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } } /* for */ return SQL_SUCCESS; } /* get_params */ static int display_select_list ( ASSOCIATE_ID assoc_id, /* Associate ID. */ SQLDA_ID select_sqlda /* Select list SQLDA. */ ) { int sts; /* Return status value. */ char colname[ 32 ]; /* Column name */ short colnamlen; /* Length of column name */ short coltyp; /* Column data type */ unsigned short int collen; /* Column length */ short colscl; /* Column scale or sub-type */ CHARPTR coldata; /* Pointer to column data */ SHORTPTR nullp; /* Pointer to indicator */ short i; /* Loop counter */ CHARPTR varchar_ptr; /* Pointer to VARCAR data */ int varchar_len; /* Length of VARCHAR data */ /* SQLD contains number of columns */ for (i = 0; i < sqlsrv_sqlda_sqld( select_sqlda ); i++) { /* Get the column name */ sts = sqlsrv_sqlda_column_name( select_sqlda, /* select list SQLDA */ i, /* column index number */ colname, /* to receive column name */ &colnamlen /* to receive column name length */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* print first 20 chars of column name */ printf("%-20.20s: ", colname); /* Reference the SQLDATA and SQLIND for this column */ sts = sqlsrv_sqlda_ref_data( select_sqlda, /* select list SQLDA */ i, /* column index number */ &coltyp, /* to receive column data type */ &collen, /* to receive column length */ &colscl, /* to receive column scale/type */ &coldata, /* to receive column data ptr. */ &nullp, /* to receive column ind. ptr. */ NULL /* reserved argument */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } /* check the indicator variable for NULL value */ if (*nullp < 0) { printf("NULL\n"); } else { switch (coltyp) { case SQLSRV_ASCII_STRING: /* Fixed-length character strings */ printf("%-.*s\n", collen, coldata); break; case SQLSRV_GENERALIZED_NUMBER: case SQLSRV_GENERALIZED_DATE: case SQLSRV_INTERVAL: /* Null-terminated strings */ printf("%s\n", coldata); break; case SQLSRV_VARCHAR: /* Counted string. The first 16-bit unsigned word of */ /* the data buffer is the length. Get length then */ /* advance the pointer to the data. */ /* Note: SQLSRV_VARCHAR data may contain non-printable */ /* binary data; a real application may not display the */ /* data value using printf. */ varchar_ptr = coldata; varchar_len = *(unsigned short int *)varchar_ptr; varchar_ptr += sizeof(unsigned short int); printf("%-.*s\n", varchar_len, varchar_ptr); break; } /* switch */ } /* else */ /* De-reference the SQLDATA and SQLIND for this column */ sts = sqlsrv_sqlda_unref_data( select_sqlda, /* select list SQLDA */ i /* column index number */ ); if (sts != SQL_SUCCESS) { handle_error(assoc_id); return sts; } } /* for */ return SQL_SUCCESS; } /* display_select_list */ static void handle_error ( ASSOCIATE_ID assoc_id /* association ID */ ) { int major_error; /* Major error status value */ /* Display the complete error message, then release the association and */ /* exit the sample application if error is non-recoverable. */ major_error = report_error(assoc_id); if (major_error == SQLSRV_NETERR || major_error == SQLSRV_INTERR || major_error == SQLSRV_EXEINTERR || major_error == SQLSRV_CONNTIMEOUT || major_error == SQLSRV_SVC_SHUTDOWN) { sqlsrv_release(assoc_id, NULL); #if defined (_WINDOWS) IvpExit(); #else exit(2); #endif } } /* handle_error */ static int report_error ( ASSOCIATE_ID assoc_id /* association ID */ ) { SQS_LONGWORD major_error; /* SQLCODE from SQLCA */ SQS_LONGWORD minor_error_1; /* SQLERRD[0] from SQLCA */ SQS_LONGWORD minor_error_2; /* SQLERRD[2] from SQLCA */ int sts; short err_msg_len; char *fixup_ptr; char err_msg_buf[512]; /* Retrieve the error message text returned by the server, if any */ sts = sqlsrv_sqlca_error_text( assoc_id, /* associate ID */ &err_msg_len, /* to receive error message length */ err_msg_buf, /* error message buffer */ sizeof(err_msg_buf) /* size of error message buffer */ ); if ( sts != SQL_SUCCESS) { printf("Multiple errors encountered\n"); printf("Most recent error value: %d\n", sts); return sts; } /* Display the error message text if there is any; otherwise retrieve */ /* the major and minor error codes from the SQLCA, and treat the error */ /* as an Oracle SQL/Services client API error and display the */ /* corresponding error message. */ if (err_msg_len != 0) { /* * Subsitute - for % in %SQLSRV, %DBS or %SQL error messages that * might cause printf to fail. */ fixup_ptr = strstr(err_msg_buf, "%S"); if (fixup_ptr == NULL) { fixup_ptr = strstr(err_msg_buf, "%D"); } if (fixup_ptr != NULL) { *fixup_ptr = '-'; } printf("%s\n", err_msg_buf); } else { sts = sqlsrv_sqlca_error( assoc_id, /* associate ID */ &major_error, /* to receive major error code */ &minor_error_1, /* to receive first sub-error */ &minor_error_2 /* to receive second sub-error */ ); if ( sts != SQL_SUCCESS) { printf("Multiple errors encountered\n"); printf("Most recent error value: %d\n", sts); return sts; } report_sqlsvcs_error( major_error, minor_error_1, minor_error_2 ); } /* Return status to caller for any special error handling */ return major_error; } /* report_error */ static void report_sqlsvcs_error ( SQS_LONGWORD major_error, /* Major error value */ SQS_LONGWORD minor_error_1, /* First sub-error value */ SQS_LONGWORD minor_error_2 /* Second sub-error value */ ) { /* Process error based on major error code */ switch (major_error) { case SQLSRV_INVARG: printf("Invalid routine parameter.\n"); break; case SQLSRV_INVBUFSIZ: printf("Invalid read or write buffer size.\n"); break; case SQLSRV_NETERR: #if defined WINDOWS || defined VMS || defined __osf__ if (minor_error_1 == SQLSRV_SQLNET_BADINIT) { printf("Network error: Oracle SQL*Net bad initialization.\n"); break; } if (minor_error_1 == SQLSRV_SQLNET_BADSERVICE) { printf("Network error: Oracle SQL*Net service lookup error.\n"); break; } if (minor_error_1 == SQLSRV_SQLNET_BADCONNECT) { printf("Network error: Oracle SQL*Net connect primary error: %ld.\n", (long)minor_error_2); break; } #endif printf("Network returned an error.\n"); printf("SQLERRD[0]: %ld\n", (long)minor_error_1); printf("SQLERRD[2]: %ld\n", (long)minor_error_2); break; case SQLSRV_INVASC: printf("Invalid association ID.\n"); break; case SQLSRV_INVSQLDA: printf("Invalid SQLDA structure.\n"); break; case SQLSRV_PRSERR: printf("Internal error parsing message protocol.\n"); break; case SQLSRV_INVSTMID: printf("Invalid statement ID.\n"); break; case SQLSRV_INVCURNAM: printf("Invalid cursor name.\n"); break; case SQLSRV_INTERR: printf("Internal client or server error. Examine log files for details\n"); break; case SQLSRV_OPNLOGFIL: printf("Unable to open log file\n"); break; case SQLSRV_NO_MEM: printf("Memory allocation failed.\n"); break; case SQLSRV_INVSQLCA: printf("Invalid SQLCA structure.\n"); break; case SQLSRV_SQLDA_NOTALL: printf("Attempt to free SQLDA memory not allocated by Oracle SQL/Services.\n"); break; case SQLSRV_MULTI_ACT: printf("A batched sqlsrv_execute or sqlsrv_fetch_many context is active.\n"); break; case SQLSRV_INVEXEFLG: printf("Invalid execute flag.\n"); break; case SQLSRV_INVASCSTR: printf("Invalid parameter in ASSOCIATE_STR.\n"); break; case SQLSRV_DUPCRSNAM: printf("Duplicate cursor name.\n"); break; case SQLSRV_INVCOLNUM: printf("Invalid column index number.\n"); break; case SQLSRV_INVDATTYP: printf("Invalid column data type.\n"); break; case SQLSRV_INCDATTYP: printf("Incompatible column data type.\n"); break; case SQLSRV_USRDATALL: printf("Attempt to free SQLDA data memory not allocated by Oracle SQL/Services.\n"); break; case SQLSRV_ACTSTM: printf("The statement ID already has an active cursor.\n"); break; case SQLSRV_APINOTSUP: printf("Oracle SQL/Services client API request is not supported.\n"); break; case SQLSRV_INV_CLS: printf("Service doesn't exist or is not running.\n"); break; case SQLSRV_NO_PRCAVL: printf("No executor processes are available.\n"); break; case SQLSRV_GETACCINF: printf("User authentication failed.\n"); break; case SQLSRV_EXEINTERR: printf("The executor process has encountered an internal error.\n"); break; case SQLSRV_HOSTERR: printf("Unable to connect to specified server using TCP/IP.\n"); printf("Check host name, hosts file, or name server.\n"); break; case SQLSRV_XPT_MISSING: printf("Network transport not supported on this platform.\n"); break; case SQLSRV_NO_SYSFLDR: printf("Can't find Oracle SQL/Services control panel file.\n"); break; case SQLSRV_NO_RSRC: printf("Can't access a resource in the Oracle SQL/Services control panel.\n"); break; case SQLSRV_NO_CONNREC: printf("Error using the CommToolbox; check node name.\n"); break; case SQLSRV_PARTIAL_XFR: printf("Partial write occured while sending a message to the server.\n"); break; case SQLSRV_SRVNOTSUP: printf("Server doesn't support operation requested by client.\n"); break; case SQLSRV_INVSETLEN: printf("Unsupported data type for operation or invalid column lengths.\n"); break; case SQLSRV_INVSQLLEN: printf("Invalid column length.\n"); case SQLSRV_DLL_LOAD_ERR: printf("Error returned from MS Windows LoadLibrary call.\n"); break; case SQLSRV_DLL_ADDR_ERR: printf("Error returned from MS Windows GetProcAddress call.\n"); break; case SQLSRV_INVSELLST: printf("Invalid select list.\n"); break; case SQLSRV_PWD_EXPIRED: printf("Password has expired.\n"); break; case SQLSRV_CONNTIMEOUT: printf("Server timed-out inactive connection.\n"); break; case SQLSRV_SVCNOTRUN: printf("Requested service is not running.\n"); break; case SQLSRV_SVC_SHUTDOWN: printf("Requested service was shut down.\n"); break; case SQLSRV_TOOMANYCONNECTS: printf("Too many network connections at server.\n"); break; case SQLSRV_FTCMNYACT: printf("sqlsrv_fetch_many is already active for the cursor.\n"); break; case SQLSRV_DATA_TOO_LONG: printf("A data value exceeded the maximum allowed for the data type.\n"); break; default: printf("Unknown error\n"); printf("SQLCA.SQLCODE: %d\n", major_error); break; } /* switch */ } /* report_sqlsvcs_error */ #ifdef VMS static void get_vms_password ( char password[] ) { int sts, i; short int chn; char msg[SQLSRV_TXTPWDSIZ]; struct sqlsrv_iosbstr { /* I/O status block structure */ unsigned short int sts; /* status value */ unsigned short int cnt; /* transfer count */ int devspc; /* Device-specific */ } iosb; $DESCRIPTOR( indsc, "SYS$INPUT" ); printf( "Server account password: " ); sts = sys$assign( &indsc, &chn, 0, NULL ); if ( sts == 1 ) { sts = sys$qiow( 0, /* event flag 0 */ chn, /* channel number */ IO$_READVBLK|IO$M_NOECHO, /* read function */ &iosb, /* IOSB */ NULL, /* AST routine */ NULL, /* AST parameter */ msg, /* read buffer address */ SQLSRV_TXTPWDSIZ, /* read buffer len */ 0, 0, 0, 0); /* p3-p6 unused */ sys$dassgn( chn ); if ((sts == 1) && (iosb.sts == 1)) { strncpy( password, msg, iosb.cnt ); password[iosb.cnt] = '\0'; } else { gets( password ); } } else { gets( password ); } printf("****\n"); } /* get_vms_password */ #endif