database.php

来自「GForge 3.0 协作开发平台 支持CVS, mailing lists, 」· PHP 代码 · 共 507 行

PHP
507
字号
<?php//// SourceForge: Breaking Down the Barriers to Open Source Development// Copyright 1999-2000 (c) The SourceForge Crew// http://sourceforge.net//// $Id: database.php,v 1.1 2001/05/09 15:59:47 tperdue Exp $///*This document summarize the changes I made to SourceForge 2.5 code that supports Oracle 8 (oci8) database replacing postgres. The change coversthe oracle layer, namely the script database-oci8.php which is an ALPHAversion as claimed in its header, the database schema that is convertedfrom the postgres schema (file SourceForge.sql), and some PHP code withSQL statements that have wrong syntax, or with bugs.Part 1: database-oci8.php		The changes are made to correct the defects/bugs in this ALPHA 	version of OCI8 support in SourceForge 2.5. I used PHP version 	4 OCI functions and the working environment includes apache 	1.3.14 and Sun Solaris 2.6	Summary of changes:	. Eliminated all @ in front of the OCI function calls;	. Added ocicommit($conn) after ociexecute. OCI_COMMIT_ON_SUCCESS	  should take care of that, but somehow certain INSERT/UPDATE	  queries do not commit unless I call ocicommit.	. I use column name instead of column index number to retrieve	  column values here, though both should work due to the mode	  OCI_ASSOC+OCI_NUM used in ocifetchinto. The reason I make	  the change is that column names are used in most of PHP codes	  of SourceForge (I recall that a few places use numbers though)	  and I want to make it consistent. There is a defect here that	  I did not fix: the db_query will return if the value of the	  first column is null. This would cause problem if it happens	  that the value is null, not because it is at the end of the	  rows. The function could return less rows than actual result.	  I do not have time to figure out a better way to detect if we	  are at the end of the rows, considering that function db_query	  applies to SELECT, INSERT, UPDATE, DELETE, all the queries.	. The ALPHA code uses the returned value of ociexecute as the	  array index of the returned result rows. Note that the returned	  value is always 1 (if execution is successful) and if I have 	  two db_query calls and the result of the second call will 	  unexpectedly replace that of the first one. I use the returned	  handle of ociparse as the index instead, since the handle will	  be a different value for each db_query call. Then in all the 	  code of calling db_query, it would be nice to free that handle	  and the result array after the call. I guess it does not matter	  much since each PHP script runs once as a CGI program and then	  exit. If the PHP script is permanently loaded in web server	  after the call, that would cause memory leak problem. I will 	  try to clean the SourceForge PHP code that calls db_query later.	. There was a problem with $sys_db_row_pointer, fixed that.	. Oracle likes UPPER case names. If you try to SELECT rows from	  an oracle table, most likely you will get a upper case column	  name, which means you have to retrieve a column value like	  $x[USER_ID] or $x['USER_ID'] or $x["USER_ID"], and $x[user_id]	  or $x['user_id'] or $x["user_id"] will not work. I noticed that	  almost all of the SourceForge codes use lower case names. 	  A solution could be defining oracle tables like:		create table users ("user_id" varchar2(20), ...)	  In this case the field user_id is created in lower case in Oracle.	  As a result $x["user_id"] is correct.	  I personally does not like it due to that I have to do SELECT as:		select "user_id" from users	  Another solution is to make a copy of the returned rows and	  replace the upper case names to lower case when copying.	  Then make both result arrays available to the caller of db_query.	  I prefer this generic approach even it costs a little bit of	  memory and cpu. I have not done that though.	  What I did here is accepting upper case column names and changed	  all of the places in SourceForge that call db_query, or uses the	  result arrays. Anyhow I want to find out the places and free the	  arrays later when I have more time.Part 2: Database Schema	The schema enclosed in SF 2.5 is for postgres. I wrote a perl	script that converts the postgres SQL statements to Oracle.	The results are 3 separate files. File SourceForge_oci8.sql includes 	all the tables, sequences, indices. Table session has been renamed 	to session1, since it is a key word in Oracle DDL. Also all the 	fields date has been renamed to date1. Corresponding changes need 	to be made in places that refer to the table and/or fields.	File Trigger_auto.sql are triggers that used to implement the auto 	insertion of sequence numbers. Oracle does not allow 		"bug_id" integer DEFAULT nextval('bug_pk_seq'::text) NOT NULL,	So the triggers are necessary here. With these triggers, you can	insert a record without specify the sequence number, and the	trigger will get the next one and insert for you. If you do want	to specify sequences in your INSERT/UPDATE queries, the trigger	will take you number. 	File Trigger_er.sql is integrity constraint triggers defining the 	E-R among tables. I did not apply those in my case due to that I 	would not be able to insert the default rows after that. I will 	apply the constraints later.	Many fields are defined as text in postgres and I had trouble 	deciding what to do with it. There are a lot of limitation in 	Oracle to LONG and LOB fields. I use varchar2() to replace text 	even though the maximum bytes for varchar2() is 4000 (?). Most 	likely we will not run that limit and if any case, I can simply 	change it to LONG or LOB.Part 3: Misc Changes Fixing SQL Syntax or Bugs (incomplete)	File Name	Changes	------------------------------------------------------------------	account/login.php				added lines to set the hask cookie. Also added 			the 3rd parameters to session_login_valid. 			changed table name session to session1	account/logout.php			changed table name session to session1	admin/lastlogins.php			changed table name session to session1	admin/search.php			changed "distinctrow" to "unique"	admin/userlist.php			added select before insert statement	developer/monitor.php			changed variable user to user_id	docman/doc_utils.php			defined count(*) as cnt	forum/forum.php			changed table field date to date1	forum/forum_utils.php			changed table field date to date1. changed the			SELECT nextval('forum_thread_seq') to 			SELECT forum_thread_seq.nextval from dual	include/User.class			added select statement to get a user object	include/cache.php			comment out flock statements due to access rights.	include/osdn.php			image changed to /image. commented out some ads.	include/session.php			$allowingpending=0 changed to allowpending. added 			UPDATE statement to activate pending user accounts.			changed session to session1	include/user_home.php			changed user= to user_id=	my/diary.php			added a section to retrieve user object to set			$G_SESSION		news/news_utils.php			changed date to date1. changed a few http to https.	news/submit.php			changed date to date1	project/memberlist.php			changed the join to outer join in query	softwaremap/trove_list.php			changed the LEFT JOIN to outer join in Oracle.*/$sys_db_oci_commit_mode='OCI_COMMIT_ON_SUCCESS';/** * *  Connect to the database *  Notice the global vars that must be set up *  Sets up a global $conn variable which is used  *  in other functions in this library * */function db_connect() {	global $sys_dbuser,$sys_dbpasswd,$conn,$sys_dbname;	$conn = ocilogon($sys_dbuser,$sys_dbpasswd,$sys_dbname);	#return $conn;}/** * *  Query the database * *  @param qstring - SQL statement *  @param limit - how many rows do you want returned *  @param offset - of matching rows, return only rows starting here * * *  NOTE - the OCI version of this may be somewhat inefficient *  for large result sets (hundreds or thousands of rows selected) *  However - most queries are returning 25-50 rows * */function db_query($qstring,$limit='-1',$offset=0) {	global $conn,$QUERY_COUNT,$sys_db_results;        global $sys_db_row_pointer,$sys_db_oci_commit_mode;	$QUERY_COUNT++;	$stmt=ociparse($conn,$qstring);	if (!$stmt) {		return 0;	} else {		if ($limit > 0) {			if (!$offset || $offset < 0) {				$offset=0;			}		}		$res=ociexecute($stmt,$sys_db_oci_commit_mode);                ocicommit($conn);		if (!$res) {			return 0;		} else {			//if offset, seek to starting point			//potentially expensive if large offset			//however there is no data_seek feature AFAICT                        $col_name  = OCIColumnName($stmt,1);			$more_data=true;			if ($offset > 0) {				for ($i=0; $i<$offset; $i++) {					//burn them off					ocifetchinto($stmt,&$x,OCI_ASSOC+OCI_NUM);					if (!$x[$col_name]) {						//if no data be returned						//get out of loop						$more_data=false;						break;					}				}			}			$i=0;			while ($more_data) {                                unset($x);				$ret = ocifetchinto($stmt,&$x,OCI_ASSOC+OCI_NUM);				if (!$ret) {                                  //if no data be returned                                  //get out of loop                                  $more_data=false;                                  break;                                }				$i++;				$sys_db_results[$stmt][$i-1]=$x;				//see if data is being returned && we are 				//still within the requested $limit				if (count($x) < 1 || (($limit > 0) &&                                    ($i >= $limit)))                                 {					$more_data=false;				}			}			$sys_db_row_pointer[$stmt]=0;			return $stmt;		}	}}/** *      db_begin() * *      begin a transaction */function db_begin() {	global $sys_db_oci_commit_mode;	$sys_db_oci_commit_mode='OCI_DEFAULT';}/** *      db_commit() * *      commit a transaction */function db_commit() {	global $sys_db_oci_commit_mode,$conn;	$sys_db_oci_commit_mode='OCI_COMMIT_ON_SUCCESS';	return ocicommit($conn);}/** *      db_rollback() * *      rollback a transaction */function db_rollback() {	global $sys_db_oci_commit_mode,$conn;	$sys_db_oci_commit_mode='OCI_COMMIT_ON_SUCCESS';	return ocirollback($conn);}/** * *  Returns the number of rows in this result set * *  @param qhandle query result set handle * */function db_numrows($qhandle) {	global $sys_db_results;	// return only if qhandle exists, otherwise 0	if ($qhandle) {		return count($sys_db_results[$qhandle]);	} else {		return 0;	}}/** * *  Frees a database result properly  * *  @param qhandle query result set handle * */function db_free_result($qhandle) {	global $sys_db_results;	unset($sys_db_results[$qhandle]);	return ocifreestatement($qhandle);}/** * *  Reset is useful for db_fetch_array *  sometimes you need to start over * *  @param qhandle query result set handle *  @param row - integer row number * */function db_reset_result($qhandle,$row=0) {	global $sys_db_row_pointer;	return $sys_db_row_pointer[$qhandle]=$row;}/** * *  Returns a field from a result set * *  @param qhandle query result set handle *  @param row - integer row number *  @param field - text field name * */function db_result($qhandle,$row,$field) {	global $sys_db_results;        $fieldu = strtoupper($field);	return $sys_db_results[$qhandle][$row][$fieldu];}/** * *  Returns the number of fields in this result set * *  @param qhandle query result set handle * */function db_numfields($lhandle) {	return ocinumcols($lhandle);}/** * *  Returns the number of rows changed in the last query * *  @param qhandle - query result set handle *  @param fnumber - column number * */function db_fieldname($lhandle,$fnumber) {	   return ocicolumnname($lhandle,$fnumber);}/** * *  Returns the number of rows changed in the last query * *  @param qhandle query result set handle * */function db_affected_rows($qhandle) {	return ocirowcount($qhandle);}/** * *  Returns an associative array from  *  the current row of this database result *  Use db_reset_result to seek a particular row * *  @param qhandle query result set handle * */function db_fetch_array($qhandle) {	global $sys_db_results,$sys_db_row_pointer;        $row = $sys_db_row_pointer[$qhandle];        $sys_db_row_pointer[$qhandle] = $sys_db_row_pointer[$qhandle] + 1;        //$sys_db_row_pointer = $sys_db_row_pointer + 1;	return $sys_db_results[$qhandle][$row];}/** * *  Returns the last primary key from an insert * *  @param qhandle query result set handle *  @param table_name is the name of the table you inserted into *  @param pkey_field_name is the field name of the primary key * */function db_insertid($qhandle,$table_name,$pkey_field_name) {	$res=db_query("SELECT max($pkey_field_name) AS id FROM $table_name");	if ($res && db_numrows($res) > 0) {		return db_result($res,0,'id');	} else {		return 0;	}}/** * *  Returns the last error from the database * */function db_error() {	global $conn;	$err= ocierror($conn);	if ($err) {		return $err['message'];	} else {		return false;	}}?>

⌨️ 快捷键说明

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