📄 token.c
字号:
tds_free_all_results(tds); tds->rows_affected = TDS_NO_COUNT; if ((info = tds_alloc_results(num_names)) != NULL) { tds->current_results = tds->res_info = info; cur = head; for (col = 0; col < num_names; ++col) { curcol = info->columns[col]; tds_strlcpy(curcol->column_name, cur->name, sizeof(curcol->column_name)); curcol->column_namelen = strlen(curcol->column_name); prev = cur; cur = cur->next; free(prev->name); free(prev); } return TDS_SUCCEED; } tds_free_namelist(head); return TDS_FAIL;}/** * tds_process_col_fmt() is the other half of result set processing * under TDS 4.2. It follows tds_process_col_name(). It contains all the * column type and size information. * This is a 4.2 only function */static inttds_process_col_fmt(TDSSOCKET * tds){ int col, hdrsize; TDSCOLUMN *curcol; TDSRESULTINFO *info; TDS_SMALLINT tabnamesize; int bytes_read = 0; int rest; TDS_SMALLINT flags; CHECK_TDS_EXTRA(tds); hdrsize = tds_get_smallint(tds); /* TODO use current_results instead of res_info ?? */ info = tds->res_info; for (col = 0; col < info->num_cols; col++) { curcol = info->columns[col]; /* In Sybase all 4 byte are used for usertype, while mssql place 2 byte as usertype and 2 byte as flags */ if (TDS_IS_MSSQL(tds)) { curcol->column_usertype = tds_get_smallint(tds); flags = tds_get_smallint(tds); curcol->column_nullable = flags & 0x01; curcol->column_writeable = (flags & 0x08) > 0; curcol->column_identity = (flags & 0x10) > 0; } else { curcol->column_usertype = tds_get_int(tds); } /* on with our regularly scheduled code (mlilback, 11/7/01) */ tds_set_column_type(tds, curcol, tds_get_byte(tds)); tdsdump_log(TDS_DBG_INFO1, "processing result. type = %d(%s), varint_size %d\n", curcol->column_type, tds_prtype(curcol->column_type), curcol->column_varint_size); switch (curcol->column_varint_size) { case 4: curcol->column_size = tds_get_int(tds); /* junk the table name -- for now */ tabnamesize = tds_get_smallint(tds); tds_get_n(tds, NULL, tabnamesize); bytes_read += 5 + 4 + 2 + tabnamesize; break; case 1: curcol->column_size = tds_get_byte(tds); bytes_read += 5 + 1; break; case 0: bytes_read += 5 + 0; break; } /* Adjust column size according to client's encoding */ curcol->on_server.column_size = curcol->column_size; adjust_character_column_size(tds, curcol); } /* get the rest of the bytes */ rest = hdrsize - bytes_read; if (rest > 0) { tdsdump_log(TDS_DBG_INFO1, "NOTE:tds_process_col_fmt: draining %d bytes\n", rest); tds_get_n(tds, NULL, rest); } return tds_alloc_row(info);}static inttds8_read_table_names(TDSSOCKET *tds, int remainder, struct namelist **p_head){ struct namelist *head = NULL, *cur = NULL, *prev; int num_names = 0; /* * this is a little messy...TDS 5.0 gives the number of columns * upfront, while in TDS 4.2, you're expected to figure it out * by the size of the message. So, I use a link list to get the * colum names and then allocate the result structure, copy * and delete the linked list */ while (remainder > 0) { int namelen, elements, i, len; char *partials[4], *p; prev = cur; if (!(cur = (struct namelist *) malloc(sizeof(struct namelist)))) { tds_free_namelist(head); return -1; } cur->name = NULL; cur->next = NULL; if (prev) prev->next = cur; else head = cur; elements = tds_get_byte(tds); --remainder; if (elements <= 0 || elements > 4) { tds_free_namelist(head); return -1; } /* read partials IDs and compute full length */ len = 0; for (i = 0; i < elements; ++i) { namelen = tds_get_smallint(tds); remainder -= 2 + 2 * namelen; if (tds_alloc_get_string(tds, &partials[i], namelen) < 0) { while (i > 0) free(partials[--i]); tds_free_namelist(head); return -1; } len += tds_quote_id(tds, NULL, partials[i], -1) + 1; } /* allocate full name */ p = (char *) malloc(len); if (!p) { i = elements; while (i > 0) free(partials[--i]); tds_free_namelist(head); return -1; } /* compose names */ cur->name = p; for (i = 0; i < elements; ++i) { p += tds_quote_id(tds, p, partials[i], -1); *p++ = '.'; free(partials[i]); } *--p = 0; num_names++; } *p_head = head; return num_names;}static inttds_process_tabname(TDSSOCKET *tds){ struct namelist *head, *cur; int num_names, hdrsize, i; char **names; unsigned char marker; int rc; hdrsize = tds_get_smallint(tds); /* different structure for tds8 */ if (IS_TDS8_PLUS(tds)) num_names = tds8_read_table_names(tds, hdrsize, &head); else num_names = tds_read_namelist(tds, hdrsize, &head, 1); if (num_names < 0) return TDS_FAIL; /* put in an array */ names = (char **) malloc(num_names * sizeof(char*)); if (!names) { tds_free_namelist(head); return TDS_FAIL; } for (cur = head, i = 0; i < num_names; ++i, cur = cur->next) names[i] = cur->name; rc = TDS_SUCCEED; marker = tds_get_byte(tds); if (marker != TDS_COLINFO_TOKEN) tds_unget_byte(tds); else rc = tds_process_colinfo(tds, names, num_names); free(names); tds_free_namelist(head); return rc;}static inttds_process_colinfo(TDSSOCKET * tds, char **names, int num_names){ int hdrsize; TDSCOLUMN *curcol; TDSRESULTINFO *info; int bytes_read = 0; unsigned char col_info[3], l; CHECK_TDS_EXTRA(tds); hdrsize = tds_get_smallint(tds); info = tds->current_results; while (bytes_read < hdrsize) { tds_get_n(tds, col_info, 3); bytes_read += 3; curcol = NULL; if (info && col_info[0] > 0 && col_info[0] <= info->num_cols) curcol = info->columns[col_info[0] - 1]; if (curcol) { curcol->column_writeable = (col_info[2] & 0x4) == 0; curcol->column_key = (col_info[2] & 0x8) > 0; curcol->column_hidden = (col_info[2] & 0x10) > 0; if (names && col_info[1] > 0 && col_info[1] <= num_names) { tds_strlcpy(curcol->table_name, names[col_info[1] - 1], sizeof(curcol->table_name)); curcol->table_namelen = strlen(curcol->table_name); } } /* read real column name */ if (col_info[2] & 0x20) { l = tds_get_byte(tds); if (curcol) { if (curcol->table_column_name) TDS_ZERO_FREE(curcol->table_column_name); tds_alloc_get_string(tds, &curcol->table_column_name, l); if (IS_TDS7_PLUS(tds)) l *= 2; } else { if (IS_TDS7_PLUS(tds)) l *= 2; /* discard silently */ tds_get_n(tds, NULL, l); } bytes_read += l + 1; } } return TDS_SUCCEED;}/** * process output parameters of a stored * procedure. This differs from regular row/compute results in that there * is no total number of parameters given, they just show up singly. */static inttds_process_param_result(TDSSOCKET * tds, TDSPARAMINFO ** pinfo){ int hdrsize; TDSCOLUMN *curparam; TDSPARAMINFO *info; int token; tdsdump_log(TDS_DBG_FUNC, "tds_process_param_result(%p, %p)\n", tds, pinfo); CHECK_TDS_EXTRA(tds); if (*pinfo) CHECK_PARAMINFO_EXTRA(*pinfo); /* TODO check if current_results is a param result */ /* limited to 64K but possible types are always smaller (not TEXT/IMAGE) */ hdrsize = tds_get_smallint(tds); if ((info = tds_alloc_param_result(*pinfo)) == NULL) return TDS_FAIL; *pinfo = info; curparam = info->columns[info->num_cols - 1]; /* * FIXME check support for tds7+ (seem to use same format of tds5 for data...) * perhaps varint_size can be 2 or collation can be specified ?? */ tds_get_data_info(tds, curparam, 1); curparam->column_cur_size = curparam->column_size; /* needed ?? */ if (tds_alloc_param_data(curparam) == NULL) return TDS_FAIL; token = tds_get_data(tds, curparam); /* * Real output parameters will either be unnamed or will have a valid * parameter name beginning with '@'. Ignore any other Spurious parameters * such as those returned from calls to writetext in the proc. */ if (curparam->column_namelen > 0 && curparam->column_name[0] != '@') tds_free_param_result(*pinfo); return token;}static inttds_process_param_result_tokens(TDSSOCKET * tds){ int marker; TDSPARAMINFO **pinfo; CHECK_TDS_EXTRA(tds); if (tds->cur_dyn) pinfo = &(tds->cur_dyn->res_info); else pinfo = &(tds->param_info); while ((marker = tds_get_byte(tds)) == TDS_PARAM_TOKEN) { tds_process_param_result(tds, pinfo); } if (!marker) { tdsdump_log(TDS_DBG_FUNC, "error: tds_process_param_result() returned TDS_FAIL\n"); return TDS_FAIL; } tds->current_results = *pinfo; tds_unget_byte(tds); return TDS_SUCCEED;}/** * tds_process_params_result_token() processes params on TDS5. */static inttds_process_params_result_token(TDSSOCKET * tds){ int i; TDSCOLUMN *curcol; TDSPARAMINFO *info; CHECK_TDS_EXTRA(tds); /* TODO check if current_results is a param result */ info = tds->current_results; if (!info) return TDS_FAIL; for (i = 0; i < info->num_cols; i++) { curcol = info->columns[i]; if (tds_get_data(tds, curcol) != TDS_SUCCEED) return TDS_FAIL; } return TDS_SUCCEED;}/** * tds_process_compute_result() processes compute result sets. These functions * need work but since they get little use, nobody has complained! * It is very similar to normal result sets. */static inttds_process_compute_result(TDSSOCKET * tds){ int hdrsize; int col, num_cols; TDS_TINYINT by_cols = 0; TDS_SMALLINT *cur_by_col; TDS_SMALLINT compute_id = 0; TDSCOLUMN *curcol; TDSCOMPUTEINFO *info; int i; CHECK_TDS_EXTRA(tds); hdrsize = tds_get_smallint(tds); /* * compute statement id which this relates * to. You can have more than one compute * statement in a SQL statement */ compute_id = tds_get_smallint(tds); tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. compute_id = %d\n", compute_id); /* * number of compute columns returned - so * COMPUTE SUM(x), AVG(x)... would return * num_cols = 2 */ num_cols = tds_get_byte(tds); for (i = 0;; ++i) { if (i >= tds->num_comp_info) return TDS_FAIL; info = tds->comp_info[i]; tdsdump_log(TDS_DBG_FUNC, "in dbaltcolid() found computeid = %d\n", info->computeid); if (info->computeid == compute_id) break; } tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. num_cols = %d\n", num_cols); for (col = 0; col < num_cols; col++) { tdsdump_log(TDS_DBG_INFO1, "processing tds7 compute result. point 2\n"); curcol = info->columns[col]; curcol->column_operator = tds_get_byte(tds); curcol->column_operand = tds_get_byte(tds); /* * if no name has been defined for the compute column, * put in "max", "avg" etc. */ if (curcol->column_namelen == 0) { strcpy(curcol->column_name, tds_pr_op(curcol->column_operator)); curcol->column_namelen = strlen(curcol->column_name); } /* User defined data type of the column */ curcol->column_usertype = tds_get_int(tds); tds_set_column_type(tds, curcol, tds_get_byte(tds)); switch (curcol->column_varint_size) { case 4: curcol->column_size = tds_get_int(tds); break; case 2: curcol->column_size = tds_get_smallint(tds); break; case 1: curcol->column_size = tds_get_byte(tds); break; case 0:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -