token.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:50k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: token.c,v $
  4.  * PRODUCTION Revision 1000.1  2004/04/01 21:01:24  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [CORE_002] Dev-tree R1.5
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include "tds.h"
  29. #include "tdsutil.h"
  30. #include "tdsconvert.h"
  31. #ifdef DMALLOC
  32. #include <dmalloc.h>
  33. #endif
  34. static char  software_version[]   = "$Id: token.c,v 1000.1 2004/04/01 21:01:24 gouriano Exp $";
  35. static void *no_unused_var_warn[] = {software_version,
  36.                                      no_unused_var_warn};
  37. static int tds_process_msg(TDSSOCKET *tds,int marker);
  38. static int tds_process_compute_result(TDSSOCKET *tds);
  39. static int tds_process_result(TDSSOCKET *tds);
  40. static int tds_process_col_name(TDSSOCKET *tds);
  41. static int tds_process_col_info(TDSSOCKET *tds);
  42. static int tds_process_compute(TDSSOCKET *tds);
  43. static int tds_process_row(TDSSOCKET *tds);
  44. static int tds_process_param_result(TDSSOCKET *tds);
  45. static int tds7_process_result(TDSSOCKET *tds);
  46. static int tds_process_param_result_tokens(TDSSOCKET *tds);
  47. static void tds_process_dyn_result(TDSSOCKET *tds);
  48. static int tds_process_dynamic(TDSSOCKET *tds);
  49. static int tds_process_auth(TDSSOCKET *tds);
  50. static int tds_get_varint_size(int datatype);
  51. static int tds_get_cardinal_type(int datatype);
  52. void tds_swap_datatype(int coltype, unsigned char *buf);
  53. /*
  54. ** The following little table is indexed by precision and will
  55. ** tell us the number of bytes required to store the specified
  56. ** precision.
  57. */
  58. extern const int g__numeric_bytes_per_prec[];
  59. /*
  60. ** tds_process_default_tokens() is a catch all function that is called to
  61. ** process tokens not known to other tds_process_* routines
  62. */
  63. int tds_process_default_tokens(TDSSOCKET *tds, int marker)
  64. {
  65. int order_len;
  66. int tok_size;
  67. int   more_results;
  68. int   cancelled;
  69.    tdsdump_log(TDS_DBG_FUNC, "%L inside tds_process_default_tokens() marker is %xn", marker);
  70.    if (!tds->s) {
  71.         tdsdump_log(TDS_DBG_FUNC, "%L leaving tds_process_default_tokens() connection deadn");
  72. tds->state=TDS_DEAD;
  73. return TDS_FAIL;
  74.    }
  75.    switch(marker) {
  76. case TDS_AUTH_TOKEN:
  77. tds_process_auth(tds);
  78. break;
  79. case TDS_ENV_CHG_TOKEN:
  80.       {
  81.          tds_process_env_chg(tds);
  82.          break;
  83.       }
  84.       case TDS_DONE_TOKEN:
  85.       case TDS_DONEPROC_TOKEN:
  86.       case TDS_DONEINPROC_TOKEN:
  87.       {
  88.          tds_process_end(tds, marker, &more_results, &cancelled);
  89.          if (!more_results) tds->state=TDS_COMPLETED;
  90.          break;
  91.       }
  92.       case TDS_124_TOKEN:
  93.          tds_get_n(tds,NULL,8);
  94.          break;
  95.       case TDS_RET_STAT_TOKEN:
  96. tds->has_status=1;
  97. tds->ret_status=tds_get_int(tds);
  98.         break;
  99.       case TDS_ERR_TOKEN:
  100.       case TDS_MSG_TOKEN:
  101.       case TDS_EED_TOKEN:
  102.          return tds_process_msg(tds,marker);
  103.          break;
  104.       case TDS_CAP_TOKEN:
  105.  tok_size = tds_get_smallint(tds);
  106.          tds_get_n(tds,tds->capabilities,tok_size > TDS_MAX_CAPABILITY ? TDS_MAX_CAPABILITY : tok_size);
  107.          break;
  108.       case TDS_LOGIN_ACK_TOKEN:
  109.          tds_get_n(tds,NULL,tds_get_smallint(tds));
  110.          break;
  111.       case TDS_ORDER_BY_TOKEN:
  112.          order_len = tds_get_smallint(tds);
  113.          tds_get_n(tds, NULL, order_len);
  114.          /* get the next token which is ROW_TOKEN (209)
  115. tds_get_byte(tds);
  116. if(orderLen > 1)
  117. tds_process_column_row(tds); */
  118.          break;
  119.       case TDS_168_TOKEN:
  120.          tds_process_compute_result(tds); 
  121.          break;
  122.       case TDS_PARAM_TOKEN: 
  123.  tds_unget_byte(tds);
  124.  tds_process_param_result_tokens(tds);
  125.          break;
  126.          /* 167 is somehow related to compute columns */
  127.       case TDS_167_TOKEN:
  128.       case TDS_174_TOKEN: 
  129.          tds_get_n(tds, NULL, tds_get_smallint(tds));
  130.          break;
  131.       case TDS7_RESULT_TOKEN:
  132.          tds7_process_result(tds); 
  133.          break;
  134.       case TDS_RESULT_TOKEN:
  135.          tds_process_result(tds); 
  136.          break;
  137.       case TDS_COL_NAME_TOKEN:
  138.          tds_process_col_name(tds); 
  139.          break;
  140.       case TDS_COL_INFO_TOKEN:
  141.          tds_process_col_info(tds); 
  142.          break;
  143.       case TDS_CMP_ROW_TOKEN:
  144.          tds_process_compute(tds); 
  145.          break;
  146.       case TDS_ROW_TOKEN:
  147.          tds_process_row(tds); 
  148.          break;
  149.       case TDS5_DYN_TOKEN:
  150.       case TDS5_DYNRES_TOKEN:
  151.       case TDS5_DYN3_TOKEN:
  152. #ifdef NCBI_FTDS
  153.    case TDS_COL_INFO_TOKEN2:
  154. #endif
  155.  tdsdump_log(TDS_DBG_WARN, "eating token %dn",marker);
  156.          tds_get_n(tds, NULL, tds_get_smallint(tds));
  157.          break;
  158.       default:
  159.  tdsdump_log(TDS_DBG_ERROR, "Unknown marker: %d(%x)!!n",marker,(unsigned char)marker); 
  160.          return TDS_FAIL;
  161.    }
  162.    return TDS_SUCCEED;
  163. }
  164. /*
  165. ** tds_process_login_tokens() is called after sending the login packet 
  166. ** to the server.  It returns the success or failure of the login 
  167. ** dependent on the protocol version. 4.2 sends an ACK token only when
  168. ** successful, TDS 5.0 sends it always with a success byte within
  169. */
  170. int tds_process_login_tokens(TDSSOCKET *tds)
  171. {
  172. int succeed=0;
  173. int marker;
  174. int len;
  175. unsigned char major_ver, minor_ver;
  176. unsigned char ack;
  177. #ifdef WORDS_BIGENDIAN
  178. char *tmpbuf;
  179. #endif
  180. tdsdump_log(TDS_DBG_FUNC, "%L inside tds_process_login_tokens()n");
  181. /* get_incoming(tds->s); */
  182. do {
  183. marker=tds_get_byte(tds);
  184. switch(marker) {
  185. case TDS_AUTH_TOKEN:
  186. tds_process_auth(tds);
  187. break;
  188. case TDS_LOGIN_ACK_TOKEN:
  189. len = tds_get_smallint(tds);
  190. ack = tds_get_byte(tds);
  191. major_ver = tds_get_byte(tds);
  192. minor_ver = tds_get_byte(tds);
  193. tds_get_n(tds, NULL, len-4);
  194. tds_get_byte(tds);
  195. #ifdef WORDS_BIGENDIAN
  196. /*
  197. if (major_ver==7) {
  198. tds->broken_dates=1;
  199. }
  200. */
  201. #endif
  202. /*
  203. tmpbuf = (char *) malloc(len);
  204. tds_get_n(tds, tmpbuf, len);
  205. tdsdump_log(TDS_DBG_INFO1, "%L login ack marker = %dn%Dn", marker, tmpbuf, len);
  206. free(tmpbuf);
  207. */
  208. /* TDS 5.0 reports 5 on success 6 on failure
  209. ** TDS 4.2 reports 1 on success and is not
  210. ** present on failure */
  211. if (ack==5 || ack==1) succeed=TDS_SUCCEED;
  212. break;
  213. default:
  214. if (tds_process_default_tokens(tds,marker)==TDS_FAIL)
  215. return TDS_FAIL;
  216. break;
  217. }
  218. } while (marker!=TDS_DONE_TOKEN);
  219. tdsdump_log(TDS_DBG_FUNC, "%L leaving tds_process_login_tokens() returning %dn",succeed);
  220. return succeed;
  221. }
  222. static int tds_process_auth(TDSSOCKET *tds)
  223. {
  224. int pdu_size, ntlm_size;
  225. char nonce[10];
  226. /* char domain[30]; */
  227. int where = 0;
  228. pdu_size = tds_get_smallint(tds);
  229. tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN PDU size %dn", pdu_size);
  230. tds_get_n(tds, NULL, 8); /* NTLMSSP */ 
  231. where += 8;
  232. tds_get_int(tds); /* sequence -> 2 */
  233. where += 4;
  234. tds_get_n(tds, NULL, 4); /* domain len (2 time) */
  235. where += 4;
  236. ntlm_size = tds_get_int(tds); /* size of remainder of ntlmssp packet */
  237. where += 4;
  238. tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN NTLMSSP size %dn", ntlm_size);
  239. tds_get_n(tds, NULL, 4); /* flags */
  240. where += 4;
  241. tds_get_n(tds, nonce, 8); 
  242. where += 8;
  243. tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN noncen");
  244. tdsdump_dump_buf(nonce, 8);
  245. tds_get_n(tds, NULL, 8); 
  246. where += 8;
  247. /*
  248. tds_get_ntstring(tds, domain, 30); 
  249. tdsdump_log(TDS_DBG_INFO1, "TDS_AUTH_TOKEN domain %sn", domain);
  250. where += strlen(domain);
  251. */
  252. tds_get_n(tds, NULL, pdu_size - where); 
  253. tdsdump_log(TDS_DBG_INFO1,"%L Draining %d bytesn", pdu_size - where);
  254. tds7_send_auth(tds, nonce);
  255. return TDS_SUCCEED;
  256. }
  257. /*
  258. ** tds_process_result_tokens() is called after submitting a query with
  259. ** tds_submit_query() and is responsible for calling the routines to
  260. ** populate tds->res_info if appropriate (some query have no result sets)
  261. */
  262. int tds_process_result_tokens(TDSSOCKET *tds)
  263. {
  264. int result=0;
  265. int marker;
  266. int more_results = 0;
  267. int cancelled;
  268. int retcode=TDS_NO_MORE_RESULTS;
  269. int rc;
  270. if (tds->state==TDS_COMPLETED) {
  271. /* tds_process_row() now eats the end marker and sets
  272. ** state to TDS_COMPLETED
  273. */
  274. return TDS_NO_MORE_RESULTS;
  275. }
  276. /* get_incoming(tds->s); */
  277. do {
  278. marker=tds_get_byte(tds);
  279. tdsdump_log(TDS_DBG_INFO1, "%L processing result tokens.  marker is  %xn", marker);
  280. switch(marker) {
  281.        case TDS_ERR_TOKEN:
  282.        case TDS_MSG_TOKEN:
  283.        case TDS_EED_TOKEN:
  284. rc = tds_process_msg(tds,marker);
  285. /* don't fail until we get a DONE */
  286. if (rc == TDS_ERROR) 
  287. retcode=TDS_FAIL;
  288. break;
  289. case TDS7_RESULT_TOKEN:
  290. if (!result) {
  291. tds7_process_result(tds);
  292. result++;
  293. } else {
  294. tds_unget_byte(tds);
  295. return TDS_SUCCEED;
  296. }
  297. break;
  298. case TDS_RESULT_TOKEN:
  299. if (!result) {
  300. tds_process_result(tds);
  301. result++;
  302. } else {
  303. tds_unget_byte(tds);
  304. return TDS_SUCCEED;
  305. }
  306. break;
  307. case TDS_COL_NAME_TOKEN:
  308. if (!result) {
  309. tds_process_col_name(tds);
  310. result++;
  311. } else {
  312. tds_unget_byte(tds);
  313. return TDS_SUCCEED;
  314. }
  315. break;
  316. case TDS_ROW_TOKEN:
  317. if (!result) {
  318. } else {
  319. tds->res_info->rows_exist=1;
  320. tds_unget_byte(tds);
  321. return TDS_SUCCEED;
  322. }
  323. #ifdef NCBI_FTDS
  324.              break; /* <-- looks like it should be here (v. soussov) */
  325. #endif
  326.        case TDS_RET_STAT_TOKEN:
  327. tds->has_status=1;
  328. tds->ret_status=tds_get_int(tds);
  329. /* return TDS_SUCCEED; */
  330. break;
  331. case TDS5_DYN_TOKEN:
  332. tds->cur_dyn_elem = tds_process_dynamic(tds);
  333. break;
  334.        case TDS5_DYNRES_TOKEN:
  335. tds_process_dyn_result(tds);
  336. break;
  337. case TDS_DONE_TOKEN:
  338. case TDS_DONEPROC_TOKEN:
  339. case TDS_DONEINPROC_TOKEN:
  340. tds_process_end(tds, marker, 
  341. &more_results, 
  342. &cancelled);
  343. break;
  344. default:
  345. if (tds_process_default_tokens(tds, marker)==TDS_FAIL) 
  346. return TDS_FAIL;
  347. break;
  348. }
  349. } while (!is_end_token(marker) || more_results);
  350. tds->state=TDS_COMPLETED;
  351. return retcode;
  352. }
  353. /* 
  354. ** tds_process_row_tokens() is called once a result set has been obtained
  355. ** with tds_process_result_tokens(). It calls tds_process_row() to copy
  356. ** data into the row buffer.
  357. */
  358. int tds_process_row_tokens(TDSSOCKET *tds)
  359. {
  360. int marker;
  361. int   more_results;
  362. int   cancelled;
  363. if (tds->state==TDS_COMPLETED) {
  364. return TDS_NO_MORE_ROWS;
  365. }
  366. while (1) {
  367. marker=tds_get_byte(tds);
  368.         tdsdump_log(TDS_DBG_INFO1, "%L processing row tokens.  marker is  %xn", marker);
  369. switch(marker) {
  370. case TDS_RESULT_TOKEN:
  371. case TDS7_RESULT_TOKEN:
  372. tds_unget_byte(tds);
  373. return TDS_NO_MORE_ROWS;
  374. case TDS_ROW_TOKEN:
  375. tds_process_row(tds);
  376. return TDS_SUCCEED;
  377. case TDS_DONE_TOKEN:
  378. case TDS_DONEPROC_TOKEN:
  379. case TDS_DONEINPROC_TOKEN:
  380. tds_process_end(tds, marker, 
  381. &more_results, 
  382. &cancelled);
  383. tds->res_info->more_results = more_results;
  384. return TDS_NO_MORE_ROWS;
  385. default:
  386. if (tds_process_default_tokens(tds,marker)==TDS_FAIL)
  387. return TDS_FAIL;
  388. break;
  389. }
  390. return TDS_SUCCEED;
  391. }
  392. /* 
  393. ** tds_process_col_name() is one half of the result set under TDS 4.2
  394. ** it contains all the column names, a TDS_COLINFO_TOKEN should 
  395. ** immediately follow this token with the datatype/size information
  396. ** This is a 4.2 only function
  397. */
  398. static int tds_process_col_name(TDSSOCKET *tds)
  399. {
  400. int hdrsize, len=0;
  401. int col,num_cols=0;
  402. struct tmp_col_struct {
  403. char *column_name;
  404. int column_namelen;
  405. struct tmp_col_struct *next;
  406. };
  407. struct tmp_col_struct *head=NULL, *cur=NULL, *prev;
  408. TDSCOLINFO *curcol;
  409. TDSRESULTINFO *info;
  410. hdrsize = tds_get_smallint(tds);
  411. /* this is a little messy...TDS 5.0 gives the number of columns
  412. ** upfront, while in TDS 4.2, you're expected to figure it out
  413. ** by the size of the message. So, I use a link list to get the
  414. ** colum names and then allocate the result structure, copy
  415. ** and delete the linked list */
  416. while (len<hdrsize) {
  417. prev = cur;
  418. cur = (struct tmp_col_struct *) 
  419. malloc(sizeof (struct tmp_col_struct));
  420. if (prev) prev->next=cur;
  421. if (!head) head = cur;
  422. cur->column_namelen = tds_get_byte(tds);
  423. cur->column_name = (char *) malloc(cur->column_namelen+1);
  424. tds_get_n(tds,cur->column_name, cur->column_namelen);
  425. cur->column_name[cur->column_namelen]='';
  426. cur->next=NULL;
  427. len += cur->column_namelen + 1;
  428. num_cols++;
  429. }
  430. /* free results/computes/params etc... */
  431. tds_free_all_results(tds);
  432. tds->res_info = tds_alloc_results(num_cols);
  433. info = tds->res_info;
  434. /* tell the upper layers we are processing results */
  435. tds->state = TDS_PENDING; 
  436. cur=head;
  437. for (col=0;col<info->num_cols;col++) 
  438. {
  439. curcol=info->columns[col];
  440. curcol->column_namelen = cur->column_namelen;
  441. strncpy(curcol->column_name, cur->column_name, 
  442. sizeof(curcol->column_name));
  443. prev=cur; cur=cur->next;
  444. free(prev->column_name);
  445. free(prev);
  446. }
  447. return TDS_SUCCEED;
  448. /* 
  449. ** tds_process_col_info() is the other half of result set processing
  450. ** under TDS 4.2. It follows tds_process_col_name(). It contains all the 
  451. ** column type and size information.
  452. ** This is a 4.2 only function
  453. */
  454. static int tds_process_col_info(TDSSOCKET *tds)
  455. {
  456. int col,hdrsize;
  457. TDSCOLINFO *curcol;
  458. TDSRESULTINFO *info;
  459. TDS_SMALLINT tabnamesize;
  460. int bytes_read = 0;
  461. int rest;
  462. /* XXX do a best check for alignment than this */
  463. union { void *p; int i; } align_struct;
  464. const int align = sizeof(align_struct);
  465. int remainder;
  466. char ci_flags[4];
  467. hdrsize = tds_get_smallint(tds);
  468. info = tds->res_info;
  469. for (col=0; col<info->num_cols; col++) 
  470. {
  471. curcol=info->columns[col];
  472. /* Used to ignore next 4 bytes, now we'll actually parse (some of)
  473. the data in them. (mlilback, 11/7/01) */
  474. tds_get_n(tds, ci_flags, 4);
  475. curcol->column_nullable = ci_flags[3] & 0x01;
  476. curcol->column_writeable = (ci_flags[3] & 0x08) > 0;
  477. curcol->column_identity = (ci_flags[3] & 0x10) > 0;
  478. /* on with our regularly scheduled code (mlilback, 11/7/01) */
  479. curcol->column_type = tds_get_byte(tds);
  480. curcol->column_varint_size  = tds_get_varint_size(curcol->column_type);
  481.         tdsdump_log(TDS_DBG_INFO1, "%L processing result. type = %d, varint_size %dn", 
  482.                     curcol->column_type, curcol->column_varint_size);
  483. switch(curcol->column_varint_size) {
  484. case 4: 
  485. curcol->column_size = tds_get_int(tds);
  486. /* junk the table name -- for now */
  487.     tabnamesize = tds_get_smallint(tds);
  488. #ifdef NCBI_FTDS
  489.              tds_get_n(tds,curcol->full_column_name,tabnamesize);
  490.              curcol->full_column_name[tabnamesize]='.';
  491.              strcpy(curcol->full_column_name+tabnamesize+1,curcol->column_name);
  492. #else             
  493.     tds_get_n(tds,NULL,tabnamesize);
  494. #endif
  495.     bytes_read += 5+4+2+tabnamesize;
  496. break;
  497. case 1: 
  498. curcol->column_size = tds_get_byte(tds);
  499.     bytes_read += 5+1;
  500. break;
  501. case 0: 
  502. curcol->column_size = get_size_by_type(curcol->column_type);
  503.     bytes_read += 5+0;
  504. break;
  505. }
  506. if (is_blob_type(curcol->column_type)) {
  507. curcol->column_offset = info->row_size;
  508. } else {
  509. curcol->column_offset = info->row_size;
  510. info->row_size += curcol->column_size + 1;
  511. }
  512. if (IS_TDS42(tds)) {
  513. remainder = info->row_size % align; 
  514. if (remainder)
  515. info->row_size += (align - remainder);
  516. }
  517. }
  518. /* get the rest of the bytes */
  519. rest = hdrsize - bytes_read;
  520. if (rest > 0) {
  521. tdsdump_log(TDS_DBG_INFO1,"NOTE:tds_process_col_info: draining %d bytesn", rest);
  522. tds_get_n(tds, NULL, rest);
  523. }
  524. info->current_row = tds_alloc_row(info);
  525. return TDS_SUCCEED;
  526. }
  527. /*
  528. ** tds_process_param_result() processes output parameters of a stored 
  529. ** procedure. This differs from regular row/compute results in that there
  530. ** is no total number of parameters given, they just show up singley.
  531. */
  532. static int tds_process_param_result(TDSSOCKET *tds)
  533. {
  534. int hdrsize;
  535. int column_type;
  536. int column_size, actual_size;
  537. hdrsize = tds_get_smallint(tds);
  538. tds_get_string(tds, NULL, tds_get_byte(tds)); /* column name */
  539. tds_get_n(tds, NULL, 5); /* unknown */
  540. column_type = tds_get_byte(tds); /* datatype */
  541. if (!is_fixed_type(column_type)) {
  542. column_size = tds_get_byte(tds);
  543. actual_size = tds_get_byte(tds);
  544. tds_get_n(tds, NULL, actual_size);
  545. } else { 
  546. column_size = get_size_by_type(column_type);
  547. tds_get_n(tds, NULL, column_size);
  548. }
  549. return TDS_SUCCEED;
  550. }
  551. static int tds_process_param_result_tokens(TDSSOCKET *tds)
  552. {
  553. int marker;
  554. while ((marker=tds_get_byte(tds))==TDS_PARAM_TOKEN) {
  555. tds_process_param_result(tds);
  556. }
  557. tds_unget_byte(tds);
  558. return TDS_SUCCEED;
  559. }
  560. /*
  561. ** tds_process_compute_result() processes compute result sets.  These functions
  562. ** need work but since they get little use, nobody has complained!
  563. ** It is very similar to normal result sets.
  564. */
  565. static int tds_process_compute_result(TDSSOCKET *tds)
  566. {
  567. int hdrsize;
  568. int col, num_cols;
  569. TDSCOLINFO *curcol;
  570. TDSCOMPUTEINFO *info;
  571. int remainder;
  572. info = tds->comp_info;
  573. /* should not occur...but just in case */
  574. if (info) tds_free_compute_results(info);
  575. hdrsize = tds_get_smallint(tds);
  576. /* unknown always 1 ? */
  577. tds_get_smallint(tds); 
  578. num_cols = tds_get_byte(tds);
  579. tds->comp_info = tds_alloc_compute_results(num_cols);
  580. info = tds->comp_info;
  581. for (col=0;col<num_cols;col++) 
  582. {
  583. curcol=info->columns[col];
  584. /* user type and some other stuff? */
  585. tds_get_n(tds,NULL,6);
  586. /* column type */
  587. curcol->column_type = tds_get_byte(tds);
  588. /* column size */
  589. if (!is_fixed_type(curcol->column_type)) {
  590. curcol->column_size = tds_get_byte(tds);
  591. } else { 
  592. curcol->column_size = get_size_by_type(curcol->column_type);
  593. }
  594. curcol->column_offset = info->row_size;
  595. info->row_size += curcol->column_size + 1;
  596. /* actually this 4 should be a machine dependent #define */
  597. remainder = info->row_size & 0x3; 
  598. if (remainder) info->row_size += (4 - remainder);
  599. tds_get_byte(tds);
  600. }
  601. tds_get_n(tds,NULL,tds_get_smallint(tds));
  602. return TDS_SUCCEED;
  603. }
  604. /*
  605. ** tds7_process_result() is the TDS 7.0 result set processing routine.  It 
  606. ** is responsible for populating the tds->res_info structure.
  607. ** This is a TDS 7.0 only function
  608. */
  609. static int tds7_process_result(TDSSOCKET *tds)
  610. {
  611. int col, num_cols;
  612. int colnamelen;
  613. TDS_SMALLINT tabnamelen;
  614. TDSCOLINFO *curcol;
  615. TDSRESULTINFO *info;
  616. TDS_SMALLINT collate_type;
  617. int remainder;
  618. tds_free_all_results(tds);
  619. /* read number of columns and allocate the columns structure */
  620. num_cols = tds_get_smallint(tds);
  621. tds->res_info = tds_alloc_results(num_cols);
  622. info = tds->res_info;
  623. /* tell the upper layers we are processing results */
  624. tds->state = TDS_PENDING; 
  625. /* loop through the columns populating COLINFO struct from
  626. ** server response */
  627. for (col=0;col<num_cols;col++) {
  628. curcol = info->columns[col];
  629. /*  User defined data type of the column */
  630. curcol->column_usertype = tds_get_smallint(tds);  
  631.         curcol->column_flags = tds_get_smallint(tds);     /*  Flags */
  632.         curcol->column_nullable  =  curcol->column_flags & 0x01;
  633.         curcol->column_writeable = (curcol->column_flags & 0x08) > 0;
  634. curcol->column_identity  = (curcol->column_flags & 0x10) > 0;
  635. curcol->column_type = tds_get_byte(tds); 
  636.         curcol->column_type_save = curcol->column_type;
  637. collate_type = (curcol->column_flags & 0x2) || is_collate_type(curcol->column_type);
  638. curcol->column_varint_size  = tds_get_varint_size(curcol->column_type);
  639. switch(curcol->column_varint_size) {
  640. case 4: 
  641. curcol->column_size = tds_get_int(tds);
  642. break;
  643. case 2: 
  644. curcol->column_size = tds_get_smallint(tds);
  645. break;
  646. case 1: 
  647. curcol->column_size = tds_get_byte(tds);
  648. break;
  649. case 0: 
  650. curcol->column_size = get_size_by_type(curcol->column_type);
  651. break;
  652. }
  653. curcol->column_unicodedata = 0;
  654. if (is_unicode(curcol->column_type))
  655. curcol->column_unicodedata = 1;
  656. curcol->column_type = tds_get_cardinal_type(curcol->column_type);
  657. /* numeric and decimal have extra info */
  658. if (is_numeric_type(curcol->column_type)) {
  659. curcol->column_prec = tds_get_byte(tds); /* precision */
  660. curcol->column_scale = tds_get_byte(tds); /* scale */
  661. }
  662. if (IS_TDS80(tds)) {
  663. if (collate_type) 
  664. tds_get_n(tds, curcol->collation, 5);
  665. }
  666. if (is_blob_type(curcol->column_type)) {
  667. tabnamelen = tds_get_smallint(tds);
  668. #ifdef NCBI_FTDS
  669.   tds_get_string(tds,curcol->full_column_name,tabnamelen);
  670.   curcol->full_column_name[tabnamelen]='.';
  671. #else
  672. tds_get_string(tds, NULL, tabnamelen);
  673. #endif
  674. }
  675. /* under 7.0 lengths are number of characters not 
  676. ** number of bytes...tds_get_string handles this */
  677. colnamelen = tds_get_byte(tds);
  678. tds_get_string(tds,curcol->column_name, colnamelen);
  679. /* the column_offset is the offset into the row buffer
  680. ** where this column begins, text types are no longer
  681. ** stored in the row buffer because the max size can
  682. ** be too large (2gig) to allocate */
  683. curcol->column_offset = info->row_size;
  684. if (!is_blob_type(curcol->column_type)) {
  685. info->row_size += curcol->column_size + 1;
  686. }
  687. #ifdef NCBI_FTDS
  688.       else {
  689.           strcpy(curcol->full_column_name+tabnamelen+1,curcol->column_name);
  690.       }
  691. #endif
  692. if (is_numeric_type(curcol->column_type)) {
  693.                        info->row_size += sizeof(TDS_NUMERIC) + 1;
  694. }
  695. #ifdef NCBI_FTDS
  696. else if(curcol->column_type == SYBVARBINARY) {
  697.   info->row_size+= sizeof(TDS_INT); /* to prevent memory corruption */
  698. }
  699. #endif
  700. /* actually this 4 should be a machine dependent #define */
  701. if(remainder = info->row_size & 0x3) {
  702.           info->row_size += (4 - remainder);
  703.       }
  704. }
  705. /* all done now allocate a row for tds_process_row to use */
  706. info->current_row = tds_alloc_row(info);
  707. return TDS_SUCCEED;
  708. }
  709. /*
  710. ** tds_process_result() is the TDS 5.0 result set processing routine.  It 
  711. ** is responsible for populating the tds->res_info structure.
  712. ** This is a TDS 5.0 only function
  713. */
  714. static int tds_process_result(TDSSOCKET *tds)
  715. {
  716. int hdrsize;
  717. int colnamelen;
  718. int col, num_cols;
  719. TDSCOLINFO *curcol;
  720. TDSRESULTINFO *info;
  721. int remainder;
  722. tds_free_all_results(tds);
  723. hdrsize = tds_get_smallint(tds);
  724. /* read number of columns and allocate the columns structure */
  725. num_cols = tds_get_smallint(tds);
  726. tds->res_info = tds_alloc_results(num_cols);
  727. info = tds->res_info;
  728. /* tell the upper layers we are processing results */
  729. tds->state = TDS_PENDING; 
  730. /* loop through the columns populating COLINFO struct from
  731. ** server response */
  732. for (col=0;col<info->num_cols;col++) 
  733. {
  734. curcol=info->columns[col];
  735. colnamelen = tds_get_byte(tds);
  736. tds_get_n(tds,curcol->column_name, colnamelen);
  737. curcol->column_name[colnamelen]='';
  738.         curcol->column_flags = tds_get_byte(tds);     /*  Flags */
  739.         curcol->column_nullable  = (curcol->column_flags & 0x20) > 1;
  740. curcol->column_usertype = tds_get_smallint(tds);
  741. tds_get_smallint(tds);  /* another unknown */
  742. curcol->column_type = tds_get_byte(tds);
  743. curcol->column_varint_size  = tds_get_varint_size(curcol->column_type);
  744.         tdsdump_log(TDS_DBG_INFO1, "%L processing result. type = %d, varint_size %dn", curcol->column_type, curcol->column_varint_size);
  745. switch(curcol->column_varint_size) {
  746. case 4: 
  747. curcol->column_size = tds_get_int(tds);
  748. /* junk the table name -- for now */
  749. tds_get_n(tds,NULL,tds_get_smallint(tds));
  750. break;
  751. case 1: 
  752. curcol->column_size = tds_get_byte(tds);
  753. break;
  754. case 0: 
  755. curcol->column_size = get_size_by_type(curcol->column_type);
  756. break;
  757. /* FIXME can varint_size be 2 ?? */
  758. }
  759.         tdsdump_log(TDS_DBG_INFO1, "%L processing result. column_size %dn", curcol->column_size);
  760. /* numeric and decimal have extra info */
  761. if (is_numeric_type(curcol->column_type)) {
  762. curcol->column_prec = tds_get_byte(tds); /* precision */
  763. curcol->column_scale = tds_get_byte(tds); /* scale */
  764. }
  765. curcol->column_offset = info->row_size;
  766. if (is_numeric_type(curcol->column_type)) {
  767. info->row_size += sizeof(TDS_NUMERIC) + 1;
  768. } else if (!is_blob_type(curcol->column_type)) {
  769. info->row_size += curcol->column_size + 1;
  770. }
  771. #ifdef NCBI_FTDS
  772. else if(curcol->column_type == SYBVARBINARY) {
  773.   info->row_size+= sizeof(TDS_INT); /* to prevent memory corruption */
  774. }
  775. #endif
  776. /* actually this 4 should be a machine dependent #define */
  777. remainder = info->row_size & 0x3; 
  778. if (remainder) info->row_size += (4 - remainder);
  779. tds_get_byte(tds); /* ? */
  780. }
  781. info->current_row = tds_alloc_row(info);
  782. return TDS_SUCCEED;
  783. }
  784. /*
  785. ** tds_process_compute() processes compute rows and places them in the row
  786. ** buffer.  It's in a bit of disrepair and may not have tracked the row
  787. ** buffer changes completely.
  788. */
  789. static int tds_process_compute(TDSSOCKET *tds)
  790. {
  791. int colsize, i;
  792. TDSCOLINFO *curcol;
  793. TDSCOMPUTEINFO *info;
  794. int compid;
  795. unsigned char *dest;
  796. info = tds->comp_info;
  797. compid = tds_get_smallint(tds); /* compute id? */
  798. for (i=0;i<info->num_cols;i++)
  799. {
  800. curcol = info->columns[i];
  801. if (!is_fixed_type(curcol->column_type)) {
  802. colsize = tds_get_byte(tds);
  803. } else {
  804. colsize = get_size_by_type(curcol->column_type);
  805. }
  806. dest = &(info->current_row[curcol->column_offset]);
  807. tds_get_n(tds,dest,colsize);
  808. #ifndef NCBI_FTDS
  809. dest[colsize]='';
  810. #endif
  811. }
  812. return TDS_SUCCEED;
  813. }
  814. /*
  815. ** tds_process_row() processes rows and places them in the row buffer.  There
  816. ** is also some special handling for some of the more obscure datatypes here.
  817. */
  818. static int tds_process_row(TDSSOCKET *tds)
  819. {
  820. int colsize, i;
  821. TDSCOLINFO *curcol;
  822. TDSRESULTINFO *info;
  823. unsigned char *dest;
  824. TDS_NUMERIC *num;
  825. TDS_VARBINARY *varbin;
  826. int len;
  827.  TDS_SMALLINT cur_col_type;
  828. info = tds->res_info;
  829. if (!info)
  830. return TDS_FAIL;
  831. info->row_count++;
  832. #ifdef NCBI_FTDS
  833.   memset(info->current_row,'',info->null_info_size); /*** clear nulls ***/
  834. #endif
  835. for (i=0;i<info->num_cols;i++) {
  836. curcol = info->columns[i];
  837. cur_col_type= curcol->column_type;
  838.         tdsdump_log(TDS_DBG_INFO1, "%L processing row.  column is %d varint size = %dn", i, curcol->column_varint_size);
  839. switch (curcol->column_varint_size) {
  840. case 4: /* Its a BLOB... */
  841. len = tds_get_byte(tds);
  842. if (len == 16) { /*  Jeff's hack */
  843. tds_get_n(tds,curcol->column_textptr,16);
  844. tds_get_n(tds,curcol->column_timestamp,8);
  845. colsize = tds_get_int(tds);
  846. } else {
  847. colsize = 0;
  848. }
  849. break;
  850. case 2: 
  851. /* FIXME add support for empty no-NULL string*/
  852. colsize = tds_get_smallint(tds);
  853. if (colsize == -1)
  854. colsize=0;
  855. break;
  856. case 1: 
  857. colsize = tds_get_byte(tds);
  858. break;
  859. case 0: 
  860. colsize = get_size_by_type(cur_col_type);
  861. break;
  862. }
  863.         tdsdump_log(TDS_DBG_INFO1, "%L processing row.  column size is %d n", colsize);
  864. /* set NULL flag in the row buffer */
  865. if (colsize==0) {
  866. tds_set_null(info->current_row, i);
  867. } else {
  868. tds_clr_null(info->current_row, i);
  869. if (is_numeric_type(cur_col_type)) {
  870. /* 
  871. ** handling NUMERIC datatypes: 
  872. ** since these can be passed around independent
  873. ** of the original column they were from, I decided
  874. ** to embed the TDS_NUMERIC datatype in the row buffer
  875. ** instead of using the wire representation even though
  876. ** it uses a few more bytes
  877. */
  878. num = (TDS_NUMERIC *) &(info->current_row[curcol->column_offset]);
  879.                 memset(num, '', sizeof(TDS_NUMERIC));
  880. num->precision = curcol->column_prec;
  881. num->scale = curcol->column_scale;
  882. tds_get_n(tds,num->array,colsize);
  883. /* corrected colsize for cur_row_size */
  884. colsize = sizeof(TDS_NUMERIC);
  885.         if (IS_TDS70(tds) || IS_TDS80(tds)) 
  886.                 {
  887.    tdsdump_log(TDS_DBG_INFO1, "%L swapping numeric data...n");
  888.                    tds_swap_datatype(tds_get_conversion_type(cur_col_type, colsize), (unsigned char *)num );
  889.                 }
  890. } else if (cur_col_type == SYBVARBINARY) {
  891. varbin = (TDS_VARBINARY *) &(info->current_row[curcol->column_offset]);
  892. varbin->len = colsize;
  893.                             /*  It is important to re-zero out the whole
  894.                                 column_size varbin array here because the result
  895.                                 of the query ("colsize") may be any number of
  896.                                 bytes <= column_size (because the result
  897.                                 will be truncated if the rest of the data
  898.                                 in the column would be all zeros).  */
  899.                                 memset(varbin->array,'',curcol->column_size);
  900. tds_get_n(tds,varbin->array,colsize);
  901. } else if (is_blob_type(cur_col_type)) {
  902. if (curcol->column_unicodedata) colsize /= 2;
  903. curcol->column_textvalue = realloc(curcol->column_textvalue,colsize+1); /* FIXME +1 needed by tds_get_string */
  904. curcol->column_textsize = colsize;
  905. if (curcol->column_unicodedata) {
  906. tds_get_string(tds,curcol->column_textvalue,colsize);
  907. } else {
  908. tds_get_n(tds,curcol->column_textvalue,colsize);
  909. }
  910. } else {
  911. dest = &(info->current_row[curcol->column_offset]);
  912. if (curcol->column_unicodedata) {
  913. tds_get_string(tds,dest,colsize/2);
  914. colsize /= 2;
  915. } else {
  916. tds_get_n(tds,dest,colsize);
  917. }
  918. /* FIXME correct for unicode ? */
  919. #ifdef NCBI_FTDS
  920.             if(cur_col_type == SYBVARCHAR)
  921. #endif
  922.                 dest[colsize]='';
  923. if (cur_col_type == SYBDATETIME4) {
  924. tdsdump_log(TDS_DBG_INFO1, "%L datetime4 %d %d %d %dn", dest[0], dest[1], dest[2], dest[3]);
  925. }
  926. }
  927. /* Value used to properly know value in dbdatlen. (mlilback, 11/7/01) */
  928. curcol->cur_row_size = colsize;
  929. #ifdef WORDS_BIGENDIAN
  930. /* MS SQL Server 7.0 has broken date types from big endian 
  931. ** machines, this swaps the low and high halves of the 
  932. ** affected datatypes
  933. **
  934. ** Thought - this might be because we don't have the
  935. ** right flags set on login.  -mjs
  936. **
  937. ** Nope its an actual MS SQL bug -bsb
  938. */
  939. if (tds->broken_dates &&
  940. (cur_col_type == SYBDATETIME ||
  941. cur_col_type == SYBDATETIME4 ||
  942. cur_col_type == SYBDATETIMN ||
  943. cur_col_type == SYBMONEY ||
  944. cur_col_type == SYBMONEY4 ||
  945. (cur_col_type == SYBMONEYN && curcol->column_size > 4))) 
  946. /* above line changed -- don't want this for 4 byte SYBMONEYN 
  947. values (mlilback, 11/7/01) */
  948. {
  949. unsigned char temp_buf[8];
  950. memcpy(temp_buf,dest,colsize/2);
  951. memcpy(dest,&dest[colsize/2],colsize/2);
  952. memcpy(&dest[colsize/2],temp_buf,colsize/2);
  953. }
  954.             if (tds->emul_little_endian && !is_numeric_type(cur_col_type)) {
  955.                 tdsdump_log(TDS_DBG_INFO1, "%L swapping coltype %dn",
  956.                             tds_get_conversion_type(cur_col_type,colsize));
  957.                 tds_swap_datatype(tds_get_conversion_type(cur_col_type, colsize),
  958.                                   &(info->current_row[curcol->column_offset])
  959.                                  );
  960.             }
  961. #endif
  962. }
  963. }
  964. return TDS_SUCCEED;
  965. }
  966. /*
  967. ** tds_process_end() processes any of the DONE, DONEPROC, or DONEINPROC
  968. ** tokens.
  969. */
  970. TDS_INT tds_process_end(
  971.    TDSSOCKET     *tds,
  972.    int            marker,
  973.    int           *more_results_parm,
  974.    int           *was_cancelled_parm)
  975. {
  976. int more_results, was_cancelled;
  977. int tmp = tds_get_smallint(tds);
  978.    more_results = (tmp & 0x1) != 0;
  979.    was_cancelled = (tmp & 0x20) != 0;
  980.    if (tds->res_info)  {
  981.       tds->res_info->more_results=more_results;
  982.       if (was_cancelled || !(more_results)) {
  983.           tds->state = TDS_COMPLETED;
  984.       }
  985.    }
  986.    if (more_results_parm)
  987. *more_results_parm = more_results;
  988.    if (was_cancelled_parm)
  989. *was_cancelled_parm = was_cancelled;
  990.    tds_get_smallint(tds);
  991.    /* rows affected is in the tds struct because a query may affect rows but
  992.    ** have no result set. */
  993.    tds->rows_affected = tds_get_int(tds);
  994.    return tds->rows_affected;
  995. }
  996. /*
  997. ** tds_client_msg() sends a message to the client application from the CLI or
  998. ** TDS layer. A client message is one that is generated from with the library
  999. ** and not from the server.  The message is sent to the CLI (the 
  1000. ** err_handler) so that it may forward it to the client application or
  1001. ** discard it if no msg handler has been by the application. tds->parent
  1002. ** contains a void pointer to the parent of the tds socket. This can be cast
  1003. ** back into DBPROCESS or CS_CONNECTION by the CLI and used to determine the
  1004. ** proper recipient function for this message.
  1005. */
  1006. int tds_client_msg(TDSCONTEXT *tds_ctx, TDSSOCKET *tds, int msgnum, int level, int state, int line, char *message)
  1007. {
  1008. int ret;
  1009. TDSMSGINFO msg_info;
  1010.         if(tds_ctx->err_handler) {
  1011. memset(&msg_info, 0, sizeof(TDSMSGINFO));
  1012. msg_info.msg_number=msgnum;
  1013.          msg_info.msg_level=level; /* severity? */
  1014.          msg_info.msg_state=state;
  1015.          msg_info.server=strdup("OpenClient");
  1016.          msg_info.line_number=line;
  1017.          msg_info.message=strdup(message);
  1018.          ret = tds_ctx->err_handler(tds_ctx, tds, &msg_info);
  1019. /* message handler returned FAIL/CS_FAIL
  1020. ** mark socket as dead */
  1021. if (ret && tds) {
  1022. tds->state=TDS_DEAD;
  1023. }
  1024. }
  1025. return 0;
  1026. }
  1027. /*
  1028. ** tds_process_env_chg() 
  1029. ** when ever certain things change on the server, such as database, character
  1030. ** set, language, or block size.  A environment change message is generated
  1031. ** There is no action taken currently, but certain functions at the CLI level
  1032. ** that return the name of the current database will need to use this.
  1033. */
  1034. #ifdef NCBI_FTDS
  1035. extern int tds_process_env_chg(TDSSOCKET *tds)
  1036. {
  1037. int size, type,env_left;
  1038. char oldval[1024], newval[1024];
  1039. int  new_block_size;
  1040. TDSENVINFO *env = tds->env;
  1041. env_left = tds_get_smallint(tds);
  1042. /* this came in a patch, apparently someone saw an env message
  1043. ** that was different from what we are handling? -- brian
  1044. ** changed back because it won't handle multibyte chars -- 7.0
  1045. */
  1046. /* tds_get_n(tds,NULL,size); */
  1047. type = tds_get_byte(tds);
  1048. env_left--;
  1049. switch(type){
  1050.  case TDS_ENV_BLOCKSIZE:
  1051. /* fetch the new value */
  1052. size = tds_get_byte(tds);
  1053. if(size) tds_get_string(tds,newval,size);
  1054. newval[size]='';
  1055. /* fetch the old value */
  1056. size = tds_get_byte(tds);
  1057. if(size) tds_get_string(tds,oldval,size);
  1058. oldval[size]='';
  1059. new_block_size = atoi(newval);
  1060. if (new_block_size > env->block_size) {
  1061. tdsdump_log(TDS_DBG_INFO1, "%L increasing block size from %d to %dn",
  1062. env->block_size, new_block_size);
  1063. /* 
  1064. ** I'm not aware of any way to shrink the 
  1065. ** block size but if it is possible, we don't 
  1066. ** handle it.
  1067. */
  1068. tds->out_buf = (unsigned char*) realloc(tds->out_buf, new_block_size);
  1069. env->block_size = new_block_size;
  1070. }
  1071. break;
  1072.  case TDS_ENV_DATABASE:
  1073.    case TDS_ENV_CHARSET: 
  1074.        tds_get_n(tds,NULL,env_left);
  1075. break;
  1076.  default:
  1077. tdsdump_log(TDS_DBG_INFO1, "%L unknown TDS_ENV type %d, skipping %d bytes blockn", type, env_left);
  1078. tds_get_n(tds,NULL,env_left);
  1079. break;
  1080. }
  1081. return TDS_SUCCEED;
  1082. }
  1083. #else
  1084. int tds_process_env_chg(TDSSOCKET *tds)
  1085. {
  1086. int size, type;
  1087. char *oldval, *newval;
  1088. int  new_block_size;
  1089. TDSENVINFO *env = tds->env;
  1090. size = tds_get_smallint(tds);
  1091. /* this came in a patch, apparently someone saw an env message
  1092. ** that was different from what we are handling? -- brian
  1093. ** changed back because it won't handle multibyte chars -- 7.0
  1094. */
  1095. /* tds_get_n(tds,NULL,size); */
  1096. type = tds_get_byte(tds);
  1097. if (type==0x07) {
  1098. size = tds_get_byte(tds);
  1099. if (size) tds_get_n(tds, NULL, size);
  1100. size = tds_get_byte(tds);
  1101. if (size) tds_get_n(tds, NULL, size);
  1102. return TDS_SUCCEED;
  1103. }
  1104. /* fetch the new value */
  1105. size = tds_get_byte(tds);
  1106. newval = (char *) malloc((size+1)*2);
  1107. tds_get_string(tds,newval,size);
  1108. newval[size]='';
  1109. /* fetch the old value */
  1110. size = tds_get_byte(tds);
  1111. oldval = (char *) malloc((size+1)*2); /* may be a unicode string */
  1112. tds_get_string(tds,oldval,size);
  1113. oldval[size]='';
  1114. switch (type) {
  1115. case TDS_ENV_BLOCKSIZE:
  1116. new_block_size = atoi(newval);
  1117. if (new_block_size > env->block_size) {
  1118. tdsdump_log(TDS_DBG_INFO1, "%L increasing block size from %s to %dn", oldval, new_block_size);
  1119. /* 
  1120. ** I'm not aware of any way to shrink the 
  1121. ** block size but if it is possible, we don't 
  1122. ** handle it.
  1123. */
  1124. tds->out_buf = (unsigned char*) realloc(tds->out_buf, new_block_size);
  1125. env->block_size = new_block_size;
  1126. }
  1127. break;
  1128. }
  1129. free(oldval);
  1130. free(newval);
  1131. return TDS_SUCCEED;
  1132. }
  1133. #endif
  1134. int tds_process_column_row(TDSSOCKET *tds)
  1135. {
  1136. int colsize, i;
  1137. TDSCOLINFO *curcol;
  1138. TDSRESULTINFO *info;
  1139. unsigned char *dest;
  1140.       info = tds->res_info;
  1141.       info->row_count++;
  1142.       for (i=0;i<(info->num_cols -1);i++)
  1143.       {
  1144.               curcol = info->columns[i];
  1145.               if (!is_fixed_type(curcol->column_type)) {
  1146.                       colsize = tds_get_byte(tds);
  1147.               } else {
  1148.                       colsize = get_size_by_type(curcol->column_type);
  1149.               }
  1150. dest = &(info->current_row[curcol->column_offset]);
  1151. tds_get_n(tds,dest,colsize);
  1152. #ifndef NCBI_FTDS
  1153. dest[colsize]='';
  1154. #endif
  1155.               /* printf("%sn",curcol->column_value); */
  1156. }
  1157. /* now skip over some stuff and get the rest of the columns */
  1158. tds_get_n(tds,NULL,25);
  1159. colsize = tds_get_byte(tds);
  1160. tds_get_n(tds,NULL,3);
  1161. curcol = info->columns[i];
  1162. dest = &(info->current_row[curcol->column_offset]);
  1163. tds_get_n(tds,dest,colsize);
  1164. #ifndef NCBI_FTDS
  1165. dest[colsize]='';
  1166. #endif
  1167. return TDS_SUCCEED;
  1168. }
  1169. /*
  1170. ** tds_process_msg() is called for MSG, ERR, or EED tokens and is responsible
  1171. ** for calling the CLI's message handling routine
  1172. ** returns TDS_SUCCEED if informational, TDS_ERROR if error.
  1173. **
  1174. ** Note: the called function is responsible for calling tds_reset_msg on the 
  1175. ** passed structure.
  1176. */
  1177. static int tds_process_msg(TDSSOCKET *tds,int marker)
  1178. {
  1179. int rc;
  1180. int len;
  1181. int len_msg;
  1182. int len_svr;
  1183. int len_sqlstate;
  1184. /* make sure message has been freed */
  1185. tds_free_msg(tds->msg_info);
  1186. /* packet length */
  1187. len = tds_get_smallint(tds);
  1188. /* message number */
  1189. rc = tds_get_int(tds);
  1190. tds->msg_info->msg_number = rc;
  1191. /* msg state */
  1192. tds->msg_info->msg_state = tds_get_byte(tds);
  1193. /* msg level */
  1194. tds->msg_info->msg_level = tds_get_byte(tds);
  1195. /* determine if msg or error */
  1196. if (marker==TDS_EED_TOKEN) {
  1197. if (tds->msg_info->msg_level<=10) 
  1198.                     tds->msg_info->priv_msg_type = 0;
  1199. else 
  1200.                     tds->msg_info->priv_msg_type = 1;
  1201. /* junk this info for now */
  1202. len_sqlstate = tds_get_byte(tds);
  1203. tds->msg_info->sql_state = (char*)malloc(len_sqlstate+1);
  1204. tds_get_n(tds, tds->msg_info->sql_state,len_sqlstate);
  1205. tds->msg_info->sql_state[len_sqlstate] = '';
  1206. /* unknown values */
  1207. tds_get_byte(tds);
  1208. tds_get_smallint(tds);
  1209. else if (marker==TDS_MSG_TOKEN) {
  1210. tds->msg_info->priv_msg_type = 0;
  1211. } else if (marker==TDS_ERR_TOKEN) {
  1212. tds->msg_info->priv_msg_type = 1;
  1213. } else {
  1214. tdsdump_log(TDS_DBG_ERROR,"tds_process_msg() called with unknown marker!n");
  1215. return TDS_FAIL;
  1216. }
  1217. /* the message */
  1218. len_msg = tds_get_smallint(tds);
  1219. tds->msg_info->message = (char*)malloc(len_msg+1);
  1220. tds_get_string(tds, tds->msg_info->message, len_msg);
  1221. tds->msg_info->message[len_msg] = '';
  1222. /* server name */
  1223. len_svr = tds_get_byte(tds);
  1224. tds->msg_info->server = (char*)malloc(len_svr+1);
  1225. tds_get_string(tds, tds->msg_info->server, len_svr);
  1226. tds->msg_info->server[len_svr] = '';
  1227. /* stored proc name if available */
  1228. rc = tds_get_byte(tds);
  1229. if (rc) {
  1230. tds_unget_byte(tds);
  1231. tds->msg_info->proc_name=tds_msg_get_proc_name(tds);
  1232. } else {
  1233. tds->msg_info->proc_name=strdup("");
  1234. }
  1235. /* line number in the sql statement where the problem occurred */
  1236. tds->msg_info->line_number = tds_get_smallint(tds);
  1237. if (tds->msg_info->priv_msg_type)  {
  1238. rc = TDS_ERROR;
  1239. } else {
  1240. rc = TDS_SUCCEED;
  1241. }
  1242. /* call the global_tds_msg_handler that was set by an upper layer 
  1243. ** (dblib, ctlib or some other one).  Call it with the pointer to 
  1244. ** the "parent" structure.
  1245. */
  1246. if(tds->msg_info->priv_msg_type
  1247.                    ? tds->tds_ctx->err_handler : tds->tds_ctx->msg_handler) {
  1248. if (tds->msg_info->priv_msg_type)
  1249. tds->tds_ctx->err_handler(tds->tds_ctx, tds, tds->msg_info);
  1250. else
  1251. tds->tds_ctx->msg_handler(tds->tds_ctx, tds, tds->msg_info);
  1252. } else {
  1253. if(tds->msg_info->msg_number)
  1254. tdsdump_log(TDS_DBG_WARN,
  1255. "%L Msg %d, Level %d, State %d, Server %s, Line %dn%sn",
  1256. tds->msg_info->msg_number,
  1257. tds->msg_info->msg_level,
  1258. tds->msg_info->msg_state,
  1259. tds->msg_info->server,
  1260. tds->msg_info->line_number,
  1261. tds->msg_info->message);
  1262. tds_free_msg(tds->msg_info);
  1263. }
  1264. return rc;
  1265. }
  1266. char *tds_msg_get_proc_name(TDSSOCKET *tds)
  1267. {
  1268. int len_proc;
  1269. char *proc_name;
  1270. len_proc = tds_get_byte(tds);
  1271. if (len_proc < 0) {
  1272. len_proc = 0;
  1273. }
  1274.         proc_name = (char*)malloc(len_proc+1);
  1275. if (len_proc > 0) {
  1276.               tds_get_string(tds, proc_name, len_proc);
  1277. }
  1278.         proc_name[len_proc] = '';
  1279. return proc_name;
  1280. }
  1281. int tds_reset_msg_info(TDSMSGINFO *msg_info)
  1282. {
  1283. if (!msg_info) 
  1284. return 0;
  1285. msg_info->priv_msg_type = 0;
  1286. msg_info->msg_number = 0;
  1287. msg_info->msg_state = 0;
  1288. msg_info->msg_level = 0;
  1289. msg_info->line_number = 0;
  1290. if( msg_info->message)
  1291. TDS_ZERO_FREE(msg_info->message);
  1292. if(msg_info->server)
  1293. TDS_ZERO_FREE(msg_info->server);
  1294. if(msg_info->proc_name)
  1295. TDS_ZERO_FREE(msg_info->proc_name);
  1296. return 0;
  1297. }
  1298. /*
  1299. ** tds_process_cancel() processes the incoming token stream until it finds
  1300. ** an end token (DONE, DONEPROC, DONEINPROC) with the cancel flag set.
  1301. ** a that point the connetion should be ready to handle a new query.
  1302. */
  1303. int tds_process_cancel(TDSSOCKET *tds)
  1304. {
  1305. int marker, cancelled=0;
  1306. do {
  1307. marker=tds_get_byte(tds);
  1308. if (marker==TDS_DONE_TOKEN) {
  1309. tds_process_end(tds, marker, NULL, &cancelled);
  1310. } else if (marker==0) {
  1311. cancelled = 1;
  1312. } else {
  1313. tds_process_default_tokens(tds,marker);
  1314. }
  1315. } while (!cancelled);
  1316. tds->state = TDS_COMPLETED;
  1317. return 0;
  1318. }
  1319. /* =========================== tds_is_result_row() ===========================
  1320.  * 
  1321.  * Def:  does the next token in stream signify a result row?
  1322.  * 
  1323.  * Ret:  true if stream is positioned at a row, false otherwise
  1324.  * 
  1325.  * ===========================================================================
  1326.  */
  1327. int tds_is_result_row(TDSSOCKET *tds)
  1328. {
  1329.    const int  marker = tds_peek(tds);
  1330.    int        result = 0;
  1331.    if (marker==TDS_ROW_TOKEN)
  1332.    {
  1333.       result = 1;
  1334.    }
  1335.    return result;
  1336. } /* tds_is_result_row()  */
  1337. int tds_is_result_set(TDSSOCKET *tds)
  1338. {
  1339.    const int  marker = tds_peek(tds);
  1340.    int        result = 0;
  1341.    result = (marker==TDS_COL_NAME_TOKEN 
  1342.              || marker==TDS_COL_INFO_TOKEN 
  1343.              || marker==TDS_RESULT_TOKEN
  1344.              || marker==TDS7_RESULT_TOKEN);
  1345.    return result;
  1346. } /* tds_is_result_set()  */
  1347. int tds_is_end_of_results(TDSSOCKET *tds)
  1348. {
  1349.    const int  marker = tds_peek(tds);
  1350.    int        result = 0;
  1351.    result = marker==TDS_DONE_TOKEN || marker==TDS_DONEPROC_TOKEN;
  1352.    return result;
  1353. } /* tds_is_end_of_results()  */
  1354. int tds_is_doneinproc(TDSSOCKET *tds)
  1355. {
  1356.    const int  marker = tds_peek(tds);
  1357.    int        result = 0;
  1358.    result = marker==TDS_DONEINPROC_TOKEN;
  1359.    return result;
  1360. } /* tds_is_end_of_results()  */
  1361. int tds_is_error(TDSSOCKET *tds)
  1362. {
  1363.    const int  marker = tds_peek(tds);
  1364.    int        result = 0;
  1365.    result = marker==TDS_ERR_TOKEN;
  1366.    return result;
  1367. } /* tds_is_error()  */
  1368. int tds_is_message(TDSSOCKET *tds)
  1369. {
  1370.    const int  marker = tds_peek(tds);
  1371.    int        result = 0;
  1372.    result = marker==TDS_MSG_TOKEN;
  1373.    return result;
  1374. } /* tds_is_message()  */
  1375. int tds_is_control(TDSSOCKET *tds)
  1376. {
  1377.    const int  marker = tds_peek(tds);
  1378.    int        result = 0;
  1379.    result = (marker==TDS_174_TOKEN || marker==TDS_167_TOKEN);
  1380.    return result;
  1381. }
  1382. /*
  1383. ** set the null bit for the given column in the row buffer
  1384. */
  1385. #ifdef NCBI_FTDS
  1386. static unsigned char s_null_mask[8]= {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
  1387. void tds_set_null(unsigned char *current_row, int column)
  1388. {
  1389.     current_row[column >> 3]|= s_null_mask[column & 0x7];
  1390. }
  1391. /*
  1392. ** clear the null bit for the given column in the row buffer
  1393. */
  1394. void tds_clr_null(unsigned char *current_row, int column)
  1395. {
  1396.     current_row[column >> 3]&= ~s_null_mask[column & 0x7];
  1397. }
  1398. /*
  1399. ** return the null bit for the given column in the row buffer
  1400. */
  1401. int tds_get_null(unsigned char *current_row, int column)
  1402. {
  1403.  return (current_row[column >> 3] & s_null_mask[column & 0x7])? 1 : 0;
  1404. }
  1405. #else
  1406. void tds_set_null(unsigned char *current_row, int column)
  1407. {
  1408. int bytenum = column >> 3;
  1409. int bit = column & 0x7;
  1410. unsigned char mask = 1 << bit;
  1411. tdsdump_log(TDS_DBG_INFO1,"%L setting column %d NULL bitn", column);
  1412. current_row[bytenum] |= mask;
  1413. }
  1414. /*
  1415. ** clear the null bit for the given column in the row buffer
  1416. */
  1417. void tds_clr_null(unsigned char *current_row, int column)
  1418. {
  1419. int bytenum = column  >> 3;
  1420. int bit = column & 0x7;
  1421. unsigned char mask = ~(1 << bit);
  1422. tdsdump_log(TDS_DBG_INFO1, "%L clearing column %d NULL bitn", column);
  1423. current_row[bytenum] &= mask;
  1424. }
  1425. /*
  1426. ** return the null bit for the given column in the row buffer
  1427. */
  1428. int tds_get_null(unsigned char *current_row, int column)
  1429. {
  1430. int bytenum = column >> 3;
  1431. int bit = column & 0x7;
  1432. unsigned char mask = 1 << bit;
  1433. return (current_row[bytenum] & mask) ? 1 : 0;
  1434. }
  1435. #endif
  1436. int tds_lookup_dynamic(TDSSOCKET *tds, char *id)
  1437. {
  1438. int i;
  1439. for (i=0;i<tds->num_dyns;i++) {
  1440. if (!strcmp(tds->dyns[i]->id, id)) {
  1441. return i;
  1442. }
  1443. }
  1444. return -1;
  1445. }
  1446. /*
  1447. ** tds_process_dynamic()
  1448. ** finds the element of the dyns array for the id
  1449. */
  1450. static int tds_process_dynamic(TDSSOCKET *tds)
  1451. {
  1452. int token_sz;
  1453. char subtoken[2];
  1454. int id_len;
  1455. char id[TDS_MAX_DYNID_LEN+1];
  1456. int drain = 0;
  1457. token_sz = tds_get_smallint(tds);
  1458. subtoken[0] = tds_get_byte(tds);
  1459. subtoken[1] = tds_get_byte(tds);
  1460. if (subtoken[0]!=0x20 || subtoken[1]!=0x00) {
  1461. tdsdump_log(TDS_DBG_ERROR,"Unrecognized TDS5_DYN subtoken %x,%xn",
  1462.         subtoken[0], subtoken[1]);
  1463. tds_get_n(tds, NULL, token_sz-2);
  1464. return -1;
  1465. }
  1466. id_len = tds_get_byte(tds);
  1467. if (id_len > TDS_MAX_DYNID_LEN) {
  1468. drain = id_len - TDS_MAX_DYNID_LEN;
  1469. id_len = TDS_MAX_DYNID_LEN;
  1470. }
  1471. tds_get_string(tds, id, id_len);
  1472. id[id_len]='';
  1473. if (drain) { 
  1474. tds_get_string(tds, NULL, drain);
  1475. }
  1476. return tds_lookup_dynamic(tds,id);
  1477. }
  1478. static void tds_process_dyn_result(TDSSOCKET *tds)
  1479. {
  1480. int hdrsize;
  1481. int col, num_cols;
  1482. TDSCOLINFO *curcol;
  1483. TDSRESULTINFO *info;
  1484. TDSDYNAMIC *dyn;
  1485. hdrsize = tds_get_smallint(tds);
  1486. num_cols = tds_get_smallint(tds);
  1487. if (tds->cur_dyn_elem) {
  1488. dyn = tds->dyns[tds->cur_dyn_elem];
  1489. tds_free_results(dyn->res_info);
  1490. /* read number of columns and allocate the columns structure */
  1491. dyn->res_info = tds_alloc_results(num_cols);
  1492. info = dyn->res_info;
  1493. } else {
  1494. tds_free_results(tds->res_info);
  1495. tds->res_info = tds_alloc_results(num_cols);
  1496. info = tds->res_info;
  1497. }
  1498. for (col=0;col<info->num_cols;col++) {
  1499. curcol=info->columns[col];
  1500. tds_get_n(tds,NULL,6);
  1501. /* column type */
  1502. curcol->column_type = tds_get_byte(tds);
  1503. /* column size */
  1504. if (!is_fixed_type(curcol->column_type)) {
  1505. curcol->column_size = tds_get_byte(tds);
  1506. } else { 
  1507. curcol->column_size = get_size_by_type(curcol->column_type);
  1508. }
  1509. tds_get_byte(tds);
  1510. /* fprintf(stderr,"elem %d coltype %d size %dn",tds->cur_dyn_elem, curcol->column_type, curcol->column_size); */
  1511. }
  1512. }
  1513. /* 
  1514. ** tds_is_fixed_token()
  1515. ** some tokens are fixed length while others are variable.  This function is 
  1516. ** used by tds_process_cancel() to determine how to read past a token
  1517. */
  1518. int tds_is_fixed_token(int marker)
  1519. {
  1520. switch (marker) {
  1521. case TDS_DONE_TOKEN:
  1522. case TDS_DONEPROC_TOKEN:
  1523. case TDS_DONEINPROC_TOKEN:
  1524. case TDS_RET_STAT_TOKEN:
  1525. return 1;
  1526. default:
  1527. return 0;
  1528. }
  1529. }
  1530. /* 
  1531. ** tds_get_token_size() returns the size of a fixed length token
  1532. ** used by tds_process_cancel() to determine how to read past a token
  1533. */
  1534. int tds_get_token_size(int marker)
  1535. {
  1536. switch(marker) {
  1537. case TDS_DONE_TOKEN:
  1538. case TDS_DONEPROC_TOKEN:
  1539. case TDS_DONEINPROC_TOKEN:
  1540. return 8;
  1541. case TDS_RET_STAT_TOKEN:
  1542. return 4;
  1543. case TDS_124_TOKEN:
  1544. return 8;
  1545. default:
  1546. return 0;
  1547. }
  1548. }
  1549. void tds_swap_datatype(int coltype, unsigned char *buf)
  1550. {
  1551. TDS_NUMERIC *num;
  1552. switch(coltype) {
  1553. #ifdef NCBI_FTDS
  1554. case SYBINT2:
  1555. tds_swap_2bytes(buf); break;
  1556. case SYBINT4:
  1557. tds_swap_4bytes(buf); break;
  1558. case SYBINT8:
  1559. tds_swap_8bytes(buf); break;
  1560. case SYBREAL:
  1561. tds_swap_4bytes(buf); break;
  1562. case SYBFLT8:
  1563. tds_swap_8bytes(buf); break;
  1564. case SYBMONEY4:
  1565. tds_swap_4bytes(buf); break;
  1566. case SYBMONEY:
  1567. tds_swap_4bytes(buf);
  1568. tds_swap_4bytes(&buf[4]); break;
  1569. case SYBDATETIME4:
  1570. tds_swap_2bytes(buf);
  1571. tds_swap_2bytes(&buf[2]); break;
  1572. case SYBDATETIME:
  1573. tds_swap_4bytes(buf);
  1574. tds_swap_4bytes(&buf[4]); break;
  1575. case SYBNUMERIC:
  1576. case SYBDECIMAL:
  1577. num = (TDS_NUMERIC *) buf;
  1578.             /* swap the sign */
  1579.             num->array[0] = (num->array[0] == 0) ? 1 : 0;
  1580.             /* swap the data */
  1581.             tds_swap_bytes(&(num->array[1]),
  1582.                            g__numeric_bytes_per_prec[num->precision] - 1); break;
  1583.         case SYBUNIQUE:
  1584. tds_swap_4bytes(buf);
  1585. tds_swap_2bytes(&buf[4]); 
  1586. tds_swap_2bytes(&buf[6]); break;
  1587. #else
  1588. case SYBINT2:
  1589. tds_swap_bytes(buf,2); break;
  1590. case SYBINT4:
  1591. tds_swap_bytes(buf,4); break;
  1592. case SYBINT8:
  1593. tds_swap_bytes(buf,8); break;
  1594. case SYBREAL:
  1595. tds_swap_bytes(buf,4); break;
  1596. case SYBFLT8:
  1597. tds_swap_bytes(buf,8); break;
  1598. case SYBMONEY4:
  1599. tds_swap_bytes(buf,4); break;
  1600. case SYBMONEY:
  1601. tds_swap_bytes(buf,4);
  1602. tds_swap_bytes(&buf[4],4); break;
  1603. case SYBDATETIME4:
  1604. tds_swap_bytes(buf,2);
  1605. tds_swap_bytes(&buf[2],2); break;
  1606. case SYBDATETIME:
  1607. tds_swap_bytes(buf,4);
  1608. tds_swap_bytes(&buf[4],4); break;
  1609. case SYBNUMERIC:
  1610. case SYBDECIMAL:
  1611. num = (TDS_NUMERIC *) buf;
  1612.             /* swap the sign */
  1613.             num->array[0] = (num->array[0] == 0) ? 1 : 0;
  1614.             /* swap the data */
  1615.             tds_swap_bytes(&(num->array[1]),
  1616.                            g__numeric_bytes_per_prec[num->precision] - 1); break;
  1617.         case SYBUNIQUE:
  1618. tds_swap_bytes(buf,4);
  1619. tds_swap_bytes(&buf[4],2); 
  1620. tds_swap_bytes(&buf[6],2); break;
  1621. #endif
  1622. }
  1623. }
  1624. /*
  1625. ** tds_get_varint_size() returns the size of a variable length integer
  1626. ** returned in a TDS 7.0 result string
  1627. */
  1628. static int tds_get_varint_size(int datatype)
  1629. {
  1630. switch(datatype) {
  1631. case SYBTEXT:
  1632. case SYBNTEXT:
  1633. case SYBIMAGE:
  1634. case SYBVARIANT:
  1635. return 4;
  1636. case SYBVOID:
  1637. case SYBINT1:
  1638. case SYBBIT:
  1639. case SYBINT2:
  1640. case SYBINT4:
  1641. case SYBDATETIME4:
  1642. case SYBREAL:
  1643. case SYBMONEY:
  1644. case SYBDATETIME:
  1645. case SYBFLT8:
  1646. case SYBMONEY4:
  1647. case SYBINT8:
  1648. return 0;
  1649. case XSYBNCHAR:
  1650. case XSYBNVARCHAR:
  1651. case XSYBCHAR:
  1652. case XSYBVARCHAR:
  1653. case XSYBBINARY:
  1654. case XSYBVARBINARY:
  1655. return 2;
  1656. default:
  1657. return 1;
  1658. }
  1659. }
  1660. static int tds_get_cardinal_type(int datatype)
  1661. {
  1662. switch(datatype) {
  1663. case XSYBVARBINARY: 
  1664. return SYBVARBINARY;
  1665. case XSYBBINARY: 
  1666. return SYBBINARY;
  1667. case SYBNTEXT:
  1668. return SYBTEXT;
  1669. case XSYBNVARCHAR: 
  1670. case XSYBVARCHAR: 
  1671. return SYBVARCHAR;
  1672. case XSYBNCHAR: 
  1673. case XSYBCHAR: 
  1674. return SYBCHAR;
  1675. }
  1676. return datatype;
  1677. }