PageRenderTime 62ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/letuboy/SwiftSharing-Core
PHP | 445 lines | 203 code | 73 blank | 169 comment | 15 complexity | 6e816f16f45faf525cf0493fe31c1ea4 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.1
  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. // UNION ...
  27. protected $_union = array();
  28. // The last JOIN statement created
  29. protected $_last_join;
  30. /**
  31. * Sets the initial columns to select from.
  32. *
  33. * @param array column list
  34. * @return void
  35. */
  36. public function __construct(array $columns = NULL)
  37. {
  38. if ( ! empty($columns))
  39. {
  40. // Set the initial columns
  41. $this->_select = $columns;
  42. }
  43. // Start the query with no actual SQL statement
  44. parent::__construct(Database::SELECT, '');
  45. }
  46. /**
  47. * Enables or disables selecting only unique columns using "SELECT DISTINCT"
  48. *
  49. * @param boolean enable or disable distinct columns
  50. * @return $this
  51. */
  52. public function distinct($value)
  53. {
  54. $this->_distinct = (bool) $value;
  55. return $this;
  56. }
  57. /**
  58. * Choose the columns to select from.
  59. *
  60. * @param mixed column name or array($column, $alias) or object
  61. * @param ...
  62. * @return $this
  63. */
  64. public function select($columns = NULL)
  65. {
  66. $columns = func_get_args();
  67. $this->_select = array_merge($this->_select, $columns);
  68. return $this;
  69. }
  70. /**
  71. * Choose the columns to select from, using an array.
  72. *
  73. * @param array list of column names or aliases
  74. * @return $this
  75. */
  76. public function select_array(array $columns)
  77. {
  78. $this->_select = array_merge($this->_select, $columns);
  79. return $this;
  80. }
  81. /**
  82. * Choose the tables to select "FROM ..."
  83. *
  84. * @param mixed table name or array($table, $alias) or object
  85. * @param ...
  86. * @return $this
  87. */
  88. public function from($tables)
  89. {
  90. $tables = func_get_args();
  91. $this->_from = array_merge($this->_from, $tables);
  92. return $this;
  93. }
  94. /**
  95. * Adds addition tables to "JOIN ...".
  96. *
  97. * @param mixed column name or array($column, $alias) or object
  98. * @param string join type (LEFT, RIGHT, INNER, etc)
  99. * @return $this
  100. */
  101. public function join($table, $type = NULL)
  102. {
  103. $this->_join[] = $this->_last_join = new Database_Query_Builder_Join($table, $type);
  104. return $this;
  105. }
  106. /**
  107. * Adds "ON ..." conditions for the last created JOIN statement.
  108. *
  109. * @param mixed column name or array($column, $alias) or object
  110. * @param string logic operator
  111. * @param mixed column name or array($column, $alias) or object
  112. * @return $this
  113. */
  114. public function on($c1, $op, $c2)
  115. {
  116. $this->_last_join->on($c1, $op, $c2);
  117. return $this;
  118. }
  119. /**
  120. * Adds "USING ..." conditions for the last created JOIN statement.
  121. *
  122. * @param string column name
  123. * @param ...
  124. * @return $this
  125. */
  126. public function using($columns)
  127. {
  128. $columns = func_get_args();
  129. call_user_func_array(array($this->_last_join, 'using'), $columns);
  130. return $this;
  131. }
  132. /**
  133. * Creates a "GROUP BY ..." filter.
  134. *
  135. * @param mixed column name or array($column, $alias) or object
  136. * @param ...
  137. * @return $this
  138. */
  139. public function group_by($columns)
  140. {
  141. $columns = func_get_args();
  142. $this->_group_by = array_merge($this->_group_by, $columns);
  143. return $this;
  144. }
  145. /**
  146. * Alias of and_having()
  147. *
  148. * @param mixed column name or array($column, $alias) or object
  149. * @param string logic operator
  150. * @param mixed column value
  151. * @return $this
  152. */
  153. public function having($column, $op, $value = NULL)
  154. {
  155. return $this->and_having($column, $op, $value);
  156. }
  157. /**
  158. * Creates a new "AND HAVING" condition for the query.
  159. *
  160. * @param mixed column name or array($column, $alias) or object
  161. * @param string logic operator
  162. * @param mixed column value
  163. * @return $this
  164. */
  165. public function and_having($column, $op, $value = NULL)
  166. {
  167. $this->_having[] = array('AND' => array($column, $op, $value));
  168. return $this;
  169. }
  170. /**
  171. * Creates a new "OR HAVING" condition for the query.
  172. *
  173. * @param mixed column name or array($column, $alias) or object
  174. * @param string logic operator
  175. * @param mixed column value
  176. * @return $this
  177. */
  178. public function or_having($column, $op, $value = NULL)
  179. {
  180. $this->_having[] = array('OR' => array($column, $op, $value));
  181. return $this;
  182. }
  183. /**
  184. * Alias of and_having_open()
  185. *
  186. * @return $this
  187. */
  188. public function having_open()
  189. {
  190. return $this->and_having_open();
  191. }
  192. /**
  193. * Opens a new "AND HAVING (...)" grouping.
  194. *
  195. * @return $this
  196. */
  197. public function and_having_open()
  198. {
  199. $this->_having[] = array('AND' => '(');
  200. return $this;
  201. }
  202. /**
  203. * Opens a new "OR HAVING (...)" grouping.
  204. *
  205. * @return $this
  206. */
  207. public function or_having_open()
  208. {
  209. $this->_having[] = array('OR' => '(');
  210. return $this;
  211. }
  212. /**
  213. * Closes an open "AND HAVING (...)" grouping.
  214. *
  215. * @return $this
  216. */
  217. public function having_close()
  218. {
  219. return $this->and_having_close();
  220. }
  221. /**
  222. * Closes an open "AND HAVING (...)" grouping.
  223. *
  224. * @return $this
  225. */
  226. public function and_having_close()
  227. {
  228. $this->_having[] = array('AND' => ')');
  229. return $this;
  230. }
  231. /**
  232. * Closes an open "OR HAVING (...)" grouping.
  233. *
  234. * @return $this
  235. */
  236. public function or_having_close()
  237. {
  238. $this->_having[] = array('OR' => ')');
  239. return $this;
  240. }
  241. /**
  242. * Adds an other UNION clause.
  243. *
  244. * @param mixed $select if string, it must be the name of a table. Else
  245. * must be an instance of Database_Query_Builder_Select
  246. * @param boolean $all decides if it's an UNION or UNION ALL clause
  247. * @return $this
  248. */
  249. public function union($select, $all = TRUE)
  250. {
  251. if (is_string($select))
  252. {
  253. $select = DB::select()->from($select);
  254. }
  255. if ( ! $select instanceof Database_Query_Builder_Select)
  256. throw new Kohana_Exception('first parameter must be a string or an instance of Database_Query_Builder_Select');
  257. $this->_union []= array('select' => $select, 'all' => $all);
  258. return $this;
  259. }
  260. /**
  261. * Start returning results after "OFFSET ..."
  262. *
  263. * @param integer starting result number
  264. * @return $this
  265. */
  266. public function offset($number)
  267. {
  268. $this->_offset = (int) $number;
  269. return $this;
  270. }
  271. /**
  272. * Compile the SQL query and return it.
  273. *
  274. * @param object Database instance
  275. * @return string
  276. */
  277. public function compile(Database $db)
  278. {
  279. // Callback to quote columns
  280. $quote_column = array($db, 'quote_column');
  281. // Callback to quote tables
  282. $quote_table = array($db, 'quote_table');
  283. // Start a selection query
  284. $query = 'SELECT ';
  285. if ($this->_distinct === TRUE)
  286. {
  287. // Select only unique results
  288. $query .= 'DISTINCT ';
  289. }
  290. if (empty($this->_select))
  291. {
  292. // Select all columns
  293. $query .= '*';
  294. }
  295. else
  296. {
  297. // Select all columns
  298. $query .= implode(', ', array_unique(array_map($quote_column, $this->_select)));
  299. }
  300. if ( ! empty($this->_from))
  301. {
  302. // Set tables to select from
  303. $query .= ' FROM '.implode(', ', array_unique(array_map($quote_table, $this->_from)));
  304. }
  305. if ( ! empty($this->_join))
  306. {
  307. // Add tables to join
  308. $query .= ' '.$this->_compile_join($db, $this->_join);
  309. }
  310. if ( ! empty($this->_where))
  311. {
  312. // Add selection conditions
  313. $query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
  314. }
  315. if ( ! empty($this->_group_by))
  316. {
  317. // Add sorting
  318. $query .= ' GROUP BY '.implode(', ', array_map($quote_column, $this->_group_by));
  319. }
  320. if ( ! empty($this->_having))
  321. {
  322. // Add filtering conditions
  323. $query .= ' HAVING '.$this->_compile_conditions($db, $this->_having);
  324. }
  325. if ( ! empty($this->_order_by))
  326. {
  327. // Add sorting
  328. $query .= ' '.$this->_compile_order_by($db, $this->_order_by);
  329. }
  330. if ($this->_limit !== NULL)
  331. {
  332. // Add limiting
  333. $query .= ' LIMIT '.$this->_limit;
  334. }
  335. if ($this->_offset !== NULL)
  336. {
  337. // Add offsets
  338. $query .= ' OFFSET '.$this->_offset;
  339. }
  340. if ( ! empty($this->_union))
  341. {
  342. foreach ($this->_union as $u) {
  343. $query .= ' UNION ';
  344. if ($u['all'] === TRUE)
  345. {
  346. $query .= 'ALL ';
  347. }
  348. $query .= $u['select']->compile($db);
  349. }
  350. }
  351. $this->_sql = $query;
  352. return parent::compile($db);
  353. }
  354. public function reset()
  355. {
  356. $this->_select =
  357. $this->_from =
  358. $this->_join =
  359. $this->_where =
  360. $this->_group_by =
  361. $this->_having =
  362. $this->_order_by =
  363. $this->_union = array();
  364. $this->_distinct = FALSE;
  365. $this->_limit =
  366. $this->_offset =
  367. $this->_last_join = NULL;
  368. $this->_parameters = array();
  369. $this->_sql = NULL;
  370. return $this;
  371. }
  372. } // End Database_Query_Select