Main Page Modules Compound List File List Compound Members File Members Related Pages

# Results processing
[LibTDS API]

Handle tokens in packets. More...

## Functions

int | tds_process_login_tokens (TDSSOCKET *tds)
| tds_process_login_tokens() is called after sending the login packet to the server.
int | tds_process_result_tokens (TDSSOCKET *tds, TDS_INT *result_type, int *done_flags)
| process TDS result-type message streams.
int | tds_process_row_tokens (TDSSOCKET *tds, TDS_INT *rowtype, TDS_INT *computeid)
| process TDS row-type message streams.
int | tds_process_row_tokens_ct (TDSSOCKET *tds, TDS_INT *rowtype, TDS_INT *computeid)
int | tds_process_trailing_tokens (TDSSOCKET *tds)
| tds_process_trailing_tokens() is called to discard messages that may be left unprocessed at the end of a result "batch".
int | tds_process_simple_query (TDSSOCKET *tds)
| Process results for simple query as "SET TEXTSIZE" or "USE dbname" If the statement returns results, beware they are discarded.
int | tds_do_until_done (TDSSOCKET *tds)
| simple flush function.
void | tds_add_row_column_size (TDSRESULTINFO *info, TDSCOLINFO *curcol)
| Add a column size to result info row size and calc offset into row.
int | tds_client_msg (TDSCONTEXT *tds_ctx, TDSSOCKET *tds, int msgnum, int level, int state, int line, const char *message)
| tds_client_msg() sends a message to the client application from the CLI or TDS layer.
int | tds_alloc_get_string (TDSSOCKET *tds, char **string, int len)
| Read a string from wire in a new allocated buffer.
int | tds_process_cancel (TDSSOCKET *tds)
| tds_process_cancel() processes the incoming token stream until it finds an end token (DONE, DONEPROC, DONEINPROC) with the cancel flag set.
void | tds_set_null (unsigned char *current_row, int column)
| set the null bit for the given column in the row buffer
void | tds_clr_null (unsigned char *current_row, int column)
| clear the null bit for the given column in the row buffer
int | tds_get_null (unsigned char *current_row, int column)
| Return the null bit for the given column in the row buffer.
TDSDYNAMIC * | tds_lookup_dynamic (TDSSOCKET *tds, char *id)
| Find a dynamic given string id.
int | tds_get_token_size (int marker)
| tds_get_token_size() returns the size of a fixed length token used by tds_process_cancel() to determine how to read past a token
void | tds_swap_datatype (int coltype, unsigned char *buf)
int | tds5_send_optioncmd (TDSSOCKET *tds, TDS_OPTION_CMD tds_command, TDS_OPTION tds_option, TDS_OPTION_ARG *ptds_argument, TDS_INT *ptds_argsize)
const char * | tds_prtype (int token)

## Detailed Description

Handle tokens in packets.

Many PDU (packets data unit) contain tokens. (like result description, rows, data, errors and many other).

## Function Documentation

void tds_add_row_column_size | ( | TDSRESULTINFO * | info,
|  | TDSCOLINFO * | curcol
| ) |

Add a column size to result info row size and calc offset into row.

Parameters:

  info | result where to add column
  curcol | column to add

int tds_alloc_get_string | ( | TDSSOCKET * | tds,
|  | char ** | string,
|  | int | len
| ) |

Read a string from wire in a new allocated buffer.

Parameters:

  len | length of string to read

int tds_client_msg | ( | TDSCONTEXT * | tds_ctx,
|  | TDSSOCKET * | tds,
|  | int | msgnum,
|  | int | level,
|  | int | state,
|  | int | line,
|  | const char * | message
| ) |

tds_client_msg() sends a message to the client application from the CLI or TDS layer.

A client message is one that is generated from with the library and not from the server. The message is sent to the CLI (the err_handler) so that it may forward it to the client application or discard it if no msg handler has been by the application. tds->parent contains a void pointer to the parent of the tds socket. This can be cast back into DBPROCESS or CS_CONNECTION by the CLI and used to determine the proper recipient function for this message.

Todo:
  This procedure is deprecated, because the client libraries use differing messages and message numbers. The general approach is to emit ct-lib error information and let db-lib and ODBC map that to their number and text.

int tds_do_until_done | ( | TDSSOCKET * | tds | ) |

