ct_cursor

Description

Initiate a Client-Library cursor command.

Syntax

CS_RETCODE ct_cursor(cmd, type, name, namelen, text,
               textlen, option)
CS_COMMAND      *cmd;
 CS_INT                  type;
 CS_CHAR             *name;
 CS_INT                  namelen;
 CS_CHAR             *text;
 CS_INT                  textlen;
 CS_INT                  option;

Parameters

cmd

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

type

The type of cursor command to initiate. Table 3-14 lists the symbolic values for type.

name

A pointer to the name associated with the cursor command, if any. Table 3-14 indicates which types of commands require names.

namelen

The length, in bytes, of *name. If *name is null-terminated, pass namelen as CS_NULLTERM. If name is NULL pass namelen as CS_UNUSED.

text

A pointer to the text associated with the cursor command. Table 3-14 indicates which commands require text and what that text must be.

textlen

The length, in bytes, of *text. If *text is null-terminated, pass textlen as CS_NULLTERM. If text is NULL, pass textlen as CS_UNUSED.

option

The option associated with this command. Table 3-14 indicates which commands take an option and what that option can be.

Returns

ct_cursor 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 following code excerpt is from the csr_disp.c sample program and describes the functionality of regular cursors:

        /* DoCursor(connection) */
         CS_STATIC CS_RETCODE
         DoCursor(connection)
         CS_CONNECTION  *connection;
        {
             CS_RETCODE       retcode;
             CS_COMMAND       *cmd;
             CS_INT            res_type;
            /* Use the pubs2 database */
             ...CODE DELETED.....
            /*
             ** Allocate a command handle to declare the 
             ** cursor on.
             */
             retcode = ct_cmd_alloc(connection, &cmd)
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_cmd_alloc() failed");
                 return retcode;
             }
            /*
             ** Declare the cursor. SELECT is a select 
             ** statement defined in the header file.
             */
             retcode = ct_cursor(cmd, CS_CURSOR_DECLARE,
                 "cursor_a", CS_NULLTERM, SELECT, CS_NULLTERM,
                 CS_READ_ONLY);
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_cursor(declare)
                     failed");
                     return retcode;
             }
            /* Set cursor rows to 10*/
             retcode = ct_cursor(cmd, CS_CURSOR_ROWS, NULL,
                 CS_UNUSED, NULL, CS_UNUSED, (CS_INT)10);
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_cursor(currows)
                     failed");
                 return retcode;
             }
            /* Open the cursor */
             retcode = ct_cursor(cmd, CS_CURSOR_OPEN, NULL,
                 CS_UNUSED, NULL,     CS_UNUSED, CS_UNUSED);
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_cursor() failed");
                 return retcode;
             }
            /*
             ** Send (batch) the last 3 cursor commands to 
             ** the server 
             */
             retcode = ct_send(cmd)
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_send() failed");
                 return retcode;
             }
            /*
             ** Process the results.  Loop while ct_results() 
             ** returns CS_SUCCEED, and then check ct_result’s 
             ** final return code to see if everything went ok.
             */
             ...CODE DELETED.....
            /*
             ** Close and deallocate the cursor. Note that we 
             ** don’t have to do this, since it is done
             ** automatically when the connection is closed.
             */
             retcode = ct_cursor(cmd, CS_CURSOR_CLOSE, NULL,
                 CS_UNUSED, NULL, CS_UNUSED, CS_DEALLOC);
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_cursor(dealloc)
                     failed");
                 return retcode;
             }
            /* Send the cursor command to the server */
             retcode = ct_send(cmd)
             if (retcode != CS_SUCCEED)
             {
                 ex_error("DoCursor: ct_send() failed");
                 return retcode;
             }
            /*
             ** Check its results.  The command won't generate 
             ** fetchable results.
             */
             ...CODE DELETED.....
            /* Drop the cursor's command structure */
             ...CODE DELETED.....
            return retcode;
         }

Example 2

The following code excerpt is from the csr_disp_scrollcurs.c sample program and describes the functionality of scrollable cursors:

CS_STATIC CS_RETCODE
DoCursor(connection)
CS_CONNECTION	*connection;
{
	CS_RETCODE	retcode;
	CS_COMMAND	*cmd;	
	CS_INT		res_type;
	
        if ((retcode = ex_use_db(connection, Ex_dbname)) != CS_SUCCEED)
        {
                ex_error("DoCursor: ex_use_db(pubs2) failed");
                return retcode;
        }
	
        if ((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED)
        {
                ex_error("DoCursor: ct_cmd_alloc() failed");
                return retcode;
        }
	
	/*
	** Declare an insensitive, scrollable cursor. The same result
	** would be obtained by using CS_SCROLL_INSENSITIVE.
	*/
	retcode = ct_cursor(cmd, CS_CURSOR_DECLARE, "cursor_a", CS_NULLTERM,
			SELECT, CS_NULLTERM, CS_SCROLL_CURSOR);
	
	if (retcode != CS_SUCCEED)
	{
                ex_error("DoCursor: ct_cursor(declare) failed");
		return retcode;
	}
	
	/*
	** This example relies on CS_CURSOR_ROWS set to 1, e.g. fetch a single
	** row at any time for the server. No row buffering here.
	*/	
	retcode = ct_cursor(cmd, CS_CURSOR_ROWS, NULL, CS_UNUSED, NULL, 
			CS_UNUSED, (CS_INT)1);
	if (retcode != CS_SUCCEED)
	{
                ex_error("DoCursor: ct_cursor(currows) failed");
		return retcode;
	}
	
	retcode = ct_cursor(cmd, CS_CURSOR_OPEN, NULL, CS_UNUSED, NULL,
			CS_UNUSED, CS_UNUSED);
	if (retcode != CS_SUCCEED)
	{
                ex_error("DoCursor: ct_cursor() failed");
		return retcode;
	}
	
	if ((retcode = ct_send(cmd)) != CS_SUCCEED)
	{
                ex_error("DoCursor: ct_send() failed");
		return retcode;
	}
	
	while((retcode = ct_results(cmd, &res_type)) == CS_SUCCEED)
	{
		switch ((int)res_type)
		{
		case CS_CMD_SUCCEED:
			break;
	
		case CS_CMD_DONE:
   			break;
	
		case CS_CMD_FAIL:
			ex_error("DoCursor: ct_results() returned CMD_FAIL");
			break;
	
		case CS_CURSOR_RESULT:
			retcode = ex_scroll_fetch_1(cmd);
			if (retcode != CS_SUCCEED)
			{
				if (retcode == CS_SCROLL_CURSOR_ENDS || 
					retcode == CS_CURSOR_BEFORE_FIRST ||
					retcode == CS_CURSOR_AFTER_LAST)
				{
					retcode = CS_SUCCEED;
				}
			}
			else
			{
				ex_error("DoCursor: ex_scroll_fetch_1() failed on CS_CURSOR_RESULT ");
			  	return retcode;
			}
			break;
 
		default:
			ex_error("DoCursor: ct_results() returned unexpected result type");
			return CS_FAIL;
		}
	}
	
	switch ((int)retcode)
	{
		case CS_SUCCEED:
		case CS_END_RESULTS:
			break;
	
		case CS_FAIL:
			ex_error("DoCursor: ct_results() failed");
			return retcode;
	
		default:
			ex_error("DoCursor: ct_results() returned unexpected result code");
			return retcode;
	}
	
	/*
	** cursor close only
	*/
	retcode = ct_cursor(cmd, CS_CURSOR_CLOSE, NULL, CS_UNUSED, NULL,
			CS_UNUSED, CS_UNUSED);
	
	if (retcode != CS_SUCCEED)
	{
               ex_error("DoCursor: ct_cursor(close) failed");
		return retcode;
	}
	
	if ((retcode = ct_send(cmd)) != CS_SUCCEED)
	{
               ex_error("DoCursor: ct_send() for close failed");
		return retcode;
	}
	
	while((retcode = ct_results(cmd, &res_type)) == CS_SUCCEED)
	{
		switch ((int)res_type)
		{
		    case CS_CMD_SUCCEED:
		    case CS_CMD_DONE:
			break;
 
		case CS_CMD_FAIL:
			ex_error("DoCursor: ct_results() close returned CMD_FAIL");
			break;
	
		default:
			ex_error("DoCursor: ct_results() close returned unexpected result type");
			return CS_FAIL;
		}
	}
	
	if (retcode != CS_END_RESULTS)
	{
		ex_error("DoCursor: close ENDRESULTS ct_results() failed");
		return retcode;
	}
	
	/*
	** cursor dealloc only, but this could be combined with the close.
	*/
 	retcode = ct_cursor(cmd, CS_CURSOR_DEALLOC, NULL, CS_UNUSED, NULL,
			CS_UNUSED, CS_UNUSED); 
	
	if (retcode != CS_SUCCEED)
	{
               ex_error("DoCursor: ct_cursor(cursor_dealloc) failed");
		return retcode;
	}
	
	if ((retcode = ct_send(cmd)) != CS_SUCCEED)
	{
               ex_error("DoCursor: ct_send() for dealloc failed");
		return retcode;
	}
	
	while((retcode = ct_results(cmd, &res_type)) == CS_SUCCEED)
	{
		switch ((int)res_type)
		{
		    case CS_CMD_SUCCEED:
		    case CS_CMD_DONE:
			break;
 
		case CS_CMD_FAIL:
			ex_error("DoCursor: ct_results() returned CMD_FAIL");
			break;
		default:
			ex_error("DoCursor: ct_results() returned unexpected result type");
			return CS_FAIL;
		}
	}
	
	if (retcode != CS_END_RESULTS)
	{
		ex_error("DoCursor: cursor_dealloc ENDRESULTS ct_results() failed");
		return retcode;
	}
	
	if ((retcode = ct_cmd_drop(cmd)) != CS_SUCCEED)
	{
                ex_error("DoCompute: ct_cmd_drop() failed");
                return retcode;
	}
	
	return retcode;
}

Usage

Table 3-14: Summary of ct_cursor parameters

Value of type

Command initiated

name value

text value

option value

CS_CURSOR_ DECLARE

A cursor declare command.

A pointer to the cursor name.

A pointer to the SQL text that is the body of the cursor.

CS_UNUSED, or a bitwise OR of the values in Table 3-15.

CS_CURSOR_ OPTION

A cursor set options command.

NULL

NULL

  • CS_FOR_UPDATE to indicate that the cursor is “for update.”

  • CS_READ_ONLY to indicate that the cursor is “read-only.”

  • CS_UNUSED to indicate that the server should decide whether a cursor is updatable.

  • CS_SCROLL_INSENSITIVE to declare a scrollable cursor insensitive.

  • CS_SCROLL_SEMISENSITIVEto declare a scrollable, semi sensitive cursor.

  • CS_SCROLL_CURSOR to declare a scrollable cursor that is insensitive (default).

  • CS_NOSCROLL_INSENSITIVEto declare a cursor insensitive and non-scrollable.

See Specifying updatability on page 373 for more information.

CS_CURSOR_ROWS

A cursor set rows command.

NULL

NULL

An integer representing the number of rows to be returned with a single fetch request.

The default is 1 if not specified in subsequent ct_cursor calls.

For multi-row returns from ct_scroll_fetch, the CS_CURSOR_ROWS value must be greater than 1.

For best performance, set CS_CURSOR_ROWS to the same value as the count field in the ct_bind call.

See “ct_bind” for more information.

CS_CURSOR_OPEN

A cursor open command.

NULL

NULL

  • CS_RESTORE_OPEN restores parameter-binding information for a previously sent cursor-open command. See “Restoring a cursor-open command” for an explanation.

  • CS_UNUSED should be passed the first time a cursor is opened.

CS_CURSOR_ UPDATE

A cursor update command.

A pointer to the name of the table to update.

A pointer to the SQL update statement.

  • CS_UNUSED if *text is the entire update statement.

  • CS_MORE if *text is part of the update statement.

  • CS_END if *text is the last piece of the update statement.

CS_CURSOR_ DELETE

A cursor delete command.

A pointer to the name of the table to delete from.

NULL

CS_UNUSED

CS_CURSOR_ CLOSE

A cursor close command.

NULL

NULL

  • CS_DEALLOC to close and deallocate the cursor.

  • CS_UNUSED to close the cursor without deallocating it.

CS_CURSOR_ DEALLOC

A deallocate cursor command.

NULL

NULL

CS_UNUSED


Sequencing cursor commands


Cursor-declare commands

Option values for ct_cursor(CS_ CURSOR_DECLARE)

Specifying updatability


Dynamic SQL cursor option


Cursor-Rows commands


Using implicit cursors

You can use implicit cursors with Client-Library version 12.5 and later. Implicit cursors function in the same way as read-only cursors during row-fetching, but they use system resources more efficiently.

This example uses read-only cursors:

ct_cursor(cmd, CS_CURSOR_DECLARE, "cursor_a", CS_NULLTERM, SELECT, CS_READ_ONLY)
ct_cursor(cmd, CS_CURSOR_ROWS, NULL, CS_UNUSED, NULL, CS_UNUSED, CS_INT)5)
ct_cursor(cmd, CS_CURSOR_OPEN, NULL, CS_UNUSED, NULL, CS_UNUSED, CS_UNUSED)

This example uses implicit cursors:

ct_cursor(cmd, CS_CURSOR_DECLARE, "cursor_a", CS_NULLTERM, SELECT, CS_IMPLICIT CURSOR)
ct_cursor(cmd, CS_CURSOR_ROWS, NULL, CS_UNUSED, NULL, CS_UNUSED, CS_INT)5)
ct_cursor(cmd, CS_CURSOR_OPEN, NULL, CS_UNUSED, NULL, CS_UNUSED, CS_UNUSED)

To use implicit cursors, you must set cs_ctx_alloc(CS_VERSION_125, context) or ct_init(*context, CS_VERSION_125). You must set CS_CURSOR_ROWS to a minimum value of 2 for single-row fetches, and a higher value if more rows are to be retrieved.

WARNING! You can use implicit cursors only with Client-Library version 12.5 and later. If you use them with an earlier version of Client-Library, they are converted to read-only cursors.


Cursor-open commands


Batching cursor-open commands


Restoring a cursor-open command


Cursor-update commands


Cursor-delete commands


Cursor-close commands

A nested cursor-close command is the preferred way to abandon rows returned from a cursor-open command, since ct_cancel can put a connection’s cursors into an undefined state.


Cursor-deallocate commands

See also

“Commands”, ct_cmd_alloc, ct_keydata, ct_param, ct_results, ct_send, ct_setparam, ct_scroll_fetch.