📄 getsend.c
字号:
/*
** CT_GET_DATA/CT_SEND_DATA EXAMPLE PROGRAM
** ---------------------------------------------
**
** Description
** -----------
** This example program demonstrates how to retrieve
** and update text data from a table containing text along
** with other datatypes. The process demonstrated could
** also be used for retrieving and updating image data.
**
** The example uses standard ANSI C library routines for input/output
** and memory management.
**
** All work is performed synchronously.
**
** Routines Used
** -------------
** All the required routines required for establishing and closing
** a connection to a server, sending a language command to a
** server, and processing row results.
**
** In addition, the following routines were used to demonstrate
** text/image data manipulation:
**
** ct_get_data()
** ct_getdata_info()
** ct_send_data()
** ct_describe()
**
** Input
** -----
** No input is required. Information normally required
** from the user is retrieved from global variables defined
** in the example header files.
**
** Output
** ------
** The example program displays the text data it retrieved
** prior to and after the update of the text field. The retrieved
** data is compared to the text the example expected from the
** retrieve. A message is displayed indicating if the data retrieved
** is the expected text. This output is directed to stdout.
**
** Messages from the server and error messages from the
** Server and Client-Library are directed to stderr.
**
** Server Dependencies
** -------------------
** If connecting to an Open Server, the Open Server must be able
** to handle language commands intended for a SQL Server.
**
** Server Version
** --------------
** 5.0, 4.9.5, 4.9.1
**
**
** Server Tables
** -------------
** This example will create a table with the following
** definition in a database created by the example:
**
** create table xxx (i1 int, t text, f float, i2 int)
**
** The example will insert a single row into the table.
** The example will drop the database it created.
**
** Algorithm
** ----------
** Initialize Client-Library.
**
** install message handling callbacks.
**
** Establish two connections. One connection will be used for
** retrieving data while the other connection will be used to do
** the update of the text data.
**
** Create the database and the table, and initialize the table.
**
** Retrieve the text data from the newly created table and retrieve
** the timestamp for the text data.
**
** Display the data and validate that it is the expected value.
**
** Update the text data with a new text value with the second connection.
**
** Retrieve the text data from the newly created table and retrieve
** the timestamp for the text data.
**
** Display the data and validate hat it is the expected value.
**
** Repeat the update, retrieve, and display operations for a final time.
**
** Perform cleanup by dropping the database and the connection,
** deallocating memory allocated for commands, connections, and
** contexts, and exiting Client-Library.
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctpublic.h>
#include "example.h"
#include "exutils.h"
#if !lint
static char Sccsid[] = {"%Z% %M% %I% %G%"};
#endif /* !lint */
/*****************************************************************************
**
** defines and globals used.
**
*****************************************************************************/
/*
** Global names used in this module
*/
CS_CHAR *Ex_appname = "getsend_example";
CS_CHAR *Ex_dbname = "sampledb";
CS_CHAR *Ex_tabname = "sampletext";
CS_CHAR *Ex_server = EX_SERVER;
CS_CHAR *Ex_username = EX_USERNAME;
CS_CHAR *Ex_password = EX_PASSWORD;
/*
** Define what text values that we will manipulate
*/
#define EX_TXT_INIT_VALUE "This is the initial value of the text field"
#define EX_TXT_UPD1_VALUE "This is the text value after the first update"
#define EX_TXT_UPD2_VALUE "The second update changed the text to this"
/*
** The maximum length of text that this example program may use
*/
#define EX_MAX_TEXT 255
/*
** Define a structure used in managing the text data
*/
typedef struct _text_data
{
CS_IODESC iodesc; /* iodesc associated with text value */
CS_TEXT textbuf[EX_MAX_TEXT]; /* holds the value */
CS_INT textlen; /* number of bytes in textbuf */
} TEXT_DATA;
/*
** Prototypes for routines in the example code.
*/
CS_STATIC CS_RETCODE CreateDatabase PROTOTYPE((
CS_CONNECTION *connection1,
CS_CONNECTION *connection2
));
CS_STATIC CS_RETCODE RemoveDatabase PROTOTYPE((
CS_CONNECTION *connection1,
CS_CONNECTION *connection2
));
CS_STATIC CS_RETCODE CreateTable PROTOTYPE((
CS_CONNECTION *connection
));
CS_STATIC CS_INT DoGetSend PROTOTYPE((
CS_CONNECTION *connection1,
CS_CONNECTION *connection2
));
CS_STATIC CS_RETCODE RetrieveData PROTOTYPE((
CS_CONNECTION *connection,
TEXT_DATA *textdata
));
CS_STATIC CS_RETCODE FetchResults PROTOTYPE((
CS_COMMAND *cmd,
TEXT_DATA *textdata
));
CS_STATIC CS_RETCODE UpdateTextData PROTOTYPE((
CS_CONNECTION *connection,
TEXT_DATA *textdata,
char *newdata
));
CS_STATIC CS_RETCODE ProcessTimestamp PROTOTYPE((
CS_COMMAND *cmd,
TEXT_DATA *textdata
));
CS_STATIC CS_VOID ValidateTxt PROTOTYPE((
TEXT_DATA *textdata,
char *valid_str
));
CS_STATIC CS_VOID DisplayData PROTOTYPE((
TEXT_DATA *textdata
));
/*
** main()
**
** Purpose:
** Entry point for example program.
**
** Parameters:
** None, argc and argv will not be used.
**
** Return:
** EX_EXIT_ERROR or EX_EXIT_SUCCEED
**
*/
int
main()
{
CS_CONTEXT *context;
CS_CONNECTION *connection1 = NULL;
CS_CONNECTION *connection2 = NULL;
CS_RETCODE retcode;
EX_SCREEN_INIT();
fprintf(stdout,"Get/Send Text Example\n");
fflush(stdout);
/*
** Allocate a context structure and initialize Client-Library
*/
retcode = ex_init(&context);
if (retcode != CS_SUCCEED)
{
ex_panic("ex_init failed");
}
/*
** Establish two connections. Connection1 is used to
** select data. Connection2 is used for doing updates.
** Allocate the connection structure, set their properties, and
** establish the connections.
*/
retcode = ex_connect(context, &connection1, Ex_appname,
Ex_username, Ex_password, Ex_server);
if (retcode == CS_SUCCEED)
{
retcode = ex_connect(context, &connection2, Ex_appname,
Ex_username, Ex_password, Ex_server);
}
/*
** Create a database for the sample program and change to it. The
** routine will use the global variable Ex_dbname, which is defined in
** the sample header file.
*/
if (retcode == CS_SUCCEED)
{
retcode = CreateDatabase(connection1, connection2);
if (retcode != CS_SUCCEED)
{
ex_error("getsend: ex_create_db() failed");
}
}
/*
** Create a table for the example.
*/
if (retcode == CS_SUCCEED)
{
retcode = CreateTable(connection1);
}
/*
** Execute the routines for the getsend sample
*/
if (retcode == CS_SUCCEED)
{
retcode = DoGetSend(connection1, connection2);
}
/*
** Remove the sample database.
*/
if (retcode == CS_SUCCEED)
{
retcode = RemoveDatabase(connection1, connection2);
}
/*
** Deallocate the allocated structures, close the connection,
** and exit Client-Library.
*/
if (connection1 != NULL)
{
retcode = ex_con_cleanup(connection1, retcode);
}
if (connection2 != NULL)
{
retcode = ex_con_cleanup(connection2, retcode);
}
if (context != NULL)
{
retcode = ex_ctx_cleanup(context, retcode);
}
return (retcode == CS_SUCCEED) ? EX_EXIT_SUCCEED : EX_EXIT_FAIL;
}
/*
** CreateDatabase()
**
** Type of function:
** getsend program internal api
**
** Purpose:
** This routine uses ex_create_db() to create a database. It then
** does a ex_use_db() to attach to it.
**
** Parameters:
** connection1 - Pointer to CS_CONNECTION structure.
** connection2 - Pointer to CS_CONNECTION structure.
**
** Return:
** CS_SUCCEED if database was created.
** Otherwise a Client-Library failure code.
*/
CS_STATIC CS_RETCODE
CreateDatabase(connection1, connection2)
CS_CONNECTION *connection1;
CS_CONNECTION *connection2;
{
CS_RETCODE retcode;
/*
** create database
*/
retcode = ex_create_db(connection1, Ex_dbname);
if (retcode != CS_SUCCEED)
{
ex_error("CreateDatabase: ex_create_db() failed");
return retcode;
}
/*
** point both connections to the new database.
*/
if ((retcode = ex_use_db(connection1, Ex_dbname)) != CS_SUCCEED)
{
ex_error("CreateDatabase: ex_use_db(Ex_dbname) failed");
return retcode;
}
if ((retcode = ex_use_db(connection2, Ex_dbname)) != CS_SUCCEED)
{
ex_error("CreateDatabase: ex_use_db(Ex_dbname) failed");
return retcode;
}
return retcode;
}
/*
** RemoveDatabase()
**
** Type of function:
** getsend program internal api
**
** Purpose:
** This routine uses ex_remove_db() to remove a database.
**
** Note: The server will only let us drop a database if there are no
** current users logged in and using it. Since multiple connections
** have been established and are using the sampledb database, we need
** to have them use master before the drop. This could be optimized by
** first closing connection2, then do the remove of the database on
** connection1.
**
** Parameters:
** connection1 - Pointer to CS_CONNECTION structure.
** connection2 - Pointer to CS_CONNECTION structure.
**
** Return:
** CS_SUCCEED if database was removed.
** Otherwise a Client-Library failure code.
*/
CS_STATIC CS_RETCODE
RemoveDatabase(connection1, connection2)
CS_CONNECTION *connection1;
CS_CONNECTION *connection2;
{
CS_RETCODE retcode;
if ((retcode = ex_use_db(connection1, "master")) != CS_SUCCEED)
{
ex_error("RemoveDatabase: ex_use_db(master) failed");
return retcode;
}
if ((retcode = ex_use_db(connection2, "master")) != CS_SUCCEED)
{
ex_error("RemoveDatabase: ex_use_db(master) failed");
return retcode;
}
retcode = ex_remove_db(connection1, Ex_dbname);
if (retcode != CS_SUCCEED)
{
ex_error("getsend: ex_remove_db() failed");
return retcode;
}
return retcode;
}
/*
** CreateTable()
**
** Type of function:
** getsend program internal api
**
** Purpose:
** This routine sets up the table for the getdata operation
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
**
** Return:
** CS_SUCCEED if table was created.
** Otherwise a Client-Library failure code.
*/
CS_STATIC CS_RETCODE
CreateTable(connection)
CS_CONNECTION *connection;
{
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("CreateTable: malloc() failed");
return CS_MEM_ERROR;
}
/*
** If the table exists, drop it.
*/
sprintf(cmdbuf, "if exists (select name from sysobjects \
where name = \"%s\") drop table %s",
Ex_tabname, Ex_tabname);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("CreateTable: ex_execute_cmd(drop table) failed");
free (cmdbuf);
return retcode;
}
/*
** Set up and send the command to create the table.
*/
sprintf(cmdbuf, "create table %s (i1 int, t text, f float, i2 int)",
Ex_tabname);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("CreateTable: ex_execute_cmd(drop table) failed");
free (cmdbuf);
return retcode;
}
/*
** Insert an initial value into the table
*/
sprintf(cmdbuf, "insert %s values (35, '%s', 20.3, 50)",
Ex_tabname, EX_TXT_INIT_VALUE);
if ((retcode = ex_execute_cmd(connection, cmdbuf)) != CS_SUCCEED)
{
ex_error("CreateTable: ex_execute_cmd(insert table) failed");
}
free(cmdbuf);
return retcode;
}
/*
** DoGetSend()
**
** Type of function:
** getsend program internal api
**
** Purpose:
** This routine is the main driver for doing the getdata operation.
** It assumes that tha database and tables have been set up.
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
** connection - Pointer to CS_CONNECTION structure.
**
** Return:
*/
CS_STATIC CS_RETCODE
DoGetSend(connection1, connection2)
CS_CONNECTION *connection1;
CS_CONNECTION *connection2;
{
CS_RETCODE retcode;
TEXT_DATA textdata;
/*
** Retrieve the data initially in the table and
** get the descriptor for the text data.
*/
if ((retcode = RetrieveData(connection1, &textdata)) != CS_SUCCEED)
{
ex_error("DoGetSend: RetrieveData failed");
return retcode;
}
/*
** Display the text data retrieved, validate it is what we expected
*/
DisplayData(&textdata);
ValidateTxt(&textdata, EX_TXT_INIT_VALUE);
/*
** update the table with new text, validate that it's ok.
*/
retcode = UpdateTextData(connection2, &textdata, EX_TXT_UPD1_VALUE);
if (retcode != CS_SUCCEED)
{
ex_error("DoGetSend: UpdateTextData failed");
return retcode;
}
if ((retcode = RetrieveData(connection1, &textdata)) != CS_SUCCEED)
{
ex_error("DoGetSend: RetrieveData failed");
return retcode;
}
DisplayData(&textdata);
ValidateTxt(&textdata, EX_TXT_UPD1_VALUE);
/*
** Do it again with another text value.
*/
retcode = UpdateTextData(connection2, &textdata, EX_TXT_UPD2_VALUE);
if (retcode != CS_SUCCEED)
{
ex_error("DoGetSend: UpdateTextData failed");
return retcode;
}
if ((retcode = RetrieveData(connection1, &textdata)) != CS_SUCCEED)
{
ex_error("DoGetSend: RetrieveData failed");
return retcode;
}
DisplayData(&textdata);
ValidateTxt(&textdata, EX_TXT_UPD2_VALUE);
return retcode;
}
/*
** RetrieveData()
**
** Type of function:
** getsend program internal api
**
** Purpose:
** This function queries the database for all columns and rows in the
** table defined in EX_tabname.
**
** Parameters:
** connection - Pointer to CS_CONNECTION structure.
** textdata - Pointer to a TEXT_DATA structure to fill.
**
** Return:
** CS_SUCCEED if text was retrieved correctly.
** Otherwise a Client-Library failure code.
*/
CS_STATIC CS_RETCODE
RetrieveData(connection, textdata)
CS_CONNECTION *connection;
TEXT_DATA *textdata;
{
CS_RETCODE retcode;
CS_INT res_type;
CS_CHAR *cmdbuf;
CS_COMMAND *cmd;
/*
** Allocate the buffer for the command string.
*/
cmdbuf = (CS_CHAR *) malloc(EX_BUFSIZE);
if (cmdbuf == (CS_CHAR *)NULL)
{
ex_error("RetrieveData: malloc() failed");
return (CS_FAIL);
}
/*
** Allocate a command handle to send the select query with
*/
if ((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED)
{
ex_error("RetrieveData: ct_cmd_alloc() failed");
free(cmdbuf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -