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

📄 ecpglib.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright comment *//* * The aim is to get a simpler inteface to the database routines. * All the tidieous messing around with tuples is supposed to be hidden * by this function. *//* Author: Linus Tolke   (actually most if the code is "borrowed" from the distribution and just   slightly modified) *//* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>   on Feb. 5th, 1998 */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <libpq-fe.h>#include <libpq/pqcomm.h>#include <ecpgtype.h>#include <ecpglib.h>#include <sqlca.h>/* variables visible to the programs */static struct sqlca sqlca_init ={	{'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},	sizeof(struct sqlca),	0,	{0, {0}},	{'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},	{0, 0, 0, 0, 0, 0},	{0, 0, 0, 0, 0, 0, 0, 0},	{0, 0, 0, 0, 0, 0, 0, 0}};struct sqlca sqlca ={	{'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},	sizeof(struct sqlca),	0,	{0, {0}},	{'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},	{0, 0, 0, 0, 0, 0},	{0, 0, 0, 0, 0, 0, 0, 0},	{0, 0, 0, 0, 0, 0, 0, 0}};static struct connection{	char	   *name;	PGconn	   *connection;	bool		committed;	int			autocommit;	struct connection *next;}		   *all_connections = NULL, *actual_connection = NULL;struct variable{	enum ECPGttype type;	void	   *value;	void	   *pointer;	long		varcharsize;	long		arrsize;	long		offset;	enum ECPGttype ind_type;	void	   *ind_value;	long		ind_varcharsize;	long		ind_arrsize;	long		ind_offset;	struct variable *next;};struct statement{	int			lineno;	char	   *command;	struct connection *connection;	struct variable *inlist;	struct variable *outlist;};struct prepared_statement{	char	   *name;	struct statement *stmt;	struct prepared_statement *next;}		   *prep_stmts = NULL;struct auto_mem{	void	   *pointer;	struct auto_mem *next;}		   *auto_allocs = NULL;static int	simple_debug = 0;static FILE *debugstream = NULL;static voidregister_error(long code, char *fmt,...){	va_list		args;	struct auto_mem *am;	sqlca.sqlcode = code;	va_start(args, fmt);	vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);	va_end(args);	sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);	/* free all memory we have allocated for the user */	for (am = auto_allocs; am;)	{		struct auto_mem *act = am;		am = am->next;		free(act->pointer);		free(act);	}	auto_allocs = NULL;}static struct connection *get_connection(const char *connection_name){	struct connection *con = all_connections;	if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)		return actual_connection;	for (; con && strcmp(connection_name, con->name) != 0; con = con->next);	if (con)		return con;	else		return NULL;}static voidECPGfinish(struct connection * act){	if (act != NULL)	{		ECPGlog("ECPGfinish: finishing %s.\n", act->name);		PQfinish(act->connection);		/* remove act from the list */		if (act == all_connections)			all_connections = act->next;		else		{			struct connection *con;			for (con = all_connections; con->next && con->next != act; con = con->next);			if (con->next)				con->next = act->next;		}		if (actual_connection == act)			actual_connection = all_connections;		free(act->name);		free(act);	}	else		ECPGlog("ECPGfinish: called an extra time.\n");}static char *ecpg_alloc(long size, int lineno){	char	   *new = (char *) calloc(1L, size);	if (!new)	{		ECPGlog("out of memory\n");		register_error(ECPG_OUT_OF_MEMORY, "Out of memory in line %d", lineno);		return NULL;	}	memset(new, '\0', size);	return (new);}static char *ecpg_strdup(const char *string, int lineno){	char	   *new = strdup(string);	if (!new)	{		ECPGlog("out of memory\n");		register_error(ECPG_OUT_OF_MEMORY, "Out of memory in line %d", lineno);		return NULL;	}	return (new);}static voidadd_mem(void *ptr, int lineno){	struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);	am->next = auto_allocs;	auto_allocs = am;}/* This function returns a newly malloced string that has the ' and \   in the argument quoted with \. */staticchar *quote_postgres(char *arg, int lineno){	char	   *res = (char *) ecpg_alloc(2 * strlen(arg) + 1, lineno);	int			i,				ri;	if (!res)		return (res);	for (i = 0, ri = 0; arg[i]; i++, ri++)	{		switch (arg[i])		{			case '\'':			case '\\':				res[ri++] = '\\';			default:				;		}		res[ri] = arg[i];	}	res[ri] = '\0';	return res;}/* * create a list of variables * The variables are listed with input variables preceeding outputvariables * The end of each group is marked by an end marker. * per variable we list: * type - as defined in ecpgtype.h * value - where to store the data * varcharsize - length of string in case we have a stringvariable, else 0 * arraysize - 0 for pointer (we don't know the size of the array), * 1 for simple variable, size for arrays * offset - offset between ith and (i+1)th entry in an array, * normally that means sizeof(type) * ind_type - type of indicator variable * ind_value - pointer to indicator variable * ind_varcharsize - empty * ind_arraysize -	arraysize of indicator array * ind_offset - indicator offset */static boolcreate_statement(int lineno, struct connection * connection, struct statement ** stmt, char *query, va_list ap){	struct variable **list = &((*stmt)->inlist);	enum ECPGttype type;	if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))		return false;	(*stmt)->command = query;	(*stmt)->connection = connection;	(*stmt)->lineno = lineno;	list = &((*stmt)->inlist);	type = va_arg(ap, enum ECPGttype);	while (type != ECPGt_EORT)	{		if (type == ECPGt_EOIT)			list = &((*stmt)->outlist);		else		{			struct variable *var,					   *ptr;			if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))				return false;			var->type = type;			var->pointer = va_arg(ap, void *);			/* if variable is NULL, the statement hasn't been prepared */			if (var->pointer == NULL)			{				ECPGlog("create_statement: invalid statement name\n");				register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d.", lineno);				free(var);				return false;			}			var->varcharsize = va_arg(ap, long);			var->arrsize = va_arg(ap, long);			var->offset = va_arg(ap, long);			if (var->arrsize == 0 || var->varcharsize == 0)				var->value = *((void **) (var->pointer));			else				var->value = var->pointer;			var->ind_type = va_arg(ap, enum ECPGttype);			var->ind_value = va_arg(ap, void *);			var->ind_varcharsize = va_arg(ap, long);			var->ind_arrsize = va_arg(ap, long);			var->ind_offset = va_arg(ap, long);			var->next = NULL;			for (ptr = *list; ptr && ptr->next; ptr = ptr->next);			if (ptr == NULL)				*list = var;			else				ptr->next = var;		}		type = va_arg(ap, enum ECPGttype);	}	return (true);}static voidfree_variable(struct variable * var){	struct variable *var_next;	if (var == (struct variable *) NULL)		return;	var_next = var->next;	free(var);	while (var_next)	{		var = var_next;		var_next = var->next;		free(var);	}}static voidfree_statement(struct statement * stmt){	if (stmt == (struct statement *) NULL)		return;	free_variable(stmt->inlist);	free_variable(stmt->outlist);	free(stmt);}static char *next_insert(char *text){	char	   *ptr = text;	bool		string = false;	for (; *ptr != '\0' && (*ptr != '?' || string); ptr++)		if (*ptr == '\'')			string = string ? false : true;	return (*ptr == '\0') ? NULL : ptr;}static boolECPGexecute(struct statement * stmt){	bool		status = false;	char	   *copiedquery;	PGresult   *results;	PGnotify   *notify;	struct variable *var;	memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));	copiedquery = ecpg_strdup(stmt->command, stmt->lineno);	/*	 * Now, if the type is one of the fill in types then we take the	 * argument and enter that in the string at the first %s position.	 * Then if there are any more fill in types we fill in at the next and	 * so on.	 */	var = stmt->inlist;	while (var)	{		char	   *newcopy;		char	   *mallocedval = NULL;		char	   *tobeinserted = NULL;		char	   *p;		char		buff[20];		/*		 * Some special treatment is needed for records since we want		 * their contents to arrive in a comma-separated list on insert (I		 * think).		 */		buff[0] = '\0';		/* check for null value and set input buffer accordingly */		switch (var->ind_type)		{			case ECPGt_short:			case ECPGt_unsigned_short:				if (*(short *) var->ind_value < 0)					strcpy(buff, "null");				break;			case ECPGt_int:			case ECPGt_unsigned_int:				if (*(int *) var->ind_value < 0)					strcpy(buff, "null");				break;			case ECPGt_long:			case ECPGt_unsigned_long:				if (*(long *) var->ind_value < 0L)					strcpy(buff, "null");				break;			default:				break;		}		if (*buff == '\0')		{			switch (var->type)			{				case ECPGt_short:					sprintf(buff, "%d", *(short *) var->value);					tobeinserted = buff;					break;				case ECPGt_int:					sprintf(buff, "%d", *(int *) var->value);					tobeinserted = buff;					break;				case ECPGt_unsigned_short:					sprintf(buff, "%d", *(unsigned short *) var->value);					tobeinserted = buff;					break;				case ECPGt_unsigned_int:					sprintf(buff, "%d", *(unsigned int *) var->value);					tobeinserted = buff;					break;				case ECPGt_long:					sprintf(buff, "%ld", *(long *) var->value);					tobeinserted = buff;					break;				case ECPGt_unsigned_long:					sprintf(buff, "%ld", *(unsigned long *) var->value);					tobeinserted = buff;					break;				case ECPGt_float:					sprintf(buff, "%.14g", *(float *) var->value);					tobeinserted = buff;					break;				case ECPGt_double:					sprintf(buff, "%.14g", *(double *) var->value);

⌨️ 快捷键说明

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