📄 token.c
字号:
curcol = info->columns[i]; cur_col_type= curcol->column_type; tdsdump_log(TDS_DBG_INFO1, "%L processing row. column is %d varint size = %d\n", i, curcol->column_varint_size); switch (curcol->column_varint_size) { case 4: /* Its a BLOB... */ len = tds_get_byte(tds); if (len == 16) { /* Jeff's hack */ tds_get_n(tds,curcol->column_textptr,16); tds_get_n(tds,curcol->column_timestamp,8); colsize = tds_get_int(tds); } else { colsize = 0; } break; case 2: /* FIXME add support for empty no-NULL string*/ colsize = tds_get_smallint(tds); if (colsize == -1) colsize=0; break; case 1: colsize = tds_get_byte(tds); break; case 0: colsize = get_size_by_type(cur_col_type); break; } tdsdump_log(TDS_DBG_INFO1, "%L processing row. column size is %d \n", colsize); /* set NULL flag in the row buffer */ if (colsize==0) { tds_set_null(info->current_row, i); } else { tds_clr_null(info->current_row, i); if (is_numeric_type(cur_col_type)) { /* ** handling NUMERIC datatypes: ** since these can be passed around independent ** of the original column they were from, I decided ** to embed the TDS_NUMERIC datatype in the row buffer ** instead of using the wire representation even though ** it uses a few more bytes */ num = (TDS_NUMERIC *) &(info->current_row[curcol->column_offset]); memset(num, '\0', sizeof(TDS_NUMERIC)); num->precision = curcol->column_prec; num->scale = curcol->column_scale; tds_get_n(tds,num->array,colsize); /* corrected colsize for cur_row_size */ colsize = sizeof(TDS_NUMERIC); if (IS_TDS70(tds) || IS_TDS80(tds)) { tdsdump_log(TDS_DBG_INFO1, "%L swapping numeric data...\n"); tds_swap_datatype(tds_get_conversion_type(cur_col_type, colsize), (unsigned char *)num ); } } else if (cur_col_type == SYBVARBINARY) { varbin = (TDS_VARBINARY *) &(info->current_row[curcol->column_offset]); varbin->len = colsize; /* It is important to re-zero out the whole column_size varbin array here because the result of the query ("colsize") may be any number of bytes <= column_size (because the result will be truncated if the rest of the data in the column would be all zeros). */ memset(varbin->array,'\0',curcol->column_size); tds_get_n(tds,varbin->array,colsize); } else if (is_blob_type(cur_col_type)) { if (curcol->column_unicodedata) colsize /= 2; curcol->column_textvalue = realloc(curcol->column_textvalue,colsize+1); /* FIXME +1 needed by tds_get_string */ curcol->column_textsize = colsize; if (curcol->column_unicodedata) { tds_get_string(tds,curcol->column_textvalue,colsize); } else { tds_get_n(tds,curcol->column_textvalue,colsize); } } else { dest = &(info->current_row[curcol->column_offset]); if (curcol->column_unicodedata) { tds_get_string(tds,dest,colsize/2); colsize /= 2; } else { tds_get_n(tds,dest,colsize); } /* FIXME correct for unicode ? */#ifdef NCBI_FTDS if(cur_col_type == SYBVARCHAR)#endif dest[colsize]='\0'; if (cur_col_type == SYBDATETIME4) { tdsdump_log(TDS_DBG_INFO1, "%L datetime4 %d %d %d %d\n", dest[0], dest[1], dest[2], dest[3]); } } /* Value used to properly know value in dbdatlen. (mlilback, 11/7/01) */ curcol->cur_row_size = colsize;#ifdef WORDS_BIGENDIAN /* MS SQL Server 7.0 has broken date types from big endian ** machines, this swaps the low and high halves of the ** affected datatypes ** ** Thought - this might be because we don't have the ** right flags set on login. -mjs ** ** Nope its an actual MS SQL bug -bsb */ if (tds->broken_dates && (cur_col_type == SYBDATETIME || cur_col_type == SYBDATETIME4 || cur_col_type == SYBDATETIMN || cur_col_type == SYBMONEY || cur_col_type == SYBMONEY4 || (cur_col_type == SYBMONEYN && curcol->column_size > 4))) /* above line changed -- don't want this for 4 byte SYBMONEYN values (mlilback, 11/7/01) */ { unsigned char temp_buf[8]; memcpy(temp_buf,dest,colsize/2); memcpy(dest,&dest[colsize/2],colsize/2); memcpy(&dest[colsize/2],temp_buf,colsize/2); } if (tds->emul_little_endian && !is_numeric_type(cur_col_type)) { tdsdump_log(TDS_DBG_INFO1, "%L swapping coltype %d\n", tds_get_conversion_type(cur_col_type,colsize)); tds_swap_datatype(tds_get_conversion_type(cur_col_type, colsize), &(info->current_row[curcol->column_offset]) ); }#endif } } return TDS_SUCCEED;}/*** tds_process_end() processes any of the DONE, DONEPROC, or DONEINPROC** tokens.*/TDS_INT tds_process_end( TDSSOCKET *tds, int marker, int *more_results_parm, int *was_cancelled_parm){int more_results, was_cancelled;int tmp = tds_get_smallint(tds); more_results = (tmp & 0x1) != 0; was_cancelled = (tmp & 0x20) != 0; if (tds->res_info) { tds->res_info->more_results=more_results; if (was_cancelled || !(more_results)) { tds->state = TDS_COMPLETED; } } if (more_results_parm) *more_results_parm = more_results; if (was_cancelled_parm) *was_cancelled_parm = was_cancelled; tds_get_smallint(tds); /* rows affected is in the tds struct because a query may affect rows but ** have no result set. */ tds->rows_affected = tds_get_int(tds); return tds->rows_affected;}/*** tds_client_msg() sends a message to the client application from the CLI or** TDS layer. A client message is one that is generated from with the library** and not from the server. The message is sent to the CLI (the ** err_handler) so that it may forward it to the client application or** discard it if no msg handler has been by the application. tds->parent** contains a void pointer to the parent of the tds socket. This can be cast** back into DBPROCESS or CS_CONNECTION by the CLI and used to determine the** proper recipient function for this message.*/int tds_client_msg(TDSCONTEXT *tds_ctx, TDSSOCKET *tds, int msgnum, int level, int state, int line, char *message){int ret;TDSMSGINFO msg_info; if(tds_ctx->err_handler) { memset(&msg_info, 0, sizeof(TDSMSGINFO)); msg_info.msg_number=msgnum; msg_info.msg_level=level; /* severity? */ msg_info.msg_state=state; msg_info.server=strdup("OpenClient"); msg_info.line_number=line; msg_info.message=strdup(message); ret = tds_ctx->err_handler(tds_ctx, tds, &msg_info); /* message handler returned FAIL/CS_FAIL ** mark socket as dead */ if (ret && tds) { tds->state=TDS_DEAD; } } return 0;}/*** tds_process_env_chg() ** when ever certain things change on the server, such as database, character** set, language, or block size. A environment change message is generated** There is no action taken currently, but certain functions at the CLI level** that return the name of the current database will need to use this.*/#ifdef NCBI_FTDSextern int tds_process_env_chg(TDSSOCKET *tds){int size, type,env_left;char oldval[1024], newval[1024];int new_block_size;TDSENVINFO *env = tds->env; env_left = tds_get_smallint(tds); /* this came in a patch, apparently someone saw an env message ** that was different from what we are handling? -- brian ** changed back because it won't handle multibyte chars -- 7.0 */ /* tds_get_n(tds,NULL,size); */ type = tds_get_byte(tds); env_left--; switch(type){ case TDS_ENV_BLOCKSIZE: /* fetch the new value */ size = tds_get_byte(tds); if(size) tds_get_string(tds,newval,size); newval[size]='\0'; /* fetch the old value */ size = tds_get_byte(tds); if(size) tds_get_string(tds,oldval,size); oldval[size]='\0'; new_block_size = atoi(newval); if (new_block_size > env->block_size) { tdsdump_log(TDS_DBG_INFO1, "%L increasing block size from %d to %d\n", env->block_size, new_block_size); /* ** I'm not aware of any way to shrink the ** block size but if it is possible, we don't ** handle it. */ tds->out_buf = (unsigned char*) realloc(tds->out_buf, new_block_size); env->block_size = new_block_size; } break; case TDS_ENV_DATABASE: case TDS_ENV_CHARSET: tds_get_n(tds,NULL,env_left); break; default: tdsdump_log(TDS_DBG_INFO1, "%L unknown TDS_ENV type %d, skipping %d bytes block\n", type, env_left); tds_get_n(tds,NULL,env_left); break; } return TDS_SUCCEED;}#elseint tds_process_env_chg(TDSSOCKET *tds){int size, type;char *oldval, *newval;int new_block_size;TDSENVINFO *env = tds->env; size = tds_get_smallint(tds); /* this came in a patch, apparently someone saw an env message ** that was different from what we are handling? -- brian ** changed back because it won't handle multibyte chars -- 7.0 */ /* tds_get_n(tds,NULL,size); */ type = tds_get_byte(tds); if (type==0x07) { size = tds_get_byte(tds); if (size) tds_get_n(tds, NULL, size); size = tds_get_byte(tds); if (size) tds_get_n(tds, NULL, size); return TDS_SUCCEED; } /* fetch the new value */ size = tds_get_byte(tds); newval = (char *) malloc((size+1)*2); tds_get_string(tds,newval,size); newval[size]='\0'; /* fetch the old value */ size = tds_get_byte(tds); oldval = (char *) malloc((size+1)*2); /* may be a unicode string */ tds_get_string(tds,oldval,size); oldval[size]='\0'; switch (type) { case TDS_ENV_BLOCKSIZE: new_block_size = atoi(newval); if (new_block_size > env->block_size) { tdsdump_log(TDS_DBG_INFO1, "%L increasing block size from %s to %d\n", oldval, new_block_size); /* ** I'm not aware of any way to shrink the ** block size but if it is possible, we don't ** handle it. */ tds->out_buf = (unsigned char*) realloc(tds->out_buf, new_block_size); env->block_size = new_block_size; } break; } free(oldval); free(newval); return TDS_SUCCEED;}#endifint tds_process_column_row(TDSSOCKET *tds){int colsize, i;TDSCOLINFO *curcol;TDSRESULTINFO *info;unsigned char *dest; info = tds->res_info; info->row_count++; for (i=0;i<(info->num_cols -1);i++) { curcol = info->columns[i]; if (!is_fixed_type(curcol->column_type)) { colsize = tds_get_byte(tds); } else { colsize = get_size_by_type(curcol->column_type); } dest = &(info->current_row[curcol->column_offset]); tds_get_n(tds,dest,colsize);#ifndef NCBI_FTDS dest[colsize]='\0';#endif /* printf("%s\n",curcol->column_value); */ } /* now skip over some stuff and get the rest of the columns */ tds_get_n(tds,NULL,25); colsize = tds_get_byte(tds); tds_get_n(tds,NULL,3); curcol = info->columns[i]; dest = &(info->current_row[curcol->column_offset]); tds_get_n(tds,dest,colsize);#ifndef NCBI_FTDS dest[colsize]='\0';#endif return TDS_SUCCEED;}/*** tds_process_msg() is called for MSG, ERR, or EED tokens and is responsible** for calling the CLI's message handling routine** returns TDS_SUCCEED if informational, TDS_ERROR if error.**** Note: the called function is responsible for calling tds_reset_msg on the ** passed structure.*/static int tds_process_msg(TDSSOCKET *tds,int marker){int rc;int len;int len_msg;int len_svr;int len_sqlstate; /* make sure message has been freed */ tds_free_msg(tds->msg_info); /* packet length */ len = tds_get_smallint(tds); /* message number */ rc = tds_get_int(tds); tds->msg_info->msg_number = rc; /* msg state */ tds->msg_info->msg_state = tds_get_byte(tds); /* msg level */ tds->msg_info->msg_level = tds_get_byte(tds); /* determine if msg or error */ if (marker==TDS_EED_TOKEN) { if (tds->msg_info->msg_level<=10) tds->msg_info->priv_msg_type = 0; else tds->msg_info->priv_msg_type = 1; /* junk this info for now */ len_sqlstate = tds_get_byte(tds); tds->msg_info->sql_state = (char*)malloc(len_sqlstate+1); tds_get_n(tds, tds->msg_info->sql_state,len_sqlstate); tds->msg_info->sql_state[len_sqlstate] = '\0'; /* unknown values */ tds_get_byte(tds); tds_get_smallint(tds); } else if (marker==TDS_MSG_TOKEN) { tds->msg_info->priv_msg_type = 0; } else if (marker==TDS_ERR_TOKEN) { tds->msg_info->priv_msg_type = 1; } else { tdsdump_log(TDS_DBG_ERROR,"tds_process_msg() called with unknown marker!\n"); return TDS_FAIL; } /* the message */ len_msg = tds_get_smallint(tds); tds->msg_info->message = (char*)malloc(len_msg+1); tds_get_string(tds, tds->msg_info->message, len_msg); tds->msg_info->message[len_msg] = '\0'; /* server name */ len_svr = tds_get_byte(tds); tds->msg_info->server = (char*)malloc(len_svr+1); tds_get_string(tds, tds->msg_info->server, len_svr); tds->msg_info->server[len_svr] = '\0'; /* stored proc name if available */ rc = tds_get_byte(tds); if (rc) { tds_unget_byte(tds); tds->msg_info->proc_name=tds_msg_get_proc_name(tds); } else { tds->msg_info->proc_name=strdup(""); } /* line number in the sql statement where the problem occurred */ tds->msg_info->line_number = tds_get_smallint(tds); if (tds->msg_info->priv_msg_type) { rc = TDS_ERROR; } else { rc = TDS_SUCCEED; } /* call the global_tds_msg_handler that was set by an upper layer ** (dblib, ctlib or some other one). Call it with the pointer to ** the "parent" structure. */ if(tds->msg_info->priv_msg_type ? tds->tds_ctx->err_handler : tds->tds_ctx->msg_handler) { if (tds->msg_info->priv_msg_type) tds->tds_ctx->err_handler(tds->tds_ctx, tds, tds->msg_info); else tds->tds_ctx->msg_handler(tds->tds_ctx, tds, tds->msg_info); } else { if(tds->msg_info->msg_number) tdsdump_log(TDS_DBG_WARN, "%L Msg %d, Level %d, State %d, Server %s, Line %d\n%s\n", tds->msg_info->msg_number, tds->msg_info->msg_level, tds->msg_info->msg_state,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -