grammar.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <?php namespace Laravel\Database\Grammars;
  2. use Laravel\Arr;
  3. use Laravel\Database\Query;
  4. use Laravel\Database\Expression;
  5. class Grammar {
  6. /**
  7. * The keyword identifier for the database system.
  8. *
  9. * @var string
  10. */
  11. protected $wrapper = '"';
  12. /**
  13. * All of the query componenets in the order they should be built.
  14. *
  15. * Each derived compiler may adjust these components and place them in the
  16. * order needed for its particular database system, providing greater
  17. * control over how the query is structured.
  18. *
  19. * @var array
  20. */
  21. protected $components = array(
  22. 'aggregate',
  23. 'selects',
  24. 'from',
  25. 'joins',
  26. 'wheres',
  27. 'orderings',
  28. 'limit',
  29. 'offset'
  30. );
  31. /**
  32. * Compile a SQL SELECT statement from a Query instance.
  33. *
  34. * The query will be compiled according to the order of the elements specified
  35. * in the "components" property. The entire query is passed into each component
  36. * compiler for convenience.
  37. *
  38. * @param Query $query
  39. * @return string
  40. */
  41. final public function select(Query $query)
  42. {
  43. $sql = array();
  44. foreach ($this->components as $component)
  45. {
  46. if ( ! is_null($query->$component))
  47. {
  48. $sql[] = call_user_func(array($this, $component), $query);
  49. }
  50. }
  51. return implode(' ', Arr::without($sql, array(null, '')));
  52. }
  53. /**
  54. * Compile the SELECT clause for a query.
  55. *
  56. * @param Query $query
  57. * @return string
  58. */
  59. protected function selects(Query $query)
  60. {
  61. $select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
  62. return $select.$this->columnize($query->selects);
  63. }
  64. /**
  65. * Compile an aggregating SELECT clause for a query.
  66. *
  67. * If an aggregate function is called on the query instance, no select
  68. * columns will be set, so it is safe to assume that the "selects"
  69. * compiler function will not be called. We can simply build the
  70. * aggregating select clause within this function.
  71. *
  72. * @param Query $query
  73. * @return string
  74. */
  75. protected function aggregate(Query $query)
  76. {
  77. $column = $this->wrap($query->aggregate['column']);
  78. return 'SELECT '.$query->aggregate['aggregator'].'('.$column.')';
  79. }
  80. /**
  81. * Compile the FROM clause for a query.
  82. *
  83. * This method should not handle the construction of "join" clauses.
  84. * The join clauses will be constructured by their own compiler.
  85. *
  86. * @param Query $query
  87. * @return string
  88. */
  89. protected function from(Query $query)
  90. {
  91. return 'FROM '.$this->wrap($query->from);
  92. }
  93. /**
  94. * Compile the JOIN clauses for a query.
  95. *
  96. * @param Query $query
  97. * @return string
  98. */
  99. protected function joins(Query $query)
  100. {
  101. $format = '%s JOIN %s ON %s %s %s';
  102. foreach ($query->joins as $join)
  103. {
  104. $table = $this->wrap($join['table']);
  105. $column1 = $this->wrap($join['column1']);
  106. $column2 = $this->wrap($join['column2']);
  107. $sql[] = sprintf($format, $join['type'], $table, $column1, $join['operator'], $column2);
  108. }
  109. return implode(' ', $sql);
  110. }
  111. /**
  112. * Compile the WHERE clause for a query.
  113. *
  114. * @param Query $query
  115. * @return string
  116. */
  117. final protected function wheres(Query $query)
  118. {
  119. // Each WHERE clause array has a "type" that is assigned by the query
  120. // builder, and each type has its own compiler function. We will simply
  121. // iterate through the where clauses and call the appropriate compiler
  122. // for each clause.
  123. foreach ($query->wheres as $where)
  124. {
  125. $sql[] = $where['connector'].' '.$this->{$where['type']}($where);
  126. }
  127. if (isset($sql)) return implode(' ', array_merge(array('WHERE 1 = 1'), $sql));
  128. }
  129. /**
  130. * Compile a simple WHERE clause.
  131. *
  132. * This method handles the compilation of the structures created by the
  133. * "where" and "or_where" methods on the query builder.
  134. *
  135. * This method also handles database expressions, so care must be taken
  136. * to implement this functionality in any derived database grammars.
  137. *
  138. * @param array $where
  139. * @return string
  140. */
  141. protected function where($where)
  142. {
  143. $parameter = $this->parameter($where['value']);
  144. return $this->wrap($where['column']).' '.$where['operator'].' '.$parameter;
  145. }
  146. /**
  147. * Compile a WHERE IN clause.
  148. *
  149. * @param array $where
  150. * @return string
  151. */
  152. protected function where_in($where)
  153. {
  154. $parameters = $this->parameterize($where['values']);
  155. return $this->wrap($where['column']).' IN ('.$parameters.')';
  156. }
  157. /**
  158. * Compile a WHERE NOT IN clause.
  159. *
  160. * @param array $where
  161. * @return string
  162. */
  163. protected function where_not_in($where)
  164. {
  165. $parameters = $this->parameterize($where['values']);
  166. return $this->wrap($where['column']).' NOT IN ('.$parameters.')';
  167. }
  168. /**
  169. * Compile a WHERE NULL clause.
  170. *
  171. * @param array $where
  172. * @return string
  173. */
  174. protected function where_null($where)
  175. {
  176. return $this->wrap($where['column']).' IS NULL';
  177. }
  178. /**
  179. * Compile a WHERE NULL clause.
  180. *
  181. * @param array $where
  182. * @return string
  183. */
  184. protected function where_not_null($where)
  185. {
  186. return $this->wrap($where['column']).' IS NOT NULL';
  187. }
  188. /**
  189. * Compile a raw WHERE clause.
  190. *
  191. * @param string $where
  192. * @return string
  193. */
  194. protected function where_raw($where)
  195. {
  196. return $where;
  197. }
  198. /**
  199. * Compile the ORDER BY clause for a query.
  200. *
  201. * @param Query $query
  202. * @return string
  203. */
  204. protected function orderings(Query $query)
  205. {
  206. foreach ($query->orderings as $ordering)
  207. {
  208. $sql[] = $this->wrap($ordering['column']).' '.strtoupper($ordering['direction']);
  209. }
  210. return 'ORDER BY '.implode(', ', $sql);
  211. }
  212. /**
  213. * Compile the LIMIT clause for a query.
  214. *
  215. * @param Query $query
  216. * @return string
  217. */
  218. protected function limit(Query $query)
  219. {
  220. return 'LIMIT '.$query->limit;
  221. }
  222. /**
  223. * Compile the OFFSET clause for a query.
  224. *
  225. * @param Query $query
  226. * @return string
  227. */
  228. protected function offset(Query $query)
  229. {
  230. return 'OFFSET '.$query->offset;
  231. }
  232. /**
  233. * Compile a SQL INSERT statment from a Query instance.
  234. *
  235. * Note: This method handles the compilation of single row inserts and batch inserts.
  236. *
  237. * @param Query $query
  238. * @param array $values
  239. * @return string
  240. */
  241. public function insert(Query $query, $values)
  242. {
  243. // Force every insert to be treated like a batch insert. This simple makes
  244. // creating the SQL syntax a little easier on us since we can always treat
  245. // the values as if it is an array containing multiple inserts.
  246. if ( ! is_array(reset($values))) $values = array($values);
  247. // Since we only care about the column names, we can pass any of the insert
  248. // arrays into the "columnize" method. The names should be the same for
  249. // every insert to the table.
  250. $columns = $this->columnize(array_keys(reset($values)));
  251. // Build the list of parameter place-holders of values bound to the query.
  252. // Each insert should have the same number of bound paramters, so we can
  253. // just use the first array of values.
  254. $parameters = $this->parameterize(reset($values));
  255. $parameters = implode(', ', array_fill(0, count($values), '('.$parameters.')'));
  256. return 'INSERT INTO '.$this->wrap($query->from).' ('.$columns.') VALUES '.$parameters;
  257. }
  258. /**
  259. * Compile a SQL UPDATE statment from a Query instance.
  260. *
  261. * Note: Since UPDATE statements can be limited by a WHERE clause,
  262. * this method will use the same WHERE clause compilation
  263. * functions as the "select" method.
  264. *
  265. * @param Query $query
  266. * @param array $values
  267. * @return string
  268. */
  269. public function update(Query $query, $values)
  270. {
  271. foreach ($values as $column => $value)
  272. {
  273. $columns[] = $this->wrap($column).' = '.$this->parameter($value);
  274. }
  275. $columns = implode(', ', $columns);
  276. return trim('UPDATE '.$this->wrap($query->from).' SET '.$columns.' '.$this->wheres($query));
  277. }
  278. /**
  279. * Compile a SQL DELETE statment from a Query instance.
  280. *
  281. * @param Query $query
  282. * @return string
  283. */
  284. public function delete(Query $query)
  285. {
  286. return trim('DELETE FROM '.$this->wrap($query->from).' '.$this->wheres($query));
  287. }
  288. /**
  289. * The following functions primarily serve as utility functions for
  290. * the grammar. They perform tasks such as wrapping values in keyword
  291. * identifiers or creating variable lists of bindings.
  292. */
  293. /**
  294. * Create a comma-delimited list of wrapped column names.
  295. *
  296. * @param array $columns
  297. * @return string
  298. */
  299. final public function columnize($columns)
  300. {
  301. return implode(', ', array_map(array($this, 'wrap'), $columns));
  302. }
  303. /**
  304. * Wrap a value in keyword identifiers.
  305. *
  306. * They keyword identifier used by the method is specified as
  307. * a property on the grammar class so it can be conveniently
  308. * overriden without changing the wrapping logic itself.
  309. *
  310. * @param string $value
  311. * @return string
  312. */
  313. public function wrap($value)
  314. {
  315. // If the value being wrapped contains a column alias, we need to wrap
  316. // it a little differently since each segment must be wrapped and not
  317. // the entire string.
  318. if (strpos(strtolower($value), ' as ') !== false)
  319. {
  320. return $this->alias($value);
  321. }
  322. // Expressions should be injected into the query as raw strings, so we
  323. // do not want to wrap them in any way. We will just return the string
  324. // value from the expression to be included in the query.
  325. if ($value instanceof Expression) return $value->get();
  326. foreach (explode('.', $value) as $segment)
  327. {
  328. if ($segment === '*')
  329. {
  330. $wrapped[] = $segment;
  331. }
  332. else
  333. {
  334. $wrapped[] = $this->wrapper.$segment.$this->wrapper;
  335. }
  336. }
  337. return implode('.', $wrapped);
  338. }
  339. /**
  340. * Wrap an alias in keyword identifiers.
  341. *
  342. * @param string $value
  343. * @return string
  344. */
  345. protected function alias($value)
  346. {
  347. $segments = explode(' ', $value);
  348. return $this->wrap($segments[0]).' AS '.$this->wrap($segments[2]);
  349. }
  350. /**
  351. * Create query parameters from an array of values.
  352. *
  353. * @param array $values
  354. * @return string
  355. */
  356. public function parameterize($values)
  357. {
  358. return implode(', ', array_map(array($this, 'parameter'), $values));
  359. }
  360. /**
  361. * Get the appropriate query parameter string for a value.
  362. *
  363. * If the value is an expression, the raw expression string should
  364. * be returned, otherwise, the parameter place-holder will be
  365. * returned by the method.
  366. *
  367. * @param mixed $value
  368. * @return string
  369. */
  370. public function parameter($value)
  371. {
  372. return ($value instanceof Expression) ? $value->get() : '?';
  373. }
  374. }