PageRenderTime 52ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/symphony/lib/toolkit/class.mysql.php

https://github.com/scottkf/nicholscommunications
PHP | 429 lines | 296 code | 129 blank | 4 comment | 45 complexity | 0b6f1dbd3c0d1884522bd78d4ba4d342 MD5 | raw file
  1. <?php
  2. Class DatabaseException extends Exception{
  3. private $_error;
  4. public function __construct($message, array $error=NULL){
  5. parent::__construct($message);
  6. $this->_error = $error;
  7. }
  8. public function getQuery(){
  9. return $this->_error['query'];
  10. }
  11. public function getDatabaseErrorMessage(){
  12. return $this->_error['msg'];
  13. }
  14. public function getDatabaseErrorCode(){
  15. return $this->_error['num'];
  16. }
  17. }
  18. Class MySQL {
  19. const __WRITE_OPERATION__ = 0;
  20. const __READ_OPERATION__ = 1;
  21. private $_connection = array();
  22. private static $_log;
  23. private $_result;
  24. private $_lastResult = array();
  25. private $_lastQuery;
  26. private $_affectedRows;
  27. private $_insertID;
  28. private $_dumpTables = array();
  29. private $_client_info;
  30. private $_client_encoding;
  31. private static $_query_count;
  32. private $_cache;
  33. private $_logEverything;
  34. function __construct(){
  35. if(!is_numeric(self::$_query_count)){
  36. self::$_query_count = 0;
  37. }
  38. $this->_cache = NULL;
  39. $this->_logEverything = NULL;
  40. $this->flushLog();
  41. }
  42. function __destruct(){
  43. $this->flush();
  44. $this->close();
  45. }
  46. public function toggleCaching(){
  47. $this->_cache = !$this->_cache;
  48. }
  49. public function enableCaching(){
  50. $this->_cache = true;
  51. }
  52. public function disableCaching(){
  53. $this->_cache = false;
  54. }
  55. public function isCachingEnabled(){
  56. return $this->_cache;
  57. }
  58. public function toggleLogging(){
  59. $this->_logEverything = !$this->_logEverything;
  60. }
  61. public function enableLogging(){
  62. $this->_logEverything = true;
  63. }
  64. public function disableLogging(){
  65. $this->_logEverything = false;
  66. }
  67. public function isLogging(){
  68. return $this->_logEverything;
  69. }
  70. public function setPrefix($prefix){
  71. $this->_connection['tbl_prefix'] = $prefix;
  72. }
  73. public function isConnected(){
  74. return (isset($this->_connection['id']) && is_resource($this->_connection['id']));
  75. }
  76. public function getSelected(){
  77. return $this->_connection['database'];
  78. }
  79. public function getConnectionResource(){
  80. return $this->_connection['id'];
  81. }
  82. public function connect($host=NULL, $user=NULL, $password=NULL, $port ='3306'){
  83. $this->_connection['id'] = NULL;
  84. if($host) $this->_connection['host'] = $host;
  85. if($user) $this->_connection['user'] = $user;
  86. if($password) $this->_connection['pass'] = $password;
  87. if($port) $this->_connection['port'] = $port;
  88. $this->_connection['id'] = @mysql_connect($this->_connection['host'] . ':' . $this->_connection['port'], $this->_connection['user'], $this->_connection['pass']);
  89. if(!$this->isConnected()){
  90. $this->__error();
  91. return false;
  92. }
  93. $this->_client_info = mysql_get_client_info();
  94. $this->_client_encoding = mysql_client_encoding($this->_connection['id']);
  95. return true;
  96. }
  97. public function setCharacterSet($set='utf8'){
  98. $this->query("SET CHARACTER SET '$set'");
  99. }
  100. public function setCharacterEncoding($set='utf8'){
  101. $this->query("SET NAMES '$set'");
  102. }
  103. public function select($db=NULL){
  104. if($db) $this->_connection['database'] = $db;
  105. if(!mysql_select_db($this->_connection['database'], $this->_connection['id'])){
  106. $this->__error();
  107. $this->_connection['database'] = null;
  108. return false;
  109. }
  110. return true;
  111. }
  112. public static function cleanValue($value) {
  113. if (function_exists('mysql_real_escape_string')) {
  114. return mysql_real_escape_string($value);
  115. } else {
  116. return addslashes($value);
  117. }
  118. }
  119. public static function cleanFields(array &$array){
  120. foreach($array as $key => $val){
  121. // Handle arrays with more than 1 level
  122. if(is_array($val)){
  123. self::cleanFields($val);
  124. continue;
  125. }
  126. elseif(strlen($val) == 0){
  127. $array[$key] = 'NULL';
  128. }
  129. else{
  130. $array[$key] = "'" . self::cleanValue($val) . "'";
  131. }
  132. }
  133. }
  134. public function insert(array $fields, $table, $updateOnDuplicate=false){
  135. // Multiple Insert
  136. if(is_array(current($fields))){
  137. $sql = "INSERT INTO `$table` (`".implode('`, `', array_keys(current($fields))).'`) VALUES ';
  138. foreach($fields as $key => $array){
  139. // Sanity check: Make sure we dont end up with ',()' in the SQL.
  140. if(!is_array($array)) continue;
  141. self::cleanFields($array);
  142. $rows[] = '('.implode(', ', $array).')';
  143. }
  144. $sql .= implode(", ", $rows);
  145. }
  146. // Single Insert
  147. else{
  148. self::cleanFields($fields);
  149. $sql = "INSERT INTO `$table` (`".implode('`, `', array_keys($fields)).'`) VALUES ('.implode(', ', $fields).')';
  150. if($updateOnDuplicate){
  151. $sql .= ' ON DUPLICATE KEY UPDATE ';
  152. foreach($fields as $key => $value) $sql .= " `$key` = $value,";
  153. $sql = trim($sql, ',');
  154. }
  155. }
  156. return $this->query($sql);
  157. }
  158. public function update($fields, $table, $where=NULL){
  159. self::cleanFields($fields);
  160. $sql = "UPDATE $table SET ";
  161. foreach($fields as $key => $val)
  162. $rows[] = " `$key` = $val";
  163. $sql .= implode(', ', $rows) . ($where != NULL ? ' WHERE ' . $where : NULL);
  164. return $this->query($sql);
  165. }
  166. public function delete($table, $where){
  167. $this->query("DELETE FROM $table WHERE $where");
  168. }
  169. public function close(){
  170. if($this->isConnected()) return @mysql_close($this->_connection['id']);
  171. }
  172. public function determineQueryType($query){
  173. return (preg_match('/^(insert|replace|delete|update|optimize|truncate)/i', $query) ? self::__WRITE_OPERATION__ : self::__READ_OPERATION__);
  174. }
  175. public function query($query){
  176. if(empty($query)) return false;
  177. $query = trim($query);
  178. $query_type = $this->determineQueryType($query);
  179. if($query_type == self::__READ_OPERATION__ && $this->isCachingEnabled() !== NULL && !preg_match('/^SELECT\s+SQL(_NO)?_CACHE/i', $query)){
  180. if($this->isCachingEnabled() === false) $query = preg_replace('/^SELECT\s+/i', 'SELECT SQL_NO_CACHE ', $query);
  181. elseif($this->isCachingEnabled() === true) $query = preg_replace('/^SELECT\s+/i', 'SELECT SQL_CACHE ', $query);
  182. }
  183. if($this->_connection['tbl_prefix'] != 'tbl_'){
  184. $query = preg_replace('/tbl_(\S+?)([\s\.,]|$)/', $this->_connection['tbl_prefix'].'\\1\\2', $query);
  185. }
  186. $query_hash = md5($query.microtime());
  187. self::$_log['query'][$query_hash] = array('query' => $query, 'start' => precision_timer());
  188. $this->flush();
  189. $this->_lastQuery = $query;
  190. $this->_result = mysql_query($query, $this->_connection['id']);
  191. self::$_query_count++;
  192. if(mysql_error()){
  193. $this->__error();
  194. return false;
  195. }
  196. if(is_resource($this->_result)){
  197. while ($row = mysql_fetch_object($this->_result)){
  198. $this->_lastResult[] = $row;
  199. }
  200. mysql_free_result($this->_result);
  201. }
  202. self::$_log['query'][$query_hash]['time'] = precision_timer('stop', self::$_log['query'][$query_hash]['start']);
  203. if($this->_logEverything) self::$_log['query'][$query_hash]['lastResult'] = $this->_lastResult;
  204. return true;
  205. }
  206. public function extractTargetTablesFromQuery($query){
  207. if(!preg_match('/\\s+FROM\\s+(([\\w\\d\\-`_]+(,(\\s+)?)?)+)/i', $query, $matches)) return 'DUAL';
  208. return $matches[1];
  209. }
  210. public function numOfRows(){
  211. return count($this->_lastResult);
  212. }
  213. public function getInsertID(){
  214. return mysql_insert_id($this->_connection['id']);
  215. }
  216. public function queryCount(){
  217. return self::$_query_count;
  218. }
  219. public function fetch($query=NULL, $index_by_field=NULL){
  220. if($query) $this->query($query);
  221. elseif($this->_lastResult == NULL){
  222. return array();
  223. }
  224. $newArray = array();
  225. foreach ($this->_lastResult as $row){
  226. $newArray[] = get_object_vars($row);
  227. }
  228. if($index_by_field && isset($newArray[0][$index_by_field])){
  229. $n = array();
  230. foreach($newArray as $ii)
  231. $n[$ii[$index_by_field]] = $ii;
  232. $newArray = $n;
  233. }
  234. return $newArray;
  235. }
  236. public function fetchRow($offset=0, $query=NULL){
  237. $arr = $this->fetch($query);
  238. return (empty($arr) ? array() : $arr[$offset]);
  239. }
  240. public function fetchCol ($name, $query = NULL){
  241. $arr = $this->fetch($query);
  242. if(empty($arr)) return array();
  243. foreach ($arr as $row){
  244. $result[] = $row[$name];
  245. }
  246. return $result;
  247. }
  248. public function fetchVar ($varName, $offset = 0, $query = NULL){
  249. $arr = $this->fetch($query);
  250. return (empty($arr) ? NULL : $arr[$offset][$varName]);
  251. }
  252. public function flush(){
  253. $this->_result = NULL;
  254. $this->_lastResult = array();
  255. $this->_lastQuery = NULL;
  256. }
  257. public function flushLog(){
  258. self::$_log = array('error' => array(), 'query' => array());
  259. }
  260. private function __error($msg = NULL){
  261. if(!$msg){
  262. $msg = mysql_error();
  263. $errornum = mysql_errno();
  264. }
  265. self::$_log['error'][] = array('query' => $this->_lastQuery,
  266. 'msg' => $msg,
  267. 'num' => $errornum);
  268. throw new DatabaseException(__('MySQL Error (%1$s): %2$s in query "%3$s"', array($errornum, $msg, $this->_lastQuery)), end(self::$_log['error']));
  269. }
  270. public function debug($section=NULL){
  271. if(!$section) return self::$_log;
  272. return ($section == 'error' ? self::$_log['error'] : self::$_log['query']);
  273. }
  274. public function getLastError(){
  275. return current(self::$_log['error']);
  276. }
  277. public function getStatistics(){
  278. $stats = array();
  279. $query_log = $this->debug('query');
  280. $query_timer = 0.0;
  281. $slow_queries = array();
  282. foreach($query_log as $key => $val) {
  283. $query_timer += $val['time'];
  284. if($val['time'] > 0.0999) $slow_queries[] = $val;
  285. }
  286. return array('queries' => $this->queryCount(),
  287. 'slow-queries' => $slow_queries,
  288. 'total-query-time' => number_format($query_timer, 4, '.', ''));
  289. }
  290. public function import($sql){
  291. $queries = preg_split('/;[\\r\\n]+/', $sql, -1, PREG_SPLIT_NO_EMPTY);
  292. if(is_array($queries) && !empty($queries)){
  293. foreach($queries as $sql){
  294. if(trim($sql) != '') $result = $this->query($sql);
  295. if(!$result) return false;
  296. }
  297. }
  298. return true;
  299. }
  300. }