📄 wide_compute.c
字号:
/*
** Drop our command structure
*/
if ((retcode = ct_cmd_drop(cmd)) != CS_SUCCEED)
{
ex_error("DoCompute: ct_cmd_drop() failed");
return retcode;
}
return retcode;
}
/*
** FetchComputeResults()
**
** Type of function:
** compute program internal api
**
** Purpose:
** This function processes compute results. It is called by DoCompute()
** when the type of result is CS_COMPUTE_RESULT. We could have used
** ex_fetch_data(), but the display header would not have reflected
** the compute operator used.
**
** Parameters:
** cmd - Pointer to command structure
**
** Return:
** CS_MEM_ERROR If an memory allocation failed.
** CS_SUCCEED If the data was displayed.
** CS_FAIL If no columns were present.
** <retcode> Result of the Client-Library function if a failure was
** returned.
*/
CS_STATIC CS_RETCODE CS_INTERNAL
FetchComputeResults(cmd)
CS_COMMAND *cmd;
{
CS_RETCODE retcode;
CS_INT num_cols;
CS_INT i;
CS_INT j;
CS_INT agg_op;
CS_CHAR *agg_op_name;
CS_INT row_count = 0;
CS_INT rows_read;
CS_INT outlen;
CS_DATAFMT *datafmt;
EX_COLUMN_DATA *coldata;
/*
** Find out how many columns there are in this result set.
*/
retcode = ct_res_info(cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL);
if (retcode != CS_SUCCEED)
{
ex_error("FetchComputeResults: ct_res_info() failed");
return retcode;
}
/*
** Make sure we have at least one column
*/
if (num_cols <= 0)
{
ex_error("FetchComputeResults: ct_res_info() returned zero columns");
return CS_FAIL;
}
/*
** Our program variable, called 'coldata', is an array of
** EX_COLUMN_DATA structures. Each array element represents
** one column. Each array element will re-used for each row.
**
** First, allocate memory for the data element to process.
*/
coldata = (EX_COLUMN_DATA *)malloc(num_cols * sizeof (EX_COLUMN_DATA));
if (coldata == NULL)
{
ex_error("FetchComputeResults: malloc() failed");
return CS_MEM_ERROR;
}
datafmt = (CS_DATAFMT *)malloc(num_cols * sizeof (CS_DATAFMT));
if (datafmt == NULL)
{
ex_error("FetchComputeResults: malloc() failed");
free(coldata);
return CS_MEM_ERROR;
}
/*
** Loop through the columns getting a description of each one
** and binding each one to a program variable.
**
** We're going to bind each column to the native sql server type.
** When fetching, we'll call ex_display_column() to perform the
** conversion and print out the column value. The column could have
** also been bound to a string, and have Client-Library perform the
** conversion for you. The ex_fetch_data() routine shows this approach.
**
** We're going to use the same datafmt structure for both the describe
** and the subsequent bind.
**
** If an error occurs within the for loop, a break is used to get out
** of the loop and the data that was allocated is free'd before
** returning.
*/
for (i = 0; i < num_cols; i++)
{
/*
** Get the column description. ct_describe() fills the
** datafmt parameter with a description of the column.
*/
retcode = ct_describe(cmd, (i + 1), &datafmt[i]);
if (retcode != CS_SUCCEED)
{
ex_error("FetchComputeResults: ct_describe() failed");
break;
}
/*
** Let's find out what aggregate operator was used for this
** column.
*/
retcode = ct_compute_info(cmd, CS_COMP_OP, (i + 1), &agg_op,
CS_UNUSED, &outlen);
if (retcode != CS_SUCCEED)
{
ex_error("FetchComputeResults: ct_compute_info() failed");
return retcode;
}
/*
** Get a string that represents the aggregate operator.
*/
agg_op_name = GetAggOp(agg_op);
/*
** Copy it into the name portion of the datafmt structure.
** The ex_display_header() routine will then use this as
** the name to display.
*/
strcpy(datafmt[i].name, agg_op_name);
/*
** Allocate memory for the column data element based on the
** above describe.
*/
coldata[i].value = (CS_CHAR *)malloc(datafmt[i].maxlength);
if (coldata[i].value == NULL)
{
ex_error("FetchComputeResults: malloc() failed");
retcode = CS_MEM_ERROR;
break;
}
/*
** Now bind.
*/
retcode = ct_bind(cmd, (i + 1), &datafmt[i],
coldata[i].value, &coldata[i].valuelen,
(CS_SMALLINT *)&coldata[i].indicator);
if (retcode != CS_SUCCEED)
{
ex_error("FetchComputeResults: ct_describe() failed");
break;
}
}
if (retcode != CS_SUCCEED)
{
for (j = 0; j < i; j++)
{
free(coldata[j].value);
}
free(coldata);
free(datafmt);
return retcode;
}
/*
** Display column header
*/
ex_display_header(num_cols, datafmt);
/*
** Fetch the rows. Loop while ct_fetch() returns CS_SUCCEED or
** CS_ROW_FAIL
*/
while (((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&rows_read)) == CS_SUCCEED) || (retcode == CS_ROW_FAIL))
{
/*
** Increment our row count by the number of rows just fetched.
*/
row_count = row_count + rows_read;
/*
** Check if we hit a recoverable error.
*/
if (retcode == CS_ROW_FAIL)
{
fprintf(stdout, "Error on row %d.\n", row_count);
fflush(stdout);
}
/*
** We have a row. Loop through the columns displaying the
** column values.
*/
for (i = 0; i < num_cols; i++)
{
ex_display_column(Ex_context, &datafmt[i],
coldata[i].value,
coldata[i].valuelen,
coldata[i].indicator);
}
fprintf(stdout, "\n");
fflush(stdout);
}
/*
** Free allocated space.
*/
for (i = 0; i < num_cols; i++)
{
free(coldata[i].value);
}
free(coldata);
free(datafmt);
/*
** We're done processing rows. Let's check the final return
** value of ct_fetch().
*/
switch ((int)retcode)
{
case CS_END_DATA:
/*
** Everything went fine.
*/
fprintf(stdout, "All done processing compute rows.\n");
fflush(stdout);
retcode = CS_SUCCEED;
break;
case CS_FAIL:
/*
** Something terrible happened.
*/
ex_error("FetchComputeResults: ct_fetch() failed");
return retcode;
break;
default:
/*
** We got an unexpected return value.
*/
ex_error("FetchComputeResults: ct_fetch() returned an expected retcode");
return retcode;
break;
}
return retcode;
}
/*
** GetAggOp(op)
**
** Purpose:
** This function takes an aggregate operator type and returns
** a string representing that type. E.g. if the type is
** CS_OP_SUM, the returned string is "sum".
**
** Parameters:
** op - the aggregate operator type (a symbolic value)
**
** Return:
** A pointer to the string name.
*/
CS_STATIC CS_CHAR * CS_INTERNAL
GetAggOp(op)
CS_INT op;
{
CS_CHAR *name;
switch ((int)op)
{
case CS_OP_SUM:
name = "sum";
break;
case CS_OP_AVG:
name = "avg";
break;
case CS_OP_COUNT:
name = "count";
break;
case CS_OP_MIN:
name = "min";
break;
case CS_OP_MAX:
name = "max";
break;
default:
name = "unknown";
break;
}
return name;
}
/*
** DoCommand(connection)
**
** Type of function:
** compute program internal api
**
** Purpose:
** This function sends a commands to create a database, create a table,
** insert row into the table and select rows from the table. It
** then processes the results in the standard ct_results() loop.
** This function is added to test XNL/Wide & More column feature.
**
** Parameters:
** connection - Pointer to connection structure
** statement - An CS_INT to differentite between different command.
**
** Return:
** CS_SUCCEED if processed correctly
** Otherwise a Client-Library failure code.
**
*/
CS_STATIC CS_RETCODE CS_INTERNAL
DoCommand(connection, statement)
CS_CONNECTION *connection;
CS_INT statement;
{
CS_RETCODE retcode;
CS_COMMAND *cmd;
CS_INT res_type; /* result type from ct_results */
/*
** Allocate a command handle to send the compute query with
*/
if ((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED)
{
ex_error("DoCommand: ct_cmd_alloc() failed");
return retcode;
}
/*
** Make sure you are in the master database
*/
if ((retcode = ex_use_db(connection, "master")) != CS_SUCCEED)
{
ex_error("DoCompute: ex_use_db(master) failed");
return retcode;
}
/*
** Create required databases
*/
if (statement == DATABASE)
{
retcode = ct_command(cmd, CS_LANG_CMD, CREATEDB, CS_NULLTERM,
CS_UNUSED);
}
else if (statement == TABLE)
{
retcode = ct_command(cmd, CS_LANG_CMD, CREATETBL1, CS_NULLTERM,
CS_MORE);
retcode = ct_command(cmd, CS_LANG_CMD, CREATETBL2, CS_NULLTERM,
CS_END);
}
else if (statement == INSERTROW)
{
if ((retcode = ex_use_db(connection, Ex_dbname)) != CS_SUCCEED)
{
ex_error("DoCompute: ex_use_db(XNL_TEST) failed");
return retcode;
}
retcode = ct_command(cmd, CS_LANG_CMD, INSERT, CS_NULLTERM,
CS_UNUSED);
}
/* This is the SELECT2 command, where statement is equal to SELECT */
else
{
if ((retcode = ex_use_db(connection, Ex_dbname)) != CS_SUCCEED)
{
ex_error("DoCompute: ex_use_db(XNL_TEST) failed");
return retcode;
}
retcode = ct_command(cmd, CS_LANG_CMD, SELECT2, CS_NULLTERM,
CS_UNUSED);
}
if (retcode != CS_SUCCEED)
{
ex_error("DoCommand: ct_command() failed");
return retcode;
}
/*
** Send the command to the server
*/
if (ct_send(cmd) != CS_SUCCEED)
{
ex_error("DoCommand: ct_send() failed");
return retcode;
}
/*
** Process the results. Loop while ct_results() returns CS_SUCCEED.
*/
while ((retcode = ct_results(cmd, &res_type)) == CS_SUCCEED)
{
switch ((int)res_type)
{
case CS_CMD_SUCCEED:
/*
** This means no rows were returned.
*/
break;
case CS_CMD_DONE:
/*
** This means we're done with one result set.
*/
break;
case CS_CMD_FAIL:
/*
** This means that the server encountered an error while
** processing our command.
*/
ex_error("DoCommand: ct_results() returned CMD_FAIL");
break;
case CS_ROW_RESULT:
retcode = ex_fetch_data(cmd);
if (retcode != CS_SUCCEED)
{
ex_error("DoCommand: ex_fetch_data() failed");
return retcode;
}
break;
case CS_COMPUTE_RESULT:
retcode = FetchComputeResults(cmd);
if (retcode != CS_SUCCEED)
{
ex_error("DoCommand: FetchComputeResults() failed");
return retcode;
}
break;
default:
/*
** We got an unexpected result type.
*/
ex_error("DoCommand: ct_results() returned unexpected result type");
return CS_FAIL;
}
}
/*
** We're done processing results. Let's check the
** return value of ct_results() to see if everything
** went ok.
*/
switch ((int)retcode)
{
case CS_END_RESULTS:
/*
** Everything went fine.
*/
break;
case CS_FAIL:
/*
** Something went wrong.
*/
ex_error("DoCommand: ct_results() failed");
return retcode;
default:
/*
** We got an unexpected return value.
*/
ex_error("DoCommand: ct_results() returned unexpected result code");
return retcode;
}
/*
** Drop our command structure
*/
if ((retcode = ct_cmd_drop(cmd)) != CS_SUCCEED)
{
ex_error("DoCommand: ct_cmd_drop() failed");
return retcode;
}
return retcode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -