示例#1
0
static harg*
create_harg
  (hargtype_t type,
   void      *data,
   unsigned   size)
{
  harg *h ; 

  if (!is_blob_type (type) && size == 0)
    size = sizeof (void*);
  
  h = XMALLOC (HARG_SIZE (size));
  h->type = type ;
  h->size = size ;

  if (!is_blob_type (type)) {
    h->d.d.ptr [0] = data ;
    return h;
  }

  if (verify_simple_type (type, HARG_STRING) && size != 0)
    /* last character is '\0' */
    h->d.d.data [ -- size] = '\0' ;

  if (size != 0 && data != 0)
    memcpy (h->d.d.data, data, size);
  return h;
}
示例#2
0
int
harg_set_valuet
  (harglst      *a,
   hargkey_t  *key,
   hargtype_t type,
   unsigned   size,
   void     *value)
{
  harg **R, *r ;
  int klen = klen_by_type (type);

  /* sanity check */
  if (a == 0 || key == 0 ||
      size == 0 && (value == 0 && is_blob_type (type) ||
		    verify_simple_type (type, HARG_BLOB))) {
    errno = EINVAL; 
    return -1;
  }
  

    R = (harg**)find_hlst (a->x, key, klen);

  if ((r = *R) == 0) { /* zombie, should not happen, anyway */
    delete_hlst (a->x, key, klen);
    errno = ENOENT ;
    return -1;
  }
  if (falsify_given_type (type, (*R)->type)) {
    errno = EPERM;  /* not permitted */
    return -1;
  }
  if (is_blob_type (r->type) == 0) {
    r->d.d.ptr [0] = value ; /* the quick way */
    return 0;
  }
  if (verify_simple_type (r->type, HARG_STRING)) {
    if (size == 0) /* need a terminating '\0' */
      size = strlen (value) + 1 ;
    else
      size ++ ;
  }
  /* remains to any blob type */
  if (r->size != size) { /* reallocate that entry */
    *R = create_harg (r->type, value, size);
    XFREE (r);
    return 0;
  } 
  if (value != 0) {
    if (verify_simple_type (r->type, HARG_STRING))
      /* the string terminator may be on protected memory */
      r->d.d.data [-- size] = '\0' ;
    memcpy (r->d.d.data, value, size);
  }
  return 0;
}
void
tds7_send_result(TDSSOCKET * tds, TDSRESULTINFO * resinfo)
{
	int i, j;
	TDSCOLUMN *curcol;

	/* TDS7+ uses TDS7_RESULT_TOKEN to send column names and info */
	tds_put_byte(tds, TDS7_RESULT_TOKEN);

	/* send the number of columns */
	tds_put_smallint(tds, resinfo->num_cols);

	/* send info about each column */
	for (i = 0; i < resinfo->num_cols; i++) {

		/* usertype, flags, and type */
		curcol = resinfo->columns[i];
		tds_put_smallint(tds, curcol->column_usertype);
		tds_put_smallint(tds, curcol->column_flags);
		tds_put_byte(tds, curcol->column_type); /* smallint? */

		/* bytes in "size" field varies */
		if (is_blob_type(curcol->column_type)) {
			tds_put_int(tds, curcol->column_size);
		} else if (curcol->column_type>=128) { /*is_large_type*/
			tds_put_smallint(tds, curcol->column_size);
		} else {
			tds_put_tinyint(tds, curcol->column_size);
		}

		/* some types have extra info */
		if (is_numeric_type(curcol->column_type)) {
			tds_put_tinyint(tds, curcol->column_prec);
			tds_put_tinyint(tds, curcol->column_scale);
		} else if (is_blob_type(curcol->column_type)) {
			size_t len = tds_dstr_len(&curcol->table_name);
			const char *name = tds_dstr_cstr(&curcol->table_name);

			tds_put_smallint(tds, 2 * len);
			for (j = 0; name[j] != '\0'; j++){
				tds_put_byte(tds, name[j]);
				tds_put_byte(tds, 0);
			}
		}

		/* finally the name, in UCS16 format */
		assert(strlen(curcol->column_name) == curcol->column_namelen);
		tds_put_byte(tds, curcol->column_namelen);
		for (j = 0; j < curcol->column_namelen; j++) {
			tds_put_byte(tds, curcol->column_name[j]);
			tds_put_byte(tds, 0);
		}
	}
}
示例#4
0
/** 
 * Tell the TDSPARAMINFO structure where the data go.  This is a kind of "bind" operation.
 */
static const unsigned char *
param_row_alloc(TDSPARAMINFO * params, TDSCOLUMN * curcol, int param_num, void *value, int size)
{
	const unsigned char *row = tds_alloc_param_row(params, curcol);
	tdsdump_log(TDS_DBG_INFO1, "parameter size = %d, offset = %d, row_size = %d\n",
				   size, curcol->column_offset, params->row_size);
	if (!row)
		return NULL;
	if (size > 0 && value) {
		tdsdump_log(TDS_DBG_FUNC, "copying %d bytes of data to parameter #%d\n", size, param_num);
		if (!is_blob_type(curcol->column_type)) {
			memcpy(&params->current_row[curcol->column_offset], value, size);
		} else {
			TDSBLOB *blob = (TDSBLOB *) &params->current_row[curcol->column_offset];
			blob->textvalue = malloc(size);
			tdsdump_log(TDS_DBG_FUNC, "blob parameter supported, size %d textvalue pointer is %p\n", size, blob->textvalue);
			if (!blob->textvalue)
				return NULL;
			memcpy(blob->textvalue, value, size);
		}
	}
	else {
		tdsdump_log(TDS_DBG_FUNC, "setting parameter #%d to NULL\n", param_num);
		curcol->column_cur_size = -1;
	}

	return row;
}
示例#5
0
文件: read.c 项目: dparnell/freetds
/**
 * Fetch character data the wire.
 * Output is NOT null terminated.
 * If \a char_conv is not NULL, convert data accordingly.
 * \param tds         state information for the socket and the TDS protocol
 * \param row_buffer  destination buffer in current_row. Can't be NULL
 * \param wire_size   size to read from wire (in bytes)
 * \param curcol      column information
 * \return TDS_SUCCEED or TDS_FAIL (probably memory error on text data)
 * \todo put a TDSICONV structure in every TDSCOLUMN
 */
int
tds_get_char_data(TDSSOCKET * tds, char *row_buffer, size_t wire_size, TDSCOLUMN * curcol)
{
	size_t in_left;
	TDSBLOB *blob = NULL;
	char *dest = row_buffer;

	if (is_blob_type(curcol->column_type)) {
		blob = (TDSBLOB *) row_buffer;
		dest = blob->textvalue;
	}

	/* 
	 * dest is usually a column buffer, allocated when the column's metadata are processed 
	 * and reused for each row.  
	 * For blobs, dest is blob->textvalue, and can be reallocated or freed
	 * TODO: reallocate if blob and no space 
	 */
	 
	/* silly case, empty string */
	if (wire_size == 0) {
		curcol->column_cur_size = 0;
		if (blob)
			TDS_ZERO_FREE(blob->textvalue);
		return TDS_SUCCEED;
	}

	if (curcol->char_conv) {
		/*
		 * TODO The conversion should be selected from curcol and tds version
		 * TDS8/single -> use curcol collation
		 * TDS7/single -> use server single byte
		 * TDS7+/unicode -> use server (always unicode)
		 * TDS5/4.2 -> use server 
		 * TDS5/UTF-8 -> use server
		 * TDS5/UTF-16 -> use UTF-16
		 */
		in_left = blob ? curcol->column_cur_size : curcol->column_size;
		curcol->column_cur_size = read_and_convert(tds, curcol->char_conv, &wire_size, &dest, &in_left);
		if (wire_size > 0) {
			tdsdump_log(TDS_DBG_NETWORK, "error: tds_get_char_data: discarded %u on wire while reading %d into client. \n", 
							 (unsigned int) wire_size, curcol->column_cur_size);
			return TDS_FAIL;
		}
	} else {
		curcol->column_cur_size = wire_size;
		if (tds_get_n(tds, dest, wire_size) == NULL) {
			tdsdump_log(TDS_DBG_NETWORK, "error: tds_get_char_data: failed to read %u from wire. \n",
				    (unsigned int) wire_size);
			return TDS_FAIL;
		}
	}
	return TDS_SUCCEED;
}
示例#6
0
static int 
do_for_all_cb
  (do_for_all_cb_state *s, 
   harg                *h,
   hargkey_t         *key, 
   unsigned           len)
{
  return (s->cb_fn) 
    (s->state, 
     is_blob_type (h->type) ?h->d.d.data :h->d.d.ptr [0],
     h->type, h->size, key);
}
示例#7
0
void* TdsResultSet::GetResultBlob(int nField, wxMemoryBuffer& Buffer)
{
  TDSCOLUMN *curcol = m_pDatabase->current_results->columns[nField-1];
  TDS_CHAR *src = (TDS_CHAR *) curcol->column_data;

  if (curcol->column_cur_size < 0)
    return NULL;

  if (is_blob_type(curcol->column_type))
  {
    TDSBLOB *blob = (TDSBLOB*) src;

    src = blob->textvalue;
  }
  else
  {
    //fprintf(stderr, "Not a blob!!!\n");
    return NULL;
  }

  int nLength = curcol->column_cur_size;
  //fprintf(stderr, "Blob size = %d\n", nLength);
  void* pBuffer = Buffer.GetWriteBuf(nLength);
  memcpy(pBuffer, src, nLength);
  
  return Buffer.GetData();

/*
  CONV_RESULT cr;
  int conv_type = tds_get_conversion_type(curcol->column_type, curcol->column_size);
  if (tds_convert(test_context, conv_type, src, curcol->column_cur_size, SYBVARCHAR, &cr) < 0)
  {
    //fprintf(stderr, "Error converting\n");
    free(cr.c);
    return NULL;
  }
  else
  {
    if (strcmp(data[i_row].result, cr.c) != 0)
    {
      //fprintf(stderr, "Failed! Is \n%s\nShould be\n%s\n", cr.c, data[i_row].result);
      free(cr.c);
      return NULL;
    }
    free(cr.c);
  }

  return Buffer.GetData();
*/
}
示例#8
0
void * /* same as above, but with type check */
harg_get_valuet
  (harglst      *a,
   hargkey_t  *key,
   hargtype_t type)
{
  harg *r ;
  
  if ((r = get_harg_entry (a, key, klen_by_type (type))) == 0)
    return 0;

  /* check for strict type checking */
  if (falsify_given_type (type, r->type)) {
    errno = EPERM ;
    return 0;
  }
  return is_blob_type (r->type) ? r->d.d.data : r->d.d.ptr [0] ;
}
示例#9
0
void
odbc_set_return_params(struct _hstmt *stmt)
{
	TDSSOCKET *tds = stmt->dbc->tds_socket;
	TDSPARAMINFO *info = tds->curr_resinfo;
	TDSCONTEXT *context = stmt->dbc->env->tds_ctx;

	int i_begin = stmt->prepared_query_is_func ? 1 : 0;
	int i;
	int nparam = i_begin;

	/* I don't understand why but this happen -- freddy77 */
	/* TODO check why, put an assert ? */
	if (!info)
		return;

	for (i = 0; i < info->num_cols; ++i) {
		struct _drecord *drec_apd, *drec_ipd;
		TDSCOLINFO *colinfo = info->columns[i];
		TDS_CHAR *src;
		int srclen;
		SQLINTEGER len;
		int c_type;

		/* find next output parameter */
		for (;;) {
			drec_apd = NULL;
			/* TODO best way to stop */
			if (nparam >= stmt->apd->header.sql_desc_count || nparam >= stmt->ipd->header.sql_desc_count)
				return;
			drec_apd = &stmt->apd->records[nparam];
			drec_ipd = &stmt->ipd->records[nparam];
			if (stmt->ipd->records[nparam++].sql_desc_parameter_type != SQL_PARAM_INPUT)
				break;
		}

		/* null parameter ? */
		if (tds_get_null(info->current_row, i)) {
			/* FIXME error if NULL */
			if (drec_apd->sql_desc_indicator_ptr)
				*drec_apd->sql_desc_indicator_ptr = SQL_NULL_DATA;
			continue;
		}

		src = (TDS_CHAR *) & info->current_row[colinfo->column_offset];
		if (is_blob_type(colinfo->column_type))
			src = ((TDSBLOBINFO *) src)->textvalue;
		srclen = colinfo->column_cur_size;
		c_type = drec_apd->sql_desc_concise_type;
		if (c_type == SQL_C_DEFAULT)
			c_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type);
		len = convert_tds2sql(context, tds_get_conversion_type(colinfo->column_type, colinfo->column_size), src, srclen,
				      c_type, drec_apd->sql_desc_data_ptr, drec_apd->sql_desc_octet_length);
		/* TODO error handling */
		if (len < 0)
			return /* SQL_ERROR */ ;
		if (drec_apd->sql_desc_indicator_ptr)
			*drec_apd->sql_desc_indicator_ptr = 0;
		*drec_apd->sql_desc_octet_length_ptr = len;
	}
}
示例#10
0
int
harg_renamet
  (harglst       *a,
   hargkey_t   *key,
   hargtype_t  type,
   hargkey_t  *nkey,
   hargtype_t ntype)
{
  harg **S, **R, *r ;
  int same_keys, klen = klen_by_type (type);

  /* sanity check */
  if (a == 0) {
    errno = EINVAL; 
    return -1; 
  }


    R = (harg**)find_hlst (a->x, key, klen);


  if ((r = *R) == 0) { /* zombie, should not happen, anyway */
    delete_hlst (a->x, key, klen);
    errno = ENOENT ;
    return -1;
  }
  /* check for a specific source type */
  if (falsify_given_type (type, r->type)) {
    errno = EPERM ;
    return -1;
  }
  same_keys = 
    nkey == 0 || 
    (is_ptrkey_type  (type) && 
     is_ptrkey_type (ntype) &&
     memcmp (key, nkey, sizeof (void*)) == 0) ||
    (is_ptrkey_type  (type) == 0 && 
     is_ptrkey_type (ntype) == 0 &&
     strcmp (key, nkey) == 0)
    ? 1 
    : 0 
    ;
  if (r->type == ntype && same_keys)
    return 0 ; /* nothing to do */

  /* check target type groups */
  if (is_blob_type   (ntype) &&   is_blob_type (r->type) ||
      is_scalar_type (ntype) && is_scalar_type (r->type) ||
      is_specific_type (ntype) == 0) {
    if (same_keys == 0) {
      /* make new index */
      if ((S = (harg**)make_hlst (a->x, nkey, klen_by_type (ntype))) == 0)
	return -1;
      *S = *R;
      *R = 0;
      delete_hlst (a->x, key, klen);
    }
    if (is_specific_type (ntype))
      r->type = ntype ;
    return 0;
  }
  errno = EPERM;  /* not permitted */
  return -1 ;
}
示例#11
0
hargkey_t*
harg_addt
  (harglst      *a,
   hargkey_t  *key,
   hargtype_t type,
   int   overwrite,
   unsigned   size,
   void     *value)
{
  harg **R, *r ;

  /* depending on the key type get its length */
  int klen = klen_by_type (type);;

  /* sanity check */
  if (a == 0 || key == 0 ||
      size == 0 && ((value == 0) && is_blob_type (type) ||
		    verify_simple_type (type, HARG_BLOB))) {
    errno = EINVAL; 
    return 0;
  }

  if (verify_simple_type (type, HARG_STRING)) {
    if (size == 0) /* need a terminating '\0' */
      size = strlen (value) + 1 ;
    else
      size ++ ;
  }


    R = (harg**)find_hlst (a->x, key, klen);

  
  if (R != 0) {
    r = *R ;
    /* record exists, do we need to overwrite ? */
    if (!overwrite && type == r->type)
      return query_key_hlst ((void**)R);
    /* reuse the data block if the sizes did not change */
    if (r->size == size) {
      r->type = type ;
      if (type == HARG_STRING || type == HARG_BLOB) {
	if (size)
	  memcpy (r->d.d.data, value, size);
      } else {
	r->d.d.ptr [0] = value;
      }
      return query_key_hlst ((void**)R);
    }
    /* sizes have changed - reallocate but keep ID */
    *R = create_harg (type, value, size);
    XFREE (r);
    return query_key_hlst ((void**)R);
  }

  /* no such value - create anew */
  if ((R = (harg**)make_hlst (a->x, key, klen)) != 0) {
    *R = create_harg (type, value, size);
    return query_key_hlst ((void**)R);
  }
  /* cannot happen */

 
  return 0; 
}
示例#12
0
void
tds_check_column_extra(const TDSCOLUMN * column)
{
	int size;
	TDSCONNECTION conn;
	int varint_ok;
	int column_varint_size;

	assert(column);
	column_varint_size = column->column_varint_size;

	/* 8 is for varchar(max) or similar */
	assert(column_varint_size == 8 || (column_varint_size <= 5 && column_varint_size != 3));

	assert(column->column_scale <= column->column_prec);
	assert(column->column_prec <= MAXPRECISION);

	/* I don't like this that much... freddy77 */
	if (column->column_type == 0)
		return;
	assert(column->funcs);
	assert(column->column_type > 0);

	/* check type and server type same or SQLNCHAR -> SQLCHAR */
#define SPECIAL(ttype, server_type, varint) \
	if (column->column_type == ttype && column->on_server.column_type == server_type && column_varint_size == varint) {} else
	SPECIAL(SYBTEXT, XSYBVARCHAR, 8)
	SPECIAL(SYBTEXT, XSYBNVARCHAR, 8)
	SPECIAL(SYBIMAGE, XSYBVARBINARY, 8)
	assert(tds_get_cardinal_type(column->on_server.column_type, column->column_usertype) == column->column_type
		|| (tds_get_conversion_type(column->on_server.column_type, column->column_size) == column->column_type
		&& column_varint_size == 1 && is_fixed_type(column->column_type)));

	varint_ok = 0;
	if (column_varint_size == 8) {
		assert(column->on_server.column_type == XSYBVARCHAR || column->on_server.column_type == XSYBVARBINARY || column->on_server.column_type == XSYBNVARCHAR || column->on_server.column_type == SYBMSXML || column->on_server.column_type == SYBMSUDT);
		varint_ok = 1;
	} else if (is_blob_type(column->column_type)) {
		assert(column_varint_size >= 4);
	} else if (column->column_type == SYBVARIANT) {
		assert(column_varint_size == 4);
	}
	conn.tds_version = 0x500;
	varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
	conn.tds_version = 0x700;
	varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
	assert(varint_ok);

	/* check current size <= size */
	if (is_numeric_type(column->column_type)) {
		/* I don't like that much this difference between numeric and not numeric - freddy77 */
		/* TODO what should be the size ?? */
		assert(column->column_prec >= 1 && column->column_prec <= MAXPRECISION);
		assert(column->column_scale <= column->column_prec);
/*		assert(column->column_cur_size == tds_numeric_bytes_per_prec[column->column_prec] + 2 || column->column_cur_size == -1); */
	} else {
		assert(column->column_cur_size <= column->column_size);
	}

	/* check size of fixed type correct */
	size = tds_get_size_by_type(column->column_type);
	assert(size != 0 || column->column_type == SYBVOID);
	if (size >= 0 && column->column_type != SYBBITN) {
		/* check macro */
		assert(is_fixed_type(column->column_type));
		/* check current size */
		if (column->column_type != SYBMSDATE)
			assert(size == column->column_size);
		/* check cases where server need nullable types */
		if (column->column_type != column->on_server.column_type && (column->column_type != SYBINT8 || column->on_server.column_type != SYB5INT8)) {
			assert(!is_fixed_type(column->on_server.column_type));
			assert(column_varint_size == 1);
			assert(column->column_size == column->column_cur_size || column->column_cur_size == -1);
		} else {
			assert(column_varint_size == 0
				|| (column->column_type == SYBUNIQUE && column_varint_size == 1)
				|| (column->column_type == SYBMSDATE  && column_varint_size == 1));
			assert(column->column_size == column->column_cur_size
				|| (column->column_type == SYBUNIQUE && column->column_cur_size == -1)
				|| (column->column_type == SYBMSDATE  && column->column_cur_size == -1));
		}
		assert(column->column_size == column->on_server.column_size);
	} else {
		assert(!is_fixed_type(column->column_type));
		assert(is_char_type(column->column_type) || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
		assert(column_varint_size != 0);
	}

	/* check size of nullable types (ie intN) it's supported */
	if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
		/* check macro */
		assert(is_nullable_type(column->column_type));
		/* check that size it's correct for this type of nullable */
		assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
		/* check current size */
		assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
		/* check same type and size on server */
		assert(column->column_type == column->on_server.column_type);
		assert(column->column_size == column->on_server.column_size);
	}
}
示例#13
0
文件: bulk.c 项目: DmitrySigaev/ncbi
/**
 * Send one row of data to server
 * \tds
 * \param bcpinfo BCP information
 * \param get_col_data function to call to retrieve data to be sent
 * \param ignored function to call if we try to send NULL if not allowed (not used)
 * \param offset passed to get_col_data and null_error to specify the row to get
 * \return TDS_SUCCESS or TDS_FAIL.
 */
TDSRET
tds_bcp_send_record(TDSSOCKET *tds, TDSBCPINFO *bcpinfo, tds_bcp_get_col_data get_col_data, tds_bcp_null_error null_error, int offset)
{
	TDSCOLUMN  *bindcol;
    int i, start_col = bcpinfo->next_col;
	TDSRET rc;

    tdsdump_log(TDS_DBG_FUNC, "tds_bcp_send_bcp_record(%p, %p, %p, %p, %d)\n", tds, bcpinfo, get_col_data, null_error, offset);

	if (tds->out_flag != TDS_BULK || tds_set_state(tds, TDS_WRITING) != TDS_WRITING)
		return TDS_FAIL;

    if (start_col > 0) {
        bindcol = bcpinfo->bindinfo->columns[start_col - 1];
        *bindcol->column_lenbind
            = MIN((TDS_INT) bindcol->column_bindlen - bcpinfo->text_sent,
                  *bindcol->column_lenbind);
        tds_put_n(tds, bindcol->column_varaddr, *bindcol->column_lenbind);
        bcpinfo->text_sent += *bindcol->column_lenbind;
        if ((TDS_UINT) bcpinfo->text_sent < bindcol->column_bindlen) {
            return TDS_SUCCESS; /* That's all for now. */
        } else if (!IS_TDS7_PLUS(tds->conn)) {
            bcpinfo->blob_cols++;
        }
        bcpinfo->next_col  = 0;
        bcpinfo->text_sent = 0;
    }

	if (IS_TDS7_PLUS(tds->conn)) {

        if (start_col == 0) {
            tds_put_byte(tds, TDS_ROW_TOKEN);   /* 0xd1 */
        }
        for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) {
	
			TDS_INT save_size;
			unsigned char *save_data;
			TDSBLOB blob;
            int /* bool */ has_text = 0;

			bindcol = bcpinfo->bindinfo->columns[i];

			/*
			 * Don't send the (meta)data for timestamp columns or
			 * identity columns unless indentity_insert is enabled.
			 */

			if ((!bcpinfo->identity_insert_on && bindcol->column_identity) || 
                bindcol->column_timestamp ||
                !tds_bcp_is_bound(bcpinfo, bindcol)) {
				continue;
			}

			rc = get_col_data(bcpinfo, bindcol, offset);
            if (rc == TDS_FAIL) {
				tdsdump_log(TDS_DBG_INFO1, "get_col_data (column %d) failed\n", i + 1);
				goto cleanup;
            } else if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */
                has_text = 1;
			}
			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);

			save_size = bindcol->column_cur_size;
			save_data = bindcol->column_data;
			assert(bindcol->column_data == NULL);
			if (bindcol->bcp_column_data->is_null) {
                if ( !bindcol->column_nullable
                     &&  !is_nullable_type(bindcol->on_server.column_type) ) {
                    return TDS_FAIL;
                }
				bindcol->column_cur_size = -1;
            } else if (has_text) {
                bindcol->column_cur_size = bindcol->bcp_column_data->datalen;
			} else if (is_blob_col(bindcol)) {
				bindcol->column_cur_size = bindcol->bcp_column_data->datalen;
				memset(&blob, 0, sizeof(blob));
				blob.textvalue = (TDS_CHAR *) bindcol->bcp_column_data->data;
				bindcol->column_data = (unsigned char *) &blob;
			} else {
				bindcol->column_cur_size = bindcol->bcp_column_data->datalen;
				bindcol->column_data = bindcol->bcp_column_data->data;
			}
			rc = bindcol->funcs->put_data(tds, bindcol, 1);
			bindcol->column_cur_size = save_size;
			bindcol->column_data = save_data;

			if (TDS_FAILED(rc))
				goto cleanup;
            else if (has_text) {
                bcpinfo->next_col = i + 1;
                /* bcpinfo->text_sent = 0; */
                break;
            }
		}
	}  /* IS_TDS7_PLUS */
	else {
      if (start_col == 0) {
		int row_pos;
		int row_sz_pos;
		int var_cols_written = 0;
		TDS_INT	 old_record_size = bcpinfo->bindinfo->row_size;
		unsigned char *record = bcpinfo->bindinfo->current_row;

		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;

		rc = TDS_FAIL;
        if ((row_pos = tds_bcp_add_fixed_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos)) < 0)
			goto cleanup;

		row_sz_pos = row_pos;

		/* potential variable columns to write */

        if ((row_pos = tds_bcp_add_variable_columns(bcpinfo, get_col_data, null_error, offset, record, row_pos, &var_cols_written)) < 0)
			goto cleanup;


		if (var_cols_written) {
			TDS_PUT_UA2(&record[row_sz_pos], row_pos);
			record[0] = var_cols_written;
		}

		tdsdump_log(TDS_DBG_INFO1, "old_record_size = %d new size = %d \n", old_record_size, row_pos);

		tds_put_smallint(tds, row_pos);
		tds_put_n(tds, record, row_pos);

		/* row is done, now handle any text/image data */

        bcpinfo->blob_cols = 0;
      }

        for (i = start_col; i < bcpinfo->bindinfo->num_cols; i++) {
			bindcol = bcpinfo->bindinfo->columns[i];
			if (is_blob_type(bindcol->column_type)) {
                /* Elide trailing NULLs */
                if (bindcol->bcp_column_data->is_null) {
                    int j;
                    for (j = i + 1;  j < bcpinfo->bindinfo->num_cols;  ++j) {
                        TDSCOLUMN *bindcol2 = bcpinfo->bindinfo->columns[j];
                        if (is_blob_type(bindcol2->column_type)
                            &&  !bindcol2->bcp_column_data->is_null) {
                            break;
                        }
                    }
                    if (j == bcpinfo->bindinfo->num_cols) {
                        i = j;
                        break;
                    }
                }

				rc = get_col_data(bcpinfo, bindcol, offset);
                if (rc == TDS_FAIL)
					goto cleanup;
				/* unknown but zero */
				tds_put_smallint(tds, 0);
                tds_put_byte(tds, (unsigned char) bindcol->column_type);
                tds_put_byte(tds, 0xff - bcpinfo->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);
                if (rc != TDS_SUCCESS) { /* CS_BLK_HAS_TEXT? */
                    bcpinfo->next_col = i + 1;
                    /* bcpinfo->text_sent = 0; */
                    break;
                }
				tds_put_n(tds, bindcol->bcp_column_data->data, bindcol->bcp_column_data->datalen);
                bcpinfo->blob_cols++;

			}
		}
	}

    if (i == bcpinfo->bindinfo->num_cols) {
        tds_set_state(tds, TDS_SENDING);
        bcpinfo->next_col = 0;
    }
	return TDS_SUCCESS;

cleanup:
	tds_set_state(tds, TDS_SENDING);
	return rc;
}
示例#14
0
static void
test0(const char *type, ...)
{
	char buf[512];
	CONV_RESULT cr;
	int rc;
	TDS_INT result_type;
	int done_flags;
	va_list ap;
	struct {
		const char *value;
		const char *result;
	} data[10];
	int num_data = 0, i_row;

	sprintf(buf, "CREATE TABLE #tmp(a %s)", type);
	exec_query(buf);

        va_start(ap, type);
	for (;;) {
		const char * value = va_arg(ap, const char *);
		const char * result;
		if (!value)
			break;
		result = va_arg(ap, const char *);
		if (!result)
			result = value;
		data[num_data].value = value;
		data[num_data].result = result;
		sprintf(buf, "INSERT INTO #tmp VALUES(CONVERT(%s,'%s'))", type, value);
		exec_query(buf);
		++num_data;
	}
        va_end(ap);

	assert(num_data > 0);

	/* execute it */
	rc = tds_submit_query(tds, "SELECT * FROM #tmp");
	if (rc != TDS_SUCCEED) {
		fprintf(stderr, "tds_submit_query() failed\n");
		exit(1);
	}

	if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() failed\n");
		exit(1);
	}

	if (result_type != TDS_ROWFMT_RESULT) {
		fprintf(stderr, "expected row fmt() failed\n");
		exit(1);
	}

	if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() failed\n");
		exit(1);
	}

	if (result_type != TDS_ROW_RESULT) {
		fprintf(stderr, "expected row result() failed\n");
		exit(1);
	}

	i_row = 0;
	while ((rc = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)) == TDS_SUCCEED && (result_type == TDS_ROW_RESULT || result_type == TDS_COMPUTE_RESULT)) {

		TDSCOLUMN *curcol = tds->current_results->columns[0];
		TDS_CHAR *src = (TDS_CHAR *) curcol->column_data;
		int conv_type = tds_get_conversion_type(curcol->column_type, curcol->column_size);

		assert(i_row < num_data);

		if (is_blob_type(curcol->column_type)) {
			TDSBLOB *blob = (TDSBLOB *) src;

			src = blob->textvalue;
		}

		if (tds_convert(test_context, conv_type, src, curcol->column_cur_size, SYBVARCHAR, &cr) < 0) {
			fprintf(stderr, "Error converting\n");
			g_result = 1;
		} else {
			if (strcmp(data[i_row].result, cr.c) != 0) {
				fprintf(stderr, "Failed! Is \n%s\nShould be\n%s\n", cr.c, data[i_row].result);
				g_result = 1;
			}
			free(cr.c);
		}
		++i_row;
	}

	if (rc != TDS_NO_MORE_RESULTS && rc != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() unexpected return\n");
		exit(1);
	}

	while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) {
		switch (result_type) {
		case TDS_NO_MORE_RESULTS:
			return;

		case TDS_DONE_RESULT:
		case TDS_DONEPROC_RESULT:
		case TDS_DONEINPROC_RESULT:
			if (!(done_flags & TDS_DONE_ERROR))
				break;

		default:
			fprintf(stderr, "tds_process_tokens() unexpected result_type\n");
			exit(1);
			break;
		}
	}

	exec_query("DROP TABLE #tmp");
}
示例#15
0
void
tds_check_column_extra(const TDSCOLUMN * column)
{
	int size;
	TDSCONNECTION conn;
	int varint_ok;
	int column_varint_size;

	assert(column);
	column_varint_size = column->column_varint_size;

	/* 8 is for varchar(max) or similar */
	assert(column_varint_size == 8 || (column_varint_size <= 5 && column_varint_size != 3));

	assert(column->column_scale <= column->column_prec);
	assert(column->column_prec <= MAXPRECISION);

	/* I don't like this that much... freddy77 */
	if (column->column_type == 0)
		return;
	assert(column->funcs);
	assert(column->column_type > 0);

	/* specific checks, if true fully checked */
	if (column->funcs->check(column))
		return;

	/* check type and server type same or SQLNCHAR -> SQLCHAR */
#define SPECIAL(ttype, server_type, varint) \
	if (column->column_type == ttype && column->on_server.column_type == server_type && column_varint_size == varint) {} else
	SPECIAL(SYBTEXT, XSYBVARCHAR, 8)
	SPECIAL(SYBTEXT, XSYBNVARCHAR, 8)
	SPECIAL(SYBIMAGE, XSYBVARBINARY, 8)
	assert(tds_get_cardinal_type(column->on_server.column_type, column->column_usertype) == column->column_type
		|| (tds_get_conversion_type(column->on_server.column_type, column->column_size) == column->column_type
		&& column_varint_size == 1 && is_fixed_type(column->column_type)));

	varint_ok = 0;
	if (column_varint_size == 8) {
		if (column->on_server.column_type == XSYBVARCHAR
		    || column->on_server.column_type == XSYBVARBINARY
		    || column->on_server.column_type == XSYBNVARCHAR)
			varint_ok = 1;
	} else if (is_blob_type(column->column_type)) {
		assert(column_varint_size >= 4);
	} else if (column->column_type == SYBVARIANT) {
		assert(column_varint_size == 4);
	}
	conn.tds_version = 0x500;
	varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
	conn.tds_version = 0x700;
	varint_ok = varint_ok || tds_get_varint_size(&conn, column->on_server.column_type) == column_varint_size;
	assert(varint_ok);

	assert(!is_numeric_type(column->column_type));
	assert(column->column_cur_size <= column->column_size);

	/* check size of fixed type correct */
	size = tds_get_size_by_type(column->column_type);
	assert(size != 0 || column->column_type == SYBVOID);
	/* these peculiar types are variable but have only a possible size */
	if (size >= 0 && (column->column_type != SYBBITN
		  && column->column_type != SYBDATEN && column->column_type != SYBTIMEN)) {
		/* check macro */
		assert(is_fixed_type(column->column_type));
		/* check current size */
		assert(size == column->column_size);
		/* check cases where server need nullable types */
		if (column->column_type != column->on_server.column_type && (column->column_type != SYBINT8 || column->on_server.column_type != SYB5INT8)) {
			assert(!is_fixed_type(column->on_server.column_type));
			assert(column_varint_size == 1);
			assert(column->column_size == column->column_cur_size || column->column_cur_size == -1);
		} else {
			assert(column_varint_size == 0
				|| (column->column_type == SYBUNIQUE && column_varint_size == 1));
			assert(column->column_size == column->column_cur_size
				|| (column->column_type == SYBUNIQUE && column->column_cur_size == -1));
		}
		assert(column->column_size == column->on_server.column_size);
	} else {
		assert(!is_fixed_type(column->column_type));
		assert(is_char_type(column->column_type) || (column->on_server.column_size == column->column_size || column->on_server.column_size == 0));
		assert(column_varint_size != 0);
	}

	/* check size of nullable types (ie intN) it's supported */
	if (tds_get_conversion_type(column->column_type, 4) != column->column_type) {
		/* check macro */
		assert(is_nullable_type(column->column_type));
		/* check that size it's correct for this type of nullable */
		assert(tds_get_conversion_type(column->column_type, column->column_size) != column->column_type);
		/* check current size */
		assert(column->column_size >= column->column_cur_size || column->column_cur_size == -1);
		/* check same type and size on server */
		assert(column->column_type == column->on_server.column_type);
		assert(column->column_size == column->on_server.column_size);
	}
}
示例#16
0
文件: utf8_2.c 项目: dparnell/freetds
static void
test(int n, int type)
{
	int rc;
	TDS_INT result_type;
	char buf[1024], tmp[1024];
	TDSCOLUMN *curcol;
	char *src;
	int done_flags;
	int i;
	char prefix[32], suffix[32];

	sprintf(test_name, "test %d len %d", type, n);

	/* do a select and check all results */
	prefix[0] = 0;
	suffix[0] = 0;
	tmp[0] = 0;
	switch (type) {
	case 0:
		strcpy(suffix, "C280C290");
		break;
	case 1:
		/* try two invalid in different part */
		strcpy(prefix, "C480C290");
		strcpy(suffix, "C480C290");
		break;
	}

	for (i = 0; i < n; ++i)
		sprintf(strchr(tmp, 0), "%02X", 0x30 + (i % 10));
	sprintf(buf, "select convert(varchar(255), 0x%s%s%s)", prefix, tmp, suffix);
	rc = tds_submit_query(tds, buf);
	if (rc != TDS_SUCCEED) {
		fprintf(stderr, "tds_submit_query() failed\n");
		exit(1);
	}

	if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() failed\n");
		exit(1);
	}

	if (result_type != TDS_ROWFMT_RESULT) {
		fprintf(stderr, "expected row fmt() failed\n");
		exit(1);
	}

	if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() failed\n");
		exit(1);
	}

	if (result_type != TDS_ROW_RESULT) {
		fprintf(stderr, "expected row result() failed\n");
		exit(1);
	}

	/* force tds to convert from utf8 to iso8859-1 (even on Sybase) */
	tds_srv_charset_changed(tds, "UTF-8");
	tds->current_results->columns[0]->char_conv = tds->char_convs[client2server_chardata];

	rc = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
	if (rc != TDS_SUCCEED) {
		fprintf(stderr, "tds_process_tokens() failed\n");
		exit(1);
	}

	curcol = tds->current_results->columns[0];
	src = (char*) curcol->column_data;

	if (is_blob_type(curcol->column_type)) {
		TDSBLOB *blob = (TDSBLOB *) src;

		src = blob->textvalue;
	}

	prefix[0] = 0;
	suffix[0] = 0;
	tmp[0] = 0;
	switch (type) {
	case 0:
		strcpy(suffix, "\x80\x90");
		break;
	case 1:
		/* try two invalid in different part */
		strcpy(prefix, "?\x90");
		strcpy(suffix, "?\x90");
		/* some platforms replace invalid sequence with a fixed char */
		if (invalid_char < 0)
			invalid_char = (unsigned char) src[0];
		prefix[0] = (char) invalid_char;
		suffix[0] = (char) invalid_char;
		break;
	}

	for (i = 0; i < n; ++i)
		sprintf(strchr(tmp, 0), "%c", "0123456789"[i % 10]);
	sprintf(buf, "%s%s%s", prefix, tmp, suffix);

	if (strlen(buf) != curcol->column_cur_size || strncmp(buf, src, curcol->column_cur_size) != 0) {
		int l = curcol->column_cur_size;

		if (l > 1000)
			l = 1000;
		strncpy(tmp, src, l);
		tmp[l] = 0;
		fprintf(stderr, "Wrong result in %s\n Got: '%s' len %d\n Expected: '%s' len %u\n", test_name, tmp,
			curcol->column_cur_size, buf, (unsigned int) strlen(buf));
		exit(1);
	}

	rc = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
	if (rc != TDS_SUCCEED || result_type == TDS_ROW_RESULT) {
		fprintf(stderr, "tds_process_tokens() unexpected return\n");
		exit(1);
	}

	while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCEED) {
		switch (result_type) {
		case TDS_NO_MORE_RESULTS:
			break;

		case TDS_DONE_RESULT:
		case TDS_DONEPROC_RESULT:
		case TDS_DONEINPROC_RESULT:
			if (!(done_flags & TDS_DONE_ERROR))
				break;

		default:
			fprintf(stderr, "tds_process_tokens() unexpected result_type\n");
			exit(1);
			break;
		}
	}
}