Send a command to the server.
CS_RETCODE ct_send(cmd) CS_COMMAND *cmd;
A pointer to the CS_COMMAND structure managing a client/server operation.
ct_send returns the following values:
Return value |
Meaning |
---|---|
CS_SUCCEED |
The routine completed successfully. |
CS_FAIL |
The routine failed. For less serious failures, the application can call ct_cancel(CS_CANCEL_ALL) to clean up the command structure. For more serious failures, the application must call ct_close(CS_FORCE_CLOSE) to force the connection closed. |
CS_CANCELED |
The routine was canceled. |
CS_PENDING |
Asynchronous network I/O is in effect. See “Asynchronous programming”. |
CS_BUSY |
An asynchronous operation is already pending for this connection. See “Asynchronous programming”. |
Common causes of ct_send failure include results-pending errors and attempts to send a command that has not been initiated.
Results-pending errors
ct_send raises results-pending errors if Client-Library is reading results when ct_send is called. This can occur if the application is retrieving non-cursor results associated with another command structure that belongs to the same parent connection. Sometimes this problem can be solved by rewriting the application to use Client-Library cursors (see ct_cursor for details). If the application cannot use cursors, then separate connections are necessary.
Attempt to send a command that has not been initiated
ct_send fails if a command has not been defined with ct_command, ct_cursor, or ct_dynamic.
The following fragment declares a function that sends a language command and processes the results. The code assumes that the command returns no fetchable results.
/*
** ex_execute_cmd()
*/
CS_RETCODE CS_PUBLIC
ex_execute_cmd(connection, cmdbuf)
CS_CONNECTION *connection;
CS_CHAR *cmdbuf;
{
CS_RETCODE retcode;
CS_INT restype;
CS_COMMAND *cmd;
CS_RETCODE query_code;
/*
** Get a command handle, store the command string
** in it, and send it to the server.
*/
if ((retcode = ct_cmd_alloc(connection, &cmd)) !=
CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_cmd_alloc() \
failed");
return retcode;
}
if ((retcode = ct_command(cmd, CS_LANG_CMD,
cmdbuf, CS_NULLTERM, CS_UNUSED)) !=
CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_command() \
failed");
(void)ct_cmd_drop(cmd);
return retcode;
}
if ((retcode = ct_send(cmd)) != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_send() failed");
(void)ct_cmd_drop(cmd);
return retcode;
}
/*
** Examine the results coming back. If any errors
** are seen, the query result code (which we will
** return from this function) will be set to FAIL.
*/
...CODE DELETED.....
/* Clean up the command handle used */
if (retcode == CS_END_RESULTS)
{
retcode = ct_cmd_drop(cmd);
if (retcode != CS_SUCCEED)
{
query_code = CS_FAIL;
}
}
else
{
(void)ct_cmd_drop(cmd);
query_code = CS_FAIL;
}
return query_code;
}
This code excerpt is from the exutils.c example program.
ct_send sends a command over the network for the server to execute.
Before calling ct_send, the application must specify the type of command and the data needed for its execution. Once this step is done, the command structure is said to be initiated. The routines ct_command, ct_cursor, or ct_dynamic initiate a command.
See Chapter 5, “Choosing Command Types,” in the Open Client Client-Library/C Programmer’s Guide for a description of the server commands available to a Client-Library application.
For most command types, ct_send can be called to resend a previously executed command after all the results from the previous execution have been handled. Exceptions are noted in the following section titled “Resending commands.”
Sending a command to a server for first-time execution is a multi-step process:
Initiate the command by calling ct_command, ct_cursor, or ct_dynamic. These routines set up internal structures that are used in building a symbolic command stream to send to the server.
Pass parameters for the command (if required) by calling ct_param or ct_setparam once for each parameter that the command requires.
Not all commands require parameters. For example, a remote procedure call command may or may not require parameters, depending on the stored procedure being called.
Send the command to the server by calling ct_send. ct_send writes the symbolic command stream onto the command structure’s parent connection.
Handle the results of command execution by calling ct_results repeatedly until it no longer returns CS_SUCCEED. See “Results” for a discussion of processing results.
An application can call ct_cancel(CS_CANCEL_ALL) to cancel a command that has been initiated but not yet sent. But after an application has sent a command, it must call ct_results before calling ct_cancel to cancel the results of command execution.
ct_send uses an asynchronous write and does not wait for a response from the server. An application must call ct_results to verify the success of the command and to set up the command results for processing.
Most types of commands can be resent immediately after all the results of the previous command have been handled. The exceptions are:
Send-data commands initiated by ct_command(CS_SEND_DATA_CMD).
Send-bulk commands initiated by ct_command(CS_SEND_BULK_CMD)
For all other types of commands, the application can resend the command with ct_send immediately after the application has processed all the results of the previous execution. Client-Library does not discard the initiated command information until the application initiates a new command with ct_command, ct_cursor, ct_dynamic, or ct_sendpassthru.
In general, applications that resend commands should supply command parameters with ct_setparam rather than ct_param.
ct_setparam allows the application to change parameter values before resending the command. ct_setparam accepts pointers to program variables that contain parameter values. The variables’ contents are read by subsequent calls to ct_send. The binding between command parameters and program variables persists until the application initiates a new command with ct_command, ct_cursor, ct_dynamic, or ct_sendpassthru.
ct_param copies data from program variables before it returns. If ct_param is called to supply command parameters, the parameter values cannot be changed when the command is resent.
If a parameter is effectively a literal value (that is, it will not change), then it is appropriate for the application to define the parameter with ct_param even if the command will be resent.
An application can check the CS_HAVE_CMD property to see if a resendable command exists for the command structure. See “Have resendable command” for a description of this property.
Applications which resend commands may be able to use the CS_STICKY_BINDS property to eliminate redundant ct_bind calls. See “Persistent result bindings” for a description of this property.
ct_command, ct_cursor, ct_dynamic, ct_fetch, ct_param, ct_results, ct_setparam