📄 exutils.c
字号:
/*
** ex_con_cleanup()
**
** Type of function:
** example program utility api
**
** Purpose:
** The routine closes a connection and deallocates the
** CS_CONNECTION structure.
**
** Parameters:
** connection - Pointer to connection structure.
** status - status of last interaction with this Client-Library
** If not ok, this routine will perform a force close.
**
** Returns:
** Result of function calls from CT-Lib.
*/
CS_RETCODE CS_PUBLIC
ex_con_cleanup(connection, status)
CS_CONNECTION *connection;
CS_RETCODE status;
{
CS_RETCODE retcode;
CS_INT close_option;
close_option = (status != CS_SUCCEED) ? CS_FORCE_CLOSE : CS_UNUSED;
retcode = ct_close(connection, close_option);
if (retcode != CS_SUCCEED)
{
ex_error("ex_con_cleanup: ct_close() failed");
return retcode;
}
retcode = ct_con_drop(connection);
if (retcode != CS_SUCCEED)
{
ex_error("ex_con_cleanup: ct_con_drop() failed");
return retcode;
}
return retcode;
}
/*
** ex_ctx_cleanup()
**
** Type of function:
** example program utility api
**
** Purpose:
** The routine exits Client-Library deallocates the
** CS_CONTEXT structure.
**
** Parameters:
** context - Pointer to context structure.
** status - status of last interaction with Client-Library.
** If not ok, this routine will perform a force exit.
**
** Returns:
** Result of function calls from CT-Lib.
*/
CS_RETCODE CS_PUBLIC
ex_ctx_cleanup(context, status)
CS_CONTEXT *context;
CS_RETCODE status;
{
CS_RETCODE retcode;
CS_INT exit_option;
exit_option = (status != CS_SUCCEED) ? CS_FORCE_EXIT : CS_UNUSED;
retcode = ct_exit(context, exit_option);
if (retcode != CS_SUCCEED)
{
ex_error("ex_ctx_cleanup: ct_exit() failed");
return retcode;
}
retcode = cs_ctx_drop(context);
if (retcode != CS_SUCCEED)
{
ex_error("ex_ctx_cleanup: cs_ctx_drop() failed");
return retcode;
}
return retcode;
}
/*
** ex_execute_cmd()
**
** Type of function:
** example program utility api
**
** Purpose:
** This routine sends a language command to the server. It expects no
** rows or parameters to be returned from the server.
**
** Parameters:
** connection - Pointer to CS_COMMAND structure.
** cmdbuf - The buffer containing the command.
**
** Return:
** Result of functions called in CT-Lib
*/
CS_RETCODE CS_PUBLIC
ex_execute_cmd(connection, cmdbuf)
CS_CONNECTION *connection;
CS_CHAR *cmdbuf;
{
CS_RETCODE retcode;
CS_INT restype;
CS_COMMAND *cmd;
CS_RETCODE query_code;
/*
** Get a command handle, store the command string in it, and
** send it to the server.
*/
if ((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_cmd_alloc() failed");
return retcode;
}
if ((retcode = ct_command(cmd, CS_LANG_CMD, cmdbuf, CS_NULLTERM,
CS_UNUSED)) != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_command() failed");
(void)ct_cmd_drop(cmd);
return retcode;
}
if ((retcode = ct_send(cmd)) != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_send() failed");
(void)ct_cmd_drop(cmd);
return retcode;
}
/*
** Examine the results coming back. If any errors are seen, the query
** result code (which we will return from this function) will be
** set to FAIL.
*/
query_code = CS_SUCCEED;
while ((retcode = ct_results(cmd, &restype)) == CS_SUCCEED)
{
switch((int)restype)
{
case CS_CMD_SUCCEED:
case CS_CMD_DONE:
break;
case CS_CMD_FAIL:
query_code = CS_FAIL;
break;
case CS_STATUS_RESULT:
retcode = ct_cancel(NULL, cmd, CS_CANCEL_CURRENT);
if (retcode != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_cancel() failed");
query_code = CS_FAIL;
}
break;
default:
/*
** Unexpected result type.
*/
query_code = CS_FAIL;
break;
}
if (query_code == CS_FAIL)
{
/*
** Terminate results processing and break out of
** the results loop
*/
retcode = ct_cancel(NULL, cmd, CS_CANCEL_ALL);
if (retcode != CS_SUCCEED)
{
ex_error("ex_execute_cmd: ct_cancel() failed");
}
break;
}
}
/*
** Clean up the command handle used
*/
if (retcode == CS_END_RESULTS)
{
retcode = ct_cmd_drop(cmd);
if (retcode != CS_SUCCEED)
{
query_code = CS_FAIL;
}
}
else
{
(void)ct_cmd_drop(cmd);
query_code = CS_FAIL;
}
return query_code;
}
/*
** ex_fetch_data()
**
** Type of function:
** example program utility api
**
** Purpose:
** This function processes fetchable results sets. The results include:
**
** CS_ROW_RESULT
** CS_CURSOR_RESULT
** CS_PARAM_RESULT
** CS_STATUS_RESULT
** CS_COMPUTE_RESULT
**
** Since the Client-Library result model has been unified, the same
** apis are used for each of the above result types.
**
** One caveat is the processing of CS_COMPUTE_RESULTs. The name field
** sent from the server is typically zero length. To display a meaningful
** header, the aggregate compute operator name should be found for the
** column, and that name used instead. The compute example program has
** code which demonstrates this.
**
** 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_RETCODE CS_PUBLIC
ex_fetch_data(cmd)
CS_COMMAND *cmd;
{
CS_RETCODE retcode;
CS_INT num_cols;
CS_INT i;
CS_INT j;
CS_INT row_count = 0;
CS_INT rows_read;
CS_INT disp_len;
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("ex_fetch_data: ct_res_info() failed");
return retcode;
}
/*
** Make sure we have at least one column
*/
if (num_cols <= 0)
{
ex_error("ex_fetch_data: 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("ex_fetch_data: malloc() failed");
return CS_MEM_ERROR;
}
datafmt = (CS_DATAFMT *)malloc(num_cols * sizeof (CS_DATAFMT));
if (datafmt == NULL)
{
ex_error("ex_fetch_data: 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 a character string;
** this will show how conversions from server native datatypes
** to strings can occur via bind.
**
** 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("ex_fetch_data: ct_describe() failed");
break;
}
/*
** update the datafmt structure to indicate that we want the
** results in a null terminated character string.
**
** First, update datafmt.maxlength to contain the maximum
** possible length of the column. To do this, call
** ex_display_len() to determine the number of bytes needed
** for the character string representation, given the
** datatype described above. Add one for the null
** termination character.
*/
datafmt[i].maxlength = ex_display_dlen(&datafmt[i]) + 1;
/*
** Set datatype and format to tell bind we want things
** converted to null terminated strings
*/
datafmt[i].datatype = CS_CHAR_TYPE;
datafmt[i].format = CS_FMT_NULLTERM;
/*
** Allocate memory for the column string
*/
coldata[i].value = (CS_CHAR *)malloc(datafmt[i].maxlength);
if (coldata[i].value == NULL)
{
ex_error("ex_fetch_data: 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("ex_fetch_data: ct_bind() 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++)
{
/*
** Display the column value
*/
fprintf(stdout, "%s", coldata[i].value);
fflush(stdout);
/*
** If not last column, Print out spaces between this
** column and next one.
*/
if (i != num_cols - 1)
{
disp_len = ex_display_dlen(&datafmt[i]);
disp_len -= coldata[i].valuelen - 1;
for (j = 0; j < disp_len; j++)
{
fputc(' ', stdout);
}
}
}
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 rows.\n");
fflush(stdout);
retcode = CS_SUCCEED;
break;
case CS_FAIL:
/*
** Something terrible happened.
*/
ex_error("ex_fetch_data: ct_fetch() failed");
return retcode;
/*NOTREACHED*/
break;
default:
/*
** We got an unexpected return value.
*/
ex_error("ex_fetch_data: ct_fetch() returned an expected retcode");
return retcode;
/*NOTREACHED*/
break;
}
return retcode;
}
/*****************************************************************************
**
** sql based functions
**
*****************************************************************************/
/*
** ex_create_db()
**
** Type of function:
** example program utility api
**
** Purpose:
** This routine creates a database and opens it. It first checks
** that the database does not already exists. If it does exist
** the database is dropped before creating a new one.
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
** dbname - The name to be used for the created database.
**
** Return:
** Result of functions called in CT-Lib.
**
*/
CS_RETCODE CS_PUBLIC
ex_create_db(connection, dbname)
CS_CONNECTION *connection;
char *dbname;
{
CS_RETCODE retcode;
CS_CHAR *cmdbuf;
/*
** If the database already exists, drop it.
*/
if ((retcode = ex_remove_db(connection, dbname)) != CS_SUCCEED)
{
ex_error("ex_create_db: ex_remove_db() failed");
}
/*
** Allocate the buffer for the command string.
*/
cmdbuf = (CS_CHAR *) malloc(EX_BUFSIZE);
if (cmdbuf == (CS_CHAR *)NULL)
{
ex_error("ex_create_db: malloc() failed");
return CS_FAIL;
}
/*
** Set up and send the command to create the database.
*/
sprintf(cmdbuf, "create database %s", dbname);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("ex_create_db: ex_execute_cmd(create db) failed");
}
free(cmdbuf);
return retcode;
}
/*
** ex_remove_db()
**
** Type of function:
** example program utility api
**
** Purpose:
** This routine removes a database. It first checks that
** the database exists, and if so, removes it.
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
** dbname - The name of the database to remove.
**
** Return:
** Result of functions called in CT-Lib or CS_FAIL if a malloc failure
** occurred.
*/
CS_RETCODE
ex_remove_db(connection, dbname)
CS_CONNECTION *connection;
char *dbname;
{
CS_RETCODE retcode;
CS_CHAR *cmdbuf;
/*
** Connect to the master database in order to
** remove the specified database.
*/
if ((retcode = ex_use_db(connection, "master")) != CS_SUCCEED)
{
ex_error("ex_remove_db: ex_use_db(master) failed");
return retcode;
}
/*
** Allocate the buffer for the command string.
*/
cmdbuf = (CS_CHAR *) malloc(EX_BUFSIZE);
if (cmdbuf == (CS_CHAR *)NULL)
{
ex_error("ex_remove_db: malloc() failed");
return CS_FAIL;
}
/*
** Set up and send the command to check for and drop the
** database if it exists.
*/
sprintf(cmdbuf,
"if exists (select name from sysdatabases where name = \"%s\") \
drop database %s", dbname, dbname);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("ex_remove_db: ex_execute_cmd(drop db) failed");
}
free(cmdbuf);
return retcode;
}
/*
** ex_use_db()
**
** Type of function:
** example program utility api
**
** Purpose:
** This routine changes the current database to the named db passed in.
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
** dbname - The name of the database to use.
**
** Return:
** Result of functions called in CT-Lib or CS_FAIL if a malloc failure
** occured.
*/
CS_RETCODE
ex_use_db(connection, dbname)
CS_CONNECTION *connection;
char *dbname;
{
CS_RETCODE retcode;
CS_CHAR *cmdbuf;
/*
** Allocate the buffer for the command string.
*/
cmdbuf = (CS_CHAR *) malloc(EX_BUFSIZE);
if (cmdbuf == (CS_CHAR *)NULL)
{
ex_error("ex_use_db: malloc() failed");
return CS_FAIL;
}
/*
** Set up and send the command to use the database
*/
sprintf(cmdbuf, "use %s\n", dbname);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("ex_use_db: ex_execute_cmd(use db) failed");
}
free(cmdbuf);
return retcode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -