query.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <?php
  2. /**
  3. * Database query wrapper.
  4. *
  5. * @package Fuel/Database
  6. * @category Query
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. namespace Fuel\Core;
  12. class Database_Query
  13. {
  14. /**
  15. * @var int Query type
  16. */
  17. protected $_type;
  18. /**
  19. * @var int Cache lifetime
  20. */
  21. protected $_lifetime;
  22. /**
  23. * @var string Cache key
  24. */
  25. protected $_cache_key = null;
  26. /**
  27. * @var boolean Cache all results
  28. */
  29. protected $_cache_all = true;
  30. /**
  31. * @var string SQL statement
  32. */
  33. protected $_sql;
  34. /**
  35. * @var array Quoted query parameters
  36. */
  37. protected $_parameters = array();
  38. /**
  39. * @var bool Return results as associative arrays or objects
  40. */
  41. protected $_as_object = false;
  42. /**
  43. * Creates a new SQL query of the specified type.
  44. *
  45. * @param string query string
  46. * @param integer query type: DB::SELECT, DB::INSERT, etc
  47. * @return void
  48. */
  49. public function __construct($sql, $type = null)
  50. {
  51. $this->_type = $type;
  52. $this->_sql = $sql;
  53. }
  54. /**
  55. * Return the SQL query string.
  56. *
  57. * @return string
  58. */
  59. final public function __toString()
  60. {
  61. try
  62. {
  63. // Return the SQL string
  64. return $this->compile(\Database_Connection::instance());
  65. }
  66. catch (\Exception $e)
  67. {
  68. return $e->getMessage();
  69. }
  70. }
  71. /**
  72. * Get the type of the query.
  73. *
  74. * @return integer
  75. */
  76. public function type()
  77. {
  78. return $this->_type;
  79. }
  80. /**
  81. * Enables the query to be cached for a specified amount of time.
  82. *
  83. * @param integer number of seconds to cache or null for default
  84. * @param string name of the cache key to be used or null for default
  85. * @param boolean if true, cache all results, even empty ones
  86. * @return $this
  87. */
  88. public function cached($lifetime = null, $cache_key = null, $cache_all = true)
  89. {
  90. $this->_lifetime = $lifetime;
  91. $this->_cache_all = (bool) $cache_all;
  92. is_string($cache_key) and $this->_cache_key = $cache_key;
  93. return $this;
  94. }
  95. /**
  96. * Returns results as associative arrays
  97. *
  98. * @return $this
  99. */
  100. public function as_assoc()
  101. {
  102. $this->_as_object = false;
  103. return $this;
  104. }
  105. /**
  106. * Returns results as objects
  107. *
  108. * @param string classname or true for stdClass
  109. * @return $this
  110. */
  111. public function as_object($class = true)
  112. {
  113. $this->_as_object = $class;
  114. return $this;
  115. }
  116. /**
  117. * Set the value of a parameter in the query.
  118. *
  119. * @param string parameter key to replace
  120. * @param mixed value to use
  121. * @return $this
  122. */
  123. public function param($param, $value)
  124. {
  125. // Add or overload a new parameter
  126. $this->_parameters[$param] = $value;
  127. return $this;
  128. }
  129. /**
  130. * Bind a variable to a parameter in the query.
  131. *
  132. * @param string parameter key to replace
  133. * @param mixed variable to use
  134. * @return $this
  135. */
  136. public function bind($param, & $var)
  137. {
  138. // Bind a value to a variable
  139. $this->_parameters[$param] =& $var;
  140. return $this;
  141. }
  142. /**
  143. * Add multiple parameters to the query.
  144. *
  145. * @param array list of parameters
  146. * @return $this
  147. */
  148. public function parameters(array $params)
  149. {
  150. // Merge the new parameters in
  151. $this->_parameters = $params + $this->_parameters;
  152. return $this;
  153. }
  154. /**
  155. * Compile the SQL query and return it. Replaces any parameters with their
  156. * given values.
  157. *
  158. * @param mixed Database instance or instance name
  159. * @return string
  160. */
  161. public function compile($db = null)
  162. {
  163. if ( ! $db instanceof \Database_Connection)
  164. {
  165. // Get the database instance
  166. $db = \Database_Connection::instance($db);
  167. }
  168. // Import the SQL locally
  169. $sql = $this->_sql;
  170. if ( ! empty($this->_parameters))
  171. {
  172. // Quote all of the values
  173. $values = array_map(array($db, 'quote'), $this->_parameters);
  174. // Replace the values in the SQL
  175. $sql = \Str::tr($sql, $values);
  176. }
  177. return trim($sql);
  178. }
  179. /**
  180. * Execute the current query on the given database.
  181. *
  182. * @param mixed Database instance or name of instance
  183. * @return object Database_Result for SELECT queries
  184. * @return mixed the insert id for INSERT queries
  185. * @return integer number of affected rows for all other queries
  186. */
  187. public function execute($db = null)
  188. {
  189. if ( ! is_object($db))
  190. {
  191. // Get the database instance
  192. $db = \Database_Connection::instance($db);
  193. }
  194. // Compile the SQL query
  195. $sql = $this->compile($db);
  196. switch(strtoupper(substr(ltrim($sql,'('), 0, 6)))
  197. {
  198. case 'SELECT':
  199. $this->_type = \DB::SELECT;
  200. break;
  201. case 'INSERT':
  202. case 'CREATE':
  203. $this->_type = \DB::INSERT;
  204. break;
  205. }
  206. if ($db->caching() and ! empty($this->_lifetime) and $this->_type === DB::SELECT)
  207. {
  208. $cache_key = empty($this->_cache_key) ?
  209. 'db.'.md5('Database_Connection::query("'.$db.'", "'.$sql.'")') : $this->_cache_key;
  210. $cache = \Cache::forge($cache_key);
  211. try
  212. {
  213. $result = $cache->get();
  214. return new Database_Result_Cached($result, $sql, $this->_as_object);
  215. }
  216. catch (CacheNotFoundException $e) {}
  217. }
  218. // Execute the query
  219. \DB::$query_count++;
  220. $result = $db->query($this->_type, $sql, $this->_as_object);
  221. // Cache the result if needed
  222. if (isset($cache) and ($this->_cache_all or $result->count()))
  223. {
  224. $cache->set_expiration($this->_lifetime)->set_contents($result->as_array())->set();
  225. }
  226. return $result;
  227. }
  228. }