00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #if HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025 #include <stdio.h>
00026 #include <assert.h>
00027
00028 #if HAVE_STDLIB_H
00029 #include <stdlib.h>
00030 #endif
00031
00032 #if HAVE_STRING_H
00033 #include <string.h>
00034 #endif
00035
00036 #include "ctpublic.h"
00037 #include "ctlib.h"
00038 #include "tdsstring.h"
00039 #include "replacements.h"
00040
00041 TDS_RCSID(var, "$Id: ct.c 177293 2009-11-30 13:36:02Z ivanovp $");
00042
00043
00044 static char * ct_describe_cmd_state(CS_INT state);
00045
00046
00047
00048
00049 static int _ct_fetch_cursor(CS_COMMAND * cmd, CS_INT type, CS_INT offset, CS_INT option, CS_INT * rows_read);
00050 int _ct_get_client_type(CS_CONTEXT *ctx, int datatype, int usertype, int size);
00051 static int _ct_fetchable_results(CS_COMMAND * cmd);
00052 static int _ct_process_return_status(TDSSOCKET * tds);
00053
00054 static int _ct_fill_param(CS_INT cmd_type, CS_PARAM * param, CS_DATAFMT * datafmt, CS_VOID * data,
00055 CS_INT * datalen, CS_SMALLINT * indicator, CS_BYTE byvalue);
00056 void _ctclient_msg(CS_CONNECTION * con, const char *funcname, int layer, int origin, int severity, int number,
00057 const char *fmt, ...);
00058 int _ct_bind_data(CS_CONTEXT *ctx, TDSRESULTINFO * resinfo, TDSRESULTINFO *bindinfo, CS_INT offset);
00059 static void _ct_initialise_cmd(CS_COMMAND *cmd);
00060 static CS_RETCODE _ct_cancel_cleanup(CS_COMMAND * cmd);
00061 static CS_RETCODE _ct_cmd_drop(CS_COMMAND * cmd, CS_INT free_conn_ref);
00062
00063
00064
00065
00066 static CS_INT ct_diag_storeclientmsg(CS_CONTEXT * context, CS_CONNECTION * conn, CS_CLIENTMSG * message);
00067 static CS_INT ct_diag_storeservermsg(CS_CONTEXT * context, CS_CONNECTION * conn, CS_SERVERMSG * message);
00068 static CS_INT ct_diag_countmsg(CS_CONTEXT * context, CS_INT type, CS_INT * count);
00069 static CS_INT ct_diag_getclientmsg(CS_CONTEXT * context, CS_INT idx, CS_CLIENTMSG * message);
00070 static CS_INT ct_diag_getservermsg(CS_CONTEXT * context, CS_INT idx, CS_SERVERMSG * message);
00071
00072
00073
00074
00075
00076
00077 static void rpc_clear(CSREMOTE_PROC * rpc);
00078 static void param_clear(CSREMOTE_PROC_PARAM * pparam);
00079
00080 static TDSPARAMINFO *paraminfoalloc(TDSSOCKET * tds, CS_PARAM * first_param);
00081
00082 static CS_DYNAMIC * _ct_allocate_dynamic(CS_CONNECTION * con, char *id, int idlen);
00083 static CS_INT _ct_deallocate_dynamic(CS_CONNECTION * con, CS_DYNAMIC *dyn);
00084 static CS_DYNAMIC * _ct_locate_dynamic(CS_CONNECTION * con, char *id, int idlen);
00085
00086
00087
00088 void _csclient_msg(CS_CONTEXT * ctx, const char *funcname, int layer, int origin, int severity, int number, const char *fmt, ...);
00089
00090
00091 static const char *
00092 _ct_get_layer(int layer)
00093 {
00094 switch (layer) {
00095 case 1:
00096 return "user api layer";
00097 break;
00098 case 2:
00099 return "blk layer";
00100 break;
00101 default:
00102 break;
00103 }
00104 return "unrecognized layer";
00105 }
00106
00107 static const char *
00108 _ct_get_origin(int origin)
00109 {
00110 switch (origin) {
00111 case 1:
00112 return "external error";
00113 break;
00114 case 2:
00115 return "internal CT-Library error";
00116 break;
00117 case 4:
00118 return "common library error";
00119 break;
00120 case 5:
00121 return "intl library error";
00122 break;
00123 case 6:
00124 return "user error";
00125 break;
00126 case 7:
00127 return "internal BLK-Library error";
00128 break;
00129 default:
00130 break;
00131 }
00132 return "unrecognized origin";
00133 }
00134
00135 static const char *
00136 _ct_get_user_api_layer_error(int error)
00137 {
00138 switch (error) {
00139 case 137:
00140 return "A bind count of %1! is not consistent with the count supplied for existing binds. The current bind count is %2!.";
00141 break;
00142 case 138:
00143 return "Use direction CS_BLK_IN or CS_BLK_OUT for a bulk copy operation.";
00144 break;
00145 case 139:
00146 return "The parameter tblname cannot be NULL.";
00147 break;
00148 case 140:
00149 return "Failed when processing results from server.";
00150 break;
00151 case 141:
00152 return "Parameter %1! has an illegal value of %2!";
00153 break;
00154 case 142:
00155 return "No value or default value available and NULL not allowed. col = %1! row = %2! .";
00156 break;
00157 case 143:
00158 return "parameter name(s) must be supplied for LANGUAGE command.";
00159 break;
00160 case 16843163:
00161 return "This routine cannot be called when the command structure is idle.";
00162 break;
00163 case 16843164:
00164 return "Cannot send anything else but Text/Image for column %1! when server datatype is Text/Image";
00165 break;
00166 default:
00167 break;
00168 }
00169 return "unrecognized error";
00170 }
00171
00172 static char *
00173 _ct_get_msgstr(const char *funcname, int layer, int origin, int severity, int number)
00174 {
00175 char *m;
00176
00177 if (asprintf(&m,
00178 "%s: %s: %s: %s", funcname, _ct_get_layer(layer), _ct_get_origin(origin), _ct_get_user_api_layer_error(number)
00179 ) < 0) {
00180 return NULL;
00181 }
00182 return m;
00183 }
00184
00185 void
00186 _ctclient_msg(CS_CONNECTION * con, const char *funcname, int layer, int origin, int severity, int number, const char *fmt, ...)
00187 {
00188 CS_CONTEXT *ctx = con->ctx;
00189 va_list ap;
00190 CS_CLIENTMSG cm;
00191 char *msgstr;
00192
00193 va_start(ap, fmt);
00194
00195 if (ctx->_clientmsg_cb) {
00196 cm.severity = severity;
00197 cm.msgnumber = (((layer << 24) & 0xFF000000)
00198 | ((origin << 16) & 0x00FF0000)
00199 | ((severity << 8) & 0x0000FF00)
00200 | ((number) & 0x000000FF));
00201 msgstr = _ct_get_msgstr(funcname, layer, origin, severity, number);
00202 tds_vstrbuild(cm.msgstring, CS_MAX_MSG, &(cm.msgstringlen), msgstr, CS_NULLTERM, fmt, CS_NULLTERM, ap);
00203 cm.msgstring[cm.msgstringlen] = '\0';
00204 free(msgstr);
00205 cm.osnumber = 0;
00206 cm.osstring[0] = '\0';
00207 cm.osstringlen = 0;
00208 cm.status = 0;
00209
00210 cm.sqlstatelen = 0;
00211 ctx->_clientmsg_cb(ctx, con, &cm);
00212 }
00213
00214 va_end(ap);
00215 }
00216
00217 static CS_RETCODE
00218 ct_set_command_state(CS_COMMAND *cmd, CS_INT state) {
00219
00220 tdsdump_log(TDS_DBG_FUNC, "setting command state from %s to %s\n",
00221 ct_describe_cmd_state(cmd->command_state),
00222 ct_describe_cmd_state(state));
00223
00224 cmd->command_state = state;
00225
00226 return CS_SUCCEED;
00227 }
00228
00229 static char *
00230 ct_describe_cmd_state(CS_INT state) {
00231 switch (state) {
00232 case _CS_COMMAND_IDLE:
00233 return "IDLE";
00234 case _CS_COMMAND_BUILDING:
00235 return "BUILDING";
00236 case _CS_COMMAND_READY:
00237 return "READY";
00238 case _CS_COMMAND_SENT:
00239 return "SENT";
00240 }
00241 return "???";
00242 }
00243
00244 CS_RETCODE
00245 ct_exit(CS_CONTEXT * ctx, CS_INT unused)
00246 {
00247 tdsdump_log(TDS_DBG_FUNC, "ct_exit()\n");
00248 return CS_SUCCEED;
00249 }
00250
00251 CS_RETCODE
00252 ct_init(CS_CONTEXT * ctx, CS_INT version)
00253 {
00254
00255
00256 tdsdump_log(TDS_DBG_FUNC, "ct_init()\n");
00257 ctx->tds_ctx->msg_handler = _ct_handle_server_message;
00258 ctx->tds_ctx->err_handler = _ct_handle_client_message;
00259
00260 return CS_SUCCEED;
00261 }
00262
00263 CS_RETCODE
00264 ct_con_alloc(CS_CONTEXT * ctx, CS_CONNECTION ** con)
00265 {
00266 TDSLOGIN *login;
00267
00268 tdsdump_log(TDS_DBG_FUNC, "ct_con_alloc()\n");
00269 login = tds_alloc_login();
00270 if (!login)
00271 return CS_FAIL;
00272 *con = (CS_CONNECTION *) malloc(sizeof(CS_CONNECTION));
00273 if (!*con) {
00274 tds_free_login(login);
00275 return CS_FAIL;
00276 }
00277 memset(*con, '\0', sizeof(CS_CONNECTION));
00278 (*con)->tds_login = login;
00279
00280
00281 (*con)->ctx = ctx;
00282
00283
00284 tds_set_library((*con)->tds_login, "CT-Library");
00285
00286
00287 return CS_SUCCEED;
00288 }
00289
00290 CS_RETCODE
00291 ct_callback(CS_CONTEXT * ctx, CS_CONNECTION * con, CS_INT action, CS_INT type, CS_VOID * func)
00292 {
00293 int (*funcptr) (void *, void *, void *) = (int (*)(void *, void *, void *)) func;
00294
00295 tdsdump_log(TDS_DBG_FUNC, "ct_callback() action = %s\n", CS_GET ? "CS_GET" : "CS_SET");
00296
00297 if (!ctx && !con)
00298 return CS_FAIL;
00299
00300 if (action == CS_GET) {
00301 switch (type) {
00302 case CS_CLIENTMSG_CB:
00303 *(void **) func = (CS_VOID *) (con ? con->_clientmsg_cb : ctx->_clientmsg_cb);
00304 return CS_SUCCEED;
00305 case CS_SERVERMSG_CB:
00306 *(void **) func = (CS_VOID *) (con ? con->_servermsg_cb : ctx->_servermsg_cb);
00307 return CS_SUCCEED;
00308 default:
00309 _csclient_msg(ctx, "ct_callback", 2, 1, 16, 27, "%d", type);
00310 *(void **) func = NULL;
00311 return CS_SUCCEED;
00312 }
00313 }
00314
00315 switch (type) {
00316 case CS_CLIENTMSG_CB:
00317 if (con)
00318 con->_clientmsg_cb = (CS_CLIENTMSG_FUNC) funcptr;
00319 else
00320 ctx->_clientmsg_cb = (CS_CLIENTMSG_FUNC) funcptr;
00321 break;
00322 case CS_SERVERMSG_CB:
00323 if (con)
00324 con->_servermsg_cb = (CS_SERVERMSG_FUNC) funcptr;
00325 else
00326 ctx->_servermsg_cb = (CS_SERVERMSG_FUNC) funcptr;
00327 break;
00328 }
00329 return CS_SUCCEED;
00330 }
00331
00332 CS_RETCODE
00333 ct_con_props(CS_CONNECTION * con, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * out_len)
00334 {
00335 CS_INT intval = 0, maxcp;
00336 TDSSOCKET *tds;
00337 TDSLOGIN *tds_login;
00338 char *set_buffer = NULL;
00339
00340 tdsdump_log(TDS_DBG_FUNC, "ct_con_props() action = %s property = %d\n", CS_GET ? "CS_GET" : "CS_SET", property);
00341
00342 tds = con->tds_socket;
00343 tds_login = con->tds_login;
00344
00345 if (action == CS_SET) {
00346 if (property == CS_USERNAME || property == CS_PASSWORD || property == CS_APPNAME ||
00347 property == CS_HOSTNAME || property == CS_SERVERADDR) {
00348 if (buflen == CS_NULLTERM) {
00349 maxcp = strlen((char *) buffer);
00350 set_buffer = (char *) malloc(maxcp + 1);
00351 strcpy(set_buffer, (char *) buffer);
00352 } else if (buflen == CS_UNUSED) {
00353 return CS_SUCCEED;
00354 } else {
00355 set_buffer = (char *) malloc(buflen + 1);
00356 strncpy(set_buffer, (char *) buffer, buflen);
00357 set_buffer[buflen] = '\0';
00358 }
00359 }
00360
00361
00362
00363
00364
00365
00366 switch (property) {
00367 case CS_USERNAME:
00368 tds_set_user(tds_login, set_buffer);
00369 break;
00370 case CS_PASSWORD:
00371 tds_set_passwd(tds_login, set_buffer);
00372 break;
00373 case CS_APPNAME:
00374 tds_set_app(tds_login, set_buffer);
00375 break;
00376 case CS_HOSTNAME:
00377 tds_set_host(tds_login, set_buffer);
00378 break;
00379 case CS_PORT:
00380 tds_set_port(tds_login, *((int *) buffer));
00381 break;
00382 case CS_SERVERADDR: {
00383
00384 char *host, *port;
00385 int portno;
00386 host= strtok(set_buffer, " ");
00387 port= strtok(NULL, " ");
00388 if (!host || !port)
00389 return CS_FAIL;
00390
00391 portno= (int)strtol(port, NULL, 10);
00392 tds_set_server_addr(tds_login, host);
00393 tds_set_port(tds_login, portno);
00394 break;
00395 }
00396 case CS_LOC_PROP:
00397 con->locale = (CS_LOCALE *) buffer;
00398 break;
00399 case CS_USERDATA:
00400 if (con->userdata)
00401 free(con->userdata);
00402 con->userdata = (void *) malloc(buflen + 1);
00403 tdsdump_log(TDS_DBG_INFO2, "setting userdata orig %p new %p\n", buffer, con->userdata);
00404 con->userdata_len = buflen;
00405 memcpy(con->userdata, buffer, buflen);
00406 break;
00407 case CS_BULK_LOGIN:
00408 memcpy(&intval, buffer, sizeof(intval));
00409 if (intval)
00410 tds_set_bulk(tds_login, 1);
00411 else
00412 tds_set_bulk(tds_login, 0);
00413 break;
00414 case CS_PACKETSIZE:
00415 memcpy(&intval, buffer, sizeof(intval));
00416 tds_set_packet(tds_login, (short) intval);
00417 break;
00418 case CS_TDS_VERSION:
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 if (*(int *) buffer == 0) {
00430
00431 tds_set_version(tds_login, 0, 0);
00432 } else if (*(int *) buffer == CS_TDS_40) {
00433 tds_set_version(tds_login, 4, 2);
00434 } else if (*(int *) buffer == CS_TDS_42) {
00435 tds_set_version(tds_login, 4, 2);
00436 } else if (*(int *) buffer == CS_TDS_46) {
00437 tds_set_version(tds_login, 4, 6);
00438 } else if (*(int *) buffer == CS_TDS_495) {
00439 tds_set_version(tds_login, 4, 6);
00440 } else if (*(int *) buffer == CS_TDS_50) {
00441 tds_set_version(tds_login, 5, 0);
00442 } else if (*(int *) buffer == CS_TDS_70) {
00443 tds_set_version(tds_login, 7, 0);
00444 } else if (*(int *) buffer == CS_TDS_80) {
00445 tds_set_version(tds_login, 8, 0);
00446 } else {
00447 return CS_FAIL;
00448 }
00449 break;
00450 default:
00451 tdsdump_log(TDS_DBG_ERROR, "Unknown property %d\n", property);
00452 break;
00453 }
00454 if (set_buffer)
00455 free(set_buffer);
00456 } else if (action == CS_GET) {
00457 switch (property) {
00458 case CS_USERNAME:
00459 if (out_len)
00460 *out_len = tds_dstr_len(&tds_login->user_name);
00461 tds_strlcpy((char *) buffer, tds_dstr_cstr(&tds_login->user_name), buflen);
00462 break;
00463 case CS_PASSWORD:
00464 if (out_len)
00465 *out_len = tds_dstr_len(&tds_login->password);
00466 tds_strlcpy((char *) buffer, tds_dstr_cstr(&tds_login->password), buflen);
00467 break;
00468 case CS_APPNAME:
00469 if (out_len)
00470 *out_len = tds_dstr_len(&tds_login->app_name);
00471 tds_strlcpy((char *) buffer, tds_dstr_cstr(&tds_login->app_name), buflen);
00472 break;
00473 case CS_HOSTNAME:
00474 if (out_len)
00475 *out_len = tds_dstr_len(&tds_login->client_host_name);
00476 tds_strlcpy((char *) buffer, tds_dstr_cstr(&tds_login->client_host_name), buflen);
00477 break;
00478 case CS_SERVERNAME:
00479 if (out_len)
00480 *out_len = tds_dstr_len(&tds_login->server_name);
00481 tds_strlcpy((char *) buffer, tds_dstr_cstr(&tds_login->server_name), buflen);
00482 break;
00483 case CS_LOC_PROP:
00484 buffer = (CS_VOID *) con->locale;
00485 break;
00486 case CS_USERDATA:
00487 tdsdump_log(TDS_DBG_INFO2, "fetching userdata %p\n", con->userdata);
00488 maxcp = con->userdata_len;
00489 if (out_len)
00490 *out_len = maxcp;
00491 if (maxcp > buflen)
00492 maxcp = buflen;
00493 memcpy(buffer, con->userdata, maxcp);
00494 break;
00495 case CS_CON_STATUS:
00496 if (!(IS_TDSDEAD(tds)))
00497 intval |= CS_CONSTAT_CONNECTED;
00498 else
00499 intval &= ~CS_CONSTAT_CONNECTED;
00500 if (tds && tds->state == TDS_DEAD)
00501 intval |= CS_CONSTAT_DEAD;
00502 else
00503 intval &= ~CS_CONSTAT_DEAD;
00504 memcpy(buffer, &intval, sizeof(intval));
00505 break;
00506 case CS_BULK_LOGIN:
00507 if (tds_login->bulk_copy)
00508 intval = CS_FALSE;
00509 else
00510 intval = CS_TRUE;
00511 memcpy(buffer, &intval, sizeof(intval));
00512 break;
00513 case CS_PACKETSIZE:
00514 if (tds)
00515 intval = tds->env.block_size;
00516 else
00517 intval = tds_login->block_size;
00518 memcpy(buffer, &intval, sizeof(intval));
00519 if (out_len)
00520 *out_len = sizeof(intval);
00521 break;
00522 case CS_TDS_VERSION:
00523 switch (tds_version(tds, NULL)) {
00524 case 40:
00525 (*(int *) buffer = CS_TDS_40);
00526 break;
00527 case 42:
00528 (*(int *) buffer = CS_TDS_42);
00529 break;
00530 case 46:
00531 (*(int *) buffer = CS_TDS_46);
00532 break;
00533 case 40 + 95:
00534 (*(int *) buffer = CS_TDS_495);
00535 break;
00536 case 50:
00537 (*(int *) buffer = CS_TDS_50);
00538 break;
00539 case 70:
00540 (*(int *) buffer = CS_TDS_70);
00541 break;
00542 case 80:
00543 (*(int *) buffer = CS_TDS_80);
00544 break;
00545 default:
00546 return CS_FAIL;
00547 }
00548 break;
00549 case CS_PARENT_HANDLE:
00550 *(CS_CONTEXT **) buffer = con->ctx;
00551 break;
00552
00553 default:
00554 tdsdump_log(TDS_DBG_ERROR, "Unknown property %d\n", property);
00555 break;
00556 }
00557 }
00558 return CS_SUCCEED;
00559 }
00560
00561 static int
00562 ctlib_query_timeout(void *param, unsigned int total_timeout)
00563 {
00564 CS_CONNECTION* con = (CS_CONNECTION*) param;
00565
00566 if (!con)
00567 return TDS_INT_CONTINUE;
00568
00569
00570 tds_set_state(con->tds_socket, TDS_QUERYING);
00571
00572
00573 ct_cancel(con, NULL, CS_CANCEL_ATTN);
00574
00575 return TDS_INT_CANCEL;
00576 }
00577
00578 CS_RETCODE
00579 ct_connect(CS_CONNECTION * con, CS_CHAR * servername, CS_INT snamelen)
00580 {
00581 char *server;
00582 int needfree = 0;
00583 CS_CONTEXT *ctx;
00584 TDSCONNECTION *connection;
00585
00586 tdsdump_log(TDS_DBG_FUNC, "ct_connect() servername = %s\n", servername ? servername : "NULL");
00587
00588 if (!tds_dstr_isempty(&con->tds_login->server_addr)) {
00589 server = tds_dstr_cstr(&con->tds_login->server_addr);
00590 } else if (snamelen == 0 || snamelen == CS_UNUSED) {
00591 server = NULL;
00592 } else if (snamelen == CS_NULLTERM) {
00593 server = (char *) servername;
00594 } else {
00595 server = (char *) malloc(snamelen + 1);
00596 needfree++;
00597 strncpy(server, servername, snamelen);
00598 server[snamelen] = '\0';
00599 }
00600 tds_set_server(con->tds_login, server);
00601 if (needfree)
00602 free(server);
00603 ctx = con->ctx;
00604 if (!(con->tds_socket = tds_alloc_socket(ctx->tds_ctx, 512)))
00605 return CS_FAIL;
00606 tds_set_parent(con->tds_socket, (void *) con);
00607 if (!(connection = tds_read_config_info(NULL, con->tds_login, ctx->tds_ctx->locale))) {
00608 tds_free_socket(con->tds_socket);
00609 con->tds_socket = NULL;
00610 return CS_FAIL;
00611 }
00612
00613
00614 con->tds_socket->query_timeout_param = con;
00615 con->tds_socket->query_timeout_func = ctlib_query_timeout;
00616
00617 if (ctx->login_timeout > 0) {
00618 connection->connect_timeout = ctx->login_timeout;
00619 }
00620
00621 if (ctx->query_timeout > 0) {
00622 connection->query_timeout = ctx->query_timeout;
00623 }
00624
00625 if (con->locale && con->locale->charset) {
00626 tds_dstr_copy(&connection->client_charset, con->locale->charset);
00627 }
00628
00629
00630 if (tds_connect(con->tds_socket, connection) == TDS_FAIL) {
00631 tds_free_socket(con->tds_socket);
00632 con->tds_socket = NULL;
00633 tds_free_connection(connection);
00634 tdsdump_log(TDS_DBG_FUNC, "leaving ct_connect() returning %d\n", CS_FAIL);
00635 return CS_FAIL;
00636 }
00637 tds_free_connection(connection);
00638
00639 tdsdump_log(TDS_DBG_FUNC, "leaving ct_connect() returning %d\n", CS_SUCCEED);
00640 return CS_SUCCEED;
00641 }
00642
00643 CS_RETCODE
00644 ct_cmd_alloc(CS_CONNECTION * con, CS_COMMAND ** cmd)
00645 {
00646
00647 CS_COMMAND_LIST *command_list;
00648 CS_COMMAND_LIST *pcommand;
00649
00650 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_alloc()\n");
00651
00652 *cmd = (CS_COMMAND *) malloc(sizeof(CS_COMMAND));
00653 if (!*cmd)
00654 return CS_FAIL;
00655 memset(*cmd, '\0', sizeof(CS_COMMAND));
00656
00657
00658 (*cmd)->con = con;
00659
00660
00661 ct_set_command_state(*cmd, _CS_COMMAND_IDLE);
00662
00663 command_list = malloc(sizeof(CS_COMMAND_LIST));
00664 memset(command_list, '\0', sizeof(CS_COMMAND_LIST));
00665 command_list->cmd = *cmd;
00666 command_list->next = NULL;
00667
00668 if ( con->cmds == NULL ) {
00669 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_alloc() : allocating command list to head\n");
00670 con->cmds = command_list;
00671 } else {
00672 pcommand = con->cmds;
00673 for (;;) {
00674 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_alloc() : stepping thru existing commands\n");
00675 if (pcommand->next == NULL)
00676 break;
00677 pcommand = pcommand->next;
00678 }
00679 pcommand->next = command_list;
00680 }
00681
00682 return CS_SUCCEED;
00683 }
00684
00685 CS_RETCODE
00686 ct_command(CS_COMMAND * cmd, CS_INT type, const CS_VOID * buffer, CS_INT buflen, CS_INT option)
00687 {
00688 int query_len;
00689 int current_query_len;
00690
00691 tdsdump_log(TDS_DBG_FUNC, "ct_command()\n");
00692
00693
00694
00695
00696 if (cmd->command_state != _CS_COMMAND_BUILDING) {
00697 _ct_initialise_cmd(cmd);
00698 ct_set_command_state(cmd, _CS_COMMAND_IDLE);
00699 }
00700
00701 switch (type) {
00702 case CS_LANG_CMD:
00703 switch (option) {
00704 case CS_MORE:
00705 case CS_END:
00706 case CS_UNUSED:
00707 if (buflen == CS_NULLTERM) {
00708 query_len = strlen((const char *) buffer);
00709 } else {
00710 query_len = buflen;
00711 }
00712
00713 if (query_len == CS_UNUSED) {
00714 cmd->query = NULL;
00715 return CS_FAIL;
00716 }
00717 if (cmd->command_state == _CS_COMMAND_IDLE) {
00718 cmd->query = (char *) malloc(query_len + 1);
00719 strncpy(cmd->query, (const char *) buffer, query_len);
00720 cmd->query[query_len] = '\0';
00721 if (option == CS_MORE) {
00722 ct_set_command_state(cmd, _CS_COMMAND_BUILDING);
00723 } else {
00724 ct_set_command_state(cmd, _CS_COMMAND_READY);
00725 }
00726 }
00727 if (cmd->command_state == _CS_COMMAND_BUILDING) {
00728 current_query_len = strlen(cmd->query);
00729 cmd->query = (char *) realloc(cmd->query, current_query_len + query_len + 1);
00730 strncat(cmd->query, (const char *) buffer, query_len);
00731 cmd->query[current_query_len + query_len] = '\0';
00732 if (option == CS_MORE) {
00733 ct_set_command_state(cmd, _CS_COMMAND_BUILDING);
00734 } else {
00735 ct_set_command_state(cmd, _CS_COMMAND_READY);
00736 }
00737 }
00738
00739 break;
00740 default:
00741 return CS_FAIL;
00742 }
00743 break;
00744
00745 case CS_RPC_CMD:
00746
00747
00748
00749
00750 if (cmd == NULL)
00751 return CS_FAIL;
00752
00753 cmd->rpc = (CSREMOTE_PROC *) malloc(sizeof(CSREMOTE_PROC));
00754 if (cmd->rpc == NULL)
00755 return CS_FAIL;
00756
00757 memset(cmd->rpc, 0, sizeof(CSREMOTE_PROC));
00758
00759 if (buflen == CS_NULLTERM) {
00760 cmd->rpc->name = strdup(buffer);
00761 if (cmd->rpc->name == NULL)
00762 return CS_FAIL;
00763 } else if (buflen > 0) {
00764 cmd->rpc->name = (char *) malloc(buflen + 1);
00765 if (cmd->rpc->name == NULL)
00766 return CS_FAIL;
00767 memset(cmd->rpc->name, 0, buflen + 1);
00768 strncpy(cmd->rpc->name, (const char *) buffer, buflen);
00769 } else {
00770 return CS_FAIL;
00771 }
00772
00773 cmd->rpc->param_list = NULL;
00774
00775 tdsdump_log(TDS_DBG_INFO1, "ct_command() added rpcname \"%s\"\n", cmd->rpc->name);
00776
00777
00778 switch (option) {
00779 case CS_RECOMPILE:
00780 cmd->rpc->options = 0;
00781 break;
00782 case CS_NO_RECOMPILE:
00783 cmd->rpc->options = 0;
00784 break;
00785 case CS_UNUSED:
00786 cmd->rpc->options = 0;
00787 break;
00788 default:
00789 return CS_FAIL;
00790 }
00791 ct_set_command_state(cmd, _CS_COMMAND_READY);
00792 break;
00793
00794
00795 case CS_SEND_DATA_CMD:
00796 switch (option) {
00797 case CS_COLUMN_DATA:
00798 cmd->send_data_started = 0;
00799 break;
00800 case CS_BULK_DATA:
00801 default:
00802 return CS_FAIL;
00803 }
00804 ct_set_command_state(cmd, _CS_COMMAND_READY);
00805 break;
00806
00807 case CS_SEND_BULK_CMD:
00808 switch (option) {
00809 case CS_BULK_INIT:
00810 case CS_BULK_CONT:
00811 default:
00812 return CS_FAIL;
00813 }
00814 ct_set_command_state(cmd, _CS_COMMAND_READY);
00815 break;
00816
00817 default:
00818 return CS_FAIL;
00819 }
00820
00821 cmd->command_type = type;
00822
00823
00824 return CS_SUCCEED;
00825 }
00826
00827 static void
00828 _ct_initialise_cmd(CS_COMMAND *cmd)
00829 {
00830 if (cmd->query) {
00831 free(cmd->query);
00832 cmd->query = NULL;
00833 }
00834
00835 if (cmd->input_params) {
00836 param_clear(cmd->input_params);
00837 cmd->input_params = NULL;
00838 }
00839 ct_set_command_state(cmd, _CS_COMMAND_IDLE);
00840
00841 rpc_clear(cmd->rpc);
00842 cmd->rpc = NULL;
00843 }
00844
00845 CS_RETCODE
00846 ct_send(CS_COMMAND * cmd)
00847 {
00848 TDSSOCKET *tds;
00849 CS_RETCODE ret;
00850 CSREMOTE_PROC **rpc;
00851 TDSPARAMINFO *pparam_info;
00852 TDSCURSOR *cursor;
00853 TDSDYNAMIC *tdsdyn;
00854
00855 tdsdump_log(TDS_DBG_FUNC, "ct_send() command_type = %d\n", cmd->command_type);
00856
00857 if (!cmd->con || !cmd->con->tds_socket)
00858 return CS_FAIL;
00859
00860 tds = cmd->con->tds_socket;
00861
00862 if (cmd->cancel_state == _CS_CANCEL_PENDING) {
00863 _ct_cancel_cleanup(cmd);
00864 return CS_CANCELED;
00865 }
00866
00867 if (cmd->command_state == _CS_COMMAND_IDLE) {
00868 tdsdump_log(TDS_DBG_FUNC, "ct_send() command_state = IDLE\n");
00869 _ctclient_msg(cmd->con, "ct_send", 1, 1, 1, 16843163, "");
00870 return CS_FAIL;
00871 }
00872
00873 cmd->results_state = _CS_RES_NONE;
00874
00875 if (cmd->command_type == CS_DYNAMIC_CMD) {
00876
00877 if (cmd->dyn == NULL)
00878 return CS_FAIL;
00879
00880 switch (cmd->dynamic_cmd) {
00881 case CS_PREPARE:
00882 if (tds_submit_prepare(tds, cmd->dyn->stmt, cmd->dyn->id, NULL, NULL) == TDS_FAIL)
00883 return CS_FAIL;
00884 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00885 return CS_SUCCEED;
00886 break;
00887 case CS_EXECUTE:
00888 pparam_info = paraminfoalloc(tds, cmd->dyn->param_list);
00889 tdsdyn = tds_lookup_dynamic(tds, cmd->dyn->id);
00890 if (!tdsdyn) {
00891 tdsdump_log(TDS_DBG_INFO1, "ct_send(CS_EXECUTE) no tdsdyn!\n");
00892 return CS_FAIL;
00893 }
00894 tds_free_input_params(tdsdyn);
00895 tdsdyn->params = pparam_info;
00896 if (tds_submit_execute(tds, tdsdyn) == TDS_FAIL)
00897 return CS_FAIL;
00898 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00899 return CS_SUCCEED;
00900 break;
00901 case CS_DESCRIBE_INPUT:
00902 tdsdump_log(TDS_DBG_INFO1, "ct_send(CS_DESCRIBE_INPUT)\n");
00903 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00904 cmd->results_state = _CS_RES_DESCRIBE_RESULT;
00905 if (tds->cur_dyn)
00906 tds->current_results = tds->cur_dyn->res_info;
00907 else
00908 tds->current_results = tds->param_info;
00909 break;
00910
00911 case CS_DESCRIBE_OUTPUT:
00912 tdsdump_log(TDS_DBG_INFO1, "ct_send(CS_DESCRIBE_OUTPUT)\n");
00913 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00914 cmd->results_state = _CS_RES_DESCRIBE_RESULT;
00915 tds->current_results = tds->res_info;
00916 break;
00917
00918 case CS_DEALLOC:
00919 tdsdyn = tds_lookup_dynamic(tds, cmd->dyn->id);
00920 if (!tdsdyn) {
00921 tdsdump_log(TDS_DBG_INFO1, "ct_send(CS_DEALLOC) no tdsdyn!\n");
00922 return CS_FAIL;
00923 }
00924 if (tds_submit_unprepare(tds, tdsdyn) == TDS_FAIL)
00925 return CS_FAIL;
00926 else {
00927 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00928 return CS_SUCCEED;
00929 }
00930 break;
00931
00932 default:
00933 return CS_FAIL;
00934 }
00935 }
00936
00937 if (cmd->command_type == CS_RPC_CMD) {
00938
00939 if (cmd == NULL || cmd->rpc == NULL
00940 || cmd->rpc->name == NULL) {
00941 return CS_FAIL;
00942 }
00943
00944 rpc = &(cmd->rpc);
00945 pparam_info = paraminfoalloc(tds, cmd->rpc->param_list);
00946 ret = tds_submit_rpc(tds, cmd->rpc->name, pparam_info);
00947
00948 tds_free_param_results(pparam_info);
00949
00950 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00951
00952 if (ret == TDS_FAIL) {
00953 return CS_FAIL;
00954 }
00955
00956 return CS_SUCCEED;
00957 }
00958
00959
00960
00961 if (cmd->command_type == CS_LANG_CMD) {
00962 ret = CS_FAIL;
00963 if (cmd->input_params) {
00964 pparam_info = paraminfoalloc(tds, cmd->input_params);
00965 ret = tds_submit_query_params(tds, cmd->query, pparam_info);
00966 tds_free_param_results(pparam_info);
00967 } else {
00968 ret = tds_submit_query(tds, cmd->query);
00969 }
00970
00971 ct_set_command_state(cmd, _CS_COMMAND_SENT);
00972
00973 if (ret == TDS_FAIL) {
00974 tdsdump_log(TDS_DBG_WARN, "ct_send() failed\n");
00975 return CS_FAIL;
00976 }
00977 tdsdump_log(TDS_DBG_INFO2, "ct_send() succeeded\n");
00978 return CS_SUCCEED;
00979 }
00980
00981
00982
00983 if (cmd->command_type == CS_CUR_CMD) {
00984
00985
00986
00987
00988
00989
00990
00991 int something_to_send = 0;
00992
00993 tdsdump_log(TDS_DBG_FUNC, "ct_send() : CS_CUR_CMD\n");
00994
00995 cursor = cmd->cursor;
00996 if (!cursor) {
00997 tdsdump_log(TDS_DBG_FUNC, "ct_send() : cursor not present\n");
00998 return CS_FAIL;
00999 }
01000
01001 if (cmd == NULL ) {
01002 tdsdump_log(TDS_DBG_FUNC, "ct_send() : cmd is null\n");
01003 return CS_FAIL;
01004 }
01005 if (cursor->query == NULL ) {
01006 tdsdump_log(TDS_DBG_FUNC, "ct_send() : cursor->query is null\n");
01007 return CS_FAIL;
01008 }
01009 if ( cursor->cursor_name == NULL ) {
01010 tdsdump_log(TDS_DBG_FUNC, "ct_send() : cursor->name is null\n");
01011 return CS_FAIL;
01012 }
01013
01014 if (cursor->status.declare == _CS_CURS_TYPE_REQUESTED) {
01015 ret = tds_cursor_declare(tds, cursor, &something_to_send);
01016 if (ret == CS_SUCCEED){
01017 cursor->status.declare = _CS_CURS_TYPE_SENT;
01018 if (something_to_send == 0) {
01019 cmd->results_state = _CS_RES_END_RESULTS;
01020 }
01021 }
01022 else {
01023 tdsdump_log(TDS_DBG_WARN, "ct_send(): cursor declare failed \n");
01024 return CS_FAIL;
01025 }
01026 }
01027
01028 if (cursor->status.cursor_row == _CS_CURS_TYPE_REQUESTED &&
01029 cursor->status.declare == _CS_CURS_TYPE_SENT) {
01030
01031 ret = tds_cursor_setrows(tds, cursor, &something_to_send);
01032 if (ret == CS_SUCCEED){
01033 cursor->status.cursor_row = _CS_CURS_TYPE_SENT;
01034 if (something_to_send == 0) {
01035 cmd->results_state = _CS_RES_END_RESULTS;
01036 }
01037 }
01038 else {
01039 tdsdump_log(TDS_DBG_WARN, "ct_send(): cursor set rows failed\n");
01040 return CS_FAIL;
01041 }
01042 }
01043
01044 if (cursor->status.open == _CS_CURS_TYPE_REQUESTED &&
01045 cursor->status.declare == _CS_CURS_TYPE_SENT) {
01046
01047 ret = tds_cursor_open(tds, cursor, &something_to_send);
01048 if (ret == CS_SUCCEED){
01049 cursor->status.open = _CS_CURS_TYPE_SENT;
01050 cmd->results_state = _CS_RES_INIT;
01051 }
01052 else {
01053 tdsdump_log(TDS_DBG_WARN, "ct_send(): cursor open failed\n");
01054 return CS_FAIL;
01055 }
01056 }
01057
01058 if (something_to_send) {
01059 tdsdump_log(TDS_DBG_WARN, "ct_send(): sending cursor commands\n");
01060 tds_flush_packet(tds);
01061 tds_set_state(tds, TDS_PENDING);
01062 something_to_send = 0;
01063
01064 ct_set_command_state(cmd, _CS_COMMAND_SENT);
01065
01066 return CS_SUCCEED;
01067 }
01068
01069 if (cursor->status.close == _CS_CURS_TYPE_REQUESTED){
01070 if (cursor->status.dealloc == TDS_CURSOR_STATE_REQUESTED) {
01071
01072 ret = tds_cursor_close(tds, cursor);
01073 cmd->cursor = NULL;
01074
01075
01076
01077
01078 } else {
01079 ret = tds_cursor_close(tds, cursor);
01080 cursor->status.close = _CS_CURS_TYPE_SENT;
01081 }
01082 }
01083
01084 if (cursor && cursor->status.dealloc == _CS_CURS_TYPE_REQUESTED) {
01085
01086 ret = tds_cursor_dealloc(tds, cursor);
01087 cmd->cursor = NULL;
01088 tds_free_all_results(tds);
01089 }
01090
01091 ct_set_command_state(cmd, _CS_COMMAND_SENT);
01092 return CS_SUCCEED;
01093 }
01094
01095 if (cmd->command_type == CS_SEND_DATA_CMD) {
01096 tds_flush_packet(tds);
01097 tds_set_state(tds, TDS_PENDING);
01098 ct_set_command_state(cmd, _CS_COMMAND_SENT);
01099 }
01100
01101 return CS_SUCCEED;
01102 }
01103
01104
01105 CS_RETCODE
01106 ct_results(CS_COMMAND * cmd, CS_INT * result_type)
01107 {
01108 TDSSOCKET *tds;
01109 CS_CONTEXT *context;
01110
01111 int tdsret;
01112 CS_INT res_type;
01113 CS_INT done_flags;
01114
01115 tdsdump_log(TDS_DBG_FUNC, "ct_results()\n");
01116
01117 if (cmd->cancel_state == _CS_CANCEL_PENDING) {
01118 _ct_cancel_cleanup(cmd);
01119 return CS_CANCELED;
01120 }
01121
01122 if (!cmd->con || !cmd->con->tds_socket)
01123 return CS_FAIL;
01124
01125 cmd->bind_count = CS_UNUSED;
01126
01127 context = cmd->con->ctx;
01128
01129 tds = cmd->con->tds_socket;
01130 cmd->row_prefetched = 0;
01131
01132
01133
01134
01135
01136
01137 switch (cmd->results_state) {
01138 case _CS_RES_CMD_SUCCEED:
01139 *result_type = CS_CMD_SUCCEED;
01140 cmd->results_state = _CS_RES_CMD_DONE;
01141 return CS_SUCCEED;
01142 case _CS_RES_CMD_DONE:
01143 *result_type = CS_CMD_DONE;
01144 cmd->results_state = _CS_RES_INIT;
01145 return CS_SUCCEED;
01146 case _CS_RES_END_RESULTS:
01147 *result_type = CS_CMD_DONE;
01148 cmd->results_state = _CS_RES_INIT;
01149 return CS_END_RESULTS;
01150 case _CS_RES_DESCRIBE_RESULT:
01151 *result_type = CS_DESCRIBE_RESULT;
01152 cmd->results_state = _CS_RES_CMD_DONE;
01153 return CS_SUCCEED;
01154 case _CS_RES_NONE:
01155 cmd->results_state = _CS_RES_INIT;
01156 break;
01157 default:
01158 break;
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168 for (;;) {
01169
01170 tdsret = tds_process_tokens(tds, &res_type, &done_flags, TDS_TOKEN_RESULTS);
01171
01172 tdsdump_log(TDS_DBG_FUNC, "ct_results() process_result_tokens returned %d (type %d) \n",
01173 tdsret, res_type);
01174
01175 switch (tdsret) {
01176
01177 case TDS_SUCCEED:
01178
01179 cmd->curr_result_type = res_type;
01180
01181 switch (res_type) {
01182
01183 case CS_COMPUTEFMT_RESULT:
01184 case CS_ROWFMT_RESULT:
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 cmd->results_state = _CS_RES_RESULTSET_EMPTY;
01196
01197 if (context->config.cs_expose_formats) {
01198 *result_type = res_type;
01199 return CS_SUCCEED;
01200 }
01201 break;
01202
01203 case CS_ROW_RESULT:
01204
01205
01206
01207
01208
01209
01210
01211 cmd->results_state = _CS_RES_RESULTSET_ROWS;
01212 if (cmd->command_type == CS_CUR_CMD) {
01213 *result_type = CS_CURSOR_RESULT;
01214 } else {
01215 *result_type = CS_ROW_RESULT;
01216 }
01217 return CS_SUCCEED;
01218 break;
01219
01220 case CS_COMPUTE_RESULT:
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 if (cmd->results_state == _CS_RES_RESULTSET_EMPTY) {
01234 *result_type = CS_ROW_RESULT;
01235 tds->current_results = tds->res_info;
01236 cmd->results_state = _CS_RES_RESULTSET_ROWS;
01237 return CS_SUCCEED;
01238 }
01239
01240 tdsret = tds_process_tokens(tds, &res_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
01241
01242
01243
01244 cmd->results_state = _CS_RES_RESULTSET_ROWS;
01245
01246 *result_type = res_type;
01247 if (tdsret == TDS_SUCCEED && (res_type == TDS_ROW_RESULT || res_type == TDS_COMPUTE_RESULT)) {
01248 if (res_type == TDS_COMPUTE_RESULT) {
01249 cmd->row_prefetched = 1;
01250 return CS_SUCCEED;
01251 } else {
01252
01253 return CS_FAIL;
01254 }
01255 } else
01256 return CS_FAIL;
01257 break;
01258
01259 case TDS_DONE_RESULT:
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277 tdsdump_log(TDS_DBG_FUNC, "ct_results() results state = %d\n",cmd->results_state);
01278 tdsdump_log(TDS_DBG_FUNC, "ct_results() command type = %d\n",cmd->command_type);
01279 tdsdump_log(TDS_DBG_FUNC, "ct_results() dynamic cmd = %d\n",cmd->dynamic_cmd);
01280
01281 if ((cmd->command_type == CS_DYNAMIC_CMD) &&
01282 (cmd->dynamic_cmd == CS_PREPARE || cmd->dynamic_cmd == CS_DEALLOC)) {
01283 *result_type = CS_CMD_SUCCEED;
01284 cmd->results_state = _CS_RES_CMD_DONE;
01285 return CS_SUCCEED;
01286 }
01287
01288 switch (cmd->results_state) {
01289
01290 case _CS_RES_INIT:
01291 case _CS_RES_STATUS:
01292 if (done_flags & TDS_DONE_ERROR)
01293 *result_type = CS_CMD_FAIL;
01294 else
01295 *result_type = CS_CMD_SUCCEED;
01296 cmd->results_state = _CS_RES_CMD_DONE;
01297 break;
01298
01299 case _CS_RES_RESULTSET_EMPTY:
01300 if (cmd->command_type == CS_CUR_CMD) {
01301 *result_type = CS_CURSOR_RESULT;
01302 cmd->results_state = _CS_RES_RESULTSET_ROWS;
01303 } else {
01304 *result_type = CS_ROW_RESULT;
01305 cmd->results_state = _CS_RES_CMD_DONE;
01306 }
01307 break;
01308
01309 case _CS_RES_RESULTSET_ROWS:
01310 *result_type = CS_CMD_DONE;
01311 cmd->results_state = _CS_RES_INIT;
01312 break;
01313
01314 }
01315 return CS_SUCCEED;
01316 break;
01317
01318 case TDS_DONEINPROC_RESULT:
01319
01320
01321
01322
01323
01324
01325
01326 switch (cmd->results_state) {
01327 case _CS_RES_INIT:
01328 break;
01329 case _CS_RES_RESULTSET_EMPTY:
01330 if (cmd->command_type == CS_CUR_CMD) {
01331 *result_type = CS_CURSOR_RESULT;
01332 } else {
01333 *result_type = CS_ROW_RESULT;
01334 }
01335 cmd->results_state = _CS_RES_CMD_DONE;
01336 return CS_SUCCEED;
01337 break;
01338 case _CS_RES_RESULTSET_ROWS:
01339 *result_type = CS_CMD_DONE;
01340 cmd->results_state = _CS_RES_INIT;
01341 return CS_SUCCEED;
01342 break;
01343 }
01344 break;
01345
01346 case TDS_DONEPROC_RESULT:
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357 if (cmd->results_state == _CS_RES_STATUS ||
01358 cmd->results_state == _CS_RES_INIT
01359 ) {
01360 if (done_flags & TDS_DONE_ERROR)
01361 *result_type = CS_CMD_FAIL;
01362 else
01363 *result_type = CS_CMD_SUCCEED;
01364 cmd->results_state = _CS_RES_CMD_DONE;
01365 return CS_SUCCEED;
01366 } else {
01367 if (cmd->command_type == CS_DYNAMIC_CMD) {
01368 *result_type = CS_CMD_SUCCEED;
01369 cmd->results_state = _CS_RES_CMD_DONE;
01370 return CS_SUCCEED;
01371 }
01372 }
01373
01374 break;
01375
01376 case TDS_PARAM_RESULT:
01377 cmd->row_prefetched = 1;
01378 *result_type = res_type;
01379 return CS_SUCCEED;
01380 break;
01381
01382 case TDS_STATUS_RESULT:
01383 _ct_process_return_status(tds);
01384 cmd->row_prefetched = 1;
01385 *result_type = res_type;
01386 cmd->results_state = _CS_RES_STATUS;
01387 return CS_SUCCEED;
01388 break;
01389
01390 case TDS_DESCRIBE_RESULT:
01391 if (cmd->dynamic_cmd == CS_DESCRIBE_INPUT ||
01392 cmd->dynamic_cmd == CS_DESCRIBE_OUTPUT) {
01393 *result_type = res_type;
01394 return CS_SUCCEED;
01395 }
01396 break;
01397 default:
01398 *result_type = res_type;
01399 return CS_SUCCEED;
01400 break;
01401 }
01402
01403 break;
01404
01405 case TDS_NO_MORE_RESULTS:
01406
01407
01408
01409
01410 if (cmd->command_type == CS_LANG_CMD ||
01411 cmd->command_type == CS_RPC_CMD ||
01412 cmd->command_type == CS_CUR_CMD ||
01413 cmd->command_type == CS_DYNAMIC_CMD) {
01414 ct_set_command_state(cmd, _CS_COMMAND_READY);
01415 }
01416
01417
01418
01419 if (cmd->command_type == CS_DYNAMIC_CMD &&
01420 cmd->dynamic_cmd == CS_DEALLOC) {
01421 _ct_deallocate_dynamic(cmd->con, cmd->dyn);
01422 cmd->dyn = NULL;
01423 }
01424 return CS_END_RESULTS;
01425 break;
01426
01427 case TDS_CANCELLED:
01428 cmd->cancel_state = _CS_CANCEL_NOCANCEL;
01429 return CS_CANCELED;
01430 break;
01431
01432 case TDS_FAIL:
01433 default:
01434 return CS_FAIL;
01435 break;
01436
01437 }
01438 }
01439 }
01440
01441
01442 CS_RETCODE
01443 ct_bind(CS_COMMAND * cmd, CS_INT item, CS_DATAFMT * datafmt, CS_VOID * buffer, CS_INT * copied, CS_SMALLINT * indicator)
01444 {
01445 TDSCOLUMN *colinfo;
01446 TDSRESULTINFO *resinfo;
01447 TDSSOCKET *tds;
01448 CS_CONNECTION *con = cmd->con;
01449 CS_INT bind_count;
01450
01451 tdsdump_log(TDS_DBG_FUNC, "ct_bind() datafmt count = %d column_number = %d\n", datafmt->count, item);
01452
01453 if (!con || !con->tds_socket)
01454 return CS_FAIL;
01455
01456 tds = con->tds_socket;
01457 resinfo = tds->current_results;
01458
01459
01460 if (!resinfo || item <= 0 || item > resinfo->num_cols)
01461 return CS_FAIL;
01462
01463 colinfo = resinfo->columns[item - 1];
01464
01465
01466
01467
01468 bind_count = (datafmt->count == 0) ? 1 : datafmt->count;
01469
01470
01471
01472 if (cmd->bind_count == CS_UNUSED) {
01473 cmd->bind_count = bind_count;
01474 } else {
01475
01476 if (cmd->bind_count != bind_count) {
01477 _ctclient_msg(con, "ct_bind", 1, 1, 1, 137, "%d, %d", bind_count, cmd->bind_count);
01478 return CS_FAIL;
01479 }
01480 }
01481
01482
01483
01484 colinfo = resinfo->columns[item - 1];
01485 colinfo->column_varaddr = (char *) buffer;
01486 colinfo->column_bindtype = datafmt->datatype;
01487 colinfo->column_bindfmt = datafmt->format;
01488 colinfo->column_bindlen = datafmt->maxlength;
01489 if (indicator) {
01490 colinfo->column_nullbind = indicator;
01491 }
01492 if (copied) {
01493 colinfo->column_lenbind = copied;
01494 }
01495 return CS_SUCCEED;
01496 }
01497
01498 CS_RETCODE
01499 ct_fetch(CS_COMMAND * cmd, CS_INT type, CS_INT offset, CS_INT option, CS_INT * rows_read)
01500 {
01501 TDS_INT ret_type;
01502 TDS_INT ret;
01503 TDS_INT marker;
01504 TDS_INT temp_count;
01505 TDSSOCKET *tds;
01506
01507 tdsdump_log(TDS_DBG_FUNC, "ct_fetch()\n");
01508
01509 if (!cmd->con || !cmd->con->tds_socket)
01510 return CS_FAIL;
01511
01512 if (cmd->command_state == _CS_COMMAND_IDLE) {
01513 _ctclient_msg(cmd->con, "ct_fetch", 1, 1, 1, 16843163, "");
01514 return CS_FAIL;
01515 }
01516
01517 if (cmd->cancel_state == _CS_CANCEL_PENDING) {
01518 _ct_cancel_cleanup(cmd);
01519 return CS_CANCELED;
01520 }
01521
01522 tds = cmd->con->tds_socket;
01523
01524
01525
01526
01527 if (cmd->command_type == CS_CUR_CMD) {
01528 return _ct_fetch_cursor(cmd, type, offset, option, rows_read);
01529 }
01530
01531 if (rows_read)
01532 *rows_read = 0;
01533
01534
01535 temp_count = cmd->bind_count;
01536
01537 if ( cmd->bind_count == CS_UNUSED )
01538 cmd->bind_count = 1;
01539
01540
01541
01542 if (cmd->row_prefetched) {
01543 cmd->row_prefetched = 0;
01544 cmd->get_data_item = 0;
01545 cmd->get_data_bytes_returned = 0;
01546 if (_ct_bind_data(cmd->con->ctx, tds->current_results, tds->current_results, 0))
01547 return CS_ROW_FAIL;
01548 if (rows_read)
01549 *rows_read = 1;
01550 return CS_SUCCEED;
01551 }
01552
01553 if (cmd->results_state == _CS_RES_CMD_DONE)
01554 return CS_END_DATA;
01555 if (cmd->curr_result_type == CS_COMPUTE_RESULT)
01556 return CS_END_DATA;
01557 if (cmd->curr_result_type == CS_CMD_FAIL)
01558 return CS_CMD_FAIL;
01559
01560
01561 marker = tds_peek(tds);
01562 if ((cmd->curr_result_type == CS_ROW_RESULT && marker != TDS_ROW_TOKEN) ||
01563 (cmd->curr_result_type == CS_STATUS_RESULT && marker != TDS_RETURNSTATUS_TOKEN) )
01564 return CS_END_DATA;
01565
01566
01567
01568 for (temp_count = 0; temp_count < cmd->bind_count; temp_count++) {
01569
01570 ret = tds_process_tokens(tds, &ret_type, NULL, TDS_STOPAT_ROWFMT|TDS_STOPAT_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
01571
01572 tdsdump_log(TDS_DBG_FUNC, "inside ct_fetch()process_row_tokens returned %d\n", ret);
01573
01574 switch (ret) {
01575 case TDS_SUCCEED:
01576 if (ret_type == TDS_ROW_RESULT || ret_type == TDS_COMPUTE_RESULT) {
01577 cmd->get_data_item = 0;
01578 cmd->get_data_bytes_returned = 0;
01579 if (_ct_bind_data(cmd->con->ctx, tds->current_results, tds->current_results, temp_count))
01580 return CS_ROW_FAIL;
01581 if (rows_read)
01582 *rows_read = *rows_read + 1;
01583 break;
01584 }
01585 case TDS_NO_MORE_RESULTS:
01586 return CS_END_DATA;
01587 break;
01588
01589 case TDS_CANCELLED:
01590 cmd->cancel_state = _CS_CANCEL_NOCANCEL;
01591 return CS_CANCELED;
01592 break;
01593
01594 default:
01595 return CS_FAIL;
01596 break;
01597 }
01598
01599
01600
01601 marker = tds_peek(tds);
01602
01603 if (cmd->curr_result_type == CS_ROW_RESULT && marker != TDS_ROW_TOKEN)
01604 break;
01605
01606 }
01607
01608
01609
01610 return CS_SUCCEED;
01611 }
01612
01613 static CS_RETCODE
01614 _ct_fetch_cursor(CS_COMMAND * cmd, CS_INT type, CS_INT offset, CS_INT option, CS_INT * rows_read)
01615 {
01616 TDSSOCKET * tds;
01617 TDSCURSOR *cursor;
01618 TDS_INT restype;
01619 TDS_INT ret;
01620 TDS_INT temp_count;
01621 TDS_INT done_flags;
01622 TDS_INT rows_this_fetch = 0;
01623
01624 tdsdump_log(TDS_DBG_FUNC, "_ct_fetch_cursor()\n");
01625
01626 if (!cmd->con || !cmd->con->tds_socket)
01627 return CS_FAIL;
01628
01629 tds = cmd->con->tds_socket;
01630
01631 if (rows_read)
01632 *rows_read = 0;
01633
01634
01635 temp_count = cmd->bind_count;
01636
01637 if ( cmd->bind_count == CS_UNUSED )
01638 cmd->bind_count = 1;
01639
01640 cursor = cmd->cursor;
01641 if (!cursor) {
01642 tdsdump_log(TDS_DBG_FUNC, "ct_fetch_cursor() : cursor not present\n");
01643 return CS_FAIL;
01644 }
01645
01646
01647
01648
01649
01650 if (cmd->bind_count < cursor->cursor_rows) {
01651 tdsdump_log(TDS_DBG_WARN, "_ct_fetch_cursor(): bind count must equal cursor rows \n");
01652 return CS_FAIL;
01653 }
01654
01655
01656 if (tds_cursor_fetch(tds, cursor, TDS_CURSOR_FETCH_NEXT, 0) == CS_SUCCEED) {
01657 cursor->status.fetch = _CS_CURS_TYPE_SENT;
01658 }
01659 else {
01660 tdsdump_log(TDS_DBG_WARN, "ct_fetch(): cursor fetch failed\n");
01661 return CS_FAIL;
01662 }
01663
01664 tds->cur_cursor = cursor;
01665
01666 while ((tds_process_tokens(tds, &restype, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) {
01667 switch (restype) {
01668 case CS_ROWFMT_RESULT:
01669 break;
01670 case CS_ROW_RESULT:
01671 for (temp_count = 0; temp_count < cmd->bind_count; temp_count++) {
01672
01673 ret = tds_process_tokens(tds, &restype, NULL, TDS_STOPAT_ROWFMT|TDS_STOPAT_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
01674
01675 tdsdump_log(TDS_DBG_FUNC, "_ct_fetch_cursor() tds_process_tokens returned %d\n", ret);
01676
01677 if (ret == TDS_SUCCEED && (restype == TDS_ROW_RESULT || restype == TDS_COMPUTE_RESULT)) {
01678 cmd->get_data_item = 0;
01679 cmd->get_data_bytes_returned = 0;
01680 if (restype == TDS_ROW_RESULT) {
01681 if (_ct_bind_data(cmd->con->ctx, tds->current_results, tds->current_results, temp_count))
01682 return CS_ROW_FAIL;
01683 if (rows_read)
01684 *rows_read = *rows_read + 1;
01685 rows_this_fetch++;
01686 }
01687 } else {
01688 if (ret != TDS_FAIL) {
01689 break;
01690 } else {
01691 return CS_FAIL;
01692 }
01693 }
01694 }
01695 break;
01696 case TDS_DONE_RESULT:
01697 break;
01698 }
01699 }
01700 if (rows_this_fetch)
01701 return CS_SUCCEED;
01702 else {
01703 cmd->results_state = _CS_RES_CMD_SUCCEED;
01704 return CS_END_DATA;
01705 }
01706
01707 }
01708
01709
01710 int
01711 _ct_bind_data(CS_CONTEXT *ctx, TDSRESULTINFO * resinfo, TDSRESULTINFO *bindinfo, CS_INT offset)
01712 {
01713 int i;
01714 TDSCOLUMN *curcol;
01715 TDSCOLUMN *bindcol;
01716 unsigned char *src;
01717 unsigned char *dest, *temp_add;
01718 int result = 0;
01719 TDS_INT srctype, srclen, desttype, len;
01720 CS_DATAFMT srcfmt, destfmt;
01721 TDS_INT *datalen = NULL;
01722 TDS_SMALLINT *nullind = NULL;
01723
01724 tdsdump_log(TDS_DBG_FUNC, "_ct_bind_data()\n");
01725
01726 for (i = 0; i < resinfo->num_cols; i++) {
01727 datalen = NULL;
01728 nullind = NULL;
01729
01730 curcol = resinfo->columns[i];
01731 bindcol = bindinfo->columns[i];
01732
01733 tdsdump_log(TDS_DBG_FUNC, "_ct_bind_data(): column_type: %d column_len: %d\n",
01734 curcol->column_type,
01735 curcol->column_cur_size
01736 );
01737
01738 if (curcol->column_hidden)
01739 continue;
01740
01741
01742 srctype = curcol->column_type;
01743 desttype = _ct_get_server_type(bindcol->column_bindtype);
01744
01745
01746
01747
01748 temp_add = (unsigned char *) bindcol->column_varaddr;
01749 dest = temp_add + (offset * bindcol->column_bindlen);
01750
01751 if (bindcol->column_nullbind) {
01752 nullind = bindcol->column_nullbind;
01753 nullind += offset;
01754 }
01755 if (bindcol->column_lenbind) {
01756 datalen = bindcol->column_lenbind;
01757 datalen += offset;
01758 }
01759
01760 if (dest) {
01761
01762 if (curcol->column_cur_size < 0) {
01763 if (nullind)
01764 *nullind = -1;
01765 if (datalen)
01766 *datalen = 0;
01767 } else {
01768
01769 srctype = _ct_get_client_type(ctx, curcol->column_type, curcol->column_usertype, curcol->column_size);
01770
01771 src = &(resinfo->current_row[curcol->column_offset]);
01772 if (is_blob_type(curcol->column_type))
01773 src = (unsigned char *) ((TDSBLOB *) src)->textvalue;
01774
01775 srclen = curcol->column_cur_size;
01776 srcfmt.datatype = srctype;
01777 srcfmt.maxlength = srclen;
01778
01779 destfmt.datatype = bindcol->column_bindtype;
01780
01781 destfmt.maxlength = bindcol->column_bindlen;
01782 destfmt.format = bindcol->column_bindfmt;
01783
01784
01785 if ((result= cs_convert(ctx, &srcfmt, (CS_VOID *) src, &destfmt, (CS_VOID *) dest, &len) != CS_SUCCEED)) {
01786 tdsdump_log(TDS_DBG_FUNC, "cs_convert-result = %d\n", result);
01787 result = 1;
01788 len = 0;
01789 tdsdump_log(TDS_DBG_INFO1, "\n convert failed for %d \n", srcfmt.datatype);
01790 }
01791
01792 if (nullind)
01793 *nullind = 0;
01794 if (datalen) {
01795 *datalen = len;
01796 }
01797 }
01798 } else {
01799 if (datalen)
01800 *datalen = 0;
01801 }
01802 }
01803 return result;
01804 }
01805
01806 CS_RETCODE
01807 ct_cmd_drop(CS_COMMAND * cmd)
01808 {
01809 CS_RETCODE ret;
01810 ret = _ct_cmd_drop(cmd, 1);
01811 return ret;
01812 }
01813
01814 static CS_RETCODE
01815 _ct_cmd_drop(CS_COMMAND * cmd, CS_INT free_conn_ref)
01816 {
01817 CS_COMMAND_LIST *victim = NULL;
01818 CS_COMMAND_LIST *prev = NULL;
01819 CS_COMMAND_LIST *next = NULL;
01820 CS_CONNECTION *con;
01821
01822 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_drop()\n");
01823 if (cmd) {
01824 if (cmd->query)
01825 free(cmd->query);
01826 if (cmd->input_params)
01827 param_clear(cmd->input_params);
01828 if (cmd->userdata)
01829 free(cmd->userdata);
01830 if (cmd->rpc) {
01831 if (cmd->rpc->param_list)
01832 param_clear(cmd->rpc->param_list);
01833 free(cmd->rpc->name);
01834 free(cmd->rpc);
01835 }
01836 if (cmd->iodesc)
01837 free(cmd->iodesc);
01838
01839
01840
01841 if (free_conn_ref && cmd->con) {
01842 con = cmd->con;
01843 victim = con->cmds;
01844
01845 for (;;) {
01846 if (victim->cmd == cmd)
01847 break;
01848 prev = victim;
01849 victim = victim->next;
01850 if (victim == NULL) {
01851 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_drop() : cannot find command entry in list \n");
01852 return CS_FAIL;
01853 }
01854 }
01855
01856 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_drop() : command entry found in list\n");
01857
01858 next = victim->next;
01859 free(victim);
01860
01861 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_drop() : relinking list\n");
01862
01863 if (prev)
01864 prev->next = next;
01865 else
01866 con->cmds = next;
01867
01868 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_drop() : relinked list\n");
01869 }
01870
01871 free(cmd);
01872 }
01873 return CS_SUCCEED;
01874 }
01875
01876 CS_RETCODE
01877 ct_close(CS_CONNECTION * con, CS_INT option)
01878 {
01879 tdsdump_log(TDS_DBG_FUNC, "ct_close()\n");
01880 tds_free_socket(con->tds_socket);
01881 con->tds_socket = NULL;
01882 return CS_SUCCEED;
01883 }
01884
01885 CS_RETCODE
01886 ct_con_drop(CS_CONNECTION * con)
01887 {
01888 CS_COMMAND_LIST *currptr;
01889 CS_COMMAND_LIST *freeptr;
01890
01891 tdsdump_log(TDS_DBG_FUNC, "ct_con_drop()\n");
01892 if (con) {
01893 if (con->userdata)
01894 free(con->userdata);
01895 if (con->tds_login)
01896 tds_free_login(con->tds_login);
01897 if (con->cmds) {
01898 currptr = con->cmds;
01899 while (currptr != NULL) {
01900 freeptr = currptr;
01901 if (currptr->cmd)
01902 currptr->cmd->con = NULL;
01903 currptr = currptr->next;
01904 free(freeptr);
01905 }
01906 }
01907 free(con);
01908 }
01909 return CS_SUCCEED;
01910 }
01911
01912 int
01913 _ct_get_client_type(CS_CONTEXT *ctx, int datatype, int usertype, int size)
01914 {
01915 tdsdump_log(TDS_DBG_FUNC, "_ct_get_client_type(type %d, user %d, size %d)\n", datatype, usertype, size);
01916 switch (datatype) {
01917 case SYBBIT:
01918 case SYBBITN:
01919 return CS_BIT_TYPE;
01920 break;
01921 case SYBCHAR:
01922 return CS_VARCHAR_TYPE;
01923 break;
01924 case SYBVARCHAR:
01925 return CS_VARCHAR_TYPE;
01926 break;
01927 case SYBINT8:
01928 return CS_LONG_TYPE;
01929 break;
01930 case SYBINT4:
01931 return CS_INT_TYPE;
01932 break;
01933 case SYBINT2:
01934 return CS_SMALLINT_TYPE;
01935 break;
01936 case SYBINT1:
01937 return CS_TINYINT_TYPE;
01938 break;
01939 case SYBINTN:
01940 switch (size) {
01941 case 8:
01942 return CS_LONG_TYPE;
01943 case 4:
01944 return CS_INT_TYPE;
01945 case 2:
01946 return CS_SMALLINT_TYPE;
01947 case 1:
01948 return CS_TINYINT_TYPE;
01949 default:
01950 _csclient_msg(ctx, "_ct_get_client_type", 2, 1, 16, 28, "%d", size);
01951 }
01952 break;
01953 case SYBREAL:
01954 return CS_REAL_TYPE;
01955 break;
01956 case SYBFLT8:
01957 return CS_FLOAT_TYPE;
01958 break;
01959 case SYBFLTN:
01960 if (size == 4) {
01961 return CS_REAL_TYPE;
01962 } else if (size == 8) {
01963 return CS_FLOAT_TYPE;
01964 } else {
01965 _csclient_msg(ctx, "_ct_get_client_type", 2, 1, 16, 29, "%d", size);
01966 }
01967 case SYBMONEY:
01968 return CS_MONEY_TYPE;
01969 break;
01970 case SYBMONEY4:
01971 return CS_MONEY4_TYPE;
01972 break;
01973 case SYBMONEYN:
01974 if (size == 4) {
01975 return CS_MONEY4_TYPE;
01976 } else if (size == 8) {
01977 return CS_MONEY_TYPE;
01978 } else {
01979 _csclient_msg(ctx, "_ct_get_client_type", 2, 1, 16, 30, "%d", size);
01980 }
01981 case SYBDATETIME:
01982 return CS_DATETIME_TYPE;
01983 break;
01984 case SYBDATETIME4:
01985 return CS_DATETIME4_TYPE;
01986 break;
01987 case SYBDATETIMN:
01988 if (size == 4) {
01989 return CS_DATETIME4_TYPE;
01990 } else if (size == 8) {
01991 return CS_DATETIME_TYPE;
01992 } else {
01993 _csclient_msg(ctx, "_ct_get_client_type", 2, 1, 16, 31, "%d", size);
01994 }
01995 break;
01996 case SYBNUMERIC:
01997 return CS_NUMERIC_TYPE;
01998 break;
01999 case SYBDECIMAL:
02000 return CS_DECIMAL_TYPE;
02001 break;
02002 case SYBBINARY:
02003 return CS_BINARY_TYPE;
02004 break;
02005 case SYBIMAGE:
02006 return CS_IMAGE_TYPE;
02007 break;
02008 case SYBVARBINARY:
02009 return CS_VARBINARY_TYPE;
02010 break;
02011 case SYBTEXT:
02012 return CS_TEXT_TYPE;
02013 break;
02014 case SYBUNIQUE:
02015 return CS_UNIQUE_TYPE;
02016 break;
02017 case SYBLONGBINARY:
02018 if (usertype == USER_UNICHAR_TYPE || usertype == USER_UNIVARCHAR_TYPE)
02019 return CS_UNICHAR_TYPE;
02020
02021 return CS_LONGBINARY_TYPE;
02022 break;
02023 }
02024
02025 return CS_FAIL;
02026 }
02027
02028 int
02029 _ct_get_server_type(int datatype)
02030 {
02031 tdsdump_log(TDS_DBG_FUNC, "_ct_get_server_type(%d)\n", datatype);
02032 switch (datatype) {
02033 case CS_IMAGE_TYPE:
02034 return SYBIMAGE;
02035 break;
02036 case CS_BINARY_TYPE:
02037 return SYBBINARY;
02038 break;
02039 case CS_BIT_TYPE:
02040 return SYBBIT;
02041 break;
02042 case CS_CHAR_TYPE:
02043 return SYBCHAR;
02044 break;
02045 case CS_LONG_TYPE:
02046 return SYBINT8;
02047 break;
02048 case CS_INT_TYPE:
02049 return SYBINT4;
02050 break;
02051 case CS_SMALLINT_TYPE:
02052 return SYBINT2;
02053 break;
02054 case CS_TINYINT_TYPE:
02055 return SYBINT1;
02056 break;
02057 case CS_REAL_TYPE:
02058 return SYBREAL;
02059 break;
02060 case CS_FLOAT_TYPE:
02061 return SYBFLT8;
02062 break;
02063 case CS_MONEY_TYPE:
02064 return SYBMONEY;
02065 break;
02066 case CS_MONEY4_TYPE:
02067 return SYBMONEY4;
02068 break;
02069 case CS_DATETIME_TYPE:
02070 return SYBDATETIME;
02071 break;
02072 case CS_DATETIME4_TYPE:
02073 return SYBDATETIME4;
02074 break;
02075 case CS_NUMERIC_TYPE:
02076 return SYBNUMERIC;
02077 break;
02078 case CS_DECIMAL_TYPE:
02079 return SYBDECIMAL;
02080 break;
02081 case CS_VARBINARY_TYPE:
02082 return SYBVARBINARY;
02083 break;
02084 case CS_TEXT_TYPE:
02085 return SYBTEXT;
02086 break;
02087 case CS_UNIQUE_TYPE:
02088 return SYBUNIQUE;
02089 break;
02090 case CS_LONGBINARY_TYPE:
02091 return SYBLONGBINARY;
02092 break;
02093 case CS_UNICHAR_TYPE:
02094 return SYBNVARCHAR;
02095 case CS_LONGCHAR_TYPE:
02096 return SYBVARCHAR;
02097 case CS_NLONGCHAR_TYPE:
02098 return SYBNVARCHAR;
02099 case CS_VARCHAR_TYPE:
02100 return SYBVARCHAR;
02101 case CS_NVARCHAR_TYPE:
02102 return SYBNVARCHAR;
02103 default:
02104
02105
02106
02107
02108
02109 return -1;
02110 break;
02111 }
02112 }
02113
02114 CS_RETCODE
02115 ct_cancel(CS_CONNECTION * conn, CS_COMMAND * cmd, CS_INT type)
02116 {
02117 CS_RETCODE ret;
02118 CS_COMMAND_LIST *cmds;
02119 CS_COMMAND *conn_cmd;
02120 CS_CONNECTION *cmd_conn;
02121
02122 tdsdump_log(TDS_DBG_FUNC, "ct_cancel()\n");
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136 if (type == CS_CANCEL_CURRENT) {
02137
02138
02139 tdsdump_log(TDS_DBG_FUNC, "CS_CANCEL_CURRENT\n");
02140 if (conn || !cmd)
02141 return CS_FAIL;
02142
02143
02144 if (!_ct_fetchable_results(cmd)) {
02145 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() no fetchable results - return()\n");
02146 return CS_SUCCEED;
02147 }
02148
02149 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() - fetching results()\n");
02150 do {
02151 ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, NULL);
02152 } while ((ret == CS_SUCCEED) || (ret == CS_ROW_FAIL));
02153
02154 if (cmd->con && cmd->con->tds_socket)
02155 tds_free_all_results(cmd->con->tds_socket);
02156
02157 if (ret == CS_END_DATA) {
02158 return CS_SUCCEED;
02159 }
02160 return CS_FAIL;
02161 }
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189 if (type == CS_CANCEL_ATTN) {
02190 if ((conn && cmd) || (!conn && !cmd)) {
02191 return CS_FAIL;
02192 }
02193 if (cmd) {
02194 tdsdump_log(TDS_DBG_FUNC, "CS_CANCEL_ATTN with cmd\n");
02195 cmd_conn = cmd->con;
02196 switch (cmd->command_state) {
02197 case _CS_COMMAND_IDLE:
02198 case _CS_COMMAND_READY:
02199 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state READY/IDLE\n");
02200 break;
02201 case _CS_COMMAND_SENT:
02202 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state SENT results_state %d\n", cmd->results_state);
02203 if (cmd->results_state != _CS_RES_NONE) {
02204 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() sending a cancel \n");
02205 tds_send_cancel(cmd_conn->tds_socket);
02206 cmd->cancel_state = _CS_CANCEL_PENDING;
02207 }
02208 break;
02209 }
02210 }
02211 if (conn) {
02212 tdsdump_log(TDS_DBG_FUNC, "CS_CANCEL_ATTN with connection\n");
02213 for (cmds = conn->cmds; cmds != NULL; cmds = cmds->next) {
02214 conn_cmd = cmds->cmd;
02215 switch (conn_cmd->command_state) {
02216 case _CS_COMMAND_IDLE:
02217 case _CS_COMMAND_READY:
02218 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state READY/IDLE\n");
02219 break;
02220 case _CS_COMMAND_SENT:
02221 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state SENT\n");
02222 if (conn_cmd->results_state != _CS_RES_NONE) {
02223 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() sending a cancel \n");
02224 tds_send_cancel(conn->tds_socket);
02225 conn_cmd->cancel_state = _CS_CANCEL_PENDING;
02226 }
02227 break;
02228 }
02229 }
02230 }
02231
02232 return CS_SUCCEED;
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 if (type == CS_CANCEL_ALL) {
02265
02266 if ((conn && cmd) || (!conn && !cmd)) {
02267 return CS_FAIL;
02268 }
02269 if (cmd) {
02270 tdsdump_log(TDS_DBG_FUNC, "CS_CANCEL_ALL with cmd\n");
02271 cmd_conn = cmd->con;
02272 switch (cmd->command_state) {
02273 case _CS_COMMAND_IDLE:
02274 case _CS_COMMAND_BUILDING:
02275 case _CS_COMMAND_READY:
02276 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state READY/IDLE\n");
02277 _ct_initialise_cmd(cmd);
02278 break;
02279 case _CS_COMMAND_SENT:
02280 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state SENT\n");
02281 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() sending a cancel \n");
02282 tds_send_cancel(cmd_conn->tds_socket);
02283 tds_process_cancel(cmd_conn->tds_socket);
02284 _ct_initialise_cmd(cmd);
02285 break;
02286 }
02287 }
02288 if (conn) {
02289 tdsdump_log(TDS_DBG_FUNC, "CS_CANCEL_ALL with connection\n");
02290 for (cmds = conn->cmds; cmds != NULL; cmds = cmds->next) {
02291 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() cancelling a command for a connection\n");
02292 conn_cmd = cmds->cmd;
02293 switch (conn_cmd->command_state) {
02294 case _CS_COMMAND_IDLE:
02295 case _CS_COMMAND_BUILDING:
02296 case _CS_COMMAND_READY:
02297 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state SENT\n");
02298 _ct_initialise_cmd(conn_cmd);
02299 break;
02300 case _CS_COMMAND_SENT:
02301 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() command state SENT\n");
02302 tdsdump_log(TDS_DBG_FUNC, "ct_cancel() sending a cancel \n");
02303 tds_send_cancel(conn->tds_socket);
02304 tds_process_cancel(conn->tds_socket);
02305 _ct_initialise_cmd(conn_cmd);
02306 break;
02307 }
02308 }
02309 }
02310
02311 return CS_SUCCEED;
02312 }
02313 return CS_FAIL;
02314 }
02315
02316 static CS_RETCODE
02317 _ct_cancel_cleanup(CS_COMMAND * cmd)
02318 {
02319 CS_CONNECTION * con;
02320
02321 con = cmd->con;
02322
02323 if (con && !IS_TDSDEAD(con->tds_socket))
02324 tds_process_cancel(con->tds_socket);
02325
02326 cmd->cancel_state = _CS_CANCEL_NOCANCEL;
02327
02328 return CS_SUCCEED;
02329
02330 }
02331
02332 CS_RETCODE
02333 ct_describe(CS_COMMAND * cmd, CS_INT item, CS_DATAFMT * datafmt)
02334 {
02335 TDSSOCKET *tds;
02336 TDSRESULTINFO *resinfo;
02337 TDSCOLUMN *curcol;
02338 int len;
02339
02340 tdsdump_log(TDS_DBG_FUNC, "ct_describe()\n");
02341
02342 if (!cmd->con || !cmd->con->tds_socket)
02343 return CS_FAIL;
02344
02345 tds = cmd->con->tds_socket;
02346 resinfo = tds->current_results;;
02347
02348 if (item < 1 || item > resinfo->num_cols)
02349 return CS_FAIL;
02350
02351 curcol = resinfo->columns[item - 1];
02352 len = curcol->column_namelen;
02353 if (len >= CS_MAX_NAME)
02354 len = CS_MAX_NAME - 1;
02355 strncpy(datafmt->name, curcol->column_name, len);
02356
02357 datafmt->name[len] = 0;
02358 datafmt->namelen = len;
02359
02360 datafmt->datatype = _ct_get_client_type(cmd->con->ctx, curcol->column_type, curcol->column_usertype, curcol->column_size);
02361 tdsdump_log(TDS_DBG_INFO1, "ct_describe() datafmt->datatype = %d server type %d\n", datafmt->datatype,
02362 curcol->column_type);
02363
02364 datafmt->maxlength = curcol->column_size;
02365 datafmt->usertype = curcol->column_usertype;
02366 datafmt->precision = curcol->column_prec;
02367 datafmt->scale = curcol->column_scale;
02368
02369 datafmt->format = curcol->column_bindfmt;
02370
02371
02372
02373
02374
02375 datafmt->status = 0;
02376 if (curcol->column_nullable)
02377 datafmt->status |= CS_CANBENULL;
02378 if (curcol->column_identity)
02379 datafmt->status |= CS_IDENTITY;
02380 if (strcmp(datafmt->name, "txts") == 0)
02381 datafmt->status |= CS_TIMESTAMP;
02382
02383 datafmt->count = 1;
02384 datafmt->locale = NULL;
02385
02386 return CS_SUCCEED;
02387 }
02388
02389 CS_RETCODE
02390 ct_res_info(CS_COMMAND * cmd, CS_INT type, CS_VOID * buffer, CS_INT buflen, CS_INT * out_len)
02391 {
02392 TDSSOCKET *tds;
02393 TDSRESULTINFO *resinfo;
02394 TDSCOLUMN *curcol;
02395 CS_INT int_val;
02396 int i;
02397
02398 tdsdump_log(TDS_DBG_FUNC, "ct_res_info()\n");
02399
02400 if (!cmd->con || !cmd->con->tds_socket)
02401 return CS_FAIL;
02402
02403 tds = cmd->con->tds_socket;
02404 resinfo = tds->current_results;
02405
02406 switch (type) {
02407 case CS_NUMDATA:
02408 int_val = 0;
02409 if (resinfo) {
02410 for (i = 0; i < resinfo->num_cols; i++) {
02411 curcol = resinfo->columns[i];
02412 if (!curcol->column_hidden) {
02413 int_val++;
02414 }
02415 }
02416 }
02417 tdsdump_log(TDS_DBG_FUNC, "ct_res_info(): Number of columns is %d\n", int_val);
02418 memcpy(buffer, &int_val, sizeof(CS_INT));
02419 break;
02420 case CS_ROW_COUNT:
02421 int_val = tds->rows_affected;
02422 tdsdump_log(TDS_DBG_FUNC, "ct_res_info(): Number of rows is %d\n", int_val);
02423 memcpy(buffer, &int_val, sizeof(CS_INT));
02424 break;
02425 default:
02426 _csclient_msg(cmd->con->ctx, "ct_res_info", 2, 1, 16, 32, "%d", type);
02427 return CS_FAIL;
02428 break;
02429 }
02430 return CS_SUCCEED;
02431
02432 }
02433
02434 CS_RETCODE
02435 ct_config(CS_CONTEXT * ctx, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
02436 {
02437 CS_RETCODE ret = CS_SUCCEED;
02438 CS_INT *buf = (CS_INT *) buffer;
02439
02440 tdsdump_log(TDS_DBG_FUNC, "ct_config() action = %s property = %d\n",
02441 CS_GET ? "CS_GET" : CS_SET ? "CS_SET" : CS_SUPPORTED ? "CS_SUPPORTED" : "CS_CLEAR", property);
02442
02443 switch (property) {
02444 case CS_EXPOSE_FMTS:
02445 switch (action) {
02446 case CS_SUPPORTED:
02447 *buf = CS_TRUE;
02448 break;
02449 case CS_SET:
02450 if (*buf != CS_TRUE && *buf != CS_FALSE)
02451 ret = CS_FAIL;
02452 else
02453 ctx->config.cs_expose_formats = *buf;
02454 break;
02455 case CS_GET:
02456 if (buf)
02457 *buf = ctx->config.cs_expose_formats;
02458 else
02459 ret = CS_FAIL;
02460 break;
02461 case CS_CLEAR:
02462 ctx->config.cs_expose_formats = CS_FALSE;
02463 break;
02464 default:
02465 ret = CS_FAIL;
02466 }
02467 break;
02468 case CS_VER_STRING: {
02469 ret = CS_FAIL;
02470 switch (action) {
02471 case CS_GET: {
02472 if (buffer && buflen > 0 && outlen) {
02473 const TDS_COMPILETIME_SETTINGS *settings= tds_get_compiletime_settings();
02474 *outlen= snprintf((char*)buffer, buflen, "%s (%s, default tds version=%s)",
02475 settings->freetds_version,
02476 (settings->threadsafe ? "threadsafe" : "non-threadsafe"),
02477 settings->tdsver
02478 );
02479 ((char*)buffer)[buflen - 1]= 0;
02480 if (*outlen < 0)
02481 *outlen = strlen((char*) buffer);
02482 ret = CS_SUCCEED;
02483 }
02484 break;
02485 default:
02486 ret = CS_FAIL;
02487 break;
02488 }
02489 }
02490 }
02491 break;
02492 case CS_VERSION:
02493 ret = CS_FAIL;
02494 switch (action) {
02495 case CS_GET: {
02496 if (buffer && buflen > 0 && outlen) {
02497 const TDS_COMPILETIME_SETTINGS *settings= tds_get_compiletime_settings();
02498 *outlen= snprintf(buffer, buflen, "%s", settings->freetds_version);
02499 ((char*)buffer)[buflen - 1]= 0;
02500 if (*outlen < 0)
02501 *outlen = strlen((char*) buffer);
02502 ret = CS_SUCCEED;
02503 }
02504 break;
02505 default:
02506 ret = CS_FAIL;
02507 break;
02508 }
02509 }
02510 break;
02511 case CS_TIMEOUT:
02512 switch (action) {
02513 case CS_SET:
02514 ctx->query_timeout = *((unsigned int*)buf);
02515 break;
02516 case CS_GET:
02517 *((unsigned int*)buf) = ctx->query_timeout;
02518 break;
02519 case CS_CLEAR:
02520 ctx->query_timeout = -1;
02521 break;
02522 default:
02523 ret = CS_FAIL;
02524 break;
02525 }
02526 break;
02527 case CS_LOGIN_TIMEOUT:
02528 switch (action) {
02529 case CS_SET:
02530 ctx->login_timeout = *((unsigned int*)buf);
02531 break;
02532 case CS_GET:
02533 *((unsigned int*)buf) = ctx->login_timeout;
02534 break;
02535 case CS_CLEAR:
02536 ctx->login_timeout = -1;
02537 break;
02538 default:
02539 ret = CS_FAIL;
02540 break;
02541 }
02542 break;
02543 default:
02544 ret = CS_SUCCEED;
02545 break;
02546 }
02547
02548 return ret;
02549 }
02550
02551 CS_RETCODE
02552 ct_cmd_props(CS_COMMAND * cmd, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
02553 {
02554 TDSSOCKET *tds;
02555 TDSCURSOR *cursor;
02556 int maxcp;
02557
02558 if (!cmd->con || !cmd->con->tds_socket)
02559 return CS_FAIL;
02560
02561 tds = cmd->con->tds_socket;
02562
02563 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_props() action = %s property = %d\n", CS_GET ? "CS_GET" : "CS_SET", property);
02564 if (action == CS_SET) {
02565 switch (property) {
02566 case CS_USERDATA:
02567 if (cmd->userdata)
02568 free(cmd->userdata);
02569 cmd->userdata = (void *) malloc(buflen + 1);
02570 tdsdump_log(TDS_DBG_INFO2, "setting userdata orig %p new %p\n", buffer, cmd->userdata);
02571 cmd->userdata_len = buflen;
02572 memcpy(cmd->userdata, buffer, buflen);
02573 break;
02574 default:
02575 break;
02576 }
02577 }
02578 if (action == CS_GET) {
02579 switch (property) {
02580
02581 case CS_PARENT_HANDLE:
02582 *(CS_CONNECTION **) buffer = cmd->con;
02583 break;
02584
02585 case CS_CUR_STATUS:
02586 case CS_CUR_ID:
02587 case CS_CUR_NAME:
02588 case CS_CUR_ROWCOUNT:
02589
02590 cursor = cmd->cursor;
02591
02592 if (!cursor) {
02593 tdsdump_log(TDS_DBG_FUNC, "ct_cmd_props() : cannot find cursor\n");
02594 if (property == CS_CUR_STATUS) {
02595 *(CS_INT *)buffer = (CS_INT) CS_CURSTAT_NONE;
02596 if (outlen) *outlen = sizeof(CS_INT);
02597 return CS_SUCCEED;
02598 } else {
02599 return CS_FAIL;
02600 }
02601 }
02602
02603 if (property == CS_CUR_STATUS) {
02604 *(CS_INT *)buffer = cursor->srv_status;
02605 if (outlen) *outlen = sizeof(CS_INT);
02606 }
02607 if (property == CS_CUR_ID) {
02608 *(CS_INT *)buffer = cursor->cursor_id;
02609 if (outlen) *outlen = sizeof(CS_INT);
02610 }
02611 if (property == CS_CUR_NAME) {
02612 size_t len = strlen(cursor->cursor_name);
02613 if (len >= buflen)
02614 return CS_FAIL;
02615 strcpy(buffer, cursor->cursor_name);
02616 if (outlen) *outlen = len;
02617 }
02618 if (property == CS_CUR_ROWCOUNT) {
02619 *(CS_INT *)buffer = cursor->cursor_rows;
02620 if (outlen) *outlen = sizeof(CS_INT);
02621 }
02622 break;
02623
02624 case CS_USERDATA:
02625 tdsdump_log(TDS_DBG_INFO2, "fetching userdata %p\n", cmd->userdata);
02626 maxcp = cmd->userdata_len;
02627 if (outlen) *outlen = maxcp;
02628 if (maxcp > buflen)
02629 maxcp = buflen;
02630 memcpy(buffer, cmd->userdata, maxcp);
02631 break;
02632 default:
02633 break;
02634 }
02635 }
02636 return CS_SUCCEED;
02637 }
02638
02639 CS_RETCODE
02640 ct_compute_info(CS_COMMAND * cmd, CS_INT type, CS_INT colnum, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
02641 {
02642 TDSSOCKET *tds;
02643 TDSRESULTINFO *resinfo;
02644 TDSCOLUMN *curcol;
02645 CS_INT int_val;
02646 CS_SMALLINT *dest_by_col_ptr;
02647 TDS_SMALLINT *src_by_col_ptr;
02648 int i;
02649
02650 tdsdump_log(TDS_DBG_FUNC, "ct_compute_info() type = %d, colnum = %d\n", type, colnum);
02651
02652 if (!cmd->con || !cmd->con->tds_socket)
02653 return CS_FAIL;
02654
02655 tds = cmd->con->tds_socket;
02656 resinfo = tds->current_results;
02657
02658 switch (type) {
02659 case CS_BYLIST_LEN:
02660 if (!resinfo) {
02661 int_val = 0;
02662 } else {
02663 int_val = resinfo->by_cols;
02664 }
02665 memcpy(buffer, &int_val, sizeof(CS_INT));
02666 if (outlen)
02667 *outlen = sizeof(CS_INT);
02668 break;
02669 case CS_COMP_BYLIST:
02670 if (buflen < (resinfo->by_cols * sizeof(CS_SMALLINT))) {
02671 return CS_FAIL;
02672 } else {
02673 dest_by_col_ptr = (CS_SMALLINT *) buffer;
02674 src_by_col_ptr = resinfo->bycolumns;
02675 for (i = 0; i < resinfo->by_cols; i++) {
02676 *dest_by_col_ptr = *src_by_col_ptr;
02677 dest_by_col_ptr++;
02678 src_by_col_ptr++;
02679 }
02680 if (outlen)
02681 *outlen = (resinfo->by_cols * sizeof(CS_SMALLINT));
02682 }
02683 break;
02684 case CS_COMP_COLID:
02685 if (!resinfo) {
02686 int_val = 0;
02687 } else {
02688 curcol = resinfo->columns[colnum - 1];
02689 int_val = curcol->column_operand;
02690 }
02691 memcpy(buffer, &int_val, sizeof(CS_INT));
02692 if (outlen)
02693 *outlen = sizeof(CS_INT);
02694 break;
02695 case CS_COMP_ID:
02696 if (!resinfo) {
02697 int_val = 0;
02698 } else {
02699 int_val = resinfo->computeid;
02700 }
02701 memcpy(buffer, &int_val, sizeof(CS_INT));
02702 if (outlen)
02703 *outlen = sizeof(CS_INT);
02704 break;
02705 case CS_COMP_OP:
02706 if (!resinfo) {
02707 int_val = 0;
02708 } else {
02709 curcol = resinfo->columns[colnum - 1];
02710 int_val = curcol->column_operator;
02711 }
02712 memcpy(buffer, &int_val, sizeof(CS_INT));
02713 if (outlen)
02714 *outlen = sizeof(CS_INT);
02715 break;
02716 default:
02717 _csclient_msg(cmd->con->ctx, "ct_compute_info", 2, 1, 16, 32, "%d", type);
02718 return CS_FAIL;
02719 break;
02720 }
02721 return CS_SUCCEED;
02722 }
02723
02724 CS_RETCODE
02725 ct_get_data(CS_COMMAND * cmd, CS_INT item, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
02726 {
02727 TDSRESULTINFO *resinfo;
02728 TDSCOLUMN *curcol;
02729 unsigned char *src;
02730 TDS_INT srclen;
02731
02732 tdsdump_log(TDS_DBG_FUNC, "ct_get_data() item = %d buflen = %d\n", item, buflen);
02733
02734 if (cmd->cancel_state == _CS_CANCEL_PENDING) {
02735 _ct_cancel_cleanup(cmd);
02736 return CS_CANCELED;
02737 }
02738
02739
02740
02741 if (!cmd || !cmd->con || !cmd->con->tds_socket || !(resinfo = cmd->con->tds_socket->current_results))
02742 return CS_FAIL;
02743 if (item < 1 || item > resinfo->num_cols)
02744 return CS_FAIL;
02745 if (buffer == NULL)
02746 return CS_FAIL;
02747 if (buflen == CS_UNUSED)
02748 return CS_FAIL;
02749
02750
02751
02752 if (item != cmd->get_data_item) {
02753 TDSBLOB *blob = NULL;
02754 size_t table_namelen, column_namelen;
02755
02756
02757 if (cmd->iodesc)
02758 free(cmd->iodesc);
02759 cmd->iodesc = calloc(1, sizeof(CS_IODESC));
02760 if (!cmd->iodesc)
02761 return CS_FAIL;
02762
02763
02764 cmd->get_data_item = item;
02765 cmd->get_data_bytes_returned = 0;
02766
02767
02768 curcol = resinfo->columns[item - 1];
02769
02770 src = &(resinfo->current_row[curcol->column_offset]);
02771 if (is_blob_type(curcol->column_type)) {
02772 blob = (TDSBLOB *) src;
02773 src = (unsigned char *) blob->textvalue;
02774 }
02775
02776
02777
02778 cmd->iodesc->iotype = CS_IODATA;
02779 cmd->iodesc->datatype = curcol->column_type;
02780 cmd->iodesc->locale = cmd->con->locale;
02781 cmd->iodesc->usertype = curcol->column_usertype;
02782 cmd->iodesc->total_txtlen = curcol->column_cur_size;
02783 cmd->iodesc->offset = curcol->column_offset;
02784 cmd->iodesc->log_on_update = CS_FALSE;
02785
02786
02787
02788 table_namelen = curcol->table_namelen;
02789 if (table_namelen + 2 > sizeof(cmd->iodesc->name))
02790 table_namelen = sizeof(cmd->iodesc->name) - 2;
02791 column_namelen = curcol->column_namelen;
02792 if (table_namelen + column_namelen + 2 > sizeof(cmd->iodesc->name))
02793 column_namelen = sizeof(cmd->iodesc->name) - 2 - table_namelen;
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804 if (table_namelen) {
02805 memcpy(cmd->iodesc->name, curcol->table_name, table_namelen);
02806 cmd->iodesc->namelen = table_namelen;
02807 } else {
02808 cmd->iodesc->namelen = 0;
02809 }
02810
02811 cmd->iodesc->name[cmd->iodesc->namelen] = '.';
02812 ++cmd->iodesc->namelen;
02813
02814 if (column_namelen) {
02815 memcpy(cmd->iodesc->name + cmd->iodesc->namelen, curcol->column_name, column_namelen);
02816 cmd->iodesc->namelen += column_namelen;
02817 }
02818
02819 cmd->iodesc->name[cmd->iodesc->namelen] = '\0';
02820
02821
02822
02823 if (blob) {
02824 memcpy(cmd->iodesc->timestamp, blob->timestamp, CS_TS_SIZE);
02825 cmd->iodesc->timestamplen = CS_TS_SIZE;
02826 memcpy(cmd->iodesc->textptr, blob->textptr, CS_TP_SIZE);
02827 cmd->iodesc->textptrlen = CS_TP_SIZE;
02828 }
02829 } else {
02830
02831 curcol = resinfo->columns[item - 1];
02832 src = &(resinfo->current_row[curcol->column_offset]);
02833 if (is_blob_type(curcol->column_type))
02834 src = (unsigned char *) ((TDSBLOB *) src)->textvalue;
02835
02836 }
02837
02838
02839
02840
02841
02842
02843 srclen = curcol->column_cur_size;
02844 if (srclen < 0) {
02845
02846 if (outlen)
02847 *outlen = srclen;
02848 if (item < resinfo->num_cols)
02849 return CS_END_ITEM;
02850 return CS_END_DATA;
02851 }
02852
02853 src += cmd->get_data_bytes_returned;
02854 srclen -= cmd->get_data_bytes_returned;
02855
02856
02857
02858 if (buflen >= srclen) {
02859 memcpy(buffer, src, srclen);
02860 cmd->get_data_bytes_returned += srclen;
02861 if (outlen)
02862 *outlen = srclen;
02863 if (item < resinfo->num_cols)
02864 return CS_END_ITEM;
02865 return CS_END_DATA;
02866
02867 }
02868 memcpy(buffer, src, buflen);
02869 cmd->get_data_bytes_returned += buflen;
02870 if (outlen)
02871 *outlen = buflen;
02872 return CS_SUCCEED;
02873 }
02874
02875 CS_RETCODE
02876 ct_send_data(CS_COMMAND * cmd, CS_VOID * buffer, CS_INT buflen)
02877 {
02878 TDSSOCKET *tds;
02879 char writetext_cmd[512];
02880
02881 char textptr_string[35];
02882 char timestamp_string[19];
02883 char *c;
02884 int s;
02885 char hex2[3];
02886
02887 tdsdump_log(TDS_DBG_FUNC, "ct_send_data()\n");
02888
02889 if (!cmd->con || !cmd->con->tds_socket)
02890 return CS_FAIL;
02891
02892 tds = cmd->con->tds_socket;
02893
02894
02895
02896 if (cmd->command_type != CS_SEND_DATA_CMD)
02897 return CS_FAIL;
02898
02899 if (!cmd->iodesc)
02900 return CS_FAIL;
02901
02902
02903
02904 if (!cmd->send_data_started) {
02905
02906
02907
02908 c = textptr_string;
02909
02910 for (s = 0; s < cmd->iodesc->textptrlen; s++) {
02911 sprintf(hex2, "%02x", cmd->iodesc->textptr[s]);
02912 *c++ = hex2[0];
02913 *c++ = hex2[1];
02914 }
02915 *c = '\0';
02916
02917 c = timestamp_string;
02918
02919 for (s = 0; s < cmd->iodesc->timestamplen; s++) {
02920 sprintf(hex2, "%02x", cmd->iodesc->timestamp[s]);
02921 *c++ = hex2[0];
02922 *c++ = hex2[1];
02923 }
02924 *c = '\0';
02925
02926
02927
02928 sprintf(writetext_cmd, "writetext bulk %s 0x%s timestamp = 0x%s%s",
02929 cmd->iodesc->name,
02930 textptr_string, timestamp_string, ((cmd->iodesc->log_on_update == CS_TRUE) ? " with log" : "")
02931 );
02932
02933 if (tds_submit_query(tds, writetext_cmd) != TDS_SUCCEED) {
02934 return CS_FAIL;
02935 }
02936
02937
02938
02939 if (tds_process_simple_query(tds) != TDS_SUCCEED)
02940 return CS_FAIL;
02941
02942 if (tds_set_state(tds, TDS_QUERYING) != TDS_QUERYING)
02943 return CS_FAIL;
02944
02945 cmd->send_data_started = 1;
02946 tds->out_flag = TDS_BULK;
02947 tds_put_int(tds, cmd->iodesc->total_txtlen);
02948 }
02949
02950 tds->out_flag = TDS_BULK;
02951 tds_put_n(tds, buffer, buflen);
02952
02953 return CS_SUCCEED;
02954 }
02955
02956 CS_RETCODE
02957 ct_data_info(CS_COMMAND * cmd, CS_INT action, CS_INT colnum, CS_IODESC * iodesc)
02958 {
02959 TDSSOCKET *tds;
02960 TDSRESULTINFO *resinfo;
02961
02962 if (!cmd->con || !cmd->con->tds_socket)
02963 return CS_FAIL;
02964
02965 tds = cmd->con->tds_socket;
02966 resinfo = tds->current_results;
02967
02968 tdsdump_log(TDS_DBG_FUNC, "ct_data_info() colnum %d\n", colnum);
02969
02970 switch (action) {
02971 case CS_SET:
02972
02973 if (cmd->iodesc)
02974 free(cmd->iodesc);
02975 cmd->iodesc = malloc(sizeof(CS_IODESC));
02976
02977 cmd->iodesc->iotype = CS_IODATA;
02978
02979
02980
02981 switch (iodesc->datatype) {
02982 case CS_IMAGE_TYPE:
02983 cmd->iodesc->datatype = SYBIMAGE;
02984 break;
02985 case CS_TEXT_TYPE:
02986 cmd->iodesc->datatype = SYBTEXT;
02987 break;
02988 default:
02989 cmd->iodesc->datatype = iodesc->datatype;
02990 break;
02991 };
02992
02993 cmd->iodesc->locale = cmd->con->locale;
02994 cmd->iodesc->usertype = iodesc->usertype;
02995 cmd->iodesc->total_txtlen = iodesc->total_txtlen;
02996 cmd->iodesc->offset = iodesc->offset;
02997 cmd->iodesc->log_on_update = iodesc->log_on_update;
02998 strcpy(cmd->iodesc->name, iodesc->name);
02999 cmd->iodesc->namelen = iodesc->namelen;
03000 memcpy(cmd->iodesc->timestamp, iodesc->timestamp, CS_TS_SIZE);
03001 cmd->iodesc->timestamplen = CS_TS_SIZE;
03002 memcpy(cmd->iodesc->textptr, iodesc->textptr, CS_TP_SIZE);
03003 cmd->iodesc->textptrlen = CS_TP_SIZE;
03004 break;
03005
03006 case CS_GET:
03007
03008 if (colnum < 1 || colnum > resinfo->num_cols)
03009 return CS_FAIL;
03010 if (colnum != cmd->get_data_item)
03011 return CS_FAIL;
03012
03013 iodesc->iotype = cmd->iodesc->iotype;
03014
03015
03016
03017 switch (cmd->iodesc->datatype) {
03018 case SYBIMAGE:
03019 iodesc->datatype = CS_IMAGE_TYPE;
03020 break;
03021 case SYBTEXT:
03022 iodesc->datatype = CS_TEXT_TYPE;
03023 break;
03024 default:
03025 iodesc->datatype = cmd->iodesc->datatype;
03026 break;
03027 };
03028
03029 iodesc->locale = cmd->iodesc->locale;
03030 iodesc->usertype = cmd->iodesc->usertype;
03031 iodesc->total_txtlen = cmd->iodesc->total_txtlen;
03032 iodesc->offset = cmd->iodesc->offset;
03033 iodesc->log_on_update = CS_FALSE;
03034 strcpy(iodesc->name, cmd->iodesc->name);
03035 iodesc->namelen = cmd->iodesc->namelen;
03036 memcpy(iodesc->timestamp, cmd->iodesc->timestamp, cmd->iodesc->timestamplen);
03037 iodesc->timestamplen = cmd->iodesc->timestamplen;
03038 memcpy(iodesc->textptr, cmd->iodesc->textptr, cmd->iodesc->textptrlen);
03039 iodesc->textptrlen = cmd->iodesc->textptrlen;
03040 break;
03041
03042 default:
03043 return CS_FAIL;
03044 }
03045
03046 return CS_SUCCEED;
03047 }
03048
03049 CS_RETCODE
03050 ct_capability(CS_CONNECTION * con, CS_INT action, CS_INT type, CS_INT capability, CS_VOID * value)
03051 {
03052 TDSLOGIN *login;
03053 int idx = 0;
03054 unsigned char bitmask = 0;
03055 unsigned char *mask;
03056
03057 tdsdump_log(TDS_DBG_FUNC, "ct_capability()\n");
03058 login = (TDSLOGIN *) con->tds_login;
03059 mask = login->capabilities;
03060
03061 if (type == CS_CAP_RESPONSE) {
03062 switch (capability) {
03063 case CS_DATA_NOBOUNDARY:
03064 idx = 13;
03065 bitmask = 0x01;
03066 break;
03067 case CS_RES_NOTDSDEBUG:
03068 idx = 13;
03069 bitmask = 0x02;
03070 break;
03071 case CS_RES_NOSTRIPBLANKS:
03072 idx = 13;
03073 bitmask = 0x04;
03074 break;
03075 case CS_DATA_NOINT8:
03076 idx = 13;
03077 bitmask = 0x08;
03078 break;
03079 case CS_DATA_NOINTN:
03080 idx = 14;
03081 bitmask = 0x01;
03082 break;
03083 case CS_DATA_NODATETIMEN:
03084 idx = 14;
03085 bitmask = 0x02;
03086 break;
03087 case CS_DATA_NOMONEYN:
03088 idx = 14;
03089 bitmask = 0x04;
03090 break;
03091 case CS_CON_NOOOB:
03092 idx = 14;
03093 bitmask = 0x08;
03094 break;
03095 case CS_CON_NOINBAND:
03096 idx = 14;
03097 bitmask = 0x10;
03098 break;
03099 case CS_PROTO_NOTEXT:
03100 idx = 14;
03101 bitmask = 0x20;
03102 break;
03103 case CS_PROTO_NOBULK:
03104 idx = 14;
03105 bitmask = 0x40;
03106 break;
03107 case CS_DATA_NOSENSITIVITY:
03108 idx = 14;
03109 bitmask = 0x80;
03110 break;
03111 case CS_DATA_NOFLT4:
03112 idx = 15;
03113 bitmask = 0x01;
03114 break;
03115 case CS_DATA_NOFLT8:
03116 idx = 15;
03117 bitmask = 0x02;
03118 break;
03119 case CS_DATA_NONUM:
03120 idx = 15;
03121 bitmask = 0x04;
03122 break;
03123 case CS_DATA_NOTEXT:
03124 idx = 15;
03125 bitmask = 0x08;
03126 break;
03127 case CS_DATA_NOIMAGE:
03128 idx = 15;
03129 bitmask = 0x10;
03130 break;
03131 case CS_DATA_NODEC:
03132 idx = 15;
03133 bitmask = 0x20;
03134 break;
03135 case CS_DATA_NOLCHAR:
03136 idx = 15;
03137 bitmask = 0x40;
03138 break;
03139 case CS_DATA_NOLBIN:
03140 idx = 15;
03141 bitmask = 0x80;
03142 break;
03143 case CS_DATA_NOCHAR:
03144 idx = 16;
03145 bitmask = 0x01;
03146 break;
03147 case CS_DATA_NOVCHAR:
03148 idx = 16;
03149 bitmask = 0x02;
03150 break;
03151 case CS_DATA_NOBIN:
03152 idx = 16;
03153 bitmask = 0x04;
03154 break;
03155 case CS_DATA_NOVBIN:
03156 idx = 16;
03157 bitmask = 0x08;
03158 break;
03159 case CS_DATA_NOMNY8:
03160 idx = 16;
03161 bitmask = 0x10;
03162 break;
03163 case CS_DATA_NOMNY4:
03164 idx = 16;
03165 bitmask = 0x20;
03166 break;
03167 case CS_DATA_NODATE8:
03168 idx = 16;
03169 bitmask = 0x40;
03170 break;
03171 case CS_DATA_NODATE4:
03172 idx = 16;
03173 bitmask = 0x80;
03174 break;
03175 case CS_RES_NOMSG:
03176 idx = 17;
03177 bitmask = 0x02;
03178 break;
03179 case CS_RES_NOEED:
03180 idx = 17;
03181 bitmask = 0x04;
03182 break;
03183 case CS_RES_NOPARAM:
03184 idx = 17;
03185 bitmask = 0x08;
03186 break;
03187 case CS_DATA_NOINT1:
03188 idx = 17;
03189 bitmask = 0x10;
03190 break;
03191 case CS_DATA_NOINT2:
03192 idx = 17;
03193 bitmask = 0x20;
03194 break;
03195 case CS_DATA_NOINT4:
03196 idx = 17;
03197 bitmask = 0x40;
03198 break;
03199 case CS_DATA_NOBIT:
03200 idx = 17;
03201 bitmask = 0x80;
03202 break;
03203 default:
03204 tdsdump_log(TDS_DBG_SEVERE, "ct_capability -- attempt to set/get a non-existant capability\n");
03205 return CS_FAIL;
03206 }
03207
03208 assert(13 <= idx && idx <= 17);
03209 assert(bitmask);
03210
03211 switch (action) {
03212 case CS_SET:
03213
03214 switch (*(CS_BOOL *) value) {
03215 case CS_TRUE:
03216 mask[idx] |= bitmask;
03217 break;
03218 case CS_FALSE:
03219 mask[idx] &= ~bitmask;
03220 break;
03221 default:
03222 tdsdump_log(TDS_DBG_SEVERE, "ct_capability -- unknown value\n");
03223 return CS_FAIL;
03224 }
03225 break;
03226 case CS_GET:
03227 *(CS_BOOL *) value = (mask[idx] & bitmask) ? CS_TRUE : CS_FALSE;
03228 break;
03229 default:
03230 tdsdump_log(TDS_DBG_SEVERE, "ct_capability -- unknown action\n");
03231 return CS_FAIL;
03232 }
03233 return CS_SUCCEED;
03234 }
03235
03236
03237
03238
03239
03240 switch (capability) {
03241 case CS_PROTO_DYNPROC:
03242 *(CS_BOOL *) value = mask[2] & 0x01 ? CS_TRUE : CS_FALSE;
03243 break;
03244 case CS_DATA_FLTN:
03245 *(CS_BOOL *) value = mask[2] & 0x02 ? CS_TRUE : CS_FALSE;
03246 break;
03247 case CS_DATA_BITN:
03248 *(CS_BOOL *) value = mask[2] & 0x04 ? CS_TRUE : CS_FALSE;
03249 break;
03250 case CS_DATA_INT8:
03251 *(CS_BOOL *) value = mask[2] & 0x08 ? CS_TRUE : CS_FALSE;
03252 break;
03253 case CS_DATA_VOID:
03254 *(CS_BOOL *) value = mask[2] & 0x10 ? CS_TRUE : CS_FALSE;
03255 break;
03256 case CS_CON_INBAND:
03257 *(CS_BOOL *) value = mask[3] & 0x01 ? CS_TRUE : CS_FALSE;
03258 break;
03259 case CS_CON_LOGICAL:
03260 *(CS_BOOL *) value = mask[3] & 0x02 ? CS_TRUE : CS_FALSE;
03261 break;
03262 case CS_PROTO_TEXT:
03263 *(CS_BOOL *) value = mask[3] & 0x04 ? CS_TRUE : CS_FALSE;
03264 break;
03265 case CS_PROTO_BULK:
03266 *(CS_BOOL *) value = mask[3] & 0x08 ? CS_TRUE : CS_FALSE;
03267 break;
03268 case CS_REQ_URGNOTIF:
03269 *(CS_BOOL *) value = mask[3] & 0x10 ? CS_TRUE : CS_FALSE;
03270 break;
03271 case CS_DATA_SENSITIVITY:
03272 *(CS_BOOL *) value = mask[3] & 0x20 ? CS_TRUE : CS_FALSE;
03273 break;
03274 case CS_DATA_BOUNDARY:
03275 *(CS_BOOL *) value = mask[3] & 0x40 ? CS_TRUE : CS_FALSE;
03276 break;
03277 case CS_PROTO_DYNAMIC:
03278 *(CS_BOOL *) value = mask[3] & 0x80 ? CS_TRUE : CS_FALSE;
03279 break;
03280 case CS_DATA_MONEYN:
03281 *(CS_BOOL *) value = mask[4] & 0x01 ? CS_TRUE : CS_FALSE;
03282 break;
03283 case CS_CSR_PREV:
03284 *(CS_BOOL *) value = mask[4] & 0x02 ? CS_TRUE : CS_FALSE;
03285 break;
03286 case CS_CSR_FIRST:
03287 *(CS_BOOL *) value = mask[4] & 0x04 ? CS_TRUE : CS_FALSE;
03288 break;
03289 case CS_CSR_LAST:
03290 *(CS_BOOL *) value = mask[4] & 0x08 ? CS_TRUE : CS_FALSE;
03291 break;
03292 case CS_CSR_ABS:
03293 *(CS_BOOL *) value = mask[4] & 0x10 ? CS_TRUE : CS_FALSE;
03294 break;
03295 case CS_CSR_REL:
03296 *(CS_BOOL *) value = mask[4] & 0x20 ? CS_TRUE : CS_FALSE;
03297 break;
03298 case CS_CSR_MULTI:
03299 *(CS_BOOL *) value = mask[4] & 0x40 ? CS_TRUE : CS_FALSE;
03300 break;
03301 case CS_CON_OOB:
03302 *(CS_BOOL *) value = mask[4] & 0x80 ? CS_TRUE : CS_FALSE;
03303 break;
03304 case CS_DATA_NUM:
03305 *(CS_BOOL *) value = mask[5] & 0x01 ? CS_TRUE : CS_FALSE;
03306 break;
03307 case CS_DATA_TEXT:
03308 *(CS_BOOL *) value = mask[5] & 0x02 ? CS_TRUE : CS_FALSE;
03309 break;
03310 case CS_DATA_IMAGE:
03311 *(CS_BOOL *) value = mask[5] & 0x04 ? CS_TRUE : CS_FALSE;
03312 break;
03313 case CS_DATA_DEC:
03314 *(CS_BOOL *) value = mask[5] & 0x08 ? CS_TRUE : CS_FALSE;
03315 break;
03316 case CS_DATA_LCHAR:
03317 *(CS_BOOL *) value = mask[5] & 0x10 ? CS_TRUE : CS_FALSE;
03318 break;
03319 case CS_DATA_LBIN:
03320 *(CS_BOOL *) value = mask[5] & 0x20 ? CS_TRUE : CS_FALSE;
03321 break;
03322 case CS_DATA_INTN:
03323 *(CS_BOOL *) value = mask[5] & 0x40 ? CS_TRUE : CS_FALSE;
03324 break;
03325 case CS_DATA_DATETIMEN:
03326 *(CS_BOOL *) value = mask[5] & 0x80 ? CS_TRUE : CS_FALSE;
03327 break;
03328 case CS_DATA_BIN:
03329 *(CS_BOOL *) value = mask[6] & 0x01 ? CS_TRUE : CS_FALSE;
03330 break;
03331 case CS_DATA_VBIN:
03332 *(CS_BOOL *) value = mask[6] & 0x02 ? CS_TRUE : CS_FALSE;
03333 break;
03334 case CS_DATA_MNY8:
03335 *(CS_BOOL *) value = mask[6] & 0x04 ? CS_TRUE : CS_FALSE;
03336 break;
03337 case CS_DATA_MNY4:
03338 *(CS_BOOL *) value = mask[6] & 0x08 ? CS_TRUE : CS_FALSE;
03339 break;
03340 case CS_DATA_DATE8:
03341 *(CS_BOOL *) value = mask[6] & 0x10 ? CS_TRUE : CS_FALSE;
03342 break;
03343 case CS_DATA_DATE4:
03344 *(CS_BOOL *) value = mask[6] & 0x20 ? CS_TRUE : CS_FALSE;
03345 break;
03346 case CS_DATA_FLT4:
03347 *(CS_BOOL *) value = mask[6] & 0x40 ? CS_TRUE : CS_FALSE;
03348 break;
03349 case CS_DATA_FLT8:
03350 *(CS_BOOL *) value = mask[6] & 0x80 ? CS_TRUE : CS_FALSE;
03351 break;
03352 case CS_REQ_MSG:
03353 *(CS_BOOL *) value = mask[7] & 0x01 ? CS_TRUE : CS_FALSE;
03354 break;
03355 case CS_REQ_PARAM:
03356 *(CS_BOOL *) value = mask[7] & 0x02 ? CS_TRUE : CS_FALSE;
03357 break;
03358 case CS_DATA_INT1:
03359 *(CS_BOOL *) value = mask[7] & 0x04 ? CS_TRUE : CS_FALSE;
03360 break;
03361 case CS_DATA_INT2:
03362 *(CS_BOOL *) value = mask[7] & 0x08 ? CS_TRUE : CS_FALSE;
03363 break;
03364 case CS_DATA_INT4:
03365 *(CS_BOOL *) value = mask[7] & 0x10 ? CS_TRUE : CS_FALSE;
03366 break;
03367 case CS_DATA_BIT:
03368 *(CS_BOOL *) value = mask[7] & 0x20 ? CS_TRUE : CS_FALSE;
03369 break;
03370 case CS_DATA_CHAR:
03371 *(CS_BOOL *) value = mask[7] & 0x40 ? CS_TRUE : CS_FALSE;
03372 break;
03373 case CS_DATA_VCHAR:
03374 *(CS_BOOL *) value = mask[7] & 0x80 ? CS_TRUE : CS_FALSE;
03375 break;
03376 case CS_REQ_LANG:
03377 *(CS_BOOL *) value = mask[8] & 0x02 ? CS_TRUE : CS_FALSE;
03378 break;
03379 case CS_REQ_RPC:
03380 *(CS_BOOL *) value = mask[8] & 0x04 ? CS_TRUE : CS_FALSE;
03381 break;
03382 case CS_REQ_NOTIF:
03383 *(CS_BOOL *) value = mask[8] & 0x08 ? CS_TRUE : CS_FALSE;
03384 break;
03385 case CS_REQ_MSTMT:
03386 *(CS_BOOL *) value = mask[8] & 0x10 ? CS_TRUE : CS_FALSE;
03387 break;
03388 case CS_REQ_BCP:
03389 *(CS_BOOL *) value = mask[8] & 0x20 ? CS_TRUE : CS_FALSE;
03390 break;
03391 case CS_REQ_CURSOR:
03392 *(CS_BOOL *) value = mask[8] & 0x40 ? CS_TRUE : CS_FALSE;
03393 break;
03394 case CS_REQ_DYN:
03395 *(CS_BOOL *) value = mask[8] & 0x80 ? CS_TRUE : CS_FALSE;
03396 break;
03397 default:
03398 tdsdump_log(TDS_DBG_SEVERE, "ct_capability -- attempt to get a non-existant capability\n");
03399 return CS_FAIL;
03400 break;
03401 }
03402
03403 assert(*(CS_BOOL *) value);
03404
03405
03406 if (type == CS_CAP_REQUEST && action == CS_GET) {
03407 tdsdump_log(TDS_DBG_INFO1, "ct_capability returns success, value %s\n",
03408 *(CS_BOOL *)value == CS_TRUE ? "TRUE" : "FALSE");
03409 return CS_SUCCEED;
03410 }
03411
03412 tdsdump_log(TDS_DBG_SEVERE, "ct_capability -- attempt to set a read-only capability (type %d, action %d)\n",
03413 type, action);
03414 return CS_FAIL;
03415 }
03416
03417
03418 CS_RETCODE
03419 ct_dynamic(CS_COMMAND * cmd, CS_INT type, CS_CHAR * id, CS_INT idlen, CS_CHAR * buffer, CS_INT buflen)
03420 {
03421 int query_len;
03422 CS_CONNECTION *con;
03423 CS_DYNAMIC *dyn;
03424
03425 if (!cmd->con)
03426 return CS_FAIL;
03427
03428 cmd->command_type = CS_DYNAMIC_CMD;
03429 cmd->dynamic_cmd = type;
03430
03431 tdsdump_log(TDS_DBG_FUNC, "ct_dynamic(%d)\n", type);
03432 con = cmd->con;
03433
03434 switch (type) {
03435 case CS_PREPARE:
03436
03437 dyn = _ct_allocate_dynamic(con, id, idlen);
03438
03439 if (dyn == NULL) {
03440 return CS_FAIL;
03441 }
03442
03443
03444 if (buflen == CS_NULLTERM) {
03445 query_len = strlen(buffer);
03446 } else {
03447 query_len = buflen;
03448 }
03449 dyn->stmt = (char *) malloc(query_len + 1);
03450 strncpy(dyn->stmt, (char *) buffer, query_len);
03451 dyn->stmt[query_len] = '\0';
03452
03453 cmd->dyn = dyn;
03454
03455 break;
03456 case CS_DEALLOC:
03457 cmd->dyn = _ct_locate_dynamic(con, id, idlen);
03458 if (cmd->dyn == NULL)
03459 return CS_FAIL;
03460 break;
03461 case CS_DESCRIBE_INPUT:
03462 case CS_DESCRIBE_OUTPUT:
03463 cmd->dyn = _ct_locate_dynamic(con, id, idlen);
03464 if (cmd->dyn == NULL)
03465 return CS_FAIL;
03466 break;
03467 case CS_EXECUTE:
03468 cmd->dyn = _ct_locate_dynamic(con, id, idlen);
03469 if (cmd->dyn == NULL)
03470 return CS_FAIL;
03471
03472 tdsdump_log(TDS_DBG_FUNC, "ct_dynamic() calling param_clear\n");
03473 param_clear(cmd->dyn->param_list);
03474 cmd->dyn->param_list = NULL;
03475 break;
03476 }
03477
03478 ct_set_command_state(cmd, _CS_COMMAND_READY);
03479 return CS_SUCCEED;
03480 }
03481
03482 CS_RETCODE
03483 ct_param(CS_COMMAND * cmd, CS_DATAFMT * datafmt, CS_VOID * data, CS_INT datalen, CS_SMALLINT indicator)
03484 {
03485 CSREMOTE_PROC *rpc;
03486 CS_DYNAMIC *dyn;
03487 CS_PARAM **pparam;
03488 CS_PARAM *param;
03489
03490
03491 tdsdump_log(TDS_DBG_FUNC, "ct_param()\n");
03492 tdsdump_log(TDS_DBG_INFO1, "ct_param() data addr = %p data length = %d\n", data, datalen);
03493
03494 if (cmd == NULL || cmd->con == NULL)
03495 return CS_FAIL;
03496
03497 if (datafmt->datatype == CS_VARCHAR_TYPE && IS_TDS7_PLUS(cmd->con->tds_socket))
03498 datafmt->datatype = CS_NVARCHAR_TYPE;
03499 if (datafmt->datatype == CS_LONGCHAR_TYPE && IS_TDS7_PLUS(cmd->con->tds_socket))
03500 datafmt->datatype = CS_NLONGCHAR_TYPE;
03501
03502 switch (cmd->command_type) {
03503 case CS_RPC_CMD:
03504 if (cmd->rpc == NULL) {
03505 fprintf(stdout, "RPC is NULL ct_param\n");
03506 return CS_FAIL;
03507 }
03508
03509 param = (CSREMOTE_PROC_PARAM *) malloc(sizeof(CSREMOTE_PROC_PARAM));
03510 if (!param)
03511 return CS_FAIL;
03512 memset(param, 0, sizeof(CSREMOTE_PROC_PARAM));
03513
03514 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, &datalen, &indicator, 1)) {
03515 tdsdump_log(TDS_DBG_INFO1, "ct_param() failed to add rpc param\n");
03516 tdsdump_log(TDS_DBG_INFO1, "ct_param() failed to add input value\n");
03517 free(param);
03518 return CS_FAIL;
03519 }
03520
03521 rpc = cmd->rpc;
03522 pparam = &rpc->param_list;
03523 while (*pparam) {
03524 pparam = &(*pparam)->next;
03525 }
03526
03527 *pparam = param;
03528 tdsdump_log(TDS_DBG_INFO1, " ct_param() added rpc parameter %s \n", (*param).name);
03529 return CS_SUCCEED;
03530 break;
03531
03532 case CS_LANG_CMD:
03533
03534 if (CS_INPUTVALUE != datafmt->status) {
03535 tdsdump_log(TDS_DBG_ERROR, "illegal datafmt->status(%d) passed to ct_param()\n", datafmt->status);
03536 return CS_FAIL;
03537 }
03538
03539 param = (CSREMOTE_PROC_PARAM *) malloc(sizeof(CSREMOTE_PROC_PARAM));
03540 memset(param, 0, sizeof(CSREMOTE_PROC_PARAM));
03541
03542 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, &datalen, &indicator, 1)) {
03543 free(param);
03544 return CS_FAIL;
03545 }
03546
03547 if (NULL == cmd->input_params)
03548 cmd->input_params = param;
03549 else {
03550 pparam = &cmd->input_params;
03551 while ((*pparam)->next)
03552 pparam = &(*pparam)->next;
03553 (*pparam)->next = param;
03554 }
03555 tdsdump_log(TDS_DBG_INFO1, "ct_param() added input value\n");
03556 return CS_SUCCEED;
03557 break;
03558
03559 case CS_DYNAMIC_CMD:
03560 if (cmd->dyn == NULL) {
03561 tdsdump_log(TDS_DBG_INFO1, "cmd->dyn is NULL ct_param\n");
03562 return CS_FAIL;
03563 }
03564
03565 param = (CS_DYNAMIC_PARAM *) malloc(sizeof(CS_DYNAMIC_PARAM));
03566 if (!param)
03567 return CS_FAIL;
03568 memset(param, 0, sizeof(CS_DYNAMIC_PARAM));
03569
03570 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, &datalen, &indicator, 1)) {
03571 tdsdump_log(TDS_DBG_INFO1, "ct_param() failed to add CS_DYNAMIC param\n");
03572 free(param);
03573 return CS_FAIL;
03574 }
03575
03576 dyn = cmd->dyn;
03577 pparam = &dyn->param_list;
03578 while (*pparam) {
03579 pparam = &(*pparam)->next;
03580 }
03581
03582 *pparam = param;
03583 return CS_SUCCEED;
03584 break;
03585 }
03586 return CS_FAIL;
03587 }
03588
03589 CS_RETCODE
03590 ct_setparam(CS_COMMAND * cmd, CS_DATAFMT * datafmt, CS_VOID * data, CS_INT * datalen, CS_SMALLINT * indicator)
03591 {
03592 CSREMOTE_PROC *rpc;
03593 CS_PARAM **pparam;
03594 CS_PARAM *param;
03595 CS_DYNAMIC *dyn;
03596
03597 tdsdump_log(TDS_DBG_FUNC, "ct_setparam() command type = %d, data type = %d\n", cmd->command_type, datafmt->datatype);
03598
03599
03600
03601
03602 if (cmd == NULL)
03603 return CS_FAIL;
03604
03605 switch (cmd->command_type) {
03606
03607 case CS_RPC_CMD:
03608
03609 if (cmd->rpc == NULL) {
03610 fprintf(stdout, "RPC is NULL ct_param\n");
03611 return CS_FAIL;
03612 }
03613
03614 param = (CSREMOTE_PROC_PARAM *) malloc(sizeof(CSREMOTE_PROC_PARAM));
03615 memset(param, 0, sizeof(CSREMOTE_PROC_PARAM));
03616
03617 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, datalen, indicator, 0)) {
03618 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() failed to add rpc param\n");
03619 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() failed to add input value\n");
03620 free(param);
03621 return CS_FAIL;
03622 }
03623
03624 rpc = cmd->rpc;
03625 pparam = &rpc->param_list;
03626 tdsdump_log(TDS_DBG_INFO1, " ct_setparam() reached here\n");
03627 if (*pparam != NULL) {
03628 while ((*pparam)->next != NULL) {
03629 pparam = &(*pparam)->next;
03630 }
03631
03632 pparam = &(*pparam)->next;
03633 }
03634 *pparam = param;
03635 param->next = NULL;
03636 tdsdump_log(TDS_DBG_INFO1, " ct_setparam() added parameter %s \n", (*param).name);
03637 return CS_SUCCEED;
03638 break;
03639
03640 case CS_DYNAMIC_CMD :
03641
03642 if (cmd->dyn == NULL) {
03643 fprintf(stdout, "cmd->dyn is NULL ct_param\n");
03644 return CS_FAIL;
03645 }
03646
03647 param = (CS_DYNAMIC_PARAM *) malloc(sizeof(CS_DYNAMIC_PARAM));
03648 memset(param, 0, sizeof(CS_DYNAMIC_PARAM));
03649
03650 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, datalen, indicator, 0)) {
03651 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() failed to add dynamic param\n");
03652 free(param);
03653 return CS_FAIL;
03654 }
03655
03656 dyn = cmd->dyn;
03657 pparam = &dyn->param_list;
03658 if (*pparam != NULL) {
03659 while ((*pparam)->next != NULL) {
03660 pparam = &(*pparam)->next;
03661 }
03662
03663 pparam = &(*pparam)->next;
03664 }
03665 *pparam = param;
03666 param->next = NULL;
03667 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() added dynamic parameter\n");
03668 return CS_SUCCEED;
03669 break;
03670
03671 case CS_LANG_CMD:
03672
03673
03674 if (CS_INPUTVALUE != datafmt->status) {
03675 tdsdump_log(TDS_DBG_ERROR, "illegal datafmt->status(%d) passed to ct_setparam()\n", datafmt->status);
03676 return CS_FAIL;
03677 }
03678
03679 param = (CSREMOTE_PROC_PARAM *) malloc(sizeof(CSREMOTE_PROC_PARAM));
03680 memset(param, 0, sizeof(CSREMOTE_PROC_PARAM));
03681
03682 if (CS_SUCCEED != _ct_fill_param(cmd->command_type, param, datafmt, data, datalen, indicator, 0)) {
03683 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() failed to add language param\n");
03684 free(param);
03685 return CS_FAIL;
03686 }
03687
03688 if (NULL == cmd->input_params)
03689 cmd->input_params = param;
03690 else {
03691 pparam = &cmd->input_params;
03692 while ((*pparam)->next)
03693 pparam = &(*pparam)->next;
03694 (*pparam)->next = param;
03695 }
03696 tdsdump_log(TDS_DBG_INFO1, "ct_setparam() added language parameter\n");
03697 return CS_SUCCEED;
03698 break;
03699 }
03700 return CS_FAIL;
03701 }
03702
03703 CS_RETCODE
03704 ct_options(CS_CONNECTION * con, CS_INT action, CS_INT option, CS_VOID * param, CS_INT paramlen, CS_INT * outlen)
03705 {
03706 TDS_OPTION_CMD tds_command = 0;
03707 TDS_OPTION tds_option = 0;
03708 TDS_OPTION_ARG tds_argument;
03709 TDS_INT tds_argsize = 0;
03710 TDSSOCKET *tds;
03711
03712 const char *action_string = NULL;
03713 int i;
03714
03715
03716 static const struct TDS_BOOL_OPTION_MAP
03717 {
03718 CS_INT option;
03719 TDS_OPTION tds_option;
03720 } tds_bool_option_map[] = {
03721 { CS_OPT_ANSINULL, TDS_OPT_ANSINULL }
03722 , { CS_OPT_CHAINXACTS, TDS_OPT_CHAINXACTS }
03723 , { CS_OPT_CURCLOSEONXACT, TDS_OPT_CURCLOSEONXACT }
03724 , { CS_OPT_FIPSFLAG, TDS_OPT_FIPSFLAG }
03725 , { CS_OPT_FORCEPLAN, TDS_OPT_FORCEPLAN }
03726 , { CS_OPT_FORMATONLY, TDS_OPT_FORMATONLY }
03727 , { CS_OPT_GETDATA, TDS_OPT_GETDATA }
03728 , { CS_OPT_NOCOUNT, TDS_OPT_NOCOUNT }
03729 , { CS_OPT_NOEXEC, TDS_OPT_NOEXEC }
03730 , { CS_OPT_PARSEONLY, TDS_OPT_PARSEONLY }
03731 , { CS_OPT_QUOTED_IDENT, TDS_OPT_QUOTED_IDENT }
03732 , { CS_OPT_RESTREES, TDS_OPT_RESTREES }
03733 , { CS_OPT_SHOWPLAN, TDS_OPT_SHOWPLAN }
03734 , { CS_OPT_STATS_IO, TDS_OPT_STAT_IO }
03735 , { CS_OPT_STATS_TIME, TDS_OPT_STAT_TIME }
03736 };
03737
03738 if (param == NULL)
03739 return CS_FAIL;
03740
03741 tds = con->tds_socket;
03742
03743
03744
03745
03746 switch (action) {
03747 case CS_GET:
03748 tds_command = TDS_OPT_LIST;
03749 action_string = "CS_GET";
03750 tds_argsize = 0;
03751 break;
03752 case CS_SET:
03753 tds_command = TDS_OPT_SET;
03754 action_string = "CS_SET";
03755 break;
03756 case CS_CLEAR:
03757 tds_command = TDS_OPT_DEFAULT;
03758 action_string = "CS_CLEAR";
03759 tds_argsize = 0;
03760 break;
03761 default:
03762 tdsdump_log(TDS_DBG_FUNC, "ct_options: invalid action = %d\n", action);
03763 return CS_FAIL;
03764 }
03765
03766 assert(tds_command && action_string);
03767
03768 tdsdump_log(TDS_DBG_FUNC, "ct_options: %s, option = %d\n", action_string, option);
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786 for (i = 0; i < TDS_VECTOR_SIZE(tds_bool_option_map); i++) {
03787 if (tds_bool_option_map[i].option == option) {
03788 tds_option = tds_bool_option_map[i].tds_option;
03789 break;
03790 }
03791 }
03792
03793 if (tds_option != 0) {
03794 if (action == CS_SET) {
03795 switch (*(CS_BOOL *) param) {
03796 case CS_TRUE:
03797 tds_argument.ti = 1;
03798 break;
03799 case CS_FALSE:
03800 tds_argument.ti = 0;
03801 break;
03802 default:
03803 return CS_FAIL;
03804 }
03805 tds_argsize = 1;
03806 }
03807 if (action == CS_GET) {
03808 tds_argsize = 0;
03809 }
03810 goto SEND_OPTION;
03811 }
03812
03813
03814
03815
03816 switch (option) {
03817 case CS_OPT_ANSIPERM:
03818 case CS_OPT_STR_RTRUNC:
03819
03820 switch (*(CS_BOOL *) param) {
03821 case CS_TRUE:
03822 case CS_FALSE:
03823 break;
03824 default:
03825 if (action == CS_SET)
03826 return CS_FAIL;
03827 }
03828 break;
03829 case CS_OPT_ARITHABORT:
03830 switch (*(CS_BOOL *) param) {
03831 case CS_TRUE:
03832 tds_option = TDS_OPT_ARITHABORTON;
03833 break;
03834 case CS_FALSE:
03835 tds_option = TDS_OPT_ARITHABORTOFF;
03836 break;
03837 default:
03838 if (action == CS_SET)
03839 return CS_FAIL;
03840 tds_option = TDS_OPT_ARITHABORTON;
03841 }
03842 tds_argument.ti = TDS_OPT_ARITHOVERFLOW | TDS_OPT_NUMERICTRUNC;
03843 tds_argsize = (action == CS_SET) ? 1 : 0;
03844 break;
03845 case CS_OPT_ARITHIGNORE:
03846 switch (*(CS_BOOL *) param) {
03847 case CS_TRUE:
03848 tds_option = TDS_OPT_ARITHIGNOREON;
03849 break;
03850 case CS_FALSE:
03851 tds_option = TDS_OPT_ARITHIGNOREOFF;
03852 break;
03853 default:
03854 if (action == CS_SET)
03855 return CS_FAIL;
03856 }
03857 tds_argument.i = TDS_OPT_ARITHOVERFLOW | TDS_OPT_NUMERICTRUNC;
03858 tds_argsize = (action == CS_SET) ? 4 : 0;
03859 break;
03860 case CS_OPT_AUTHOFF:
03861 tds_option = TDS_OPT_AUTHOFF;
03862 tds_argument.c = (TDS_CHAR *) param;
03863 tds_argsize = (action == CS_SET) ? paramlen : 0;
03864 break;
03865 case CS_OPT_AUTHON:
03866 tds_option = TDS_OPT_AUTHON;
03867 tds_argument.c = (TDS_CHAR *) param;
03868 tds_argsize = (action == CS_SET) ? paramlen : 0;
03869 break;
03870
03871 case CS_OPT_DATEFIRST:
03872 tds_option = TDS_OPT_DATEFIRST;
03873 switch (*(CS_INT *) param) {
03874 case CS_OPT_SUNDAY:
03875 tds_argument.ti = TDS_OPT_SUNDAY;
03876 break;
03877 case CS_OPT_MONDAY:
03878 tds_argument.ti = TDS_OPT_MONDAY;
03879 break;
03880 case CS_OPT_TUESDAY:
03881 tds_argument.ti = TDS_OPT_TUESDAY;
03882 break;
03883 case CS_OPT_WEDNESDAY:
03884 tds_argument.ti = TDS_OPT_WEDNESDAY;
03885 break;
03886 case CS_OPT_THURSDAY:
03887 tds_argument.ti = TDS_OPT_THURSDAY;
03888 break;
03889 case CS_OPT_FRIDAY:
03890 tds_argument.ti = TDS_OPT_FRIDAY;
03891 break;
03892 case CS_OPT_SATURDAY:
03893 tds_argument.ti = TDS_OPT_SATURDAY;
03894 break;
03895 default:
03896 if (action == CS_SET)
03897 return CS_FAIL;
03898 }
03899 tds_argsize = (action == CS_SET) ? 1 : 0;
03900 break;
03901 case CS_OPT_DATEFORMAT:
03902 tds_option = TDS_OPT_DATEFORMAT;
03903 switch (*(CS_INT *) param) {
03904 case CS_OPT_FMTMDY:
03905 tds_argument.ti = TDS_OPT_FMTMDY;
03906 break;
03907 case CS_OPT_FMTDMY:
03908 tds_argument.ti = TDS_OPT_FMTDMY;
03909 break;
03910 case CS_OPT_FMTYMD:
03911 tds_argument.ti = TDS_OPT_FMTYMD;
03912 break;
03913 case CS_OPT_FMTYDM:
03914 tds_argument.ti = TDS_OPT_FMTYDM;
03915 break;
03916 case CS_OPT_FMTMYD:
03917 tds_argument.ti = TDS_OPT_FMTMYD;
03918 break;
03919 case CS_OPT_FMTDYM:
03920 tds_argument.ti = TDS_OPT_FMTDYM;
03921 break;
03922 default:
03923 if (action == CS_SET)
03924 return CS_FAIL;
03925 }
03926 tds_argsize = (action == CS_SET) ? 1 : 0;
03927 break;
03928 case CS_OPT_ISOLATION:
03929 tds_option = TDS_OPT_ISOLATION;
03930 switch (*(char *) param) {
03931 case CS_OPT_LEVEL0:
03932
03933 tds_option = 0;
03934 tds_argument.ti = 0;
03935 break;
03936 case CS_OPT_LEVEL1:
03937 tds_argument.ti = TDS_OPT_LEVEL1;
03938 case CS_OPT_LEVEL3:
03939 tds_argument.ti = TDS_OPT_LEVEL3;
03940 break;
03941 default:
03942 if (action == CS_SET)
03943 return CS_FAIL;
03944 }
03945 tds_argsize = (action == CS_SET) ? 1 : 0;
03946 break;
03947 case CS_OPT_TRUNCIGNORE:
03948 tds_option = TDS_OPT_TRUNCABORT;
03949 switch (*(CS_BOOL *) param) {
03950 case CS_TRUE:
03951 case CS_FALSE:
03952 break;
03953 default:
03954 if (action == CS_SET)
03955 return CS_FAIL;
03956 }
03957 tds_argument.ti = !*(char *) param;
03958 tds_argsize = (action == CS_SET) ? 1 : 0;
03959 break;
03960 default:
03961 return CS_FAIL;
03962 }
03963
03964 SEND_OPTION:
03965
03966 tdsdump_log(TDS_DBG_FUNC, "\ttds_submit_optioncmd will be action(%s) option(%d) arg(%x) arglen(%d)\n",
03967 action_string, tds_option, tds_argsize == 1 ? tds_argument.ti : (tds_argsize == 4 ? tds_argument.i : 0), tds_argsize);
03968
03969 if (tds_submit_optioncmd(tds, tds_command, tds_option, &tds_argument, tds_argsize) == TDS_FAIL) {
03970 return CS_FAIL;
03971 }
03972
03973 if (action == CS_GET) {
03974 switch (option) {
03975 case CS_OPT_ANSINULL :
03976 case CS_OPT_CHAINXACTS :
03977 case CS_OPT_CURCLOSEONXACT :
03978 case CS_OPT_NOCOUNT :
03979 case CS_OPT_QUOTED_IDENT :
03980 *(CS_BOOL *)param = tds->option_value;
03981 break;
03982 case CS_OPT_DATEFIRST:
03983 switch (tds->option_value) {
03984 case TDS_OPT_SUNDAY: *(CS_INT *)param = CS_OPT_SUNDAY; break;
03985 case TDS_OPT_MONDAY: *(CS_INT *)param = CS_OPT_MONDAY; break;
03986 case TDS_OPT_TUESDAY: *(CS_INT *)param = CS_OPT_TUESDAY; break;
03987 case TDS_OPT_WEDNESDAY: *(CS_INT *)param = CS_OPT_WEDNESDAY; break;
03988 case TDS_OPT_THURSDAY: *(CS_INT *)param = CS_OPT_THURSDAY; break;
03989 case TDS_OPT_FRIDAY: *(CS_INT *)param = CS_OPT_FRIDAY; break;
03990 case TDS_OPT_SATURDAY: *(CS_INT *)param = CS_OPT_SATURDAY; break;
03991 default: return CS_FAIL;
03992 }
03993 break;
03994 case CS_OPT_DATEFORMAT:
03995 switch (tds->option_value) {
03996 case TDS_OPT_FMTDMY: *(CS_INT *)param = CS_OPT_FMTDMY; break;
03997 case TDS_OPT_FMTDYM: *(CS_INT *)param = CS_OPT_FMTDYM; break;
03998 case TDS_OPT_FMTMDY: *(CS_INT *)param = CS_OPT_FMTMDY; break;
03999 case TDS_OPT_FMTMYD: *(CS_INT *)param = CS_OPT_FMTMYD; break;
04000 case TDS_OPT_FMTYMD: *(CS_INT *)param = CS_OPT_FMTYMD; break;
04001 case TDS_OPT_FMTYDM: *(CS_INT *)param = CS_OPT_FMTYDM; break;
04002 default: return CS_FAIL;
04003 }
04004 break;
04005 case CS_OPT_ARITHABORT :
04006 case CS_OPT_ARITHIGNORE :
04007 *(CS_BOOL *)param = tds->option_value;
04008 break;
04009 case CS_OPT_TRUNCIGNORE :
04010 break;
04011 }
04012 }
04013
04014 return CS_SUCCEED;
04015 }
04016
04017 CS_RETCODE
04018 ct_poll(CS_CONTEXT * ctx, CS_CONNECTION * connection, CS_INT milliseconds, CS_CONNECTION ** compconn, CS_COMMAND ** compcmd,
04019 CS_INT * compid, CS_INT * compstatus)
04020 {
04021 tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED ct_poll()\n");
04022 return CS_FAIL;
04023 }
04024
04025 static
04026 int str_icmp(char* s1, char* s2, int len)
04027 {
04028 int i;
04029
04030 for (i = 0; i < len; ++i) {
04031 char c1 = s1[i];
04032 char c2 = s2[i];
04033
04034 if (c1 >= 'a' && c1 <= 'z') {
04035 c1 -= 'a'-'A';
04036 }
04037
04038 if (c2 >= 'a' && c2 <= 'z') {
04039 c2 -= 'a'-'A';
04040 }
04041
04042 if (c1 == c2) {
04043 if (c1 == '\0') {
04044 return 0;
04045 }
04046 } else {
04047 if (c1 < c2) {
04048 return -1;
04049 } else {
04050 return 1;
04051 }
04052 }
04053 }
04054
04055 return 0;
04056 }
04057
04058 static
04059 char* get_next_tok(char* str, char* delimiter, char **ptrptr)
04060 {
04061 char* result = NULL;
04062 *ptrptr = NULL;
04063
04064 if (str && delimiter) {
04065 size_t str_len = strlen(str);
04066
04067 size_t pos = strspn(str, delimiter);
04068
04069 if (pos == 0) {
04070 *ptrptr = strpbrk(str, delimiter);
04071 return str;
04072 } else {
04073 if (pos != str_len) {
04074 result = str + pos;
04075 *ptrptr = strpbrk(result, delimiter);
04076 }
04077 }
04078 }
04079
04080 return result;
04081 }
04082
04083 CS_RETCODE
04084 ct_cursor(CS_COMMAND * cmd, CS_INT type, CS_CHAR * name, CS_INT namelen, CS_CHAR * text, CS_INT tlen, CS_INT option)
04085 {
04086 TDSSOCKET *tds;
04087 TDSCURSOR *cursor;
04088
04089 if (!cmd->con || !cmd->con->tds_socket)
04090 return CS_FAIL;
04091
04092 tds = cmd->con->tds_socket;
04093 cmd->command_type = CS_CUR_CMD;
04094
04095 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : type = %d \n", type);
04096
04097 switch (type) {
04098 case CS_CURSOR_DECLARE:
04099
04100 cursor = tds_alloc_cursor(tds, name, namelen == CS_NULLTERM ? strlen(name) + 1 : namelen,
04101 text, tlen == CS_NULLTERM ? strlen(text) + 1 : tlen);
04102 if (!cursor)
04103 return CS_FAIL;
04104
04105 cursor->cursor_rows = 1;
04106 cursor->options = option;
04107 cursor->status.declare = _CS_CURS_TYPE_REQUESTED;
04108 cursor->status.cursor_row = _CS_CURS_TYPE_UNACTIONED;
04109 cursor->status.open = _CS_CURS_TYPE_UNACTIONED;
04110 cursor->status.fetch = _CS_CURS_TYPE_UNACTIONED;
04111 cursor->status.close = _CS_CURS_TYPE_UNACTIONED;
04112 cursor->status.dealloc = _CS_CURS_TYPE_UNACTIONED;
04113
04114
04115 if (option == CS_UNUSED || (option & CS_END) != 0) {
04116
04117 char delimiter[] = "\n\t,.[]() ";
04118 int state = 0;
04119 char* savept = NULL;
04120 char* s = text;
04121
04122 char* tok = get_next_tok(s, delimiter, &savept);
04123 while (tok != NULL) {
04124 s = savept;
04125
04126 if (str_icmp(tok, "FOR", 3) == 0) {
04127 state = 1;
04128 } else if (str_icmp(tok, "UPDATE", 6) == 0) {
04129 if (state == 1) {
04130 state = 2;
04131 break;
04132 }
04133 } else {
04134 state = 0;
04135 }
04136
04137 tok = get_next_tok(s, delimiter, &savept);
04138 }
04139
04140 if (state == 2) {
04141
04142 cursor->type = 0x4;
04143 } else {
04144
04145 cursor->type = 0x1;
04146 }
04147 } else if ((option & CS_FOR_UPDATE) != 0) {
04148 cursor->type = 0x4;
04149 } else {
04150 cursor->type = 0x1;
04151 }
04152
04153 cursor->concurrency = 0x2000 | 0x4;
04154
04155 cmd->cursor = cursor;
04156 ct_set_command_state(cmd, _CS_COMMAND_READY);
04157 return CS_SUCCEED;
04158 break;
04159
04160 case CS_CURSOR_ROWS:
04161
04162 cursor = cmd->cursor;
04163 if (!cursor) {
04164 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not present\n");
04165 return CS_FAIL;
04166 }
04167
04168 if (cursor->status.declare == _CS_CURS_TYPE_REQUESTED ||
04169 cursor->status.declare == _CS_CURS_TYPE_SENT) {
04170
04171 cursor->cursor_rows = option;
04172 cursor->status.cursor_row = _CS_CURS_TYPE_REQUESTED;
04173
04174 ct_set_command_state(cmd, _CS_COMMAND_READY);
04175 return CS_SUCCEED;
04176 }
04177 else {
04178 cursor->status.cursor_row = _CS_CURS_TYPE_UNACTIONED;
04179 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not declared\n");
04180 return CS_FAIL;
04181 }
04182 break;
04183
04184 case CS_CURSOR_OPEN:
04185
04186 cursor = cmd->cursor;
04187 if (!cursor) {
04188 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not present\n");
04189 return CS_FAIL;
04190 }
04191
04192 if (cursor->status.declare == _CS_CURS_TYPE_REQUESTED ||
04193 cursor->status.declare == _CS_CURS_TYPE_SENT ) {
04194
04195 cursor->status.open = _CS_CURS_TYPE_REQUESTED;
04196
04197 return CS_SUCCEED;
04198 ct_set_command_state(cmd, _CS_COMMAND_READY);
04199 }
04200 else {
04201 cursor->status.open = _CS_CURS_TYPE_UNACTIONED;
04202 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not declared\n");
04203 return CS_FAIL;
04204 }
04205
04206 break;
04207
04208 case CS_CURSOR_CLOSE:
04209
04210 cursor = cmd->cursor;
04211 if (!cursor) {
04212 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not present\n");
04213 return CS_FAIL;
04214 }
04215
04216 cursor->status.cursor_row = _CS_CURS_TYPE_UNACTIONED;
04217 cursor->status.open = _CS_CURS_TYPE_UNACTIONED;
04218 cursor->status.fetch = _CS_CURS_TYPE_UNACTIONED;
04219 cursor->status.close = _CS_CURS_TYPE_REQUESTED;
04220 if (option == CS_DEALLOC) {
04221 cursor->status.dealloc = _CS_CURS_TYPE_REQUESTED;
04222 }
04223 ct_set_command_state(cmd, _CS_COMMAND_READY);
04224 return CS_SUCCEED;
04225
04226 case CS_CURSOR_DEALLOC:
04227
04228 cursor = cmd->cursor;
04229 if (!cursor) {
04230 tdsdump_log(TDS_DBG_FUNC, "ct_cursor() : cursor not present\n");
04231 return CS_FAIL;
04232 }
04233 cursor->status.dealloc = _CS_CURS_TYPE_REQUESTED;
04234 ct_set_command_state(cmd, _CS_COMMAND_READY);
04235 return CS_SUCCEED;
04236
04237 case CS_IMPLICIT_CURSOR:
04238 tdsdump_log(TDS_DBG_INFO1, "CS_IMPLICIT_CURSOR: Option not implemented\n");
04239 return CS_FAIL;
04240 case CS_CURSOR_OPTION:
04241 tdsdump_log(TDS_DBG_INFO1, "CS_CURSOR_OPTION: Option not implemented\n");
04242 return CS_FAIL;
04243 case CS_CURSOR_UPDATE:
04244 tdsdump_log(TDS_DBG_INFO1, "CS_CURSOR_UPDATE: Option not implemented\n");
04245 return CS_FAIL;
04246 case CS_CURSOR_DELETE:
04247 tdsdump_log(TDS_DBG_INFO1, "CS_CURSOR_DELETE: Option not implemented\n");
04248 return CS_FAIL;
04249
04250 }
04251
04252 return CS_FAIL;
04253 }
04254
04255 static int
04256 _ct_fetchable_results(CS_COMMAND * cmd)
04257 {
04258 switch (cmd->curr_result_type) {
04259 case CS_COMPUTE_RESULT:
04260 case CS_CURSOR_RESULT:
04261 case CS_PARAM_RESULT:
04262 case CS_ROW_RESULT:
04263 case CS_STATUS_RESULT:
04264 return 1;
04265 }
04266 return 0;
04267 }
04268
04269 static int
04270 _ct_process_return_status(TDSSOCKET * tds)
04271 {
04272 TDSRESULTINFO *info;
04273 TDSCOLUMN *curcol;
04274 TDS_INT saved_status;
04275
04276 enum
04277 { num_cols = 1 };
04278
04279 assert(tds);
04280 saved_status = tds->ret_status;
04281 tds_free_all_results(tds);
04282
04283
04284 tds->current_results = tds->res_info = tds_alloc_results(num_cols);
04285
04286 if (!tds->res_info)
04287 return TDS_FAIL;
04288
04289 info = tds->res_info;
04290
04291 curcol = info->columns[0];
04292
04293 tds_set_column_type(tds, curcol, SYBINT4);
04294
04295 tdsdump_log(TDS_DBG_INFO1, "generating return status row. type = %d(%s), varint_size %d\n",
04296 curcol->column_type, tds_prtype(curcol->column_type), curcol->column_varint_size);
04297
04298 tds_add_row_column_size(info, curcol);
04299
04300 info->current_row = tds_alloc_row(info);
04301
04302 if (!info->current_row)
04303 return TDS_FAIL;
04304
04305 assert(0 <= curcol->column_offset && curcol->column_offset < info->row_size);
04306
04307 *(TDS_INT *) (info->current_row + curcol->column_offset) = saved_status;
04308
04309 return TDS_SUCCEED;
04310 }
04311
04312
04313
04314
04315 static const unsigned char *
04316 paramrowalloc(TDSPARAMINFO * params, TDSCOLUMN * curcol, int param_num, void *value, int size)
04317 {
04318 const unsigned char *row = tds_alloc_param_row(params, curcol);
04319
04320 tdsdump_log(TDS_DBG_INFO1, "paramrowalloc, size = %d, offset = %d, row_size = %d\n",
04321 size, curcol->column_offset,
04322 params->row_size);
04323 if (!row)
04324 return NULL;
04325
04326 if (value) {
04327
04328 if (size > curcol->column_size)
04329 size = curcol->column_size;
04330
04331 if (is_blob_type(curcol->column_type)) {
04332 TDSBLOB *blob = ¶ms->current_row[curcol->column_offset];
04333 blob->textvalue = (TDS_CHAR *) malloc(size);
04334 memcpy(blob->textvalue, value, size);
04335 }
04336 else {
04337 memcpy(¶ms->current_row[curcol->column_offset], value, size);
04338 }
04339 curcol->column_cur_size = size;
04340 } else {
04341 tdsdump_log(TDS_DBG_FUNC, "paramrowalloc(): setting parameter #%d to NULL\n", param_num);
04342 curcol->column_cur_size = -1;
04343 }
04344
04345 return row;
04346 }
04347
04348
04349
04350
04351 static TDSPARAMINFO *
04352 paraminfoalloc(TDSSOCKET * tds, CS_PARAM * first_param)
04353 {
04354 int i;
04355 CS_PARAM *p;
04356 TDSCOLUMN *pcol;
04357 TDSPARAMINFO *params = NULL;
04358
04359 int temp_type;
04360 CS_BYTE *temp_value;
04361 CS_INT temp_datalen;
04362 int param_is_null;
04363
04364
04365
04366 if (first_param == NULL)
04367 return NULL;
04368
04369 for (i = 0, p = first_param; p != NULL; p = p->next, i++) {
04370 const unsigned char *prow;
04371
04372 if (!(params = tds_alloc_param_result(params))) {
04373 _csclient_msg(((CS_CONNECTION*)tds->parent)->ctx, "paraminfoalloc", 2, 1, 17, 33, "");
04374 return NULL;
04375 }
04376
04377
04378
04379
04380 if (p->param_by_value == 0) {
04381
04382 param_is_null = 0;
04383 temp_datalen = 0;
04384 temp_value = NULL;
04385 temp_type = p->type;
04386
04387
04388
04389 if (*(p->ind) == -1) {
04390 temp_value = NULL;
04391 temp_datalen = 0;
04392 param_is_null = 1;
04393 } else {
04394
04395
04396 if ((*(p->datalen) == 0 || *(p->datalen) == CS_UNUSED) && p->value == NULL) {
04397 temp_value = NULL;
04398 temp_datalen = 0;
04399 param_is_null = 1;
04400 } else {
04401
04402
04403
04404 if (is_fixed_type(temp_type)) {
04405 temp_datalen = tds_get_size_by_type(temp_type);
04406 } else {
04407 temp_datalen = (*(p->datalen) == CS_UNUSED) ? 0 : *(p->datalen);
04408 }
04409
04410 if (temp_datalen && p->value) {
04411 temp_value = p->value;
04412 } else {
04413 temp_value = NULL;
04414 temp_datalen = 0;
04415 param_is_null = 1;
04416 }
04417 }
04418 }
04419
04420 if (param_is_null) {
04421 switch (temp_type) {
04422 case SYBINT1:
04423 case SYBINT2:
04424 case SYBINT4:
04425
04426 case SYBINT8:
04427 temp_type = SYBINTN;
04428 break;
04429 case SYBDATETIME:
04430 case SYBDATETIME4:
04431 temp_type = SYBDATETIMN;
04432 break;
04433 case SYBFLT8:
04434 temp_type = SYBFLTN;
04435 break;
04436 case SYBBIT:
04437 temp_type = SYBBITN;
04438 break;
04439 case SYBMONEY:
04440 case SYBMONEY4:
04441 temp_type = SYBMONEYN;
04442 break;
04443 default:
04444 break;
04445 }
04446 }
04447 } else {
04448 temp_type = p->type;
04449 temp_value = p->value;
04450 temp_datalen = *(p->datalen);
04451 }
04452
04453 pcol = params->columns[i];
04454
04455
04456 pcol->column_namelen = 0;
04457 if (p->name) {
04458 tds_strlcpy(pcol->column_name, p->name, sizeof(pcol->column_name));
04459 pcol->column_namelen = strlen(pcol->column_name);
04460 }
04461
04462 if (p->status == CS_RETURN)
04463 pcol->column_output = 1;
04464 else
04465 pcol->column_output = 0;
04466
04467 tds_set_param_type(tds, pcol, temp_type);
04468
04469 if (temp_datalen == CS_NULLTERM && temp_value)
04470 temp_datalen = strlen((const char*) temp_value);
04471
04472 pcol->column_prec = p->precision;
04473 pcol->column_scale = p->scale;
04474 if (pcol->column_varint_size) {
04475 if (p->maxlen < 0)
04476 return NULL;
04477 pcol->on_server.column_size = pcol->column_size = p->maxlen;
04478 pcol->column_cur_size = temp_datalen;
04479 if (temp_datalen > 0 && temp_datalen > p->maxlen)
04480 pcol->on_server.column_size = pcol->column_size = temp_datalen;
04481 } else {
04482 pcol->column_cur_size = pcol->column_size;
04483 }
04484
04485
04486 tdsdump_log(TDS_DBG_FUNC, "paraminfoalloc: status = %d, maxlen %d \n", p->status, p->maxlen);
04487 tdsdump_log(TDS_DBG_FUNC,
04488 "paraminfoalloc: name = %*.*s, varint size %d column_type %d size %d, %d column_cur_size %d column_output = %d\n",
04489 pcol->column_namelen, pcol->column_namelen, pcol->column_name,
04490 pcol->column_varint_size, pcol->column_type,
04491 pcol->on_server.column_size, pcol->column_size,
04492 pcol->column_cur_size, pcol->column_output);
04493 prow = paramrowalloc(params, pcol, i, temp_value, temp_datalen);
04494 if (!prow) {
04495 _csclient_msg(((CS_CONNECTION*)tds->parent)->ctx, "paraminfoalloc", 2, 1, 17, 33, "");
04496 return NULL;
04497 }
04498 }
04499
04500 return params;
04501
04502 }
04503
04504 static void
04505 rpc_clear(CSREMOTE_PROC * rpc)
04506 {
04507 if (rpc == NULL)
04508 return;
04509
04510 param_clear(rpc->param_list);
04511
04512 assert(rpc->name);
04513 free(rpc->name);
04514 free(rpc);
04515 }
04516
04517
04518
04519
04520 static void
04521 param_clear(CS_PARAM * pparam)
04522 {
04523 if (pparam == NULL)
04524 return;
04525
04526 if (pparam->next) {
04527 param_clear(pparam->next);
04528 pparam->next = NULL;
04529 }
04530
04531
04532
04533 if (pparam->name)
04534 free(pparam->name);
04535 if (pparam->param_by_value)
04536 free(pparam->value);
04537
04538
04539
04540
04541
04542
04543 free(pparam);
04544 }
04545
04546
04547
04548
04549 static int
04550 _ct_fill_param(CS_INT cmd_type, CS_PARAM * param, CS_DATAFMT * datafmt, CS_VOID * data, CS_INT * datalen, CS_SMALLINT * indicator, CS_BYTE byvalue)
04551 {
04552 int param_is_null = 0;
04553
04554 if (cmd_type == CS_DYNAMIC_CMD) {
04555 param->name = NULL;
04556 } else {
04557 if (datafmt->namelen == CS_NULLTERM) {
04558 param->name = strdup(datafmt->name);
04559 if (param->name == NULL)
04560 return CS_FAIL;
04561 } else if (datafmt->namelen > 0) {
04562 param->name = malloc(datafmt->namelen + 1);
04563 if (param->name == NULL)
04564 return CS_FAIL;
04565 memset(param->name, 0, datafmt->namelen + 1);
04566 strncpy(param->name, datafmt->name, datafmt->namelen);
04567 } else {
04568 param->name = NULL;
04569 }
04570 }
04571
04572 param->status = datafmt->status;
04573 tdsdump_log(TDS_DBG_INFO1, " _ct_fill_param() status = %d \n", param->status);
04574
04575
04576
04577
04578
04579 param->type = _ct_get_server_type(datafmt->datatype);
04580
04581 if (is_numeric_type(param->type)) {
04582 param->scale = datafmt->scale;
04583 param->precision = datafmt->precision;
04584 if (param->scale < 0 || param->precision < 0
04585 || param->precision > 77 || param->scale > param->precision)
04586 return CS_FAIL;
04587 }
04588
04589 param->maxlen = datafmt->maxlength;
04590
04591 if (is_fixed_type(param->type)) {
04592 param->maxlen = tds_get_size_by_type(param->type);
04593 }
04594
04595 param->param_by_value = byvalue;
04596
04597 if (byvalue) {
04598 param->datalen = ¶m->datalen_value;
04599 *(param->datalen) = *datalen;
04600
04601 param->ind = ¶m->indicator_value;
04602 *(param->ind) = *indicator;
04603
04604
04605
04606 if (*indicator == -1) {
04607 param->value = NULL;
04608 *(param->datalen) = 0;
04609 param_is_null = 1;
04610 } else {
04611
04612
04613 if ((*datalen == 0 || *datalen == CS_UNUSED) && data == NULL) {
04614 param->value = NULL;
04615 *(param->datalen) = 0;
04616 param_is_null = 1;
04617 } else {
04618
04619
04620
04621 if (is_fixed_type(param->type)) {
04622 *(param->datalen) = tds_get_size_by_type(param->type);
04623 } else {
04624 *(param->datalen) = (*datalen == CS_UNUSED) ? 0 : *datalen;
04625 }
04626
04627 if (data) {
04628 if (*(param->datalen) == CS_NULLTERM) {
04629 tdsdump_log(TDS_DBG_INFO1, " _ct_fill_param() about to strdup string %u bytes long\n",
04630 (unsigned int) strlen(data));
04631 *(param->datalen) = strlen(data);
04632 } else if (*(param->datalen) < 0) {
04633 return CS_FAIL;
04634 }
04635 param->value = malloc(*(param->datalen));
04636 if (param->value == NULL)
04637 return CS_FAIL;
04638 memcpy(param->value, data, *(param->datalen));
04639 param->param_by_value = 1;
04640 } else {
04641 param->value = NULL;
04642 *(param->datalen) = 0;
04643 param_is_null = 1;
04644 }
04645 }
04646 }
04647
04648 if (param_is_null) {
04649 switch (param->type) {
04650 case SYBINT1:
04651 case SYBINT2:
04652 case SYBINT4:
04653
04654 case SYBINT8:
04655 param->type = SYBINTN;
04656 break;
04657 case SYBDATETIME:
04658 case SYBDATETIME4:
04659 param->type = SYBDATETIMN;
04660 break;
04661 case SYBFLT8:
04662 param->type = SYBFLTN;
04663 break;
04664 case SYBBIT:
04665 param->type = SYBBITN;
04666 break;
04667 case SYBMONEY:
04668 case SYBMONEY4:
04669 param->type = SYBMONEYN;
04670 break;
04671 default:
04672 break;
04673 }
04674 }
04675 } else {
04676 param->datalen = datalen;
04677 param->ind = indicator;
04678 param->value = data;
04679 }
04680 return CS_SUCCEED;
04681 }
04682
04683
04684
04685
04686 CS_RETCODE
04687 ct_diag(CS_CONNECTION * conn, CS_INT operation, CS_INT type, CS_INT idx, CS_VOID * buffer)
04688 {
04689 switch (operation) {
04690 case CS_INIT:
04691 if (conn->ctx->cs_errhandletype == _CS_ERRHAND_CB) {
04692
04693
04694
04695 return CS_FAIL;
04696 }
04697
04698 conn->ctx->cs_errhandletype = _CS_ERRHAND_INLINE;
04699
04700 if (conn->ctx->cs_diag_msglimit_client == 0)
04701 conn->ctx->cs_diag_msglimit_client = CS_NO_LIMIT;
04702
04703 if (conn->ctx->cs_diag_msglimit_server == 0)
04704 conn->ctx->cs_diag_msglimit_server = CS_NO_LIMIT;
04705
04706 if (conn->ctx->cs_diag_msglimit_total == 0)
04707 conn->ctx->cs_diag_msglimit_total = CS_NO_LIMIT;
04708
04709 conn->ctx->_clientmsg_cb = (CS_CLIENTMSG_FUNC) ct_diag_storeclientmsg;
04710 conn->ctx->_servermsg_cb = (CS_SERVERMSG_FUNC) ct_diag_storeservermsg;
04711
04712 break;
04713
04714 case CS_MSGLIMIT:
04715 if (conn->ctx->cs_errhandletype != _CS_ERRHAND_INLINE)
04716 return CS_FAIL;
04717
04718 if (type == CS_CLIENTMSG_TYPE)
04719 conn->ctx->cs_diag_msglimit_client = *(CS_INT *) buffer;
04720
04721 if (type == CS_SERVERMSG_TYPE)
04722 conn->ctx->cs_diag_msglimit_server = *(CS_INT *) buffer;
04723
04724 if (type == CS_ALLMSG_TYPE)
04725 conn->ctx->cs_diag_msglimit_total = *(CS_INT *) buffer;
04726
04727 break;
04728
04729 case CS_CLEAR:
04730 if (conn->ctx->cs_errhandletype != _CS_ERRHAND_INLINE)
04731 return CS_FAIL;
04732 return _ct_diag_clearmsg(conn->ctx, type);
04733 break;
04734
04735 case CS_GET:
04736 if (conn->ctx->cs_errhandletype != _CS_ERRHAND_INLINE)
04737 return CS_FAIL;
04738
04739 if (buffer == NULL)
04740 return CS_FAIL;
04741
04742 if (type == CS_CLIENTMSG_TYPE) {
04743 if (idx == 0
04744 || (conn->ctx->cs_diag_msglimit_client != CS_NO_LIMIT && idx > conn->ctx->cs_diag_msglimit_client))
04745 return CS_FAIL;
04746
04747 return (ct_diag_getclientmsg(conn->ctx, idx, (CS_CLIENTMSG *) buffer));
04748 }
04749
04750 if (type == CS_SERVERMSG_TYPE) {
04751 if (idx == 0
04752 || (conn->ctx->cs_diag_msglimit_server != CS_NO_LIMIT && idx > conn->ctx->cs_diag_msglimit_server))
04753 return CS_FAIL;
04754 return (ct_diag_getservermsg(conn->ctx, idx, (CS_SERVERMSG *) buffer));
04755 }
04756
04757 break;
04758
04759 case CS_STATUS:
04760 if (conn->ctx->cs_errhandletype != _CS_ERRHAND_INLINE)
04761 return CS_FAIL;
04762 if (buffer == NULL)
04763 return CS_FAIL;
04764
04765 return (ct_diag_countmsg(conn->ctx, type, (CS_INT *) buffer));
04766 break;
04767 }
04768 return CS_SUCCEED;
04769 }
04770
04771 static CS_INT
04772 ct_diag_storeclientmsg(CS_CONTEXT * context, CS_CONNECTION * conn, CS_CLIENTMSG * message)
04773 {
04774 struct cs_diag_msg_client **curptr;
04775 struct cs_diag_msg_svr **scurptr;
04776
04777 CS_INT msg_count = 0;
04778
04779 curptr = &(conn->ctx->clientstore);
04780
04781 scurptr = &(conn->ctx->svrstore);
04782
04783
04784
04785
04786 while (*curptr != NULL) {
04787 msg_count++;
04788 curptr = &((*curptr)->next);
04789 }
04790
04791
04792
04793
04794 if (conn->ctx->cs_diag_msglimit_client != CS_NO_LIMIT && msg_count >= conn->ctx->cs_diag_msglimit_client) {
04795 return CS_FAIL;
04796 }
04797
04798
04799
04800
04801 if (conn->ctx->cs_diag_msglimit_total != CS_NO_LIMIT) {
04802 while (*scurptr != NULL) {
04803 msg_count++;
04804 scurptr = &((*scurptr)->next);
04805 }
04806 if (msg_count >= conn->ctx->cs_diag_msglimit_total) {
04807 return CS_FAIL;
04808 }
04809 }
04810
04811 *curptr = (struct cs_diag_msg_client *) malloc(sizeof(struct cs_diag_msg_client));
04812 if (*curptr == NULL) {
04813 return CS_FAIL;
04814 } else {
04815 (*curptr)->next = NULL;
04816 (*curptr)->clientmsg = malloc(sizeof(CS_CLIENTMSG));
04817 if ((*curptr)->clientmsg == NULL) {
04818 return CS_FAIL;
04819 } else {
04820 memcpy((*curptr)->clientmsg, message, sizeof(CS_CLIENTMSG));
04821 }
04822 }
04823
04824 return CS_SUCCEED;
04825 }
04826
04827 static CS_INT
04828 ct_diag_storeservermsg(CS_CONTEXT * context, CS_CONNECTION * conn, CS_SERVERMSG * message)
04829 {
04830 struct cs_diag_msg_svr **curptr;
04831 struct cs_diag_msg_client **ccurptr;
04832
04833 CS_INT msg_count = 0;
04834
04835 curptr = &(conn->ctx->svrstore);
04836 ccurptr = &(conn->ctx->clientstore);
04837
04838
04839
04840
04841 while (*curptr != NULL) {
04842 msg_count++;
04843 curptr = &((*curptr)->next);
04844 }
04845
04846
04847
04848
04849 if (conn->ctx->cs_diag_msglimit_server != CS_NO_LIMIT && msg_count >= conn->ctx->cs_diag_msglimit_server) {
04850 return CS_FAIL;
04851 }
04852
04853
04854
04855
04856 if (conn->ctx->cs_diag_msglimit_total != CS_NO_LIMIT) {
04857 while (*ccurptr != NULL) {
04858 msg_count++;
04859 ccurptr = &((*ccurptr)->next);
04860 }
04861 if (msg_count >= conn->ctx->cs_diag_msglimit_total) {
04862 return CS_FAIL;
04863 }
04864 }
04865
04866 *curptr = (struct cs_diag_msg_svr *) malloc(sizeof(struct cs_diag_msg_svr));
04867 if (*curptr == NULL) {
04868 return CS_FAIL;
04869 } else {
04870 (*curptr)->next = NULL;
04871 (*curptr)->servermsg = malloc(sizeof(CS_SERVERMSG));
04872 if ((*curptr)->servermsg == NULL) {
04873 return CS_FAIL;
04874 } else {
04875 memcpy((*curptr)->servermsg, message, sizeof(CS_SERVERMSG));
04876 }
04877 }
04878
04879 return CS_SUCCEED;
04880 }
04881
04882 static CS_INT
04883 ct_diag_getclientmsg(CS_CONTEXT * context, CS_INT idx, CS_CLIENTMSG * message)
04884 {
04885 struct cs_diag_msg_client *curptr;
04886 CS_INT msg_count = 0, msg_found = 0;
04887
04888 curptr = context->clientstore;
04889
04890
04891
04892
04893 while (curptr != NULL) {
04894 msg_count++;
04895 if (msg_count == idx) {
04896 msg_found++;
04897 break;
04898 }
04899 curptr = curptr->next;
04900 }
04901
04902 if (msg_found) {
04903 memcpy(message, curptr->clientmsg, sizeof(CS_CLIENTMSG));
04904 return CS_SUCCEED;
04905 }
04906 return CS_NOMSG;
04907 }
04908
04909 static CS_INT
04910 ct_diag_getservermsg(CS_CONTEXT * context, CS_INT idx, CS_SERVERMSG * message)
04911 {
04912 struct cs_diag_msg_svr *curptr;
04913 CS_INT msg_count = 0, msg_found = 0;
04914
04915 curptr = context->svrstore;
04916
04917
04918
04919
04920 while (curptr != NULL) {
04921 msg_count++;
04922 if (msg_count == idx) {
04923 msg_found++;
04924 break;
04925 }
04926 curptr = curptr->next;
04927 }
04928
04929 if (msg_found) {
04930 memcpy(message, curptr->servermsg, sizeof(CS_SERVERMSG));
04931 return CS_SUCCEED;
04932 } else {
04933 return CS_NOMSG;
04934 }
04935 }
04936
04937 CS_INT
04938 _ct_diag_clearmsg(CS_CONTEXT * context, CS_INT type)
04939 {
04940 struct cs_diag_msg_client *curptr, *freeptr;
04941 struct cs_diag_msg_svr *scurptr, *sfreeptr;
04942
04943 if (type == CS_CLIENTMSG_TYPE || type == CS_ALLMSG_TYPE) {
04944 curptr = context->clientstore;
04945 context->clientstore = NULL;
04946
04947 while (curptr != NULL) {
04948 freeptr = curptr;
04949 curptr = freeptr->next;
04950 if (freeptr->clientmsg)
04951 free(freeptr->clientmsg);
04952 free(freeptr);
04953 }
04954 }
04955
04956 if (type == CS_SERVERMSG_TYPE || type == CS_ALLMSG_TYPE) {
04957 scurptr = context->svrstore;
04958 context->svrstore = NULL;
04959
04960 while (scurptr != NULL) {
04961 sfreeptr = scurptr;
04962 scurptr = sfreeptr->next;
04963 if (sfreeptr->servermsg)
04964 free(sfreeptr->servermsg);
04965 free(sfreeptr);
04966 }
04967 }
04968 return CS_SUCCEED;
04969 }
04970
04971 static CS_INT
04972 ct_diag_countmsg(CS_CONTEXT * context, CS_INT type, CS_INT * count)
04973 {
04974 struct cs_diag_msg_client *curptr;
04975 struct cs_diag_msg_svr *scurptr;
04976
04977 CS_INT msg_count = 0;
04978
04979 if (type == CS_CLIENTMSG_TYPE || type == CS_ALLMSG_TYPE) {
04980 curptr = context->clientstore;
04981
04982 while (curptr != NULL) {
04983 msg_count++;
04984 curptr = curptr->next;
04985 }
04986 }
04987
04988 if (type == CS_SERVERMSG_TYPE || type == CS_ALLMSG_TYPE) {
04989 scurptr = context->svrstore;
04990
04991 while (scurptr != NULL) {
04992 msg_count++;
04993 scurptr = scurptr->next;
04994 }
04995 }
04996 *count = msg_count;
04997
04998 return CS_SUCCEED;
04999 }
05000
05001
05002
05003 static CS_DYNAMIC *
05004 _ct_allocate_dynamic(CS_CONNECTION * con, char *id, int idlen)
05005 {
05006 CS_DYNAMIC *dyn;
05007 CS_DYNAMIC **pdyn;
05008 int id_len;
05009
05010 dyn = (CS_DYNAMIC *) malloc(sizeof(CS_DYNAMIC));
05011
05012 if (idlen == CS_NULLTERM)
05013 id_len = strlen(id);
05014 else
05015 id_len = idlen;
05016
05017 if (dyn != NULL) {
05018 memset(dyn, '\0', sizeof(CS_DYNAMIC));
05019 dyn->id = malloc(id_len + 1);
05020 strncpy(dyn->id, id, id_len);
05021 dyn->id[id_len] = '\0';
05022
05023 if (con->dynlist == NULL) {
05024 tdsdump_log(TDS_DBG_INFO1, "_ct_allocate_dynamic() attaching dynamic command to head\n");
05025 con->dynlist = dyn;
05026 } else {
05027 pdyn = &con->dynlist;
05028 while (*pdyn) {
05029 pdyn = &(*pdyn)->next;
05030 }
05031
05032 *pdyn = dyn;
05033 }
05034 }
05035 return (dyn);
05036 }
05037
05038 static CS_DYNAMIC *
05039 _ct_locate_dynamic(CS_CONNECTION * con, char *id, int idlen)
05040 {
05041 CS_DYNAMIC *dyn;
05042 int id_len;
05043
05044 if (idlen == CS_NULLTERM)
05045 id_len = strlen(id);
05046 else
05047 id_len = idlen;
05048
05049 tdsdump_log(TDS_DBG_INFO1, "_ct_locate_dynamic() looking for %s\n", (char *) id);
05050
05051 for (dyn = con->dynlist; dyn != NULL; dyn = dyn->next) {
05052 tdsdump_log(TDS_DBG_INFO1, "_ct_locate_dynamic() matching with %s\n", (char *) dyn->id);
05053 if (strncmp(dyn->id, id, id_len) == 0)
05054 break;
05055 }
05056
05057 return (dyn);
05058 }
05059
05060 static CS_INT
05061 _ct_deallocate_dynamic(CS_CONNECTION * con, CS_DYNAMIC *dyn)
05062 {
05063 CS_DYNAMIC_LIST *victim = NULL;
05064 CS_DYNAMIC_LIST *prev = NULL;
05065 CS_DYNAMIC_LIST *next = NULL;
05066 TDSDYNAMIC *tdsdyn;
05067 char myid[256];
05068
05069 strcpy(myid,"");
05070
05071 victim = con->dynlist;
05072
05073 for (;;) {
05074 if (victim == dyn)
05075 break;
05076 prev = victim;
05077 victim = victim->next;
05078 if (victim == NULL) {
05079 tdsdump_log(TDS_DBG_FUNC, "ct_deallocate_dynamic() : cannot find entry in list\n");
05080 return CS_FAIL;
05081 }
05082 }
05083
05084 tdsdump_log(TDS_DBG_FUNC, "ct_deallocate_dynamic() : command entry found in list\n");
05085
05086 next = victim->next;
05087
05088 if (victim->id) {
05089 strcpy(myid, victim->id);
05090 free(victim->id);
05091 }
05092 if (victim->stmt) free(victim->stmt);
05093 param_clear(victim->param_list);
05094
05095 free(victim);
05096
05097 tdsdump_log(TDS_DBG_FUNC, "ct_deallocate_dynamic() : relinking list\n");
05098
05099 if (prev)
05100 prev->next = next;
05101 else
05102 con->dynlist = next;
05103
05104 tdsdump_log(TDS_DBG_FUNC, "ct_deallocate_dynamic() : relinked list\n");
05105
05106 if (strlen(myid) > 0) {
05107 tdsdyn = tds_lookup_dynamic(con->tds_socket, myid);
05108 if (tdsdyn) {
05109 tds_free_dynamic(con->tds_socket, tdsdyn);
05110 }
05111 }
05112
05113 return CS_SUCCEED;
05114
05115 }
05116
05117