RETCODE Exec_with_parameters_resolved()

in execute.c [454:679]


RETCODE	Exec_with_parameters_resolved(StatementClass *stmt, EXEC_TYPE exec_type, BOOL *exec_end)
{
	CSTR func = "Exec_with_parameters_resolved";
	RETCODE		retval;
	SQLLEN		start_row, end_row;
	SQLINTEGER	cursor_type, scroll_concurrency;
	ConnectionClass	*conn;
	QResultClass	*res;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	BOOL		prepare_before_exec = FALSE;
	char *stmt_with_params;
	SQLLEN		status_row = stmt->exec_current_row;
	int		count_of_deferred;

	*exec_end = FALSE;
	conn = SC_get_conn(stmt);
	MYLOG(MIN_LOG_LEVEL, "copying statement params: trans_status=%d, len=" FORMAT_SIZE_T ", stmt='%s'\n", conn->transact_status, strlen(stmt->statement), stmt->statement);

#define	return	DONT_CALL_RETURN_FROM_HERE???
#define	RETURN(code)	{ retval = code; goto cleanup; }
	ENTER_CONN_CS(conn);
	/* save the cursor's info before the execution */
	cursor_type = stmt->options.cursor_type;
	scroll_concurrency = stmt->options.scroll_concurrency;
	/* Prepare the statement if possible at backend side */
	if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
		prepare_before_exec = TRUE;

MYLOG(DETAIL_LOG_LEVEL, "prepare_before_exec=%d srv=%d\n", prepare_before_exec, stmt->use_server_side_prepare);
	/* Create the statement with parameters substituted. */
	stmt_with_params = stmt->stmt_with_params;
	if (LAST_EXEC == exec_type)
	{
		if (NULL != stmt_with_params)
		{
			free(stmt_with_params);
			stmt_with_params = stmt->stmt_with_params = NULL;
		}
		if (INVALID_EXPBUFFER ||
		    !stmt->stmt_deferred.data[0])
			RETURN(SQL_SUCCESS);
	}
	else
	{
		retval = copy_statement_with_parameters(stmt, prepare_before_exec);
		stmt->current_exec_param = -1;
		if (retval != SQL_SUCCESS)
		{
			stmt->exec_current_row = -1;
			*exec_end = TRUE;
			RETURN(retval) /* error msg is passed from the above */
		}
		stmt_with_params = stmt->stmt_with_params;
		if (!stmt_with_params) // Extended Protocol
			exec_type = DIRECT_EXEC;
	}

	MYLOG(MIN_LOG_LEVEL, "   stmt_with_params = '%s'\n", stmt->stmt_with_params);

	/*
	 *	The real execution.
	 */
MYLOG(MIN_LOG_LEVEL, "about to begin SC_execute exec_type=%d\n", exec_type);
	ipdopts = SC_get_IPDF(stmt);
	apdopts = SC_get_APDF(stmt);
	if (start_row = stmt->exec_start_row, start_row < 0)
		start_row = 0;
	if (end_row = stmt->exec_end_row, end_row < 0)
	{
		end_row = (SQLINTEGER) apdopts->paramset_size - 1;
		if (end_row < 0)
			end_row = 0;
	}
	if (LAST_EXEC == exec_type &&
	    NULL != ipdopts->param_status_ptr)
	{
		int i;
		for (i = end_row; i >= start_row; i--)
		{
			if (SQL_PARAM_UNUSED != ipdopts->param_status_ptr[i])
			{
				status_row = i;
				break;
			}
		}
	}
	count_of_deferred = stmt->count_of_deffered;
	if (DIRECT_EXEC == exec_type)
	{
		retval = SC_execute(stmt);
		stmt->count_of_deffered = 0;
	}
	else if (DEFFERED_EXEC == exec_type &&
		 stmt->exec_current_row < end_row &&
		 stmt->count_of_deffered + 1 < stmt->batch_size)
	{
		if (INVALID_EXPBUFFER)
			initPQExpBuffer(&stmt->stmt_deferred);
		if (INVALID_EXPBUFFER)
		{
			retval = SQL_ERROR;
			SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory", __FUNCTION__); 
		}
		else
		{
			if (NULL != stmt_with_params)
			{
				if (stmt->stmt_deferred.data[0])
					appendPQExpBuffer(&stmt->stmt_deferred, ";%s", stmt_with_params);
				else
					printfPQExpBuffer(&stmt->stmt_deferred, "%s", stmt_with_params);
			}
			if (NULL != ipdopts->param_status_ptr)
				ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS; // set without exec
			stmt->count_of_deffered++;
			stmt->exec_current_row++;
			RETURN(SQL_SUCCESS);
		}
	}
	else
	{
		if (VALID_EXPBUFFER)
		{
			if (NULL != stmt_with_params)
				appendPQExpBuffer(&stmt->stmt_deferred, ";%s", stmt_with_params);
			stmt->stmt_with_params = stmt->stmt_deferred.data;
		}
		retval = SC_execute(stmt);
		stmt->stmt_with_params = stmt_with_params;
		stmt->count_of_deffered = 0;
		if (VALID_EXPBUFFER)
			resetPQExpBuffer(&stmt->stmt_deferred);
	}
	if (retval == SQL_ERROR)
	{
MYLOG(MIN_LOG_LEVEL, "count_of_deferred=%d\n", count_of_deferred);
		param_status_batch_update(ipdopts, SQL_PARAM_ERROR, stmt->exec_current_row, count_of_deferred);
		stmt->exec_current_row = -1;
		*exec_end = TRUE;
		RETURN(retval)
	}
	res = SC_get_Result(stmt);
	/* special handling of result for keyset driven cursors */
	if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
	    SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
	{
		QResultClass	*kres;

		if (kres = QR_nextr(res), kres)
		{
			QR_set_fields(kres, QR_get_fields(res));
			QR_set_fields(res,  NULL);
			kres->num_fields = res->num_fields;
			QR_detach(res);
			SC_set_Result(stmt, kres);
			res = kres;
		}
	}
	ipdopts = SC_get_IPDF(stmt);
	if (ipdopts->param_status_ptr)
	{
		switch (retval)
		{
			case SQL_SUCCESS:
				ipdopts->param_status_ptr[status_row] = SQL_PARAM_SUCCESS;
				break;
			case SQL_SUCCESS_WITH_INFO:
MYLOG(MIN_LOG_LEVEL, "count_of_deffered=%d has_notice=%d\n", count_of_deferred, stmt->has_notice);
				param_status_batch_update(ipdopts, (count_of_deferred > 0 && !stmt->has_notice) ? SQL_PARAM_SUCCESS : SQL_PARAM_SUCCESS_WITH_INFO, status_row, count_of_deferred);
				break;
			default:
				param_status_batch_update(ipdopts, SQL_PARAM_ERROR, status_row, count_of_deferred);
				break;
		}
	}
	stmt->has_notice = 0;
	if (stmt->exec_current_row >= end_row)
	{
		*exec_end = TRUE;
		stmt->exec_current_row = -1;
	}
	else
		stmt->exec_current_row++;
	if (res)
	{
		EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
		const char *cmd = QR_get_command(res);

		if (retval == SQL_SUCCESS &&
		    NULL != cmd &&
		    start_row >= end_row &&
		    NULL != env &&
		    EN_is_odbc3(env))
		{
			int	count;
			int	status = 0;

			if (secure_sscanf(cmd, &status, "UPDATE %d", ARG_INT(&count)) == 1)
				;
			else if (secure_sscanf(cmd, &status, "DELETE %d", ARG_INT(&count)) == 1)
				;
			else
				count = -1;
			if (0 == count)
				retval = SQL_NO_DATA;
		}
		stmt->diag_row_count = res->recent_processed_row_count;
	}
	/*
	 *	The cursor's info was changed ?
	 */
	if (retval == SQL_SUCCESS &&
	    (stmt->options.cursor_type != cursor_type ||
	     stmt->options.scroll_concurrency != scroll_concurrency))
	{
		SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed", func);
		retval = SQL_SUCCESS_WITH_INFO;
	}

cleanup:
#undef	RETURN
#undef	return
	LEAVE_CONN_CS(conn);
	return retval;
}