示例#1
0
static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
{
	pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
	pdo_dblib_db_handle *H = S->H;
	DBTYPEINFO* dbtypeinfo;

	if(colno >= stmt->column_count || colno < 0)  {
		return FAILURE;
	}

	array_init(return_value);

	dbtypeinfo = dbcoltypeinfo(H->link, colno+1);
	
	if(!dbtypeinfo) return FAILURE;
		
	add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
	add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
	add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
	add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
	add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
	add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
	add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));

	return 1;
}
示例#2
0
EDB_Type CDBL_Result::GetDataType(int n)
{
    switch (Check(dbcoltype(GetCmd(), n))) {
    case SYBBINARY:    return (Check(dbcollen(GetCmd(), n)) > 255) ? eDB_LongBinary :
                                                         eDB_VarBinary;
#if 0
    case SYBBITN:
#endif
    case SYBBIT:       return eDB_Bit;
    case SYBCHAR:      return (Check(dbcollen(GetCmd(), n)) > 255) ? eDB_LongChar :
                                                         eDB_VarChar;
    case SYBDATETIME:  return eDB_DateTime;
    case SYBDATETIME4: return eDB_SmallDateTime;
    case SYBINT1:      return eDB_TinyInt;
    case SYBINT2:      return eDB_SmallInt;
    case SYBINT4:      return eDB_Int;
    case SYBDECIMAL:
    case SYBNUMERIC:   break;
    case SYBFLT8:      return eDB_Double;
    case SYBREAL:      return eDB_Float;
    case SYBTEXT:      return eDB_Text;
    case SYBIMAGE:     return eDB_Image;
    default:           return eDB_UnsupportedType;
    }

    DBTYPEINFO* t = Check(dbcoltypeinfo(GetCmd(), n));
    return t->scale == 0 && t->precision < 20 ? eDB_BigInt : eDB_Numeric;
}
示例#3
0
static int
get_printable_column_size(DBPROCESS * dbproc, int col)
{
	int collen;

	collen = get_printable_size(dbcoltype(dbproc, col), dbcollen(dbproc, col));
	if (strlen(dbcolname(dbproc, col)) > collen) {
		collen = strlen(dbcolname(dbproc, col));
	}
	return collen;
}
示例#4
0
int syb_get_date_data (int no_des, int i)
{
  DBPROCESS * dbp = descriptor[no_des];
  
  data_type = dbcoltype (dbp, i);
  if (data_type == SYBDATETIME)
    {
      if (dbdatecrack (dbp, &date, (DBDATETIME *) dbdata (dbp, i)) == FAIL)
	{
	  return 0;
	}
    }
  return 1;
}
示例#5
0
int syb_get_integer_16_data (int no_des, int i)
{
  int result;
  DBPROCESS * dbp = descriptor[no_des];
  
  data_type = dbcoltype (dbp, i);
  if ( (data_type == SYBINT1) || (data_type == SYBINT2) || (data_type == SYBINT4) )
    {
      dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
		 SYBINT2, &result, sizeof (result));
      return (int) result;

    }
  return 0;
}
示例#6
0
int syb_get_boolean_data (int no_des, int i)
{
  int result;
  DBPROCESS * dbp = descriptor[no_des];
  
  data_type = dbcoltype (dbp,i);
  if (data_type == SYBBIT)
    {
      dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
		 SYBINT4, &result, sizeof (result));
      return (int) result;

    }
  return 0;
}
示例#7
0
float syb_get_real_data (int no_des, int i)
{
  float result_real;
  /*char result_real;*/
  DBPROCESS * dbp = descriptor[no_des];
  
  data_type = dbcoltype (dbp, i);
  if (data_type == SYBREAL)
	{
      dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
		 SYBREAL, &result_real, sizeof (result_real));
      return (float) result_real;
	}
  return 0.0;
}
示例#8
0
static const char *dbd_freetds_get_entry(const apr_dbd_row_t *row, int n)
{
    /* FIXME: support different data types */
    /* this fails - bind gets some vars but not others
    return (const char*)row->res->vars[n].data;
     */
    DBPROCESS* proc = row->res->proc;
    BYTE *ptr = dbdata(proc, n+1);
    int t = dbcoltype(proc, n+1);
    int l = dbcollen(proc, n+1);
    if (dbwillconvert(t, SYBCHAR)) {
      dbconvert(proc, t, ptr, l, SYBCHAR, (BYTE *)row->buf, -1);
      return (const char*)row->buf;
    }
    return (char*)ptr;
}
示例#9
0
char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, size_t *len)
{
	pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;

	RETCODE ret;
	char *id = NULL;

	/*
	 * Would use scope_identity() but it's not implemented on Sybase
	 */

	if (FAIL == dbcmd(H->link, "SELECT @@IDENTITY")) {
		return NULL;
	}

	if (FAIL == dbsqlexec(H->link)) {
		return NULL;
	}

	ret = dbresults(H->link);
	if (ret == FAIL || ret == NO_MORE_RESULTS) {
		dbcancel(H->link);
		return NULL;
	}

	ret = dbnextrow(H->link);

	if (ret == FAIL || ret == NO_MORE_ROWS) {
		dbcancel(H->link);
		return NULL;
	}

	if (dbdatlen(H->link, 1) == 0) {
		dbcancel(H->link);
		return NULL;
	}

	id = emalloc(32);
	*len = dbconvert(NULL, (dbcoltype(H->link, 1)) , (dbdata(H->link, 1)) , (dbdatlen(H->link, 1)), SQLCHAR, (BYTE *)id, (DBINT)-1);

	dbcancel(H->link);
	return id;
}
示例#10
0
static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zval *return_value)
{
	pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
	pdo_dblib_db_handle *H = S->H;
	DBTYPEINFO* dbtypeinfo;
	int coltype;

	if(colno >= stmt->column_count || colno < 0)  {
		return FAILURE;
	}

	array_init(return_value);

	dbtypeinfo = dbcoltypeinfo(H->link, colno+1);

	if(!dbtypeinfo) return FAILURE;

	coltype = dbcoltype(H->link, colno+1);

	add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
	add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
	add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
	add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
	add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype));
	add_assoc_long(return_value, "native_type_id", coltype);
	add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));

	switch (coltype) {
		case SQLBIT:
		case SQLINT1:
		case SQLINT2:
		case SQLINT4:
			add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
			break;
		default:
			add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
			break;
	}

	return 1;
}
示例#11
0
int syb_put_data (int no_des, int i, char *result)
{
	DBPROCESS * dbp = descriptor[no_des];
	data_type = dbcoltype (dbp, i);

	if (data_type == SYBBINARY)
	{ 
		/* Prefix the string by `Ox' for Hexa */
		result[0] = '0';
		result[1] = 'x';

		size = dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
			SYBCHAR, &(result[2]), max_size-2);
		if (size != -1)
		{
			size += 2;
		} 
	}
	else if (data_type == SYBLONGBINARY)
	{
		size = dbdatlen(dbp,i);
		memcpy(result, (char *)dbdata(dbp,i), size); 
		size = TXTLEN(result)*2;
	}
	else
	{
		size = dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
			SYBCHAR, result, max_size);
	}
	if (size == -1)
	{
		return 0;
	}
	else
	{
		return size;
	}
}
示例#12
0
double syb_get_float_data (int no_des, int i)
{
  double result;
  float result_real;
  
  DBPROCESS * dbp = descriptor[no_des];
  
  data_type = dbcoltype (dbp, i);
  if ( (data_type == SYBFLT8) || (data_type == SYBMONEY) )
    {
      dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
		 SYBFLT8, &result, sizeof (result));
      return result;

    }
  else if (data_type == SYBREAL)
	{
      dbconvert (dbp, data_type, dbdata (dbp, i), dbdatlen (dbp, i),
		 SYBREAL, &result_real, sizeof (result_real));
	  return result_real;
	}
  return 0.0;
}
示例#13
0
文件: rpc.c 项目: joshuahlang/freetds
static int 
colwidth( DBPROCESS * dbproc, int icol ) 
{
	int width = dbwillconvert(dbcoltype(dbproc, icol), SYBCHAR);
	return 255 == width? dbcollen(dbproc, icol) : width;
}
示例#14
0
int /* return count of SQL text rows */
print_results(DBPROCESS *dbproc) 
{
	static const char empty_string[] = "";
	struct METADATA *metadata = NULL;
	struct DATA { char *buffer; int status; } *data = NULL;
	
	RETCODE erc;
	int row_code;
	int c, ret;
	int iresultset;
	int nrows=0, ncols=0, ncomputeids;
	
	/* 
	 * Set up each result set with dbresults()
	 */
	for (iresultset=1; (erc = dbresults(dbproc)) != NO_MORE_RESULTS; iresultset++) {
		if (erc == FAIL) {
			fprintf(stderr, "%s:%d: dbresults(), result set %d failed\n", options.appname, __LINE__, iresultset);
			return -1;
		}

		if (SUCCEED != dbrows(dbproc)) {
			return 0;
		}

		/* Free prior allocations, if any. */
		for (c=0; c < ncols; c++) {
			free(metadata[c].format_string);
			free(data[c].buffer);
		}
		free(metadata);
		metadata = NULL;
		free(data);
		data = NULL;
		ncols = 0;
		
		/* 
		 * Allocate memory for metadata and bound columns 
		 */
		ncols = dbnumcols(dbproc);	

		metadata = (struct METADATA*) calloc(ncols, sizeof(struct METADATA));
		assert(metadata);

		data = (struct DATA*) calloc(ncols, sizeof(struct DATA));
		assert(data);
		
		/* The hard-coded queries don't generate compute rows. */
		ncomputeids = dbnumcompute(dbproc);
		assert(0 == ncomputeids);

		/* 
		 * For each column, get its name, type, and size. 
		 * Allocate a buffer to hold the data, and bind the buffer to the column.
		 * "bind" here means to give db-lib the address of the buffer we want filled as each row is fetched.
		 */

		for (c=0; c < ncols; c++) {
			int width;
			/* Get and print the metadata.  Optional: get only what you need. */
			char *name = dbcolname(dbproc, c+1);
			metadata[c].name = (name)? name : (char*) empty_string;

			name = dbcolsource(dbproc, c+1);
			metadata[c].source = (name)? name : (char*) empty_string;

			metadata[c].type = dbcoltype(dbproc, c+1);
			metadata[c].size = dbcollen(dbproc, c+1);
			assert(metadata[c].size != -1); /* -1 means indicates an out-of-range request*/

#if 0
			fprintf(stderr, "%6d  %30s  %30s  %15s  %6d  %6d  \n", 
				c+1, metadata[c].name, metadata[c].source, dbprtype(metadata[c].type), 
				metadata[c].size,  dbvarylen(dbproc, c+1));
#endif 
			/* 
			 * Build the column header format string, based on the column width. 
			 * This is just one solution to the question, "How wide should my columns be when I print them out?"
			 */
			width = get_printable_size(metadata[c].type, metadata[c].size);
			if (width < strlen(metadata[c].name))
				width = strlen(metadata[c].name);
				
			ret = set_format_string(&metadata[c], (c+1 < ncols)? "  " : "\n");
			if (ret <= 0) {
				fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);
				return -1;
			}

			/* 
			 * Bind the column to our variable.
			 * We bind everything to strings, because we want db-lib to convert everything to strings for us.
			 * If you're performing calculations on the data in your application, you'd bind the numeric data
			 * to C integers and floats, etc. instead. 
			 * 
			 * It is not necessary to bind to every column returned by the query.  
			 * Data in unbound columns are simply never copied to the user's buffers and are thus 
			 * inaccesible to the application.  
			 */

			data[c].buffer = calloc(1, metadata[c].size);
			assert(data[c].buffer);

			erc = dbbind(dbproc, c+1, STRINGBIND, -1, (BYTE *) data[c].buffer);
			if (erc == FAIL) {
				fprintf(stderr, "%s:%d: dbbind(), column %d failed\n", options.appname, __LINE__, c+1);
				return -1;
			}

			erc = dbnullbind(dbproc, c+1, &data[c].status);
			if (erc == FAIL) {
				fprintf(stderr, "%s:%d: dbnullbind(), column %d failed\n", options.appname, __LINE__, c+1);
				return -1;
			}
		}

		/* 
		 * Print the data to stdout.  
		 */
		for (;(row_code = dbnextrow(dbproc)) != NO_MORE_ROWS; nrows++) {
			switch (row_code) {
			case REG_ROW:
				for (c=0; c < ncols; c++) {
					switch (data[c].status) { /* handle nulls */
					case -1: 	/* is null */
						fprintf(stderr, "defncopy: error: unexpected NULL row in SQL text\n");
						break;
					case 0:	/* OK */
					default:	/* >1 is datlen when buffer is too small */
						fprintf(stdout, "%s", data[c].buffer);
						break;
					}
				}
				break;
				
			case BUF_FULL:
			default:
				fprintf(stderr, "defncopy: error: expected REG_ROW (%d), got %d instead\n", REG_ROW, row_code);
				assert(row_code == REG_ROW);
				break;
			} /* row_code */

		} /* wend dbnextrow */
		fprintf(stdout, "\n");

	} /* wend dbresults */
	return nrows;
}
示例#15
0
文件: bcp.c 项目: DavidRueter/freetds
int
main(int argc, char **argv)
{
	LOGINREC *login;
	DBPROCESS *dbproc;
	int i, rows_sent=0;
	int failed = 0;
	const char *s;
	const char *table_name = "all_types_bcp_unittest";

	set_malloc_options();

	read_login_info(argc, argv);

	fprintf(stdout, "Starting %s\n", argv[0]);

	dbinit();

	dberrhandle(syb_err_handler);
	dbmsghandle(syb_msg_handler);

	fprintf(stdout, "About to logon\n");

	login = dblogin();
	DBSETLPWD(login, PASSWORD);
	DBSETLUSER(login, USER);
	DBSETLAPP(login, "bcp.c unit test");
	BCP_SETL(login, 1);

	fprintf(stdout, "About to open %s.%s\n", SERVER, DATABASE);

	dbproc = dbopen(login, SERVER);
	if (strlen(DATABASE))
		dbuse(dbproc, DATABASE);
	dbloginfree(login);

	if (init(dbproc, table_name))
		exit(1);

	/* set up and send the bcp */
	sprintf(cmd, "%s..%s", DATABASE, table_name);
	fprintf(stdout, "preparing to insert into %s ... ", cmd);
	if (bcp_init(dbproc, cmd, NULL, NULL, DB_IN) == FAIL) {
		fprintf(stdout, "failed\n");
    		exit(1);
	}
	fprintf(stdout, "OK\n");

	test_bind(dbproc);

	fprintf(stdout, "Sending same row 10 times... \n");
	for (i=0; i<10; i++) {
		if (bcp_sendrow(dbproc) == FAIL) {
			fprintf(stdout, "send failed\n");
		        exit(1);
		}
	}
	
	fprintf(stdout, "Sending 5 more rows ... \n");
	for (i=15; i <= 27; i++) {
		int type = dbcoltype(dbproc, i);
		int len = (type == SYBCHAR || type == SYBVARCHAR)? dbcollen(dbproc, i) : -1;
		if (bcp_collen(dbproc, len, i) == FAIL) {
			fprintf(stdout, "bcp_collen failed for column %d\n", i);
		        exit(1);
		}
	}
	for (i=0; i<5; i++) {
		if (bcp_sendrow(dbproc) == FAIL) {
			fprintf(stdout, "send failed\n");
		        exit(1);
		}
	}
#if 1
	rows_sent = bcp_batch(dbproc);
	if (rows_sent == -1) {
		fprintf(stdout, "batch failed\n");
	        exit(1);
	}
#endif

	fprintf(stdout, "OK\n");

	/* end bcp.  */
	if ((rows_sent += bcp_done(dbproc)) == -1)
	    printf("Bulk copy unsuccessful.\n");
	else
	    printf("%d rows copied.\n", rows_sent);


	printf("done\n");


#if 1
	sql_cmd(dbproc);

	dbsqlexec(dbproc);
	while ((i=dbresults(dbproc)) == SUCCEED) {
		dbprhead(dbproc);
		dbprrow(dbproc);
		while ((i=dbnextrow(dbproc)) == REG_ROW) {
			dbprrow(dbproc);
		}
	}
#endif
	if ((s = getenv("BCP")) != NULL && 0 == strcmp(s, "nodrop")) {
		fprintf(stdout, "BCP=nodrop: '%s..%s' kept\n", DATABASE, table_name);
	} else {
		fprintf(stdout, "Dropping table %s\n", table_name);
		sql_cmd(dbproc);
		dbsqlexec(dbproc);
		while (dbresults(dbproc) != NO_MORE_RESULTS) {
			/* nop */
		}
	}
	dbexit();

	failed = 0;

	fprintf(stdout, "%s %s\n", __FILE__, (failed ? "failed!" : "OK"));
	return failed ? 1 : 0;
}
示例#16
0
int syb_get_col_type (int no_des, int i)
{
  return syb_conv_type (dbcoltype (descriptor[no_des], i));
}
示例#17
0
static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
	 zend_ulong *len, int *caller_frees)
{

	pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
	pdo_dblib_db_handle *H = S->H;

	int coltype;
	LPBYTE data;
	DBCHAR *tmp_data;
	DBINT data_len, tmp_data_len;
	zval *zv = NULL;

	coltype = dbcoltype(H->link, colno+1);
	data = dbdata(H->link, colno+1);
	data_len = dbdatlen(H->link, colno+1);

	if (data_len != 0 || data != NULL) {
		if (pdo_dblib_stmt_should_stringify_col(stmt, coltype) && dbwillconvert(coltype, SQLCHAR)) {
			pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
		}

		if (!zv) {
			switch (coltype) {
				case SQLCHAR:
				case SQLVARCHAR:
				case SQLTEXT: {
#if ilia_0
					while (data_len>0 && data[data_len-1] == ' ') { /* nuke trailing whitespace */
						data_len--;
					}
#endif
				}
				case SQLVARBINARY:
				case SQLBINARY:
				case SQLIMAGE: {
					zv = emalloc(sizeof(zval));
					ZVAL_STRINGL(zv, (DBCHAR *) data, data_len);

					break;
				}
#ifdef SQLMSDATETIME2
				case SQLMSDATETIME2:
#endif
				case SQLDATETIME:
				case SQLDATETIM4: {
					size_t dl;
					DBDATEREC di;
					DBDATEREC dt;

					dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1);
					dbdatecrack(H->link, &di, (DBDATETIME *) &dt);

					dl = spprintf(&tmp_data, 20, "%04d-%02d-%02d %02d:%02d:%02d",
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
							di.year,     di.month,       di.day,        di.hour,     di.minute,     di.second
#else
							di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
#endif
					);

					zv = emalloc(sizeof(zval));
					ZVAL_STRINGL(zv, tmp_data, dl);

					efree(tmp_data);

					break;
				}
				case SQLFLT4: {
					zv = emalloc(sizeof(zval));
					ZVAL_DOUBLE(zv, *(DBFLT4 *) data);

					break;
				}
				case SQLFLT8: {
					zv = emalloc(sizeof(zval));
					ZVAL_DOUBLE(zv, *(DBFLT8 *) data);

					break;
				}
				case SQLINT8: {
					zv = emalloc(sizeof(zval));
					ZVAL_LONG(zv, *(DBBIGINT *) data);

					break;
				}
				case SQLINT4: {
					zv = emalloc(sizeof(zval));
					ZVAL_LONG(zv, *(DBINT *) data);

					break;
				}
				case SQLINT2: {
					zv = emalloc(sizeof(zval));
					ZVAL_LONG(zv, *(DBSMALLINT *) data);

					break;
				}
				case SQLINT1:
				case SQLBIT: {
					zv = emalloc(sizeof(zval));
					ZVAL_LONG(zv, *(DBTINYINT *) data);

					break;
				}
				case SQLDECIMAL:
				case SQLNUMERIC:
				case SQLMONEY:
				case SQLMONEY4:
				case SQLMONEYN: {
					DBFLT8 float_value;
					dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE) &float_value, -1);

					zv = emalloc(sizeof(zval));
					ZVAL_DOUBLE(zv, float_value);

					break;
				}

				case SQLUNIQUE: {
					if (H->stringify_uniqueidentifier) {
						/* 36-char hex string representation */
						tmp_data_len = 36;
						tmp_data = safe_emalloc(tmp_data_len, sizeof(char), 1);
						data_len = dbconvert(NULL, SQLUNIQUE, data, data_len, SQLCHAR, (LPBYTE) tmp_data, tmp_data_len);
						php_strtoupper(tmp_data, data_len);
						zv = emalloc(sizeof(zval));
						ZVAL_STRINGL(zv, tmp_data, data_len);
						efree(tmp_data);
					} else {
						/* 16-byte binary representation */
						zv = emalloc(sizeof(zval));
						ZVAL_STRINGL(zv, (DBCHAR *) data, 16);
					}
					break;
				}

				default: {
					if (dbwillconvert(coltype, SQLCHAR)) {
						pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
					}

					break;
				}
			}
		}
	}

	if (zv != NULL) {
		*ptr = (char*)zv;
		*len = sizeof(zval);
	} else {
		*ptr = NULL;
		*len = 0;
	}

	*caller_frees = 1;

	return 1;
}
示例#18
0
文件: qsql_tds.cpp 项目: Suneal/qt
QVariant::Type qFieldType(QTDSResultPrivate* d, int i)
{
    QVariant::Type type = qDecodeTDSType(dbcoltype(d->dbproc, i+1));
    return type;
}
示例#19
0
文件: qsql_tds.cpp 项目: Suneal/qt
bool QTDSResult::reset (const QString& query)
{
    cleanup();
    if (!driver() || !driver()-> isOpen() || driver()->isOpenError())
        return false;
    setActive(false);
    setAt(QSql::BeforeFirstRow);
    if (dbcmd(d->dbproc, const_cast<char*>(query.toLocal8Bit().constData())) == FAIL) {
        setLastError(d->lastError);
        return false;
    }

    if (dbsqlexec(d->dbproc) == FAIL) {
        setLastError(d->lastError);
        dbfreebuf(d->dbproc);
        return false;
    }
    if (dbresults(d->dbproc) != SUCCEED) {
        setLastError(d->lastError);
        dbfreebuf(d->dbproc);
        return false;
    }

    setSelect((DBCMDROW(d->dbproc) == SUCCEED)); // decide whether or not we are dealing with a SELECT query
    int numCols = dbnumcols(d->dbproc);
    if (numCols > 0) {
        d->buffer.resize(numCols * 2);
        init(numCols);
    }
    for (int i = 0; i < numCols; ++i) {
        int dbType = dbcoltype(d->dbproc, i+1);
        QVariant::Type vType = qDecodeTDSType(dbType);
        QSqlField f(QString::fromAscii(dbcolname(d->dbproc, i+1)), vType);
        f.setSqlType(dbType);
        f.setLength(dbcollen(d->dbproc, i+1));
        d->rec.append(f);

        RETCODE ret = -1;
        void* p = 0;
        switch (vType) {
        case QVariant::Int:
            p = malloc(4);
            ret = dbbind(d->dbproc, i+1, INTBIND, (DBINT) 4, (unsigned char *)p);
            break;
        case QVariant::Double:
            // use string binding to prevent loss of precision
            p = malloc(50);
            ret = dbbind(d->dbproc, i+1, STRINGBIND, 50, (unsigned char *)p);
            break;
        case QVariant::String:
            p = malloc(dbcollen(d->dbproc, i+1) + 1);
            ret = dbbind(d->dbproc, i+1, STRINGBIND, DBINT(dbcollen(d->dbproc, i+1) + 1), (unsigned char *)p);
            break;
        case QVariant::DateTime:
            p = malloc(8);
            ret = dbbind(d->dbproc, i+1, DATETIMEBIND, (DBINT) 8, (unsigned char *)p);
            break;
        case QVariant::ByteArray:
            p = malloc(dbcollen(d->dbproc, i+1) + 1);
            ret = dbbind(d->dbproc, i+1, BINARYBIND, DBINT(dbcollen(d->dbproc, i+1) + 1), (unsigned char *)p);
            break;
        default: //don't bind the field since we do not support it
            qWarning("QTDSResult::reset: Unsupported type for field \"%s\"", dbcolname(d->dbproc, i+1));
            break;
        }
        if (ret == SUCCEED) {
            d->buffer[i * 2] = p;
            ret = dbnullbind(d->dbproc, i+1, (DBINT*)(&d->buffer[i * 2 + 1]));
        } else {
            d->buffer[i * 2] = 0;
            d->buffer[i * 2 + 1] = 0;
            free(p);
        }
        if ((ret != SUCCEED) && (ret != -1)) {
            setLastError(d->lastError);
            return false;
        }
    }

    setActive(true);
    return true;
}
示例#20
0
void
print_results(DBPROCESS *dbproc) 
{
	static const char empty_string[] = "";
	static const char dashes[] = "----------------------------------------------------------------" /* each line is 64 */
				     "----------------------------------------------------------------"
				     "----------------------------------------------------------------"
				     "----------------------------------------------------------------";
	
	struct METADATA *metadata = NULL, return_status;
	
	struct DATA { char *buffer; int status; } *data = NULL;
	
	struct METACOMP { int numalts; struct METADATA *meta; struct DATA *data; } **metacompute = NULL;
	
	RETCODE erc;
	int row_code;
	int i, c, ret;
	int iresultset;
	int ncomputeids = 0, ncols = 0;
	
	/* 
	 * Set up each result set with dbresults()
	 * This is more commonly implemented as a while() loop, but we're counting the result sets. 
	 */
	fprintf(options.verbose, "%s:%d: calling dbresults OK:\n", options.appname, __LINE__);
	for (iresultset=1; (erc = dbresults(dbproc)) != NO_MORE_RESULTS; iresultset++) {
		if (erc == FAIL) {
			fprintf(stderr, "%s:%d: dbresults(), result set %d failed\n", options.appname, __LINE__, iresultset);
			return;
		}
		
		fprintf(options.verbose, "Result set %d\n", iresultset);
		/* Free prior allocations, if any. */
		fprintf(options.verbose, "Freeing prior allocations\n", iresultset);
		for (c=0; c < ncols; c++) {
			free(metadata[c].format_string);
			free(data[c].buffer);
		}
		free(metadata);
		metadata = NULL;
		free(data);
		data = NULL;
		ncols = 0;
		
		for (i=0; i < ncomputeids; i++) {
			for (c=0; c < metacompute[i]->numalts; c++) {
				free(metacompute[i]->meta[c].name);
				free(metacompute[i]->meta[c].format_string);
			}
			free(metacompute[i]->meta);
			free(metacompute[i]->data);
			free(metacompute[i]);
		}
		free(metacompute);
		metacompute = NULL;
		ncomputeids = 0;
		
		/* 
		 * Allocate memory for metadata and bound columns 
		 */
		fprintf(options.verbose, "Allocating buffers\n", iresultset);
		ncols = dbnumcols(dbproc);	

		metadata = (struct METADATA*) calloc(ncols, sizeof(struct METADATA));
		assert(metadata);

		data = (struct DATA*) calloc(ncols, sizeof(struct DATA));
		assert(data);
		
		/* metadata is more complicated only because there may be several compute ids for each result set */
		fprintf(options.verbose, "Allocating compute buffers\n", iresultset);
		ncomputeids = dbnumcompute(dbproc);
		if (ncomputeids > 0) {
			metacompute = (struct METACOMP**) calloc(ncomputeids, sizeof(struct METACOMP*));
			assert(metacompute);
		}
		
		for (i=0; i < ncomputeids; i++) {
			metacompute[i] = (struct METACOMP*) calloc(ncomputeids, sizeof(struct METACOMP));
			assert(metacompute[i]);
			metacompute[i]->numalts = dbnumalts(dbproc, 1+i);
			fprintf(options.verbose, "%d columns found in computeid %d\n", metacompute[i]->numalts, 1+i);
			if (metacompute[i]->numalts > 0) {
				fprintf(options.verbose, "allocating column %d\n", 1+i);
				metacompute[i]->meta = (struct METADATA*) calloc(metacompute[i]->numalts, sizeof(struct METADATA));
				assert(metacompute[i]->meta);
				metacompute[i]->data = (struct     DATA*) calloc(metacompute[i]->numalts, sizeof(struct     DATA));
				assert(metacompute[i]->data);
			}
		}

		/* 
		 * For each column, get its name, type, and size. 
		 * Allocate a buffer to hold the data, and bind the buffer to the column.
		 * "bind" here means to give db-lib the address of the buffer we want filled as each row is fetched.
		 * TODO: Implement dbcoltypeinfo() for numeric/decimal datatypes.  
		 */

		fprintf(options.verbose, "Metadata\n", iresultset);
		fprintf(options.verbose, "%-6s  %-30s  %-30s  %-15s  %-6s  %-6s  \n", "col", "name", "source", "type", "size", "varys");
		fprintf(options.verbose, "%.6s  %.30s  %.30s  %.15s  %.6s  %.6s  \n", dashes, dashes, dashes, dashes, dashes, dashes);
		for (c=0; c < ncols; c++) {
			int width;
			/* Get and print the metadata.  Optional: get only what you need. */
			char *name = dbcolname(dbproc, c+1);
			metadata[c].name = (name)? name : empty_string;

			name = dbcolsource(dbproc, c+1);
			metadata[c].source = (name)? name : empty_string;

			metadata[c].type = dbcoltype(dbproc, c+1);
			metadata[c].size = dbcollen(dbproc, c+1);
			assert(metadata[c].size != -1); /* -1 means indicates an out-of-range request*/

			fprintf(options.verbose, "%6d  %30s  %30s  %15s  %6d  %6d  \n", 
				c+1, metadata[c].name, metadata[c].source, dbprtype(metadata[c].type), 
				metadata[c].size,  dbvarylen(dbproc, c+1));

			/* 
			 * Build the column header format string, based on the column width. 
			 * This is just one solution to the question, "How wide should my columns be when I print them out?"
			 */
			width = get_printable_size(metadata[c].type, metadata[c].size);
			if (width < strlen(metadata[c].name))
				width = strlen(metadata[c].name);
				
			ret = set_format_string(&metadata[c], (c+1 < ncols)? "  " : "\n");
			if (ret <= 0) {
				fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);
				return;
			}

			/* 
			 * Bind the column to our variable.
			 * We bind everything to strings, because we want db-lib to convert everything to strings for us.
			 * If you're performing calculations on the data in your application, you'd bind the numeric data
			 * to C integers and floats, etc. instead. 
			 * 
			 * It is not necessary to bind to every column returned by the query.  
			 * Data in unbound columns are simply never copied to the user's buffers and are thus 
			 * inaccesible to the application.  
			 */

			data[c].buffer = calloc(1, metadata[c].size);
			assert(data[c].buffer);

			erc = dbbind(dbproc, c+1, STRINGBIND, -1, (BYTE *) data[c].buffer);
			if (erc == FAIL) {
				fprintf(stderr, "%s:%d: dbbind(), column %d failed\n", options.appname, __LINE__, c+1);
				return;
			}

			erc = dbnullbind(dbproc, c+1, &data[c].status);
			if (erc == FAIL) {
				fprintf(stderr, "%s:%d: dbnullbind(), column %d failed\n", options.appname, __LINE__, c+1);
				return;
			}
		}
		
		/* 
		 * Get metadata and bind the columns for any compute rows.
		 */
		for (i=0; i < ncomputeids; i++) {
			fprintf(options.verbose, "For computeid %d:\n", 1+i);
			for (c=0; c < metacompute[i]->numalts; c++) {
				/* read metadata */
				struct METADATA *meta = &metacompute[i]->meta[c];
				int nbylist, ibylist;
				BYTE *bylist;
				char *colname, bynames[256] = "by (";
				int altcolid = dbaltcolid(dbproc, i+1, c+1);
				
				metacompute[i]->meta[c].type = dbalttype(dbproc, i+1, c+1);
				metacompute[i]->meta[c].size = dbaltlen(dbproc, i+1, c+1);

				/* 
				 * Jump through hoops to determine a useful name for the computed column 
				 * If the query says "compute count(c) by a,b", we get a "by list" indicating a & b.  
				 */
				bylist = dbbylist(dbproc, c+1, &nbylist);

				for (ibylist=0; ibylist < nbylist; ibylist++) {
					int ret;
					char *s = strchr(bynames, '\0'); 
					int remaining = bynames + sizeof(bynames) - s;
					assert(remaining > 0);
					ret = snprintf(s, remaining, "%s%s", dbcolname(dbproc, bylist[ibylist]), 
										(ibylist+1 < nbylist)? ", " : ")");
					if (ret <= 0) {
						fprintf(options.verbose, "Insufficient room to create name for column %d:\n", 1+c);
						break;
					}
				}
				
				if( altcolid == -1 ) {
					colname = "*";
				} else {
					colname = metadata[altcolid].name;
				}

				asprintf(&metacompute[i]->meta[c].name, "%s(%s)", dbprtype(dbaltop(dbproc, i+1, c+1)), colname);
				assert(metacompute[i]->meta[c].name);
					
				ret = set_format_string(meta, (c+1 < metacompute[i]->numalts)? "  " : "\n");
				if (ret <= 0) {
					fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}
				
				fprintf(options.verbose, "\tcolumn %d is %s, type %s, size %d %s\n", 
					c+1, metacompute[i]->meta[c].name, dbprtype(metacompute[i]->meta[c].type), metacompute[i]->meta[c].size, 
					(nbylist > 0)? bynames : "");
	
				/* allocate buffer */
				assert(metacompute[i]->data);
				metacompute[i]->data[c].buffer = calloc(1, metacompute[i]->meta[c].size);
				assert(metacompute[i]->data[c].buffer);
				
				/* bind */
				erc = dbaltbind(dbproc, i+1, c+1, STRINGBIND, -1, metacompute[i]->data[c].buffer);
				if (erc == FAIL) {
					fprintf(stderr, "%s:%d: dbaltbind(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}
			}
		}
		
		fprintf(options.verbose, "\n");
		fprintf(options.verbose, "Data\n", iresultset);

		/* Print the column headers to stderr to keep them separate from the data.  */
		for (c=0; c < ncols; c++) {
			char fmt[256] = "%-";
			
			/* left justify the names */
			strcat(fmt, &metadata[c].format_string[1]);
			fprintf(stderr, fmt, metadata[c].name);
		}

		/* Underline the column headers.  */
		for (c=0; c < ncols; c++) {
			fprintf(stderr, metadata[c].format_string, dashes);
		}

		/* 
		 * Print the data to stdout.  
		 */
		while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
			switch (row_code) {
			case REG_ROW:
				for (c=0; c < ncols; c++) {
					switch (data[c].status) { /* handle nulls */
					case -1: /* is null */
						/* TODO: FreeTDS 0.62 does not support dbsetnull() */
						fprintf(stdout, metadata[c].format_string, "NULL");
						break;
					case 0:
					/* case >1 is datlen when buffer is too small */
					default:
						fprintf(stdout, metadata[c].format_string, data[c].buffer);
						break;
					}
				}
				break;
				
			case BUF_FULL:
				assert(row_code != BUF_FULL);
				break;
				
			default: /* computeid */
				fprintf(options.verbose, "Data for computeid %d\n", row_code);
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					char fmt[256] = "%-";
					struct METADATA *meta = &metacompute[row_code-1]->meta[c];
					
					/* left justify the names */
					strcat(fmt, &meta->format_string[1]);
					fprintf(stderr, fmt, meta->name);
				}

				/* Underline the column headers.  */
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					fprintf(stderr, metacompute[row_code-1]->meta[c].format_string, dashes);
				}
					
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					struct METADATA *meta = &metacompute[row_code-1]->meta[c];
					struct     DATA *data = &metacompute[row_code-1]->data[c];
					
					switch (data->status) { /* handle nulls */
					case -1: /* is null */
						/* TODO: FreeTDS 0.62 does not support dbsetnull() */
						fprintf(stdout, meta->format_string, "NULL");
						break;
					case 0:
					/* case >1 is datlen when buffer is too small */
					default:
						fprintf(stdout, meta->format_string, data->buffer);
						break;
					}
				}
			}


		}

		/* Check return status */
		fprintf(options.verbose, "Retrieving return status... ");
		if (dbhasretstat(dbproc) == TRUE) {
			fprintf(stderr, "Procedure returned %d\n", dbretstatus(dbproc));
		} else {
			fprintf(options.verbose, "none\n");
		}
		
		/* 
		 * Get row count, if available.   
		 */
		if (DBCOUNT(dbproc) > -1)
			fprintf(stderr, "%d rows affected\n", DBCOUNT(dbproc));
			

		/* 
		 * Check return parameter values 
		 */
		fprintf(options.verbose, "Retrieving output parameters... ");
		if (dbnumrets(dbproc) > 0) {
			for (i = 1; i <= dbnumrets(dbproc); i++) {
				char parameter_string[1024];
				
				return_status.name = dbretname(dbproc, i);
				fprintf(stderr, "ret name %d is %s\n", i, return_status.name);
				
				return_status.type = dbrettype(dbproc, i);
				fprintf(options.verbose, "\n\tret type %d is %d", i, return_status.type);
				
				return_status.size = dbretlen(dbproc, i);
				fprintf(options.verbose, "\n\tret len %d is %d\n", i, return_status.size);
				
				dbconvert(dbproc, return_status.type, dbretdata(dbproc, i), return_status.size, 
					  SYBVARCHAR, (BYTE *) parameter_string, -1);
				fprintf(stderr, "ret data %d is %s\n", i, parameter_string);
			}
		} else {
			fprintf(options.verbose, "none\n");
		}
	} /* wend dbresults */
	fprintf(options.verbose, "%s:%d: dbresults() returned NO_MORE_RESULTS (%d):\n", options.appname, __LINE__, erc);
}
示例#21
0
static int
transfer_data(BCPPARAMDATA params, DBPROCESS * dbsrc, DBPROCESS * dbdest)
{
	char ls_command[256];
	int col;

	DBINT src_numcols = 0;

	DBINT src_datlen;

	typedef struct migcoldata
	{
		DBINT coltype;
		DBINT collen;
		DBINT nullind;
		DBCHAR *data;
	} MIGCOLDATA;

	MIGCOLDATA **srcdata;

	DBINT rows_read = 0;
	DBINT rows_sent = 0;
	DBINT rows_done = 0;
	DBINT ret;

	struct timeval start_time;
	struct timeval end_time;
	double elapsed_time;
	struct timeval batch_start;
	struct timeval batch_end;
	double elapsed_batch = 0.0;

	if (params.vflag) {
		printf("\nStarting copy...\n");
	}

	if (params.tflag) {

		sprintf(ls_command, "truncate table %s", params.ddbobject);

		if (dbcmd(dbdest, ls_command) == FAIL) {
			printf("dbcmd failed\n");
			return FALSE;
		}

		if (dbsqlexec(dbdest) == FAIL) {
			printf("dbsqlexec failed\n");
			return FALSE;
		}

		if (dbresults(dbdest) == FAIL) {
			printf("Error in dbresults\n");
			return FALSE;
		}
	}


	sprintf(ls_command, "select * from %s", params.sdbobject);

	if (dbcmd(dbsrc, ls_command) == FAIL) {
		printf("dbcmd failed\n");
		return FALSE;
	}

	if (dbsqlexec(dbsrc) == FAIL) {
		printf("dbsqlexec failed\n");
		return FALSE;
	}

	if (NO_MORE_RESULTS != dbresults(dbsrc));
	{
		if (0 == (src_numcols = dbnumcols(dbsrc))) {
			printf("Error in dbnumcols\n");
			return FALSE;
		}
	}



	if (bcp_init(dbdest, params.ddbobject, (char *) NULL, (char *) NULL, DB_IN) == FAIL) {
		printf("Error in bcp_init\n");
		return FALSE;
	}

	srcdata = (MIGCOLDATA **) malloc(sizeof(MIGCOLDATA *) * src_numcols);

	for (col = 0; col < src_numcols; col++) {

		srcdata[col] = (MIGCOLDATA *) malloc(sizeof(MIGCOLDATA));
		memset(srcdata[col], '\0', sizeof(MIGCOLDATA));
		srcdata[col]->coltype = dbcoltype(dbsrc, col + 1);
		srcdata[col]->collen = dbcollen(dbsrc, col + 1);

		switch (srcdata[col]->coltype) {
		case SYBBIT:
			srcdata[col]->data = malloc(sizeof(DBBIT));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, BITBIND, sizeof(DBBIT), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBBIT, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;
		case SYBINT1:
			srcdata[col]->data = malloc(sizeof(DBTINYINT));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, TINYBIND, sizeof(DBTINYINT), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBINT1, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBINT2:
			srcdata[col]->data = malloc(sizeof(DBSMALLINT));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, SMALLBIND, sizeof(DBSMALLINT), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBINT2, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBINT4:
			srcdata[col]->data = malloc(sizeof(DBINT));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, INTBIND, sizeof(DBINT), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBINT4, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBFLT8:
			srcdata[col]->data = malloc(sizeof(DBFLT8));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, FLT8BIND, sizeof(DBFLT8), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBFLT8, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBREAL:
			srcdata[col]->data = malloc(sizeof(DBREAL));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, REALBIND, sizeof(DBREAL), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBREAL, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBMONEY:
			srcdata[col]->data = malloc(sizeof(DBMONEY));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, MONEYBIND, sizeof(DBMONEY), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBMONEY, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBMONEY4:
			srcdata[col]->data = malloc(sizeof(DBMONEY4));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, SMALLMONEYBIND, sizeof(DBMONEY4), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBMONEY4, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBDATETIME:
			srcdata[col]->data = malloc(sizeof(DBDATETIME));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, DATETIMEBIND, sizeof(DBDATETIME), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBDATETIME, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBDATETIME4:
			srcdata[col]->data = malloc(sizeof(DBDATETIME4));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, SMALLDATETIMEBIND, sizeof(DBDATETIME), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBDATETIME4, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBNUMERIC:
			srcdata[col]->data = malloc(sizeof(DBNUMERIC));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, NUMERICBIND, sizeof(DBNUMERIC), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, sizeof(DBNUMERIC), NULL, 0, SYBNUMERIC, col + 1) ==
			    FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;

		case SYBDECIMAL:
			srcdata[col]->data = malloc(sizeof(DBDECIMAL));
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, DECIMALBIND, sizeof(DBDECIMAL), (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, sizeof(DBDECIMAL), NULL, 0, SYBDECIMAL, col + 1) ==
			    FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;
		case SYBTEXT:
		case SYBCHAR:
			srcdata[col]->data = malloc(srcdata[col]->collen + 1);
			if (srcdata[col]->data == (char *) NULL) {
				printf("allocation error\n");
				return FALSE;
			}
			dbbind(dbsrc, col + 1, NTBSTRINGBIND, srcdata[col]->collen + 1, (BYTE *) srcdata[col]->data);
			dbnullbind(dbsrc, col + 1, &(srcdata[col]->nullind));
			if (bcp_bind(dbdest, (BYTE *) srcdata[col]->data, 0, -1, NULL, 0, SYBCHAR, col + 1) == FAIL) {
				printf("bcp_bind error\n");
				return FALSE;
			}
			break;
		}
	}

	gettimeofday(&start_time, 0);

	while (dbnextrow(dbsrc) != NO_MORE_ROWS) {
		rows_read++;
		for (col = 0; col < src_numcols; col++) {
			switch (srcdata[col]->coltype) {
			case SYBBIT:
			case SYBINT1:
			case SYBINT2:
			case SYBINT4:
			case SYBFLT8:
			case SYBREAL:
			case SYBDATETIME:
			case SYBDATETIME4:
			case SYBMONEY:
			case SYBMONEY4:
				if (srcdata[col]->nullind == -1) {	/* NULL data retrieved from source */
					bcp_collen(dbdest, 0, col + 1);
				} else {
					bcp_collen(dbdest, -1, col + 1);
				}
				break;
			case SYBNUMERIC:
				if (srcdata[col]->nullind == -1) {	/* NULL data retrieved from source */
					bcp_collen(dbdest, 0, col + 1);
				} else {
					bcp_collen(dbdest, sizeof(DBNUMERIC), col + 1);
				}
				break;
			case SYBDECIMAL:
				if (srcdata[col]->nullind == -1) {	/* NULL data retrieved from source */
					bcp_collen(dbdest, 0, col + 1);
				} else {
					bcp_collen(dbdest, sizeof(DBDECIMAL), col + 1);
				}
				break;
			case SYBTEXT:
			case SYBCHAR:
				if (srcdata[col]->nullind == -1) {	/* NULL data retrieved from source */
					bcp_collen(dbdest, 0, col + 1);
				} else {

					/*
					 * if there is zero length data, then the
					 * input data MUST have been all blanks,
					 * trimmed down to nothing by the bind
					 * type of NTBSTRINGBIND.
					 * so find out the source data length and
					 * re-set the data accordingly...
					 */

					if (strlen(srcdata[col]->data) == 0) {
						src_datlen = dbdatlen(dbsrc, col + 1);
						memset(srcdata[col]->data, ' ', src_datlen);
						srcdata[col]->data[src_datlen] = '\0';
					}
					bcp_collen(dbdest, strlen(srcdata[col]->data), col + 1);
				}
				break;
			}
		}
		if (bcp_sendrow(dbdest) == FAIL) {
			fprintf(stderr, "bcp_sendrow failed.  \n");
			return FALSE;
		} else {
			rows_sent++;
			if (rows_sent == params.batchsize) {
				gettimeofday(&batch_start, 0);
				ret = bcp_batch(dbdest);
				gettimeofday(&batch_end, 0);
				elapsed_batch = elapsed_batch +
					((double) (batch_end.tv_sec - batch_start.tv_sec) +
					 ((double) (batch_end.tv_usec - batch_start.tv_usec) / 1000000.00)
					);
				if (ret == -1) {
					printf("bcp_batch error\n");
					return FALSE;
				} else {
					rows_done += ret;
					printf("%d rows successfully copied (total %d)\n", ret, rows_done);
					rows_sent = 0;
				}
			}
		}
	}

	if (rows_read) {
		gettimeofday(&batch_start, 0);
		ret = bcp_done(dbdest);
		gettimeofday(&batch_end, 0);
		elapsed_batch = elapsed_batch +
			((double) (batch_end.tv_sec - batch_start.tv_sec) +
			 ((double) (batch_end.tv_usec - batch_start.tv_usec) / 1000000.00)
			);
		if (ret == -1) {
			fprintf(stderr, "bcp_done failed.  \n");
			return FALSE;
		} else {
			rows_done += ret;
		}
	}

	gettimeofday(&end_time, 0);


	elapsed_time = (double) (end_time.tv_sec - start_time.tv_sec) +
		((double) (end_time.tv_usec - start_time.tv_usec) / 1000000.00);

	if (params.vflag) {
		printf("\n");
		printf("rows read            : %d\n", rows_read);
		printf("rows written         : %d\n", rows_done);
		printf("elapsed time (secs)  : %f\n", elapsed_time);
		printf("rows per second      : %f\n", rows_done / elapsed_time);
	}

	return TRUE;


}
示例#22
0
    static int onDataResponse(eio_req *req) {
      v8::HandleScope scope;
      data_callback_t *callbackData = (data_callback_t *) req->data;

      if(req->result == FAIL){
        Local<Value> argv[1];
        argv[0] = v8::Exception::Error(v8::String::New("An error occurred executing that statement"));
        callbackData->callback->Call(Context::GetCurrent()->Global(), 1, argv);
      }

      uint32_t rownum = 0;
      bool err = false;
      COL *columns, *pcol;
      int ncols = 0;
      v8::Local<v8::Array> results = v8::Array::New();

      while(dbresults(callbackData->dbconn) != NO_MORE_RESULTS){
        ncols = dbnumcols(callbackData->dbconn);
        columns = (COL *) calloc(ncols, sizeof(struct COL));
        for (pcol = columns; pcol - columns < ncols; pcol++) {
          int i = pcol - columns + 1;
          pcol->name = v8::String::New(dbcolname(callbackData->dbconn, i));
          pcol->type = dbcoltype(callbackData->dbconn, i);
          pcol->size = dbcollen(callbackData->dbconn, i);

          if (SYBCHAR != pcol->type) {      
            pcol->size = dbwillconvert(pcol->type, SYBCHAR);
          }
          //todo: work out if I'm leaking
          if((pcol->buffer = (void *) malloc(pcol->size + 1)) == NULL) {
            err = true;
            break;
          }
        }
        if(err){
          for (pcol = columns; pcol - columns < ncols; pcol++) {
            free(pcol->buffer);
            free(columns);
          }
          Local<Value> argv[1];
          argv[0] = v8::Exception::Error(v8::String::New("Could not allocate memory for columns"));
          callbackData->callback->Call(Context::GetCurrent()->Global(), 1, argv);
          return 0;
        }
        for (pcol = columns; pcol - columns < ncols; pcol++) {
          int i = pcol - columns + 1;
          int binding = NTBSTRINGBIND;
          // switch(pcol->type){
          //   case TINYBIND:
          //   case SMALLBIND:
          //   case INTBIND:
          //   case FLT8BIND:
          //   case REALBIND:
          //   case SMALLDATETIMEBIND:
          //   case MONEYBIND:
          //   case SMALLMONEYBIND:
          //   case BINARYBIND:
          //   case BITBIND:
          //   case NUMERICBIND:
          //   case DECIMALBIND:
          //   case BIGINTBIND:
          //     // all numbers in JS are doubles
          //     binding = REALBIND;
          //     break;
          // }
          if(dbbind(callbackData->dbconn, i, binding,  pcol->size + 1, (BYTE*)pcol->buffer) == FAIL){
            err = true;
          }else if(dbnullbind(callbackData->dbconn, i, &pcol->status) == FAIL){
            err = true;
          }
        }
        if(err){
          for (pcol = columns; pcol - columns < ncols; pcol++) {
            free(pcol->buffer);
            free(columns);
          }
          Local<Value> argv[1];
          argv[0] = v8::Exception::Error(v8::String::New("Could not allocate memory for columns"));
          callbackData->callback->Call(Context::GetCurrent()->Global(), 1, argv);
          return 0;
        }
        int row_code;

        while ((row_code = dbnextrow(callbackData->dbconn)) != NO_MORE_ROWS){ 
          if(row_code == REG_ROW) {
            v8::Local<v8::Object> tuple = v8::Object::New();
            for (pcol = columns; pcol - columns < ncols; pcol++) {
              if(pcol->status == -1){
                tuple->Set(pcol->name, v8::Null());
                continue;
              }
              switch(pcol->type){
                case SQLINTN:
                case SQLINT1:
                case SQLINT2:
                case SQLINT4:
                case SQLINT8:
                case SQLFLT8:
                case SQLDATETIME:
                case SQLDATETIM4:
                case SQLBIT:
                case SQLFLT4:
                case SQLNUMERIC:
                case SQLDECIMAL:
                case SQLFLTN:
                case SQLDATETIMN:
                case 36:
                case SQLCHAR:
                case SQLVARCHAR:
                case SQLTEXT:
                  tuple->Set(pcol->name, v8::String::New((char*) pcol->buffer));
                  break;
                // case SQLINTN:
                // case SQLINT1:
                // case SQLINT2:
                // case SQLINT4:
                // case SQLINT8:
                // case SQLFLT8:
                // case SQLDATETIME:
                // case SQLDATETIM4:
                // case SQLBIT:
                // case SQLFLT4:
                // case SQLNUMERIC:
                // case SQLDECIMAL:
                // case SQLFLTN:
                // case SQLDATETIMN:
                  // DBREAL val;
                  // memcpy(&val, pcol->buffer, pcol->size);
                  // tuple->Set(pcol->name, v8::Number::New((double)val));
                  break;
                case SQLIMAGE:
                case SQLMONEY4:
                case SQLMONEY:
                case SQLBINARY:
                case SQLVARBINARY:
                case SQLMONEYN:
                case SQLVOID:
                default:
                  printf("unsupported col type %d\n", pcol->type);
                  break;
              }
            }
            results->Set(rownum++, tuple);
          }
        }
        for (pcol = columns; pcol - columns < ncols; pcol++) {
          free(pcol->buffer);
        }
        free(columns);
      }

      v8::Local<v8::Value> argv[2] = { Local<Value>::New(Null()), results };
      callbackData->callback->Call(Context::GetCurrent()->Global(), 2, argv);

      callbackData->callback.Dispose();
      delete callbackData;


      return 0;
    }
示例#23
0
文件: t0013.c 项目: angcoch/freetds
static int
test(int argc, char **argv, int over4k)
{
	LOGINREC *login;
	int i;
	DBINT testint;
	FILE *fp;
	long result, isiz;
	char *blob, *rblob;
	DBBINARY *textPtr = NULL, *timeStamp = NULL;
	char objname[256];
	char rbuf[BLOB_BLOCK_SIZE];
	long numread;
	int data_ok;
	int numtowrite, numwritten;
	set_malloc_options();

	read_login_info(argc, argv);
	fprintf(stdout, "Starting %s\n", argv[0]);
	dbinit();

	dberrhandle(syb_err_handler);
	dbmsghandle(syb_msg_handler);

	fprintf(stdout, "About to logon\n");

	login = dblogin();
	DBSETLPWD(login, PASSWORD);
	DBSETLUSER(login, USER);
	DBSETLAPP(login, "t0013");

	fprintf(stdout, "About to open, PASSWORD: %s, USER: %s, SERVER: %s\n", "", "", "");	/* PASSWORD, USER, SERVER); */

	dbproc = dbopen(login, SERVER);
	dbprocw = dbopen(login, SERVER);
	if (strlen(DATABASE)) {
		dbuse(dbproc, DATABASE);
		dbuse(dbprocw, DATABASE);
	}
	dbloginfree(login);
	fprintf(stdout, "logged in\n");

	if (argc == 1) {
		argv = testargs;
		argc = 3;
	}
	if (argc < 3) {
		fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
		return 1;
	}

	if ((fp = fopen(argv[1], "rb")) == NULL) {
		fprintf(stderr, "Cannot open input file: %s\n", argv[1]);
		return 2;
	}
	fprintf(stdout, "Reading binary input file\n");

	fseek(fp, 0, SEEK_END);
	isiz = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	blob = malloc(isiz);
	assert(blob);
	result = fread((void *) blob, isiz, 1, fp);
	assert(result == 1);
	fclose(fp);

	drop_table();

	sql_cmd(dbproc);
	dbsqlexec(dbproc);
	while (dbresults(dbproc) != NO_MORE_RESULTS) {
		/* nop */
	}

	sql_cmd(dbproc);
	dbsqlexec(dbproc);
	while (dbresults(dbproc) != NO_MORE_RESULTS) {
		/* nop */
	}

	sql_cmd(dbproc);
	dbsqlexec(dbproc);
	if (dbresults(dbproc) != SUCCEED) {
		fprintf(stderr, "Error inserting blob\n");
		return 4;
	}

	for (i=0; (result = dbnextrow(dbproc)) != NO_MORE_ROWS; i++) {
		assert(REG_ROW == result);
		printf("fetching row %d\n", i+1);
		strcpy(objname, TABLE_NAME ".PigTure");
		textPtr = dbtxptr(dbproc, 1);
		timeStamp = dbtxtimestamp(dbproc, 1);
		break; /* can't proceed until no more rows */
	}
	assert(REG_ROW == result || 0 < i);

	if (!textPtr && !timeStamp && dbtds(dbproc) >= DBTDS_7_2) {
		printf("Protocol 7.2+ detected, test not supported\n");
		free(blob);
		dbclose(dbproc);
		dbproc = NULL;
		dbexit();
		exit(0);
	}

	if (!textPtr) {
		fprintf(stderr, "Error getting textPtr\n");
		exit(1);
	}

	/*
	 * Use #ifdef if you want to test dbmoretext mode (needed for 16-bit apps)
	 * Use #ifndef for big buffer version (32-bit)
	 */
	fprintf(stdout, "writing text ... ");
	if (over4k) {
		if (dbwritetext(dbprocw, objname, textPtr, DBTXPLEN, timeStamp, FALSE, isiz, (BYTE*) blob) != SUCCEED)
			return 5;
		fprintf(stdout, "done (in one shot)\n");
		for (; (result = dbnextrow(dbproc)) != NO_MORE_ROWS; i++) {
			assert(REG_ROW == result);
			printf("fetching row %d?\n", i+1);
		}
	} else {
		if (dbwritetext(dbprocw, objname, textPtr, DBTXPLEN, timeStamp, FALSE, isiz, NULL) != SUCCEED)
			return 15;
		fprintf(stdout, "done\n");

		fprintf(stdout, "dbsqlok\n");
		dbsqlok(dbprocw);
		fprintf(stdout, "dbresults\n");
		dbresults(dbprocw);

		numtowrite = 0;
		/* Send the update value in chunks. */
		for (numwritten = 0; numwritten < isiz; numwritten += numtowrite) {
			fprintf(stdout, "dbmoretext %d\n", 1 + numwritten);
			numtowrite = (isiz - numwritten);
			if (numtowrite > BLOB_BLOCK_SIZE)
				numtowrite = BLOB_BLOCK_SIZE;
			dbmoretext(dbprocw, (DBINT) numtowrite, (BYTE *) (blob + numwritten));
		}
		dbsqlok(dbprocw);
		while (dbresults(dbprocw) != NO_MORE_RESULTS){
			printf("suprise!\n");
		}
	}
#if 0
	if (SUCCEED != dbclose(dbproc)){
		fprintf(stdout, "dbclose failed");
		exit(1);
	}
	dbproc = dbopen(login, SERVER);
	assert(dbproc);
	if (strlen(DATABASE)) {
		dbuse(dbproc, DATABASE);
	}
#endif
	sql_cmd(dbproc);
	dbsqlexec(dbproc);

	if (dbresults(dbproc) != SUCCEED) {
		failed = 1;
		fprintf(stdout, "Was expecting a result set.");
		exit(1);
	}

	for (i = 1; i <= dbnumcols(dbproc); i++) {
		printf("col %d, \"%s\", is type %s\n", 
			i, dbcolname(dbproc, i), dbprtype(dbcoltype(dbproc, i)));
	}
	if (2 != dbnumcols(dbproc)) {
		fprintf(stderr, "Failed.  Expected 2 columns\n");
		exit(1);
	}

	if (SUCCEED != dbbind(dbproc, 1, INTBIND, -1, (BYTE *) & testint)) {
		fprintf(stderr, "Had problem with bind\n");
		exit(1);
	}

	if (REG_ROW != dbnextrow(dbproc)) {
		fprintf(stderr, "Failed.  Expected a row\n");
		exit(1);
	}
	if (testint != 1) {
		failed = 1;
		fprintf(stderr, "Failed.  Expected i to be %d, was %d\n", 1, (int) testint);
		exit(1);
	}
	dbnextrow(dbproc);

	/* get the image */
	sql_cmd(dbproc);
	dbsqlexec(dbproc);
	dbresults(dbproc);

	fprintf(stdout, "select 2\n");

	sql_cmd(dbproc);
	dbsqlexec(dbproc);
	if (dbresults(dbproc) != SUCCEED) {
		fprintf(stderr, "Error extracting blob\n");
		return 6;
	}

	numread = 0;
	rblob = NULL;
	while ((result = dbreadtext(dbproc, rbuf, BLOB_BLOCK_SIZE)) != NO_MORE_ROWS) {
		if (result != 0) {	/* this indicates not end of row */
			rblob = (char*) realloc(rblob, result + numread);
			memcpy((void *) (rblob + numread), (void *) rbuf, result);
			numread += result;
		}
	}

	data_ok = 1;
	if (memcmp(blob, rblob, numread) != 0) {
		printf("Saving first blob data row to file: %s\n", argv[2]);
		if ((fp = fopen(argv[2], "wb")) == NULL) {
			fprintf(stderr, "Unable to open output file: %s\n", argv[2]);
			return 3;
		}
		fwrite((void *) rblob, numread, 1, fp);
		fclose(fp);
		failed = 1;
		data_ok = 0;
	}

	printf("Read blob data row %d --> %s %ld byte comparison\n",
	       (int) testint, data_ok ? "PASSED" : "failed", numread);
	free(rblob);

	if (dbnextrow(dbproc) != NO_MORE_ROWS) {
		failed = 1;
		fprintf(stderr, "Was expecting no more rows\n");
		exit(1);
	}

	free(blob);
	drop_table();
	dbclose(dbproc);
	dbproc = NULL;

	dbexit();

	return 0;
}
示例#24
0
void MSSqlDatatable::update()
{
    // clear.
    this->clear();
    
# ifdef _FREETDS
    
    DBPROCESS* proc = (DBPROCESS*)_proc;
    
    // update.
    uint const ncols = dbnumcols(proc); 
    
    struct COL 						
    { 
        char *name; 
        char *buffer; 
        int type, size, status; 
    } *columns, *pcol;
    
    if ((columns = (COL*)calloc(ncols, sizeof(struct COL))) == NULL) {
        return;
    }
    
    RETCODE sta = 0;
    
    rows_type& rows = this->_rows;
    cols_type& cols = this->_cols;
    cols.resize(ncols);        
    
    //Read metadata and bind.  
    for (pcol = columns; pcol - columns < ncols; pcol++) {
        int c = (int)(pcol - columns + 1);
        
        pcol->name = dbcolname(proc, c);		
        pcol->type = dbcoltype(proc, c);
        pcol->size = dbcollen(proc, c);
        
        // add cols.
        cols[c - 1] = new variant_t(pcol->name, core::copy);
        
        if (SYBCHAR != pcol->type) {			
            pcol->size = dbwillconvert(pcol->type, SYBCHAR);
        }        
        
        if ((pcol->buffer = (char*)calloc(1, pcol->size + 1)) == NULL){
            break;
        }
        
        sta = dbbind(proc,
                     c,
                     NTBSTRINGBIND,	
                     pcol->size + 1,
                     (byte*)pcol->buffer);
        if (sta == FAIL) {
            break;
        }
        sta = dbnullbind(proc, 
                         c,
                         &pcol->status);	
        if (sta == FAIL) {
            break;
        }
    }
    
    // Get rows.
    while ((sta = dbnextrow(proc)) != NO_MORE_ROWS){	
        switch (sta) {
			case REG_ROW:
            {
                DBMSqlDatatable::row_type *row = new DBMSqlDatatable::row_type;
                row->resize(ncols);
                
				for (pcol=columns; pcol - columns < ncols; ++pcol) 
                {
                    int c = (int)(pcol - columns + 1);
					char const* buffer = pcol->status == -1 ? "" : pcol->buffer;
                    (*row)[c - 1] = new variant_t(buffer, core::copy);
				}
                
                rows.push_back(row);
            } break;
        }                
    }
    
    /* free metadata and data buffers */
    for (pcol=columns; pcol - columns < ncols; pcol++) {
        free(pcol->buffer);
    }
    free(columns);
    
# endif

# ifdef _MSSQL
	_RecordsetPtr& rcdset = *((_RecordsetPtr*)_proc);

	usize const ncols = (usize const)rcdset->Fields->GetCount();

	rows_type& rows = this->_rows;
	cols_type& cols = this->_cols;
	cols.resize(ncols);	

	// read cols.
	for (uint idx = 0; idx < ncols; ++idx)
	{
# ifdef NNT_DEBUG
		try {
# endif

		_bstr_t name = rcdset->Fields->GetItem((long)idx)->GetName();
		cols[idx] = new variant_t((char const*)name, core::copy);

# ifdef NNT_DEBUG
		} catch (_com_error& err) 	{
			_bstr_t msg = err.ErrorMessage();
			trace_msg((char const*)msg);
		}
# endif
	}

	// read rows.
	while (!rcdset->adoEOF)
	{
		row_type* row = new row_type;
		row->resize(ncols);

		for (uindex idx = 0; idx < ncols; ++idx)
		{
# ifdef NNT_DEBUG
			try {
# endif

			_bstr_t val = rcdset->GetCollect((long)idx);
			(*row)[idx] = new variant_t((char const*)val, core::copy);

# ifdef NNT_DEBUG
			} catch (_com_error& err) 	{
				_bstr_t msg = err.ErrorMessage();
				trace_msg((char const*)msg);
			}
# endif
		}

		rows.push_back(row);

		rcdset->MoveNext();
	}

# endif

}
示例#25
0
static int dbd_freetds_select(apr_pool_t *pool, apr_dbd_t *sql,
                              apr_dbd_results_t **results,
                              const char *query, int seek)
{
    apr_dbd_results_t *res;
    if (sql->trans && (sql->trans->errnum != SUCCEED)) {
        return 1;
    }
    /* the core of this is
     * dbcmd(proc, query);
     * dbsqlexec(proc);
     * while (dbnextrow(dbproc) != NO_MORE_ROWS) {
     *     do things
     * }
     *
     * Ignore seek
     */

    sql->err = freetds_exec(sql->proc, query, 1, NULL);
    if (!dbd_freetds_is_success(sql->err)) {
        if (sql->trans) {
            sql->trans->errnum = sql->err;
        }
        return 1;
    }

    sql->err = dbresults(sql->proc);
    if (sql->err != SUCCEED) {
        if (sql->trans) {
            sql->trans->errnum = sql->err;
        }
        return 1;
    }

    if (!*results) {
        *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
    }
    res = *results;
    res->proc = sql->proc;
    res->random = seek;
    res->pool = pool;
    res->ntuples = dblastrow(sql->proc);
    res->sz = dbnumcols(sql->proc);
    apr_pool_cleanup_register(pool, sql->proc, clear_result,
                              apr_pool_cleanup_null);

#if 0
    /* Now we have a result set.  We need to bind to its vars */
    res->vars = apr_palloc(pool, res->sz * sizeof(freetds_cell_t*));
    for (i=1; i <= res->sz; ++i) {
        freetds_cell_t *cell = &res->vars[i-1];
        cell->type = dbcoltype(sql->proc, i);
        cell->len = dbcollen(sql->proc, i);
        cell->data = apr_palloc(pool, cell->len);
        sql->err = dbbind(sql->proc, i, /*cell->type */ STRINGBIND, cell->len, cell->data);
        if (sql->err != SUCCEED) {
            fprintf(stderr, "dbbind error: %d, %d, %d", i, cell->type, cell->len);
        }
        if ((sql->err != SUCCEED) && (sql->trans != NULL)) {
            sql->trans->errnum = sql->err;
        }
    }
#endif
    return (sql->err == SUCCEED) ? 0 : 1;
}
示例#26
0
static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
	 zend_ulong *len, int *caller_frees)
{
	
	pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
	pdo_dblib_db_handle *H = S->H;
	
	int coltype;
	unsigned int tmp_len;
	char *tmp_ptr = NULL;
	
	coltype = dbcoltype(H->link, colno+1);
	
	*len = dbdatlen(H->link, colno+1);
	*ptr = dbdata(H->link, colno+1);
	
	if (*len == 0 && *ptr == NULL) {
		return 1;
	}
	
	switch (coltype) {
		case SQLVARBINARY:
		case SQLBINARY:
		case SQLIMAGE:
		case SQLTEXT:
			/* FIXME: Above types should be returned as a stream as they can be VERY large */
		case SQLCHAR:
		case SQLVARCHAR:
			tmp_ptr = emalloc(*len + 1);
			memcpy(tmp_ptr, *ptr, *len);
			tmp_ptr[*len] = '\0';
			*ptr = tmp_ptr;
			break;
		case SQLMONEY:
		case SQLMONEY4:
		case SQLMONEYN: {
			DBFLT8 money_value;
			dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
			*len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
			*ptr = tmp_ptr;
			break;
		}
		case SQLUNIQUE: {
			*len = 37;
			tmp_ptr = emalloc(*len + 1);
			*len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
			php_strtoupper(tmp_ptr, *len);
			tmp_ptr[36] = '\0';
			*ptr = tmp_ptr;
			break;
		}
		default:
			if (dbwillconvert(coltype, SQLCHAR)) {
				tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
				tmp_ptr = emalloc(tmp_len);
				*len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
				*ptr = tmp_ptr;
			} else {
				*len = 0; /* FIXME: Silently fails and returns null on conversion errors */
				*ptr = NULL;
			}
	}

	*caller_frees = 1;

	return 1;
}
示例#27
0
文件: dbpivot.c 项目: RQZeng/freetds
/** 
 * Pivot the rows, creating a new resultset
 *
 * Call dbpivot() immediately after dbresults().  It calls dbnextrow() as long as
 * it returns REG_ROW, transforming the results into a cross-tab report.  
 * dbpivot() modifies the metadata such that DB-Library can be used tranparently: 
 * retrieve the rows as usual with dbnumcols(), dbnextrow(), etc. 
 *
 * @dbproc, our old friend
 * @nkeys the number of left-edge columns to group by
 * @keys  an array of left-edge columns to group by
 * @ncols the number of top-edge columns to group by
 * @cols  an array of top-edge columns to group by
 * @func  the aggregation function to use
 * @val   the number of the column to which @func is applied
 *
 * @returns the return code from the final call to dbnextrow().  
 *  Success is normally indicated by NO_MORE_ROWS.  
 */
RETCODE
dbpivot(DBPROCESS *dbproc, int nkeys, int *keys, int ncols, int *cols, DBPIVOT_FUNC func, int val)
{
	enum { logalot = 1 };
	struct pivot_t P, *pp;
	struct agg_t input, *pout = NULL;
	struct key_t *pacross;
	struct metadata_t *metadata, *pmeta;
	size_t i, nmeta = 0;

	tdsdump_log(TDS_DBG_FUNC, "dbpivot(%p, %d,%p, %d,%p, %p, %d)\n", dbproc, nkeys, keys, ncols, cols, func, val);
	if (logalot) {
		char buffer[1024] = {'\0'}, *s = buffer;
		const static char *names[2] = { "\tkeys (down)", "\n\tcols (across)" };
		int *p = keys, *pend = p + nkeys;
		
		for (i=0; i < 2; i++) {
			const char *sep = "";
			s += sprintf(s, "%s: ", names[i]);
			for ( ; p < pend; p++) {
				s += sprintf(s, "%s%d", sep, *p);
				sep = ", ";
			}
			p = cols;
			pend = p + ncols;
			assert(s < buffer + sizeof(buffer));
		}
		tdsdump_log(TDS_DBG_FUNC, "%s\n", buffer);
	}
	
	memset(&input,  0, sizeof(input));
	
	P.dbproc = dbproc;
	if ((pp = tds_find(&P, pivots, npivots, sizeof(*pivots), pivot_key_equal)) == NULL ) {
		pp = realloc(pivots, (1 + npivots) * sizeof(*pivots)); 
		if (!pp)
			return FAIL;
		pivots = pp;
		pp += npivots++;
	} else {
		agg_free(pp->output);
		key_free(pp->across);		
	}
	memset(pp, 0, sizeof(*pp));

	if ((input.row_key.keys = calloc(nkeys, sizeof(*input.row_key.keys))) == NULL)
		return FAIL;
	input.row_key.nkeys = nkeys;
	for (i=0; i < nkeys; i++) {
		int type = dbcoltype(dbproc, keys[i]);
		int len = dbcollen(dbproc, keys[i]);
		assert(type && len);
		
		col_init(input.row_key.keys+i, type, len);
		if (FAIL == dbbind(dbproc, keys[i], bind_type(type), input.row_key.keys[i].len, col_buffer(input.row_key.keys+i)))
			return FAIL;
		if (FAIL == dbnullbind(dbproc, keys[i], &input.row_key.keys[i].null_indicator))
			return FAIL;
	}
	
	if ((input.col_key.keys = calloc(ncols, sizeof(*input.col_key.keys))) == NULL)
		return FAIL;
	input.col_key.nkeys = ncols;
	for (i=0; i < ncols; i++) {
		int type = dbcoltype(dbproc, cols[i]);
		int len = dbcollen(dbproc, cols[i]);
		assert(type && len);
		
		col_init(input.col_key.keys+i, type, len);
		if (FAIL == dbbind(dbproc, cols[i], bind_type(type), input.col_key.keys[i].len, col_buffer(input.col_key.keys+i)))
			return FAIL;
		if (FAIL == dbnullbind(dbproc, cols[i], &input.col_key.keys[i].null_indicator))
			return FAIL;
	}
	
	/* value */ {
		int type = dbcoltype(dbproc, val);
		int len = dbcollen(dbproc, val);
		assert(type && len);
		
		col_init(&input.value, type, len);
		if (FAIL == dbbind(dbproc, val, bind_type(type), input.value.len, col_buffer(&input.value)))
			return FAIL;
		if (FAIL == dbnullbind(dbproc, val, &input.value.null_indicator))
			return FAIL;
	}
	
	while ((pp->status = dbnextrow(dbproc)) == REG_ROW) {
		/* add to unique list of crosstab columns */
		if ((pacross = tds_find(&input.col_key, pp->across, pp->nacross, sizeof(*pp->across), key_equal)) == NULL ) {
			pacross = realloc(pp->across, (1 + pp->nacross) * sizeof(*pp->across)); 
			if (!pacross)
				return FAIL;
			pp->across = pacross;
			pacross += pp->nacross++;
			key_cpy(pacross, &input.col_key);
		}
		assert(pp->across);
		
		if ((pout = tds_find(&input, pp->output, pp->nout, sizeof(*pp->output), agg_equal)) == NULL ) {
			pout = realloc(pp->output, (1 + pp->nout) * sizeof(*pp->output)); 
			if (!pout)
				return FAIL;
			pp->output = pout;
			pout += pp->nout++;

			
			if ((pout->row_key.keys = calloc(input.row_key.nkeys, sizeof(*pout->row_key.keys))) == NULL)
				return FAIL;
			key_cpy(&pout->row_key, &input.row_key);

			if ((pout->col_key.keys = calloc(input.col_key.nkeys, sizeof(*pout->col_key.keys))) == NULL)
				return FAIL;
			key_cpy(&pout->col_key, &input.col_key);

			col_init(&pout->value, input.value.type, input.value.len);
		}
		
		func(&pout->value, &input.value);

	}

	/* Mark this proc as pivoted, so that dbnextrow() sees it when the application calls it */
	pp->dbproc = dbproc;
	pp->dbresults_state = dbproc->dbresults_state;
	dbproc->dbresults_state = pp->output < pout? _DB_RES_RESULTSET_ROWS : _DB_RES_RESULTSET_EMPTY;
	
	/*
	 * Initialize new metadata
	 */
	nmeta = input.row_key.nkeys + pp->nacross;	
	metadata = calloc(nmeta, sizeof(*metadata));
	
	assert(pp->across || pp->nacross == 0);
	
	/* key columns are passed through as-is, verbatim */
	for (i=0; i < input.row_key.nkeys; i++) {
		assert(i < nkeys);
		metadata[i].name = strdup(dbcolname(dbproc, keys[i]));
		metadata[i].pacross = NULL;
		col_cpy(&metadata[i].col, input.row_key.keys+i);
	}

	/* pivoted columms are found in the "across" data */
	for (i=0, pmeta = metadata + input.row_key.nkeys; i < pp->nacross; i++) {
		struct col_t col;
		col_init(&col, SYBFLT8, sizeof(double));
		assert(pmeta + i < metadata + nmeta);
		pmeta[i].name = make_col_name(pp->across+i);
		assert(pp->across);
		pmeta[i].pacross = pp->across + i;
		col_cpy(&pmeta[i].col, pp->nout? &pp->output[0].value : &col);
	}

	if (!reinit_results(dbproc->tds_socket, nmeta, metadata)) {
		return FAIL;
	}
	
	return SUCCEED;
	
#if 0
	for (pp->pout=pp->output; pp->pout < pp->output + pp->nout; pp->pout++) {
		char name[256] = {0};
	
		assert(pp->pout->col_key.keys[0].len < sizeof(name));
		memset(name, '\0', sizeof(name));
		memcpy(name, pp->pout->col_key.keys[0].s, pp->pout->col_key.keys[0].len), 
		printf("%5d  %-30s  %5d\n", pp->pout->row_key.keys[0].i, 
					    name, 
					    pp->pout->value.i );
	}
	exit(1);
#endif
}
示例#28
0
文件: bsqldb.c 项目: msabramo/freetds
static void
print_results(DBPROCESS *dbproc) 
{
	static const char empty_string[] = "";
	static const char dashes[] = "----------------------------------------------------------------" /* each line is 64 */
				     "----------------------------------------------------------------"
				     "----------------------------------------------------------------"
				     "----------------------------------------------------------------";
	
	struct METADATA *metadata = NULL, return_status;
	
	struct DATA { char *buffer; int status; } *data = NULL;
	
	struct METACOMP { int numalts; struct METADATA *meta; struct DATA *data; } **metacompute = NULL;
	
	RETCODE erc;
	int row_code;
	int i, c, ret;
	int iresultset;
	int ncomputeids = 0, ncols = 0;
	

	/* 
	 * If using default column separator, we want columns to line up vertically, 
	 * 	so we use blank padding (STRINGBIND).  
	 * For any other separator, we use no padding.
	 */
	const int bindtype = (0 == strcmp(options.colsep, default_colsep))? STRINGBIND : NTBSTRINGBIND;
	
	/* 
	 * Set up each result set with dbresults()
	 * This is more commonly implemented as a while() loop, but we're counting the result sets. 
	 */
	fprintf(options.verbose, "%s:%d: calling dbresults: OK\n", options.appname, __LINE__);
	for (iresultset=1; (erc = dbresults(dbproc)) != NO_MORE_RESULTS; iresultset++) {
		if (erc == FAIL) {
			fprintf(stderr, "%s:%d: dbresults(), result set %d failed\n", options.appname, __LINE__, iresultset);
			return;
		}
		
		if (options.pivot.func) {
			const struct key_t *rk = &options.pivot.row_key, *ck = &options.pivot.col_key;
			erc = dbpivot(dbproc, rk->nkeys, rk->keys, ck->nkeys, ck->keys, 
					options.pivot.func, options.pivot.val_col);
		}
		
		fprintf(options.verbose, "Result set %d\n", iresultset);
		/* Free prior allocations, if any. */
		for (c=0; c < ncols; c++) {
			free(metadata[c].format_string);
			free(data[c].buffer);
		}
		free(metadata);
		metadata = NULL;
		free(data);
		data = NULL;
		ncols = 0;
		
		for (i=0; i < ncomputeids; i++) {
			for (c=0; c < metacompute[i]->numalts; c++) {
				free(metacompute[i]->meta[c].name);
				free(metacompute[i]->meta[c].format_string);
			}
			free(metacompute[i]->meta);
			free(metacompute[i]->data);
			free(metacompute[i]);
		}
		free(metacompute);
		metacompute = NULL;
		ncomputeids = 0;
		
		/* 
		 * Allocate memory for metadata and bound columns 
		 */
		fprintf(options.verbose, "Allocating buffers\n");
		ncols = dbnumcols(dbproc);	

		metadata = (struct METADATA*) calloc(ncols, sizeof(struct METADATA));
		assert(metadata);

		data = (struct DATA*) calloc(ncols, sizeof(struct DATA));
		assert(data);
		
		/* metadata is more complicated only because there may be several compute ids for each result set */
		fprintf(options.verbose, "Allocating compute buffers\n");
		ncomputeids = dbnumcompute(dbproc);
		if (ncomputeids > 0) {
			metacompute = (struct METACOMP**) calloc(ncomputeids, sizeof(struct METACOMP*));
			assert(metacompute);
		}
		
		for (i=0; i < ncomputeids; i++) {
			metacompute[i] = (struct METACOMP*) calloc(ncomputeids, sizeof(struct METACOMP));
			assert(metacompute[i]);
			metacompute[i]->numalts = dbnumalts(dbproc, 1+i);
			fprintf(options.verbose, "%d columns found in computeid %d\n", metacompute[i]->numalts, 1+i);
			if (metacompute[i]->numalts > 0) {
				fprintf(options.verbose, "allocating column %d\n", 1+i);
				metacompute[i]->meta = (struct METADATA*) calloc(metacompute[i]->numalts, sizeof(struct METADATA));
				assert(metacompute[i]->meta);
				metacompute[i]->data = (struct     DATA*) calloc(metacompute[i]->numalts, sizeof(struct     DATA));
				assert(metacompute[i]->data);
			}
		}

		/* 
		 * For each column, get its name, type, and size. 
		 * Allocate a buffer to hold the data, and bind the buffer to the column.
		 * "bind" here means to give db-lib the address of the buffer we want filled as each row is fetched.
		 * TODO: Implement dbcoltypeinfo() for numeric/decimal datatypes.  
		 */

		fprintf(options.verbose, "Metadata\n");
		fprintf(options.verbose, "%-6s  %-30s  %-30s  %-15s  %-6s  %-6s  \n", "col", "name", "source", "type", "size", "varies");
		fprintf(options.verbose, "%.6s  %.30s  %.30s  %.15s  %.6s  %.6s  \n", dashes, dashes, dashes, dashes, dashes, dashes);
		for (c=0; c < ncols; c++) {
			/* Get and print the metadata.  Optional: get only what you need. */
			char *name = dbcolname(dbproc, c+1);
			metadata[c].name = strdup(name ? (const char *) name : empty_string);

			name = dbcolsource(dbproc, c+1);
			metadata[c].source = (name)? name : empty_string;

			metadata[c].type = dbcoltype(dbproc, c+1);
			metadata[c].size = dbcollen(dbproc, c+1);
			assert(metadata[c].size != -1); /* -1 means indicates an out-of-range request*/

			fprintf(options.verbose, "%6d  %30s  %30s  %15s  %6d  %6d  \n", 
				c+1, metadata[c].name, metadata[c].source, dbprtype(metadata[c].type), 
				metadata[c].size,  dbvarylen(dbproc, c+1));

			/* 
			 * Build the column header format string, based on the column width. 
			 * This is just one solution to the question, "How wide should my columns be when I print them out?"
			 */
			metadata[c].width = get_printable_size(metadata[c].type, metadata[c].size);
			if (metadata[c].width < strlen(metadata[c].name))
				metadata[c].width = strlen(metadata[c].name);
				
			ret = set_format_string(&metadata[c], (c+1 < ncols)? options.colsep : "\n");
			if (ret <= 0) {
				fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);
				return;
			}

			/* 
			 * Bind the column to our variable.
			 * We bind everything to strings, because we want db-lib to convert everything to strings for us.
			 * If you're performing calculations on the data in your application, you'd bind the numeric data
			 * to C integers and floats, etc. instead. 
			 * 
			 * It is not necessary to bind to every column returned by the query.  
			 * Data in unbound columns are simply never copied to the user's buffers and are thus 
			 * inaccesible to the application.  
			 */

			if (metadata[c].width < INT_MAX) {
				data[c].buffer = calloc(1, 1 + metadata[c].width); /* allow for null terminator */
				assert(data[c].buffer);

				erc = dbbind(dbproc, c+1, bindtype, 0, (BYTE *) data[c].buffer);
				if (erc == FAIL) {
					fprintf(stderr, "%s:%d: dbbind(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}

				erc = dbnullbind(dbproc, c+1, &data[c].status);
				if (erc == FAIL) {
					fprintf(stderr, "%s:%d: dbnullbind(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}
			} else {
				/* We don't bind text buffers, but use dbreadtext instead. */
				data[c].buffer = NULL;
			}

		}
		
		/* 
		 * Get metadata and bind the columns for any compute rows.
		 */
		for (i=0; i < ncomputeids; i++) {
			fprintf(options.verbose, "For computeid %d:\n", 1+i);
			for (c=0; c < metacompute[i]->numalts; c++) {
				/* read metadata */
				struct METADATA *meta = &metacompute[i]->meta[c];
				int nby, iby;
				BYTE *bylist;
				char *colname, *bynames;
				int altcolid = dbaltcolid(dbproc, i+1, c+1);
				
				metacompute[i]->meta[c].type = dbalttype(dbproc, i+1, c+1);
				metacompute[i]->meta[c].size = dbaltlen(dbproc, i+1, c+1);

				/* 
				 * Jump through hoops to determine a useful name for the computed column 
				 * If the query says "compute count(c) by a,b", we get a "by list" indicating a & b.  
				 */
				bylist = dbbylist(dbproc, c+1, &nby);

				bynames = strdup("by (");
				for (iby=0; iby < nby; iby++) {
					char *s = NULL; 
					int ret = asprintf(&s, "%s%s%s", bynames, dbcolname(dbproc, bylist[iby]), 
										(iby+1 < nby)? ", " : ")");
					if (ret < 0) {
						fprintf(options.verbose, "Insufficient room to create name for column %d:\n", 1+c);
						break;
					}
					free(bynames);
					bynames = s;
				}
				
				if( altcolid == -1 ) {
					colname = "*";
				} else {
					assert(0 < altcolid && altcolid <= dbnumcols(dbproc));
					colname = metadata[--altcolid].name;
				}

				asprintf(&metacompute[i]->meta[c].name, "%s(%s)", dbprtype(dbaltop(dbproc, i+1, c+1)), colname);
				assert(metacompute[i]->meta[c].name);
					
				metacompute[i]->meta[c].width = get_printable_size(metacompute[i]->meta[c].type, 
										   metacompute[i]->meta[c].size);
				if (metacompute[i]->meta[c].width < strlen(metacompute[i]->meta[c].name))
					metacompute[i]->meta[c].width = strlen(metacompute[i]->meta[c].name);

				ret = set_format_string(meta, (c+1 < metacompute[i]->numalts)? options.colsep : "\n");
				if (ret <= 0) {
					free(bynames);
					fprintf(stderr, "%s:%d: asprintf(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}
				
				fprintf(options.verbose, "\tcolumn %d is %s, type %s, size %d %s\n", 
					c+1, metacompute[i]->meta[c].name, dbprtype(metacompute[i]->meta[c].type),
					metacompute[i]->meta[c].size, (nby > 0)? bynames : "");
				free(bynames);
	
				/* allocate buffer */
				assert(metacompute[i]->data);
				metacompute[i]->data[c].buffer = calloc(1, metacompute[i]->meta[c].width);
				assert(metacompute[i]->data[c].buffer);
				
				/* bind */
				erc = dbaltbind(dbproc, i+1, c+1, bindtype, -1, (BYTE*) metacompute[i]->data[c].buffer);
				if (erc == FAIL) {
					fprintf(stderr, "%s:%d: dbaltbind(), column %d failed\n", options.appname, __LINE__, c+1);
					return;
				}
			}
		}
		
		fprintf(options.verbose, "\n");
		fprintf(options.verbose, "Data\n");

		if (!options.fquiet) {
			/* Print the column headers to stderr to keep them separate from the data.  */
			for (c=0; c < ncols; c++) {
				fprintf(options.headers, metadata[c].format_string, metadata[c].name);
			}

			/* Underline the column headers.  */
			for (c=0; c < ncols; c++) {
				fprintf(options.headers, metadata[c].format_string, dashes);
			}
		}
		/* 
		 * Print the data to stdout.  
		 */
		while ((row_code = dbnextrow(dbproc)) != NO_MORE_ROWS) {
			switch (row_code) {
			case REG_ROW:
				for (c=0; c < ncols; c++) {
					if (metadata[c].width == INT_MAX) { /* TEXT/IMAGE */
						BYTE *p = dbdata(dbproc, c+1);
						size_t len = dbdatlen(dbproc, c+1);
						if (len == 0) {
							fputs("NULL", stdout);
						} else {
							BYTE *pend = p + len;
							switch(dbcoltype(dbproc, c+1)) {
							case SYBTEXT:
								if (fwrite(p, len, 1, stdout) != 1) {
									perror("could not write to output file");
									exit(EXIT_FAILURE);
								}
								break;
							default:	/* image, binary */
								fprintf(stdout, "0x");
								for (; p < pend; p++) {
									printf("%02hx", (unsigned short int)*p);
								}
								break;
							}
						}
						fprintf(stdout, metadata[c].format_string, ""); /* col/row separator */
						continue;
					}
					switch (data[c].status) { /* handle nulls */
					case -1: /* is null */
						/* TODO: FreeTDS 0.62 does not support dbsetnull() */
						fprintf(stdout, metadata[c].format_string, "NULL");
						break;
					case 0:
					/* case >1 is datlen when buffer is too small */
					default:
						fprintf(stdout, metadata[c].format_string, data[c].buffer);
						break;
					}
				}
				break;
				
			case BUF_FULL:
				assert(row_code != BUF_FULL);
				break;
				
			case FAIL:
				fprintf(stderr, "bsqldb: fatal error: dbnextrow returned FAIL\n");
				assert(row_code != FAIL);
				exit(EXIT_FAILURE);
				break;
				
			default: /* computeid */
				fprintf(options.verbose, "Data for computeid %d\n", row_code);
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					char fmt[256] = "%-";
					struct METADATA *meta = &metacompute[row_code-1]->meta[c];
					
					/* left justify the names */
					strcat(fmt, &meta->format_string[1]);
					fprintf(options.headers, fmt, meta->name);
				}

				/* Underline the column headers.  */
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					fprintf(options.headers, metacompute[row_code-1]->meta[c].format_string, dashes);
				}
					
				for (c=0; c < metacompute[row_code-1]->numalts; c++) {
					struct METADATA *meta = &metacompute[row_code-1]->meta[c];
					struct     DATA *data = &metacompute[row_code-1]->data[c];
					
					switch (data->status) { /* handle nulls */
					case -1: /* is null */
						/* TODO: FreeTDS 0.62 does not support dbsetnull() */
						fprintf(stdout, meta->format_string, "NULL");
						break;
					case 0:
					/* case >1 is datlen when buffer is too small */
					default:
						fprintf(stdout, meta->format_string, data->buffer);
						break;
					}
				}
			}


		}

		/* Check return status */
		if (!options.fquiet) {
			fprintf(options.verbose, "Retrieving return status... ");
			if (dbhasretstat(dbproc) == TRUE) {
				fprintf(stderr, "Procedure returned %d\n", dbretstatus(dbproc));
			} else {
				fprintf(options.verbose, "none\n");
			}
		}
		
		/* 
		 * Get row count, if available.   
		 */
		if (!options.fquiet) {
			if (DBCOUNT(dbproc) > -1)
				fprintf(stderr, "%d rows affected\n", DBCOUNT(dbproc));
			else 
				fprintf(stderr, "@@rowcount not available\n");
		}			

		/* 
		 * Check return parameter values 
		 */
		fprintf(options.verbose, "Retrieving output parameters... ");
		if (dbnumrets(dbproc) > 0) {
			for (i = 1; i <= dbnumrets(dbproc); i++) {
				char parameter_string[1024];
				
				return_status.name = dbretname(dbproc, i);
				fprintf(stderr, "ret name %d is %s\n", i, return_status.name);
				
				return_status.type = dbrettype(dbproc, i);
				fprintf(options.verbose, "\n\tret type %d is %d", i, return_status.type);
				
				return_status.size = dbretlen(dbproc, i);
				fprintf(options.verbose, "\n\tret len %d is %d\n", i, return_status.size);
				
				dbconvert(dbproc, return_status.type, dbretdata(dbproc, i), return_status.size, 
					  SYBVARCHAR, (BYTE *) parameter_string, -1);
				fprintf(stderr, "ret data %d is %s\n", i, parameter_string);
			}
		} else {
			fprintf(options.verbose, "none\n");
		}
	} /* wend dbresults */
	fprintf(options.verbose, "%s:%d: dbresults() returned NO_MORE_RESULTS (%d):\n", options.appname, __LINE__, erc);
}
示例#29
0
static int
check_table_structures(char *sobjname, char *dobjname, DBPROCESS * dbsrc, DBPROCESS * dbdest)
{
	char ls_command[256];
	int i;

	DBINT src_numcols = 0;
	DBINT dest_numcols = 0;

	DBINT src_coltype, dest_coltype;
	DBINT src_collen, dest_collen;


	sprintf(ls_command, "SET FMTONLY ON select * from %s SET FMTONLY OFF", sobjname);

	if (dbcmd(dbsrc, ls_command) == FAIL) {
		printf("dbcmd failed\n");
		return FALSE;
	}

	if (dbsqlexec(dbsrc) == FAIL) {
		printf("table %s not found on SOURCE\n", sobjname);
		return FALSE;
	}

	while (NO_MORE_RESULTS != dbresults(dbsrc));
	{

		if (0 == (src_numcols = dbnumcols(dbsrc))) {
			printf("Error in dbnumcols\n");
			return FALSE;
		}
	}

	sprintf(ls_command, "SET FMTONLY ON select * from %s SET FMTONLY OFF", dobjname);

	if (dbcmd(dbdest, ls_command) == FAIL) {
		printf("dbcmd failed\n");
		return FALSE;
	}

	if (dbsqlexec(dbdest) == FAIL) {
		printf("table %s not found on DEST\n", sobjname);
		return FALSE;
	}

	while (NO_MORE_RESULTS != dbresults(dbdest));
	{

		if (0 == (dest_numcols = dbnumcols(dbdest))) {
			printf("Error in dbnumcols\n");
			return FALSE;
		}
	}

	if (src_numcols != dest_numcols) {
		printf("number of columns do not match. source : %d , dest: %d\n", src_numcols, dest_numcols);
		return FALSE;
	}

	for (i = 1; i <= src_numcols; i++) {

		src_coltype = dbcoltype(dbsrc, i);
		src_collen = dbcollen(dbsrc, i);
		dest_coltype = dbcoltype(dbdest, i);
		dest_collen = dbcollen(dbdest, i);

		if ((src_coltype == SYBNUMERIC && dest_coltype == SYBNUMERIC) ||
		    (src_coltype == SYBDECIMAL && dest_coltype == SYBDECIMAL)
			) {
			continue;
		}

		if (src_coltype != dest_coltype || src_collen != dest_collen) {
			printf("COLUMN TYPE MISMATCH: column %d\n", i);
			printf("source: type %d, length %d\n", src_coltype, src_collen);
			printf("dest  : type %d, length %d\n", dest_coltype, dest_collen);
			return FALSE;
		}
	}
	return TRUE;
}
示例#30
0
static VALUE rb_tinytds_result_fetch_row(VALUE self, ID timezone, int symbolize_keys, int as_array) {
  VALUE row;
  /* Storing Values */
  unsigned int i;
  /* Wrapper And Local Vars */
  GET_RESULT_WRAPPER(self);
  /* Create Empty Row */
  row = as_array ? rb_ary_new2(rwrap->number_of_fields) : rb_hash_new();
  for (i = 0; i < rwrap->number_of_fields; i++) {
    VALUE val = Qnil;
    int col = i+1;
    int coltype = dbcoltype(rwrap->client, col);
    BYTE *data = dbdata(rwrap->client, col);
    DBINT data_len = dbdatlen(rwrap->client, col);
    int null_val = ((data == NULL) && (data_len == 0));
    if (!null_val) {
      switch(coltype) {
        case SYBINT1:
          val = INT2FIX(*(DBTINYINT *)data);
          break;
        case SYBINT2:
          val = INT2FIX(*(DBSMALLINT *)data);
          break;
        case SYBINT4:
          val = INT2NUM(*(DBINT *)data);
          break;
        case SYBINT8:
          val = LL2NUM(*(DBBIGINT *)data);
          break;
        case SYBBIT:
          val = *(int *)data ? Qtrue : Qfalse;
          break;
        case SYBNUMERIC:
        case SYBDECIMAL: {
          DBTYPEINFO *data_info = dbcoltypeinfo(rwrap->client, col);
          int data_slength = (int)data_info->precision + (int)data_info->scale + 1;
          char converted_decimal[data_slength];
          dbconvert(rwrap->client, coltype, data, data_len, SYBVARCHAR, (BYTE *)converted_decimal, -1);
          val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new2((char *)converted_decimal));
          break;
        }
        case SYBFLT8: {
          double col_to_double = *(double *)data;
          val = (col_to_double == 0.000000) ? opt_float_zero : rb_float_new(col_to_double);
          break;
        }
        case SYBREAL: {
          float col_to_float = *(float *)data;
          val = (col_to_float == 0.0) ? opt_float_zero : rb_float_new(col_to_float);
          break;
        }
        case SYBMONEY: {
          DBMONEY *money = (DBMONEY *)data;
          char converted_money[25];
          long long money_value = ((long long)money->mnyhigh << 32) | money->mnylow;
          sprintf(converted_money, "%" LONG_LONG_FORMAT, money_value);
          val = rb_funcall(cBigDecimal, intern_new, 2, rb_str_new2(converted_money), opt_four);
          val = rb_funcall(val, intern_divide, 1, opt_tenk);
          break;
        }
        case SYBMONEY4: {
          DBMONEY4 *money = (DBMONEY4 *)data;
          char converted_money[20];
          sprintf(converted_money, "%f", money->mny4 / 10000.0);
          val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new2(converted_money));
          break;
        }
        case SYBBINARY:
        case SYBIMAGE:
          val = rb_str_new((char *)data, (long)data_len);
          #ifdef HAVE_RUBY_ENCODING_H
            rb_enc_associate(val, binaryEncoding);
          #endif
          break;
        case 36: { // SYBUNIQUE
          char converted_unique[37];
          dbconvert(rwrap->client, coltype, data, 37, SYBVARCHAR, (BYTE *)converted_unique, -1);
          val = ENCODED_STR_NEW2(converted_unique);
          break;
        }
        case SYBDATETIME4: {
          DBDATETIME new_data;
          dbconvert(rwrap->client, coltype, data, data_len, SYBDATETIME, (BYTE *)&new_data, sizeof(new_data));
          data = (BYTE *)&new_data;
          data_len = sizeof(new_data);
        }
        case SYBDATETIME: {
          DBDATEREC dr;
          dbdatecrack(rwrap->client, &dr, (DBDATETIME *)data);
          if (dr.year + dr.month + dr.day + dr.hour + dr.minute + dr.second + dr.millisecond != 0) {
            val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr.year), INT2NUM(dr.month), INT2NUM(dr.day), INT2NUM(dr.hour), INT2NUM(dr.minute), INT2NUM(dr.second), INT2NUM(dr.millisecond*1000));
          }
          break;
        }
        case 40:   // SYBMSDATE
        case 41:   // SYBMSTIME
        case 42:   // SYBMSDATETIME2
        case 43: { // SYBMSDATETIMEOFFSET
          #ifdef DBVERSION_73
            if (dbtds(rwrap->client) >= DBTDS_7_3) {
              DBDATEREC2 dr2;
              dbanydatecrack(rwrap->client, &dr2, coltype, data);
              switch(coltype) {
                case 40: { // SYBMSDATE
                  val = rb_funcall(cDate, intern_new, 3, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day));
                  break;
                }
                case 41: { // SYBMSTIME
                  VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
                  val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(1900), INT2NUM(1), INT2NUM(1), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
                  break;
                }
                case 42: { // SYBMSDATETIME2
                  VALUE rational_nsec = rb_Rational(INT2NUM(dr2.nanosecond), opt_onek);
                  val = rb_funcall(rb_cTime, timezone, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), INT2NUM(dr2.second), rational_nsec);
                  break;
                }
                case 43: { // SYBMSDATETIMEOFFSET
                  long long numerator = ((long)dr2.second * (long long)1000000000) + (long long)dr2.nanosecond;
                  VALUE rational_sec = rb_Rational(LL2NUM(numerator), opt_onebil);
                  val = rb_funcall(rb_cTime, intern_new, 7, INT2NUM(dr2.year), INT2NUM(dr2.month), INT2NUM(dr2.day), INT2NUM(dr2.hour), INT2NUM(dr2.minute), rational_sec, INT2NUM(dr2.tzone*60));
                  break;
                }
              }
            } else {
              val = ENCODED_STR_NEW(data, data_len);
            }
          #else
            val = ENCODED_STR_NEW(data, data_len);
          #endif
          break;
        }
        case SYBCHAR:
        case SYBTEXT:
          val = ENCODED_STR_NEW(data, data_len);
          break;
        default:
          val = ENCODED_STR_NEW(data, data_len);
          break;
      }
    }
    if (as_array) {
      rb_ary_store(row, i, val);
    } else {
      VALUE key;
      if (rwrap->number_of_results == 0) {
        key = rb_ary_entry(rwrap->fields, i);
      } else {
        key = rb_ary_entry(rb_ary_entry(rwrap->fields, rwrap->number_of_results), i);
      }
      rb_hash_aset(row, key, val);
    }
  }
  return row;
}