| simple flush function. maybe be superseded soon.

TDSDYNAMIC* tds_lookup_dynamic | ( | TDSSOCKET * | tds,
|  | char * | id
| ) |

Find a dynamic given string id.

Returns:
  dynamic or NULL is not found

Parameters:

  id | dynamic id to search

int tds_process_cancel | ( | TDSSOCKET * | tds | ) |

| tds_process_cancel() processes the incoming token stream until it finds an end token (DONE, DONEPROC, DONEINPROC) with the cancel flag set. a that point the connetion should be ready to handle a new query.

int tds_process_login_tokens | ( | TDSSOCKET * | tds | ) |

| tds_process_login_tokens() is called after sending the login packet to the server. It returns the success or failure of the login dependent on the protocol version. 4.2 sends an ACK token only when successful, TDS 5.0 sends it always with a success byte within

int tds_process_result_tokens | ( | TDSSOCKET * | tds,
|  | TDS_INT * | result_type,
|  | int * | done_flags
| ) |

process TDS result-type message streams.

tds_process_result_tokens() is called after submitting a query with tds_submit_query() and is responsible for calling the routines to populate tds->res_info if appropriate (some query have no result sets)

Parameters:

  tds | A pointer to the TDSSOCKET structure managing a client/server operation.
  result_type | A pointer to an integer variable which tds_process_result_tokens sets to indicate the current type of result.

  Values that indicate command status

  TDS_DONE_RESULT | The results of a command have been completely processed. This command return no rows.
  TDS_DONEPROC_RESULT | The results of a command have been completely processed. This command return rows.
  TDS_DONEINPROC_RESULT | The results of a command have been completely processed. This command return rows.

  Values that indicate results information is available

  TDS_ROWFMT_RESULT | Regular Data format information | tds->res_info now contains the result details ; tds->curr_resinfo now points to that data
  TDS_COMPUTEFMT_ RESULT | Compute data format information | tds->comp_info now contains the result data; tds->curr_resinfo now points to that data
  TDS_DESCRIBE_RESULT |  |

  Values that indicate data is available

  Value | Meaning | Information returned
  TDS_ROW_RESULT | Regular row results | 1 or more rows of regular data can now be retrieved
  TDS_COMPUTE_RESULT | Compute row results | A single row of compute data can now be retrieved
  TDS_PARAM_RESULT | Return parameter results | param_info or cur_dyn->params contain returned parameters
  TDS_STATUS_RESULT | Stored procedure status results | tds->ret_status contain the returned code

Todo:
  Complete TDS_DESCRIBE_RESULT description

Return values:

  TDS_SUCCEED | if a result set is available for processing.
  TDS_NO_MORE_RESULTS | if all results have been completely processed.

Examples
  The following code is cut from ct_results(), the ct-library function

      done = 0;

          /* see what "result" tokens we have. a "result" in ct-lib terms also  */
          /* includes row data. Some result types always get reported back  to  */
          /* the calling program, others are only reported back if the relevant */
          /* config flag is set.                                                */

      while (!done) {

              tdsret = tds_process_result_tokens(tds, &res_type, NULL);

              switch (tdsret) {

              case TDS_SUCCEED:

                      cmd->curr_result_type = res_type;

                      switch (res_type) {
                      case TDS_COMPUTEFMT_RESULT:
                      case TDS_ROWFMT_RESULT:
                              if (context->config.cs_expose_formats) {
                                      done = 1;
                                      retcode = CS_SUCCEED;
                                      *result_type = res_type;
                              }
                              break;

                      case TDS_COMPUTE_RESULT:
                              /* we've hit a compute data row. We have to get hold of this */
                              /* data now, as it's necessary  to tie this data back to its */
                              /* result format...the user may call ct_res_info() & friends */
                              /* after getting back a compute "result".                    */

                              tdsret = tds_process_row_tokens(tds, &rowtype, &computeid);

                              if (tdsret == TDS_SUCCEED) {
                                      if (rowtype == TDS_COMP_ROW) {
                                              cmd->row_prefetched = 1;
                                              retcode = CS_SUCCEED;
                                      } else {
                                              /* this couldn't really happen, but... */
                                              retcode = CS_FAIL;
                                      }
                              } else
                                      retcode = CS_FAIL;
                              done = 1;
                              *result_type = res_type;
                              break;

                      case TDS_DONE_RESULT:
                      case TDS_DONEPROC_RESULT:
                      case TDS_DONEINPROC_RESULT:

                              /* there's a distinction in ct-library     */
                              /* depending on whether a command returned */
                              /* results or not...                          */

                              if (tds->res_info)
                                      *result_type = CS_CMD_DONE;
                              else
                                      *result_type = CS_CMD_SUCCEED;

                              retcode = CS_SUCCEED;
                              done = 1;
                              break;

                      default:
                              retcode = CS_SUCCEED;
                              *result_type = res_type;
                              done = 1;
                              break;
                      }
                      break;

              case TDS_NO_MORE_RESULTS:
                      done = 1;
                      retcode = CS_END_RESULTS;
                      break;
              case TDS_FAIL:
                      done = 1;
                      retcode = CS_FAIL;
                      break;
              }
      }

int tds_process_row_tokens | ( | TDSSOCKET * | tds,
|  | TDS_INT * | rowtype,
|  | TDS_INT * | computeid
| ) |

process TDS row-type message streams.

tds_process_row_tokens() is called once a result set has been obtained with tds_process_result_tokens(). It calls tds_process_row() to copy data into the row buffer.

Parameters:

  tds | A pointer to the TDSSOCKET structure managing a client/server operation.
  rowtype | A pointer to an integer variable which tds_process_row_tokens sets to indicate the current type of row
  computeid | A pointer to an integer variable which tds_process_row_tokens sets to identify the compute_id of the row being returned. A compute row is a row that is generated by a compute clause. The compute_id matches the number of the compute row that was read; the first compute row is 1, the second is 2, and so forth.

Possible values of *rowtype
  - `TDS_REG_ROW` A regular data row
  - `TDS_COMP_ROW` A row of compute data
  - `TDS_NO_MORE_ROWS` There are no more rows of data in this result set

Return values:

  TDS_SUCCEED | A row of data is available for processing.
  TDS_NO_MORE_ROWS | All rows have been completely processed.
  TDS_FAIL | An unexpected error occurred

Examples
  The following code is cut from dbnextrow(), the db-library function

      if ((ret = tds_process_row_tokens(dbproc->tds_socket, &rowtype, &computeid))
          == TDS_SUCCEED) {
              if (rowtype == TDS_REG_ROW) {
                      /* Add the row to the row buffer */
                      resinfo = tds->curr_resinfo;
                      buffer_add_row(&(dbproc->row_buf), resinfo->current_row,
                                              resinfo->row_size);
                      result = REG_ROW;
              } else if (rowtype == TDS_COMP_ROW) {
                      /* Add the row to the row buffer */
                      resinfo = tds->curr_resinfo;
                      buffer_add_row(&(dbproc->row_buf), resinfo->current_row,
                                              resinfo->row_size);
                      result = computeid;
              } else
                      result = FAIL;
      } else if (ret == TDS_NO_MORE_ROWS) {
              result = NO_MORE_ROWS;
      } else
              result = FAIL;

int tds_process_simple_query | ( | TDSSOCKET * | tds | ) |

Process results for simple query as "SET TEXTSIZE" or "USE dbname" If the statement returns results, beware they are discarded.

This function was written to avoid direct calls to tds_process_default_tokens (which caused problems such as ignoring query errors). Results are read until idle state or severe failure (do not stop for statement failure).

Returns:
  see tds_process_result_tokens for results (TDS_NO_MORE_RESULTS is never returned)

int tds_process_trailing_tokens | ( | TDSSOCKET * | tds | ) |

tds_process_trailing_tokens() is called to discard messages that may be left unprocessed at the end of a result "batch".

In dblibrary, it is valid to process all the data rows that a command may have returned but to leave end tokens etc. unprocessed (at least explicitly) This function is called to discard such tokens. If it comes across a token that does not fall into the category of valid "trailing" tokens, it will return TDS_FAIL, allowing the calling dblibrary function to return a "results pending" message. The valid "trailing" tokens are :

TDS_DONE_TOKEN TDS_DONEPROC_TOKEN TDS_DONEINPROC_TOKEN TDS_RETURNSTATUS_TOKEN TDS_PARAM_TOKEN TDS5_PARAMFMT_TOKEN TDS5_PARAMS_TOKEN