⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i18n.c

📁 sybase数据库ct library的开发,使用了所以有函数
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**
** Description
** -----------
**	This example demonstrates some of the international features that
**	are available in Client Library. It installs a custom conversion
**	routine to handle multiple monetary formats. When processing
**	results, any conversions that are needed during a fetch of a row
**	will automatically call the installed routine when needed.
**
**	To demonstrate the fetch processing, the example sends user SQL
**	commands to the server via a language command. It processes the
**	results using the standard ct_results() while loop. It binds the
**	column values to program variables. It then fetches and displays
**	the rows in the standard ct_fetch() while loop.
**
**	The example also demonstrate the use of cs_locale() to set
**	localization, and supports a simplistic method of displaying
**	messages to the user based on language.
**
** Routines Used
** -------------
**	cs_ctx_alloc()
**	ct_init()
**	ct_config()
**	ct_callback()
**	ct_con_alloc()
**	ct_con_props()
**	ct_connect()
**	ct_cmd_alloc()
**	ct_send()
**	ct_results()
**	ct_res_info()
**	ct_describe()
**	ct_bind()
**	ct_fetch()
**	ct_cmd_drop()
**	ct_close()
**	ct_con_drop()
**	ct_exit()
**	ct_ctx_drop()
**	cs_loc_alloc()
**	cs_locale()
**	cs_config()
**	cs_set_convert()
**	cs_setnull()
**	cs_loc_drop()
**	cs_convert()
**
**
** Input
** -----
**	This example can use a hard-coded query of the titles table in
**	the pubs2 database.  The query is defined by EX_SELECT. If
**	EX_USE_SELECT is not defined, stdin is used to prompt the user.
**
**
** Output
** ------
**	This example displays the rows as they are returned from the server.
**	
**
** Server Dependencies
** -------------------
**	To have server messages in the defined language requires that
**	langinstall has been run against the server for the language.
**
**
** Server Tables
** -------------
**	This example relies on the pubs2 database and the titles table.
**
*/
#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  = "i18n";
CS_CHAR	*Ex_dbname   = "pubs2";
CS_CHAR *Ex_server   = EX_SERVER;
CS_CHAR *Ex_username = EX_USERNAME;
CS_CHAR *Ex_password = EX_PASSWORD;

/*
** Global context structure
*/
CS_CONTEXT	*Ex_context;

/*
** Uncomment the following if a hard coded select statment is desired for
** this example program. Otherwise, we will prompt for a query using
** stdin.
**
** #define EX_USE_SELECT	1
*/
#define EX_SELECT	"select title_id, total_sales, price from titles \
 				where type like \"%cook\""

/*
** If a hard coded locale is desired, uncomment the defined below.
** Otherwise, the example program will use the environment for the
** locale. For a complete list of possible values for EX_LOCALE, please
** refer to the file $SYBASE/locales/locales.dat for valid entries for
** your particular platform.
**
** #define EX_USE_LOCALE	1
*/
#define EX_LOCALE	"fr"

/*
** Define an index for the custom conversion routine that
** we will install in this example.
*/
#define MY_MONEY_CHAR_TYPE	(CS_USER_TYPE + 1)

/*
** The following defines a very simplistic method of managing a
** set of messages which can work with multiple languages. The
** SetupLocale() function will initialize the Ex_language variable
** to the correct language.
**
** Normally, these messages would be in an external resource file.
*/ 

#define M_UNKNOWN	(CS_INT)-1
#define M_ENGLISH	(CS_INT)0
#define M_GERMAN	(CS_INT)1
#define M_FRENCH	(CS_INT)2
#define M_MAX_LANG	(CS_INT)(M_FRENCH + 1)

#define MSG_STARTUP	(CS_INT)0
#define MSG_QUERY	(CS_INT)1
#define MSG_ROW_DONE	(CS_INT)2
#define MSG_CMD_FAIL	(CS_INT)3
#define MSG_MAX_MSG	(CS_INT)(MSG_CMD_FAIL + 1)

CS_CHAR	*Ex_messages[][MSG_MAX_MSG] = {
{ 
  "International Example Program\n",
  "\nEnter query to send or type quit: ",
  "\nAll done processing rows.\n",
  "\nSQL command failed. Check the Server messages for possible errors.\n",
},
{ 
  "DM: International Example Program\n",
  "\nDM: Enter query to send or type quit: ",
  "\nDM: All done processing rows.\n",
  "\nDM: SQL command failed. Check the Server messages for possible errors.\n",
},
{ 
  "FF: International Example Program\n",
  "\nFF: Enter query to send or type quit: ",
  "\nFF: All done processing rows.\n",
  "\nFF: SQL command failed. Check the Server messages for possible errors.\n",
},
};

CS_INT	Ex_language = M_ENGLISH;

#define MSG(X)		 Ex_messages[Ex_language][(X)]

/*
** Prototypes for routines in sample code
*/ 
CS_STATIC CS_RETCODE CS_INTERNAL SetupLocale PROTOTYPE((
	CS_CONTEXT *context
	));
CS_STATIC CS_RETCODE CS_INTERNAL DoCommand PROTOTYPE((
	CS_CONNECTION *connection,
	CS_BOOL *p_domore
	));
CS_STATIC CS_RETCODE CS_INTERNAL FetchData PROTOTYPE((
	CS_COMMAND *cmd
	));
CS_STATIC CS_RETCODE CS_INTERNAL MyMoneyToChar PROTOTYPE((
	CS_CONTEXT *context,
	CS_DATAFMT *srcfmt,
	CS_VOID *srcdata,
	CS_DATAFMT *destfmt,
	CS_VOID *destdata,
	CS_INT *destlen
	));
CS_STATIC CS_INT CS_INTERNAL LookupLanguage PROTOTYPE((
	CS_CHAR *lang
	));


/*
** main()
** 
** Purpose:
**	Entry point for example program.
** 
** Parameters:
**	None, argc and argv will not be used.
**
** Returns:
** 	EX_EXIT_ERROR  or EX_EXIT_SUCCEED
**
*/

int
main()
{
	CS_CONNECTION	*connection;
	CS_RETCODE	retcode;
	CS_BOOL		anothercmd = CS_TRUE;
	
	/* 
	** Allocate a context structure and initialize Client-Library 
	*/
	retcode = ex_init(&Ex_context);
	if (retcode != CS_SUCCEED)
	{
		ex_panic("ex_init failed");
	}

	/*
	** Setup up our locale for desired language and charset
	*/
	retcode = SetupLocale(Ex_context);

	fprintf(stdout, MSG(MSG_STARTUP));
	fflush(stdout);

	/* 
	** Allocate a connection structure, set its properties, and
	** establish a connection. Since the locale has already been
	** defined in the context structure, the connection will inherit
	** the context localization.
	*/
	if (retcode == CS_SUCCEED)
	{
		retcode = ex_connect(Ex_context, &connection, Ex_appname,
				Ex_username, Ex_password, Ex_server);
	}

	/*
	** Use the pubs2 database
	*/
	if (retcode == CS_SUCCEED)
	{
		if ((retcode = ex_use_db(connection, Ex_dbname)) != CS_SUCCEED)
		{
			ex_error("ex_use_db(pubs2) failed");
		}
	}

	/*
	** In a loop, execute the routines for the international example
	** program until anothercmd is set to CS_FALSE or a failure was
	** detected.
	*/
	while (retcode == CS_SUCCEED && anothercmd == CS_TRUE)
	{
		retcode = DoCommand(connection, &anothercmd);
	}

	/*
	** Deallocate the allocated structures, close the connection,
	** and exit Client-Library.
	*/
	if (connection != NULL)
	{
		retcode = ex_con_cleanup(connection, retcode);
	}
	
	if (Ex_context != NULL)
	{
		retcode = ex_ctx_cleanup(Ex_context, retcode);
	}

	return (retcode == CS_SUCCEED) ? EX_EXIT_SUCCEED : EX_EXIT_FAIL;
}

/*
** SetupLocale(context)
**
** Type of function:
** 	International example program internal api
**
** Purpose:
**	This function setups up locale related information for the
**	example program. This includes configuring the language, and
**	installing custom conversion routines.
**	
** Parameters:
**	context - Pointer to context structure
**
** Return:
**	CS_SUCCEED	If locale was setup up correctly.
** 	<retcode>	Result of the Client-Library function if a failure
**			was returned.
**
*/

CS_STATIC CS_RETCODE CS_INTERNAL
SetupLocale(context)
CS_CONTEXT	*context;
{
	CS_RETCODE	retcode;
	CS_LOCALE	*locale;
	CS_DATAFMT	tmpfmt;
	CS_CONV_FUNC	myfunc;
	CS_CHAR		locbuf[EX_MAXSTRINGLEN];

	/*
	** Get a locale handle.
	*/
	retcode = cs_loc_alloc(context, &locale);
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_loc_alloc() failed");
                return retcode;
        }

#if EX_USE_LOCALE
	/*
	** Set locale to the language/charset that we want
	*/
	retcode = cs_locale(context, CS_SET, locale, CS_LC_ALL, EX_LOCALE, 
				CS_NULLTERM, NULL);
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_locale(CS_SET) failed");
                return retcode;
        }

	/*
	** set context locale to the one we just defined
	*/
	retcode = cs_config(context, CS_SET, CS_LOC_PROP, locale,
			CS_UNUSED, NULL);
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_config(CS_LOC_PROP) failed");
                return retcode;
        }
#endif /* EX_USE_LOCALE */

	/*
	** In order for our application program to work with the
	** multitude of locales that could be defined, we will get the
	** Sybase representation of the language and standardize on that.
	*/
	retcode = cs_locale(context, CS_GET, locale, CS_SYB_LANG,
				locbuf, CS_SIZEOF(locbuf), NULL);
	if (retcode != CS_SUCCEED)
	{
		ex_error("SetupLocale: cs_locale(CS_GET) failed");
		return retcode;
	}

	/*
	** Based on locale name, Set up global messages
	*/
	Ex_language = LookupLanguage(locbuf);
	if (Ex_language == M_UNKNOWN)
	{
		fprintf(stdout,
		    "SetupLocale: Unknown language '%s', using English\n",
		    locbuf);
		fflush(stdout);
		Ex_language = M_ENGLISH;
	}

	/*
	** Install a custom conversion routine that we can use whenever
	** we want to display money values. cs_set_convert() can also be
	** used to override Sybase conversion routines (e.g. the Sybase
	** CS_MONEY_TYPE to CS_CHAR_TYPE conversion routine could be
	** replaced with MyMoneyToChar()). Since cs_set_convert()
	** requires a pointer to a pointer to a function, we use the temp
	** variable "myfunc" to hold the location of the routine.
	*/
	myfunc = MyMoneyToChar;
	retcode = cs_set_convert(context, CS_SET, CS_MONEY_TYPE,
				MY_MONEY_CHAR_TYPE, (CS_VOID *)&myfunc); 
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_set_convert() failed");
                return retcode;
        }

	/*
	** When a NULL value is received from the server, the conversion
	** routine is not called. Instead, a default null value is placed
	** in the destination buffer. In our case, we will display the
	** string "NULL" when this occurs.
	*/
	memset(&tmpfmt, 0, sizeof(tmpfmt));
	tmpfmt.datatype = MY_MONEY_CHAR_TYPE;
	retcode = cs_setnull(context, &tmpfmt, "NULL", strlen("NULL"));
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_set_convert() failed");
                return retcode;
        }

	/*
	** drop locale handle.
	*/
	retcode = cs_loc_drop(context, locale);
	if (retcode != CS_SUCCEED)
        {
                ex_error("SetupLocale: cs_loc_drop() failed");
                return retcode;
        }

	return retcode;
}

/*
** DoCommand(connection, p_domore)
**
** Type of function:
** 	International example program internal api
**
** Purpose:
**	This function is the core of the international example. It sends
**	a sql statement to the server. It then processes the results in
**	the standard ct_results() loop, calling FetchData() when the
**	type of result is "fetchable".
**	
** Parameters:
**	connection	- Pointer to connection structure
**	p_domore	- Pointer to a bool which is set to CS_TRUE if
**			  another command should be issued.
**
** Return:
**	CS_SUCCEED	If the result set was processed correctly.
** 	<retcode>	Result of the Client-Library function if a failure
**			was returned.
*/

CS_STATIC CS_RETCODE CS_INTERNAL
DoCommand(connection, p_domore)
CS_CONNECTION	*connection;
CS_BOOL		*p_domore;
{

	CS_RETCODE	retcode;
	CS_COMMAND	*cmd;
	CS_INT		res_type;	/* result type from ct_results */
	CS_CHAR		buf[MAX_CHAR_BUF];

	/*
	** Allocate a command handle to send the query with
	*/
        if ((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED)
        {
                ex_error("DoCommand: ct_cmd_alloc() failed");
                return retcode;
        }

	/*
	** Define a language command that contains a sql statement to
	** execute. EX_SELECT is a select statment which may be defined
	** above in this file. This routine will set p_domore to CS_FALSE
	** if a select was defined, or the user wants to exit the
	** application.
	*/
#if EX_USE_SELECT
	strcpy(buf, EX_SELECT);
	*p_domore = CS_FALSE;
#else
	fprintf(stdout, MSG(MSG_QUERY));
	fflush(stdout);
	fgets(buf, sizeof (buf), stdin);
	*p_domore = CS_TRUE;
#endif /* EX_USE_SELECT */
	if (strncmp(buf, "quit", 4) == 0)
	{
		*p_domore = CS_FALSE;
		return CS_SUCCEED;
	}


	retcode = ct_command(cmd, CS_LANG_CMD, buf, 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.
			*/
			fprintf(stdout, MSG(MSG_CMD_FAIL));
			fflush(stdout);
			break;

		case CS_ROW_RESULT:
		case CS_PARAM_RESULT:
		case CS_STATUS_RESULT:
		case CS_COMPUTE_RESULT:
			retcode = FetchData(cmd);
			if (retcode != CS_SUCCEED)
			{
				ex_error("DoCommand: FetchData() failed");
				return retcode;
			}
			break;

		default:
			/*
			** We got an unexpected result type.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -