grammar.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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. return $this->wrap($where['column']).' '.$where['operator'].' '.$this->parameter($where['value']);
  144. }
  145. /**
  146. * Compile a WHERE IN clause.
  147. *
  148. * @param array $where
  149. * @return string
  150. */
  151. protected function where_in($where)
  152. {
  153. return $this->wrap($where['column']).' IN ('.$this->parameterize($where['values']).')';
  154. }
  155. /**
  156. * Compile a WHERE NOT IN clause.
  157. *
  158. * @param array $where
  159. * @return string
  160. */
  161. protected function where_not_in($where)
  162. {
  163. return $this->wrap($where['column']).' NOT IN ('.$this->parameterize($where['values']).')';
  164. }
  165. /**
  166. * Compile a WHERE NULL clause.
  167. *
  168. * @param array $where
  169. * @return string
  170. */
  171. protected function where_null($where)
  172. {
  173. return $this->wrap($where['column']).' IS NULL';
  174. }
  175. /**
  176. * Compile a WHERE NULL clause.
  177. *
  178. * @param array $where
  179. * @return string
  180. */
  181. protected function where_not_null($where)
  182. {
  183. return $this->wrap($where['column']).' IS NOT NULL';
  184. }
  185. /**
  186. * Compile a raw WHERE clause.
  187. *
  188. * @param string $where
  189. * @return string
  190. */
  191. protected function where_raw($where)
  192. {
  193. return $where;
  194. }
  195. /**
  196. * Compile the ORDER BY clause for a query.
  197. *
  198. * @param Query $query
  199. * @return string
  200. */
  201. protected function orderings(Query $query)
  202. {
  203. foreach ($query->orderings as $ordering)
  204. {
  205. $sql[] = $this->wrap($ordering['column']).' '.strtoupper($ordering['direction']);
  206. }
  207. return 'ORDER BY '.implode(', ', $sql);
  208. }
  209. /**
  210. * Compile the LIMIT clause for a query.
  211. *
  212. * @param Query $query
  213. * @return string
  214. */
  215. protected function limit(Query $query)
  216. {
  217. return 'LIMIT '.$query->limit;
  218. }
  219. /**
  220. * Compile the OFFSET clause for a query.
  221. *
  222. * @param Query $query
  223. * @return string
  224. */
  225. protected function offset(Query $query)
  226. {
  227. return 'OFFSET '.$query->offset;
  228. }
  229. /**
  230. * Compile a SQL INSERT statment from a Query instance.
  231. *
  232. * Note: This method handles the compilation of single row inserts and batch inserts.
  233. *
  234. * @param Query $query
  235. * @param array $values
  236. * @return string
  237. */
  238. public function insert(Query $query, $values)
  239. {
  240. // Force every insert to be treated like a batch insert. This simple makes
  241. // creating the SQL syntax a little easier on us since we can always treat
  242. // the values as if it is an array containing multiple inserts.
  243. if ( ! is_array(reset($values))) $values = array($values);
  244. // Since we only care about the column names, we can pass any of the insert
  245. // arrays into the "columnize" method. The names should be the same for
  246. // every insert to the table.
  247. $columns = $this->columnize(array_keys(reset($values)));
  248. // Build the list of parameter place-holders of values bound to the query.
  249. // Each insert should have the same number of bound paramters, so we can
  250. // just use the first array of values.
  251. $parameters = $this->parameterize(reset($values));
  252. $parameters = implode(', ', array_fill(0, count($values), '('.$parameters.')'));
  253. return 'INSERT INTO '.$this->wrap($query->from).' ('.$columns.') VALUES '.$parameters;
  254. }
  255. /**
  256. * Compile a SQL UPDATE statment from a Query instance.
  257. *
  258. * Note: Since UPDATE statements can be limited by a WHERE clause,
  259. * this method will use the same WHERE clause compilation
  260. * functions as the "select" method.
  261. *
  262. * @param Query $query
  263. * @param array $values
  264. * @return string
  265. */
  266. public function update(Query $query, $values)
  267. {
  268. foreach ($values as $column => $value)
  269. {
  270. $columns[] = $this->wrap($column).' = '.$this->parameter($value);
  271. }
  272. $columns = implode(', ', $columns);
  273. return trim('UPDATE '.$this->wrap($query->from).' SET '.$columns.' '.$this->wheres($query));
  274. }
  275. /**
  276. * Compile a SQL DELETE statment from a Query instance.
  277. *
  278. * @param Query $query
  279. * @return string
  280. */
  281. public function delete(Query $query)
  282. {
  283. return trim('DELETE FROM '.$this->wrap($query->from).' '.$this->wheres($query));
  284. }
  285. /**
  286. * The following functions primarily serve as utility functions for
  287. * the grammar. They perform tasks such as wrapping values in keyword
  288. * identifiers or creating variable lists of bindings.
  289. */
  290. /**
  291. * Create a comma-delimited list of wrapped column names.
  292. *
  293. * @param array $columns
  294. * @return string
  295. */
  296. final public function columnize($columns)
  297. {
  298. return implode(', ', array_map(array($this, 'wrap'), $columns));
  299. }
  300. /**
  301. * Wrap a value in keyword identifiers.
  302. *
  303. * They keyword identifier used by the method is specified as
  304. * a property on the grammar class so it can be conveniently
  305. * overriden without changing the wrapping logic itself.
  306. *
  307. * @param string $value
  308. * @return string
  309. */
  310. public function wrap($value)
  311. {
  312. // If the value being wrapped contains a column alias, we need to wrap
  313. // it a little differently since each segment must be wrapped and not
  314. // the entire string.
  315. if (strpos(strtolower($value), ' as ') !== false)
  316. {
  317. return $this->alias($value);
  318. }
  319. // Expressions should be injected into the query as raw strings, so we
  320. // do not want to wrap them in any way. We will just return the string
  321. // value from the expression to be included in the query.
  322. if ($value instanceof Expression) return $value->get();
  323. foreach (explode('.', $value) as $segment)
  324. {
  325. if ($segment === '*')
  326. {
  327. $wrapped[] = $segment;
  328. }
  329. else
  330. {
  331. $wrapped[] = $this->wrapper.$segment.$this->wrapper;
  332. }
  333. }
  334. return implode('.', $wrapped);
  335. }
  336. /**
  337. * Wrap an alias in keyword identifiers.
  338. *
  339. * @param string $value
  340. * @return string
  341. */
  342. protected function alias($value)
  343. {
  344. $segments = explode(' ', $value);
  345. return $this->wrap($segments[0]).' AS '.$this->wrap($segments[2]);
  346. }
  347. /**
  348. * Create query parameters from an array of values.
  349. *
  350. * @param array $values
  351. * @return string
  352. */
  353. public function parameterize($values)
  354. {
  355. return implode(', ', array_map(array($this, 'parameter'), $values));
  356. }
  357. /**
  358. * Get the appropriate query parameter string for a value.
  359. *
  360. * If the value is an expression, the raw expression string should
  361. * be returned, otherwise, the parameter place-holder will be
  362. * returned by the method.
  363. *
  364. * @param mixed $value
  365. * @return string
  366. */
  367. public function parameter($value)
  368. {
  369. return ($value instanceof Expression) ? $value->get() : '?';
  370. }
  371. }