diff options
| author | Stig Bakken <ssb@php.net> | 1999-04-22 02:48:28 +0000 | 
|---|---|---|
| committer | Stig Bakken <ssb@php.net> | 1999-04-22 02:48:28 +0000 | 
| commit | 2c0ad3ee25cd8e449b02c4668a39f48998507739 (patch) | |
| tree | 8064c7ee59309ffed3d9c5b8fd5c329ede193561 /ext/pgsql/pgsql.c | |
| parent | 2a78f92804ae6f3e32cd278afbb9aa8ec3d2f52d (diff) | |
| download | php-git-2c0ad3ee25cd8e449b02c4668a39f48998507739.tar.gz | |
last bunch of extensions moving to ext/
fhttpd module taken out of functions, functions is ready to go.
The only extensions I have tested are gd+freetype and odbc(solid).
Please try compiling in your favourite extensions and let me know how it
works.
Diffstat (limited to 'ext/pgsql/pgsql.c')
| -rw-r--r-- | ext/pgsql/pgsql.c | 1490 | 
1 files changed, 1490 insertions, 0 deletions
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c new file mode 100644 index 0000000000..fa38715d25 --- /dev/null +++ b/ext/pgsql/pgsql.c @@ -0,0 +1,1490 @@ +/* +   +----------------------------------------------------------------------+ +   | PHP HTML Embedded Scripting Language Version 3.0                     | +   +----------------------------------------------------------------------+ +   | Copyright (c) 1997,1998 PHP Development Team (See Credits file)      | +   +----------------------------------------------------------------------+ +   | This program is free software; you can redistribute it and/or modify | +   | it under the terms of one of the following licenses:                 | +   |                                                                      | +   |  A) the GNU General Public License as published by the Free Software | +   |     Foundation; either version 2 of the License, or (at your option) | +   |     any later version.                                               | +   |                                                                      | +   |  B) the PHP License as published by the PHP Development Team and     | +   |     included in the distribution in the file: LICENSE                | +   |                                                                      | +   | This program is distributed in the hope that it will be useful,      | +   | but WITHOUT ANY WARRANTY; without even the implied warranty of       | +   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        | +   | GNU General Public License for more details.                         | +   |                                                                      | +   | You should have received a copy of both licenses referred to here.   | +   | If you did not, or have any questions about PHP licensing, please    | +   | contact core@php.net.                                                | +   +----------------------------------------------------------------------+ +   | Authors: Zeev Suraski <zeev@zend.com>                                | +   |          Jouni Ahto <jah@cultnet.fi> (large object interface)        | +   +----------------------------------------------------------------------+ + */ +  +/* $Id$ */ + +#include <stdlib.h> + +#ifndef MSVC5 +#include "config.h" +#endif +#include "php.h" +#include "php3_pgsql.h" +#include "ext/standard/php3_standard.h" +#include "php_globals.h" + +#if HAVE_PGSQL + + + +function_entry pgsql_functions[] = { +	{"pg_connect",		php3_pgsql_connect,			NULL}, +	{"pg_pconnect",		php3_pgsql_pconnect,		NULL}, +	{"pg_close",		php3_pgsql_close,			NULL}, +	{"pg_cmdtuples",	php3_pgsql_cmdtuples,		NULL}, +	{"pg_dbname",		php3_pgsql_dbname,			NULL}, +	{"pg_errormessage",	php3_pgsql_error_message,	NULL}, +	{"pg_options",		php3_pgsql_options,			NULL}, +	{"pg_port",			php3_pgsql_port,			NULL}, +	{"pg_tty",			php3_pgsql_tty,				NULL}, +	{"pg_host",			php3_pgsql_host,			NULL}, +	{"pg_exec",			php3_pgsql_exec,			NULL}, +	{"pg_numrows",		php3_pgsql_num_rows,		NULL}, +	{"pg_numfields",	php3_pgsql_num_fields,		NULL}, +	{"pg_fieldname",	php3_pgsql_field_name,		NULL}, +	{"pg_fieldsize",	php3_pgsql_field_size,		NULL}, +	{"pg_fieldtype",	php3_pgsql_field_type,		NULL}, +	{"pg_fieldnum",		php3_pgsql_field_number,	NULL}, +	{"pg_result",		php3_pgsql_result,			NULL}, +	{"pg_fetch_row",	php3_pgsql_fetch_row,		NULL}, +	{"pg_fetch_array",	php3_pgsql_fetch_array,		NULL}, +	{"pg_fetch_object",	php3_pgsql_fetch_object,	NULL}, +	{"pg_fieldprtlen",	php3_pgsql_data_length,		NULL}, +	{"pg_fieldisnull",	php3_pgsql_data_isnull,		NULL}, +	{"pg_freeresult",	php3_pgsql_free_result,		NULL}, +	{"pg_getlastoid",	php3_pgsql_last_oid,		NULL}, +	{"pg_locreate",		php3_pgsql_lo_create,		NULL}, +	{"pg_lounlink", 	php3_pgsql_lo_unlink,		NULL}, +	{"pg_loopen",		php3_pgsql_lo_open,			NULL}, +	{"pg_loclose",		php3_pgsql_lo_close,		NULL}, +	{"pg_loread",		php3_pgsql_lo_read,			NULL}, +	{"pg_lowrite",		php3_pgsql_lo_write,		NULL}, +	{"pg_loreadall",	php3_pgsql_lo_readall,		NULL}, +	{NULL, NULL, NULL} +}; + +php3_module_entry pgsql_module_entry = { +	"PostgreSQL", pgsql_functions, php3_minit_pgsql, NULL, php3_rinit_pgsql, NULL, NULL, STANDARD_MODULE_PROPERTIES +}; + +#if COMPILE_DL +php3_module_entry *get_module() { return &pgsql_module_entry; } +#endif + +THREAD_LS pgsql_module php3_pgsql_module; + +static void _close_pgsql_link(PGconn *link) +{ +	PQfinish(link); +	php3_pgsql_module.num_links--; +} + + +static void _close_pgsql_plink(PGconn *link) +{ +	PQfinish(link); +	php3_pgsql_module.num_persistent--; +	php3_pgsql_module.num_links--; +} + + +static void _free_ptr(pgLofp *lofp) +{ +	efree(lofp); +} + + +static void _free_result(pgsql_result_handle *pg_result) +{ +	PQclear(pg_result->result); +	efree(pg_result); +} + + +int php3_minit_pgsql(INIT_FUNC_ARGS) +{ +	if (cfg_get_long("pgsql.allow_persistent",&php3_pgsql_module.allow_persistent)==FAILURE) { +		php3_pgsql_module.allow_persistent=1; +	} +	if (cfg_get_long("pgsql.max_persistent",&php3_pgsql_module.max_persistent)==FAILURE) { +		php3_pgsql_module.max_persistent=-1; +	} +	if (cfg_get_long("pgsql.max_links",&php3_pgsql_module.max_links)==FAILURE) { +		php3_pgsql_module.max_links=-1; +	} +	php3_pgsql_module.num_persistent=0; +	php3_pgsql_module.le_link = register_list_destructors(_close_pgsql_link,NULL); +	php3_pgsql_module.le_plink = register_list_destructors(NULL,_close_pgsql_plink); +	/*	php3_pgsql_module.le_result = register_list_destructors(PQclear,NULL); */ +	php3_pgsql_module.le_result = register_list_destructors(_free_result,NULL); +	php3_pgsql_module.le_lofp = register_list_destructors(_free_ptr,NULL); +	php3_pgsql_module.le_string = register_list_destructors(_free_ptr,NULL); +	return SUCCESS; +} + + +int php3_rinit_pgsql(INIT_FUNC_ARGS) +{ +	php3_pgsql_module.default_link=-1; +	php3_pgsql_module.num_links = php3_pgsql_module.num_persistent; +	return SUCCESS; +} + + +void php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent) +{ +	char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL; +	char *hashed_details; +	int hashed_details_length; +	PGconn *pgsql; +	 +	switch(ARG_COUNT(ht)) { +		case 1: { /* new style, using connection string */ +				pval *yyconnstring; +				if (getParameters(ht, 1, &yyconnstring) == FAILURE) { +					RETURN_FALSE; +				} +				convert_to_string(yyconnstring); +				connstring = yyconnstring->value.str.val; +				hashed_details_length = yyconnstring->value.str.len+5+1; +				hashed_details = (char *) emalloc(hashed_details_length+1); +				sprintf(hashed_details,"pgsql_%s",connstring); /* SAFE */ +			} +			break; +		case 3: { /* host, port, dbname */ +				pval *yyhost, *yyport, *yydbname; +				 +				if (getParameters(ht, 3, &yyhost, &yyport, &yydbname) == FAILURE) { +					RETURN_FALSE; +				} +				convert_to_string(yyhost); +				convert_to_string(yyport); +				convert_to_string(yydbname); +				host = yyhost->value.str.val; +				port = yyport->value.str.val; +				dbname = yydbname->value.str.val; +				options=tty=NULL; +				hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yydbname->value.str.len+5+5; +				hashed_details = (char *) emalloc(hashed_details_length+1); +				sprintf(hashed_details,"pgsql_%s_%s___%s",host,port,dbname);  /* SAFE */ +			} +			break; +		case 4: { /* host, port, options, dbname */ +				pval *yyhost, *yyport, *yyoptions, *yydbname; +				 +				if (getParameters(ht, 4, &yyhost, &yyport, &yyoptions, &yydbname) == FAILURE) { +					RETURN_FALSE; +				} +				convert_to_string(yyhost); +				convert_to_string(yyport); +				convert_to_string(yyoptions); +				convert_to_string(yydbname); +				host = yyhost->value.str.val; +				port = yyport->value.str.val; +				options = yyoptions->value.str.val; +				dbname = yydbname->value.str.val; +				tty=NULL; +				hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yyoptions->value.str.len+yydbname->value.str.len+5+5; +				hashed_details = (char *) emalloc(hashed_details_length+1); +				sprintf(hashed_details,"pgsql_%s_%s_%s__%s",host,port,options,dbname);  /* SAFE */ +			} +			break; +		case 5: { /* host, port, options, tty, dbname */ +				pval *yyhost, *yyport, *yyoptions, *yytty, *yydbname; +				 +				if (getParameters(ht, 5, &yyhost, &yyport, &yyoptions, &yytty, &yydbname) == FAILURE) { +					RETURN_FALSE; +				} +				convert_to_string(yyhost); +				convert_to_string(yyport); +				convert_to_string(yyoptions); +				convert_to_string(yytty); +				convert_to_string(yydbname); +				host = yyhost->value.str.val; +				port = yyport->value.str.val; +				options = yyoptions->value.str.val; +				tty = yytty->value.str.val; +				dbname = yydbname->value.str.val; +				hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yyoptions->value.str.len+yytty->value.str.len+yydbname->value.str.len+5+5; +				hashed_details = (char *) emalloc(hashed_details_length+1); +				sprintf(hashed_details,"pgsql_%s_%s_%s_%s_%s",host,port,options,tty,dbname);  /* SAFE */ +			} +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	if (persistent) { +		list_entry *le; +		 +		/* try to find if we already have this link in our persistent list */ +		if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {  /* we don't */ +			list_entry new_le; +			 +			if (php3_pgsql_module.max_links!=-1 && php3_pgsql_module.num_links>=php3_pgsql_module.max_links) { +				php3_error(E_WARNING,"PostgresSQL:  Too many open links (%d)",php3_pgsql_module.num_links); +				efree(hashed_details); +				RETURN_FALSE; +			} +			if (php3_pgsql_module.max_persistent!=-1 && php3_pgsql_module.num_persistent>=php3_pgsql_module.max_persistent) { +				php3_error(E_WARNING,"PostgresSQL:  Too many open persistent links (%d)",php3_pgsql_module.num_persistent); +				efree(hashed_details); +				RETURN_FALSE; +			} + +			/* create the link */ +			if (connstring) { +				pgsql=PQconnectdb(connstring); +			} else { +				pgsql=PQsetdb(host,port,options,tty,dbname); +			} +			if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) { +				php3_error(E_WARNING,"Unable to connect to PostgresSQL server:  %s",PQerrorMessage(pgsql)); +				efree(hashed_details); +				RETURN_FALSE; +			} + +			/* hash it up */ +			new_le.type = php3_pgsql_module.le_plink; +			new_le.ptr = pgsql; +			if (_php3_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) { +				efree(hashed_details); +				RETURN_FALSE; +			} +			php3_pgsql_module.num_links++; +			php3_pgsql_module.num_persistent++; +		} else {  /* we do */ +			if (le->type != php3_pgsql_module.le_plink) { +				RETURN_FALSE; +			} +			/* ensure that the link did not die */ +			if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */ +				if (connstring) { +					le->ptr=PQconnectdb(connstring); +				} else { +					le->ptr=PQsetdb(host,port,options,tty,dbname); +				} +				if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) { +					php3_error(E_WARNING,"PostgresSQL link lost, unable to reconnect"); +					_php3_hash_del(plist,hashed_details,hashed_details_length+1); +					efree(hashed_details); +					RETURN_FALSE; +				} +			} +			pgsql = (PGconn *) le->ptr; +		} +		return_value->value.lval = php3_list_insert(pgsql,php3_pgsql_module.le_plink); +		return_value->type = IS_LONG; +	} else { +		list_entry *index_ptr,new_index_ptr; +		 +		/* first we check the hash for the hashed_details key.  if it exists, +		 * it should point us to the right offset where the actual pgsql link sits. +		 * if it doesn't, open a new pgsql link, add it to the resource list, +		 * and add a pointer to it with hashed_details as the key. +		 */ +		if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) { +			int type,link; +			void *ptr; + +			if (index_ptr->type != le_index_ptr) { +				RETURN_FALSE; +			} +			link = (int) index_ptr->ptr; +			ptr = php3_list_find(link,&type);   /* check if the link is still there */ +			if (ptr && (type==php3_pgsql_module.le_link || type==php3_pgsql_module.le_plink)) { +				return_value->value.lval = php3_pgsql_module.default_link = link; +				return_value->type = IS_LONG; +				efree(hashed_details); +				return; +			} else { +				_php3_hash_del(list,hashed_details,hashed_details_length+1); +			} +		} +		if (php3_pgsql_module.max_links!=-1 && php3_pgsql_module.num_links>=php3_pgsql_module.max_links) { +			php3_error(E_WARNING,"PostgresSQL:  Too many open links (%d)",php3_pgsql_module.num_links); +			efree(hashed_details); +			RETURN_FALSE; +		} +		if (connstring) { +			pgsql=PQconnectdb(connstring); +		} else { +			pgsql=PQsetdb(host,port,options,tty,dbname); +		} +		if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) { +			php3_error(E_WARNING,"Unable to connect to PostgresSQL server:  %s",PQerrorMessage(pgsql)); +			efree(hashed_details); +			RETURN_FALSE; +		} + +		/* add it to the list */ +		return_value->value.lval = php3_list_insert(pgsql,php3_pgsql_module.le_link); +		return_value->type = IS_LONG; + +		/* add it to the hash */ +		new_index_ptr.ptr = (void *) return_value->value.lval; +		new_index_ptr.type = le_index_ptr; +		if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) { +			efree(hashed_details); +			RETURN_FALSE; +		} +		php3_pgsql_module.num_links++; +	} +	efree(hashed_details); +	php3_pgsql_module.default_link=return_value->value.lval; +} + + +int php3_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS) +{ +	if (php3_pgsql_module.default_link==-1) { /* no link opened yet, implicitly open one */ +		HashTable tmp; +		 +		_php3_hash_init(&tmp,0,NULL,NULL,0); +		php3_pgsql_do_connect(&tmp,return_value,list,plist,0); +		_php3_hash_destroy(&tmp); +	} +	return php3_pgsql_module.default_link; +} + +/* {{{ proto int pg_connect([string connection_string] | [string host, string port, [string options, [string tty,]] string database) +   Open a PostgreSQL connection */ +void php3_pgsql_connect(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0); +} +/* }}} */ + +/* {{{ proto int pg_connect([string connection_string] | [string host, string port, [string options, [string tty,]] string database) +   Open a persistent PostgreSQL connection */ +void php3_pgsql_pconnect(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); +} +/* }}} */ + +/* {{{ proto bool pg_close([int connection]) +   Close a PostgreSQL connection */  +void php3_pgsql_close(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *pgsql_link; +	int id,type; +	PGconn *pgsql; +	 +	switch (ARG_COUNT(ht)) { +		case 0: +			id = php3_pgsql_module.default_link; +			break; +		case 1: +			if (getParameters(ht, 1, &pgsql_link)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	php3_list_delete(pgsql_link->value.lval); +	RETURN_TRUE; +} +/* }}} */ + + +#define PHP3_PG_DBNAME 1 +#define PHP3_PG_ERROR_MESSAGE 2 +#define PHP3_PG_OPTIONS 3 +#define PHP3_PG_PORT 4 +#define PHP3_PG_TTY 5 +#define PHP3_PG_HOST 6 + +void php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +{ +	pval *pgsql_link; +	int id,type; +	PGconn *pgsql; +	 +	switch(ARG_COUNT(ht)) { +		case 0: +			id = php3_pgsql_module.default_link; +			break; +		case 1: +			if (getParameters(ht, 1, &pgsql_link)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	switch(entry_type) { +		case PHP3_PG_DBNAME: +			return_value->value.str.val = PQdb(pgsql); +			break; +		case PHP3_PG_ERROR_MESSAGE: +			return_value->value.str.val = PQerrorMessage(pgsql); +			break; +		case PHP3_PG_OPTIONS: +			return_value->value.str.val = PQoptions(pgsql); +			break; +		case PHP3_PG_PORT: +			return_value->value.str.val = PQport(pgsql); +			break; +		case PHP3_PG_TTY: +			return_value->value.str.val = PQtty(pgsql); +			break; +		case PHP3_PG_HOST: +			return_value->value.str.val = PQhost(pgsql); +			break; +		default: +			RETURN_FALSE; +	} +	return_value->value.str.len = strlen(return_value->value.str.val); +	return_value->value.str.val = (char *) estrdup(return_value->value.str.val); +	return_value->type = IS_STRING; +} + +/* {{{ proto string pg_dbname([int connection]) +   Get the database name */  +void php3_pgsql_dbname(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_DBNAME); +} +/* }}} */ + +/* {{{ proto string pg_errormessage([int connection]) +   Get the error message string */ +void php3_pgsql_error_message(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_ERROR_MESSAGE); +} +/* }}} */ + +/* {{{ proto string pg_options([int connection]) +   Get the options associated with the connection */ +void php3_pgsql_options(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_OPTIONS); +} +/* }}} */ + +/* {{{ proto int pg_port([int connection]) +   Return the port number associated with the connection */ +void php3_pgsql_port(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_PORT); +} +/* }}} */ + +/* {{{ proto string pg_tty([int connection]) +   Return the tty name associated with the connection */ +void php3_pgsql_tty(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_TTY); +} +/* }}} */ + +/* {{{ proto string pg_host([int connection]) +   Returns the host name associated with the connection */ +void php3_pgsql_host(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_HOST); +} +/* }}} */ + +/* {{{ proto int pg_exec([int connection,] string query) +   Execute a query */ +void php3_pgsql_exec(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *query,*pgsql_link; +	int id,type; +	PGconn *pgsql; +	PGresult *pgsql_result; +	ExecStatusType  status; +	pgsql_result_handle *pg_result; +	 +	switch(ARG_COUNT(ht)) { +		case 1: +			if (getParameters(ht, 1, &query)==FAILURE) { +				RETURN_FALSE; +			} +			id = php3_pgsql_module.default_link; +			break; +		case 2: +			if (getParameters(ht, 2, &pgsql_link, &query)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	convert_to_string(query); +	pgsql_result=PQexec(pgsql,query->value.str.val); +	 +	if (pgsql_result) { +		status = PQresultStatus(pgsql_result); +	} else { +		status = (ExecStatusType) PQstatus(pgsql); +	} +	 +	 +	switch (status) { +		case PGRES_EMPTY_QUERY: +		case PGRES_BAD_RESPONSE: +		case PGRES_NONFATAL_ERROR: +		case PGRES_FATAL_ERROR: +			php3_error(E_WARNING,"PostgresSQL query failed:  %s",PQerrorMessage(pgsql)); +			RETURN_FALSE; +			break; +		case PGRES_COMMAND_OK: /* successful command that did not return rows */ +		default: +			if (pgsql_result) { +				pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle)); +				pg_result->conn = pgsql; +				pg_result->result = pgsql_result; +				return_value->value.lval = php3_list_insert(pg_result,php3_pgsql_module.le_result); +				return_value->type = IS_LONG; +			} else { +				RETURN_FALSE; +			} +			break; +	} +} +/* }}} */ + +#define PHP3_PG_NUM_ROWS 1 +#define PHP3_PG_NUM_FIELDS 2 +#define PHP3_PG_CMD_TUPLES 3 + +void php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +{ +	pval *result; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	 +	if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); + +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	 +	pgsql_result = pg_result->result; +	 +	switch (entry_type) { +		case PHP3_PG_NUM_ROWS: +			return_value->value.lval = PQntuples(pgsql_result); +			break; +		case PHP3_PG_NUM_FIELDS: +			return_value->value.lval = PQnfields(pgsql_result); +			break; +		case PHP3_PG_CMD_TUPLES: +#if HAVE_PQCMDTUPLES +			return_value->value.lval = atoi(PQcmdTuples(pgsql_result)); +#else +			php3_error(E_WARNING,"This compilation does not support pg_cmdtuples()"); +			return_value->value.lval = 0; +#endif +			break; +		default: +			RETURN_FALSE; +	} +	return_value->type = IS_LONG; +} + +/* {{{ proto int pg_numrows(int result) +   Return the number of rows in the result */ +void php3_pgsql_num_rows(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_NUM_ROWS); +} +/* }}} */ + +/* {{{ proto int pg_numfields(int result) +   Return the number of fields in the result */ +void php3_pgsql_num_fields(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_NUM_FIELDS); +} +/* }}} */ + +/* {{{ proto int pg_cmdtuples(int result) +   Returns the number of affected tuples */ +void php3_pgsql_cmdtuples(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_CMD_TUPLES); +} +/* }}} */ + + +char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list) +{ +	PGresult *result; +	char hashed_oid_key[32]; +	list_entry *field_type; +	char *ret=NULL; +	 +	/* try to lookup the type in the resource list */ +	snprintf(hashed_oid_key,31,"pgsql_oid_%d",(int) oid); +	hashed_oid_key[31]=0; + +	if (_php3_hash_find(list,hashed_oid_key,strlen(hashed_oid_key)+1,(void **) &field_type)==SUCCESS) { +		ret = estrdup((char *)field_type->ptr); +	} else { /* hash all oid's */ +		int i,num_rows; +		int oid_offset,name_offset; +		char *tmp_oid, *tmp_name; +		list_entry new_oid_entry; + +		if ((result=PQexec(pgsql,"select oid,typname from pg_type"))==NULL) { +			return empty_string; +		} +		num_rows=PQntuples(result); +		oid_offset = PQfnumber(result,"oid"); +		name_offset = PQfnumber(result,"typname"); +		 +		for (i=0; i<num_rows; i++) { +			if ((tmp_oid=PQgetvalue(result,i,oid_offset))==NULL) { +				continue; +			} +			snprintf(hashed_oid_key,31,"pgsql_oid_%s",tmp_oid); +			if ((tmp_name=PQgetvalue(result,i,name_offset))==NULL) { +				continue; +			} +			new_oid_entry.type = php3_pgsql_module.le_string; +			new_oid_entry.ptr = estrdup(tmp_name); +			_php3_hash_update(list,hashed_oid_key,strlen(hashed_oid_key)+1,(void *) &new_oid_entry, sizeof(list_entry), NULL); +			if (!ret && atoi(tmp_oid)==oid) { +				ret = estrdup(tmp_name); +			} +		} +	} +	return ret; +} +			 + +#define PHP3_PG_FIELD_NAME 1 +#define PHP3_PG_FIELD_SIZE 2 +#define PHP3_PG_FIELD_TYPE 3 + +void php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +{ +	pval *result,*field; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	 +	if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &field)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	 +	pgsql_result = pg_result->result; +	convert_to_long(field); +	 +	if (field->value.lval<0 || field->value.lval>=PQnfields(pgsql_result)) { +		php3_error(E_WARNING,"Bad field offset specified"); +		RETURN_FALSE; +	} +	 +	switch (entry_type) { +		case PHP3_PG_FIELD_NAME: +			return_value->value.str.val = PQfname(pgsql_result,field->value.lval); +			return_value->value.str.len = strlen(return_value->value.str.val); +			return_value->value.str.val = estrndup(return_value->value.str.val,return_value->value.str.len); +			return_value->type = IS_STRING; +			break; +		case PHP3_PG_FIELD_SIZE: +			return_value->value.lval = PQfsize(pgsql_result,field->value.lval); +			return_value->type = IS_LONG; +			break; +		case PHP3_PG_FIELD_TYPE: +			return_value->value.str.val = get_field_name(pg_result->conn,PQftype(pgsql_result,field->value.lval),list); +			return_value->value.str.len = strlen(return_value->value.str.val); +			return_value->type = IS_STRING; +			break; +		default: +			RETURN_FALSE; +	} +} + +/* {{{ proto string pg_fieldname(int result, int field_number) +   Returns the name of the field */ +void php3_pgsql_field_name(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_NAME); +} +/* }}} */ + +/* {{{ proto pg_fieldsize(int result, int field_number) +   Returns the internal size of the field */  +void php3_pgsql_field_size(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_SIZE); +} +/* }}} */ + +/* {{{ proto string pg_fieldtype(int result, int field_number) +   Returns the type name for the given field */ +void php3_pgsql_field_type(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_TYPE); +} +/* }}} */ + +/* {{{ proto int pg_fieldnum(int result, string field_name) +   Returns the field number of the named field */ +void php3_pgsql_field_number(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result,*field; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	 +	if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &field)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	 +	convert_to_string(field); +	return_value->value.lval = PQfnumber(pgsql_result,field->value.str.val); +	return_value->type = IS_LONG; +} +/* }}} */ + +/* {{{ proto mixed pg_result(int result, int row_number, mixed field_name) +   Returns values from a result identifier */ +void php3_pgsql_result(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result, *row, *field=NULL; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type,field_offset; +	 +	 +	if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &result, &row, &field)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	 +	convert_to_long(row); +	if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) { +		php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval); +		RETURN_FALSE; +	} +	switch(field->type) { +		case IS_STRING: +			field_offset = PQfnumber(pgsql_result,field->value.str.val); +			break; +		default: +			convert_to_long(field); +			field_offset = field->value.lval; +			break; +	} +	if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) { +		php3_error(E_WARNING,"Bad column offset specified"); +		RETURN_FALSE; +	} +	 +	return_value->value.str.val = PQgetvalue(pgsql_result,row->value.lval,field_offset); +	return_value->value.str.len = (return_value->value.str.val ? strlen(return_value->value.str.val) : 0); +	return_value->value.str.val = safe_estrndup(return_value->value.str.val,return_value->value.str.len); +	return_value->type = IS_STRING; +} +/* }}} */ + +/* {{{ proto array pg_fetchrow(int result, int row) +   Get a row as an enumerated array */  +void php3_pgsql_fetch_row(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result, *row; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	int i,num_fields; +	char *element; +	uint element_len; +	PLS_FETCH(); +	 +	 +	if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &row)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	 +	convert_to_long(row); +	if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) { +		php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval); +		RETURN_FALSE; +	} +	array_init(return_value); +	for (i=0,num_fields=PQnfields(pgsql_result); i<num_fields; i++) { +		element = PQgetvalue(pgsql_result,row->value.lval,i); +		element_len = (element ? strlen(element) : 0); +		element = safe_estrndup(element,element_len); +        if (element) { +            if (PG(magic_quotes_runtime)) { +                char *tmp=_php3_addslashes(element,element_len,&element_len,0); + +                add_index_stringl(return_value, i, tmp, element_len, 0); +            } else { +                add_index_stringl(return_value, i, element, element_len, 1); +            } +        } else { +            /* NULL field, don't set it */ +            /*add_index_stringl(return_value, i, empty_string, 0, 1);*/ +        } +	} +} +/* }}} */ + +void php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result, *row, *pval_ptr; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	int i,num_fields; +	char *element,*field_name; +	uint element_len; +	PLS_FETCH(); +	 +	 +	if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &row)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	 +	convert_to_long(row); +	if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) { +		php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval); +		RETURN_FALSE; +	} +	array_init(return_value); +	for (i=0,num_fields=PQnfields(pgsql_result); i<num_fields; i++) { +		element = PQgetvalue(pgsql_result,row->value.lval,i); +		element_len = (element ? strlen(element) : 0); +		element = safe_estrndup(element,element_len); +		if (element) { +            if (PG(magic_quotes_runtime)) { +                char *tmp=_php3_addslashes(element,element_len,&element_len,0); + +                add_get_index_stringl(return_value, i, tmp, element_len, (void **) &pval_ptr, 0); +            } else { +                add_get_index_stringl(return_value, i, element, element_len, (void **) &pval_ptr, 1); +            } +			field_name = PQfname(pgsql_result,i); +            _php3_hash_pointer_update(return_value->value.ht, field_name, strlen(field_name)+1, pval_ptr); +        } else { +            /* NULL field, don't set it */ +            /* add_get_index_stringl(return_value, i, empty_string, 0, (void **) &pval_ptr); */ +        } +	} +} + +/* ??  This is a rather odd function - why not just point pg_fetcharray() directly at fetch_hash ? -RL */ +/* {{{ proto array pg_fetch_array(int result, int row) +   Fetch a row as an array */ +void php3_pgsql_fetch_array(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} +/* }}} */ + +/* {{{ proto object pg_fetch_object(int result, int row) +   Fetch a row as an object */ +void php3_pgsql_fetch_object(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU); +	if (return_value->type==IS_ARRAY) { +		return_value->type = IS_OBJECT; +	} +} +/* }}} */ + +#define PHP3_PG_DATA_LENGTH 1 +#define PHP3_PG_DATA_ISNULL 2 + +void php3_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +{ +	pval *result,*row,*field; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type,field_offset; +	 +	if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &result, &row, &field)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	 +	convert_to_long(row); +	if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) { +		php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval); +		RETURN_FALSE; +	} +	switch(field->type) { +		case IS_STRING: +			field_offset = PQfnumber(pgsql_result,field->value.str.val); +			break; +		default: +			convert_to_long(field); +			field_offset = field->value.lval; +			break; +	} +	if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) { +		php3_error(E_WARNING,"Bad column offset specified"); +		RETURN_FALSE; +	} +	 +	switch (entry_type) { +		case PHP3_PG_DATA_LENGTH: +			return_value->value.lval = PQgetlength(pgsql_result,row->value.lval,field_offset); +			break; +		case PHP3_PG_DATA_ISNULL: +			return_value->value.lval = PQgetisnull(pgsql_result,row->value.lval,field_offset); +			break; +	} +	return_value->type = IS_LONG; +} + +/* {{{ proto int pg_fieldprtlen(int result, int row, mixed field_name_or_number) +   Returns the printed length */ +void php3_pgsql_data_length(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP3_PG_DATA_LENGTH); +} +/* }}} */ + +/* {{{ proto int pg_fieldisnull(int result, int row, mixed field_name_or_number) +   Test if a field is NULL */ +void php3_pgsql_data_isnull(INTERNAL_FUNCTION_PARAMETERS) +{ +	php3_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP3_PG_DATA_ISNULL); +} +/* }}} */ + +/* {{{ proto int pg_freeresult(int result) +   Free result memory */ +void php3_pgsql_free_result(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result; +	pgsql_result_handle *pg_result; +	int type; +	 +	if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	if (result->value.lval==0) { +		RETURN_FALSE; +	} +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	php3_list_delete(result->value.lval); +	RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int pg_getlastoid(int result) +   Returns the last object identifier */ +void php3_pgsql_last_oid(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *result; +	PGresult *pgsql_result; +	pgsql_result_handle *pg_result; +	int type; +	 +	if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) { +		WRONG_PARAM_COUNT; +	} +	 +	convert_to_long(result); +	pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type); +	 +	if (type!=php3_pgsql_module.le_result) { +		php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval); +		RETURN_FALSE; +	} +	pgsql_result = pg_result->result; +	return_value->value.str.val = (char *) PQoidStatus(pgsql_result); +	if (return_value->value.str.val) { +		return_value->value.str.len = strlen(return_value->value.str.val); +		return_value->value.str.val = estrndup(return_value->value.str.val, return_value->value.str.len); +		return_value->type = IS_STRING; +	} else { +		return_value->value.str.val = empty_string; +	}  +} +/* }}} */ + +/* {{{ proto int pg_locreate(int connection) +   Create a large object */ +void php3_pgsql_lo_create(INTERNAL_FUNCTION_PARAMETERS) +{ +  	pval *pgsql_link; +	PGconn *pgsql; +	Oid pgsql_oid; +	int id, type; +	 +	switch(ARG_COUNT(ht)) { +		case 0: +			id = php3_pgsql_module.default_link; +			break; +		case 1: +			if (getParameters(ht, 1, &pgsql_link)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	/* XXX: Archive modes not supported until I get some more data. Don't think anybody's +	   using it anyway. I believe it's also somehow related to the 'time travel' feature of +	   PostgreSQL, that's on the list of features to be removed... Create modes not supported. +	   What's the use of an object that can be only written to, but not read from, and vice +	   versa? Beats me... And the access type (r/w) must be specified again when opening +	   the object, probably (?) overrides this. (Jouni)  +	 */ + +	if ((pgsql_oid=lo_creat(pgsql, INV_READ|INV_WRITE))==0) { +		php3_error(E_WARNING,"Unable to create PostgresSQL large object"); +		RETURN_FALSE; +	} + +	return_value->value.lval = pgsql_oid; +	return_value->type = IS_LONG; +} +/* }}} */ + +/* {{{ proto void pg_lounlink([int connection, ] int large_obj_id) +   Delete a large object */ +void php3_pgsql_lo_unlink(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *pgsql_link, *oid; +	PGconn *pgsql; +	Oid pgsql_oid; +	int id, type; + +	switch(ARG_COUNT(ht)) { +		case 1: +			if (getParameters(ht, 1, &oid)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(oid); +			pgsql_oid = oid->value.lval; +			id = php3_pgsql_module.default_link; +			break; +		case 2: +			if (getParameters(ht, 2, &pgsql_link, &oid)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			convert_to_long(oid); +			pgsql_oid = oid->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} +	 +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	if (lo_unlink(pgsql, pgsql_oid)==-1) { +		php3_error(E_WARNING,"Unable to delete PostgresSQL large object %d", (int) pgsql_oid); +		RETURN_FALSE; +	} +	RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int pg_loopen([int connection,] int objoid, string mode) +   Open a large object and return fd */ +void php3_pgsql_lo_open(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *pgsql_link, *oid, *mode; +	PGconn *pgsql; +	Oid pgsql_oid; +	int id, type, pgsql_mode=0, pgsql_lofd; +	int create=0; +	char *mode_string=NULL; +	pgLofp *pgsql_lofp; + +	switch(ARG_COUNT(ht)) { +		case 2: +			if (getParameters(ht, 2, &oid, &mode)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(oid); +			pgsql_oid = oid->value.lval; +			convert_to_string(mode); +			mode_string = mode->value.str.val; +			id = php3_pgsql_module.default_link; +			break; +		case 3: +			if (getParameters(ht, 3, &pgsql_link, &oid, &mode)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_link); +			id = pgsql_link->value.lval; +			convert_to_long(oid); +			pgsql_oid = oid->value.lval; +			convert_to_string(mode); +			mode_string = mode->value.str.val; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} + +	pgsql = (PGconn *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) { +		php3_error(E_WARNING,"%d is not a PostgresSQL link index",id); +		RETURN_FALSE; +	} +	 +	/* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of +	   faster to type. Unfortunately, doesn't behave the same way as fopen()... +	   (Jouni) +	 */ + +	if (strchr(mode_string, 'r')==mode_string) { +		pgsql_mode |= INV_READ; +		if (strchr(mode_string, '+')==mode_string+1) { +			pgsql_mode |= INV_WRITE; +		} +	} +	if (strchr(mode_string, 'w')==mode_string) { +		pgsql_mode |= INV_WRITE; +		create = 1; +		if (strchr(mode_string, '+')==mode_string+1) { +			pgsql_mode |= INV_READ; +		} +	} + + +	pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp)); + +	if ((pgsql_lofd=lo_open(pgsql, pgsql_oid, pgsql_mode))==-1) { +		if (create) { +			if ((pgsql_oid=lo_creat(pgsql, INV_READ|INV_WRITE))==0) { +				efree(pgsql_lofp); +				php3_error(E_WARNING,"Unable to create PostgresSQL large object"); +				RETURN_FALSE; +			} else { +				if ((pgsql_lofd=lo_open(pgsql, pgsql_oid, pgsql_mode))==-1) { +					if (lo_unlink(pgsql, pgsql_oid)==-1) { +						efree(pgsql_lofp); +						php3_error(E_WARNING,"Something's really messed up!!! Your database is badly corrupted in a way NOT related to PHP."); +						RETURN_FALSE; +					} +					efree(pgsql_lofp); +					php3_error(E_WARNING,"Unable to open PostgresSQL large object"); +					RETURN_FALSE; +				} else { +					pgsql_lofp->conn = pgsql; +					pgsql_lofp->lofd = pgsql_lofd; +					return_value->value.lval = php3_list_insert(pgsql_lofp, php3_pgsql_module.le_lofp); +					return_value->type = IS_LONG; +				} +			} +		} else { +			efree(pgsql_lofp); +			php3_error(E_WARNING,"Unable to open PostgresSQL large object"); +			RETURN_FALSE; +		} +	} else { +		pgsql_lofp->conn = pgsql; +		pgsql_lofp->lofd = pgsql_lofd; +		return_value->value.lval = php3_list_insert(pgsql_lofp, php3_pgsql_module.le_lofp); +		return_value->type = IS_LONG; +	} +} +/* }}} */ + +/* {{{ proto void pg_loclose(int fd) +   Close a large object */ +void php3_pgsql_lo_close(INTERNAL_FUNCTION_PARAMETERS) +{ +	pval *pgsql_lofp; +	int id, type; +	pgLofp *pgsql; + +	switch(ARG_COUNT(ht)) { +		case 1: +			if (getParameters(ht, 1, &pgsql_lofp)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_lofp); +			id = pgsql_lofp->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} + +	pgsql = (pgLofp *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_lofp) { +		php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id); +		RETURN_FALSE; +	} +	 +	if (lo_close((PGconn *)pgsql->conn, pgsql->lofd)<0) { +		php3_error(E_WARNING,"Unable to close PostgresSQL large object descriptor %d", pgsql->lofd); +		RETVAL_FALSE; +	} else { +		RETVAL_TRUE; +	} +	php3_list_delete(id); +	return; +} +/* }}} */ + +/* {{{ proto string pg_loread(int fd, int len) +   Read a large object */ +void php3_pgsql_lo_read(INTERNAL_FUNCTION_PARAMETERS) +{ +  	pval *pgsql_id, *len; +	int id, buf_len, type, nbytes; +	char *buf; +	pgLofp *pgsql; + +	switch(ARG_COUNT(ht)) { +		case 2: +			if (getParameters(ht, 2, &pgsql_id, &len)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_id); +			id = pgsql_id->value.lval; +			convert_to_long(len); +			buf_len = len->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} + +	pgsql = (pgLofp *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_lofp) { +		php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id); +		RETURN_FALSE; +	} +	 +	buf = (char *) emalloc(sizeof(char)*(buf_len+1)); +	if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) { +		efree(buf); +		RETURN_FALSE; +	} +	return_value->value.str.val = buf; +	return_value->value.str.len = nbytes; +	return_value->value.str.val[nbytes] = 0; +	return_value->type = IS_STRING; +} +/* }}} */ + +/* {{{ proto int pg_lowrite(int fd, string buf) +   Write a large object */ +void php3_pgsql_lo_write(INTERNAL_FUNCTION_PARAMETERS) +{ +  	pval *pgsql_id, *str; +	int id, buf_len, nbytes, type; +	char *buf; +	pgLofp *pgsql; + +	switch(ARG_COUNT(ht)) { +		case 2: +			if (getParameters(ht, 2, &pgsql_id, &str)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_id); +			id = pgsql_id->value.lval; +			convert_to_string(str); +			buf = str->value.str.val; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} + +	pgsql = (pgLofp *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_lofp) { +		php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id); +		RETURN_FALSE; +	} +	 +	buf_len = str->value.str.len; +	if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))==-1) { +		RETURN_FALSE; +	} +	return_value->value.lval = nbytes; +	return_value->type = IS_LONG; +} +/* }}} */ + +/* {{{ proto void pg_loreadall(int fd) +   Read a large object and send straight to browser */ +void php3_pgsql_lo_readall(INTERNAL_FUNCTION_PARAMETERS) +{ +  	pval *pgsql_id; +	int i, id, tbytes, type; +	volatile int nbytes; +	char buf[8192]; +	pgLofp *pgsql; +	int output=1; + +	switch(ARG_COUNT(ht)) { +		case 1: +			if (getParameters(ht, 1, &pgsql_id)==FAILURE) { +				RETURN_FALSE; +			} +			convert_to_long(pgsql_id); +			id = pgsql_id->value.lval; +			break; +		default: +			WRONG_PARAM_COUNT; +			break; +	} + +	pgsql = (pgLofp *) php3_list_find(id,&type); +	if (type!=php3_pgsql_module.le_lofp) { +		php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id); +		RETURN_FALSE; +	} + +	tbytes = 0; +	while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, 8192))>0) { +		for(i=0; i<nbytes; i++) { +			if (output) PUTC(buf[i]); +		} +		tbytes += i; +	} +	return_value->value.lval = tbytes; +	return_value->type = IS_LONG; +} +/* }}} */ +	 +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */  | 
