<?php // include library db.php // database abstraction layer, supports multiple databases /* usage: - db_setdatabase will be called automatically each time you use db_sql (it will guarantee database availability) - you may call db_unsetdabatase at the end of your work (e.g. at end of script) - in normal operation use control constants in your main code and just call db_sql and similar functions control constants: - SERVER_DB_TYPE declares database type, e.g. "POSTGRESQL", "ODBC", "MYSQL" or others each database type needs some more special constants: POSTGRESQL: - SERVER_DB_HOST, e.g. "localhost" - SERVER_DB_PORT, e.g. 5432 - SERVER_DB_NAME, e.g. "testdatabase" - SERVER_DB_USER, e.g. "testuser" - SERVER_DB_PASS, e.g. "testpass" ODBC: - SERVER_DB_NAME, e.g. "testdatabase" - SERVER_DB_USER, e.g. "testuser" - SERVER_DB_PASS, e.g. "testpass" available functions: - db_setdb = checks/initializes database, will be called automatically - db_unsetdb = closes database manually, will be done automatically at the end of the parent script - db_sql = executes SQL statement and returns resultset - db_row = delivers a specific row from resultset, uses constants DB_ROW_* - db_fields = delivers field list from resultset, uses constants DB_FIELD_* */ define( "DB_TYPE_POSTGRESQL", "POSTGRESQL" ); define( "DB_TYPE_ODBC", "ODBC" ); define( "DB_ROW_FIRST", 0 ); define( "DB_ROW_NEXT", -1 ); define( "DB_ROW_LAST", -2 ); define( "DB_FIELD_NAME", 0 ); define( "DB_FIELD_TYPE", 1 ); define( "DB_FIELD_LEN", 2 ); // ********************************************************************** function db_setdb ( &$intdbconnid, &$strdberror ) // checks/opens database connection // updates parameter intdbconnid and strdberror // returns true if database had already been opened or has been opened successfully, // otherwise returns false and sets strdberror { $bolretcode = true; $strdberror = ''; if ( $intdbconnid == 0 ) { // database is dead or closed -> (re)open it switch ( trim(constant("SERVER_DB_TYPE")) ) { case constant("DB_TYPE_POSTGRESQL"): $intdbconnid = pg_connect ("host=" . trim(constant("SERVER_DB_HOST")) . " port=" . trim(strval(constant("SERVER_DB_PORT"))) . " dbname=" . trim(constant("SERVER_DB_NAME")) . " user=" . trim(constant("SERVER_DB_USER")) . " password=" . trim(constant("SERVER_DB_PASS"))); $strdberror = pg_last_error( $intdbconnid ); break; case constant("DB_TYPE_ODBC"): $intdbconnid = odbc_connect ( trim(constant("SERVER_DB_NAME")), trim(constant("SERVER_DB_USER")), trim(constant("SERVER_DB_PASS")), SQL_CUR_USE_ODBC ); $strdberror = odbc_errormsg( $intdbconnid ); break; default: // SERVER_DB_TYPE not supported! $intdbconnid = 0; $strdberror = 'Sorry, database of type "' . trim(constant("SERVER_DB_TYPE")) . '" is not supported.'; break; } // set return code on success $bolretcode = ( $intdbconnid != 0 ); } return $bolretcode; } // ********************************************************************** function db_unsetdb ( &$intdbconnid, &$strdberror ) // checks/closes database connection // updates parameter intdbconnid and strdberror // returns true if database had already been closed or has been closed successfully, // otherwise returns false and sets strdberror { $bolretcode = true; if ( $intdbconnid != 0 ) { // database is still opened -> close it switch ( constant("SERVER_DB_TYPE") ) { case constant("DB_TYPE_POSTGRESQL"): $bolretcode = pg_close ( $intdbconnid ); $strdberror = pg_last_error( $intdbconnid ); break; case constant("DB_TYPE_ODBC"): $bolretcode = odbc_close ( $intdbconnid ); $strdberror = odbc_errormsg( $intdbconnid ); break; default: // SERVER_DB_TYPE not supported! $bolretcode = false; $strdberror = 'Sorry, database of type "' . constant("SERVER_DB_TYPE") . '" is not supported.'; break; } // clear database connection id on success if ( $bolretcode ) { $intdbconnid = 0; } } return $bolretcode; } // ********************************************************************** function db_sql ( &$intdbconnid, $strdbsql, &$intdbresult, &$lngdbrows, &$strdberror ) // executes SQL statement on given database connection // updates parameter intdbconnid, intdbresult, lngdbrows and strdberror // returns true and sets intdbresult and lngdbrows if SQL statement had been executed successfully, // otherwise returns false and sets strdberror { $bolretcode = false; $intdbresult = 0; $lngdbrows = 0; $strdberror = ''; if ( db_setdb( $intdbconnid, $strdberror )) { // database is ok switch ( constant("SERVER_DB_TYPE") ) { case constant("DB_TYPE_POSTGRESQL"): $intdbresult = pg_query ( $intdbconnid, $strdbsql ); $strdberror = pg_last_error( $intdbconnid ); if ( $intdbresult != 0 ) { $lngdbrows = pg_num_rows( $intdbresult ) + pg_affected_rows( $intdbresult ); $bolretcode = true; } break; case constant("DB_TYPE_ODBC"): $intdbresult = odbc_exec ( $intdbconnid, $strdbsql ); $strdberror = odbc_errormsg( $intdbconnid ); if ( $intdbresult != 0 ) { // Attention: odbc_num_rows may return wrong record count in SELECT-statements! // to retrieve exact number of records in SELECT statements you should walk through the recordset $lngdbrows = odbc_num_rows( $intdbresult ); $bolretcode = true; } break; default: // SERVER_DB_TYPE not supported! $bolretcode = false; $strdberror = 'Sorry, database of type "' . constant("SERVER_DB_TYPE") . '" is not supported.'; break; } } return $bolretcode; } // ********************************************************************** function db_row ( $intdbresult, &$strdbrow, $intdbrow, &$strdberror ) // fetches row on position intdbrow from intdbresult as associative array into strdbrow // position intdbrow may be DB_RESULT_NEXTROW to fetch the next row of intdbresult // updates parameter strdbrow, strdberror // returns true and sets strdbrow if row has been fetched successfully, // otherwise returns false and sets strdberror { $bolretcode = false; $strdbrow = ''; $strdberror = ''; if ( $intdbresult != 0 ) { // resultset is ok switch ( constant("SERVER_DB_TYPE") ) { case constant("DB_TYPE_POSTGRESQL"): switch ( $intdbrow ) { case constant("DB_ROW_FIRST"): $bolretcode = ( $strdbrow = pg_fetch_assoc( $intdbresult, 0 )); break; case constant("DB_ROW_NEXT"): $bolretcode = ( $strdbrow = pg_fetch_assoc( $intdbresult )); break; case constant("DB_ROW_LAST"): $bolretcode = ( $strdbrow = pg_fetch_assoc( $intdbresult, pg_num_rows( $intdbresult ) - 1 )); break; default: // specific $intdbrow given -> use it directly, offer start at position 1 $bolretcode = ( $strdbrow = pg_fetch_assoc( $intdbresult, $intdbrow - 1 )); break; } $strdberror = pg_result_error( $intdbresult ); break; case constant("DB_TYPE_ODBC"): switch ( $intdbrow ) { case constant("DB_ROW_FIRST"): $bolretcode = ( $strdbrow = odbc_fetch_array( $intdbresult, 0 )); break; case constant("DB_ROW_NEXT"): $bolretcode = ( $strdbrow = odbc_fetch_array( $intdbresult )); break; case constant("DB_ROW_LAST"): // Attention: odbc_num_rows may return wrong record count in SELECT-statements! // to retrieve exact number of records in SELECT statements you should walk through the recordset $bolretcode = ( $strdbrow = odbc_fetch_array( $intdbresult, odbc_num_rows( $intdbresult ) - 1 )); break; default: // specific $intdbrow given -> use it directly, offer start at position 1 $bolretcode = ( $strdbrow = odbc_fetch_array( $intdbresult, $intdbrow - 1)); break; } // ODBC does not support error messages on resultset level if ( !$bolretcode ) { $strdberror = 'Sorry, could not read result row on position ' . $intdbrow ; } break; default: // SERVER_DB_TYPE not supported! $bolretcode = false; $strdberror = 'Sorry, database of type "' . constant("SERVER_DB_TYPE") . '" is not supported.'; break; } } else { $bolretcode = false; $strdberror = 'Sorry, no data available to read.'; } return $bolretcode; } // ********************************************************************** function db_fields ( $intdbresult, &$strdbfields, &$strdberror ) // returns list of field names, field type and field length from intdbresult as associative arrays into strdbfields // strdbfields will contain following partial arrays: DB_FIELD_NAME, DB_FIELD_TYPE, DB_FIELD_LEN // use as following: $strdbfields[constant("DB_FIELD_*")][$intdbfield or $strdbfieldname] // example: $intdbfieldtype[$strdbfieldname] = $strdbfields[constant("DB_FIELD_TYPE")][$strdbfieldname] // updates parameter strdbfields, strdberror // returns true and sets strdbfields if field names have been retrieved successfully, // otherwise returns false and sets strdberror { $bolretcode = false; $strdbfields = array (constant("DB_FIELD_NAME") => array(), constant("DB_FIELD_TYPE") => array(), constant("DB_FIELD_LEN") => array()); $strdberror = ''; $intindex = 0; if ( $intdbresult != 0 ) { // resultset is ok //no errors expected at all $bolretcode = true; switch ( constant("SERVER_DB_TYPE") ) { case constant("DB_TYPE_POSTGRESQL"): // field numeration in PostgreSQL starts with 0 $intindex = 0; while ( $intindex < pg_num_fields( $intdbresult )) { array_push ( $strdbfields[constant("DB_FIELD_NAME")], pg_field_name( $intdbresult, $intindex )); array_push ( $strdbfields[constant("DB_FIELD_TYPE")], pg_field_type( $intdbresult, $intindex )); array_push ( $strdbfields[constant("DB_FIELD_LEN")], pg_field_prtlen( $intdbresult, $intindex )); $intindex++; } $strdberror = pg_result_error( $intdbresult ); break; case constant("DB_TYPE_ODBC"): // field numeration in ODBC starts with 1 $intindex = 1; while ( $intindex <= odbc_num_fields( $intdbresult )) { $strfieldname = odbc_field_name( $intdbresult, $intindex ); array_push ( $strdbfields[constant("DB_FIELD_NAME")], $strfieldname ); array_push ( $strdbfields[constant("DB_FIELD_TYPE")], odbc_field_type( $intdbresult, $intindex )); array_push ( $strdbfields[constant("DB_FIELD_LEN")], odbc_field_len( $intdbresult, $intindex )); $intindex++; } // ODBC does not support error messages on resultset level if ( !$bolretcode ) { $strdberror = 'Sorry, could not read field names.'; } break; default: // SERVER_DB_TYPE not supported! $bolretcode = false; $strdberror = 'Sorry, database of type "' . constant("SERVER_DB_TYPE") . '" is not supported.'; break; } } else { $bolretcode = false; $strdberror = 'Sorry, no data available to read.'; } return $bolretcode; } ?>