Send a chunk of text or image data to the server.
CS_RETCODE ct_send_data(cmd, buffer, buflen) CS_COMMAND *cmd; CS_VOID *buffer; CS_INT buflen;
A pointer to the CS_COMMAND structure managing a client/server operation.
A pointer to the value to write to the server.
The length, in bytes, of *buffer.
CS_NULLTERM is not a legal value for buflen.
ct_send_data returns the following values:
Return value |
Meaning |
---|---|
CS_SUCCEED |
The routine completed successfully. |
CS_FAIL |
The routine failed. |
CS_CANCELED |
The send data operation 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”. |
The following fragment illustrates the call sequence to build and send a send-data command:
/*
** UpdateTextData()
*/
CS_STATIC CS_RETCODE
UpdateTextData(connection, textdata, newdata)
CS_CONNECTION connection;
TEXT_DATA textdata;
char *newdata;
{
CS_RETCODE retcode;
CS_INT res_type;
CS_COMMAND *cmd;
CS_INT i;
CS_TEXT *txtptr;
CS_INT txtlen;
/*
** Allocate a command handle to send the text with
*/
...CODE DELETED.....
/*
** Inform Client-Library the next data sent will
** be used for a text or image update.
*/
if ((retcode = ct_command(cmd, CS_SEND_DATA_CMD,
NULL, CS_UNUSED, CS_COLUMN_DATA)) !=
CS_SUCCEED)
{
ex_error("UpdateTextData: ct_command() \
failed");
return retcode;
}
/*
** Fill in the description information for the
** update and send it to Client-Library.
*/
txtptr = (CS_TEXT *)newdata;
txtlen = strlen(newdata);
textdata->iodesc.total_txtlen = txtlen;
textdata->iodesc.log_on_update = CS_TRUE;
retcode = ct_data_info(cmd, CS_SET, CS_UNUSED,
&textdata->iodesc);
if (retcode != CS_SUCCEED)
{
ex_error("UpdateTextData: ct_data_info() \
failed");
return retcode;
}
/*
** Send the text one byte at a time. This is not
** the best thing to do for performance reasons,
** but does demonstrate that ct_send_data()
** can handle arbitrary amounts of data.
*/
for (i = 0; i < txtlen; i++, txtptr++)
{
retcode = ct_send_data(cmd, txtptr,
(CS_INT)1);
if (retcode != CS_SUCCEED)
{
ex_error("UpdateTextData: ct_send_data() \
failed");
return retcode;
}
}
/*
** ct_send_data() writes to internal network
** buffers. To insure that all the data is
** flushed to the server, a ct_send() is done.
*/
if ((retcode = ct_send(cmd)) != CS_SUCCEED)
{
ex_error("UpdateTextData: ct_send() failed");
return retcode;
}
/* Process the results of the command */
while ((retcode = ct_results(cmd, &res_type)) ==
CS_SUCCEED)
{
switch ((int)res_type)
{
case CS_PARAM_RESULT:
/*
** Retrieve a description of the
** parameter data. Only timestamp data is
** expected in this example.
*/
retcode = ProcessTimestamp(cmd, textdata);
if (retcode != CS_SUCCEED)
{
ex_error("UpdateTextData: \
ProcessTimestamp() failed");
/*
** Something failed, so cancel all
** results.
*/
ct_cancel(NULL, cmd, CS_CANCEL_ALL);
return retcode;
}
break;
case CS_CMD_SUCCEED:
case CS_CMD_DONE:
/*
** This means that the command succeeded
** or is finished.
*/
break;
case CS_CMD_FAIL:
/*
** The server encountered an error while
** processing our command.
*/
ex_error("UpdateTextData: ct_results() \
returned CS_CMD_FAIL");
break;
default:
/*
** We got something unexpected.
*/
ex_error("UpdateTextData: ct_results() \
returned unexpected result type”);
/* Cancel all results */
ct_cancel(NULL, cmd, CS_CANCEL_ALL);
break;
}
}
/*
** We're done processing results. Let's check the
** return value of ct_results() to see if
** everything went ok.
*/
...CODE DELETED.....
return retcode;
}
This code excerpt is from the getsend.c sample program.
The following fragment illustrates the call sequence to send partial update data:
/* ** UpdateTextData() */ CS_STATIC CS_RETCODE UpdateTextData(connection, textdata, newdata) CS_CONNECTION connection; TEXT_DATA textdata; char *newdata; { CS_RETCODE retcode; CS_INT res_type; CS_COMMAND *cmd; CS_INT i; CS_TEXT *txtptr; CS_INT txtlen; /* ** Allocate a command handle to send the text with */ ...CODE DELETED..... /* ** Inform Client-Library the next data sent will ** be used for a text or image update. */ if ((retcode = ct_command(cmd, CS_SEND_DATA_CMD, NULL, CS_UNUSED, CS_COLUMN_DATA)) != CS_SUCCEED) { ex_error("UpdateTextData: ct_command() \ failed"); return retcode; } /* ** Fill in the description information for the ** update and send it to Client-Library. */ txtptr = (CS_TEXT *)newdata; txtlen = strlen(newdata); textdata->iodesc.total_txtlen = txtlen; textdata->iodesc.log_on_update = CS_TRUE; /* ** Insert newdata at offset 20. */ textdata->iodesc.iotype = CS_IOPARTIAL; textdata->iodesc.offset = 20; textdata->iodesc.delete_length = 0; retcode = ct_data_info(cmd, CS_SET, CS_UNUSED, &textdata->iodesc); if (retcode != CS_SUCCEED) { ex_error("UpdateTextData: ct_data_info() \ failed"); return retcode; } /* ** Send the text one byte at a time. This is not ** the best thing to do for performance reasons, ** but does demonstrate that ct_send_data() ** can handle arbitrary amounts of data. */ for (i = 0; i < txtlen; i++, txtptr++) { retcode = ct_send_data(cmd, txtptr,(CS_INT)1); if (retcode != CS_SUCCEED) { ex_error("UpdateTextData: ct_send_data() \ failed"); return retcode; } } /* ** ct_send_data() writes to internal network ** buffers. To insure that all the data is ** flushed to the server, a ct_send() is done. */ if ((retcode = ct_send(cmd)) != CS_SUCCEED) { ex_error("UpdateTextData: ct_send() failed"); return retcode; } /* Process the results of the command */ while ((retcode = ct_results(cmd, &res_type)) == CS_SUCCEED) { switch ((int)res_type) { case CS_PARAM_RESULT: /* ** Retrieve a description of the ** parameter data. Only timestamp data is ** expected in this example. */ retcode = ProcessTimestamp(cmd, textdata); if (retcode != CS_SUCCEED) { ex_error("UpdateTextData: \ ProcessTimestamp() failed"); /* ** Something failed, so cancel all ** results. */ ct_cancel(NULL, cmd, CS_CANCEL_ALL); return retcode; } break; case CS_CMD_SUCCEED: case CS_CMD_DONE: /* ** This means that the command succeeded ** or is finished. */ break; case CS_CMD_FAIL: /* ** The server encountered an error while ** processing our command. */ ex_error("UpdateTextData: ct_results() \ returned CS_CMD_FAIL"); break; default: /* ** We got something unexpected. */ ex_error("UpdateTextData: ct_results() \ returned unexpected result type”); /* Cancel all results */ ct_cancel(NULL, cmd, CS_CANCEL_ALL); break; } } /* ** We're done processing results. Let's check the ** return value of ct_results() to see if ** everything went ok. */ ...CODE DELETED..... return retcode; }
This code excerpt is from the uctext.c sample program.
An application can use ct_send_data to write a text or image value to a database column providing the user has update privileges granted for the underlying table, which may be in a different database and not in the view. This writing operation is actually an update; that is, the column must have a value when ct_send_data is called to write a new value.
This is because ct_send_data uses text timestamp information when writing to the column, and a column does not have a valid text timestamp until it contains a value. The value contained in the text or image column can be NULL, but the NULL must be entered explicitly with the SQL update statement.
For information on the steps involved in using ct_send_data to update a text or image column, see “Updating a text or image column”. For information about sending partial updates with ct_send_data, see “Sending partial updates with ct_send_data”.
To perform a send-data operation, an application must have a current I/O descriptor, or CS_IODESC structure, describing the column value that will be updated:
The textptr field of the CS_IODESC identifies the target column.
The timestamp field of the CS_IODESC is the text timestamp of the column value. If timestamp does not match the current database text timestamp for the value, the update operation will fail.
The total_txtlen field of the CS_IODESC indicates the total length, in bytes, of the column’s new value. An application must call ct_send_data in a loop to write exactly this number of bytes before calling ct_send to indicate the end of the text or image update operation.
The log_on_update of the CS_IODESC tells the server whether or not to log the update operation.
The locale field of the CS_IODESC points to a CS_LOCALE structure that contains localization information for the new value, if any.
A typical application will change only the values of the locale, total_txtlen, and log_on_update fields before using an I/O descriptor in an update operation, but an application that is updating the same column value multiple times will need to change the value of the timestamp field as well.
A successful text or image update generates a parameter result set that contains the new text timestamp for the text or image value. If an application plans to update the text or image value a second time, it must save this new text timestamp and copy it into the CS_IODESC for the value before calling ct_data_info to define the CS_IODESC for the update operation.
A text or image update operation is equivalent to a language command containing a Transact-SQL update statement.
The command space identified by cmd must be idle before a text or image update operation is initiated. A command space is idle if there are no active commands, pending results, or open cursors in the space.