Wait for results from the server and verify the correctness of the instructions the server is responding to.
RETCODE dbsqlok(dbproc) DBPROCESS *dbproc;
A pointer to the DBPROCESS structure that provides the connection for a particular front-end/server process. It contains all the information that DB-Library uses to manage communications and data between the front end and server.
SUCCEED or FAIL.
The most common reason for failing is a SQL syntax error. dbsqlok will also fail if there are semantic errors, such as incorrect column or table names. Failure occurs if any of the commands in the batch contains a semantic or syntax error.
In addition, a runtime error, such as a database protection violation, will cause dbsqlok to fail if the command buffer contains only a single command. If the command buffer contains multiple commands, a runtime error will not cause dbsqlok to fail. Instead, failure will occur with the dbresults call that processes the command causing the runtime error.
The situation is a bit more complicated for runtime errors and stored procedures. A runtime error on an execute command may cause dbsqlok to fail, in accordance with the rule given in the previous paragraph. A runtime error on a statement inside a stored procedure will not cause dbsqlok to fail, however. For example, if the stored procedure contains an insert statement and the user does not have insert permission on the database table, the insert statement fails, but dbsqlok will still return SUCCEED. To check for runtime errors inside stored procedures, use the dbretstatus routine to look at the procedure’s return status and trap relevant server messages inside your message handler.
dbsqlok reports the success or failure of a server command and initiates results processing for successful commands.
A successful dbsqlok call must always be followed by a call to dbresults to process the results.
dbsqlok is useful in the following situations:
After a dbsqlsend call
dbsqlok must be called after a batch of Transact-SQL commands is sent to the server with dbsqlsend.
After a dbrpcsend call
dbsqlok must be called after an RPC command is sent with dbrpcinit, dbrpcparam, and dbrpcsend.
After calls to dbwritetext or dbmoretext
dbsqlok must be called after a text update command is sent to the server by a call to dbwritetext or dbmoretext.
dbsqlok initiates results processing after a call to dbsqlsend.
dbsqlok and dbsqlsend provide an alternative to dbsqlexec. dbsqlexec sends a command batch and waits for initial results from the server. The application is blocked from doing anything else until results arrive. When dbsqlsend and dbsqlok are used with dbpoll, the application has a non-blocking alternative. The typical control sequence is as follows:
A call to dbsqlsend sends the command to the server.
The program calls dbpoll in a loop to check for the arrival of server results. Non-related work can be performed during each loop iteration. The loop terminates when dbpoll indicates results have arrived.
A call to dbsqlok reports success or failure and initiates results processing if successful.
On occasion, dbpoll may report that data is ready for dbsqlok to read when only the first bytes of the server response are present. When this occurs, dbsqlok waits for the rest of the response or until the timeout period has elapsed, just like dbsqlexec. In practice, however, the entire response is usually available at one time.
The example below illustrates the use of dbsqlok and dbpoll. The example calls an application function, busy_wait, to execute a dbpoll loop. Here is the mainline code that calls busy_wait:
/*
** This is a query that will take some time.
*/
dbcmd(dbproc, "waitfor delay '00:00:05' select its = 'over'");
/*
** Send the query with dbsqlsend. dbsqlsend does not
** wait for a server response.
*/
retcode = dbsqlsend(dbproc);
if (retcode != SUCCEED)
{
fprintf(stdout, "dbsqlsend failed. Exiting.\n");
dbexit();
exit(ERREXIT);
}
/*
** If we call dbsqlok() now, it might block. But, we can use
** a dbpoll() loop to get some other work done while
** we are waiting for the results.
*/
busy_wait(dbproc);
/*
** Now there should be some results waiting to be read, so
** call dbsqlok().
*/
retcode = dbsqlok(dbproc);
if (retcode != SUCCEED)
{
fprintf(stdout, "Query failed.\n");
}
else
{
... dbresults() loop goes here ...
}
busy_wait executes a dbpoll loop. During each iteration of the loop, a call to dbpoll determines whether results have arrived. If results have arrived, busy_wait returns. Otherwise, the function wait_work is called. wait_work performs a piece of non-related work, then returns. The functions wait_work_init and wait_work_cleanup perform initialization and cleanup for wait_work. Here is the code for these functions:
void busy_wait(dbproc)
DBPROCESS *dbproc;
{
RETCODE retcode;
DBPROCESS *ready_dbproc;
int poll_ret_reason;
wait_work_init();
while(1)
{
retcode = dbpoll(dbproc, 0, &ready_dbproc, &poll_ret_reason);
if (retcode != SUCCEED)
{
fprintf(stdout, "dbpoll() failed! Exiting.\n");
dbexit();
exit(ERREXIT);
}
if (poll_ret_reason == DBRESULT)
{
/*
** Query results have arrived. Now we break out of
** the loop and return. Our caller can then call dbsqlok().
*/
break; /* while */
}
else
{
/*
** Here's where we can do some non-related work while we
** are waiting.
*/
wait_work();
}
} /* while */
wait_work_cleanup();
} /* busy_wait */
/* These globals are used by the wait functions. */
static int wait_pos;
static char wait_char;
void wait_work()
{
/*
** "work", as defined here, consists of drawing a 'w' or 'W' to
** the terminal. We output one character each time we are called.
** When we reach the 65th character position, we switch from
** 'w' to 'W' (or vice-versa) and start over.
*/
fputc(wait_char, stdout);
++wait_pos;
if (wait_pos >= 65)
{
/*
** Go back to the beginning of the line, then switch from
** 'W' to 'w' or vice versa.
*/
fputc('\r', stdout);
wait_pos = 0;
wait_char = (wait_char == 'w' ? 'W' : 'w');
}
}
void wait_work_init()
{
wait_pos = 0;
wait_char = 'w';
}
void wait_work_cleanup()
{
fputc('\n', stdout);
}
dbsqlok initiates results processing after an RPC command. RPC commands are constructed and sent with dbrpcinit, dbrpcparam, and dbrpcsend. After dbrpcsend, the program must call dbsqlok.
dbpoll can be called in a loop to poll for a server response between dbrpcsend and dbsqlok.
See the reference pages for dbrpcinit, dbrpcparam, and dbrpcsend. The sample program example8.c demonstrates an RPC command.
dbsqlok initiates results processing after a text update command. For text updates, chunks of text can be sent to the server with dbwritetext and dbmoretext. After both of these calls, dbsqlok must be called.
See the reference pages for dbwritetext and dbmoretext. dbwritetext has an example.
dbcmd, dbfcmd, DBIORDESC, DBIOWDESC, dbmoretext, dbnextrow, dbpoll, DBRBUF, dbresults, dbretstatus, dbrpcsend, dbsettime, dbsqlexec, dbsqlsend, dbwritetext