⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blk.c

📁 在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		if (is_numeric_type(bcpcol->on_server.column_type)) {			tds_put_byte(tds, bcpcol->column_prec);			tds_put_byte(tds, bcpcol->column_scale);		}		if (IS_TDS8_PLUS(tds)			&& is_collate_type(bcpcol->on_server.column_type)) {			tds_put_n(tds, bcpcol->column_collation, 5);		}		if (is_blob_type(bcpcol->on_server.column_type)) {			tds_put_smallint(tds, strlen(blkdesc->tablename));			tds_put_string(tds, blkdesc->tablename, strlen(blkdesc->tablename));		}		/* FIXME support multibyte string */		tds_put_byte(tds, bcpcol->column_namelen);		tds_put_string(tds, bcpcol->column_name, bcpcol->column_namelen);	}	return CS_SUCCEED;}static CS_RETCODE_blk_build_bcp_record(CS_BLKDESC *blkdesc, CS_INT offset){	TDSSOCKET  *tds = blkdesc->con->tds_socket;	TDSCOLUMN  *bindcol;	static const unsigned char CHARBIN_NULL[] = { 0xff, 0xff };	static const unsigned char GEN_NULL = 0x00;	static const unsigned char textptr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,											 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff	};	static const unsigned char timestamp[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };	static const TDS_TINYINT textptr_size = 16;	const unsigned char row_token = 0xd1;	unsigned char *record;	TDS_INT	 old_record_size;	TDS_INT	 new_record_size;	TDS_INT	     varint_4;	TDS_SMALLINT varint_2;	TDS_TINYINT  varint_1;	int row_pos;	int row_sz_pos;	TDS_SMALLINT row_size;	int blob_cols = 0;	int var_cols_written = 0;	int i;	tdsdump_log(TDS_DBG_FUNC, "_blk_build_bcp_record(offset %d)\n", offset);	record = blkdesc->bindinfo->current_row;	old_record_size = blkdesc->bindinfo->row_size;	new_record_size = 0;	if (IS_TDS7_PLUS(tds)) {		for (i = 0; i < blkdesc->bindinfo->num_cols; i++) {				bindcol = blkdesc->bindinfo->columns[i];			/*			 * dont send the (meta)data for timestamp columns, or			 * identity columns (unless indentity_insert is enabled			 */			if ((!blkdesc->identity_insert_on && bindcol->column_identity) || 				bindcol->column_timestamp) {				continue;			}			if ((_blk_get_col_data(blkdesc, bindcol, offset)) != CS_SUCCEED) {				tdsdump_log(TDS_DBG_INFO1, "blk_get_colData (column %d) failed\n", i + 1);	 			return CS_FAIL;			}			tdsdump_log(TDS_DBG_INFO1, "gotten column %d length %d null %d\n",					i + 1, bindcol->bcp_column_data->datalen, bindcol->bcp_column_data->is_null);				if (bindcol->bcp_column_data->is_null) {				if (bindcol->column_nullable) {					switch (bindcol->on_server.column_type) {					case XSYBCHAR:					case XSYBVARCHAR:					case XSYBBINARY:					case XSYBVARBINARY:					case XSYBNCHAR:					case XSYBNVARCHAR:						memcpy(record, CHARBIN_NULL, 2);						record +=2;						new_record_size +=2;						break;					default:						*record = GEN_NULL;						record++;						new_record_size ++;						break;					}				} else {					/* No value or default value available and NULL not allowed. col = %d row = %d. */					_ctclient_msg(blkdesc->con, "blk_rowxfer", 2, 7, 1, 142, "%d, %d",  i + 1, offset + 1);					return CS_FAIL;				}			} else {				switch (bindcol->column_varint_size) {				case 4:					if (is_blob_type(bindcol->on_server.column_type)) {						*record = textptr_size; record++;						memcpy(record, textptr, 16); record += 16;						memcpy(record, timestamp, 8); record += 8;						new_record_size += 25;					}					varint_4 = bindcol->bcp_column_data->datalen;#if WORDS_BIGENDIAN					tds_swap_datatype(SYBINT4, (unsigned char *)&varint_4);#endif					memcpy(record, &varint_4, 4); record += 4; new_record_size +=4;					break;				case 2:					varint_2 = bindcol->bcp_column_data->datalen;#if WORDS_BIGENDIAN					tds_swap_datatype(SYBINT2, (unsigned char *)&varint_2);#endif					memcpy(record, &varint_2, 2); record += 2; new_record_size +=2;					break;				case 1:					varint_1 = bindcol->bcp_column_data->datalen;					if (is_numeric_type(bindcol->on_server.column_type)) 						varint_1 = tds_numeric_bytes_per_prec[bindcol->column_prec];					else						varint_1 = bindcol->bcp_column_data->datalen;					*record = varint_1; record++; new_record_size++;					break;				case 0:					break;				}#if WORDS_BIGENDIAN				tds_swap_datatype(bindcol->on_server.column_type, bindcol->bcp_column_data->data);#endif				if (is_numeric_type(bindcol->on_server.column_type)) {					CS_NUMERIC *num = (CS_NUMERIC *) bindcol->bcp_column_data->data;					if (IS_TDS7_PLUS(tds))						tds_swap_numeric((TDS_NUMERIC *) num);					memcpy(record, num->array, tds_numeric_bytes_per_prec[num->precision]);					record += tds_numeric_bytes_per_prec[num->precision]; 					new_record_size += tds_numeric_bytes_per_prec[num->precision];				} else {					memcpy(record, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen);					record += bindcol->bcp_column_data->datalen; new_record_size += bindcol->bcp_column_data->datalen;				}			}			tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n",					old_record_size, new_record_size);		}		tds_put_byte(tds, row_token);   /* 0xd1 */		tds_put_n(tds, blkdesc->bindinfo->current_row, new_record_size);	}  /* IS_TDS7_PLUS */	else {			memset(record, '\0', old_record_size);	/* zero the rowbuffer */			/*			 * offset 0 = number of var columns			 * offset 1 = row number.  zeroed (datasever assigns)			 */			row_pos = 2;			if ((row_pos = _blk_add_fixed_columns(blkdesc, offset, record, row_pos)) == CS_FAIL)				return CS_FAIL;			row_sz_pos = row_pos;			/* potential variable columns to write */			if (blkdesc->var_cols) {				if ((row_pos = _blk_add_variable_columns(blkdesc, offset, record, row_pos, &var_cols_written)) == CS_FAIL)					return CS_FAIL;			}			row_size = row_pos;			if (var_cols_written) {				memcpy(&record[row_sz_pos], &row_size, sizeof(row_size));				record[0] = var_cols_written;			}			tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n",					old_record_size, row_size);			tds_put_smallint(tds, row_size);			tds_put_n(tds, record, row_size);			/* row is done, now handle any text/image data */			blob_cols = 0;			for (i = 0; i < blkdesc->bindinfo->num_cols; i++) {				bindcol = blkdesc->bindinfo->columns[i];				if (is_blob_type(bindcol->column_type)) {					if ((_blk_get_col_data(blkdesc, bindcol, offset)) != CS_SUCCEED) {			 			return CS_FAIL;					}					/* unknown but zero */					tds_put_smallint(tds, 0);					tds_put_byte(tds, bindcol->column_type);					tds_put_byte(tds, 0xff - blob_cols);					/*					 * offset of txptr we stashed during variable					 * column processing 					 */					tds_put_smallint(tds, bindcol->column_textpos);					tds_put_int(tds, bindcol->bcp_column_data->datalen);					tds_put_n(tds, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen);					blob_cols++;				}			}	}	return CS_SUCCEED;}static CS_RETCODE_blk_add_fixed_columns(CS_BLKDESC * blkdesc, int offset, unsigned char * rowbuffer, int start){	TDS_NUMERIC *num;	int row_pos = start;	TDSCOLUMN *bcpcol;	int cpbytes;	int i, j;	tdsdump_log(TDS_DBG_FUNC, "_blk_add_fixed_columns (offset %d)\n", offset);	for (i = 0; i < blkdesc->bindinfo->num_cols; i++) {		bcpcol = blkdesc->bindinfo->columns[i];		if (!is_nullable_type(bcpcol->column_type) && !(bcpcol->column_nullable)) {			tdsdump_log(TDS_DBG_FUNC, "_blk_add_fixed_columns column %d is a fixed column\n", i + 1);			if (( _blk_get_col_data(blkdesc, bcpcol, offset)) != CS_SUCCEED) {		 		return CS_FAIL;			}			if (bcpcol->bcp_column_data->is_null) {				/* No value or default value available and NULL not allowed. col = %d row = %d. */				_ctclient_msg(blkdesc->con, "blk_rowxfer", 2, 7, 1, 142, "%d, %d",  i + 1, offset + 1);				return CS_FAIL;			}			if (is_numeric_type(bcpcol->column_type)) {				num = (TDS_NUMERIC *) bcpcol->bcp_column_data->data;				cpbytes = tds_numeric_bytes_per_prec[num->precision];				memcpy(&rowbuffer[row_pos], num->array, cpbytes);			} else {				cpbytes = bcpcol->bcp_column_data->datalen > bcpcol->column_size ? bcpcol->column_size : bcpcol->bcp_column_data->datalen;				memcpy(&rowbuffer[row_pos], bcpcol->bcp_column_data->data, cpbytes);				/* CHAR data may need padding out to the database length with blanks */				if (bcpcol->column_type == SYBCHAR && cpbytes < bcpcol->column_size) {					for (j = cpbytes; j <  bcpcol->column_size; j++)						rowbuffer[row_pos + j] = ' ';				}			}			row_pos += bcpcol->column_size;		}	}	return row_pos;}/** * Add variable size columns to the row */static int_blk_add_variable_columns(CS_BLKDESC * blkdesc, int offset, unsigned char * rowbuffer, int start, int *var_cols){	TDSCOLUMN   *bcpcol;	TDS_NUMERIC *num;	int row_pos;	int cpbytes;	unsigned char offset_table[256];	unsigned char adjust_table[256];	int offset_pos     = 0;	int adjust_pos     = 0;	int num_cols       = 0;	int last_adjustment_increment = 0;	int this_adjustment_increment = 0;	int i, adjust_table_entries_required;	/*	 * Skip over two bytes. These will be used to hold the entire record length	 * once the record has been completely built.	 */	row_pos = start + 2;	/* for each column in the target table */	tdsdump_log(TDS_DBG_FUNC, "_blk_add_variable_columns (offset %d)\n", offset);	for (i = 0; i < blkdesc->bindinfo->num_cols; i++) {		bcpcol = blkdesc->bindinfo->columns[i];		/*		 * is this column of "variable" type, i.e. NULLable		 * or naturally variable length e.g. VARCHAR		 */		if (is_nullable_type(bcpcol->column_type) || bcpcol->column_nullable) {			tdsdump_log(TDS_DBG_FUNC, "_blk_add_variable_columns column %d is a variable column\n", i + 1);			if ((_blk_get_col_data(blkdesc, bcpcol, offset)) != CS_SUCCEED) {		 		return CS_FAIL;			}			/*			 * but if its a NOT NULL column, and we have no data			 * throw an error			 */			if (!(bcpcol->column_nullable) && bcpcol->bcp_column_data->is_null) {				/* No value or default value available and NULL not allowed. col = %d row = %d. */				_ctclient_msg(blkdesc->con, "blk_rowxfer", 2, 7, 1, 142, "%d, %d",  i + 1, offset + 1);				return CS_FAIL;			}			if (is_blob_type(bcpcol->column_type)) {				cpbytes = 16;				bcpcol->column_textpos = row_pos;               /* save for data write */			} else if (is_numeric_type(bcpcol->column_type)) {				num = (TDS_NUMERIC *) bcpcol->bcp_column_data->data;				cpbytes = tds_numeric_bytes_per_prec[num->precision];				memcpy(&rowbuffer[row_pos], num->array, cpbytes);			} else {				/* compute the length to copy to the row ** buffer */				if (bcpcol->bcp_column_data->is_null) {					cpbytes = 0;				} else {					cpbytes = bcpcol->bcp_column_data->datalen > bcpcol->column_size ? bcpcol->column_size : bcpcol->bcp_column_data->datalen;					memcpy(&rowbuffer[row_pos], bcpcol->bcp_column_data->data, cpbytes);				}			}			/* if we have written data to the record for this column */			if (cpbytes > 0) {				/*				 * update offset table. Each entry in the offset table is a single byte				 * so can only hold a maximum value of 255. If the real offset is more				 * than 255 we will have to add one or more entries in the adjust table				 */				offset_table[offset_pos++] = row_pos % 256;				/* increment count of variable columns added to the record */				num_cols++;				/*				 * how many times does 256 have to be added to the one byte offset to				 * calculate the REAL offset...				 */				this_adjustment_increment = row_pos / 256;				/* has this changed since we did the last column...      */				if (this_adjustment_increment > last_adjustment_increment) {					/*					 * add n entries to the adjust table. each entry represents					 * an adjustment of 256 bytes, and each entry holds the					 * column number for which the adjustment needs to be made					 */					for ( adjust_table_entries_required = this_adjustment_increment - last_adjustment_increment;						  adjust_table_entries_required > 0;						  adjust_table_entries_required-- ) {							adjust_table[adjust_pos++] = num_cols;					}					last_adjustment_increment = this_adjustment_increment;				}				row_pos += cpbytes;			}		}	}	if (num_cols) {			/* 		 * If we have written any variable columns to the record, add entries 		 * to the offset and adjust tables for the end of data offset (as above). 		 */		offset_table[offset_pos++] = row_pos % 256;		/*		 * Write the offset data etc. to the end of the record, starting with 		 * a count of variable columns (plus 1 for the eod offset)       		 */		rowbuffer[row_pos++] = num_cols + 1;			/* write the adjust table (right to left) */		for (i = adjust_pos - 1; i >= 0; i--) {			rowbuffer[row_pos++] = adjust_table[i];		}			/* write the offset table (right to left) */		for (i = offset_pos - 1; i >= 0; i--) {			rowbuffer[row_pos++] = offset_table[i];		}	}	*var_cols = num_cols;	if (num_cols == 0) /* we haven't written anything */		return start;	else		return row_pos;}static CS_RETCODE_blk_get_col_data(CS_BLKDESC *blkdesc, TDSCOLUMN *bindcol, int offset) {	int result = 0;	CS_INT null_column = 0;		unsigned char *src = NULL;	CS_INT      srctype = 0;	CS_INT      srclen  = 0;	CS_INT      destlen  = 0;	CS_SMALLINT *nullind = NULL;	CS_INT      *datalen = NULL;	CS_CONTEXT *ctx = blkdesc->con->ctx;	CS_DATAFMT srcfmt, destfmt;	/*	 * retrieve the initial bound column_varaddress	 * and increment it if offset specified	 */	src = (unsigned char *) bindcol->column_varaddr;	src += offset * bindcol->column_bindlen;		if (bindcol->column_nullbind) {		nullind = bindcol->column_nullbind;		nullind += offset;	}	if (bindcol->column_lenbind) {		datalen = bindcol->column_lenbind;		datalen += offset;	}	if (src) {			srctype = bindcol->column_bindtype; 		/* used to pass to cs_convert */		tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data srctype = %d \n", srctype);		tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data datalen = %d \n", *datalen);			if (*datalen) {			if (*datalen == CS_UNUSED) {				switch (srctype) {					case CS_LONG_TYPE:	    srclen = 8; break;					case CS_FLOAT_TYPE:	    srclen = 8; break;					case CS_MONEY_TYPE:	    srclen = 8; break;					case CS_DATETIME_TYPE:  srclen = 8; break;					case CS_INT_TYPE:	    srclen = 4; break;					case CS_REAL_TYPE:	    srclen = 4; break;					case CS_MONEY4_TYPE:	srclen = 4; break;					case CS_DATETIME4_TYPE: srclen = 4; break;					case CS_SMALLINT_TYPE:  srclen = 2; break;					case CS_TINYINT_TYPE:   srclen = 1; break;					default:						printf("error not fixed length type (%d) and datalen not specified\n",							bindcol->column_bindtype);						return CS_FAIL;				}			} else {				srclen = *datalen;			}		}		if (srclen == 0) {			if (*nullind == -1) {				null_column = 1;			}		}		if (!null_column) {			srcfmt.datatype = srctype;			srcfmt.maxlength = srclen;			destfmt.datatype  = _ct_get_client_type(bindcol->column_type, bindcol->column_usertype, bindcol->column_size);			destfmt.maxlength = bindcol->column_size;			destfmt.precision = bindcol->column_prec;			destfmt.scale     = bindcol->column_scale;			destfmt.format	= CS_FMT_UNUSED;				/* if convert return FAIL mark error but process other columns */			if ((result = cs_convert(ctx, &srcfmt, (CS_VOID *) src, 						 &destfmt, (CS_VOID *) bindcol->bcp_column_data->data, &destlen)) != CS_SUCCEED) {				tdsdump_log(TDS_DBG_INFO1, "convert failed for %d \n", srcfmt.datatype);				return CS_FAIL;			}		}		bindcol->bcp_column_data->datalen = destlen;		bindcol->bcp_column_data->is_null = null_column;		return CS_SUCCEED;	} else {		printf("error source field not addressable \n");		return CS_FAIL;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -