Index: trunk/core/kernel/db/db_connection.php =================================================================== diff -u -N --- trunk/core/kernel/db/db_connection.php (revision 0) +++ trunk/core/kernel/db/db_connection.php (revision 1560) @@ -0,0 +1,542 @@ +dbType = $dbType; + $this->initMetaFunctions(); + if(!$errorHandler) + { + $this->errorHandler = Array(&$this,'handleError'); + } + else + { + $this->errorHandler=$errorHandler; + } + } + + /** + * Set's custom error + * + * @param int $code + * @param string $msg + * @access public + */ + function setError($code,$msg) + { + $this->errorCode=$code; + $this->errorMessage=$msg; + } + + /** + * Checks if previous query execution + * raised an error. + * + * @return bool + * @access public + */ + function hasError() + { + return !($this->errorCode == 0); + } + + /** + * Caches function specific to requested + * db type + * + * @access private + */ + function initMetaFunctions() + { + $ret = Array(); + switch($this->dbType) + { + case 'mysql': + $ret = Array(); // only define functions, that name differs from "dbType_" + + break; + + + } + $this->metaFunctions = $ret; + } + + /** + * Get's function for specific db type + * based on it's meta name + * + * @param string $name + * @return string + * @access private + */ + function getMetaFunction($name) + { + if( !isset($this->metaFunctions[$name]) ) + { + if(function_exists($this->dbType.'_'.$name)) return $this->dbType.'_'.$name; + } + else + { + return $this->dbType.$name; + } + return false; + } + + + /** + * Try to connect to database server + * using specified parameters and set + * database to $db if connection made + * + * @param string $host + * @param string $user + * @param string $pass + * @param string $db + * @access public + */ + function Connect($host,$user,$pass,$db,$force_new=false) + { + $func = $this->getMetaFunction('connect'); + $this->connectionID = $func($host,$user,$pass,$force_new) or die('Can\'t connect to db'); + if($this->connectionID) + { + $this->setDB($db); + $this->showError(); + } + } + + function ReConnect($host,$user,$pass,$db) + { + $func = $this->getMetaFunction('close'); + $func($this->connectionID); + $this->Connect($host,$user,$pass,$db); + } + + /** + * Shows error message from previous operation + * if it failed + * + * @access private + */ + function showError($sql='') + { + $this->setError(0,''); // reset error + if($this->connectionID) + { + $func = $this->getMetaFunction('errno'); $this->errorCode = $func($this->connectionID); + if($this->hasError()) + { + $func = $this->getMetaFunction('error'); $this->errorMessage = $func($this->connectionID); + if(is_array($this->errorHandler)) + { + $func = $this->errorHandler[1]; + $ret = $this->errorHandler[0]->$func($this->errorCode,$this->errorMessage,$sql); + } + else + { + $func = $this->errorHandler; + $ret = $func($this->errorCode,$this->errorMessage,$sql); + } + if(!$ret) exit; + } + } + } + + /** + * Default error handler for sql errors + * + * @param int $code + * @param string $msg + * @param string $sql + * @return bool + * @access private + */ + function handleError($code,$msg,$sql) + { + echo 'Processing SQL: '.$sql.'
'; + echo 'Error ('.$code.'): '.$msg.'
'; + return false; + } + + /** + * Set's database name for connection + * to $new_name + * + * @param string $new_name + * @return bool + * @access public + */ + function setDB($new_name) + { + if(!$this->connectionID) return false; + $func = $this->getMetaFunction('select_db'); + return $func($new_name); + } + + /** + * Returns first field of first line + * of recordset if query ok or false + * otherwise + * + * @param string $sql + * @return string + * @access public + */ + function GetOne($sql) + { + $row = $this->GetRow($sql); + if(!$row) return false; + + return array_shift($row); + } + + /** + * Returns first row of recordset + * if query ok, false otherwise + * + * @param stirng $sql + * @return Array + * @access public + */ + function GetRow($sql) + { + $sql .= ' '.$this->getLimitClause(0,1); + $ret = $this->Query($sql); + if(!$ret) return false; + + return array_shift($ret); + } + + /** + * Returns 1st column of recordset as + * one-dimensional array or false otherwise + * Optional parameter $key_field can be used + * to set field name to be used as resulting + * array key + * + * @param string $sql + * @param string $key_field + * @return Array + * @access public + */ + function GetCol($sql, $key_field = null) + { + $rows = $this->Query($sql); + if(!$rows) return $rows; + + $i = 0; $row_count = count($rows); + $ret = Array(); + if(isset($key_field)) + { + while ($i < $row_count) + { + $ret[$rows[$i][$key_field]] = array_shift($rows[$i]); + $i++; + } + } + else + { + while ($i < $row_count) + { + $ret[] = array_shift($rows[$i]); + $i++; + } + } + return $ret; + } + + /** + * Queries db with $sql query supplied + * and returns rows selected if any, false + * otherwise. Optional parameter $key_field + * allows to set one of the query fields + * value as key in string array. + * + * @param string $sql + * @param string $key_field + * @return Array + */ + function Query($sql,$key_field = null) + { + if($this->debugMode) return $this->debugQuery($sql,$key_field); + $query_func = $this->getMetaFunction('query'); + $this->queryID = $query_func($sql,$this->connectionID); + if( is_resource($this->queryID) ) + { + $ret = Array(); + $fetch_func = $this->getMetaFunction('fetch_assoc'); + if( isset($key_field) ) + { + while( ($row = $fetch_func($this->queryID)) ) + { + $ret[$row[$key_field]] = $row; + } + } + else + { + while( ($row = $fetch_func($this->queryID)) ) + { + $ret[] = $row; + } + } + $this->Destroy(); + return $ret; + } + $this->showError($sql); + return false; + } + + function ChangeQuery($sql) + { + $this->Query($sql); + return $this->errorCode==0 ? true : false; + } + + function debugQuery($sql, $key_field = null) + { + global $debugger; + $query_func = $this->getMetaFunction('query'); + + // set 1st checkpoint: begin + $isSkipTable=true; + $profileSQLs=defined('DBG_SQL_PROFILE')&&DBG_SQL_PROFILE; + if($profileSQLs) + { + $isSkipTable=isSkipTable($sql); + if(!$isSkipTable) + { + $queryID=$debugger->generateID(); + $debugger->profileStart('sql_'.$queryID, $debugger->formatSQL($sql) ); + } + } + // set 1st checkpoint: end + + $this->queryID = $query_func($sql,$this->connectionID); + + // set 2nd checkpoint: begin + if(!$isSkipTable) { + $debugger->profileFinish('sql_'.$queryID); + $debugger->profilerAddTotal('sql', 'sql_'.$queryID); + } + // set 2nd checkpoint: end + + if( is_resource($this->queryID) ) + { + $ret = Array(); + $fetch_func = $this->getMetaFunction('fetch_assoc'); + if( isset($key_field) ) + { + while( ($row = $fetch_func($this->queryID)) ) + { + $ret[$row[$key_field]] = $row; + } + } + else + { + while( ($row = $fetch_func($this->queryID)) ) + { + $ret[] = $row; + } + } + $this->Destroy(); + return $ret; + } + $this->showError($sql); + return false; + } + + /** + * Free memory used to hold recordset handle + * + * @access private + */ + function Destroy() + { + if($this->queryID) + { + $free_func = $this->getMetaFunction('free_result'); + $free_func($this->queryID); + $this->queryID = null; + } + } + + /** + * Returns auto increment field value from + * insert like operation if any, zero otherwise + * + * @return int + * @access public + */ + function getInsertID() + { + $func = $this->getMetaFunction('insert_id'); + return $func($this->connectionID); + } + + /** + * Returns row count affected by last query + * + * @return int + * @access public + */ + function getAffectedRows() + { + $func = $this->getMetaFunction('affected_rows'); + return $func($this->connectionID); + } + + /** + * Returns LIMIT sql clause part for specific db + * + * @param int $offset + * @param int $rows + * @return string + * @access private + */ + function getLimitClause($offset, $rows) + { + if(!($rows > 0)) return ''; + + switch ($this->dbType) { + + default: + return 'LIMIT '.$offset.','.$rows; + break; + } + } + + /** + * Correctly quotes a string so that all strings are escaped. We prefix and append + * to the string single-quotes. + * An example is $db->qstr("Don't bother",magic_quotes_runtime()); + * + * @param s the string to quote + * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). + * This undoes the stupidity of magic quotes for GPC. + * + * @return quoted string to be sent back to database + */ + function qstr($s,$magic_quotes=false) + { + $replaceQuote = "\\'"; + if (!$magic_quotes) + { + if ($replaceQuote[0] == '\\') + { + // only since php 4.0.5 + $s = str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); + //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s)); + } + return "'".str_replace("'",$replaceQuote,$s)."'"; + } + + // undo magic quotes for " + $s = str_replace('\\"','"',$s); + + if($replaceQuote == "\\'") // ' already quoted, no need to change anything + { + return "'$s'"; + } + else // change \' to '' for sybase/mssql + { + $s = str_replace('\\\\','\\',$s); + return "'".str_replace("\\'",$replaceQuote,$s)."'"; + } + } + + /** + * Returns last error code occured + * + * @return int + */ + function getErrorCode() + { + return $this->errorCode; + } + + /** + * Returns last error message + * + * @return string + * @access public + */ + function getErrorMsg() + { + return $this->errorMessage; + } + } +?> \ No newline at end of file