> -----Original Message----- > From: Lars Nielsen [mailto:lars@xxxxxxxxxx] > Sent: Tuesday, February 02, 2010 12:24 PM > To: php-general@xxxxxxxxxxxxx > Subject: database abstraction layer > > Hi List > > I am trying to make a Database Abstraction Layer so I can which the DB > of my application between MySQL and Postgresql. I have been looking at > the way phpBB does it, and it seems that it is only then php-functions > which are different. The SQL seems to be the same. > > Is it save to assume that I can use the same SQL, or should i > make some > exceptions? > > Regards > Lars Nielsen There are differences in the actual schema between mySQL and Postgress. At least there were a few years back when we looked at converting. In the end, we decided it was too much hassle to switch all our code and database tables, so just coughed up the licensing for mysql (we were shipping mysql on our appliance). So, before you jump into writing all this code, I would first try to make your app run in postgress and find out about which mySQL statements are 'extensions' to ANSI standard. Case sensitivity was a huge issue for us, as in one of those RDBMS was very particular about it. There were some other issues that I can't remember ATM, but perhaps they've been addressed by now. One thing I would maybe suggest is (what I do), write a wrapper around your wrapper -- AKA "Double Bag It". :) Here at Panasonic Avionics (PAC) we use the PEAR::DB class (the really old version) since we have to interface with mySQL, SQL Server, Oracle (two versions). That's where PEAR::DB comes in. However, it's very crude and you have a lot of redundant code in every page. Like this: http://pear.php.net/manual/en/package.database.db.intro-fetch.php You always have to open a connection, test for errors, do the query, test for errors, fetch the rows, etc.. When I came on board a year ago, I put an end to that micky mouse crap. I wrote a nice db.inc.php wrapper that handles all that sort of thing, and then pumps it up like it's on steroids. I added auto-reconnect in case the connection dropped. I added color-coded SQL output with substitution for the '?'. I added a last_insert_it() routine which is proprietary to mySQL BTW (speaking of incompatibilities). I added routines to get an Enum column, or to get a simple array pairing, etc. It can even force reads from slave and writes to master! It pretty much kicks ass. Just simply do this: $myfoo = sql_query('agis_core', 'SELECT * FROM foo WHERE bar = ?', $bar); All the minutia is handled for you and $myfoo is now an array of your results. :) So, now we code using my wrapper and should we want to switch out the DBAL later to a more modern one, we just change OUR wrapper calls. There is minimal overhead, and the pros FAR outweigh any cons. I've attached it here. We have another config.inc.php that has the DB settings for each DEV/TEST/PROD master/slave servers (as they are all different accounts for security reasons. So just make one with entries like this: // AGISCore Database DEV Master mySQL: $global_db_dsn_agis_core_master = array( 'phptype' => 'mysql', 'username' => 'RWMaster', 'password' => 'rwmaster', 'hostspec' => '10.10.10.2:3306', 'database' => 'agis_core', 'persistent' => TRUE ); // AGISCore Database DEV Slave mySQL: $global_db_dsn_agis_core_slave = array( 'phptype' => 'mysql', 'username' => 'ROSlave', 'password' => 'roslave', 'hostspec' => '10.10.10.3:3306', 'database' => 'agis_core', 'persistent' => TRUE ); $GLOBALS['DB_CONNECTIONS'] is a singleton (sans the class overhead) so that you always get the same handle for each database call and don't spawn new ones each time. Nice. :)
<?php /** * All of the database wrapper functions * * This is a wrapper around the PEAR::DB class. It provides many enhancements including * a singleton for database handle connections, retries for connections, debugging with ? substitutions, * handy routines to populate arrays, select boxes, IN() statements, etc. It can do SQL timing profiling. * There are routines for INSERT and UPDATE by simply passing in an array of key/value pairs. * * Confidential property of Panasonic Avionics. Do not copy or distribute. * @copyright 2006-2010 Panasonic Avionics. All rights reserved. * @category CategoryName * @package PackageName * @see * @since DART2 * @author Daevid Vincent <daevid.vincent@xxxxxxxxxxxxxx> * @date Created: 2009-01-20 * @version CVS: $Id: db.inc.php,v 1.39 2010/01/29 01:35:30 vincentd Exp $ */ require_once '/usr/share/php/DB.php'; $SQL_OPTION['noHTML'] = false; $SQL_OPTION['fullQuery'] = true; $SQL_OPTION['useLogger'] = false; $SQL_OPTION['profile'] = 0; $SQL_OPTION['debug'] = false; $SQL_OPTION['outfile'] = false; //set this to a filename, and use $show_sql in your queries and they'll go to this file. $GLOBALS['DB_CONNECTIONS'] = array(); //this will hold each db connection so we'll only create one at a time. like a singleton. /** * A wrapper around the SQL query function that provides many extra features. * * Handles the $db handle, errors and echoing of the SQL query itself * and stores any errors in the $GLOBALS['SQL_ERROR_STRING']; * * NOTE: PEAR:DB has many shortcomings, one of which is that the key of the returned hash will be lowercased! * * Prepared statements can use ?, !, & -- see http://pear.php.net/manual/en/package.database.db.intro-execute.php for more information. * * @access public * @return mixed a hash of data, a result set handle pointer or false * @param string $database the database to connect to (agis_core) is the default * @param string $sql The SQL query to be executed, this can be SELECT, INSERT, UPDATE or DELETE amongst others. * @param array $sqlvalues The sqlvalues to the $sql. One element per ? is required if this parameter is used. * @param boolean $show_sql output the $sql to the display (for debugging purposes usually). false by default. * @param array $parameters * int db_fetch_mode (DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT) * boolean $show_errors output any errors encountered to the display (for debugging purposes usually). true by default. * boolean $execute useful for debuging when you don't want the SQL command to actually execute, but you may want to see the query passed i.e. SQL_QUERY($sql, true, true, false); true by default. * boolean $no_html when using the function in console scripts to strip off HTML tags. * int $parameters['profile'] detail level (1-3) to output the SQL to /tmp/SQL_profile.txt. * profile SQL statements in varying detail levels. * Detail Levels: * 1 = m/d/y/ h:i:s * 2 = SQL timing * 3 = filename * @see sql_connect() * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 06/04/09 * @todo Intercept SELECT vs. INSERT/UPDATE/DELETE and connect to SLAVE vs MASTER respectively */ function sql_query($database='agis_core', $sql, $sqlvalues=array(), $show_sql=false, $parameters=array()) { if (!isset($parameters['db_fetch_mode'])) $parameters['db_fetch_mode'] = DB_FETCHMODE_ASSOC; //DB_FETCHMODE_ORDERED is the other common one to use if (!isset($parameters['show_errors'])) $parameters['show_errors'] = true; if (!isset($parameters['execute'])) $parameters['execute'] = true; if (!isset($parameters['no_html'])) $parameters['no_html'] = false; if (!isset($parameters['profile'])) $parameters['profile'] = 0; //var_dump($parameters); //$show_sql = true; //[dv] The PEAR::DB library is so horribly stupid that if you don't have any '?' but you do pass in $sqlvalues, // your result set will be an indexed array instead of a k:v hash -- regardless of forcing DB_FETCHMODE_ASSOC. UGH! if (is_null($sqlvalues) || strpos($sql, '?') === false) $sqlvalues = array(); elseif (!empty($sqlvalues) && !is_array($sqlvalues)) $sqlvalues = array($sqlvalues); //var_dump($sqlvalues); global $SQL_OPTION; //[dv] the preg_replace will magically strip out the spaces, newlines, tabs and other funky chars to make one nice string. $sql = preg_replace("/\s+/",' ', (preg_replace("/\s/",' ',trim($sql))) ); if ($SQL_OPTION['debug'] || $show_sql) { if ($parameters['no_html'] || $SQL_OPTION['noHTML'] || $SQL_OPTION['outfile']) $sql = str_replace( array("\n", "\r", ' '), ' ', $sql); $out_sql = '['.$database.'] '.sql_substitute_values($sql, $sqlvalues); if ($SQL_OPTION['outfile']) file_put_contents($SQL_OPTION['outfile'], 'SQL: '.$out_sql."\n", (FILE_APPEND | LOCK_EX) ); elseif ($parameters['no_html'] || $SQL_OPTION['noHTML']) echo "SQL: ".$out_sql."\n"; else { $out_sql = sql_print($out_sql); echo $out_sql; } } if ($parameters['execute'] === true) { // execute query only if it appears to be safe. if ( ($error_str = sql_is_safe_query($sql)) === TRUE ) { if (!sql_connect($database,false)) return false; //this loads $GLOBALS['DB_CONNECTION'][$database] //start profile stuff for this query if ($SQL_OPTION['profile'] > 0) $parameters['profile'] = $SQL_OPTION['profile']; if ($parameters['profile'] > 0) { if (!$handle = fopen("/tmp/SQL_profile.txt", 'a')) { echo "unable to open file /tmp/SQL_profile.txt\n"; $parameters['profile'] = 0; } $text = date("[m/d/y h:i:s "); if ($parameters['profile'] >= 2) $sql_start = microtime(true); //start timer } //[dv] PEAR::DB is so LAME! that we have to FORCE the mode here, //despite the fact that it should allow it to be passed as a parameter. What Garbage. //http://pear.php.net/manual/en/package.database.db.db-common.setfetchmode.php $GLOBALS['DB_CONNECTION'][$database]->setFetchMode($parameters['db_fetch_mode']); //determine if we need to do a 'query' or a 'getAll' //so first grab the very first word of the $sql (stripping out newlines) preg_match('/^\(?(\w+) /', str_replace( array("\n", "\r", ' '), ' ', $sql), $matches); $first_word = strtolower($matches[1]); //echo "first_word = $first_word<br/>\n"; if (in_array($first_word, array('select','show','explain'))) { $result =& $GLOBALS['DB_CONNECTION'][$database]->getAll($sql, $sqlvalues, $parameters['db_fetch_mode']); } elseif ( in_array($first_word, array('insert','update','create', 'drop', 'delete','set','/*!40014','start')) or in_array(strtolower($sql), array('commit','rollback'))) { //TODO: eventually this should do something like this: //if ('agis_core' == $database) // $result =& $GLOBALS['DB_CONNECTION']['agis_core_master']->query($sql,$sqlvalues); //else $result =& $GLOBALS['DB_CONNECTION'][$database]->query($sql, $sqlvalues); } else { notification_table('error',"db.inc.php::sql_query() does not know how to handle '<b>".$first_word."</b>'<br/>\n".sql_print($sql)); backtrace(true); exit; //we purposely exit here because any SQL after this point might give unexpected results. } if (DB::isError($result)) { //var_dump($result); preg_match("/\[nativecode=(\d+) \*\* (.*)\]/", $result->getUserInfo(), $errormatch); $error = ' Error '.$errormatch[1]."<br/>\n".$errormatch[2]."<br/>\n"; $result = FALSE; } //end of profiling stuff for this query if ($parameters['profile'] > 0) { if ($parameters['profile'] >= 2) $text .= number_format( (microtime(true) - $sql_start), 4 ).'s'; //end timer //we do this here so as not to upset the timer too much if ($parameters['profile'] >= 3) { $text .= ' '.$_SERVER['SCRIPT_FILENAME']; $traceArray = debug_backtrace(); $text .= ' '.$traceArray[1]['file'].' ('.$traceArray[1]['line'].')'; $text = str_replace('/public_html/', '', $text); } $sql = str_replace("\n", ' ', $sql); $sql = preg_replace('/\s+/',' ', $sql); if (!fwrite($handle, $text.'] '.$sql."\n")) { echo "unable to write to file /tmp/SQL_profile.txt\n"; } @fclose($handle); } } else { $error = "Malformed query (".$error_str."). Execution blocked."; $result = FALSE; // indicate that we failed } if ($result === false) { $GLOBALS['SQL_ERROR_STRING'] = ''; // if error has not been set, then we have a 'regular' mysql error. Otherwise it is a potentially malicious query. /* if(!isset($error)) { $error = mysql_error($GLOBALS['DB_CONNECTION']); $errno = mysql_errno($GLOBALS['DB_CONNECTION']); } else $errno = 0; // not 'regular' mysql error? well, we need some error code anyway. */ // trim to size if necessary if(!$SQL_OPTION['fullQuery']) $error = substr($error,0,100)."..."; if ($parameters['show_errors']) { if ($parameters['no_html'] || $SQL_OPTION['noHTML']) $sql = preg_replace("/\s+/",' ', (preg_replace("/\s/",' ',$sql)) ); if (!$out_sql) $out_sql = sql_print($sql, $sqlvalues, $database); $GLOBALS['SQL_ERROR_STRING'] .= "<B><U>SQL ERROR</U> ::</B>".$error."<br/><font SIZE='-2'>".$out_sql."</font>".backtrace(false); //TODO: [dv] is there a way to determine if we're in a CGI vs. Web page? if ($parameters['no_html'] || $SQL_OPTION['noHTML']) { //$GLOBALS['SQL_ERROR_STRING'] = preg_replace("/\s+/",' ', (preg_replace("/\s/",' ',$GLOBALS['SQL_ERROR_STRING'])) ); echo strip_tags($GLOBALS['SQL_ERROR_STRING'])."\n"; } else notification_table('error', $GLOBALS['SQL_ERROR_STRING']); //echo "<PRE STYLE='text-align: left; border: thin solid Red; padding: 5px;'><font CLASS='error'>".$GLOBALS['SQL_ERROR_STRING']."</font></PRE><BR>\n"; if ($SQL_OPTION['outfile']) { //echo "Dumping error to outfile: ".$SQL_OPTION['outfile']."\n"; file_put_contents($SQL_OPTION['outfile'], strip_tags($GLOBALS['SQL_ERROR_STRING']."\n"), (FILE_APPEND | LOCK_EX) ); } //if ($SQL_OPTION['useLogger']) logger(strip_tags($GLOBALS['SQL_ERROR_STRING'])); } //if ($parameters['show_errors']) } //if (!$result) //TODO: [dv] this should work, we just have to go audit the code for all the LIMIT 1 areas as they use [0] probably still... //now check if there was a LIMIT 1 //if ($result && $first_word == 'select' && is_array($result) && preg_match('/( limit 1$)/i', $sql)) $result =& $result[0]; //return the first row as a convenience return $result; } else { if ($show_sql) { global $SQL_INT; echo "<font color='#0000FF' style='background-color:#ffffff;'><B>DEBUG SQL[".($SQL_INT-1)."]:</font> <font color='#FF0000'>Not Executed</B></font><br/>\n"; } } return true; } /** * Output the HTML debugging string in color coded glory for a sql query * This is very nice for being able to see many SQL queries * * @access public * @return string HTML color coded string of the input $query. * @param string $query The SQL query to be executed. * @param string $database (null) an optional string to print as the database * @see sql_substitute_values() * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 05/27/09 * @todo highlight SQL functions. */ function sql_print($query, $sqlvalues=array(), $database=null) { if (!$query) return false; $query = sql_substitute_values($query, $sqlvalues); global $SQL_INT; if( !isset($SQL_INT) ) $SQL_INT = 0; //[dv] I like my version better... //require_once 'classes/geshi/geshi.php'; //$geshi =& new GeSHi($query, 'sql'); //echo $geshi->parse_code(); //return; $query = str_replace( array("\n", "\r", ' '), ' ', $query); //[dv] this has to come first or you will have goofy results later. //[dv] work in progress. was trying to show comments in gray... // I think I need to use a sprintf() or maybe preg_replace_callback() to sequence the COMMENT_BLOCK_Xs /* $comment_pattern = "/(\/\*.*?\*\/)/i"; preg_match_all($comment_pattern, $query, $comments); unset($comments[0]); //print_r($comments); $query = preg_replace($comment_pattern, "COMMENT_BLOCK", $query, -1); */ //[dv] TODO: UGH this number one is causing me lots of grief... why can't i figure out the regex to use? //highlight numbers //$query = preg_replace("/[\s=](\d+)\s/", "<font color='#FF6600'>$1</font>", $query, -1); //underline tables/databases but nothing in single quote marks as those are strings //FIXME: [dv] this will match something like "MYFUNCTION(table_name.column)" and print it later as "MYFUNCTION table_name.column)" // Note how the first ( is missing after the MYFUNCTION name $query = preg_replace("/[^']`?\b(\w+)\.`?/", " <u>$1</u>.", $query, -1); //highlight strings between quote marks $query = preg_replace("/['\"]([^'\"]*)['\"]/i", "'<font color='#FF6600'>$1</font>'", $query, -1); //highlight functions $query = preg_replace("/(\w+)\s?\(/", "<font color='#CC00FF'>".strtoupper('\\1')."</font>(", $query, -1); $query = str_ireplace( array ( '*', 'SELECT ', ' GROUP BY ', 'UPDATE ', 'DELETE ', 'INSERT ', 'INTO ', 'VALUES ', 'FROM ', 'LEFT ', 'JOIN ', 'WHERE ', 'LIMIT ', 'ORDER BY ', ' AND ', ' OR ', //[dv] note the space. otherwise you match to 'colOR' ;-) ' DESC', ' ASC', ' ON ', ' AS ', ' NULL' ), array ( "<font color='#FF6600'><b>*</b></font>", "<font color='#00AA00'><b>SELECT </b></font>", "<font color='#00AA00'><b> GROUP BY </b></font>", "<font color='#00AA00'><b>UPDATE </b></font>", "<font color='#00AA00'><b>DELETE </b></font>", "<font color='#00AA00'><b>INSERT </b></font>", "<font color='#00AA00'><b>INTO </b></font>", "<font color='#00AA00'><b>VALUES </b></font>", "<font color='#00AA00'><b>FROM </b></font>", "<font color='#00CC00'><b>LEFT </b></font>", "<font color='#00CC00'><b>JOIN </b></font>", "<font color='#00AA00'><b>WHERE </b></font>", "<font color='#00AA00'><b>LIMIT </b></font>", "<font color='#00AA00'><b>ORDER BY</b> </font>", "<font color='#0000AA'> <b>AND</b> </font>", "<font color='#0000AA'> <b>OR</b> </font>", "<font color='#0000AA'> <b>DESC</b></font>", "<font color='#0000AA'> <b>ASC</b></font>", "<font color='#00DD00'> <b>ON</b> </font>", "<font color='#0000AA'> <b>AS</b> </font>", "<font color='#FF00FF'> <b>NULL</b></font>" ), $query ); //[dv] work in progress. was trying to show comments in gray... /* if ($comments[1]) { foreach($comments[1] as $c) { $cb[] = 'COMMENT_BLOCK'; $crepl[] = "<font color='#dddddd'>".$c."</font>"; } //sadly this doesn't do a 1:1 match in each array. it matches COMMENT_BLOCK then quits after $crepl[0] $query = str_replace($cb, $crepl, $query); } */ $query = "<font color='#0000FF' style='background-color:#ffffff;'><B>DEBUG SQL[".$SQL_INT++."]:</B> ".$query."<font color='#FF0000'>;</font></font><br/>\n"; if ($database) $query = '['.$database.'] '.$query; return $query; } /** * Substitutes the sqlvalues into the query for debugging purposes * * @access public * @return string * @param string $query The SQL query * @param array $sqlvalues the sqlvalues to be substituted into the $query * @see sql_print() * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 05/27/09 * @todo put the DB_common::quoteSmart() around the sqlvalues */ function sql_substitute_values($query, $sqlvalues=array()) { if (!$sqlvalues || count($sqlvalues) < 1) return $query; $query = str_replace('?', "'%s'", $query); //TODO: wedge in http://pear.php.net/manual/en/package.database.db.db-common.quotesmart.php here for each parameter //so the debug is more in line with what the real $query should be. return vsprintf($query, $sqlvalues); } /** * @return int Number of rows in the result set * @access public * @param object $result result set * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] */ function sql_num_rows($result) { if ($result) return $result->numRows(); else return false; } /** * A wrapper around the sql_query function to return an array of key/value pairs. * * This is very useful for those tables that are simply a key/value and you'd like it in an array * then you can just reference the array and save yourself a JOIN perhaps. * * If only one column is given, then the values are a sequential array. * If two columns are returned, then they are mapped as $col[0] => $col[1] * * @access public * @return array of key/value pairs. * @param string $sql The SQL SELECT query to be executed in an order such as "SELECT id, name FROM foo ORDER BY name" * @param boolean $show_sql output the $sql to the display (for debugging purposes usually). false by default. * @param array $parameters (see sql_query() for available key/value pairs) * @see sql_query() * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 05/28/09 */ function sql_query_array_pair($database='agis_core', $sql, $sqlvalues=array(), $show_sql=false, $parameters=array()) { $parameters['db_fetch_mode'] = DB_FETCHMODE_ORDERED; //this has to be an ordered array as we don't know the hash keys in an associative one if ($result = sql_query($database, $sql, array(), $show_sql, $parameters)) { foreach($result as $key => $value) { if (!$value[1]) $tmpArray[] = $value[0]; else $tmpArray[ $value[0] ] = $value[1]; } return $tmpArray; } return false; } /** * This will return the last inserted ID -- from a mySQL database only * * @return int Insert ID of last insert action * @access public * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @see sql_insert() */ function sql_insert_id() { //not sure the PEAR equivallent for this one? //http://pear.php.net/manual/en/package.database.db.php //http://us3.php.net/manual/en/function.mysql-insert-id.php //could also use a raw query: 'SELECT LAST_INSERT_ID()' return @mysql_insert_id(); } /** * @return int Number of affected rows * @param string the database to connect to (agis_core_master) is the default * @access public * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] */ function sql_affected_rows($database='agis_core_master') { //http://pear.php.net/manual/en/package.database.db.db-common.affectedrows.php return $GLOBALS['DB_CONNECTION'][$database]->affectedRows(); } /** * Free up a mysql pointer * * @access public * @param object $result result set * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] */ function sql_free($result) { //http://pear.php.net/manual/en/package.database.db.db-result.free.php if ($result) return $result->free(); else return false; } /** * perform the smart quoting for SQL queries * * @param string $s the string to be quoted * @param boolean $trim trim leading and trailing space (true) * @param string $database a database connection to use ('agis_core') * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @return string */ function sql_escape($s, $trim=true, $database='agis_core') { if ($trim) $s = trim($s); return sql_connect($database)->quoteSmart($s); } /** * Outputs the error message from a failed SQL query/command/connection. * * @access public * @return void * @param object $db_resource the result of a sql_connect() or a sql_query $result * if a string (such as 'agis_core') is passed in, it is automatically converted to the corresponding singleton object $GLOBALS['DB_CONNECTION'][$db_resource]. * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @see sql_connect(), sql_query() * @date 2010-01-12 */ function sql_db_error($db_resource) { //var_dump($db_resource); if (is_string($db_resource)) $db_resource = $GLOBALS['DB_CONNECTION'][$db_resource]; if (!$db_resource) return "Invalid resource in sql_db_error().<br/>\n"; $error = ''; if (PEAR::isError($db_resource)) { $error .= '<b>Standard Message:</b> '.$db_resource->getMessage()."<br/>\n"; $error .= '<b>Standard Code:</b> '.$db_resource->getCode()."<br/>\n"; if ($_SESSION['DEVELOPMENT']) { $error .= '<b>DBMS/User Message:</b> '.$db_resource->getUserInfo()."<br/>\n"; //$error .= '<b>DBMS/Debug Message:</b> '.$db_resource->getDebugInfo()."<br/>\n"; backtrace(); } } return $error; } /** * Make a connection to a RDBMS and Database. Defaults to agis_core (slave). * Note: dev/test/production is determined from the config.inc.php file that resides on each server. * * @access public * @param string $database The RDBMS to connect to (reliability, [agis_core], agis_core_master, wfdmt, arinc_symonty, pcube, fmr, product_safety, fogbugz) * @param boolean $show_error (true) show an error message on screen or not. * @return PEAR DB::connect handle/object which is also set in $GLOBALS['DB_CONNECTION'][$database] or false if unable to connect * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @see sql_query() */ function sql_connect($database='agis_core', $show_error=true) { if (!$database) return false; $database = strtolower($database); // add a singleton snippet to not reconnect if the data connection object already exists (see sql_escape() for usage) if (is_object($GLOBALS['DB_CONNECTION'][$database])) return $GLOBALS['DB_CONNECTION'][$database]; $tries = 5; for($i = 1; $i <= $tries; $i++) { switch ($database) { case 'agis_core': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_agis_core(false, false); break 2; case 'agis_core_master': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_agis_core_master(false); break 2; case 'reliability': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_reliability(); break 2; case 'wfdmt': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_wfdmt(); break 2; case 'arinc_symonty': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_arinc_symonty(); break 2; case 'pcube': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_pcube(); break 2; case 'fmr': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_fmr(); break 2; case 'product_safety': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_product_safety(); break 2; case 'synergy_master': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_synergy_master(); break 2; case 'synergy_reference':$GLOBALS['DB_CONNECTION'][$database] = connect_to_db_synergy_reference(); break 2; case 'fogbugz': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_fogbugz(); break 2; case 'pana_session_pw': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_pana_session_pw(); break 2; case 'pana_session_db': $GLOBALS['DB_CONNECTION'][$database] = connect_to_db_pana_session_db(); break 2; default: if ($_SESSION['DEVELOPMENT']) { notification_table('error', "No such database named '<b>".substr($database, 0, 30)."...</b>' Perhaps you have ommited the first sql_query() parameter?<br/>\n"); backtrace(true); } else notification_table('error', "No such database. This looks like a SQL query instead.<br/>\n"); return false; break 2; } $error .= "Unable to connect to ".$database." RDBMS. Retrying [$i/$tries] in 5 seconds.<br/>\n"; sleep(5); } if ( !is_object($GLOBALS['DB_CONNECTION'][$database]) ) { $error .= 'Could not connect to '.$database." server. Aborting.<br/>\n"; if ($show_error) notification_table('error', $error); return false; } if ( PEAR::isError($GLOBALS['DB_CONNECTION'][$database]) ) { //TODO: we should log this connection failure (and the others like this) to syslog. if ($show_error) notification_table('error', sql_db_error($GLOBALS['DB_CONNECTION'][$database])); return false; } return $GLOBALS['DB_CONNECTION'][$database]; } /** * We are (currently) trying to prevent just one trivial type of sql injection. * Namely, the one that attempts to end query with a ; and then add an extra query * to the end. This is a common technique, and the one that is easiest to detect. * * First, we watch for unbalanced quotes. If any are found, the query is invalid anyway * and thus will not be allowed to run. * * Second, I can't think of a single valid use of a semicolon outside the literals * enclosed into ''. Semicolons will be alloedd in those literals, but not outside. * * Single quotes that are in the literals and have been SQL_ESCAPE()'d are treated properly, * that is as a single character within the literal. So are the backslashed-escaped chars. * * Any other additions are welcome, but this is at least a good start. */ function sql_is_safe_query($q) { $len = strlen($q); $inside = false; // inside a literal (enclosed by '') $ret = true; // query assumed good unless we can prove otherwise. for ($i = 0; $i < $len; $i++) { $more = ($i < ($len - 1)); // we have at least one more character switch($q[$i]) { case "\\": //[krogebry] Why would there be a test for '$inside' here? // anything after a \ should be an escaped char, that's what \ does. #if($inside && $more) #{ $i++; // whatever follows MUST be an escaped character. #continue; #} break; case "'": // we are inside the string and came up with a properly-escaped quote #if($inside && $more && ($q[$i+1] == "'")){ if($inside && $more && $q[$i-1] == "\\" ){ $i++; continue; } $inside = !$inside; break; case ";": // semicolons outside literals are not permitted. if(!$inside){ $ret = "Semicolon is used to chain queries. Please, do not do that."; break 2; } }// switch() } if ($inside) $ret = "Unbalanced single quotes"; #print "Ret: [$ret]<br/>\n"; return $ret; } /** * Dynamically generates a select box from a SQL query. * * The SELECT must return between two and three items. * first is the VALUE the second is the text to display and optional third is shown in parenthesis * <SELECT><OPTTION VALUE=''></SELECT> form element prefilled in * * Tooltips do NOT work in IE. sorry. blame Microsoft for not following W3 standards... * * @access public * @return int the number of rows in the SELECT box or false. * @param int $size usually 1, but the select box can be any height. * @param string $name the NAME='$name' parameter of a SELECT tag. * @param string $database the database to connect to (agis_core) is the default * @param string $sql The SQL query to be executed, this can be SELECT, INSERT, UPDATE or DELETE amongst others. * @param array $sqlvalues The sqlvalues to the $sql. One element per ? is required if this parameter is used. * @param mixed $blank (boolean) add the extra 'empty' <OPTION VALUE=''>. string will set the text of the empty option. * @param boolean $auto onChange will cause a form submit if true. * @param string $MatchToThis sometimes it is useful to match $name to something like $_GET['name'] instead. it is array safe too! * @param string $extratags Any extra CLASS='' or MULTIPLE or whatever to put in the <SELECT ...> tag. * @see select_box_array() * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 2010-01-20 */ function select_box_sql($size, $name, $database='agis_core', $sql, $sqlvalues=array(), $blank = false, $auto = false, $MatchToThis = false, $extratags = false) { $parameters['db_fetch_mode'] = DB_FETCHMODE_ORDERED; //this has to be an ordered array as we don't know the hash keys in an associative one $rslt = sql_query($database, $sql, $sqlvalues, false, $parameters); if (is_array($rslt)) { global $$name; if (intval($size) < 1) $size = 1; if ($MatchToThis === false) $MatchToThis = $$name; echo "\n<select size='".$size."' name=\"".$name."\" id=\"".$name."\""; if ($auto) echo " onChange=\"this.form.submit(); return true;\""; if ($size > 1) echo " onmouseover='topSelectedOption(this);'"; if ($extratags) echo " ".$extratags; echo ">\n"; if (count($rslt) > 0) { if ($blank && is_bool($blank) ) { echo "\t<option value=''></option>\n"; } elseif ($blank && is_string($blank)) { echo "\t<option value=''>".$blank."</option>\n"; } $items = 0; foreach ($rslt as $key => $value) { @list($key, $text, $description) = $value; $items++; // Check for selectbox sub-headings. if ( 0 == strncmp( $text, "---", 3 ) ) { echo "\t<option value='' disabled class='selectbox-ghosted'>".stripslashes($text)."</option>\n"; } else { echo "\t<option value=\"".$key."\""; if (!selected_if_in_array($MatchToThis, $key)) if ((string)$key == (string)$MatchToThis) echo " selected"; echo ">"; echo stripslashes($text); if ($description) echo " (".stripslashes($description).")"; echo "</option>\n"; } } } echo "</select>\n"; return $items; } else echo "Selectbox cannot be built because of an invalid SQL query.\n"; return false; } /** * returns a string that can be appended to an SQL statement to form the ORDER BY portion. * * if you want to sort by 'name' in descending order, then simply use 'name_DESC', * conversely, 'name_ASC' would sort in ascending order. The order of the elements in the array * will determine the order they are appended together. * * @access public * @return string of the form ' ORDER BY element[1], element[2], element[3]'... * @param $orderBy false, string, or array of elements like so: [sort_by] => Array ( [1] => name_DESC [2] => id [3] => price ) * @param $default a string to use as the default ORDER BY column * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 03/03/06 */ function parse_order_by_array($orderBy = false, $default = false) { $sql = ' ORDER BY '; if (!is_array($orderBy)) { //[dv] is_string() is not enough, as empty values are coming across as strings according to var_dump() if (strlen($orderBy) > 1) return $sql.$orderBy; elseif (is_string($default)) return $sql.$default; else return false; } foreach ($orderBy as $o) $tmp[] = str_replace('_', ' ', $o); return $sql.implode(', ',$tmp); } /** * Builds the WHERE portion of a SQL statement using the keywords in various columns with wildcard support. * * @return string SQL statement fragment * @param mixed $words either a string of words space deliminated or an array of words * @param array $columns an array of table.column names to search the $words in. Use % as a wildcard for example pass in 'username%' or '%username%'. * @param boolean $and (true) whether the words have to be ANDed or ORed together. * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 05/10/07 * @todo This should handle +, - and "" just like google or yahoo or other search engines do. */ function keyword_filter($words, $columns, $and = true) { // this maybe useful // http://wiki.ittoolbox.com/index.php/Code:Translate_Boolean_Query_to_SQL_select_statement // http://www.ibiblio.org/adriane/queries/ // http://www.zend.com/zend/tut/tutorial-ferrara1.php?article=tutorial-ferrara1&kind=t&id=8238&open=1&anc=0&view=1 // http://evolt.org/article/Boolean_Fulltext_Searching_with_PHP_and_MySQL/18/15665/index.html // http://www.databasejournal.com/features/mysql/article.php/3512461 // this would be great, but the dumb-asses don't work with InnoDB tables. GRRR! // http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html //$sql .= " AND MATCH (".implode(',',$columns).") AGAINST ('".implode(' ',$words)."' IN BOOLEAN MODE)"; if (!is_array($columns) or !$words) return; if (is_string($words)) $words = preg_split("/\s+/",$words, -1, PREG_SPLIT_NO_EMPTY); if(count($words) < 1) return ''; if ($and) //AND the words together { $sql = " AND "; $sqlArray = array(); foreach($words as $word) { $tmp = array(); foreach($columns as $field) { $col = str_replace('%','',$field); //[dv] read the http://php.net/preg_replace carefully. You must use this format, // because otherwise $words that are digits will cause undesired results. $myword = preg_replace("/(%)?([\w\.]+)(%)?/", "\${1}".$word."\${3}", $field ); $tmp[] = $col." LIKE '".SQL_ESCAPE($myword)."'"; } $sqlArray[] = " (".implode(" OR ",$tmp).") "; } $sql .= implode(" AND ", $sqlArray); } else //OR the words together { $sql = " AND ( "; $sqlArray = array(); foreach($columns as $field) { $col = str_replace('%','',$field); $tmp = array(); foreach($words as $word) { //[dv] read the http://php.net/preg_replace carefully. You must use this format, // because otherwise $words that are digits will cause undesired results. $myword = preg_replace("/(%)?([\w\.]+)(%)?/", "\${1}".$word."\${3}", $field ); $tmp[] = $col." LIKE '".SQL_ESCAPE($myword)."'"; } $sqlArray[] = "(".implode(" OR ",$tmp).") "; } $sql .= implode(" OR ", $sqlArray); $sql .= ") "; } return $sql; } /** * returns an array of ENUM values from a table/column. * * @access public * @return array of enum values * @param string $database the database to connect to (agis_core) is the default * @param string $table the name of the table to query * @param string $column the name of the enum column to query * @param boolean $sorted by default the results are sorted otherwise they are in the order of the enum schema * @param boolean $indexed by default the key/value are the same string. if true, then key is an integer. * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 05/27/09 * @see select_box_array() */ function sql_enum_values_array($database='agis_core', $table, $column, $sorted = true, $indexed = false) { $parameters['db_fetch_mode'] = DB_FETCHMODE_ORDERED; //this has to be an ordered array as we don't know the hash keys in an associative one if ( $dbQuery = sql_query($database, "SHOW COLUMNS FROM ".$table." LIKE '".$column."'", null, false, $parameters) ) { $EnumArray = array(); $EnumValues = $dbQuery[0][1]; $EnumValues = substr($EnumValues, 6, strlen($EnumValues)-8); $EnumValues = str_replace("','",",",$EnumValues); if ($indexed) { $EnumArray = explode(",",$EnumValues); if ($sorted) sort($EnumArray); } else { $tmp = explode(",",$EnumValues); foreach($tmp as $k => $v) $EnumArray[$v] = $v; if ($sorted) ksort($EnumArray); } return $EnumArray; } return false; } /** * Insert a single row into a $database.$table from an array hash of column => value pairs * * Usually these are the form field names corresponding to the equivallent SQL database column/field name. * Use the string 'null' to insert a true NULL. * * @access public * @return mixed inserted ID on success or result on failure * @param string $database the database to connect to (agis_core) is the default * @param string $table the name of the table to insert into * @param hash $rows hash of column => value pairs (optionally columns validated against $validate_columns) * @param array $valid_columns array of column/field names. Also useful to limit SQL to certain forced columns to prevent unwanted tampering with 'default' columns for example. * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 2010-01-20 * @see sql_update(), sql_insert_id() */ function sql_insert($database='agis_core_master', $table, $rows, $valid_columns=null) { ksort($rows); //not required, just easier to debug and find appropriate keys. $validate_columns = (is_array($valid_columns)) ? true : false; $temp = array(); $arrays = array(); foreach ($rows as $column => $val) { if (is_array($val)) { //if we only have one element in the array, then count it as any other $val if (count($val) == 1) $val = $val[0]; else { $arrays[$column] = $val; unset($rows[$column]); continue; } } if ($validate_columns && !in_array($column, $valid_columns)) { unset($rows[$column]); echo "\n<br/>sql_insert() <b>".$column."</b> is not in the valid_columns list</b>"; continue; } $val = trim($val); if (!$val) { unset($rows[$column]); continue; } if (strtolower($val) == 'null') $temp[$column] = 'NULL'; else $temp[$column] = "'".mysql_escape_string($val)."'"; } $values = implode(', ',$temp); $columns = "`".implode("`, `", array_keys($rows))."`"; $sql = "INSERT INTO `".$table."` (".$columns.") VALUES (".$values.")"; //echo $sql; if (count($arrays)) { echo "\n<br/>sql_insert() has arrays with multiple elements that need to be handled still: <b>".implode(', ', array_keys($arrays))."</b>"; foreach ($arrays as $a) var_dump($a); } $result = sql_query($database, $sql, null, false); if ($result) { $iid = sql_insert_id(); if (is_numeric($iid)) return $iid; } return $result; } /** * Update rows in $database.$table from an array hash of column => value pairs * * Usually these are the form field names corresponding to the equivallent SQL database column/field name. * Use the string 'null' to insert a true NULL. * * @access public * @return mixed affected rows on success or result on failure * @param string $database the database to connect to (agis_core) is the default * @param string $table the name of the table to insert into * @param hash $rows hash of column => value pairs (optionally columns validated against $validate_columns) * @param mixed hash of ID column/field name and record ID value [such as array('id_foo' => 69)] OR string to craft custom WHERE clause * @param array $valid_columns array of column/field names. Also useful to limit SQL to certain forced columns to prevent unwanted tampering with 'default' columns for example. * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 2010-01-20 * @see sql_insert() */ function sql_update($database='agis_core_master', $table, $rows, $where, $single=true, $valid_columns=null) { ksort($rows); //not required, just easier to debug and find appropriate keys. $validate_columns = (is_array($valid_columns)) ? true : false; $temp = array(); $arrays = array(); foreach ($rows as $column => $val) { if (is_array($val)) { //if we only have one element in the array, then count it as any other $val if (count($val) == 1) $val = $val[0]; else { $arrays[$column] = $val; unset($rows[$column]); continue; } } if ($validate_columns && !in_array($column, $valid_columns)) { unset($rows[$column]); echo "\n<br/>sql_update() <b>".$column."</b> is not in the valid_columns list</b>"; continue; } $val = trim($val); if (!isset($val)) { unset($rows[$column]); continue; } if (strtolower($val) == 'null') $temp[$column] = '`'.$column."` = NULL"; else $temp[$column] = '`'.$column."` = '".mysql_escape_string($val)."'"; } $sql = "UPDATE `".$table."` SET ".implode(', ', $temp); if (is_array($where)) { foreach ($where as $c => $v) $w[] = '`'.$c."` = '".mysql_escape_string($v)."'"; $sql .= " WHERE ".implode(' AND ', $w); } else $sql .= ' '.$where; if ($single) $sql .= ' LIMIT 1'; if (count($arrays)) { echo "\n<br/>sql_update() has arrays with multiple elements that need to be handled still: <b>".implode(', ', array_keys($arrays))."</b>"; foreach ($arrays as $a) var_dump($a); } $result = sql_query($database, $sql, null, false); if ($result) { $ar = sql_affected_rows($database); if (is_numeric($ar)) return $ar; } return $result; } /** * Given a single dimension array, it will sql_escape and quote all the values, * returning as a string suitable for a SQL IN() call. * * @access public * @return string string of the form "'foo,'bar','bee','boo'" * @param array $inarray a single dimension array (not hash) of values to quote/escape for an IN() function * @author Daevid Vincent [daevid.vincent@xxxxxxxxxxxxxx] * @date 2009-01-19 */ function sql_make_IN_from_array($inarray) { if (!is_array($inarray)) return '-1'; foreach ($inarray as $value) $tmp[] = sql_escape($value); return implode(', ',$tmp); } function connect_to_db_reliability() { // RELIABILITY DATA BASE // 'persistent' => TRUE,## caused connection problems if ($GLOBALS['DB_CONNECTIONS']['reliability']) return $GLOBALS['DB_CONNECTIONS']['reliability']; global $global_db_dsn_reliability; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_reliability, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['reliability'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['reliability']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['reliability']; } /** * Connect to the agis_core database * * @param boolean $use_master use the master rather than the slave (false) * @param boolean $die if there is a PEAR error, PHP dies on the spot. (true) * @return PEAR::DB object */ function connect_to_db_agis_core($use_master=FALSE, $die=true) { if ($use_master == TRUE) return connect_to_db_agis_core_master(); if ($GLOBALS['DB_CONNECTIONS']['agis_core_slave']) return $GLOBALS['DB_CONNECTIONS']['agis_core_slave']; global $global_db_dsn_agis_core_slave; $options = array( 'debug' => 0, 'persistent' => TRUE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_agis_core_slave, $options); if ( PEAR::isError( $db_connection ) ) { //TODO: we should log this connection failure (and the others like this) to syslog. //if ($die !== false) die( $db_connection->getMessage() ); if ($die !== false) die( sql_db_error($db_connection) ); } $GLOBALS['DB_CONNECTIONS']['agis_core_slave'] = $db_connection; if ($die !== false) $GLOBALS['DB_CONNECTIONS']['agis_core_slave']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['agis_core_slave']; } /** * Connect to the agis_core database * * @param boolean $die if there is a PEAR error, PHP dies on the spot. (true) * @return PEAR::DB object */ function connect_to_db_agis_core_master($die=true) { if ($GLOBALS['DB_CONNECTIONS']['agis_core_master']) return $GLOBALS['DB_CONNECTIONS']['agis_core_master']; global $global_db_dsn_agis_core_master; $options = array( 'debug' => 0, 'persistent' => TRUE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_agis_core_master, $options); if ( PEAR::isError( $db_connection ) ) { //TODO: we should log this connection failure (and the others like this) to syslog. //if ($die !== false) die( $db_connection->getMessage() ); if ($die !== false) die( sql_db_error($db_connection) ); } $GLOBALS['DB_CONNECTIONS']['agis_core_master'] = $db_connection; if ($die !== false) $GLOBALS['DB_CONNECTIONS']['agis_core_master']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['agis_core_master']; } function connect_to_db_wfdmt() { // wFDMT data base (tool that creates fdmt.dat, fdmt.xml) if ($GLOBALS['DB_CONNECTIONS']['wfdmt']) return $GLOBALS['DB_CONNECTIONS']['wfdmt']; global $global_db_dsn_wfdmt; $options = array( 'debug' => 0, 'persistent' => TRUE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_wfdmt, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['wfdmt'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['wfdmt']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['wfdmt']; } function connect_to_db_arinc_symonty() { // SYMONTEK DATABASE FOR SMS/EMAIL FROM ARINC if ($GLOBALS['DB_CONNECTIONS']['arinc_symonty']) return $GLOBALS['DB_CONNECTIONS']['arinc_symonty']; global $global_db_dsn_arinc_symonty; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_arinc_symonty, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['arinc_symonty'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['arinc_symonty']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['arinc_symonty']; } function connect_to_db_pcube() { // PCUBE DATA BASE FOR RELIABILITY (older oracle 8) if ($GLOBALS['DB_CONNECTIONS']['pcube']) return $GLOBALS['DB_CONNECTIONS']['pcube']; global $global_db_dsn_pcube; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_pcube, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['pcube'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['pcube']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['pcube']; } function connect_to_db_fmr() { // FMR DATA BASE - MMS Cabin Log Defects And Resolutions //'persistent' => TRUE,## May cause connection problems like reliability? if ($GLOBALS['DB_CONNECTIONS']['fmr']) return $GLOBALS['DB_CONNECTIONS']['fmr']; global $global_db_dsn_fmr; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_fmr, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['fmr'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['fmr']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['fmr']; } function connect_to_db_fogbugz() { if ($GLOBALS['DB_CONNECTIONS']['fogbugz']) return $GLOBALS['DB_CONNECTIONS']['fogbugz']; global $global_db_dsn_fogbugz; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_fogbugz, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['fogbugz'] =& $db_connection; $GLOBALS['DB_CONNECTIONS']['fogbugz']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['fogbugz']; } function connect_to_db_product_safety() { if ($GLOBALS['DB_CONNECTIONS']['product_safety']) return $GLOBALS['DB_CONNECTIONS']['product_safety']; global $global_db_dsn_product_safety; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_product_safety, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['product_safety'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['product_safety']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['product_safety']; } function connect_to_db_synergy_master() { // myIFE Submit Issue to synergy_master/Telelogic if ($GLOBALS['DB_CONNECTIONS']['synergy_master']) return $GLOBALS['DB_CONNECTIONS']['synergy_master']; global $global_db_dsn_synergy_master; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_synergy_master, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['synergy_master'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['synergy_master']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['synergy_master']; } function connect_to_db_synergy_reference() { // myIFE Submit Issue to synergy_reference/Telelogic if ($GLOBALS['DB_CONNECTIONS']['synergy_reference']) return $GLOBALS['DB_CONNECTIONS']['synergy_reference']; global $global_db_dsn_synergy_reference; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL ); $db_connection =& DB::connect($global_db_dsn_synergy_reference, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['synergy_reference'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['synergy_reference']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['synergy_reference']; } /** connect_to_db_pana_session_pw() Connects to the password database, which holds users (as opposed to the session database, which holds sessions). This is just a utility function for internal use. You probably don't need to use this functiion. Args: None. Returns:The PEAR::DB $db_connection. It will die() with an error message if there was a db error. */ function connect_to_db_pana_session_pw() { if ($GLOBALS['DB_CONNECTIONS']['pana_session_password_db']) return $GLOBALS['DB_CONNECTIONS']['pana_session_password_db']; /* Look it up in BlackComb: */ /* NOTE: Connecting as type "mssql" did not work for me. That was on my WinXP workstation. Switching it to ODBC (below) made it work. I think things will be different under Linux, though. $pana_session_password_dsn = array( 'phptype' => 'odbc', 'dbsyntax' => 'mssql', 'database' => 'DRIVER={SQL Server};SERVER=WEBDEV', 'username' => 'agis', 'password' => 'Please do not forget the AGIS SQL Server Password', 'persistent' => TRUE ); */ global $pana_session_password_dsn; $options = array( 'debug' => 0, 'persistent' => FALSE, 'portability' => DB_PORTABILITY_ALL, ); $db_connection =& DB::connect($pana_session_password_dsn, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['pana_session_password_db'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['pana_session_password_db']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['pana_session_password_db']; } /** connect_to_db_pana_session_db() Connects to the session database, which holds session data (as opposed to the password database(s), which holds users). This is just a utility function for internal use. You probably don't need to use this function, but you may need to edit it to match the settings for your particular environment. Args: None. Returns:The PEAR::DB $db_connection. It will die() with an error message if there was a db error. */ function connect_to_db_pana_session_db() { if ($GLOBALS['DB_CONNECTIONS']['pana_session_db']) return $GLOBALS['DB_CONNECTIONS']['pana_session_db']; /* $dsn = array( 'phptype' => 'mysql', 'username' => 'root', 'password' => 'noway', 'hostspec' => 'dev-agis03', 'database' => 'agis_core_0_0_2_3f', ); */ global $pana_session_session_dsn; $options = array( 'debug' => 0, 'persistent' => TRUE, 'portability' => DB_PORTABILITY_ALL, ); $db_connection =& DB::connect($pana_session_session_dsn, $options); if ( PEAR::isError( $db_connection ) ) die( sql_db_error($db_connection) ); $GLOBALS['DB_CONNECTIONS']['pana_session_db'] = $db_connection; $GLOBALS['DB_CONNECTIONS']['pana_session_db']->setFetchMode(DB_FETCHMODE_ASSOC); return $GLOBALS['DB_CONNECTIONS']['pana_session_db']; } ?>
-- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php