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 #if HAVE_STRING_H
00026 #include <string.h>
00027 #endif
00028
00029 #if HAVE_STDLIB_H
00030 #include <stdlib.h>
00031 #endif
00032
00033 #include <assert.h>
00034 #include <limits.h>
00035
00036 #include "tds.h"
00037 #include "tdsconvert.h"
00038 #include "tdsiconv.h"
00039 #include "tds_checks.h"
00040 #include "replacements.h"
00041 #ifdef DMALLOC
00042 #include <dmalloc.h>
00043 #endif
00044
00045 TDS_RCSID(var, "$Id: token.c 174668 2009-10-29 19:44:31Z ivanovp $");
00046
00047 static int tds_process_msg(TDSSOCKET * tds, int marker);
00048 static int tds_process_compute_result(TDSSOCKET * tds);
00049 static int tds_process_compute_names(TDSSOCKET * tds);
00050 static int tds7_process_compute_result(TDSSOCKET * tds);
00051 static int tds_process_result(TDSSOCKET * tds);
00052 static int tds_process_col_name(TDSSOCKET * tds);
00053 static int tds_process_col_fmt(TDSSOCKET * tds);
00054 static int tds_process_colinfo(TDSSOCKET * tds);
00055 static int tds_process_compute(TDSSOCKET * tds, TDS_INT * computeid);
00056 static int tds_process_cursor_tokens(TDSSOCKET * tds);
00057 static int tds_process_row(TDSSOCKET * tds);
00058 static int tds_process_param_result(TDSSOCKET * tds, TDSPARAMINFO ** info);
00059 static int tds7_process_result(TDSSOCKET * tds);
00060 static TDSDYNAMIC *tds_process_dynamic(TDSSOCKET * tds);
00061 static int tds_process_auth(TDSSOCKET * tds);
00062 static int tds_get_data(TDSSOCKET * tds, TDSCOLUMN * curcol, unsigned char *current_row, int i);
00063 static int tds_get_data_info(TDSSOCKET * tds, TDSCOLUMN * curcol, int is_param);
00064 static int tds_process_env_chg(TDSSOCKET * tds);
00065 static const char *_tds_token_name(unsigned char marker);
00066 static int tds_process_param_result_tokens(TDSSOCKET * tds);
00067 static int tds_process_params_result_token(TDSSOCKET * tds);
00068 static int tds_process_dyn_result(TDSSOCKET * tds);
00069 static int tds5_get_varint_size(int datatype);
00070 static int tds5_process_result(TDSSOCKET * tds);
00071 static int tds5_process_dyn_result2(TDSSOCKET * tds);
00072 static void adjust_character_column_size(const TDSSOCKET * tds, TDSCOLUMN * curcol);
00073 static int determine_adjusted_size(const TDSICONV * char_conv, int size);
00074 static int tds_process_default_tokens(TDSSOCKET * tds, int marker);
00075 static int tds_process_end(TDSSOCKET * tds, int marker, int *flags_parm);
00076 static int tds5_process_optioncmd(TDSSOCKET * tds);
00077
00078 static int tds5_get_varint_size(int datatype);
00079 static const char *tds_pr_op(int op);
00080 static int tds_alloc_get_string(TDSSOCKET * tds, char **string, int len) ;
00081 void generate_random_buffer(unsigned char *out, int len);
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static int
00102 tds_process_default_tokens(TDSSOCKET * tds, int marker)
00103 {
00104 int tok_size;
00105 int done_flags;
00106 TDS_INT ret_status;
00107
00108 CHECK_TDS_EXTRA(tds);
00109
00110 tdsdump_log(TDS_DBG_FUNC, "tds_process_default_tokens() marker is %x(%s)\n", marker, _tds_token_name(marker));
00111
00112 if (IS_TDSDEAD(tds)) {
00113 tdsdump_log(TDS_DBG_FUNC, "leaving tds_process_default_tokens() connection dead\n");
00114 tds_set_state(tds, TDS_DEAD);
00115 return TDS_FAIL;
00116 }
00117
00118 switch (marker) {
00119 case TDS_AUTH_TOKEN:
00120 return tds_process_auth(tds);
00121 break;
00122 case TDS_ENVCHANGE_TOKEN:
00123 return tds_process_env_chg(tds);
00124 break;
00125 case TDS_DONE_TOKEN:
00126 case TDS_DONEPROC_TOKEN:
00127 case TDS_DONEINPROC_TOKEN:
00128 return tds_process_end(tds, marker, &done_flags);
00129 break;
00130 case TDS_PROCID_TOKEN:
00131 tds_get_n(tds, NULL, 8);
00132 break;
00133 case TDS_RETURNSTATUS_TOKEN:
00134 ret_status = tds_get_int(tds);
00135 marker = tds_peek(tds);
00136 if (marker != TDS_PARAM_TOKEN && marker != TDS_DONEPROC_TOKEN && marker != TDS_DONE_TOKEN)
00137 break;
00138 tds->has_status = 1;
00139 tds->ret_status = ret_status;
00140 tdsdump_log(TDS_DBG_FUNC, "tds_process_default_tokens: return status is %d\n", tds->ret_status);
00141 break;
00142 case TDS_ERROR_TOKEN:
00143 case TDS_INFO_TOKEN:
00144 case TDS_EED_TOKEN:
00145 return tds_process_msg(tds, marker);
00146 break;
00147 case TDS_CAPABILITY_TOKEN:
00148
00149 tok_size = tds_get_smallint(tds);
00150
00151
00152
00153
00154
00155 if (!TDS_IS_MSSQL(tds) && tds->product_version < TDS_SYB_VER(12, 0, 0)) {
00156 unsigned char type, size, *p, *pend;
00157
00158 p = tds->capabilities;
00159 pend = tds->capabilities + TDS_MAX_CAPABILITY;
00160
00161 do {
00162 type = tds_get_byte(tds);
00163 size = tds_get_byte(tds);
00164 if ((p + 2) > pend)
00165 break;
00166 *p++ = type;
00167 *p++ = size;
00168 if ((p + size) > pend)
00169 break;
00170 if (tds_get_n(tds, p, size) == NULL)
00171 return TDS_FAIL;
00172 } while (type != 2);
00173 } else {
00174 if (tds_get_n(tds, tds->capabilities, tok_size > TDS_MAX_CAPABILITY ? TDS_MAX_CAPABILITY : tok_size) ==
00175 NULL)
00176 return TDS_FAIL;
00177 }
00178 break;
00179
00180 case TDS_PARAM_TOKEN:
00181 tds_unget_byte(tds);
00182 return tds_process_param_result_tokens(tds);
00183 break;
00184 case TDS7_RESULT_TOKEN:
00185 return tds7_process_result(tds);
00186 break;
00187 case TDS_OPTIONCMD_TOKEN:
00188 return tds5_process_optioncmd(tds);
00189 break;
00190 case TDS_RESULT_TOKEN:
00191 return tds_process_result(tds);
00192 break;
00193 case TDS_ROWFMT2_TOKEN:
00194 return tds5_process_result(tds);
00195 break;
00196 case TDS_COLNAME_TOKEN:
00197 return tds_process_col_name(tds);
00198 break;
00199 case TDS_COLFMT_TOKEN:
00200 return tds_process_col_fmt(tds);
00201 break;
00202 case TDS_ROW_TOKEN:
00203 return tds_process_row(tds);
00204 break;
00205 case TDS5_PARAMFMT_TOKEN:
00206
00207 tds->cur_dyn = NULL;
00208 return tds_process_dyn_result(tds);
00209 break;
00210 case TDS5_PARAMFMT2_TOKEN:
00211 tds->cur_dyn = NULL;
00212 return tds5_process_dyn_result2(tds);
00213 break;
00214 case TDS5_PARAMS_TOKEN:
00215
00216 return tds_process_params_result_token(tds);
00217 break;
00218 case TDS_CURINFO_TOKEN:
00219 return tds_process_cursor_tokens(tds);
00220 break;
00221 case TDS5_DYNAMIC_TOKEN:
00222 case TDS_LOGINACK_TOKEN:
00223 case TDS_ORDERBY_TOKEN:
00224 case TDS_CONTROL_TOKEN:
00225 case TDS_TABNAME_TOKEN:
00226 tdsdump_log(TDS_DBG_WARN, "Eating %s token\n", _tds_token_name(marker));
00227 tds_get_n(tds, NULL, tds_get_smallint(tds));
00228 break;
00229 case TDS_COLINFO_TOKEN:
00230 return tds_process_colinfo(tds);
00231 break;
00232 case TDS_ORDERBY2_TOKEN:
00233 tdsdump_log(TDS_DBG_WARN, "Eating %s token\n", _tds_token_name(marker));
00234 tds_get_n(tds, NULL, tds_get_int(tds));
00235 break;
00236 default:
00237 tds_client_msg(tds->tds_ctx, tds, 20020, 9, 0, 0, "Bad token from the server: Datastream processing out of sync");
00238 if (IS_TDSDEAD(tds))
00239 tds_set_state(tds, TDS_DEAD);
00240 else
00241 tds_close_socket(tds);
00242 tdsdump_log(TDS_DBG_ERROR, "Unknown marker: %d(%x)!!\n", marker, (unsigned char) marker);
00243 return TDS_FAIL;
00244 }
00245 return TDS_SUCCEED;
00246 }
00247
00248 static int
00249 tds_set_spid(TDSSOCKET * tds)
00250 {
00251 TDS_INT result_type;
00252 TDS_INT done_flags;
00253 TDS_INT rc;
00254 TDSCOLUMN *curcol;
00255
00256 CHECK_TDS_EXTRA(tds);
00257
00258 if (tds_submit_query(tds, "select @@spid") != TDS_SUCCEED) {
00259 return TDS_FAIL;
00260 }
00261
00262 while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_RETURN_ROWFMT|TDS_RETURN_ROW|TDS_RETURN_DONE)) == TDS_SUCCEED) {
00263
00264 switch (result_type) {
00265
00266 case TDS_ROWFMT_RESULT:
00267 if (tds->res_info->num_cols != 1)
00268 return TDS_FAIL;
00269 break;
00270
00271 case TDS_ROW_RESULT:
00272 curcol = tds->res_info->columns[0];
00273 if (curcol->column_type == SYBINT2 || (curcol->column_type == SYBINTN && curcol->column_size == 2)) {
00274 tds->spid = *((TDS_USMALLINT *) (tds->res_info->current_row + curcol->column_offset));
00275 } else if (curcol->column_type == SYBINT4 || (curcol->column_type == SYBINTN && curcol->column_size == 4)) {
00276 tds->spid = *((TDS_UINT *) (tds->res_info->current_row + curcol->column_offset));
00277 } else
00278 return TDS_FAIL;
00279 break;
00280
00281 case TDS_DONE_RESULT:
00282 if ((done_flags & TDS_DONE_ERROR) != 0)
00283 return TDS_FAIL;
00284 break;
00285
00286 default:
00287 break;
00288 }
00289 }
00290 if (rc != TDS_NO_MORE_RESULTS)
00291 return TDS_FAIL;
00292
00293 return TDS_SUCCEED;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 int
00303 tds_process_login_tokens(TDSSOCKET * tds)
00304 {
00305 int succeed = TDS_FAIL;
00306 int marker;
00307 int len;
00308 int memrc = 0;
00309 unsigned char major_ver, minor_ver;
00310 unsigned char ack;
00311 TDS_UINT product_version;
00312
00313 CHECK_TDS_EXTRA(tds);
00314
00315 tdsdump_log(TDS_DBG_FUNC, "tds_process_login_tokens()\n");
00316
00317 do {
00318 marker = tds_get_byte(tds);
00319 tdsdump_log(TDS_DBG_FUNC, "looking for login token, got %x(%s)\n", marker, _tds_token_name(marker));
00320
00321 switch (marker) {
00322 case TDS_AUTH_TOKEN:
00323 tds_process_auth(tds);
00324 break;
00325 case TDS_LOGINACK_TOKEN:
00326
00327 len = tds_get_smallint(tds);
00328 ack = tds_get_byte(tds);
00329 major_ver = tds_get_byte(tds);
00330 minor_ver = tds_get_byte(tds);
00331 tds_get_n(tds, NULL, 2);
00332
00333 tds_get_byte(tds);
00334 product_version = 0;
00335
00336
00337 len -= 10;
00338 if (tds->product_name)
00339 free(tds->product_name);
00340 if (major_ver >= 7u) {
00341 product_version = 0x80000000u;
00342 memrc += tds_alloc_get_string(tds, &tds->product_name, len / 2);
00343 } else if (major_ver >= 5) {
00344 memrc += tds_alloc_get_string(tds, &tds->product_name, len);
00345 } else {
00346 memrc += tds_alloc_get_string(tds, &tds->product_name, len);
00347 if (tds->product_name != NULL && strstr(tds->product_name, "Microsoft") != NULL)
00348 product_version = 0x80000000u;
00349 }
00350 product_version |= ((TDS_UINT) tds_get_byte(tds)) << 24;
00351 product_version |= ((TDS_UINT) tds_get_byte(tds)) << 16;
00352 product_version |= ((TDS_UINT) tds_get_byte(tds)) << 8;
00353 product_version |= tds_get_byte(tds);
00354
00355
00356
00357
00358 if (major_ver == 4 && minor_ver == 2 && (product_version & 0xff0000ffu) == 0x5f0000ffu)
00359 product_version = ((product_version & 0xffff00u) | 0x800000u) << 8;
00360 tds->product_version = product_version;
00361 #ifdef WORDS_BIGENDIAN
00362
00363
00364
00365
00366
00367
00368
00369 #endif
00370
00371
00372
00373
00374
00375 if (ack == 5 || ack == 1)
00376 succeed = TDS_SUCCEED;
00377 break;
00378 default:
00379 if (tds_process_default_tokens(tds, marker) == TDS_FAIL)
00380 return TDS_FAIL;
00381 break;
00382 }
00383 } while (marker != TDS_DONE_TOKEN);
00384
00385 tds->spid = tds->rows_affected;
00386 if (tds->spid == 0) {
00387 if (tds_set_spid(tds) != TDS_SUCCEED) {
00388 tdsdump_log(TDS_DBG_ERROR, "tds_set_spid() failed\n");
00389 succeed = TDS_FAIL;
00390 }
00391 }
00392 tdsdump_log(TDS_DBG_FUNC, "leaving tds_process_login_tokens() returning %d\n", succeed);
00393 if (memrc != 0)
00394 succeed = TDS_FAIL;
00395 return succeed;
00396 }
00397
00398
00399
00400
00401
00402 static void unix_to_nt_time(TDS_UINT8 *nt, time_t t)
00403 {
00404 #define TIME_FIXUP_CONSTANT 11644473600LL
00405
00406 TDS_UINT8 t2;
00407
00408 if (t == (time_t)-1) {
00409 *nt = (TDS_UINT8)-1LL;
00410 return;
00411 }
00412 if (t == 0) {
00413 *nt = 0;
00414 return;
00415 }
00416
00417 t2 = t;
00418 t2 += TIME_FIXUP_CONSTANT;
00419 t2 *= 1000*1000*10;
00420
00421 *nt = t2;
00422 }
00423
00424
00425 static TDS_UINT
00426 swap_32(TDS_UINT val)
00427 {
00428 return
00429 (((((TDS_UINT)val) & 0xff000000) >> 24) | ((((TDS_UINT)val) & 0x00ff0000) >> 8) |
00430 ((((TDS_UINT)val) & 0x0000ff00) << 8) | ((((TDS_UINT)val) & 0x000000ff) << 24));
00431 }
00432
00433
00434 static TDS_UINT8
00435 to_le(TDS_UINT8 val)
00436 {
00437 #ifndef WORDS_BIGENDIAN
00438 return val;
00439 #else
00440 union {
00441 TDS_UINT8 ll;
00442 TDS_UINT l[2];
00443 } w, r;
00444 w.ll = val;
00445 r.l[0] = swap_32( w.l[1] );
00446 r.l[1] = swap_32( w.l[0] );
00447 return r.ll;
00448 #endif
00449 }
00450
00451
00452 static void
00453 fill_names_blob_prefix(names_blob_prefix_t* prefix)
00454 {
00455 TDS_UINT8 nttime = 0;
00456
00457 unix_to_nt_time(&nttime, time(NULL));
00458
00459 prefix->response_type = 0x01;
00460 prefix->max_response_type = 0x01;
00461 prefix->reserved1 = 0x0000;
00462 prefix->reserved2 = 0x00000000;
00463 prefix->timestamp.l = to_le(nttime);
00464 generate_random_buffer(prefix->challenge, sizeof(prefix->challenge));
00465
00466 prefix->unknown = 0x00000000;
00467 }
00468
00469 static int
00470 tds_process_auth(TDSSOCKET * tds)
00471 {
00472 int pdu_size;
00473 unsigned char nonce[8];
00474 TDS_UINT flags;
00475 int domain_len;
00476 int data_block_offset;
00477
00478 int target_info_len;
00479 int target_info_offset;
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 int names_blob_len;
00490 unsigned char* names_blob;
00491
00492 unsigned char domain[128];
00493 int where;
00494 int rc;
00495
00496 CHECK_TDS_EXTRA(tds);
00497
00498 memset(domain, 0, sizeof(domain));
00499
00500 #if ENABLE_EXTRA_CHECKS
00501 if (!IS_TDS7_PLUS(tds))
00502 tdsdump_log(TDS_DBG_ERROR, "Called auth on TDS version < 7\n");
00503 #endif
00504
00505 pdu_size = tds_get_smallint(tds);
00506 tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN PDU size %d\n", pdu_size);
00507
00508
00509 if (pdu_size < 32)
00510 return TDS_FAIL;
00511
00512
00513
00514 tds_get_n(tds, NULL, 8);
00515 tds_get_int(tds);
00516 domain_len = tds_get_smallint(tds);
00517 domain_len = tds_get_smallint(tds);
00518 data_block_offset = tds_get_int(tds);
00519 flags = tds_get_int(tds);
00520 tds_get_n(tds, nonce, 8);
00521 tdsdump_dump_buf(TDS_DBG_INFO1, "TDS_AUTH_TOKEN nonce", nonce, 8);
00522 where = 32;
00523
00524
00525
00526
00527 if (data_block_offset != 32) {
00528
00529 tds_get_n(tds, NULL, 8);
00530
00531 target_info_len = tds_get_smallint(tds);
00532 target_info_len = tds_get_smallint(tds);
00533 target_info_offset = tds_get_int(tds);
00534
00535 where += 16;
00536
00537 if (data_block_offset == 56) {
00538
00539 tds_get_n(tds, NULL, 8);
00540 where += 8;
00541 }
00542 }
00543
00544
00545 tds_get_n(tds, domain, domain_len);
00546 tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN domain %s\n", domain);
00547 where += domain_len;
00548
00549 names_blob_len = sizeof(names_blob_prefix_t) + target_info_len + 4;
00550
00551
00552 names_blob = (unsigned char*)malloc(names_blob_len);
00553 memset(names_blob, 0, names_blob_len);
00554
00555 fill_names_blob_prefix(names_blob);
00556 tds_get_n(tds, names_blob + sizeof(names_blob_prefix_t), target_info_len);
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 rc = tds7_send_auth(tds, nonce, flags, names_blob, names_blob_len);
00573
00574 free(names_blob);
00575
00576 return rc;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 int
00627 tds_process_tokens(TDSSOCKET *tds, TDS_INT *result_type, int *done_flags, unsigned flag)
00628 {
00629 int marker;
00630 TDSPARAMINFO *pinfo = NULL;
00631 TDSCOLUMN *curcol;
00632 int rc;
00633 int saved_rows_affected = tds->rows_affected;
00634 TDS_INT ret_status;
00635 int cancel_seen = 0;
00636 unsigned return_flag = 0;
00637
00638 #define SET_RETURN(ret, f) \
00639 *result_type = ret; \
00640 return_flag = TDS_RETURN_##f | TDS_STOPAT_##f; \
00641 if (flag & TDS_STOPAT_##f) {\
00642 tds_unget_byte(tds); \
00643 tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens::SET_RETURN stopping on current token\n"); \
00644 break; \
00645 }
00646
00647 CHECK_TDS_EXTRA(tds);
00648
00649 tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens(%p, %p, %p, 0x%x)\n", tds, result_type, done_flags, flag);
00650
00651 if (tds->state == TDS_IDLE) {
00652 tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens() state is COMPLETED\n");
00653 *result_type = TDS_DONE_RESULT;
00654 return TDS_NO_MORE_RESULTS;
00655 }
00656
00657 if (tds_set_state(tds, TDS_READING) != TDS_READING)
00658 return TDS_FAIL;
00659
00660 rc = TDS_SUCCEED;
00661 for (;;) {
00662
00663 marker = tds_get_byte(tds);
00664 tdsdump_log(TDS_DBG_INFO1, "processing result tokens. marker is %x(%s)\n", marker, _tds_token_name(marker));
00665
00666 switch (marker) {
00667 case TDS7_RESULT_TOKEN:
00668
00669
00670
00671
00672
00673
00674
00675 if (tds->internal_sp_called == TDS_SP_CURSORFETCH) {
00676 rc = tds7_process_result(tds);
00677 marker = tds_get_byte(tds);
00678 if (marker != TDS_TABNAME_TOKEN) {
00679 tds_unget_byte(tds);
00680 } else {
00681 if ((rc = tds_process_default_tokens(tds, marker)) == TDS_FAIL)
00682 break;
00683 marker = tds_get_byte(tds);
00684 if (marker != TDS_COLINFO_TOKEN) {
00685 tds_unget_byte(tds);
00686 } else {
00687 tds_process_colinfo(tds);
00688 }
00689 }
00690 } else {
00691 SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);
00692
00693 rc = tds7_process_result(tds);
00694
00695
00696
00697
00698 marker = tds_get_byte(tds);
00699 if (marker != TDS_TABNAME_TOKEN) {
00700 tds_unget_byte(tds);
00701 rc = TDS_SUCCEED;
00702 break;
00703 }
00704 if ((rc = tds_process_default_tokens(tds, marker)) == TDS_FAIL)
00705 break;
00706 marker = tds_get_byte(tds);
00707 if (marker != TDS_COLINFO_TOKEN) {
00708 tds_unget_byte(tds);
00709 rc = TDS_SUCCEED;
00710 break;
00711 }
00712 if (rc == TDS_FAIL)
00713 break;
00714 else {
00715 tds_process_colinfo(tds);
00716 rc = TDS_SUCCEED;
00717 break;
00718 }
00719 }
00720 break;
00721 case TDS_RESULT_TOKEN:
00722 SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);
00723 rc = tds_process_result(tds);
00724 break;
00725 case TDS_ROWFMT2_TOKEN:
00726 SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);
00727 rc = tds5_process_result(tds);
00728 break;
00729 case TDS_COLNAME_TOKEN:
00730 rc = tds_process_col_name(tds);
00731 break;
00732 case TDS_COLFMT_TOKEN:
00733 SET_RETURN(TDS_ROWFMT_RESULT, ROWFMT);
00734 rc = tds_process_col_fmt(tds);
00735
00736 marker = tds_get_byte(tds);
00737 if (marker != TDS_TABNAME_TOKEN) {
00738 tds_unget_byte(tds);
00739 break;
00740 }
00741 if ((rc = tds_process_default_tokens(tds, marker)) == TDS_FAIL)
00742 break;
00743 marker = tds_get_byte(tds);
00744 if (marker != TDS_COLINFO_TOKEN) {
00745 tds_unget_byte(tds);
00746 break;
00747 }
00748 if (rc == TDS_FAIL)
00749 break;
00750 tds_process_colinfo(tds);
00751 rc = TDS_SUCCEED;
00752 break;
00753 case TDS_PARAM_TOKEN:
00754 tds_unget_byte(tds);
00755 if (tds->internal_sp_called) {
00756 tdsdump_log(TDS_DBG_FUNC, "processing parameters for sp %d\n", tds->internal_sp_called);
00757 while ((marker = tds_get_byte(tds)) == TDS_PARAM_TOKEN) {
00758 tdsdump_log(TDS_DBG_INFO1, "calling tds_process_param_result\n");
00759 tds_process_param_result(tds, &pinfo);
00760 }
00761 tds_unget_byte(tds);
00762 tdsdump_log(TDS_DBG_FUNC, "%d hidden return parameters\n", pinfo ? pinfo->num_cols : -1);
00763 if (pinfo && pinfo->num_cols > 0) {
00764 curcol = pinfo->columns[0];
00765 if (tds->internal_sp_called == TDS_SP_CURSOROPEN && tds->cur_cursor) {
00766 TDSCURSOR *cursor = tds->cur_cursor;
00767
00768 cursor->cursor_id = *(TDS_INT *) &(pinfo->current_row[curcol->column_offset]);
00769 tdsdump_log(TDS_DBG_FUNC, "stored internal cursor id %d\n",
00770 cursor->cursor_id);
00771 cursor->srv_status &= ~TDS_CUR_ISTAT_CLOSED;
00772 cursor->srv_status |= TDS_CUR_ISTAT_OPEN;
00773
00774
00775
00776
00777 }
00778 if (tds->internal_sp_called == TDS_SP_PREPARE
00779 && tds->cur_dyn && tds->cur_dyn->num_id == 0 && curcol->column_cur_size > 0) {
00780 tds->cur_dyn->num_id = *(TDS_INT *) &(pinfo->current_row[curcol->column_offset]);
00781 }
00782 }
00783 tds_free_param_results(pinfo);
00784 } else {
00785 SET_RETURN(TDS_PARAM_RESULT, PROC);
00786 rc = tds_process_param_result_tokens(tds);
00787 }
00788 break;
00789 case TDS_COMPUTE_NAMES_TOKEN:
00790 rc = tds_process_compute_names(tds);
00791 break;
00792 case TDS_COMPUTE_RESULT_TOKEN:
00793 SET_RETURN(TDS_COMPUTEFMT_RESULT, COMPUTEFMT);
00794 rc = tds_process_compute_result(tds);
00795 break;
00796 case TDS7_COMPUTE_RESULT_TOKEN:
00797 SET_RETURN(TDS_COMPUTEFMT_RESULT, COMPUTEFMT);
00798 rc = tds7_process_compute_result(tds);
00799 break;
00800 case TDS_ROW_TOKEN:
00801
00802 if (tds->cur_cursor) {
00803 TDSCURSOR *cursor = tds->cur_cursor;
00804
00805 tds->current_results = cursor->res_info;
00806 tdsdump_log(TDS_DBG_INFO1, "tds_process_tokens(). set current_results to cursor->res_info\n");
00807 } else {
00808
00809 if (tds->res_info)
00810 tds->current_results = tds->res_info;
00811 }
00812
00813 if (tds->current_results)
00814 tds->current_results->rows_exist = 1;
00815 SET_RETURN(TDS_ROW_RESULT, ROW);
00816
00817 rc = tds_process_row(tds);
00818 break;
00819 case TDS_CMP_ROW_TOKEN:
00820
00821 if (tds->res_info)
00822 tds->res_info->rows_exist = 1;
00823 SET_RETURN(TDS_COMPUTE_RESULT, COMPUTE);
00824 rc = tds_process_compute(tds, NULL);
00825 break;
00826 case TDS_RETURNSTATUS_TOKEN:
00827 ret_status = tds_get_int(tds);
00828 marker = tds_peek(tds);
00829 if (marker != TDS_PARAM_TOKEN && marker != TDS_DONEPROC_TOKEN && marker != TDS_DONE_TOKEN)
00830 break;
00831 if (tds->internal_sp_called) {
00832
00833 } else {
00834
00835 flag &= ~TDS_STOPAT_PROC;
00836 SET_RETURN(TDS_STATUS_RESULT, PROC);
00837 tds->has_status = 1;
00838 tds->ret_status = ret_status;
00839 tdsdump_log(TDS_DBG_FUNC, "tds_process_tokens: return status is %d\n", tds->ret_status);
00840 rc = TDS_SUCCEED;
00841 }
00842 break;
00843 case TDS5_DYNAMIC_TOKEN:
00844
00845 tds->cur_dyn = tds_process_dynamic(tds);
00846
00847 if (!tds->cur_dyn || tds->cur_dyn->emulated)
00848 break;
00849 marker = tds_get_byte(tds);
00850 if (marker != TDS_EED_TOKEN) {
00851 tds_unget_byte(tds);
00852 break;
00853 }
00854 tds_process_msg(tds, marker);
00855 if (!tds->cur_dyn || !tds->cur_dyn->emulated)
00856 break;
00857 marker = tds_get_byte(tds);
00858 if (marker != TDS_DONE_TOKEN) {
00859 tds_unget_byte(tds);
00860 break;
00861 }
00862 rc = tds_process_end(tds, marker, done_flags);
00863 if (done_flags)
00864 *done_flags &= ~TDS_DONE_ERROR;
00865
00866 SET_RETURN(TDS_DONE_RESULT, DONE);
00867 break;
00868 case TDS5_PARAMFMT_TOKEN:
00869 SET_RETURN(TDS_DESCRIBE_RESULT, PARAMFMT);
00870 rc = tds_process_dyn_result(tds);
00871 break;
00872 case TDS5_PARAMFMT2_TOKEN:
00873 SET_RETURN(TDS_DESCRIBE_RESULT, PARAMFMT);
00874 rc = tds5_process_dyn_result2(tds);
00875 break;
00876 case TDS5_PARAMS_TOKEN:
00877 SET_RETURN(TDS_PARAM_RESULT, PROC);
00878 rc = tds_process_params_result_token(tds);
00879 break;
00880 case TDS_CURINFO_TOKEN:
00881 rc = tds_process_cursor_tokens(tds);
00882 break;
00883 case TDS_DONE_TOKEN:
00884 SET_RETURN(TDS_DONE_RESULT, DONE);
00885 rc = tds_process_end(tds, marker, done_flags);
00886 break;
00887 case TDS_DONEPROC_TOKEN:
00888 SET_RETURN(TDS_DONEPROC_RESULT, DONE);
00889 rc = tds_process_end(tds, marker, done_flags);
00890 tds->rows_affected = saved_rows_affected;
00891 switch (tds->internal_sp_called) {
00892 case 0:
00893 case TDS_SP_PREPARE:
00894 case TDS_SP_EXECUTE:
00895 case TDS_SP_UNPREPARE:
00896 case TDS_SP_EXECUTESQL:
00897 break;
00898 case TDS_SP_CURSOROPEN:
00899 *result_type = TDS_DONE_RESULT;
00900 tds->rows_affected = saved_rows_affected;
00901 break;
00902 case TDS_SP_CURSORCLOSE:
00903 tdsdump_log(TDS_DBG_FUNC, "TDS_SP_CURSORCLOSE\n");
00904 if (tds->cur_cursor) {
00905
00906 TDSCURSOR *cursor = tds->cur_cursor;
00907
00908 cursor->srv_status &= ~TDS_CUR_ISTAT_OPEN;
00909 cursor->srv_status |= TDS_CUR_ISTAT_CLOSED;
00910 cursor->srv_status |= TDS_CUR_ISTAT_DECLARED;
00911 if (cursor->status.dealloc == 2) {
00912 tds_free_cursor(tds, cursor);
00913 }
00914
00915
00916
00917
00918
00919
00920 }
00921 *result_type = TDS_NO_MORE_RESULTS;
00922 rc = TDS_NO_MORE_RESULTS;
00923 break;
00924 default:
00925 *result_type = TDS_NO_MORE_RESULTS;
00926 rc = TDS_NO_MORE_RESULTS;
00927 break;
00928 }
00929 break;
00930 case TDS_DONEINPROC_TOKEN:
00931 switch(tds->internal_sp_called) {
00932 case TDS_SP_CURSOROPEN:
00933 case TDS_SP_CURSORFETCH:
00934 case TDS_SP_PREPARE:
00935 case TDS_SP_CURSORCLOSE:
00936 rc = tds_process_end(tds, marker, done_flags);
00937 if (tds->rows_affected != TDS_NO_COUNT) {
00938 saved_rows_affected = tds->rows_affected;
00939 }
00940 break;
00941 default:
00942 SET_RETURN(TDS_DONEINPROC_RESULT, DONE);
00943 rc = tds_process_end(tds, marker, done_flags);
00944 break;
00945 }
00946 break;
00947 case TDS_ERROR_TOKEN:
00948 case TDS_INFO_TOKEN:
00949 case TDS_EED_TOKEN:
00950 SET_RETURN(TDS_MSG_RESULT, MSG);
00951 rc = tds_process_default_tokens(tds, marker);
00952 break;
00953 default:
00954 SET_RETURN(TDS_OTHERS_RESULT, OTHERS);
00955 rc = tds_process_default_tokens(tds, marker);
00956 break;
00957 }
00958
00959 if (rc == TDS_FAIL) {
00960 tds_set_state(tds, TDS_PENDING);
00961 return rc;
00962 }
00963
00964 cancel_seen |= tds->in_cancel;
00965 if (cancel_seen) {
00966
00967 flag = TDS_HANDLE_ALL;
00968 }
00969
00970 if ((return_flag & flag) != 0) {
00971 tds_set_state(tds, TDS_PENDING);
00972 return rc;
00973 }
00974
00975 if (tds->state == TDS_IDLE)
00976 return cancel_seen ? TDS_CANCELLED : TDS_NO_MORE_RESULTS;
00977
00978 if (tds->state == TDS_DEAD) {
00979
00980 return TDS_FAIL;
00981 }
00982 }
00983 }
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 int
00996 tds_process_simple_query(TDSSOCKET * tds)
00997 {
00998 TDS_INT res_type;
00999 TDS_INT done_flags;
01000 int rc;
01001 int ret = TDS_SUCCEED;
01002
01003 CHECK_TDS_EXTRA(tds);
01004
01005 while ((rc = tds_process_tokens(tds, &res_type, &done_flags, TDS_RETURN_DONE)) == TDS_SUCCEED) {
01006 switch (res_type) {
01007
01008 case TDS_DONE_RESULT:
01009 case TDS_DONEPROC_RESULT:
01010 case TDS_DONEINPROC_RESULT:
01011 if ((done_flags & TDS_DONE_ERROR) != 0)
01012 ret = TDS_FAIL;
01013 break;
01014
01015 default:
01016 break;
01017 }
01018 }
01019 if (rc != TDS_NO_MORE_RESULTS) {
01020 ret = TDS_FAIL;
01021 }
01022
01023 return ret;
01024 }
01025
01026
01027
01028
01029
01030
01031
01032 static int
01033 tds_process_col_name(TDSSOCKET * tds)
01034 {
01035 int hdrsize, len = 0;
01036 int memrc = 0;
01037 int col, num_cols = 0;
01038 struct tmp_col_struct
01039 {
01040 char *column_name;
01041 int column_namelen;
01042 struct tmp_col_struct *next;
01043 };
01044 struct tmp_col_struct *head = NULL, *cur = NULL, *prev;
01045 TDSCOLUMN *curcol;
01046 TDSRESULTINFO *info;
01047
01048 CHECK_TDS_EXTRA(tds);
01049
01050 hdrsize = tds_get_smallint(tds);
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 while (len < hdrsize) {
01064 prev = cur;
01065 cur = (struct tmp_col_struct *)
01066 malloc(sizeof(struct tmp_col_struct));
01067
01068 if (!cur) {
01069 memrc = -1;
01070 break;
01071 }
01072
01073 if (prev)
01074 prev->next = cur;
01075 if (!head)
01076 head = cur;
01077
01078 cur->column_namelen = tds_get_byte(tds);
01079 memrc += tds_alloc_get_string(tds, &cur->column_name, cur->column_namelen);
01080 cur->next = NULL;
01081
01082 len += cur->column_namelen + 1;
01083 num_cols++;
01084 }
01085
01086
01087 tds_free_all_results(tds);
01088 tds->rows_affected = TDS_NO_COUNT;
01089
01090 if ((info = tds_alloc_results(num_cols)) == NULL)
01091 memrc = -1;
01092 tds->current_results = tds->res_info = info;
01093
01094 cur = head;
01095
01096 if (memrc != 0) {
01097 while (cur != NULL) {
01098 prev = cur;
01099 cur = cur->next;
01100 free(prev->column_name);
01101 free(prev);
01102 }
01103 return TDS_FAIL;
01104 } else {
01105 for (col = 0; col < info->num_cols; col++) {
01106 curcol = info->columns[col];
01107 tds_strlcpy(curcol->column_name, cur->column_name, sizeof(curcol->column_name));
01108 curcol->column_namelen = strlen(curcol->column_name);
01109 prev = cur;
01110 cur = cur->next;
01111 free(prev->column_name);
01112 free(prev);
01113 }
01114 return TDS_SUCCEED;
01115 }
01116 }
01117
01118
01119
01120
01121
01122
01123 void
01124 tds_add_row_column_size(TDSRESULTINFO * info, TDSCOLUMN * curcol)
01125 {
01126 CHECK_RESULTINFO_EXTRA(info);
01127 CHECK_COLUMN_EXTRA(curcol);
01128
01129
01130
01131
01132
01133
01134
01135 curcol->column_offset = info->row_size;
01136 if (is_numeric_type(curcol->column_type)) {
01137 info->row_size += sizeof(TDS_NUMERIC);
01138 } else if (is_blob_type(curcol->column_type)) {
01139 info->row_size += sizeof(TDSBLOB);
01140 } else {
01141 info->row_size += curcol->column_size;
01142 }
01143
01144
01145 info->row_size += curcol->column_varint_size;
01146
01147 info->row_size += (TDS_ALIGN_SIZE - 1);
01148 info->row_size -= info->row_size % TDS_ALIGN_SIZE;
01149 }
01150
01151
01152
01153
01154
01155
01156
01157 static int
01158 tds_process_col_fmt(TDSSOCKET * tds)
01159 {
01160 int col, hdrsize;
01161 TDSCOLUMN *curcol;
01162 TDSRESULTINFO *info;
01163
01164 int bytes_read = 0;
01165 int rest;
01166 TDS_SMALLINT flags;
01167
01168 CHECK_TDS_EXTRA(tds);
01169
01170 hdrsize = tds_get_smallint(tds);
01171
01172
01173 info = tds->res_info;
01174 for (col = 0; col < info->num_cols; col++) {
01175 curcol = info->columns[col];
01176
01177 if (TDS_IS_MSSQL(tds)) {
01178 curcol->column_usertype = tds_get_smallint(tds);
01179 flags = tds_get_smallint(tds);
01180 curcol->column_nullable = flags & 0x01;
01181 curcol->column_writeable = (flags & 0x08) > 0;
01182 curcol->column_identity = (flags & 0x10) > 0;
01183 } else {
01184 curcol->column_usertype = tds_get_int(tds);
01185 }
01186
01187 tds_set_column_type(tds, curcol, tds_get_byte(tds));
01188
01189 tdsdump_log(TDS_DBG_INFO1, "processing result. type = %d(%s), varint_size %d\n",
01190 curcol->column_type, tds_prtype(curcol->column_type), curcol->column_varint_size);
01191
01192 switch (curcol->column_varint_size) {
01193 case 4:
01194 curcol->column_size = tds_get_int(tds);
01195
01196
01197
01198
01199
01200
01201 curcol->table_namelen = tds_get_smallint(tds);
01202 tds_get_n(tds, curcol->table_name, curcol->table_namelen);
01203 bytes_read += 5 + 4 + 2 + curcol->table_namelen;
01204 break;
01205 case 1:
01206 curcol->column_size = tds_get_byte(tds);
01207 bytes_read += 5 + 1;
01208 break;
01209 case 0:
01210 bytes_read += 5 + 0;
01211 break;
01212 }
01213
01214
01215 curcol->on_server.column_size = curcol->column_size;
01216 adjust_character_column_size(tds, curcol);
01217
01218 tds_add_row_column_size(info, curcol);
01219 }
01220
01221
01222 rest = hdrsize - bytes_read;
01223 if (rest > 0) {
01224 tdsdump_log(TDS_DBG_INFO1, "NOTE:tds_process_col_fmt: draining %d bytes\n", rest);
01225 tds_get_n(tds, NULL, rest);
01226 }
01227
01228 if ((info->current_row = tds_alloc_row(info)) != NULL)
01229 return TDS_SUCCEED;
01230 else
01231 return TDS_FAIL;
01232 }
01233
01234 static int
01235 tds_process_colinfo(TDSSOCKET * tds)
01236 {
01237 int hdrsize;
01238 TDSCOLUMN *curcol;
01239 TDSRESULTINFO *info;
01240 int bytes_read = 0;
01241 unsigned char col_info[3], l;
01242
01243 CHECK_TDS_EXTRA(tds);
01244
01245 hdrsize = tds_get_smallint(tds);
01246
01247 info = tds->current_results;
01248
01249 while (bytes_read < hdrsize) {
01250
01251 tds_get_n(tds, col_info, 3);
01252 bytes_read += 3;
01253 if (info && col_info[0] > 0 && col_info[0] <= info->num_cols) {
01254 curcol = info->columns[col_info[0] - 1];
01255 curcol->column_writeable = (col_info[2] & 0x4) == 0;
01256 curcol->column_key = (col_info[2] & 0x8) > 0;
01257 curcol->column_hidden = (col_info[2] & 0x10) > 0;
01258 }
01259
01260
01261 if (col_info[2] & 0x20) {
01262 l = tds_get_byte(tds);
01263 if (IS_TDS7_PLUS(tds))
01264 l *= 2;
01265 tds_get_n(tds, NULL, l);
01266 bytes_read += l + 1;
01267 }
01268 }
01269
01270 return TDS_SUCCEED;
01271 }
01272
01273
01274
01275
01276
01277
01278 static int
01279 tds_process_param_result(TDSSOCKET * tds, TDSPARAMINFO ** pinfo)
01280 {
01281 int hdrsize;
01282 TDSCOLUMN *curparam;
01283 TDSPARAMINFO *info;
01284 int i;
01285
01286 CHECK_TDS_EXTRA(tds);
01287 if (*pinfo)
01288 CHECK_PARAMINFO_EXTRA(*pinfo);
01289
01290
01291
01292
01293 hdrsize = tds_get_smallint(tds);
01294 if ((info = tds_alloc_param_result(*pinfo)) == NULL)
01295 return TDS_FAIL;
01296
01297 *pinfo = info;
01298 curparam = info->columns[info->num_cols - 1];
01299
01300
01301
01302
01303
01304 tds_get_data_info(tds, curparam, 1);
01305
01306 curparam->column_cur_size = curparam->column_size;
01307
01308 if (tds_alloc_param_row(info, curparam) == NULL)
01309 return TDS_FAIL;
01310
01311 i = tds_get_data(tds, curparam, info->current_row, info->num_cols - 1);
01312
01313
01314
01315
01316
01317
01318 if (curparam->column_namelen > 0 && curparam->column_name[0] != '@')
01319 tds_free_param_result(*pinfo);
01320
01321 return i;
01322 }
01323
01324 static int
01325 tds_process_param_result_tokens(TDSSOCKET * tds)
01326 {
01327 int marker;
01328 TDSPARAMINFO **pinfo;
01329
01330 CHECK_TDS_EXTRA(tds);
01331
01332 if (tds->cur_dyn)
01333 pinfo = &(tds->cur_dyn->res_info);
01334 else
01335 pinfo = &(tds->param_info);
01336
01337 while ((marker = tds_get_byte(tds)) == TDS_PARAM_TOKEN) {
01338 tds_process_param_result(tds, pinfo);
01339 }
01340 if (!marker) {
01341 tdsdump_log(TDS_DBG_FUNC, "error: tds_process_param_result() returned TDS_FAIL\n");
01342 return TDS_FAIL;
01343 }
01344
01345 tds->current_results = *pinfo;
01346 tds_unget_byte(tds);
01347 return TDS_SUCCEED;
01348 }
01349
01350
01351
01352
01353 static int
01354 tds_process_params_result_token(TDSSOCKET * tds)
01355 {
01356 int i;
01357 TDSCOLUMN *curcol;
01358 TDSPARAMINFO *info;
01359
01360 CHECK_TDS_EXTRA(tds);
01361
01362
01363 info = tds->current_results;
01364 if (!info)
01365 return TDS_FAIL;
01366
01367 for (i = 0; i < info->num_cols; i++) {
01368 curcol = info->columns[i];
01369 if (tds_get_data(tds, curcol, info->current_row, i) != TDS_SUCCEED)
01370 return TDS_FAIL;
01371 }
01372 return TDS_SUCCEED;
01373 }
01374
01375
01376
01377
01378
01379
01380 static int
01381 tds_process_compute_result(TDSSOCKET * tds)
01382 {
01383 int hdrsize;
01384 int col, num_cols;
01385 TDS_TINYINT by_cols = 0;
01386 TDS_SMALLINT *cur_by_col;
01387 TDS_SMALLINT compute_id = 0;
01388 TDSCOLUMN *curcol;
01389 TDSCOMPUTEINFO *info;
01390 int i;
01391
01392 CHECK_TDS_EXTRA(tds);
01393
01394 hdrsize = tds_get_smallint(tds);
01395
01396
01397
01398
01399
01400
01401
01402 compute_id = tds_get_smallint(tds);
01403
01404 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. compute_id = %d\n", compute_id);
01405
01406
01407
01408
01409
01410
01411
01412 num_cols = tds_get_byte(tds);
01413
01414 for (i = 0;; ++i) {
01415 if (i >= tds->num_comp_info)
01416 return TDS_FAIL;
01417 info = tds->comp_info[i];
01418 tdsdump_log(TDS_DBG_FUNC, "in dbaltcolid() found computeid = %d\n", info->computeid);
01419 if (info->computeid == compute_id)
01420 break;
01421 }
01422
01423 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. num_cols = %d\n", num_cols);
01424
01425 for (col = 0; col < num_cols; col++) {
01426 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 2\n");
01427 curcol = info->columns[col];
01428
01429 curcol->column_operator = tds_get_byte(tds);
01430 curcol->column_operand = tds_get_byte(tds);
01431
01432
01433
01434
01435
01436
01437 if (curcol->column_namelen == 0) {
01438 strcpy(curcol->column_name, tds_pr_op(curcol->column_operator));
01439 curcol->column_namelen = strlen(curcol->column_name);
01440 }
01441
01442
01443 curcol->column_usertype = tds_get_int(tds);
01444
01445 tds_set_column_type(tds, curcol, tds_get_byte(tds));
01446
01447 switch (curcol->column_varint_size) {
01448 case 4:
01449 curcol->column_size = tds_get_int(tds);
01450 break;
01451 case 2:
01452 curcol->column_size = tds_get_smallint(tds);
01453 break;
01454 case 1:
01455 curcol->column_size = tds_get_byte(tds);
01456 break;
01457 case 0:
01458 break;
01459 }
01460 tdsdump_log(TDS_DBG_INFO1, "processing result. column_size %d\n", curcol->column_size);
01461
01462
01463 curcol->on_server.column_size = curcol->column_size;
01464
01465 adjust_character_column_size(tds, curcol);
01466
01467
01468 if (!IS_TDS42(tds))
01469 tds_get_n(tds, NULL, tds_get_byte(tds));
01470
01471 tds_add_row_column_size(info, curcol);
01472 }
01473
01474 by_cols = tds_get_byte(tds);
01475
01476 tdsdump_log(TDS_DBG_INFO1, "processing tds compute result. by_cols = %d\n", by_cols);
01477
01478 if (by_cols) {
01479 if ((info->bycolumns = (TDS_SMALLINT *) malloc(by_cols * sizeof(TDS_SMALLINT))) == NULL)
01480 return TDS_FAIL;
01481
01482 memset(info->bycolumns, '\0', by_cols * sizeof(TDS_SMALLINT));
01483 }
01484 info->by_cols = by_cols;
01485
01486 cur_by_col = info->bycolumns;
01487 for (col = 0; col < by_cols; col++) {
01488 *cur_by_col = tds_get_byte(tds);
01489 cur_by_col++;
01490 }
01491
01492 if ((info->current_row = tds_alloc_compute_row(info)) != NULL)
01493 return TDS_SUCCEED;
01494 else
01495 return TDS_FAIL;
01496 }
01497
01498
01499
01500
01501
01502
01503 static int
01504 tds7_get_data_info(TDSSOCKET * tds, TDSCOLUMN * curcol)
01505 {
01506 int colnamelen;
01507
01508 CHECK_TDS_EXTRA(tds);
01509 CHECK_COLUMN_EXTRA(curcol);
01510
01511
01512 curcol->column_usertype = tds_get_smallint(tds);
01513
01514 curcol->column_flags = tds_get_smallint(tds);
01515
01516 curcol->column_nullable = curcol->column_flags & 0x01;
01517 curcol->column_writeable = (curcol->column_flags & 0x08) > 0;
01518 curcol->column_identity = (curcol->column_flags & 0x10) > 0;
01519
01520 tds_set_column_type(tds, curcol, tds_get_byte(tds));
01521
01522 curcol->column_timestamp = (curcol->column_type == SYBBINARY && curcol->column_usertype == TDS_UT_TIMESTAMP);
01523
01524 switch (curcol->column_varint_size) {
01525 case 4:
01526 curcol->column_size = tds_get_int(tds);
01527 break;
01528 case 2:
01529 curcol->column_size = tds_get_smallint(tds);
01530 break;
01531 case 1:
01532 curcol->column_size = tds_get_byte(tds);
01533 break;
01534 case 0:
01535 break;
01536 }
01537
01538
01539 curcol->on_server.column_size = curcol->column_size;
01540
01541
01542 if (is_numeric_type(curcol->column_type)) {
01543 curcol->column_prec = tds_get_byte(tds);
01544 curcol->column_scale = tds_get_byte(tds);
01545
01546 }
01547
01548 if (IS_TDS80(tds) && is_collate_type(curcol->on_server.column_type)) {
01549
01550
01551
01552
01553
01554
01555 tds_get_n(tds, curcol->column_collation, 5);
01556 curcol->char_conv =
01557 tds_iconv_from_collate(tds, curcol->column_collation[4],
01558 curcol->column_collation[1] * 256 + curcol->column_collation[0]);
01559 }
01560
01561
01562 adjust_character_column_size(tds, curcol);
01563
01564 if (is_blob_type(curcol->column_type)) {
01565 curcol->table_namelen =
01566 tds_get_string(tds, tds_get_smallint(tds), curcol->table_name, sizeof(curcol->table_name) - 1);
01567 }
01568
01569
01570
01571
01572
01573 colnamelen = tds_get_string(tds, tds_get_byte(tds), curcol->column_name, sizeof(curcol->column_name) - 1);
01574 curcol->column_name[colnamelen] = 0;
01575 curcol->column_namelen = colnamelen;
01576
01577 tdsdump_log(TDS_DBG_INFO1, "tds7_get_data_info: \n"
01578 "\tcolname = %s (%d bytes)\n"
01579 "\ttype = %d (%s)\n"
01580 "\tserver's type = %d (%s)\n"
01581 "\tcolumn_varint_size = %d\n"
01582 "\tcolumn_size = %d (%d on server)\n",
01583 curcol->column_name, curcol->column_namelen,
01584 curcol->column_type, tds_prtype(curcol->column_type),
01585 curcol->on_server.column_type, tds_prtype(curcol->on_server.column_type),
01586 curcol->column_varint_size,
01587 curcol->column_size, curcol->on_server.column_size);
01588
01589 CHECK_COLUMN_EXTRA(curcol);
01590
01591 return TDS_SUCCEED;
01592 }
01593
01594
01595
01596
01597
01598
01599 static int
01600 tds7_process_result(TDSSOCKET * tds)
01601 {
01602 int col, num_cols;
01603 TDSCOLUMN *curcol;
01604 TDSRESULTINFO *info;
01605
01606 CHECK_TDS_EXTRA(tds);
01607 tdsdump_log(TDS_DBG_INFO1, "processing TDS7 result metadata.\n");
01608
01609
01610
01611 num_cols = tds_get_smallint(tds);
01612
01613
01614
01615 if (num_cols == -1) {
01616 tdsdump_log(TDS_DBG_INFO1, "no meta data\n");
01617 return TDS_SUCCEED;
01618 }
01619
01620 tds_free_all_results(tds);
01621 tds->rows_affected = TDS_NO_COUNT;
01622
01623 if ((info = tds_alloc_results(num_cols)) == NULL)
01624 return TDS_FAIL;
01625 tds->current_results = info;
01626 if (tds->cur_cursor) {
01627 tds->cur_cursor->res_info = info;
01628 tdsdump_log(TDS_DBG_INFO1, "set current_results to cursor->res_info\n");
01629 } else {
01630 tds->res_info = info;
01631 tdsdump_log(TDS_DBG_INFO1, "set current_results (%d column%s) to tds->res_info\n", num_cols, (num_cols==1? "":"s"));
01632 }
01633
01634
01635
01636
01637
01638
01639 for (col = 0; col < num_cols; col++) {
01640
01641 curcol = info->columns[col];
01642
01643 tdsdump_log(TDS_DBG_INFO1, "setting up column %d\n", col);
01644 tds7_get_data_info(tds, curcol);
01645
01646 tds_add_row_column_size(info, curcol);
01647 }
01648
01649
01650 if ((info->current_row = tds_alloc_row(info)) != NULL) {
01651 CHECK_TDS_EXTRA(tds);
01652 return TDS_SUCCEED;
01653 } else {
01654 CHECK_TDS_EXTRA(tds);
01655 return TDS_FAIL;
01656 }
01657 }
01658
01659
01660
01661
01662
01663
01664 static int
01665 tds_get_data_info(TDSSOCKET * tds, TDSCOLUMN * curcol, int is_param)
01666 {
01667 CHECK_TDS_EXTRA(tds);
01668 CHECK_COLUMN_EXTRA(curcol);
01669
01670 curcol->column_namelen = tds_get_string(tds, tds_get_byte(tds), curcol->column_name, sizeof(curcol->column_name) - 1);
01671 curcol->column_name[curcol->column_namelen] = '\0';
01672
01673 curcol->column_flags = tds_get_byte(tds);
01674 if (!is_param) {
01675
01676 if (IS_TDS50(tds))
01677 curcol->column_hidden = curcol->column_flags & 0x1;
01678 curcol->column_key = (curcol->column_flags & 0x2) > 1;
01679 curcol->column_writeable = (curcol->column_flags & 0x10) > 1;
01680 curcol->column_nullable = (curcol->column_flags & 0x20) > 1;
01681 curcol->column_identity = (curcol->column_flags & 0x40) > 1;
01682 }
01683
01684 curcol->column_usertype = tds_get_int(tds);
01685 tds_set_column_type(tds, curcol, tds_get_byte(tds));
01686
01687 tdsdump_log(TDS_DBG_INFO1, "processing result. type = %d(%s), varint_size %d\n",
01688 curcol->column_type, tds_prtype(curcol->column_type), curcol->column_varint_size);
01689 switch (curcol->column_varint_size) {
01690 case 4:
01691 curcol->column_size = tds_get_int(tds);
01692
01693 if (is_blob_type (curcol->column_type)) {
01694 curcol->table_namelen =
01695 tds_get_string(tds, tds_get_smallint(tds), curcol->table_name, sizeof(curcol->table_name) - 1);
01696 }
01697 break;
01698 case 2:
01699
01700 curcol->column_size = tds_get_smallint(tds);
01701 break;
01702 case 1:
01703 curcol->column_size = tds_get_byte(tds);
01704 break;
01705 case 0:
01706 break;
01707 }
01708 tdsdump_log(TDS_DBG_INFO1, "processing result. column_size %d\n", curcol->column_size);
01709
01710
01711 if (is_numeric_type(curcol->column_type)) {
01712 curcol->column_prec = tds_get_byte(tds);
01713 curcol->column_scale = tds_get_byte(tds);
01714
01715 }
01716
01717
01718
01719 if (IS_TDS80(tds) && is_collate_type(curcol->on_server.column_type)) {
01720 tds_get_n(tds, curcol->column_collation, 5);
01721 curcol->char_conv =
01722 tds_iconv_from_collate(tds, curcol->column_collation[4],
01723 curcol->column_collation[1] * 256 + curcol->column_collation[0]);
01724 }
01725
01726
01727 curcol->on_server.column_size = curcol->column_size;
01728 adjust_character_column_size(tds, curcol);
01729
01730 return TDS_SUCCEED;
01731 }
01732
01733
01734
01735
01736
01737
01738 static int
01739 tds_process_result(TDSSOCKET * tds)
01740 {
01741 int hdrsize;
01742 int col, num_cols;
01743 TDSCOLUMN *curcol;
01744 TDSRESULTINFO *info;
01745
01746 CHECK_TDS_EXTRA(tds);
01747
01748 tds_free_all_results(tds);
01749 tds->rows_affected = TDS_NO_COUNT;
01750
01751 hdrsize = tds_get_smallint(tds);
01752
01753
01754 num_cols = tds_get_smallint(tds);
01755
01756 if ((info = tds_alloc_results(num_cols)) == NULL)
01757 return TDS_FAIL;
01758 tds->current_results = info;
01759 if (tds->cur_cursor) {
01760 tds->cur_cursor->res_info = info;
01761 } else {
01762 tds->res_info = info;
01763 }
01764
01765
01766
01767
01768
01769 for (col = 0; col < info->num_cols; col++) {
01770 curcol = info->columns[col];
01771
01772 tds_get_data_info(tds, curcol, 0);
01773
01774
01775
01776 tds_get_n(tds, NULL, tds_get_byte(tds));
01777
01778 tds_add_row_column_size(info, curcol);
01779 }
01780 if ((info->current_row = tds_alloc_row(info)) != NULL)
01781 return TDS_SUCCEED;
01782 else
01783 return TDS_FAIL;
01784 }
01785
01786
01787
01788
01789
01790
01791 static int
01792 tds5_process_result(TDSSOCKET * tds)
01793 {
01794 int hdrsize;
01795
01796 int colnamelen;
01797 int col, num_cols;
01798 TDSCOLUMN *curcol;
01799 TDSRESULTINFO *info;
01800
01801 CHECK_TDS_EXTRA(tds);
01802
01803 tdsdump_log(TDS_DBG_INFO1, "tds5_process_result\n");
01804
01805
01806
01807
01808 tds_free_all_results(tds);
01809 tds->rows_affected = TDS_NO_COUNT;
01810
01811
01812
01813
01814 hdrsize = tds_get_int(tds);
01815
01816
01817 num_cols = tds_get_smallint(tds);
01818
01819 if ((info = tds_alloc_results(num_cols)) == NULL)
01820 return TDS_FAIL;
01821 tds->current_results = info;
01822 if (tds->cur_cursor) {
01823 tds->cur_cursor->res_info = info;
01824 }
01825 else
01826 tds->res_info = info;
01827
01828 tdsdump_log(TDS_DBG_INFO1, "num_cols=%d\n", num_cols);
01829
01830
01831
01832
01833
01834
01835 for (col = 0; col < info->num_cols; col++) {
01836 curcol = info->columns[col];
01837
01838
01839 curcol->column_namelen =
01840 tds_get_string(tds, tds_get_byte(tds), curcol->column_name, sizeof(curcol->column_name) - 1);
01841 curcol->column_name[curcol->column_namelen] = '\0';
01842
01843
01844
01845 colnamelen = tds_get_byte(tds);
01846 tds_get_n(tds, NULL, colnamelen);
01847
01848
01849
01850
01851
01852
01853 colnamelen = tds_get_byte(tds);
01854 tds_get_n(tds, NULL, colnamelen);
01855
01856
01857
01858
01859
01860
01861 curcol->table_namelen =
01862 tds_get_string(tds, tds_get_byte(tds), curcol->table_name, sizeof(curcol->table_name) - 1);
01863 curcol->table_name[curcol->table_namelen] = '\0';
01864
01865
01866 colnamelen = tds_get_byte(tds);
01867 if (colnamelen != 0) {
01868 if (curcol->column_namelen == 0) {
01869 tds_get_string(tds, colnamelen, curcol->column_name, sizeof(curcol->column_name) - 1);
01870 curcol->column_name[colnamelen] = '\0';
01871 curcol->column_namelen = colnamelen;
01872 }
01873 else {
01874 tds_get_n(tds, NULL, colnamelen);
01875 }
01876 }
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 curcol->column_flags = tds_get_int(tds);
01893 curcol->column_hidden = curcol->column_flags & 0x1;
01894 curcol->column_key = (curcol->column_flags & 0x2) > 1;
01895 curcol->column_writeable = (curcol->column_flags & 0x10) > 1;
01896 curcol->column_nullable = (curcol->column_flags & 0x20) > 1;
01897 curcol->column_identity = (curcol->column_flags & 0x40) > 1;
01898
01899 curcol->column_usertype = tds_get_int(tds);
01900
01901 tds_set_column_type(tds, curcol, tds_get_byte(tds));
01902
01903 switch (curcol->column_varint_size) {
01904 case 4:
01905 if (curcol->column_type == SYBTEXT || curcol->column_type == SYBIMAGE) {
01906 int namelen;
01907
01908 curcol->column_size = tds_get_int(tds);
01909
01910
01911 namelen = tds_get_smallint(tds);
01912 if (namelen)
01913 tds_get_n(tds, NULL, namelen);
01914
01915 } else {
01916 curcol->column_size = tds_get_int(tds);
01917 }
01918 break;
01919 case 2:
01920 curcol->column_size = tds_get_smallint(tds);
01921 break;
01922 case 1:
01923 curcol->column_size = tds_get_byte(tds);
01924 break;
01925 case 0:
01926 curcol->column_size = tds_get_size_by_type(curcol->column_type);
01927 break;
01928 }
01929
01930
01931 if (is_numeric_type(curcol->column_type)) {
01932 curcol->column_prec = tds_get_byte(tds);
01933 curcol->column_scale = tds_get_byte(tds);
01934
01935 }
01936
01937
01938 curcol->on_server.column_size = curcol->column_size;
01939 adjust_character_column_size(tds, curcol);
01940
01941
01942 tds_get_n(tds, NULL, tds_get_byte(tds));
01943
01944 tds_add_row_column_size(info, curcol);
01945
01946
01947
01948
01949 tdsdump_log(TDS_DBG_INFO1, "col %d:\n", col);
01950 tdsdump_log(TDS_DBG_INFO1, "tcolumn_label=[%s]\n", curcol->column_name);
01951
01952
01953
01954
01955
01956 tdsdump_log(TDS_DBG_INFO1, "\tflags=%x utype=%d type=%d varint=%d\n",
01957 curcol->column_flags, curcol->column_usertype, curcol->column_type, curcol->column_varint_size);
01958
01959 tdsdump_log(TDS_DBG_INFO1, "\tcolsize=%d prec=%d scale=%d\n",
01960 curcol->column_size, curcol->column_prec, curcol->column_scale);
01961 }
01962 if ((info->current_row = tds_alloc_row(info)) != NULL)
01963 return TDS_SUCCEED;
01964 else
01965 return TDS_FAIL;
01966 }
01967
01968
01969
01970
01971
01972 static int
01973 tds_process_compute(TDSSOCKET * tds, TDS_INT * computeid)
01974 {
01975 int i;
01976 TDSCOLUMN *curcol;
01977 TDSCOMPUTEINFO *info;
01978 TDS_INT compute_id;
01979
01980 CHECK_TDS_EXTRA(tds);
01981
01982 compute_id = tds_get_smallint(tds);
01983
01984 for (i = 0;; ++i) {
01985 if (i >= tds->num_comp_info)
01986 return TDS_FAIL;
01987 info = tds->comp_info[i];
01988 if (info->computeid == compute_id)
01989 break;
01990 }
01991 tds->current_results = info;
01992
01993 for (i = 0; i < info->num_cols; i++) {
01994 curcol = info->columns[i];
01995 if (tds_get_data(tds, curcol, info->current_row, i) != TDS_SUCCEED)
01996 return TDS_FAIL;
01997 }
01998 if (computeid)
01999 *computeid = compute_id;
02000 return TDS_SUCCEED;
02001 }
02002
02003
02004 static int
02005 tds_process_compute_095(TDSSOCKET * tds, TDS_INT * pcomputeid)
02006 {
02007 int i;
02008 TDSCOLUMN *curcol;
02009 TDSCOMPUTEINFO *info;
02010 TDS_INT id;
02011
02012 CHECK_TDS_EXTRA(tds);
02013
02014 id = tds_get_smallint(tds);
02015
02016 tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() found compute id %d\n", id);
02017
02018 for (i = 0;; ++i) {
02019 if (i >= tds->num_comp_info) {
02020 tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() FAIL: id exceeds bound (%d)\n", tds->num_comp_info);
02021 return TDS_FAIL;
02022 }
02023 info = tds->comp_info[i];
02024 if (info->computeid == id)
02025 break;
02026 }
02027 tds->current_results = info;
02028
02029 for (i = 0; i < info->num_cols; i++) {
02030 curcol = info->columns[i];
02031 if (tds_get_data(tds, curcol, info->current_row, i) != TDS_SUCCEED) {
02032 tdsdump_log(TDS_DBG_INFO1, "tds_process_compute() FAIL: tds_get_data() failed\n");
02033 return TDS_FAIL;
02034 }
02035 }
02036 if (pcomputeid)
02037 *pcomputeid = id;
02038 return TDS_SUCCEED;
02039 }
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050 static int
02051 tds_get_data(TDSSOCKET * tds, TDSCOLUMN * curcol, unsigned char *current_row, int i)
02052 {
02053 unsigned char *dest;
02054 int len, colsize;
02055 int fillchar;
02056 TDSBLOB *blob = NULL;
02057
02058 CHECK_TDS_EXTRA(tds);
02059 CHECK_COLUMN_EXTRA(curcol);
02060
02061 tdsdump_log(TDS_DBG_INFO1, "tds_get_data: type %d, varint size %d\n", curcol->column_type, curcol->column_varint_size);
02062 switch (curcol->column_varint_size) {
02063 case 4:
02064
02065
02066
02067
02068
02069
02070
02071
02072 if (curcol->column_type == SYBVARIANT) {
02073 colsize = tds_get_int(tds);
02074 tds_get_n(tds, NULL, colsize);
02075 curcol->column_cur_size = -1;
02076 return TDS_SUCCEED;
02077 }
02078
02079
02080 if (is_blob_type(curcol->column_type)) {
02081 len = tds_get_byte(tds);
02082 blob = (TDSBLOB *) & (current_row[curcol->column_offset]);
02083 if (len == 16) {
02084 tds_get_n(tds, blob->textptr, 16);
02085 tds_get_n(tds, blob->timestamp, 8);
02086 colsize = tds_get_int(tds);
02087 } else {
02088 colsize = -1;
02089 }
02090 break;
02091 }
02092
02093
02094 colsize = tds_get_int(tds);
02095 if (colsize == 0)
02096 colsize = -1;
02097 break;
02098 case 2:
02099 colsize = tds_get_smallint(tds);
02100 break;
02101 case 1:
02102 colsize = tds_get_byte(tds);
02103 if (colsize == 0)
02104 colsize = -1;
02105 break;
02106 case 0:
02107
02108 colsize = tds_get_size_by_type(curcol->column_type);
02109 break;
02110 default:
02111 colsize = -1;
02112 break;
02113 }
02114 if (IS_TDSDEAD(tds))
02115 return TDS_FAIL;
02116
02117 tdsdump_log(TDS_DBG_INFO1, "processing row. column size is %d \n", colsize);
02118
02119 if (colsize < 0) {
02120 curcol->column_cur_size = -1;
02121 return TDS_SUCCEED;
02122 }
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133 dest = &(current_row[curcol->column_offset]);
02134 if (is_numeric_type(curcol->column_type)) {
02135
02136
02137
02138
02139
02140
02141 TDS_NUMERIC *num = (TDS_NUMERIC *) dest;
02142 memset(num, '\0', sizeof(TDS_NUMERIC));
02143
02144 num->precision = curcol->column_prec;
02145 num->scale = curcol->column_scale;
02146
02147
02148
02149 if (colsize > sizeof(num->array))
02150 return TDS_FAIL;
02151 tds_get_n(tds, num->array, colsize);
02152
02153
02154 colsize = sizeof(TDS_NUMERIC);
02155 if (IS_TDS7_PLUS(tds)) {
02156 tdsdump_log(TDS_DBG_INFO1, "swapping numeric data...\n");
02157 tds_swap_numeric(num);
02158 }
02159 curcol->column_cur_size = colsize;
02160 } else if (is_blob_type(curcol->column_type)) {
02161 TDS_CHAR *p;
02162 int new_blob_size;
02163 assert(blob == (TDSBLOB *) dest);
02164
02165
02166
02167
02168
02169
02170
02171 new_blob_size = determine_adjusted_size(curcol->char_conv, colsize);
02172 if (new_blob_size == 0) {
02173 curcol->column_cur_size = 0;
02174 if (blob->textvalue)
02175 TDS_ZERO_FREE(blob->textvalue);
02176 return TDS_SUCCEED;
02177 }
02178
02179
02180 p = blob->textvalue;
02181 if (!p) {
02182 p = (TDS_CHAR *) malloc(new_blob_size);
02183 } else {
02184
02185 if (new_blob_size > curcol->column_cur_size || (curcol->column_cur_size - new_blob_size) > 10240) {
02186 p = (TDS_CHAR *) realloc(p, new_blob_size);
02187 }
02188 }
02189
02190 if (!p)
02191 return TDS_FAIL;
02192 blob->textvalue = p;
02193 curcol->column_cur_size = new_blob_size;
02194
02195
02196 if (is_char_type(curcol->column_type)) {
02197 if (tds_get_char_data(tds, (char *) blob, colsize, curcol) == TDS_FAIL)
02198 return TDS_FAIL;
02199 } else {
02200 assert(colsize == new_blob_size);
02201 tds_get_n(tds, blob->textvalue, colsize);
02202 }
02203 } else {
02204 curcol->column_cur_size = colsize;
02205
02206 if (curcol->char_conv) {
02207 if (tds_get_char_data(tds, (char *) dest, colsize, curcol) == TDS_FAIL)
02208 return TDS_FAIL;
02209 } else {
02210
02211
02212
02213
02214 int discard_len = 0;
02215 if (colsize > curcol->column_size) {
02216 discard_len = colsize - curcol->column_size;
02217 colsize = curcol->column_size;
02218 }
02219 if (tds_get_n(tds, dest, colsize) == NULL)
02220 return TDS_FAIL;
02221 if (discard_len > 0)
02222 tds_get_n(tds, NULL, discard_len);
02223 curcol->column_cur_size = colsize;
02224 }
02225
02226
02227 fillchar = 0;
02228 switch (curcol->column_type) {
02229
02230 case SYBLONGBINARY:
02231 if (curcol->column_usertype != USER_UNICHAR_TYPE)
02232 break;
02233 case SYBCHAR:
02234 case XSYBCHAR:
02235 if (curcol->column_size != curcol->on_server.column_size)
02236 break;
02237
02238 fillchar = ' ';
02239 case SYBBINARY:
02240 case XSYBBINARY:
02241 if (colsize < curcol->column_size)
02242 memset(dest + colsize, fillchar, curcol->column_size - colsize);
02243 colsize = curcol->column_size;
02244 break;
02245 }
02246
02247 if (curcol->column_type == SYBDATETIME4) {
02248 tdsdump_log(TDS_DBG_INFO1, "datetime4 %d %d %d %d\n", dest[0], dest[1], dest[2], dest[3]);
02249 }
02250 }
02251
02252 #ifdef WORDS_BIGENDIAN
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 if (tds->broken_dates &&
02265 (curcol->column_type == SYBDATETIME ||
02266 curcol->column_type == SYBDATETIME4 ||
02267 curcol->column_type == SYBDATETIMN ||
02268 curcol->column_type == SYBMONEY ||
02269 curcol->column_type == SYBMONEY4 || (curcol->column_type == SYBMONEYN && curcol->column_size > 4)))
02270
02271
02272
02273
02274 {
02275 unsigned char temp_buf[8];
02276
02277 memcpy(temp_buf, dest, colsize / 2);
02278 memcpy(dest, &dest[colsize / 2], colsize / 2);
02279 memcpy(&dest[colsize / 2], temp_buf, colsize / 2);
02280 }
02281 if (tds->emul_little_endian) {
02282 tdsdump_log(TDS_DBG_INFO1, "swapping coltype %d\n", tds_get_conversion_type(curcol->column_type, colsize));
02283 tds_swap_datatype(tds_get_conversion_type(curcol->column_type, colsize), dest);
02284 }
02285 #endif
02286 return TDS_SUCCEED;
02287 }
02288
02289
02290
02291
02292 static int
02293 tds_process_row(TDSSOCKET * tds)
02294 {
02295 int i;
02296 TDSCOLUMN *curcol;
02297 TDSRESULTINFO *info;
02298
02299 CHECK_TDS_EXTRA(tds);
02300
02301 info = tds->current_results;
02302 if (!info)
02303 return TDS_FAIL;
02304
02305 assert(info->num_cols > 0);
02306
02307 info->row_count++;
02308 for (i = 0; i < info->num_cols; i++) {
02309 tdsdump_log(TDS_DBG_INFO1, "tds_process_row(): reading column %d \n", i);
02310 curcol = info->columns[i];
02311 if (tds_get_data(tds, curcol, info->current_row, i) != TDS_SUCCEED)
02312 return TDS_FAIL;
02313 }
02314 return TDS_SUCCEED;
02315 }
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325 static int
02326 tds_process_end(TDSSOCKET * tds, int marker, int *flags_parm)
02327 {
02328 int more_results, was_cancelled, error, done_count_valid;
02329 int tmp, state;
02330
02331 CHECK_TDS_EXTRA(tds);
02332
02333 tmp = tds_get_smallint(tds);
02334
02335 state = tds_get_smallint(tds);
02336
02337 more_results = (tmp & TDS_DONE_MORE_RESULTS) != 0;
02338 was_cancelled = (tmp & TDS_DONE_CANCELLED) != 0;
02339 error = (tmp & TDS_DONE_ERROR) != 0;
02340 done_count_valid = (tmp & TDS_DONE_COUNT) != 0;
02341
02342
02343 tdsdump_log(TDS_DBG_FUNC, "tds_process_end: more_results = %d\n"
02344 "\t\twas_cancelled = %d\n"
02345 "\t\terror = %d\n"
02346 "\t\tdone_count_valid = %d\n", more_results, was_cancelled, error, done_count_valid);
02347
02348 if (tds->res_info) {
02349 tds->res_info->more_results = more_results;
02350 if (tds->current_results == NULL)
02351 tds->current_results = tds->res_info;
02352
02353 }
02354
02355 if (flags_parm)
02356 *flags_parm = tmp;
02357
02358 if (was_cancelled || (!more_results && !tds->in_cancel)) {
02359 tdsdump_log(TDS_DBG_FUNC, "tds_process_end() state set to TDS_IDLE\n");
02360
02361 tds->in_cancel = 0;
02362 tds_set_state(tds, TDS_IDLE);
02363 if (!tds->query_timeout && tds->save_query_timeout)
02364 tds->query_timeout = tds->save_query_timeout;
02365 }
02366
02367 if (IS_TDSDEAD(tds))
02368 return TDS_FAIL;
02369
02370
02371
02372
02373
02374
02375 if (done_count_valid) {
02376 tds->rows_affected = tds_get_int(tds);
02377 tdsdump_log(TDS_DBG_FUNC, " rows_affected = %d\n", tds->rows_affected);
02378 } else {
02379 tmp = tds_get_int(tds);
02380 tds->rows_affected = TDS_NO_COUNT;
02381 }
02382
02383 if (IS_TDSDEAD(tds))
02384 return TDS_FAIL;
02385
02386 return TDS_SUCCEED;
02387 }
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403 int
02404 tds_client_msg(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, int msgno, int severity, int state, int line, const char *msg_text)
02405 {
02406 int ret;
02407 TDSMESSAGE msg;
02408
02409 CHECK_CONTEXT_EXTRA(tds_ctx);
02410 if (tds)
02411 CHECK_TDS_EXTRA(tds);
02412
02413 if (tds_ctx->err_handler) {
02414 memset(&msg, 0, sizeof(TDSMESSAGE));
02415 msg.msgno = msgno;
02416 msg.severity = severity;
02417 msg.state = state;
02418
02419 msg.server = strdup("OpenClient");
02420 msg.line_number = line;
02421 msg.message = strdup(msg_text);
02422 if (msg.sql_state == NULL)
02423 msg.sql_state = tds_alloc_client_sqlstate(msg.msgno);
02424 ret = tds_ctx->err_handler(tds_ctx, tds, &msg);
02425 tds_free_msg(&msg);
02426 #if 1
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436 #else
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447 if (ret && tds) {
02448
02449 tds_set_state(tds, TDS_DEAD);
02450 }
02451 #endif
02452 }
02453
02454 tdsdump_log(TDS_DBG_FUNC, "tds_client_msg: #%d: \"%s\". Connection state is now %d. \n", msgno, msg_text, tds ? (int)tds->state : -1);
02455
02456 return 0;
02457 }
02458
02459
02460
02461
02462
02463
02464
02465
02466 static int
02467 tds_process_env_chg(TDSSOCKET * tds)
02468 {
02469 int size, type;
02470 char *oldval = NULL;
02471 char *newval = NULL;
02472 char **dest;
02473 int new_block_size;
02474 int lcid;
02475 int memrc = 0;
02476
02477 CHECK_TDS_EXTRA(tds);
02478
02479 size = tds_get_smallint(tds);
02480
02481
02482
02483
02484
02485
02486
02487 type = tds_get_byte(tds);
02488
02489
02490
02491
02492
02493 if (type == TDS_ENV_SQLCOLLATION) {
02494
02495 size = tds_get_byte(tds);
02496 memset(tds->collation, 0, 5);
02497 if (size < 5) {
02498 tds_get_n(tds, tds->collation, size);
02499 } else {
02500 tds_get_n(tds, tds->collation, 5);
02501 tds_get_n(tds, NULL, size - 5);
02502 lcid = (tds->collation[0] + ((int) tds->collation[1] << 8) + ((int) tds->collation[2] << 16)) & 0xffffflu;
02503 tds7_srv_charset_changed(tds, tds->collation[4], lcid);
02504 }
02505
02506 tds_get_n(tds, NULL, tds_get_byte(tds));
02507 return TDS_SUCCEED;
02508 }
02509
02510
02511 memrc += tds_alloc_get_string(tds, &newval, tds_get_byte(tds));
02512
02513
02514 memrc += tds_alloc_get_string(tds, &oldval, tds_get_byte(tds));
02515
02516 if (memrc != 0) {
02517 if (newval != NULL)
02518 free(newval);
02519 if (oldval != NULL)
02520 free(oldval);
02521 return TDS_FAIL;
02522 }
02523
02524 dest = NULL;
02525 switch (type) {
02526 case TDS_ENV_PACKSIZE:
02527 new_block_size = atoi(newval);
02528 if (new_block_size > tds->env.block_size) {
02529 tdsdump_log(TDS_DBG_INFO1, "increasing block size from %s to %d\n", oldval, new_block_size);
02530
02531
02532
02533
02534
02535
02536 tds_realloc_socket(tds, new_block_size);
02537 }
02538 break;
02539 case TDS_ENV_DATABASE:
02540 dest = &tds->env.database;
02541 break;
02542 case TDS_ENV_LANG:
02543 dest = &tds->env.language;
02544 break;
02545 case TDS_ENV_CHARSET:
02546 dest = &tds->env.charset;
02547 tds_srv_charset_changed(tds, newval);
02548 break;
02549 }
02550 if (tds->env_chg_func) {
02551 (*(tds->env_chg_func)) (tds, type, oldval, newval);
02552 }
02553
02554 if (oldval)
02555 free(oldval);
02556 if (newval) {
02557 if (dest) {
02558 if (*dest)
02559 free(*dest);
02560 *dest = newval;
02561 } else
02562 free(newval);
02563 }
02564
02565 return TDS_SUCCEED;
02566 }
02567
02568
02569
02570
02571
02572
02573 static int
02574 tds_process_msg(TDSSOCKET * tds, int marker)
02575 {
02576 int rc;
02577 int len;
02578 int len_sqlstate;
02579 int has_eed = 0;
02580 TDSMESSAGE msg;
02581
02582 CHECK_TDS_EXTRA(tds);
02583
02584
02585 memset(&msg, 0, sizeof(TDSMESSAGE));
02586
02587
02588 len = tds_get_smallint(tds);
02589
02590
02591 rc = tds_get_int(tds);
02592 msg.msgno = rc;
02593
02594
02595 msg.state = tds_get_byte(tds);
02596
02597
02598 msg.severity = tds_get_byte(tds);
02599
02600
02601 switch (marker) {
02602 case TDS_EED_TOKEN:
02603 if (msg.severity <= 10)
02604 msg.priv_msg_type = 0;
02605 else
02606 msg.priv_msg_type = 1;
02607
02608
02609 len_sqlstate = tds_get_byte(tds);
02610 msg.sql_state = (char *) malloc(len_sqlstate + 1);
02611 if (!msg.sql_state) {
02612 tds_free_msg(&msg);
02613 return TDS_FAIL;
02614 }
02615
02616 tds_get_n(tds, msg.sql_state, len_sqlstate);
02617 msg.sql_state[len_sqlstate] = '\0';
02618
02619
02620 if (strcmp(msg.sql_state, "ZZZZZ") == 0)
02621 TDS_ZERO_FREE(msg.sql_state);
02622
02623
02624 has_eed = tds_get_byte(tds);
02625
02626
02627 tds_get_smallint(tds);
02628 break;
02629 case TDS_INFO_TOKEN:
02630 msg.priv_msg_type = 0;
02631 break;
02632 case TDS_ERROR_TOKEN:
02633 msg.priv_msg_type = 1;
02634 break;
02635 default:
02636 tdsdump_log(TDS_DBG_ERROR, "tds_process_msg() called with unknown marker '%d'!\n", (int) marker);
02637 tds_free_msg(&msg);
02638 return TDS_FAIL;
02639 }
02640
02641 tdsdump_log(TDS_DBG_ERROR, "tds_process_msg() reading message from server\n");
02642
02643 rc = 0;
02644
02645 rc += tds_alloc_get_string(tds, &msg.message, tds_get_smallint(tds));
02646
02647
02648 rc += tds_alloc_get_string(tds, &msg.server, tds_get_byte(tds));
02649
02650
02651 rc += tds_alloc_get_string(tds, &msg.proc_name, tds_get_byte(tds));
02652
02653
02654 msg.line_number = tds_get_smallint(tds);
02655
02656
02657
02658
02659
02660
02661
02662 if (msg.sql_state == NULL)
02663 msg.sql_state = tds_alloc_lookup_sqlstate(tds, msg.msgno);
02664
02665
02666
02667 if (has_eed == 1) {
02668 int next_marker;
02669 for (;;) {
02670 switch (next_marker = tds_get_byte(tds)) {
02671 case TDS5_PARAMFMT_TOKEN:
02672 case TDS5_PARAMFMT2_TOKEN:
02673 case TDS5_PARAMS_TOKEN:
02674 if (tds_process_default_tokens(tds, next_marker) != TDS_SUCCEED)
02675 ++rc;
02676 continue;
02677 }
02678 break;
02679 }
02680 tds_unget_byte(tds);
02681 }
02682
02683
02684
02685
02686
02687
02688
02689 if (rc != 0) {
02690 tds_free_msg(&msg);
02691 return TDS_ERROR;
02692 }
02693
02694
02695 if (marker == TDS_EED_TOKEN && tds->cur_dyn && !TDS_IS_MSSQL(tds) && msg.msgno == 2782) {
02696
02697 tds->cur_dyn->emulated = 1;
02698
02699
02700
02701
02702
02703 } else {
02704
02705 tds->cur_dyn = NULL;
02706
02707 if (tds->tds_ctx->msg_handler) {
02708 tdsdump_log(TDS_DBG_ERROR, "tds_process_msg() calling client msg handler\n");
02709 tds->tds_ctx->msg_handler(tds->tds_ctx, tds, &msg);
02710 } else if (msg.msgno) {
02711 tdsdump_log(TDS_DBG_WARN,
02712 "Msg %d, Severity %d, State %d, Server %s, Line %d\n%s\n",
02713 msg.msgno,
02714 msg.severity ,
02715 msg.state, msg.server, msg.line_number, msg.message);
02716 }
02717 }
02718
02719 tds_free_msg(&msg);
02720
02721 tdsdump_log(TDS_DBG_ERROR, "tds_process_msg() returning TDS_SUCCEED\n");
02722
02723 return TDS_SUCCEED;
02724 }
02725
02726
02727
02728
02729
02730
02731 static int
02732 tds_alloc_get_string(TDSSOCKET * tds, char **string, int len)
02733 {
02734 char *s;
02735 int out_len;
02736
02737 CHECK_TDS_EXTRA(tds);
02738
02739 if (len < 0) {
02740 *string = NULL;
02741 return 0;
02742 }
02743
02744
02745 s = (char *) malloc(len * 4 + 1);
02746 out_len = tds_get_string(tds, len, s, len * 4);
02747 if (!s) {
02748 *string = NULL;
02749 return -1;
02750 }
02751 s = realloc(s, out_len + 1);
02752 s[out_len] = '\0';
02753 *string = s;
02754 return 0;
02755 }
02756
02757
02758
02759
02760
02761
02762 int
02763 tds_process_cancel(TDSSOCKET * tds)
02764 {
02765 CHECK_TDS_EXTRA(tds);
02766
02767
02768 if (!tds->in_cancel)
02769 return TDS_SUCCEED;
02770
02771 if (tds->state != TDS_PENDING)
02772 return TDS_SUCCEED;
02773
02774 tds->query_start_time = 0;
02775 tds->query_timeout = 0;
02776
02777
02778 for (;;) {
02779 TDS_INT result_type;
02780
02781 switch (tds_process_tokens(tds, &result_type, NULL, 0)) {
02782 case TDS_FAIL:
02783 return TDS_FAIL;
02784 case TDS_CANCELLED:
02785 case TDS_SUCCEED:
02786 case TDS_NO_MORE_RESULTS:
02787 return TDS_SUCCEED;
02788 }
02789 }
02790 }
02791
02792
02793
02794
02795
02796
02797
02798 TDSDYNAMIC *
02799 tds_lookup_dynamic(TDSSOCKET * tds, char *id)
02800 {
02801 TDSDYNAMIC *curr;
02802
02803 CHECK_TDS_EXTRA(tds);
02804
02805 for (curr = tds->dyns; curr != NULL; curr = curr->next) {
02806 if (!strcmp(curr->id, id))
02807 return curr;
02808 }
02809 return NULL;
02810 }
02811
02812
02813
02814
02815
02816 static TDSDYNAMIC *
02817 tds_process_dynamic(TDSSOCKET * tds)
02818 {
02819 int token_sz;
02820 unsigned char type, status;
02821 int id_len;
02822 char id[TDS_MAX_DYNID_LEN + 1];
02823 int drain = 0;
02824
02825 CHECK_TDS_EXTRA(tds);
02826
02827 token_sz = tds_get_smallint(tds);
02828 type = tds_get_byte(tds);
02829 status = tds_get_byte(tds);
02830
02831 if (type != 0x20) {
02832 tdsdump_log(TDS_DBG_ERROR, "Unrecognized TDS5_DYN type %x\n", type);
02833 tds_get_n(tds, NULL, token_sz - 2);
02834 return NULL;
02835 }
02836 id_len = tds_get_byte(tds);
02837 if (id_len > TDS_MAX_DYNID_LEN) {
02838 drain = id_len - TDS_MAX_DYNID_LEN;
02839 id_len = TDS_MAX_DYNID_LEN;
02840 }
02841 id_len = tds_get_string(tds, id_len, id, TDS_MAX_DYNID_LEN);
02842 id[id_len] = '\0';
02843 if (drain) {
02844 tds_get_string(tds, drain, NULL, drain);
02845 }
02846 return tds_lookup_dynamic(tds, id);
02847 }
02848
02849 static int
02850 tds_process_dyn_result(TDSSOCKET * tds)
02851 {
02852 int hdrsize;
02853 int col, num_cols;
02854 TDSCOLUMN *curcol;
02855 TDSPARAMINFO *info;
02856 TDSDYNAMIC *dyn;
02857
02858 CHECK_TDS_EXTRA(tds);
02859
02860 hdrsize = tds_get_smallint(tds);
02861 num_cols = tds_get_smallint(tds);
02862
02863 if (tds->cur_dyn) {
02864 dyn = tds->cur_dyn;
02865 tds_free_param_results(dyn->res_info);
02866
02867 if ((dyn->res_info = tds_alloc_results(num_cols)) == NULL)
02868 return TDS_FAIL;
02869 info = dyn->res_info;
02870 } else {
02871 tds_free_param_results(tds->param_info);
02872 if ((tds->param_info = tds_alloc_results(num_cols)) == NULL)
02873 return TDS_FAIL;
02874 info = tds->param_info;
02875 }
02876 tds->current_results = info;
02877
02878 for (col = 0; col < info->num_cols; col++) {
02879 curcol = info->columns[col];
02880
02881 tds_get_data_info(tds, curcol, 1);
02882
02883
02884 tds_get_n(tds, NULL, tds_get_byte(tds));
02885
02886 tds_add_row_column_size(info, curcol);
02887 }
02888
02889 if ((info->current_row = tds_alloc_row(info)) != NULL)
02890 return TDS_SUCCEED;
02891 else
02892 return TDS_FAIL;
02893 }
02894
02895
02896
02897
02898 static int
02899 tds5_process_dyn_result2(TDSSOCKET * tds)
02900 {
02901 int hdrsize;
02902 int col, num_cols;
02903 TDSCOLUMN *curcol;
02904 TDSPARAMINFO *info;
02905 TDSDYNAMIC *dyn;
02906
02907 CHECK_TDS_EXTRA(tds);
02908
02909 hdrsize = tds_get_int(tds);
02910 num_cols = tds_get_smallint(tds);
02911
02912 if (tds->cur_dyn) {
02913 dyn = tds->cur_dyn;
02914 tds_free_param_results(dyn->res_info);
02915
02916 if ((dyn->res_info = tds_alloc_results(num_cols)) == NULL)
02917 return TDS_FAIL;
02918 info = dyn->res_info;
02919 } else {
02920 tds_free_param_results(tds->param_info);
02921 if ((tds->param_info = tds_alloc_results(num_cols)) == NULL)
02922 return TDS_FAIL;
02923 info = tds->param_info;
02924 }
02925 tds->current_results = info;
02926
02927 for (col = 0; col < info->num_cols; col++) {
02928 curcol = info->columns[col];
02929
02930
02931
02932
02933 curcol->column_namelen =
02934 tds_get_string(tds, tds_get_byte(tds), curcol->column_name, sizeof(curcol->column_name) - 1);
02935 curcol->column_name[curcol->column_namelen] = '\0';
02936
02937
02938 curcol->column_flags = tds_get_int(tds);
02939 curcol->column_nullable = (curcol->column_flags & 0x20) > 0;
02940
02941
02942 curcol->column_usertype = tds_get_int(tds);
02943
02944
02945 tds_set_column_type(tds, curcol, tds_get_byte(tds));
02946
02947
02948 curcol->column_varint_size = tds5_get_varint_size(curcol->column_type);
02949
02950 switch (curcol->column_varint_size) {
02951 case 4:
02952 if (curcol->column_type == SYBTEXT || curcol->column_type == SYBIMAGE) {
02953 curcol->column_size = tds_get_int(tds);
02954
02955 curcol->table_namelen =
02956 tds_get_string(tds, tds_get_smallint(tds), curcol->table_name,
02957 sizeof(curcol->table_name) - 1);
02958 } else {
02959 curcol->column_size = tds_get_int(tds);
02960
02961 }
02962 break;
02963 case 2:
02964 curcol->column_size = tds_get_smallint(tds);
02965 break;
02966 case 1:
02967 curcol->column_size = tds_get_byte(tds);
02968 break;
02969 case 0:
02970 break;
02971 }
02972
02973
02974 if (is_numeric_type(curcol->column_type)) {
02975 curcol->column_prec = tds_get_byte(tds);
02976 curcol->column_scale = tds_get_byte(tds);
02977
02978 }
02979
02980
02981 curcol->on_server.column_size = curcol->column_size;
02982 adjust_character_column_size(tds, curcol);
02983
02984
02985 tds_get_n(tds, NULL, tds_get_byte(tds));
02986
02987 tds_add_row_column_size(info, curcol);
02988
02989 tdsdump_log(TDS_DBG_INFO1, "elem %d:\n", col);
02990 tdsdump_log(TDS_DBG_INFO1, "\tcolumn_name=[%s]\n", curcol->column_name);
02991 tdsdump_log(TDS_DBG_INFO1, "\tflags=%x utype=%d type=%d varint=%d\n",
02992 curcol->column_flags, curcol->column_usertype, curcol->column_type, curcol->column_varint_size);
02993 tdsdump_log(TDS_DBG_INFO1, "\tcolsize=%d prec=%d scale=%d\n",
02994 curcol->column_size, curcol->column_prec, curcol->column_scale);
02995 }
02996
02997 if ((info->current_row = tds_alloc_row(info)) != NULL)
02998 return TDS_SUCCEED;
02999 else
03000 return TDS_FAIL;
03001 }
03002
03003
03004
03005
03006
03007 int
03008 tds_get_token_size(int marker)
03009 {
03010
03011 switch (marker) {
03012 case TDS_DONE_TOKEN:
03013 case TDS_DONEPROC_TOKEN:
03014 case TDS_DONEINPROC_TOKEN:
03015 return 8;
03016 case TDS_RETURNSTATUS_TOKEN:
03017 return 4;
03018 case TDS_PROCID_TOKEN:
03019 return 8;
03020 default:
03021 return 0;
03022 }
03023 }
03024
03025 void
03026 tds_swap_datatype(int coltype, unsigned char *buf)
03027 {
03028 switch (coltype) {
03029 case SYBINT2:
03030 tds_swap_bytes(buf, 2);
03031 break;
03032 case SYBINT4:
03033 case SYBMONEY4:
03034 case SYBREAL:
03035 tds_swap_bytes(buf, 4);
03036 break;
03037 case SYBINT8:
03038 case SYBFLT8:
03039 tds_swap_bytes(buf, 8);
03040 break;
03041 case SYBMONEY:
03042 case SYBDATETIME:
03043 tds_swap_bytes(buf, 4);
03044 tds_swap_bytes(&buf[4], 4);
03045 break;
03046 case SYBDATETIME4:
03047 tds_swap_bytes(buf, 2);
03048 tds_swap_bytes(&buf[2], 2);
03049 break;
03050 case SYBUNIQUE:
03051 tds_swap_bytes(buf, 4);
03052 tds_swap_bytes(&buf[4], 2);
03053 tds_swap_bytes(&buf[6], 2);
03054 break;
03055 }
03056 }
03057
03058 void
03059 tds_swap_numeric(TDS_NUMERIC *num)
03060 {
03061
03062 num->array[0] = (num->array[0] == 0) ? 1 : 0;
03063
03064 tds_swap_bytes(&(num->array[1]), tds_numeric_bytes_per_prec[num->precision] - 1);
03065 }
03066
03067
03068
03069
03070
03071
03072
03073
03074 static int
03075 tds5_get_varint_size(int datatype)
03076 {
03077 switch (datatype) {
03078 case SYBLONGBINARY:
03079 case XSYBCHAR:
03080 case SYBTEXT:
03081 case SYBNTEXT:
03082 case SYBIMAGE:
03083 case SYBVARIANT:
03084 return 4;
03085
03086 case SYBVOID:
03087 case SYBINT1:
03088 case SYBBIT:
03089 case SYBINT2:
03090 case SYBINT4:
03091 case SYBINT8:
03092 case SYBDATETIME4:
03093 case SYBREAL:
03094 case SYBMONEY:
03095 case SYBDATETIME:
03096 case SYBFLT8:
03097 case SYBMONEY4:
03098 case SYBSINT1:
03099 case SYBUINT2:
03100 case SYBUINT4:
03101 case SYBUINT8:
03102 return 0;
03103
03104 case XSYBNVARCHAR:
03105 case XSYBVARCHAR:
03106 case XSYBBINARY:
03107 case XSYBVARBINARY:
03108 return 2;
03109
03110 default:
03111 return 1;
03112 }
03113 }
03114
03115
03116
03117
03118 static int
03119 tds_process_compute_names(TDSSOCKET * tds)
03120 {
03121 int hdrsize;
03122 int remainder;
03123 int num_cols = 0;
03124 int col;
03125 int memrc = 0;
03126 TDS_SMALLINT compute_id = 0;
03127 TDS_TINYINT namelen;
03128 TDSCOMPUTEINFO *info;
03129 TDSCOLUMN *curcol;
03130
03131 struct namelist
03132 {
03133 char name[256];
03134 int namelen;
03135 struct namelist *nextptr;
03136 };
03137
03138 struct namelist *topptr = NULL;
03139 struct namelist *curptr = NULL;
03140 struct namelist *freeptr = NULL;
03141
03142 CHECK_TDS_EXTRA(tds);
03143
03144 hdrsize = tds_get_smallint(tds);
03145 remainder = hdrsize;
03146 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. remainder = %d\n", remainder);
03147
03148
03149
03150
03151
03152
03153
03154 compute_id = tds_get_smallint(tds);
03155 remainder -= 2;
03156
03157 while (remainder) {
03158 namelen = tds_get_byte(tds);
03159 remainder--;
03160 if (topptr == NULL) {
03161 if ((topptr = (struct namelist *) malloc(sizeof(struct namelist))) == NULL) {
03162 memrc = -1;
03163 break;
03164 }
03165 curptr = topptr;
03166 curptr->nextptr = NULL;
03167 } else {
03168 if ((curptr->nextptr = (struct namelist *) malloc(sizeof(struct namelist))) == NULL) {
03169 memrc = -1;
03170 break;
03171 }
03172 curptr = curptr->nextptr;
03173 curptr->nextptr = NULL;
03174 }
03175 if (namelen == 0)
03176 strcpy(curptr->name, "");
03177 else {
03178 namelen = tds_get_string(tds, namelen, curptr->name, sizeof(curptr->name) - 1);
03179 curptr->name[namelen] = 0;
03180 remainder -= namelen;
03181 }
03182 curptr->namelen = namelen;
03183 num_cols++;
03184 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. remainder = %d\n", remainder);
03185 }
03186
03187 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. num_cols = %d\n", num_cols);
03188
03189 if ((tds->comp_info = tds_alloc_compute_results(tds, num_cols, 0)) == NULL)
03190 memrc = -1;
03191
03192 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. num_comp_info = %d\n", tds->num_comp_info);
03193
03194 info = tds->comp_info[tds->num_comp_info - 1];
03195 tds->current_results = info;
03196
03197 info->computeid = compute_id;
03198
03199 curptr = topptr;
03200
03201 if (memrc == 0) {
03202 for (col = 0; col < num_cols; col++) {
03203 curcol = info->columns[col];
03204
03205 assert(strlen(curcol->column_name) == curcol->column_namelen);
03206 memcpy(curcol->column_name, curptr->name, curptr->namelen + 1);
03207 curcol->column_namelen = curptr->namelen;
03208
03209 freeptr = curptr;
03210 curptr = curptr->nextptr;
03211 free(freeptr);
03212 }
03213 return TDS_SUCCEED;
03214 } else {
03215 while (curptr != NULL) {
03216 freeptr = curptr;
03217 curptr = curptr->nextptr;
03218 free(freeptr);
03219 }
03220 return TDS_FAIL;
03221 }
03222 }
03223
03224
03225 static int
03226 tds_process_compute_names_095(TDSSOCKET * tds)
03227 {
03228 int hdrsize;
03229 int remainder;
03230 int num_cols = 0;
03231 int col;
03232 int memrc = 0;
03233 TDS_SMALLINT compute_id = 0;
03234 TDS_TINYINT namelen;
03235 TDSCOMPUTEINFO *info;
03236 TDSCOLUMN *curcol;
03237
03238 struct namelist
03239 {
03240 char name[256];
03241 int namelen;
03242 struct namelist *nextptr;
03243 };
03244
03245 struct namelist *topptr = NULL;
03246 struct namelist *curptr = NULL;
03247 struct namelist *nextptr = NULL;
03248
03249 CHECK_TDS_EXTRA(tds);
03250
03251 hdrsize = tds_get_smallint(tds);
03252 remainder = hdrsize;
03253 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. remainder = %d\n", remainder);
03254
03255
03256
03257
03258
03259
03260
03261 compute_id = tds_get_smallint(tds);
03262 remainder -= 2;
03263
03264 while (remainder > 0) {
03265 namelen = tds_get_byte(tds);
03266 remainder--;
03267 if ((nextptr = (struct namelist *) malloc(sizeof(struct namelist))) == NULL) {
03268 memrc = -1;
03269 break;
03270 }
03271 if (topptr == NULL)
03272 topptr = nextptr;
03273 else
03274 curptr->nextptr = nextptr;
03275 curptr = nextptr;
03276 curptr->nextptr = NULL;
03277 remainder -= namelen;
03278 namelen = tds_get_string(tds, namelen, curptr->name, sizeof(curptr->name) - 1);
03279 curptr->name[namelen] = 0;
03280 curptr->namelen = namelen;
03281 num_cols++;
03282 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. remainder = %d\n", remainder);
03283 }
03284
03285 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. num_cols = %d\n", num_cols);
03286
03287 if ((tds->comp_info = tds_alloc_compute_results(tds, num_cols, 0)) == NULL)
03288 memrc = -1;
03289
03290 tdsdump_log(TDS_DBG_INFO1, "processing tds5 compute names. num_comp_info = %d\n", tds->num_comp_info);
03291
03292 info = tds->comp_info[tds->num_comp_info - 1];
03293 tds->current_results = info;
03294
03295 info->computeid = compute_id;
03296
03297 curptr = topptr;
03298
03299 if (memrc == 0) {
03300 for (col = 0; col < num_cols; col++) {
03301 curcol = info->columns[col];
03302
03303 assert(strlen(curcol->column_name) == curcol->column_namelen);
03304 memcpy(curcol->column_name, curptr->name, curptr->namelen + 1);
03305 curcol->column_namelen = curptr->namelen;
03306
03307 nextptr = curptr->nextptr;
03308 free(curptr);
03309 curptr = nextptr;
03310 }
03311 return TDS_SUCCEED;
03312 } else {
03313 while (curptr != NULL) {
03314 nextptr = curptr->nextptr;
03315 free(curptr);
03316 curptr = nextptr;
03317 }
03318 return TDS_FAIL;
03319 }
03320 }
03321
03322
03323
03324
03325
03326 static int
03327 tds7_process_compute_result(TDSSOCKET * tds)
03328 {
03329 int col, num_cols;
03330 TDS_TINYINT by_cols;
03331 TDS_SMALLINT *cur_by_col;
03332 TDS_SMALLINT compute_id;
03333 TDSCOLUMN *curcol;
03334 TDSCOMPUTEINFO *info;
03335
03336 CHECK_TDS_EXTRA(tds);
03337
03338
03339
03340
03341
03342
03343
03344 num_cols = tds_get_smallint(tds);
03345
03346 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. num_cols = %d\n", num_cols);
03347
03348
03349
03350
03351
03352
03353
03354 compute_id = tds_get_smallint(tds);
03355
03356 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. compute_id = %d\n", compute_id);
03357
03358
03359
03360
03361
03362
03363 by_cols = tds_get_byte(tds);
03364 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. by_cols = %d\n", by_cols);
03365
03366 if ((tds->comp_info = tds_alloc_compute_results(tds, num_cols, by_cols)) == NULL)
03367 return TDS_FAIL;
03368
03369 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. num_comp_info = %d\n", tds->num_comp_info);
03370
03371 info = tds->comp_info[tds->num_comp_info - 1];
03372 tds->current_results = info;
03373
03374 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 0\n");
03375
03376 info->computeid = compute_id;
03377
03378
03379
03380
03381
03382
03383 cur_by_col = info->bycolumns;
03384 for (col = 0; col < by_cols; col++) {
03385 *cur_by_col = tds_get_smallint(tds);
03386 cur_by_col++;
03387 }
03388 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 1\n");
03389
03390 for (col = 0; col < num_cols; col++) {
03391 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 2\n");
03392 curcol = info->columns[col];
03393
03394 curcol->column_operator = tds_get_byte(tds);
03395 curcol->column_operand = tds_get_smallint(tds);
03396
03397 tds7_get_data_info(tds, curcol);
03398
03399 if (!curcol->column_namelen) {
03400 strcpy(curcol->column_name, tds_pr_op(curcol->column_operator));
03401 curcol->column_namelen = strlen(curcol->column_name);
03402 }
03403
03404 tds_add_row_column_size(info, curcol);
03405 }
03406
03407
03408 tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 5 \n");
03409 if ((info->current_row = tds_alloc_compute_row(info)) != NULL)
03410 return TDS_SUCCEED;
03411 else
03412 return TDS_FAIL;
03413 }
03414
03415 static int
03416 tds_process_cursor_tokens(TDSSOCKET * tds)
03417 {
03418 TDS_SMALLINT hdrsize;
03419 TDS_INT rowcount;
03420 TDS_INT cursor_id;
03421 TDS_TINYINT namelen;
03422 unsigned char cursor_cmd;
03423 TDS_SMALLINT cursor_status;
03424 TDSCURSOR *cursor;
03425
03426 CHECK_TDS_EXTRA(tds);
03427
03428 hdrsize = tds_get_smallint(tds);
03429 cursor_id = tds_get_int(tds);
03430 hdrsize -= sizeof(TDS_INT);
03431 if (cursor_id == 0){
03432 namelen = tds_get_byte(tds);
03433 hdrsize -= 1;
03434
03435 tds_get_n(tds, NULL, namelen);
03436 hdrsize -= namelen;
03437 }
03438 cursor_cmd = tds_get_byte(tds);
03439 cursor_status = tds_get_smallint(tds);
03440 hdrsize -= 3;
03441
03442 if (hdrsize == sizeof(TDS_INT))
03443 rowcount = tds_get_int(tds);
03444
03445 if (tds->cur_cursor) {
03446 cursor = tds->cur_cursor;
03447 cursor->cursor_id = cursor_id;
03448 cursor->srv_status = cursor_status;
03449 if ((cursor_status & TDS_CUR_ISTAT_DEALLOC) != 0)
03450 tds_free_cursor(tds, cursor);
03451
03452 }
03453 return TDS_SUCCEED;
03454 }
03455
03456 static int
03457 tds5_process_optioncmd(TDSSOCKET * tds)
03458 {
03459 TDS_SMALLINT length;
03460 TDS_INT command;
03461 TDS_INT option;
03462 TDS_INT argsize;
03463 TDS_INT arg;
03464
03465 CHECK_TDS_EXTRA(tds);
03466
03467 tdsdump_log(TDS_DBG_INFO1, "tds5_process_optioncmd()\n");
03468
03469 assert(IS_TDS50(tds));
03470
03471 length = tds_get_smallint(tds);
03472 command = tds_get_byte(tds);
03473 option = tds_get_byte(tds);
03474 argsize = tds_get_byte(tds);
03475
03476 switch (argsize) {
03477 case 0:
03478 arg = 0;
03479 break;
03480 case 1:
03481 arg = tds_get_byte(tds);
03482 break;
03483 case 4:
03484 arg = tds_get_int(tds);
03485 break;
03486 default:
03487 tdsdump_log(TDS_DBG_INFO1, "oops: cannot process option of size %d\n", argsize);
03488 assert(argsize <= 4);
03489 exit(1);
03490 break;
03491 }
03492 tdsdump_log(TDS_DBG_INFO1, "received option %d value %d\n", option, arg);
03493
03494 if (command != TDS_OPT_INFO)
03495 return TDS_FAIL;
03496
03497 tds->option_value = arg;
03498
03499 return TDS_SUCCEED;
03500 }
03501
03502 static const char *
03503 tds_pr_op(int op)
03504 {
03505 #define TYPE(con, s) case con: return s; break
03506 switch (op) {
03507 TYPE(SYBAOPAVG, "avg");
03508 TYPE(SYBAOPAVGU, "avg");
03509 TYPE(SYBAOPCNT, "count");
03510 TYPE(SYBAOPCNTU, "count");
03511 TYPE(SYBAOPMAX, "max");
03512 TYPE(SYBAOPMIN, "min");
03513 TYPE(SYBAOPSUM, "sum");
03514 TYPE(SYBAOPSUMU, "sum");
03515 TYPE(SYBAOPCHECKSUM_AGG, "checksum_agg");
03516 TYPE(SYBAOPCNT_BIG, "count");
03517 TYPE(SYBAOPSTDEV, "stdevp");
03518 TYPE(SYBAOPSTDEVP, "stdevp");
03519 TYPE(SYBAOPVAR, "var");
03520 TYPE(SYBAOPVARP, "varp");
03521 default:
03522 break;
03523 }
03524 return "";
03525 #undef TYPE
03526 }
03527
03528 const char *
03529 tds_prtype(int token)
03530 {
03531 #define TYPE(con, s) case con: return s; break
03532 switch (token) {
03533 TYPE(SYBAOPAVG, "avg");
03534 TYPE(SYBAOPCNT, "count");
03535 TYPE(SYBAOPMAX, "max");
03536 TYPE(SYBAOPMIN, "min");
03537 TYPE(SYBAOPSUM, "sum");
03538
03539 TYPE(SYBBINARY, "binary");
03540 TYPE(SYBLONGBINARY, "longbinary");
03541 TYPE(SYBBIT, "bit");
03542 TYPE(SYBBITN, "bit-null");
03543 TYPE(SYBCHAR, "char");
03544 TYPE(SYBDATETIME4, "smalldatetime");
03545 TYPE(SYBDATETIME, "datetime");
03546 TYPE(SYBDATETIMN, "datetime-null");
03547 TYPE(SYBDECIMAL, "decimal");
03548 TYPE(SYBFLT8, "float");
03549 TYPE(SYBFLTN, "float-null");
03550 TYPE(SYBIMAGE, "image");
03551 TYPE(SYBINT1, "tinyint");
03552 TYPE(SYBINT2, "smallint");
03553 TYPE(SYBINT4, "int");
03554 TYPE(SYBINT8, "bigint");
03555 TYPE(SYBINTN, "integer-null");
03556 TYPE(SYBMONEY4, "smallmoney");
03557 TYPE(SYBMONEY, "money");
03558 TYPE(SYBMONEYN, "money-null");
03559 TYPE(SYBNTEXT, "UCS-2 text");
03560 TYPE(SYBNVARCHAR, "UCS-2 varchar");
03561 TYPE(SYBNUMERIC, "numeric");
03562 TYPE(SYBREAL, "real");
03563 TYPE(SYBTEXT, "text");
03564 TYPE(SYBUNIQUE, "uniqueidentifier");
03565 TYPE(SYBVARBINARY, "varbinary");
03566 TYPE(SYBVARCHAR, "varchar");
03567 TYPE(SYBVARIANT, "variant");
03568 TYPE(SYBVOID, "void");
03569 TYPE(XSYBBINARY, "xbinary");
03570 TYPE(XSYBCHAR, "xchar");
03571 TYPE(XSYBNCHAR, "x UCS-2 char");
03572 TYPE(XSYBNVARCHAR, "x UCS-2 varchar");
03573 TYPE(XSYBVARBINARY, "xvarbinary");
03574 TYPE(XSYBVARCHAR, "xvarchar");
03575 default:
03576 break;
03577 }
03578 return "";
03579 #undef TYPE
03580 }
03581
03582
03583
03584 static const char *
03585 _tds_token_name(unsigned char marker)
03586 {
03587 switch (marker) {
03588
03589 case 0x20:
03590 return "TDS5_PARAMFMT2";
03591 case 0x22:
03592 return "ORDERBY2";
03593 case 0x61:
03594 return "ROWFMT2";
03595 case 0x71:
03596 return "LOGOUT";
03597 case 0x79:
03598 return "RETURNSTATUS";
03599 case 0x7C:
03600 return "PROCID";
03601 case 0x81:
03602 return "TDS7_RESULT";
03603 case 0x88:
03604 return "TDS7_COMPUTE_RESULT";
03605 case 0xA0:
03606 return "COLNAME";
03607 case 0xA1:
03608 return "COLFMT";
03609 case 0xA3:
03610 return "DYNAMIC2";
03611 case 0xA4:
03612 return "TABNAME";
03613 case 0xA5:
03614 return "COLINFO";
03615 case 0xA7:
03616 return "COMPUTE_NAMES";
03617 case 0xA8:
03618 return "COMPUTE_RESULT";
03619 case 0xA9:
03620 return "ORDERBY";
03621 case 0xAA:
03622 return "ERROR";
03623 case 0xAB:
03624 return "INFO";
03625 case 0xAC:
03626 return "PARAM";
03627 case 0xAD:
03628 return "LOGINACK";
03629 case 0xAE:
03630 return "CONTROL";
03631 case 0xD1:
03632 return "ROW";
03633 case 0xD3:
03634 return "CMP_ROW";
03635 case 0xD7:
03636 return "TDS5_PARAMS";
03637 case 0xE2:
03638 return "CAPABILITY";
03639 case 0xE3:
03640 return "ENVCHANGE";
03641 case 0xE5:
03642 return "EED";
03643 case 0xE6:
03644 return "DBRPC";
03645 case 0xE7:
03646 return "TDS5_DYNAMIC";
03647 case 0xEC:
03648 return "TDS5_PARAMFMT";
03649 case 0xED:
03650 return "AUTH";
03651 case 0xEE:
03652 return "RESULT";
03653 case 0xFD:
03654 return "DONE";
03655 case 0xFE:
03656 return "DONEPROC";
03657 case 0xFF:
03658 return "DONEINPROC";
03659
03660 default:
03661 break;
03662 }
03663
03664 return "";
03665 }
03666
03667
03668
03669
03670 static void
03671 adjust_character_column_size(const TDSSOCKET * tds, TDSCOLUMN * curcol)
03672 {
03673 CHECK_TDS_EXTRA(tds);
03674 CHECK_COLUMN_EXTRA(curcol);
03675
03676 if (is_unicode_type(curcol->on_server.column_type))
03677 curcol->char_conv = tds->char_convs[client2ucs2];
03678
03679
03680 if (curcol->on_server.column_type == SYBLONGBINARY && (
03681 curcol->column_usertype == USER_UNICHAR_TYPE ||
03682 curcol->column_usertype == USER_UNIVARCHAR_TYPE)) {
03683
03684
03685 curcol->char_conv = tds->char_convs[client2ucs2];
03686 }
03687
03688
03689 if (!curcol->char_conv && IS_TDS7_PLUS(tds) && is_ascii_type(curcol->on_server.column_type))
03690 curcol->char_conv = tds->char_convs[client2server_chardata];
03691
03692 if (!curcol->char_conv)
03693 return;
03694
03695 curcol->on_server.column_size = curcol->column_size;
03696 curcol->column_size = determine_adjusted_size(curcol->char_conv, curcol->column_size);
03697
03698 tdsdump_log(TDS_DBG_INFO1, "adjust_character_column_size:\n"
03699 "\tServer charset: %s\n"
03700 "\tServer column_size: %d\n"
03701 "\tClient charset: %s\n"
03702 "\tClient column_size: %d\n",
03703 curcol->char_conv->server_charset.name,
03704 curcol->on_server.column_size,
03705 curcol->char_conv->client_charset.name,
03706 curcol->column_size);
03707 }
03708
03709
03710
03711
03712
03713
03714
03715
03716 static int
03717 determine_adjusted_size(const TDSICONV * char_conv, int size)
03718 {
03719 if (!char_conv)
03720 return size;
03721
03722
03723 if (char_conv->client_charset.max_bytes_per_char > 1 &&
03724 INT_MAX / char_conv->client_charset.max_bytes_per_char < size
03725 ) {
03726 size = INT_MAX;
03727 } else {
03728 size *= char_conv->client_charset.max_bytes_per_char;
03729 }
03730
03731 if (size % char_conv->server_charset.min_bytes_per_char
03732 && INT_MAX - char_conv->server_charset.min_bytes_per_char >= size)
03733 {
03734 size += char_conv->server_charset.min_bytes_per_char;
03735 }
03736 size /= char_conv->server_charset.min_bytes_per_char;
03737
03738 return size;
03739 }
03740
03741