<?
	#---------------------------------------------------------------------#
	# This source code is (c)2000 White Pajamas, Inc                      #
	# see http://www.stonekeep.com/license.html for licensing information #
	#---------------------------------------------------------------------#

	#--------------------------------------------------------------------
	# $Id: postgres.php3,v 1.15 2000/12/14 19:13:55 shevett Exp $
	#--------------------------------------------------------------------
	
	# PHP Database independent for PTS supporting: postgresql v6.x
	# Contributed by: Rolf (ebert@pe-muc.de)
	# updated and cleaned up by Roland Roberts (roberts@panix.com)


/*
	Current functions in need of work:
		db_fieldlen - Lots of extra Pg stuff needed here to get
			field length defined for a column. Further
			fixup needed to handle int data type. Other
			non-char and non-int data types not handled
			at all.

		db_listfields - PostgreSQL API has no equivalent
			call, needs to be faked by doing a "select
			*" query so $result is valid.

*/


	function db_connect ($target) {
		global $dbhost, $dbname, $dbuser, $dbpasswd, $server, $port, $options, $tty, $conn;
		$string = "";
		if ($dbuser != "")	{ $string .= "user=$dbuser ";		}
		if ($dbpasswd != "")	{ $string .= "password=$dbpasswd ";	}
		if ($dbname != "")	{ $string .= "dbname=$dbname ";		}
		if ($dbhost != "")	{ $string .= "host=$dbhost ";		}
		if ($port != "")	{ $string .= "port=$port ";		}
		if ($tty != "")		{ $string .= "tty=$tty ";		}
		if ($options != "")	{ $string .= "options=\"$options\" ";	}
		$conn = pg_Connect ($string);
	};


	function db_query ($qstring) {
		global $conn, $pg_curr_row;
		$result = pg_Exec ($conn, "$qstring");
		# This will break if different connections return the 
		# same query handle index (probable?).
		$pg_curr_row[$result] = 0;
		return $result;
	};


	function db_numrows ($qhandle) {
		if ($qhandle) {
			return pg_NumRows ($qhandle);
		} else {
			return 0;
		}
	};


	function db_result ($qhandle, $row, $field) {
		return chop(pg_Result ($qhandle, $row, $field));
	};


	# Unfortunately, we can't just return the names of the columns because
	# of the way MySQL works.  After this is called, each column will be examined 
	# and another query made to retrieve the name of the column that results from
	# this query.  If we don't query the table, we'll end up returning the name
	# of the column in the system catalogue instead of the name in the table.
	function db_listfields ($tname) {
		global $dbhost, $dbname, $server, $port, $options, $tty, $conn, $last_table;
		$last_table = $tname;		/* save for Pg use in db_fieldlen */
		if (!$conn) {
			$conn = pg_Connect ($dbhost, $port, $options, $tty, $dbname);
		}
                # PostgreSQL doesn't define MIN for oid types.
                # return pg_Exec ($conn, "SELECT * FROM $tname WHERE oid = MIN(oid)");
                return pg_Exec ($conn, "SELECT * FROM $tname");
	};


	function db_numfields ($lhandle) {
		return pg_NumFields ($lhandle);
	};


	function db_fieldname ($lhandle, $fnumber) {
		return pg_FieldName ($lhandle, $fnumber);
	};


	function db_fieldtype ($lhandle, $which) {
		LogIt("DEBUG","postgres.php3","db_fieldtype($lhandle, $which)");
		$name = pg_FieldName($lhandle,$which);
		LogIt("DEBUG","postgres.php3","field name = $name");
		if (   (pg_FieldName($lhandle,$which) == "_rowid")
		    && (db_fieldflags($lhandle, $which) == "primary key")) {
			LogIt("DEBUG","postgres.php3","returning index");
			return "index";
		} else {
			$type = pg_FieldType ($lhandle, $which);
			LogIt("DEBUG","postgres.php3","returning $type");
			return pg_FieldType ($lhandle, $which);
		}
	};


	function db_fieldlen ($lhandle, $which) {
		global $conn, $last_table;

		# At first glance this appears to be overkill because of the functions
		# pg_fieldsize and pg_fieldprtlen, but trust me they are not the what is
		# needed here. The worst of this hack is really the $last_table global.
		# special thanks to Roland Roberts (roberts@panix.com) for the fixes here.
		$aname = pg_FieldName ($lhandle, $which);
		$type  = pg_FieldType ($lhandle, $which);
		if ($type == "int4") {
			$result = 12;
		} else {
			$query	= "SELECT a.attnum, a.attname, t.typname, a.attlen, a.atttypmod "
				. "  FROM pg_class c, pg_attribute a, pg_type t "
				. "    WHERE c.relname = '$last_table' "
				. "    and a.attnum > 0 "
				. "    and a.attrelid = c.oid "
				. "    and a.atttypid = t.oid "
				. "    and a.attname  = '$aname' "
				. "  ORDER BY attnum ";
			$res = pg_Exec ($conn, "$query");
			$result = pg_Result ($res, 0, 4);
			$result = $result - 4;
		}

		return $result;
	};

	function db_affected_rows ($qhandle) {
		return pg_cmdTuples ($qhandle);
	};

	function db_fetch_array($qhandle) {
		global $pg_curr_row;
		$numfields = pg_numFields ($qhandle);

		if (pg_numrows ($qhandle) <= $pg_curr_row[$qhandle]) {
			return 0;
		}
		$row = pg_Fetch_Array ($qhandle, $pg_curr_row[$qhandle]);
		for ($i = 0; $i < $numfields; $i++) {
			$fieldname = pg_FieldName ($qhandle, $i);
			$arr[$fieldname] = $row[$i];
		}
		$pg_curr_row[$qhandle] += 1;
		return $arr;
	};
	
	function db_seek ($qhandle, $qrows) {
		global $pg_curr_row;
		$pg_curr_row[$qhandle] = $qrows;
		return $qrows;
	};
	
	function db_fieldflags ($qhandle, $which) {
		global $conn, $last_table;
		# Temporary cheat, see if this row is a primary key.
		# If not, return nothing.
		$query	= "SELECT i.indkey[0] "
			. "  FROM pg_class c, pg_class c2, pg_index i "
			. " WHERE c.relname='$last_table' "
			. "   AND c.oid=i.indrelid "
			. "   AND i.indexrelid = c2.oid "
			. "   AND c2.relname ~ '_pkey$'";
		$res   = pg_Exec ($conn, $query);
		if (pg_NumRows ($res) == 0) {
			return "";
		}
		$pkcol = pg_Result ($res, 0, 0) - 1;
		if ($pkcol == $which) {
			$result = "primary key";
		} else {
			$result = "";
		}
		return $result;
	};
	
	function db_primarykey ($tablename) {
		$fn = db_listfields("$tablename");
		$n  = db_numfields($fn);
		$priinfo[1] = "";
		$counter = 0;
		while ($counter < $n) {
			$finfo = db_fieldflags ($fn, $counter);
			if (ereg("primary key",$finfo)) {
				$priinfo[0] = db_fieldname($fn,$counter);
				$ftype=db_fieldtype ($fn, $counter);
				if ((  ("$ftype" == "string"))
				    || ("$ftype" == "bpchar")
				    || ("$ftype" == "varchar")) {
					$priinfo[1]="'";
				}
			}
			$counter++;
		}
		return ($priinfo);
	};

	function db_insertid ($r) {
		global $conn;

		$oid = pg_GetLastOID ($r);
		if (!$oid) {
		    echo pg_ErrorMessage($dbh) . "\n";
		    return "";
		}

		# This will search through all the tables in database keystone to find
		# the row with OID $oid, then return the value of the primary key column
		# for that row.	 This is not exactly what mysql_insertid does, but it
		# fits with the use of db_insertid.

		# Search the system catalogues to find all the tables.
		$query	= "SELECT c.relname "
			. "  FROM pg_class c "
			. " WHERE c.relkind = 'r'"
			. "   AND c.relname !~ '^pg_'";

		$res1 = pg_Exec ($conn, $query);

		if (!$res1) {
		    echo pg_ErrorMessage ($conn) . "\n";
		} else {
		    # For each table, query to see if the OID is present.
		    	for ($idx = 0; $idx < pg_NumRows ($res1); $idx++) {
				$row   = pg_Fetch_Row ($res1, $idx);
				$table = $row[0];
				$res2  = pg_Exec ($conn, "select oid from $table where oid = $oid");
				if (pg_NumRows ($res2) != 0) {
					# We found the OID in the current table, now find the name of the primary key column
					$query  = "SELECT a.attname FROM pg_class c, pg_attribute a, pg_index i, pg_class c2 "
						. " WHERE c.relname   = '$table' "
						. "   AND i.indrelid  = c.oid "
						. "   AND a.attrelid  = c.oid "
						. "   AND c2.oid      = i.indexrelid "
						. "   AND i.indkey[0] = a.attnum "
						. "   AND c2.relname  ~ '_pkey$'";
					$res2  = pg_Exec ($conn, $query);
					if ($res2) {
						$pkname	= pg_Result ($res2, 0, 0);
						$res2	= pg_Exec ("select $pkname from $table where oid = $oid");
						$row	= pg_Fetch_Row ($res2, 0);
						return $row[0];
					} else {
						return 0;
					}
					break;
				}
			}
		}
	};
?>
