ct_setparam

Description

Specify source variables from which ct_send reads input parameter values for a server command.

Syntax

CS_RETCODE ct_setparam(cmd, datafmt, data, 
             datalenp, indp)
 
CS_COMMAND *cmd;
CS_DATAFMT    *datafmt;
CS_VOID            *data;
CS_INT               *datalenp;
CS_SMALLINT    *indp;

Parameters

cmd

A pointer to the CS_COMMAND structure managing a client/server operation.

datafmt

A pointer to a CS_DATAFMT structure that describes the parameter. ct_setparam copies the contents of *datafmt before returning. Client-Library does not reference datafmt afterwards.

data

The address of a value buffer. Client-Library reads the parameter’s current value from *data during subsequent calls to ct_send.

There are three ways to indicate a parameter with a null value:

  • Set * indp as -1 before calling ct_send. In this case, ct_send ignores *data and .

  • Set *datalenp to 0 before calling ct_send.

  • Call ct_setparam with data, datalenp, and indp as NULL.

datalenp

The address of an integer variable that specifies the length, in bytes, of parameter values in *data, or NULL if values for this parameter do not vary in length.

If datalenp is not NULL, subsequent ct_send calls read the current value’s length from *datalenp. A length of 0 indicates a null value.

If datalenp is NULL and data is not, datafmt−>maxlength specifies the length of all non-null values for this parameter. When datalenp is NULL, an indicator variable must be used to indicate null parameter values for subsequent calls to ct_send.

indp

The address of a CS_SMALLINT variable whose value indicates whether the parameter’s current value is NULL. To indicate a parameter with a null value, set *indp as -1. If *indp is -1, ct_send ignores *data and *datalenp.

Returns

ct_setparam returns the following values:

Return value

Meaning

CS_SUCCEED

The routine completed successfully.

CS_FAIL

The routine failed.

CS_BUSY

An asynchronous operation is already pending for this connection. See “Asynchronous programming”.

Examples

Example 1

The example below shows ct_setparam being used in code that declares, opens, and reopens a cursor that takes parameters.

Example: ct_setparam for reopening a cursor

/*
 ** Data structures to describe a parameter and a cursor.
 */
 typedef struct _langparam
 {
         CS_CHAR         *name;
         CS_INT          type;
         CS_INT          len;
         CS_INT          maxlen;
         CS_VOID         *data;
         CS_SMALLINT     indicator;
 } LANGPARAM;
typedef struct _cur_control
 {
         CS_CHAR         *name;
         CS_CHAR         *query;
         LANGPARAM       *params;
         CS_INT          numparams;
 } CUR_CONTROL; 
/*
 ** Static data for a parameterized cursor body.
 */
 CS_STATIC CS_MONEY  PriceVal;
 CS_STATIC CS_INT    SalesVal;
 CS_STATIC LANGPARAM Params [] =
 {
         { "@price_val", CS_MONEY_TYPE,
            CS_SIZEOF(CS_MONEY), CS_SIZEOF(CS_MONEY), 
            (CS_VOID *)&PriceVal, 0
         },
         { "@sales_val", CS_INT_TYPE,
            CS_SIZEOF(CS_INT), CS_SIZEOF(CS_INT), 
            (CS_VOID *)&SalesVal, 0
         },
 };
 #define NUMPARAMS  (CS_SIZEOF(Params) / CS_SIZEOF(LANGPARAM))
  
 #define QUERY \
 "select title_id, title, price, total_sales from titles \
  where price > @price_val and total_sales > @sales_val \
  for read only"
  
 CS_STATIC CUR_CONTROL Cursor_Control =
 { "curly", QUERY, Params, NUMPARAMS };
/*
 ** OpenCursor() -- Declare and open a new cursor or reopen
 **         an existing cursor (which must have been originally
 **         declared and opened using this function).
 **
 **         If the open is successful, this function processes the cursor
 **         results up to the CS_CURSOR_RESULT result type value. In 
 **         other words, the command handle is ready for
 **         ct_bind/ct_fetch/etc.
 **
 ** Parameters
 **   cmd -- CS_COMMAND handle for the new cursor.
 **   cur_control -- address of a CUR_CONTROL structure that contains
 **     the cursor body statement plus parameter formats and value
 **     areas.
 **
 **     If a first-time open is successful, OpenCursor() can be used to
 **     reopen the cursor with new parameter values.
 **
 **     For later opens, the cursor must be closed.
 **
 ** Returns
 **   CS_SUCCEED or CS_FAIL
 */
CS_RETCODE
 OpenCursor(cmd, cur_control)
 CS_COMMAND         *cmd;
 CUR_CONTROL        *cur_control;
 {
   CS_RETCODE          ret;
   CS_INT              i;
   CS_DATAFMT          dfmt;
   LANGPARAM          *params;
   CS_BOOL             have_restorable_cursor;
  /*
   ** Check whether a cursor-open command can be restored with this 
   ** command handle.
   */
   ret = ct_cmd_props(cmd, CS_GET, CS_HAVE_CUROPEN,
                      &have_restorable_cursor, CS_UNUSED,
                      (CS_INT *)NULL);
   if (ret != CS_SUCCEED)
   {
     ex_error(“OpenCursor: ct_cmd_props() failed!”);
     return CS_FAIL;
   }
  /*
   ** If CS_HAVE_CUROPEN is CS_FALSE, then this is a first-time open. So,
   ** we initiate a new declare command and bind to the parameter source
   ** variables in the CUR_CONTROL structure.
   */
   if (have_restorable_cursor != CS_TRUE)
   {
    /*
     ** Initiate the declare command.
     */
     ret = ct_cursor(cmd, CS_CURSOR_DECLARE,
                     cur_control->name, CS_NULLTERM,
                     cur_control->query, CS_NULLTERM,
                     CS_UNUSED);
     if (ret != CS_SUCCEED)
     {
       ex_error(“OpenCursor: Initiate-declare failed”);
       return CS_FAIL;
     }
    /*
     ** Specify formats for the host language parameters in the cursor
     ** declare command.
     */
     params = cur_control->params;
     (CS_VOID *)memset(&dfmt, 0, sizeof(dfmt));
     dfmt.status = CS_INPUTVALUE;
    for (i = 0; i < cur_control->numparams; i++)
     {
       dfmt.datatype = params[i].type;
       dfmt.maxlength = params[i].maxlen;
       strcpy(dfmt.name, params[i].name);
       dfmt.namelen = strlen(dfmt.name);
      ret = ct_setparam(cmd, &dfmt,
                         (CS_VOID *)NULL, (CS_INT *)NULL,
                         (CS_SMALLINT *)NULL);
       if (ret != CS_SUCCEED)
       {
         ex_error(“OpenCursor: ct_setparam() failed”);
         return CS_FAIL;
       }
     }
   }
  /*
   ** Initiate or restore the cursor-open command.
   ** 
   ** The first time we open the cursor, this call initiates an 
   ** open-cursor command which gets batched with the declare command. 
   ** Since there is no cursor to restore, ct_cursor ignores the
   ** CS_RESTORE_OPEN option.
   ** 
   ** The second (and later) times we open the cursor, this call 
   ** restores the cursor-open command so that we can send it again.
   ** The declare-cursor command (originally batched with the open 
   ** command) is not restored.
   */
   ret = ct_cursor(cmd, CS_CURSOR_OPEN,
                   (CS_CHAR *)NULL, CS_UNUSED,
                   (CS_CHAR *)NULL, CS_UNUSED,
                   CS_RESTORE_OPEN);
   if (ret != CS_SUCCEED)
   {
     ex_error(“OpenCursor: Initiate-open failed.”);
     return CS_FAIL;
   }
  /*
   ** For the first-time open, supply the address of variables that have
   ** values for the cursor parameters. These variables will be read by
   ** ct_send.
   ** 
   ** The second (and later) times we open the cursor, we don’t have to
   ** call ct_setparam here -- the parameter bindings were restored by
   ** ct_cursor(OPEN, RESTORE_OPEN).
   ** 
   ** In either case, we assume that our caller has already set the 
   ** desired values, lengths, and indicators.
   */
   for (i = 0;
        ((have_restorable_cursor != CS_TRUE) &&
         (i < cur_control->numparams));
        i++)
   {
     dfmt.datatype = params[i].type;
     dfmt.maxlength = params[i].maxlen;
     strcpy(dfmt.name, params[i].name);
     dfmt.namelen = strlen(dfmt.name);
    ret = ct_setparam(cmd, &dfmt,
                       params[i].data, &params[i].len,
                       &params[i].indicator);
     if (ret != CS_SUCCEED)
     {
       ex_error(“OpenCursor: ct_setparam() failed”);
       return CS_FAIL;
     }
   }
  /*
   ** Send the command batch.
   */
   ret = ct_send(cmd);
   if (ret != CS_SUCCEED)
   {
     ex_error(“OpenCursor: ct_send() failed.”);
     return CS_FAIL;
   }
  /*
   ** GetToCursorRows() calls ct_results() until cursor rows are 
   ** fetchable on the command structure. GetToCursorRows() fails if 
   ** the declare or open command fails on the server.
   */
   ret = GetToCursorRows(cmd);
   if (ret != CS_SUCCEED)
   {
     ex_error(“OpenCursor: Cursor could not be opened.”);
     return CS_FAIL;
   }
  return CS_SUCCEED;
 } /* OpenCursor() */
/*
 ** GetToCursorRows() -- Flush results from a cursor-open command
 **   batch until ct_results returns a CS_CURSOR_RESULT result type.
 **
 ** Parameters
 **   cmd -- The command handle to read results from.
 **
 ** Returns
 **   CS_SUCCEED -- Cursor rows are ready to be fetched.
 **   CS_FAIL -- Failure. Could be due to any of the following:
 **     - No cursor results in the results stream.
 **     - Other kinds of fetchable results in the results stream.
 **     - ct_results failure.
 */
CS_STATIC CS_RETCODE
 GetToCursorRows(cmd)
 CS_COMMAND         *cmd;
 {
   CS_RETCODE          results_ret;
   CS_RETCODE          ret;
   CS_INT              result_type = CS_END_RESULTS;
   CS_BOOL             failing = CS_FALSE;
   CS_INT              intval;
   CS_CHAR             scratch[512];
  while (((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED)
          && (result_type != CS_CURSOR_RESULT))
   {
     switch ((int)result_type)
     {
     case CS_CMD_SUCCEED:
     case CS_CMD_DONE:
       break;
    case CS_CMD_FAIL:
       /*
       ** Declare or open failed on the server.
       */
       ret = ct_res_info(cmd, CS_CMD_NUMBER, (CS_VOID *)&intval,
                         CS_UNUSED, (CS_INT *)NULL);
       if (ret == CS_SUCCEED)
       {
         sprintf(scratch, “Command %ld failed”, (long)intval);
         ex_error(scratch);
       }
       failing = CS_TRUE;
       break;
    default:
       /*
       ** Nothing else is expected. Just return fail and let the caller
       ** decide how to clean up.
       */
       ex_error(
          “Unexpected result types received for cursor declare/open.”);
       return CS_FAIL;
   }
   }
  /*
   ** We are leaving the cursor results pending on the connection.
   */
   if (results_ret == CS_CANCELED)
   {
    /*
     ** Could happen if the connection has a timeout and the error 
     ** handler did ct_cancel(CS_CANCEL_ATTN);
     */
     ex_error(“Cursor declare/open was canceled.”);
     failing = CS_TRUE;
   }
   else if (results_ret != CS_SUCCEED)
   {
     ex_error(“Cursor declare/open: ct_results failed.”);
     failing = CS_TRUE;
   }
  return (failing == CS_TRUE) ? CS_FAIL : CS_SUCCEED;
 } /* GetToCursorRows() */

Usage


Using ct_setparam to define input parameter sources


Using ct_setparam to define cursor parameter formats


Using ct_setparam to identify updatable cursor columns

See also

ct_command, ct_cursor, ct_dynamic, ct_param, ct_send