PageRenderTime 49ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/database/classes/kohana/database/query/builder/select.php

https://github.com/drslice/regform
PHP | 392 lines | 173 code | 66 blank | 153 comment | 11 complexity | 00160e0bb8bf5ce8cf4ab1dadce07608 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Database query builder for SELECT statements. See [Query Builder](/database/query/builder) for usage and examples.
  4. *
  5. * @package Kohana/Database
  6. * @category Query
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2009 Kohana Team
  9. * @license http://kohanaphp.com/license
  10. */
  11. class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where {
  12. // SELECT ...
  13. protected $_select = array();
  14. // DISTINCT
  15. protected $_distinct = FALSE;
  16. // FROM ...
  17. protected $_from = array();
  18. // JOIN ...
  19. protected $_join = array();
  20. // GROUP BY ...
  21. protected $_group_by = array();
  22. // HAVING ...
  23. protected $_having = array();
  24. // OFFSET ...
  25. protected $_offset = NULL;
  26. // The last JOIN statement created
  27. protected $_last_join;
  28. /**
  29. * Sets the initial columns to select from.
  30. *
  31. * @param array column list
  32. * @return void
  33. */
  34. public function __construct(array $columns = NULL)
  35. {
  36. if ( ! empty($columns))
  37. {
  38. // Set the initial columns
  39. $this->_select = $columns;
  40. }
  41. // Start the query with no actual SQL statement
  42. parent::__construct(Database::SELECT, '');
  43. }
  44. /**
  45. * Enables or disables selecting only unique columns using "SELECT DISTINCT"
  46. *
  47. * @param boolean enable or disable distinct columns
  48. * @return $this
  49. */
  50. public function distinct($value)
  51. {
  52. $this->_distinct = (bool) $value;
  53. return $this;
  54. }
  55. /**
  56. * Choose the columns to select from.
  57. *
  58. * @param mixed column name or array($column, $alias) or object
  59. * @param ...
  60. * @return $this
  61. */
  62. public function select($columns = NULL)
  63. {
  64. $columns = func_get_args();
  65. $this->_select = array_merge($this->_select, $columns);
  66. return $this;
  67. }
  68. /**
  69. * Choose the columns to select from, using an array.
  70. *
  71. * @param array list of column names or aliases
  72. * @return $this
  73. */
  74. public function select_array(array $columns)
  75. {
  76. $this->_select = array_merge($this->_select, $columns);
  77. return $this;
  78. }
  79. /**
  80. * Choose the tables to select "FROM ..."
  81. *
  82. * @param mixed table name or array($table, $alias) or object
  83. * @param ...
  84. * @return $this
  85. */
  86. public function from($tables)
  87. {
  88. $tables = func_get_args();
  89. $this->_from = array_merge($this->_from, $tables);
  90. return $this;
  91. }
  92. /**
  93. * Adds addition tables to "JOIN ...".
  94. *
  95. * @param mixed column name or array($column, $alias) or object
  96. * @param string join type (LEFT, RIGHT, INNER, etc)
  97. * @return $this
  98. */
  99. public function join($table, $type = NULL)
  100. {
  101. $this->_join[] = $this->_last_join = new Database_Query_Builder_Join($table, $type);
  102. return $this;
  103. }
  104. /**
  105. * Adds "ON ..." conditions for the last created JOIN statement.
  106. *
  107. * @param mixed column name or array($column, $alias) or object
  108. * @param string logic operator
  109. * @param mixed column name or array($column, $alias) or object
  110. * @return $this
  111. */
  112. public function on($c1, $op, $c2)
  113. {
  114. $this->_last_join->on($c1, $op, $c2);
  115. return $this;
  116. }
  117. /**
  118. * Creates a "GROUP BY ..." filter.
  119. *
  120. * @param mixed column name or array($column, $alias) or object
  121. * @param ...
  122. * @return $this
  123. */
  124. public function group_by($columns)
  125. {
  126. $columns = func_get_args();
  127. $this->_group_by = array_merge($this->_group_by, $columns);
  128. return $this;
  129. }
  130. /**
  131. * Alias of and_having()
  132. *
  133. * @param mixed column name or array($column, $alias) or object
  134. * @param string logic operator
  135. * @param mixed column value
  136. * @return $this
  137. */
  138. public function having($column, $op, $value = NULL)
  139. {
  140. return $this->and_having($column, $op, $value);
  141. }
  142. /**
  143. * Creates a new "AND HAVING" condition for the query.
  144. *
  145. * @param mixed column name or array($column, $alias) or object
  146. * @param string logic operator
  147. * @param mixed column value
  148. * @return $this
  149. */
  150. public function and_having($column, $op, $value = NULL)
  151. {
  152. $this->_having[] = array('AND' => array($column, $op, $value));
  153. return $this;
  154. }
  155. /**
  156. * Creates a new "OR HAVING" condition for the query.
  157. *
  158. * @param mixed column name or array($column, $alias) or object
  159. * @param string logic operator
  160. * @param mixed column value
  161. * @return $this
  162. */
  163. public function or_having($column, $op, $value = NULL)
  164. {
  165. $this->_having[] = array('OR' => array($column, $op, $value));
  166. return $this;
  167. }
  168. /**
  169. * Alias of and_having_open()
  170. *
  171. * @return $this
  172. */
  173. public function having_open()
  174. {
  175. return $this->and_having_open();
  176. }
  177. /**
  178. * Opens a new "AND HAVING (...)" grouping.
  179. *
  180. * @return $this
  181. */
  182. public function and_having_open()
  183. {
  184. $this->_having[] = array('AND' => '(');
  185. return $this;
  186. }
  187. /**
  188. * Opens a new "OR HAVING (...)" grouping.
  189. *
  190. * @return $this
  191. */
  192. public function or_having_open()
  193. {
  194. $this->_having[] = array('OR' => '(');
  195. return $this;
  196. }
  197. /**
  198. * Closes an open "AND HAVING (...)" grouping.
  199. *
  200. * @return $this
  201. */
  202. public function having_close()
  203. {
  204. return $this->and_having_close();
  205. }
  206. /**
  207. * Closes an open "AND HAVING (...)" grouping.
  208. *
  209. * @return $this
  210. */
  211. public function and_having_close()
  212. {
  213. $this->_having[] = array('AND' => ')');
  214. return $this;
  215. }
  216. /**
  217. * Closes an open "OR HAVING (...)" grouping.
  218. *
  219. * @return $this
  220. */
  221. public function or_having_close()
  222. {
  223. $this->_having[] = array('OR' => ')');
  224. return $this;
  225. }
  226. /**
  227. * Start returning results after "OFFSET ..."
  228. *
  229. * @param integer starting result number
  230. * @return $this
  231. */
  232. public function offset($number)
  233. {
  234. $this->_offset = (int) $number;
  235. return $this;
  236. }
  237. /**
  238. * Compile the SQL query and return it.
  239. *
  240. * @param object Database instance
  241. * @return string
  242. */
  243. public function compile(Database $db)
  244. {
  245. // Callback to quote identifiers
  246. $quote_ident = array($db, 'quote_identifier');
  247. // Callback to quote tables
  248. $quote_table = array($db, 'quote_table');
  249. // Start a selection query
  250. $query = 'SELECT ';
  251. if ($this->_distinct === TRUE)
  252. {
  253. // Select only unique results
  254. $query .= 'DISTINCT ';
  255. }
  256. if (empty($this->_select))
  257. {
  258. // Select all columns
  259. $query .= '*';
  260. }
  261. else
  262. {
  263. // Select all columns
  264. $query .= implode(', ', array_unique(array_map($quote_ident, $this->_select)));
  265. }
  266. if ( ! empty($this->_from))
  267. {
  268. // Set tables to select from
  269. $query .= ' FROM '.implode(', ', array_unique(array_map($quote_table, $this->_from)));
  270. }
  271. if ( ! empty($this->_join))
  272. {
  273. // Add tables to join
  274. $query .= ' '.$this->_compile_join($db, $this->_join);
  275. }
  276. if ( ! empty($this->_where))
  277. {
  278. // Add selection conditions
  279. $query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
  280. }
  281. if ( ! empty($this->_group_by))
  282. {
  283. // Add sorting
  284. $query .= ' GROUP BY '.implode(', ', array_map($quote_ident, $this->_group_by));
  285. }
  286. if ( ! empty($this->_having))
  287. {
  288. // Add filtering conditions
  289. $query .= ' HAVING '.$this->_compile_conditions($db, $this->_having);
  290. }
  291. if ( ! empty($this->_order_by))
  292. {
  293. // Add sorting
  294. $query .= ' '.$this->_compile_order_by($db, $this->_order_by);
  295. }
  296. if ($this->_limit !== NULL)
  297. {
  298. // Add limiting
  299. $query .= ' LIMIT '.$this->_limit;
  300. }
  301. if ($this->_offset !== NULL)
  302. {
  303. // Add offsets
  304. $query .= ' OFFSET '.$this->_offset;
  305. }
  306. $this->_sql = $query;
  307. return parent::compile($db);
  308. }
  309. public function reset()
  310. {
  311. $this->_select =
  312. $this->_from =
  313. $this->_join =
  314. $this->_where =
  315. $this->_group_by =
  316. $this->_having =
  317. $this->_order_by = array();
  318. $this->_distinct = FALSE;
  319. $this->_limit =
  320. $this->_offset =
  321. $this->_last_join = NULL;
  322. $this->_parameters = array();
  323. $this->_sql = NULL;
  324. return $this;
  325. }
  326. } // End Database_Query_Select