Exemple #1
0
static PyObject *CS_COMMAND_ct_get_data(CS_COMMANDObj *self, PyObject *args)
{
    DataBufObj *databuf;
    int num;
    CS_RETCODE status;

    if (!PyArg_ParseTuple(args, "iO!", &num, &DataBufType, &databuf))
	return NULL;

    if (self->cmd == NULL) {
	PyErr_SetString(PyExc_TypeError, "CS_COMMAND has been dropped");
	return NULL;
    }

    /* PyErr_Clear(); */

    SY_CONN_BEGIN_THREADS(self->conn);
    status = ct_get_data(self->cmd, (CS_INT)num,
			 databuf->buff, databuf->fmt.maxlength,
			 &databuf->copied[0]);
    databuf->indicator[0] = 0;
    SY_CONN_END_THREADS(self->conn);

    if (self->debug)
	debug_msg("ct_get_data(cmd%d, %d, databuf%d->buff,"
		  " %d, &databuf%d->copied[0]) -> %s, %d\n",
		  self->serial, num, databuf->serial,
		  (int)databuf->fmt.maxlength, databuf->serial,
		  value_str(VAL_STATUS, status), (int)databuf->copied[0]);
    if (PyErr_Occurred())
	return NULL;

    return Py_BuildValue("ii", status, databuf->copied[0]);
}
Exemple #2
0
/* Testing: Retrieve CS_TEXT_TYPE using ct_bind() */
int
main(int argc, char **argv)
{
	CS_CONTEXT *ctx;
	CS_COMMAND *cmd;
	int i, verbose = 0;

	CS_RETCODE ret;
	CS_RETCODE ret2;
	CS_RETCODE results_ret;
	CS_INT result_type;
	CS_INT num_cols;

	CS_DATAFMT datafmt;
	CS_INT datalength;
	CS_SMALLINT ind;
	CS_INT count, row_count = 0;

	CS_INT  id;
	CS_CHAR name[600];
	CS_CHAR *nameptr;
	CS_INT  getlen;

	char large_sql[1024];
	char len600[601];
	char len800[801];
	char temp[11];

	char *textptr;
	CS_IODESC iodesc;

	int tds_version;

	len600[0] = 0;
	name[0] = 0;
	for (i = 0; i < 60; i++) {
		sprintf(temp, "_abcde_%03d", (i + 1) * 10);
		strcat(len600, temp);
	}
	len600[600] = '\0';

	len800[0] = 0;
	for (i = 0; i < 80; i++) {
		sprintf(temp, "_zzzzz_%03d", (i + 1) * 10);
		strcat(len800, temp);
	}
	len800[800] = '\0';


	fprintf(stdout, "%s: Retrieve CS_TEXT_TYPE using ct_bind()\n", __FILE__);
	if (verbose) {
		fprintf(stdout, "Trying login\n");
	}
	ret = try_ctlogin(&ctx, &conn, &cmd, verbose);
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "Login failed\n");
		return 1;
	}

	ret = ct_con_props(conn, CS_GET, CS_TDS_VERSION, &tds_version, CS_UNUSED, NULL);
	if (ret == CS_SUCCEED) {
		if (tds_version >= CS_TDS_72) {
			printf("Protocol TDS7.2+ detected, test not supported\n");
			try_ctlogout(ctx, conn, cmd, verbose);
			return 0;
		}
	}

	ret = run_command(cmd, "CREATE TABLE #test_table (id int, name text)");
	if (ret != CS_SUCCEED)
		return 1;

	sprintf(large_sql, "INSERT #test_table (id, name) VALUES (2, '%s')", len600);
	ret = run_command(cmd, large_sql);
	if (ret != CS_SUCCEED)
		return 1;

	ret = ct_command(cmd, CS_LANG_CMD, "SELECT id, name FROM #test_table", CS_NULLTERM, CS_UNUSED);
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "ct_command() failed\n");
		return 1;
	}
	ret = ct_send(cmd);
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "ct_send() failed\n");
		return 1;
	}
	while ((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
		switch ((int) result_type) {
		case CS_CMD_SUCCEED:
			break;
		case CS_CMD_DONE:
			break;
		case CS_CMD_FAIL:
			fprintf(stderr, "ct_results() result_type CS_CMD_FAIL.\n");
			return 1;
		case CS_ROW_RESULT:
			ret = ct_res_info(cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL);
			if (ret != CS_SUCCEED) {
				fprintf(stderr, "ct_res_info() failed");
				return 1;
			}
			if (num_cols != 2) {
				fprintf(stderr, "num_cols %d != 2", num_cols);
				return 1;
			}

			ret = ct_describe(cmd, 1, &datafmt);
			if (ret != CS_SUCCEED) {
				fprintf(stderr, "ct_describe() failed");
				return 1;
			}
			datafmt.format = CS_FMT_UNUSED;
			if (datafmt.maxlength > 1024) {
				datafmt.maxlength = 1024;
			}
			ret = ct_bind(cmd, 1, &datafmt, &id, &datalength, &ind);
			if (ret != CS_SUCCEED) {
				fprintf(stderr, "ct_bind() failed\n");
				return 1;
			}

			while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &count)) == CS_SUCCEED)
			       || (ret == CS_ROW_FAIL)) {
				row_count += count;
				if (ret == CS_ROW_FAIL) {
					fprintf(stderr, "ct_fetch() CS_ROW_FAIL on row %d.\n", row_count);
					return 1;
				} else {	/* ret == CS_SUCCEED */
					if (verbose) {
						fprintf(stdout, "id = '%d'\n", id);
					}

                    nameptr = name;
                    while ((ret2 = ct_get_data(cmd, 2 , nameptr, 200, &getlen )) == CS_SUCCEED) {
                        nameptr += getlen;
					}
                    if (ret2 != CS_END_DATA) {
						fprintf(stderr, "ct_get_data() failed\n");
						return 1;
					}

					if (memcmp(name, len600, 600)) {
						fprintf(stderr, "Bad return data\n");
						return 1;
					}
					fprintf(stdout, "%s: Trying ct_data_info on text column\n", __FILE__);

                    if (ct_data_info(cmd, CS_GET, 2, &iodesc) != CS_SUCCEED) {
						fprintf(stderr, "ct_data_info() failed\n");
						return 1;
					} else {
						fprintf(stdout, "datatype = %d\n", iodesc.datatype);
						fprintf(stdout, "usertype = %d\n", iodesc.usertype);
						fprintf(stdout, "text len = %d\n", iodesc.total_txtlen);
						fprintf(stdout, "name     = %*.*s\n", iodesc.namelen, iodesc.namelen, iodesc.name);
					}
				}
			}
			switch ((int) ret) {
			case CS_END_DATA:
				break;
			case CS_FAIL:
				fprintf(stderr, "ct_fetch() returned CS_FAIL.\n");
				return 1;
			default:
				fprintf(stderr, "ct_fetch() unexpected return.\n");
				return 1;
			}
			break;
		case CS_COMPUTE_RESULT:
			fprintf(stderr, "ct_results() unexpected CS_COMPUTE_RESULT.\n");
			return 1;
		default:
			fprintf(stderr, "ct_results() unexpected result_type.\n");
			return 1;
		}
	}
	switch ((int) results_ret) {
	case CS_END_RESULTS:
		break;
	case CS_FAIL:
		fprintf(stderr, "ct_results() failed.\n");
		return 1;
		break;
	default:
		fprintf(stderr, "ct_results() unexpected return.\n");
		return 1;
	}

	if ((ret = ct_command(cmd, CS_SEND_DATA_CMD, NULL, CS_UNUSED, CS_COLUMN_DATA)) != CS_SUCCEED) {
		fprintf(stderr, "ct_command(CS_SEND_DATA_CMD) failed.\n");
		return 1;
	}               

	iodesc.total_txtlen = 800;
	iodesc.log_on_update = CS_TRUE;

	if (ct_data_info(cmd, CS_SET, CS_UNUSED, &iodesc) != CS_SUCCEED) {
		fprintf(stderr, "ct_data_info() failed\n");
		return 1;
	}

	for ( i = 0 ; i < 800 ; i += 200 ) {
		textptr = &len800[i];

		ret = ct_send_data(cmd, textptr, (CS_INT) 200);
		if (ret != CS_SUCCEED) {
			fprintf(stderr, "ct_send_data failed\n");
			return 1;
		}
	}
	ret = ct_send(cmd);

	if (ret != CS_SUCCEED) {
		fprintf(stderr, "ct_send failed\n");
		return 1;
	}

	while ((results_ret = ct_results(cmd, &result_type)) == CS_SUCCEED) {
		switch ((int) result_type) {
		case CS_CMD_SUCCEED:
			break;
		case CS_CMD_DONE:
			break;
		case CS_CMD_FAIL:
			fprintf(stderr, "ct_results() result_type CS_CMD_FAIL.\n");
			return 1;
		case CS_ROW_RESULT:
			break;
		case CS_PARAM_RESULT:
			break;
		case CS_COMPUTE_RESULT:
			fprintf(stderr, "ct_results() unexpected CS_COMPUTE_RESULT.\n");
			return 1;
		default:
			fprintf(stderr, "ct_results() unexpected result_type.\n");
			return 1;
		}
	}
	switch ((int) results_ret) {
	case CS_END_RESULTS:
		break;
	case CS_FAIL:
		fprintf(stderr, "ct_results() failed.\n");
		return 1;
		break;
	default:
		fprintf(stderr, "ct_results() unexpected return.\n");
		return 1;
	}

	if (verbose) {
		fprintf(stdout, "Trying logout\n");
	}
	ret = try_ctlogout(ctx, conn, cmd, verbose);
	if (ret != CS_SUCCEED) {
		fprintf(stderr, "Logout failed\n");
		return 1;
	}

	return 0;
}
Exemple #3
0
static VALUE statement_Execute(VALUE self) {
	int i;
	CS_DATAFMT col;
	CS_DATAFMT *cols;
	EX_COLUMN_DATA *col_data;
	CS_INT rc;
	CS_INT resulttype;
	CS_INT num_cols;
	CS_INT col_len;
	CS_INT row_count = 0;
	CS_INT rows_read;
	
	CS_INT num_errors = 0;
	CS_SERVERMSG servermsg;
	VALUE err;
	char *error_msg;
	
	struct timeval start, stop;
	int print_rows = 1;
	char message[128];
	char* buf;
	CS_DATEREC date_rec;
	char output[200];
	CS_INT output_len;
	int tempInt;
	CS_BIGINT tempBigInt;
	double tempDouble;
	CS_NUMERIC tempNumeric;
	char* tempText;
	char* newTempText;
	int tempTextLen;
	CS_INT data_rc;
	int isNull = 0;
	CS_DATE tempDate;
	CS_DATETIME tempDateTime;

	TDS_Connection* conn;
	CS_COMMAND * cmd;
	
	VALUE connection;
	VALUE query;
	VALUE columns;
	VALUE rows;
	VALUE status;
	VALUE errors;
	
	VALUE date_parts[8];
	
	VALUE column;
	VALUE row;
	
	VALUE column_name = rb_str_new2("name");
	VALUE column_type = rb_str_new2("type");
	VALUE column_size = rb_str_new2("size");
	VALUE column_scale = rb_str_new2("scale");
	VALUE column_precision = rb_str_new2("precision");
	
	VALUE column_value;
	
	connection = rb_iv_get(self, "@connection");
	query = rb_iv_get(self, "@query");
	
	columns = rb_ary_new();
	rb_iv_set(self, "@columns", columns);

	rows = rb_ary_new();
	rb_iv_set(self, "@rows", rows);
	
	Data_Get_Struct(connection, TDS_Connection, conn);
	buf = value_to_cstr(query);

	rb_iv_set(self, "@status", Qnil);
	
	rb_iv_set(self, "@messages", rb_ary_new());
	errors = rb_ary_new();
	rb_iv_set(self, "@errors", errors);

	ct_diag(conn->connection, CS_INIT, CS_UNUSED, CS_UNUSED, NULL);
	// if ( ct_callback(conn->context, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *)clientmsg_cb) != CS_SUCCEED ) {
	// 	error_message("ct_callback CS_CLIENTMSG_CB failed\n");
	// }
	// if ( ct_callback(conn->context, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *)servermsg_cb) != CS_SUCCEED ) {
	// 	error_message("ct_callback CS_SERVERMSG_CB failed\n");
	// }
	ct_cmd_alloc(conn->connection, &cmd);
	ct_command(cmd, CS_LANG_CMD, buf, CS_NULLTERM, CS_UNUSED);
	ct_send(cmd);

	if ( ct_diag(conn->connection, CS_STATUS, CS_SERVERMSG_TYPE, CS_UNUSED, &num_errors) != CS_SUCCEED ) {
		error_message("ct_diag CS_STATUS CS_SERVERMSG_TYPE failed");
	}
	if (num_errors > 0) {
		// fprintf(stderr, "%d errors found\n", num_errors);
		for (i = 0; i < num_errors; i++) {
			if ( ct_diag(conn->connection, CS_GET, CS_SERVERMSG_TYPE, i+1, &servermsg) != CS_SUCCEED ) {
				error_message("ct_diag CS_GET CS_SERVERMSG_TYPE failed");
			}
			if (servermsg.severity > 0) {
				// error_message(servermsg.text);
				rb_ary_push(errors, rb_str_new2(servermsg.text));
			}
		}
		if ( ct_diag(conn->connection, CS_CLEAR, CS_SERVERMSG_TYPE, CS_UNUSED, NULL) != CS_SUCCEED ) {
			error_message("ct_diag CS_CLEAR CS_SERVERMSG_TYPE failed");
		}
	}
	
	// Raise errors from ct_command/ct_send
	err = rb_funcall(errors, rb_intern("first"), 0); // FIXME: should probably display all errors instead of just first
	if(RTEST(err)) {
		error_msg = value_to_cstr(err);
		rb_raise(rb_eIOError, error_msg);

		ct_cmd_drop(cmd);

		return Qnil;
	}
	// TODO:
	// - We should have an array of malloc'd cols
	// - Then we bind / fetch to those
	// - Finish conversions...
	
	while ((rc = ct_results(cmd, &resulttype)) == CS_SUCCEED) {
		switch (resulttype) {
		case CS_ROW_RESULT:
			rc = ct_res_info(cmd, CS_NUMDATA, &num_cols, sizeof(num_cols), &col_len);
			if (rc != CS_SUCCEED)
			{
				fprintf(stderr, "ct_res_info() failed\n");
				return 1;
			}

			col_data = (EX_COLUMN_DATA *)malloc(num_cols * sizeof (EX_COLUMN_DATA));
			if (col_data == NULL)
			 {
			    fprintf(stderr, "ex_fetch_data: malloc() failed");
			    return CS_MEM_ERROR;
			 }
			 cols = (CS_DATAFMT *)malloc(num_cols * sizeof (CS_DATAFMT));
			 if (cols == NULL)
			 {
			    fprintf(stderr, "ex_fetch_data: malloc() failed");
			    free(col_data);
			    return CS_MEM_ERROR;
			 }
			
			
			// Get column information
			for (i = 0; i < num_cols; i++) {
				rc = ct_describe(cmd, (i+1), &cols[i]);
				if ( rc != CS_SUCCEED ) {
					fprintf(stderr, "ct_describe failed on col #%d", i+1);
				}

				column_value = rb_hash_new();
				// fprintf(stderr, "%s\n", cols[i].name);
				if (cols[i].name) {
					rb_hash_aset(column_value, column_name, rb_str_new2(cols[i].name));
				} else {
					rb_hash_aset(column_value, column_name, Qnil);
				}
				
				rb_hash_aset(column_value, column_type, rb_str_new2(column_type_name(cols[i])));
				rb_hash_aset(column_value, column_size, INT2FIX(cols[i].maxlength));
				rb_hash_aset(column_value, column_scale, INT2FIX(cols[i].scale));
				rb_hash_aset(column_value, column_precision, INT2FIX(cols[i].precision));

				rb_ary_push(columns, column_value);
			}
			
			// Fetch data
			while (((rc = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &rows_read)) == CS_SUCCEED) || (rc == CS_ROW_FAIL)) {
				row_count = row_count + rows_read;

				row = rb_hash_new();
				rb_ary_push(rows, row);
				
				// Create Ruby objects
				for (i = 0; i < num_cols; i++) {
					// if (col_data[i].indicator == -1) {
					// 	rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
					// 	continue;
					// }
					switch (cols[i].datatype) {
					case CS_TINYINT_TYPE:
					case CS_BIT_TYPE:
						data_rc = ct_get_data(cmd, (i + 1), &tempInt, sizeof(tempInt), &output_len);
						if (output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							if(tempInt == 1) {
								rb_hash_aset(row, rb_str_new2(cols[i].name), Qtrue);
							} else {
								rb_hash_aset(row, rb_str_new2(cols[i].name), Qfalse);
							}
						}
						tempInt = -1;
						break;
					case CS_INT_TYPE:
					case CS_SMALLINT_TYPE:
						data_rc = ct_get_data(cmd, (i + 1), &tempInt, sizeof(tempInt), &output_len);
						if (output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							rb_hash_aset(row, rb_str_new2(cols[i].name), INT2FIX(tempInt));
						}
						tempInt = -1;
						break;
					
					case CS_DATETIME_TYPE:
					case CS_DATETIME4_TYPE:
						data_rc = ct_get_data(cmd, (i + 1), &tempDateTime, sizeof(tempDateTime), &output_len);
						if (output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							if ( cs_dt_crack(conn->context, CS_DATETIME_TYPE, &tempDateTime, &date_rec) == CS_SUCCEED ) {
								if(date_rec.dateyear && date_rec.datemonth && date_rec.datedmonth) {
									date_parts[0] = INT2FIX(date_rec.dateyear);
									date_parts[1] = INT2FIX(date_rec.datemonth+1);
									date_parts[2] = INT2FIX(date_rec.datedmonth);
									date_parts[3] = INT2FIX(date_rec.datehour);
									date_parts[4] = INT2FIX(date_rec.dateminute);
									date_parts[5] = INT2FIX(date_rec.datesecond);
									date_parts[6] = INT2FIX(date_rec.datemsecond);
									date_parts[7] = INT2FIX(date_rec.datetzone);
							
									// String (fastest known so far, but pushes the burden to ActiveRecord for parsing)
									sprintf(output, "%d-%02d-%02d %02d:%02d:%02d.%03d", date_rec.dateyear, date_rec.datemonth+1, date_rec.datedmonth, date_rec.datehour, date_rec.dateminute, date_rec.datesecond, date_rec.datemsecond);
									rb_hash_aset(row, rb_str_new2(cols[i].name), rb_str_new2(output));
								
									// DateTime - this is slow a f*ck
									//rb_hash_aset(row, rb_str_new2(cols[i].name), rb_funcall2(rb_DateTime, rb_intern("civil"), 6, &date_parts[0]));
								
									// Time - way faster than DateTime
									// FIXME: should we be assuming utc?!
									// rb_hash_aset(row, rb_str_new2(cols[i].name), rb_funcall2(rb_cTime, rb_intern("utc"), 6, &date_parts[0]));
								} else {
									rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
								}
							} else {
								fprintf(stderr, "cs_dt_crack failed\n");
							}
						}
						// tempDateTime = 0; // not sure how to clear this...
						break;
					
					// case CS_REAL_TYPE:
					case CS_FLOAT_TYPE:
					// case CS_MONEY_TYPE:
					// case CS_MONEY4_TYPE: 
						data_rc = ct_get_data(cmd, (i + 1), &tempDouble, sizeof(tempDouble), &output_len);
						if (output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							rb_hash_aset(row, rb_str_new2(cols[i].name), rb_float_new(tempDouble));
						}
						tempDouble = -1.0;
						break;
					
					// case CS_BIGINT_TYPE:
					// 	error_message("HELLO BIGINT!");
					// 	break;
						
					case CS_DECIMAL_TYPE:
					case CS_NUMERIC_TYPE:
						// fprintf(stderr, "CS_NUMERIC_TYPE detected - name: %s\n", cols[i].name);
						
						data_rc = ct_get_data(cmd, (i + 1), &tempNumeric, sizeof(tempNumeric), &output_len);
						if (output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							// fprintf(stderr, "tempNumeric output_len: %d, precision: %d, scale: %d, array: %s\n", output_len, tempNumeric.precision, tempNumeric.scale, tempNumeric.array);
							col.datatype = CS_CHAR_TYPE;
							col.format = CS_FMT_NULLTERM;
							col.maxlength = 200;
							// col.maxlength = cols[i].precision + 1;
							data_rc = cs_convert(conn->context, &cols[i], &tempNumeric, &col, output, &output_len);
							if ( data_rc != CS_SUCCEED ) {
								error_message("CS_NUMERIC_TYPE conversion failed");
								fprintf(stderr, "cs_convert returned: %d\n", data_rc);
							}
							// fprintf(stderr, "numeric output_len: %d, output: %s\n", output_len, output);
							rb_hash_aset(row, rb_str_new2(cols[i].name), LL2NUM(strtoll(output, NULL, 10)));
						}
						break;
						
					case CS_CHAR_TYPE:
					case CS_LONGCHAR_TYPE:
					case CS_TEXT_TYPE:
					case CS_VARCHAR_TYPE:
					case CS_UNICHAR_TYPE:
					case CS_UNIQUE_TYPE: // @todo should this one be handled differently?
						isNull = 0;
						tempTextLen = 1; // 1 for \0
						do {
							newTempText = realloc((tempTextLen == 1 ? NULL : tempText), tempTextLen + (1000 * sizeof(char))); // allocate another 1000 chars
							if (newTempText != NULL) {
								tempText = newTempText;
							} else {
								fprintf(stderr, "realloc error\n");
							}
							
							data_rc = ct_get_data(cmd, (i + 1), tempText + tempTextLen - 1, 1000, &output_len);

							if (tempTextLen == 1 && output_len == 0 && (data_rc == CS_END_DATA || data_rc == CS_END_ITEM)) {
								isNull = 1;
							}
								
							tempTextLen = tempTextLen + output_len;
						} while (data_rc == CS_SUCCEED);
						if (data_rc != CS_END_DATA && data_rc != CS_END_ITEM)
						{
							fprintf(stderr, "ct_get_data failed, data_rc = %d\n", data_rc);
							return data_rc;
						}
						tempText[tempTextLen-1] = '\0';
						if (isNull == 1) {
							rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						} else {
							rb_hash_aset(row, rb_str_new2(cols[i].name), rb_str_new2(tempText));
						}
						
						free(tempText);
						tempText = NULL;
						break;
					
					case CS_BINARY_TYPE:
					case CS_LONGBINARY_TYPE:
					case CS_VARBINARY_TYPE:
					case CS_IMAGE_TYPE:
						// rb_hash_aset(row, rb_str_new2(tds->res_info->columns[i]->column_name), rb_str_new((char *) ((TDSBLOB *) src)->textvalue, tds->res_info->columns[i]->column_cur_size));						
						rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						break;

					default:
						rb_hash_aset(row, rb_str_new2(cols[i].name), Qnil);
						printf("\nUnexpected datatype: %d\n", cols[i].datatype);
					}

				
				}
			}
			
			if( rc != CS_END_DATA )
			{
			    fprintf(stderr, "ct_fetch failed");
			}
			
			free(cols);
			cols = NULL;
			free(col_data);
			col_data = NULL;
			
			break;
		case CS_CMD_SUCCEED:
			rb_iv_set(self, "@status", Qnil);
			break;
		case CS_CMD_FAIL:
			if ( ct_diag(conn->connection, CS_STATUS, CS_SERVERMSG_TYPE, CS_UNUSED, &num_errors) != CS_SUCCEED ) {
				error_message("ct_diag CS_STATUS CS_SERVERMSG_TYPE failed");
			}
			if (num_errors > 0) {
				// fprintf(stderr, "%d errors found\n", num_errors);
				for (i = 0; i < num_errors; i++) {
					if ( ct_diag(conn->connection, CS_GET, CS_SERVERMSG_TYPE, i+1, &servermsg) != CS_SUCCEED ) {
						error_message("ct_diag CS_GET CS_SERVERMSG_TYPE failed");
					}
					if (servermsg.severity > 0) {
						// error_message(servermsg.text);
						rb_ary_push(errors, rb_str_new2(servermsg.text));
					}
				}
				if ( ct_diag(conn->connection, CS_CLEAR, CS_SERVERMSG_TYPE, CS_UNUSED, NULL) != CS_SUCCEED ) {
					error_message("ct_diag CS_CLEAR CS_SERVERMSG_TYPE failed");
				}
			}
		
			err = rb_funcall(errors, rb_intern("first"), 0); // FIXME: should probably display all errors instead of just first
			if(RTEST(err)) {
				error_msg = value_to_cstr(err);
				rb_raise(rb_eIOError, error_msg);
			} else {
				rb_raise(rb_eIOError, "CS_CMD_FAIL without server error message");
			}
			// rb_iv_set(self, "@status", INT2FIX(0));
			break;
		case CS_CMD_DONE:
			rb_iv_set(self, "@status", Qnil);
			break;
		case CS_STATUS_RESULT:
			// FIXME: We should probably do something here, right?
			break;
		default:
			fprintf(stderr, "ct_results returned unexpected result type: %d\n", resulttype);
			break;
		}
	}

	ct_cmd_drop(cmd);
	
	return Qnil;	
}
Exemple #4
0
CS_RETCODE CTL_RowResult::my_ct_get_data(CS_COMMAND* cmd,
                                         CS_INT item,
                                         CS_VOID* buffer,
                                         CS_INT buflen,
                                         CS_INT *outlen,
                                         bool& is_null)
{
    CheckIsDead();

    is_null = false;

    if(item > m_BindedCols) {
        // Not bound ...
        CS_RETCODE rc = Check(ct_get_data(cmd, item, buffer, buflen, outlen));
        if ((rc == CS_END_ITEM || rc == CS_END_DATA)) {
            if (outlen) {
#ifdef FTDS_IN_USE
                if (*outlen == -1) {
                    is_null = true;
                    *outlen = 0;
                }
                else
                    is_null = false;
#else
                is_null = (*outlen == 0);
#endif
            }
        }
        return rc;
    }

    // Bound ...
    // Move data ...

    --item;

    CS_SMALLINT   indicator = m_Indicator[item];
    CS_INT        copied = m_Copied[item];

    //   if((m_Indicator[item] < 0) || ((CS_INT)m_Indicator[item] >= m_Copied[item])) {
    if(indicator < 0) {
        // Value is NULL ...
        is_null = true;

        if(outlen) {
            *outlen = 0;
        }

        return CS_END_ITEM;
    }

    if(!buffer || (buflen < 1)) {
        return CS_SUCCEED;
    }

    CS_INT n = copied - indicator;

    if(buflen > n) {
        buflen = n;
    }

    memcpy(buffer, (char*)(m_BindItem[item]) + indicator, buflen);

    if(outlen) {
        *outlen = buflen;
    }

    m_Indicator[item] += static_cast<CS_SMALLINT>(buflen);

    return (n == buflen) ? CS_END_ITEM : CS_SUCCEED;
}