PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/system/ar/ar_mysql.php

http://github.com/esconsut1/php-rails-clone
PHP | 311 lines | 191 code | 53 blank | 67 comment | 32 complexity | 7b71bfaca0e04413816a9019ec844c3e MD5 | raw file
  1. <?php
  2. /**
  3. * Basic MySQL driver
  4. *
  5. */
  6. class Ar_Mysql
  7. {
  8. public $db;
  9. public $statement_handle;
  10. public $tablename;
  11. public $primary_key_name;
  12. public $sequence_name;
  13. public $schema;
  14. public $db_conn;
  15. public $default;
  16. public $readonly;
  17. public $record;
  18. public $alive;
  19. public $binds;
  20. public $sql;
  21. public $duration;
  22. public $db_connection;
  23. /**
  24. * Connect to the db
  25. */
  26. function __construct()
  27. {
  28. // Set some more defaults
  29. $this->db_connection = false;
  30. $this->readonly = false;
  31. $this->record = array();
  32. return(true);
  33. }
  34. // Connect to the DB
  35. function db_connect($connection_name=false) {
  36. if ($this->db) {
  37. return(true);
  38. }
  39. // Choose what to connect to
  40. if ($connection_name && $GLOBALS['AR_DB_CONFIG'][$connection_name]) {
  41. $this->default = $GLOBALS['AR_DB_CONFIG'][$connection_name];
  42. $this->db_connection = $connection_name;
  43. } elseif ($this->db_connection && $GLOBALS['AR_DB_CONFIG'][$this->db_connection]) {
  44. $this->default = $GLOBALS['AR_DB_CONFIG'][$this->db_connection];
  45. } else {
  46. $this->default = $GLOBALS['AR_DB_CONFIG'][AR_DEFAULT_DB];
  47. $this->db_connection = AR_DEFAULT_DB;
  48. }
  49. // Get outta here if we have no good setting
  50. if (!$this->default['hostname']) {
  51. die('Please setup database.ini');
  52. }
  53. // Connect
  54. if ($this->db = @mysql_connect($this->default['hostname'], $this->default['login'], $this->default['password'])) {
  55. if (!@mysql_select_db($this->default['database'], $this->db)) {
  56. // die('Unable to connect to database: ' . $this->default['database']);
  57. }
  58. } else {
  59. // die('Unable to connect to database: ' . $this->default['database']);
  60. }
  61. return(true);
  62. }
  63. function db_escape($str="")
  64. {
  65. return(mysql_real_escape_string($str, $this->db));
  66. }
  67. function db_last_insert_id()
  68. {
  69. return(mysql_insert_id($this->db));
  70. }
  71. // gets the sequence
  72. function db_next_insert_id()
  73. {
  74. return(false);
  75. }
  76. /**
  77. * Does a query with placeholders
  78. */
  79. function db_query($q)
  80. {
  81. $this->db_connect();
  82. $this->statement_handle = null;
  83. $this->sql = $this->db_merge($q);
  84. $this->last_sql = $this->sql;
  85. $start = microtime(true);
  86. $this->statement_handle = mysql_query($this->sql, $this->db);
  87. $this->duration = microtime(true) - $start;
  88. ar_logger('SQL: [' . number_format($this->duration,6) . '] ' . $this->sql, $this->db_connection);
  89. $GLOBALS['db_time'] += $this->duration;
  90. if ($this->statement_handle === false) {
  91. $errorstr = 'SQL ERROR: ' . mysql_error($this->db) . "\nSTATEMENT: " . $this->sql;
  92. //debug($errorstr);
  93. ar_logger($errorstr, $this->db_connection);
  94. throw_error($errorstr);
  95. }
  96. $this->sql = array();
  97. }
  98. /**
  99. * Load the schema for this table
  100. */
  101. function db_schema()
  102. {
  103. // Loadup from the cache
  104. $cache_file = '/tmp/ar_schema-' . $this->db_connection . '-' . $this->tablename . '.cache';
  105. if (file_exists($cache_file)) {
  106. $a = unserialize(file_get_contents($cache_file));
  107. $this->primary_key_name = $a['primary_key_name'];
  108. $this->schema = $a['schema'];
  109. if (!$t = @filectime($cache_file)) {
  110. if ($t > time() - 3600) {
  111. @unlink($cache_file);
  112. }
  113. }
  114. return(true);
  115. }
  116. $this->db_query(array("SHOW COLUMNS FROM {$this->tablename}"));
  117. $fields = $this->db_all();
  118. $this->schema = array();
  119. foreach ($fields as $rec) {
  120. $this->schema[$rec['Field']] = array();
  121. $this->schema[$rec['Field']]['type'] = preg_replace('/\(.*?\).*?$/', '', $rec['Type']);
  122. $this->schema[$rec['Field']]['default'] = $rec['Default'];
  123. $this->schema[$rec['Field']]['key'] = $rec['Key'];
  124. $this->schema[$rec['Field']]['length'] = preg_replace('/^.*?\(|\).*?$/', '', $rec['Type']);
  125. $this->schema[$rec['Field']]['type'] = preg_match('/int/i', $rec['Type']) ? 'integer' : $this->schema[$rec['Field']]['type'];
  126. if ($rec['Key'] == 'PRI' && !$this->primary_key_name) {
  127. $this->primary_key_name = $rec['Field'];
  128. }
  129. }
  130. // Set default primary_key name
  131. if (!$this->primary_key_name) {
  132. $this->primary_key_name = 'id';
  133. }
  134. // Write to the cache
  135. $cache = array('schema' => $this->schema, 'primary_key_name' => $this->primary_key_name);
  136. file_put_contents($cache_file, serialize($cache), LOCK_EX);
  137. return(true);
  138. }
  139. /**
  140. * Get the next record from a statement handle
  141. *
  142. */
  143. function db_next()
  144. {
  145. if ($this->statement_handle) {
  146. return(mysql_fetch_assoc($this->statement_handle));
  147. }
  148. }
  149. /**
  150. * Get all the records
  151. *
  152. */
  153. function db_all()
  154. {
  155. if ($this->statement_handle) {
  156. $ret = array();
  157. while($rec = mysql_fetch_assoc($this->statement_handle)) {
  158. $ret[] = $rec;
  159. }
  160. return($ret);
  161. }
  162. return(false);
  163. }
  164. /**
  165. * Get name of primary key -- we need to cache this info
  166. */
  167. function db_get_primary_key_name()
  168. {
  169. return($this->primary_key_name);
  170. // Could me manually set
  171. /*
  172. if($this->primary_key_name)
  173. return($this->primary_key_name);
  174. $sql = "SELECT column_name FROM information_schema.key_column_usage WHERE table_name=? AND constraint_name='PRIMARY'";
  175. $this->db_query(array($sql, $this->tablename));
  176. if ($this->statement_handle) {
  177. $pkey = $this->db_next();
  178. $this->primary_key_name = $pkey['column_name'];
  179. } else {
  180. $this->primary_key_name = "id";
  181. }
  182. $this->statement_handle = null;
  183. return(true);
  184. */
  185. }
  186. /**
  187. * Build a query -- this is driver specific
  188. */
  189. function build_query($params=false, $mode='SELECT')
  190. {
  191. // Setup SELECT clause... we can make this more complex later
  192. if ($mode == 'SELECT') {
  193. $this->sql[] = $params['select'] ? 'SELECT ' . $params['select'] : 'SELECT *';
  194. } elseif ($mode == 'DELETE') {
  195. $this->sql[] = 'DELETE';
  196. }
  197. // Setup from clause
  198. $this->sql[] = $params['from'] ? 'FROM ' . $params['from'] : 'FROM ' . $this->tablename;
  199. // Setup conditions and bind variables
  200. if ($params['conditions']) {
  201. if (is_array($params['conditions'])) {
  202. $this->sql[] = 'WHERE ' . $params['conditions'][0];
  203. $num = count($params['conditions']);
  204. if($num > 1) {
  205. $this->push_binds(array_slice($params['conditions'], 1));
  206. }
  207. } else {
  208. $this->sql[] = 'WHERE ' . trim($params['conditions']);
  209. }
  210. }
  211. // Setup grouping
  212. $this->sql[] = $params['group'] ? 'GROUP ON ' . $params['group'] : '';
  213. // Setup order
  214. $this->sql[] = $params['order'] ? 'ORDER BY ' . $params['order'] : '';
  215. // Limits
  216. $this->sql[] = $params['limit'] ? 'LIMIT ' . intval($params['limit']) : '';
  217. // Offset
  218. $this->sql[] = $params['offset'] ? 'OFFSET ' . intval($params['offset']) : '';
  219. // Readonly
  220. if ($params['readonly']) {
  221. $this->readonly = true;
  222. }
  223. return(implode(' ', $this->sql));
  224. }
  225. // Push more binds
  226. function push_binds($more_binds=false)
  227. {
  228. foreach($more_binds as $bind)
  229. {
  230. $this->binds[] = $bind;
  231. }
  232. }
  233. // Setup a conditions type string
  234. function db_merge($params = array())
  235. {
  236. if(!is_array($params))
  237. return($params);
  238. $n = count($params);
  239. if($n == 1)
  240. return($params[0]);
  241. if($n > 0)
  242. {
  243. $this->binds = array_slice($params,1);
  244. $parts = explode('?', $params[0]);
  245. $c = count($this->binds);
  246. for($x = 0; $x < $c; $x++)
  247. {
  248. $parts[$x] .= trim("'" . $this->db_escape($this->binds[$x]) . "'");
  249. }
  250. return( implode('', $parts));
  251. }
  252. return($params);
  253. }
  254. }
  255. ?>