Example #1
0
int
odbcdr_xlt_status(		 /* Return RDBI equiv of SQL Server status  */
    odbcdr_context_def  *context,
	SQLRETURN odbcdr_status,
	SQLSMALLINT handle_type,
	SQLHANDLE handle 	
	)
{
	int		rdbi_status = RDBI_GENERIC_ERROR;

	debug_on1( "odbcdr_xlt_status","ODBC status: %d", odbcdr_status );

	switch( odbcdr_status ) {

		case SQL_SUCCESS :
   		case SQL_SUCCESS_WITH_INFO :
			rdbi_status = RDBI_SUCCESS;
			break;

		/* DS: THIS IS NOT TRUE!
		** SQL_SUCESS_WITH_INFO is returned after executing array DML, if
		** there are ignorable errors or if a row operation failed.
		** Therefore, we need to search the diagnostic record to see if any
		** real errors occured.

        /*
		** In the SQL_ERROR case, we need to check if we can convert it to a
		** more specific database error type. The message is saved in the
		** context->odbcdr_last_err_msg field.
		*/
		case SQL_ERROR :
			rdbi_status = get_error_from_diag_rec(context, handle_type, handle);
			break;
		case SQL_NO_DATA :
			rdbi_status = RDBI_END_OF_FETCH;
			break;
		case SQL_NEED_DATA :
		case SQL_INVALID_HANDLE :
		case SQL_STILL_EXECUTING :
			rdbi_status = RDBI_GENERIC_ERROR;
            if (context->odbcdr_UseUnicode)
			    save_err_msgW(context, handle_type, handle, 1); // 1 = assuming a connection has already been made
            else
                save_err_msg(context, handle_type, handle, 1); // 1 = assuming a connection has already been made
			break;
		default:
			rdbi_status = RDBI_GENERIC_ERROR;
	}

	debug_return(NULL, rdbi_status);
}
Example #2
0
/*
** Execute a statement or set of statements.  Print 
** any result rows/columns depending on the current mode 
** set via the supplied callback.
**
** This is very similar to SQLite's built-in sqlite3_exec() 
** function except it takes a slightly different callback 
** and callback data argument.
*/
static int shell_exec(
					  sqlite3 *db,                                /* An open database */
					  const char *zSql,                           /* SQL to be evaluated */
					  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function (not the same as sqlite3_exec) */
					  struct callback_data *pArg,                 /* Pointer to struct callback_data */
					  char **pzErrMsg                             /* Error msg written here */
	)
{
	sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
	int rc = SQLITE_OK;             /* Return Code */
	const char *zLeftover;          /* Tail of unprocessed SQL */

	if( pzErrMsg ){
		*pzErrMsg = NULL;
	}

	while( zSql[0] && (SQLITE_OK == rc) ){
		rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
		if( SQLITE_OK != rc ){
			if( pzErrMsg ){
				*pzErrMsg = save_err_msg(db);
			}
		}else{
			if( !pStmt ){
				/* this happens for a comment or white-space */
				zSql = zLeftover;
				while( isspace(zSql[0]) ) zSql++;
				continue;
			}

			/* save off the prepared statment handle and reset row count */
			if( pArg ){
				pArg->pStmt = pStmt;
				pArg->cnt = 0;
			}

			/* perform the first step.  this will tell us if we
			** have a result set or not and how wide it is.
			*/
			rc = sqlite3_step(pStmt);
			/* if we have a result set... */
			if( SQLITE_ROW == rc ){
				/* if we have a callback... */
				if( xCallback ){
					/* allocate space for col name ptr, value ptr, and type */
					int nCol = sqlite3_column_count(pStmt);
					void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
					if( !pData ){
						rc = SQLITE_NOMEM;
					}else{
						char **azCols = (char **)pData;      /* Names of result columns */
						char **azVals = &azCols[nCol];       /* Results */
						int *aiTypes = (int *)&azVals[nCol]; /* Result types */
						int i;
						assert(sizeof(int) <= sizeof(char *)); 
						/* save off ptrs to column names */
						for(i=0; i<nCol; i++){
							azCols[i] = (char *)sqlite3_column_name(pStmt, i);
						}
						do{
							/* extract the data and data types */
							for(i=0; i<nCol; i++){
								azVals[i] = (char *)sqlite3_column_text(pStmt, i);
								aiTypes[i] = sqlite3_column_type(pStmt, i);
								if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
									rc = SQLITE_NOMEM;
									break; /* from for */
								}
							} /* end for */

							/* if data and types extracted successfully... */
							if( SQLITE_ROW == rc ){ 
								/* call the supplied callback with the result row data */
								if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
									rc = SQLITE_ABORT;
								}else{
									rc = sqlite3_step(pStmt);
								}
							}
						} while( SQLITE_ROW == rc );
						sqlite3_free(pData);
					}
				}else{
					do{
						rc = sqlite3_step(pStmt);
					} while( rc == SQLITE_ROW );
				}
			}

			/* Finalize the statement just executed. If this fails, save a 
			** copy of the error message. Otherwise, set zSql to point to the
			** next statement to execute. */
			rc = sqlite3_finalize(pStmt);
			if( rc==SQLITE_OK ){
				zSql = zLeftover;
				while( isspace(zSql[0]) ) zSql++;
			}else if( pzErrMsg ){
				*pzErrMsg = save_err_msg(db);
			}

			/* clear saved stmt handle */
			if( pArg ){
				pArg->pStmt = NULL;
			}
		}
	} /* end while */

	return rc;
}
Example #3
0
static int get_error_from_diag_rec(
		odbcdr_context_def *context, 
		SQLSMALLINT handle_type, 
		SQLHANDLE handle)
{
	int		rdbi_status = RDBI_SUCCESS;
	int		crit_err_found = FALSE;
	RETCODE	rec_retcode = SQL_SUCCESS;
	RETCODE	field_retcode = SQL_SUCCESS;
	SQLWCHAR	szSqlState[ODBCDR_MAX_BUFF_SIZE];
	SQLWCHAR 	szErrorMsg[ODBCDR_MAX_BUFF_SIZE];
	SDWORD		pfNativeError = 0L;
	SWORD	 	pcbErrorMsg = 0;
	SQLSMALLINT cRecNmbr = 1;
	SDWORD  	SS_Severity = 0;
	SQLINTEGER	Rownumber = 0;
	SQLINTEGER  Colnumber = 0;
    szSqlState[0] = L'\0';
    szErrorMsg[0] = L'\0';

	/*
	** Loop through the diagnostic records until there are no records
	** left or a critical error is found.
	** For now, we will only deal with the first critical error, and
	** ignore the rest.
	*/
	while ((rec_retcode != SQL_NO_DATA_FOUND) && !crit_err_found) {
		rec_retcode = (context->odbcdr_UseUnicode) ? 
            SQLGetDiagRecW(handle_type, handle,
					cRecNmbr, szSqlState, &pfNativeError,
                    szErrorMsg, ODBCDR_MAX_BUFF_SIZE, &pcbErrorMsg) : 
            SQLGetDiagRec(handle_type, handle,
					cRecNmbr, (SQLCHAR*)szSqlState, &pfNativeError,
					(SQLCHAR*)szErrorMsg, ODBCDR_MAX_BUFF_SIZE, &pcbErrorMsg);
 
		if (rec_retcode != SQL_NO_DATA_FOUND) {
			field_retcode = (context->odbcdr_UseUnicode) ? 
                SQLGetDiagFieldW( handle_type, handle, cRecNmbr,
					SQL_DIAG_ROW_NUMBER, &Rownumber,
					SQL_IS_INTEGER, NULL) :
                SQLGetDiagField( handle_type, handle, cRecNmbr,
					SQL_DIAG_ROW_NUMBER, &Rownumber,
					SQL_IS_INTEGER, NULL);

			if (Rownumber != SQL_NO_ROW_NUMBER  && Rownumber != SQL_ROW_NUMBER_UNKNOWN)	{
				field_retcode = (context->odbcdr_UseUnicode) ? 
                    SQLGetDiagFieldW( handle_type, handle, cRecNmbr,
						SQL_DIAG_COLUMN_NUMBER , &Colnumber,
						SQL_IS_INTEGER, NULL) : 
                    SQLGetDiagField( handle_type, handle, cRecNmbr,
						SQL_DIAG_COLUMN_NUMBER , &Colnumber,
						SQL_IS_INTEGER, NULL);
			}
#ifdef _WIN32
			field_retcode = (context->odbcdr_UseUnicode) ? 
                SQLGetDiagFieldW( handle_type, handle, cRecNmbr,
					SQL_DIAG_SS_SEVERITY, &SS_Severity,
                    SQL_IS_INTEGER, NULL):
                SQLGetDiagField(handle_type, handle, cRecNmbr,
					SQL_DIAG_SS_SEVERITY, &SS_Severity,
					SQL_IS_INTEGER,NULL);
#endif

			switch( pfNativeError ) {
				case 208 :
					rdbi_status = RDBI_NO_SUCH_TABLE;
					crit_err_found = TRUE;
					break;
				case 916 :
					rdbi_status = RDBI_NOT_VALID_USER_IN_DATABASE;
					crit_err_found = TRUE;
					break;
				case 1555 :
					rdbi_status = RDBI_RESOURCE_BUSY;
					crit_err_found = TRUE;
					break;
				case 18456 :
					rdbi_status = RDBI_INVLD_USER_PSWD;
					crit_err_found = TRUE;
					break;
                case 913: 
                    // "Could not find database ID 52. Database may not be activated yet or may be in transition."
                    // Severity 16. This is rather a bug related to updating views.
                    rdbi_status = RDBI_GENERIC_ERROR;
                    break;
                case 2601:
				case 2627:
                    // Duplicate index found.
                    rdbi_status = RDBI_DUPLICATE_INDEX;
					crit_err_found = TRUE;
                    break;
				case 2714:
					// There is already an object named '%.*ls' in the database.
					rdbi_status = RDBI_OBJECT_EXISTS;
					crit_err_found = TRUE;
                    break;
				case 3701:
					// No such object
					rdbi_status = RDBI_NO_SUCH_TABLE;
					crit_err_found = TRUE;
					break;
                case 229:
                    // insufficient privileges
                    rdbi_status = RDBI_INSUFFICIENT_PRIVS;
                    crit_err_found = TRUE;
                    break;
				default :
					// If we did not identify any specific errors in the 
					// diagnostic record, use the severity level to 
					// determine if a error occurred
                    // *** DS doesn't agree.
					//if (SS_Severity > 10) {
						rdbi_status = RDBI_GENERIC_ERROR;
						crit_err_found = TRUE;
					//} else {
					//	rdbi_status = RDBI_SUCCESS;
					//}
			} //switch
			cRecNmbr++; //Increment to next diagnostic record.
		} //if plm_retcode

	} // End while.

    if (context->odbcdr_UseUnicode)
	    save_err_msgW( context, handle_type, handle, 1); // 1 = assuming a connection has already been made
    else
        save_err_msg( context, handle_type, handle, 1); // 1 = assuming a connection has already been made

	return rdbi_status;
}