PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/laravel/database/query/grammars/grammar.php

https://bitbucket.org/biggash730/laravel_angular_to_do
PHP | 491 lines | 199 code | 69 blank | 223 comment | 10 complexity | ce5c5f65ad4ebf5c7362572812405702 MD5 | raw file
  1. <?php namespace Laravel\Database\Query\Grammars;
  2. use Laravel\Database\Query;
  3. use Laravel\Database\Expression;
  4. class Grammar extends \Laravel\Database\Grammar {
  5. /**
  6. * The format for properly saving a DateTime.
  7. *
  8. * @var string
  9. */
  10. public $datetime = 'Y-m-d H:i:s';
  11. /**
  12. * All of the query components in the order they should be built.
  13. *
  14. * @var array
  15. */
  16. protected $components = array(
  17. 'aggregate', 'selects', 'from', 'joins', 'wheres',
  18. 'groupings', 'havings', 'orderings', 'limit', 'offset',
  19. );
  20. /**
  21. * Compile a SQL SELECT statement from a Query instance.
  22. *
  23. * @param Query $query
  24. * @return string
  25. */
  26. public function select(Query $query)
  27. {
  28. return $this->concatenate($this->components($query));
  29. }
  30. /**
  31. * Generate the SQL for every component of the query.
  32. *
  33. * @param Query $query
  34. * @return array
  35. */
  36. final protected function components($query)
  37. {
  38. // Each portion of the statement is compiled by a function corresponding
  39. // to an item in the components array. This lets us to keep the creation
  40. // of the query very granular and very flexible.
  41. foreach ($this->components as $component)
  42. {
  43. if ( ! is_null($query->$component))
  44. {
  45. $sql[$component] = call_user_func(array($this, $component), $query);
  46. }
  47. }
  48. return (array) $sql;
  49. }
  50. /**
  51. * Concatenate an array of SQL segments, removing those that are empty.
  52. *
  53. * @param array $components
  54. * @return string
  55. */
  56. final protected function concatenate($components)
  57. {
  58. return implode(' ', array_filter($components, function($value)
  59. {
  60. return (string) $value !== '';
  61. }));
  62. }
  63. /**
  64. * Compile the SELECT clause for a query.
  65. *
  66. * @param Query $query
  67. * @return string
  68. */
  69. protected function selects(Query $query)
  70. {
  71. if ( ! is_null($query->aggregate)) return;
  72. $select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
  73. return $select.$this->columnize($query->selects);
  74. }
  75. /**
  76. * Compile an aggregating SELECT clause for a query.
  77. *
  78. * @param Query $query
  79. * @return string
  80. */
  81. protected function aggregate(Query $query)
  82. {
  83. $column = $this->columnize($query->aggregate['columns']);
  84. // If the "distinct" flag is set and we're not aggregating everything
  85. // we'll set the distinct clause on the query, since this is used
  86. // to count all of the distinct values in a column, etc.
  87. if ($query->distinct and $column !== '*')
  88. {
  89. $column = 'DISTINCT '.$column;
  90. }
  91. return 'SELECT '.$query->aggregate['aggregator'].'('.$column.') AS '.$this->wrap('aggregate');
  92. }
  93. /**
  94. * Compile the FROM clause for a query.
  95. *
  96. * @param Query $query
  97. * @return string
  98. */
  99. protected function from(Query $query)
  100. {
  101. return 'FROM '.$this->wrap_table($query->from);
  102. }
  103. /**
  104. * Compile the JOIN clauses for a query.
  105. *
  106. * @param Query $query
  107. * @return string
  108. */
  109. protected function joins(Query $query)
  110. {
  111. // We need to iterate through each JOIN clause that is attached to the
  112. // query and translate it into SQL. The table and the columns will be
  113. // wrapped in identifiers to avoid naming collisions.
  114. foreach ($query->joins as $join)
  115. {
  116. $table = $this->wrap_table($join->table);
  117. $clauses = array();
  118. // Each JOIN statement may have multiple clauses, so we will iterate
  119. // through each clause creating the conditions then we'll join all
  120. // of them together at the end to build the clause.
  121. foreach ($join->clauses as $clause)
  122. {
  123. extract($clause);
  124. $column1 = $this->wrap($column1);
  125. $column2 = $this->wrap($column2);
  126. $clauses[] = "{$connector} {$column1} {$operator} {$column2}";
  127. }
  128. // The first clause will have a connector on the front, but it is
  129. // not needed on the first condition, so we will strip it off of
  130. // the condition before adding it to the array of joins.
  131. $search = array('AND ', 'OR ');
  132. $clauses[0] = str_replace($search, '', $clauses[0]);
  133. $clauses = implode(' ', $clauses);
  134. $sql[] = "{$join->type} JOIN {$table} ON {$clauses}";
  135. }
  136. // Finally, we should have an array of JOIN clauses that we can
  137. // implode together and return as the complete SQL for the
  138. // join clause of the query under construction.
  139. return implode(' ', $sql);
  140. }
  141. /**
  142. * Compile the WHERE clause for a query.
  143. *
  144. * @param Query $query
  145. * @return string
  146. */
  147. final protected function wheres(Query $query)
  148. {
  149. if (is_null($query->wheres)) return '';
  150. // Each WHERE clause array has a "type" that is assigned by the query
  151. // builder, and each type has its own compiler function. We will call
  152. // the appropriate compiler for each where clause.
  153. foreach ($query->wheres as $where)
  154. {
  155. $sql[] = $where['connector'].' '.$this->{$where['type']}($where);
  156. }
  157. if (isset($sql))
  158. {
  159. // We attach the boolean connector to every where segment just
  160. // for convenience. Once we have built the entire clause we'll
  161. // remove the first instance of a connector.
  162. return 'WHERE '.preg_replace('/AND |OR /', '', implode(' ', $sql), 1);
  163. }
  164. }
  165. /**
  166. * Compile a nested WHERE clause.
  167. *
  168. * @param array $where
  169. * @return string
  170. */
  171. protected function where_nested($where)
  172. {
  173. return '('.substr($this->wheres($where['query']), 6).')';
  174. }
  175. /**
  176. * Compile a simple WHERE clause.
  177. *
  178. * @param array $where
  179. * @return string
  180. */
  181. protected function where($where)
  182. {
  183. $parameter = $this->parameter($where['value']);
  184. return $this->wrap($where['column']).' '.$where['operator'].' '.$parameter;
  185. }
  186. /**
  187. * Compile a WHERE IN clause.
  188. *
  189. * @param array $where
  190. * @return string
  191. */
  192. protected function where_in($where)
  193. {
  194. $parameters = $this->parameterize($where['values']);
  195. return $this->wrap($where['column']).' IN ('.$parameters.')';
  196. }
  197. /**
  198. * Compile a WHERE NOT IN clause.
  199. *
  200. * @param array $where
  201. * @return string
  202. */
  203. protected function where_not_in($where)
  204. {
  205. $parameters = $this->parameterize($where['values']);
  206. return $this->wrap($where['column']).' NOT IN ('.$parameters.')';
  207. }
  208. /**
  209. * Compile a WHERE BETWEEN clause
  210. *
  211. * @param array $where
  212. * @return string
  213. */
  214. protected function where_between($where)
  215. {
  216. $min = $this->parameter($where['min']);
  217. $max = $this->parameter($where['max']);
  218. return $this->wrap($where['column']).' BETWEEN '.$min.' AND '.$max;
  219. }
  220. /**
  221. * Compile a WHERE NOT BETWEEN clause
  222. * @param array $where
  223. * @return string
  224. */
  225. protected function where_not_between($where)
  226. {
  227. $min = $this->parameter($where['min']);
  228. $max = $this->parameter($where['max']);
  229. return $this->wrap($where['column']).' NOT BETWEEN '.$min.' AND '.$max;
  230. }
  231. /**
  232. * Compile a WHERE NULL clause.
  233. *
  234. * @param array $where
  235. * @return string
  236. */
  237. protected function where_null($where)
  238. {
  239. return $this->wrap($where['column']).' IS NULL';
  240. }
  241. /**
  242. * Compile a WHERE NULL clause.
  243. *
  244. * @param array $where
  245. * @return string
  246. */
  247. protected function where_not_null($where)
  248. {
  249. return $this->wrap($where['column']).' IS NOT NULL';
  250. }
  251. /**
  252. * Compile a raw WHERE clause.
  253. *
  254. * @param array $where
  255. * @return string
  256. */
  257. final protected function where_raw($where)
  258. {
  259. return $where['sql'];
  260. }
  261. /**
  262. * Compile the GROUP BY clause for a query.
  263. *
  264. * @param Query $query
  265. * @return string
  266. */
  267. protected function groupings(Query $query)
  268. {
  269. return 'GROUP BY '.$this->columnize($query->groupings);
  270. }
  271. /**
  272. * Compile the HAVING clause for a query.
  273. *
  274. * @param Query $query
  275. * @return string
  276. */
  277. protected function havings(Query $query)
  278. {
  279. if (is_null($query->havings)) return '';
  280. foreach ($query->havings as $having)
  281. {
  282. $sql[] = 'AND '.$this->wrap($having['column']).' '.$having['operator'].' '.$this->parameter($having['value']);
  283. }
  284. return 'HAVING '.preg_replace('/AND /', '', implode(' ', $sql), 1);
  285. }
  286. /**
  287. * Compile the ORDER BY clause for a query.
  288. *
  289. * @param Query $query
  290. * @return string
  291. */
  292. protected function orderings(Query $query)
  293. {
  294. foreach ($query->orderings as $ordering)
  295. {
  296. $sql[] = $this->wrap($ordering['column']).' '.strtoupper($ordering['direction']);
  297. }
  298. return 'ORDER BY '.implode(', ', $sql);
  299. }
  300. /**
  301. * Compile the LIMIT clause for a query.
  302. *
  303. * @param Query $query
  304. * @return string
  305. */
  306. protected function limit(Query $query)
  307. {
  308. return 'LIMIT '.$query->limit;
  309. }
  310. /**
  311. * Compile the OFFSET clause for a query.
  312. *
  313. * @param Query $query
  314. * @return string
  315. */
  316. protected function offset(Query $query)
  317. {
  318. return 'OFFSET '.$query->offset;
  319. }
  320. /**
  321. * Compile a SQL INSERT statement from a Query instance.
  322. *
  323. * This method handles the compilation of single row inserts and batch inserts.
  324. *
  325. * @param Query $query
  326. * @param array $values
  327. * @return string
  328. */
  329. public function insert(Query $query, $values)
  330. {
  331. $table = $this->wrap_table($query->from);
  332. // Force every insert to be treated like a batch insert. This simply makes
  333. // creating the SQL syntax a little easier on us since we can always treat
  334. // the values as if it contains multiple inserts.
  335. if ( ! is_array(reset($values))) $values = array($values);
  336. // Since we only care about the column names, we can pass any of the insert
  337. // arrays into the "columnize" method. The columns should be the same for
  338. // every record inserted into the table.
  339. $columns = $this->columnize(array_keys(reset($values)));
  340. // Build the list of parameter place-holders of values bound to the query.
  341. // Each insert should have the same number of bound parameters, so we can
  342. // just use the first array of values.
  343. $parameters = $this->parameterize(reset($values));
  344. $parameters = implode(', ', array_fill(0, count($values), "($parameters)"));
  345. return "INSERT INTO {$table} ({$columns}) VALUES {$parameters}";
  346. }
  347. /**
  348. * Compile a SQL INSERT and get ID statement from a Query instance.
  349. *
  350. * @param Query $query
  351. * @param array $values
  352. * @param string $column
  353. * @return string
  354. */
  355. public function insert_get_id(Query $query, $values, $column)
  356. {
  357. return $this->insert($query, $values);
  358. }
  359. /**
  360. * Compile a SQL UPDATE statement from a Query instance.
  361. *
  362. * @param Query $query
  363. * @param array $values
  364. * @return string
  365. */
  366. public function update(Query $query, $values)
  367. {
  368. $table = $this->wrap_table($query->from);
  369. // Each column in the UPDATE statement needs to be wrapped in the keyword
  370. // identifiers, and a place-holder needs to be created for each value in
  371. // the array of bindings, so we'll build the sets first.
  372. foreach ($values as $column => $value)
  373. {
  374. $columns[] = $this->wrap($column).' = '.$this->parameter($value);
  375. }
  376. $columns = implode(', ', $columns);
  377. // UPDATE statements may be constrained by a WHERE clause, so we'll run
  378. // the entire where compilation process for those constraints. This is
  379. // easily achieved by passing it to the "wheres" method.
  380. return trim("UPDATE {$table} SET {$columns} ".$this->wheres($query));
  381. }
  382. /**
  383. * Compile a SQL DELETE statement from a Query instance.
  384. *
  385. * @param Query $query
  386. * @return string
  387. */
  388. public function delete(Query $query)
  389. {
  390. $table = $this->wrap_table($query->from);
  391. return trim("DELETE FROM {$table} ".$this->wheres($query));
  392. }
  393. /**
  394. * Transform an SQL short-cuts into real SQL for PDO.
  395. *
  396. * @param string $sql
  397. * @param array $bindings
  398. * @return string
  399. */
  400. public function shortcut($sql, &$bindings)
  401. {
  402. // Laravel provides an easy short-cut notation for writing raw WHERE IN
  403. // statements. If (...) is in the query, it will be replaced with the
  404. // correct number of parameters based on the query bindings.
  405. if (strpos($sql, '(...)') !== false)
  406. {
  407. for ($i = 0; $i < count($bindings); $i++)
  408. {
  409. // If the binding is an array, we can just assume it's used to fill a
  410. // where in condition, so we'll just replace the next place-holder
  411. // in the query with the constraint and splice the bindings.
  412. if (is_array($bindings[$i]))
  413. {
  414. $parameters = $this->parameterize($bindings[$i]);
  415. array_splice($bindings, $i, 1, $bindings[$i]);
  416. $sql = preg_replace('~\(\.\.\.\)~', "({$parameters})", $sql, 1);
  417. }
  418. }
  419. }
  420. return trim($sql);
  421. }
  422. }