Grammar.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. <?php
  2. namespace Illuminate\Database\Query\Grammars;
  3. use Illuminate\Support\Arr;
  4. use Illuminate\Database\Query\Builder;
  5. use Illuminate\Database\Query\JoinClause;
  6. use Illuminate\Database\Grammar as BaseGrammar;
  7. class Grammar extends BaseGrammar
  8. {
  9. /**
  10. * The grammar specific operators.
  11. *
  12. * @var array
  13. */
  14. protected $operators = [];
  15. /**
  16. * The components that make up a select clause.
  17. *
  18. * @var array
  19. */
  20. protected $selectComponents = [
  21. 'aggregate',
  22. 'columns',
  23. 'from',
  24. 'joins',
  25. 'wheres',
  26. 'groups',
  27. 'havings',
  28. 'orders',
  29. 'limit',
  30. 'offset',
  31. 'unions',
  32. 'lock',
  33. ];
  34. /**
  35. * Compile a select query into SQL.
  36. *
  37. * @param \Illuminate\Database\Query\Builder $query
  38. * @return string
  39. */
  40. public function compileSelect(Builder $query)
  41. {
  42. // If the query does not have any columns set, we'll set the columns to the
  43. // * character to just get all of the columns from the database. Then we
  44. // can build the query and concatenate all the pieces together as one.
  45. $original = $query->columns;
  46. if (is_null($query->columns)) {
  47. $query->columns = ['*'];
  48. }
  49. // To compile the query, we'll spin through each component of the query and
  50. // see if that component exists. If it does we'll just call the compiler
  51. // function for the component which is responsible for making the SQL.
  52. $sql = trim($this->concatenate(
  53. $this->compileComponents($query))
  54. );
  55. $query->columns = $original;
  56. return $sql;
  57. }
  58. /**
  59. * Compile the components necessary for a select clause.
  60. *
  61. * @param \Illuminate\Database\Query\Builder $query
  62. * @return array
  63. */
  64. protected function compileComponents(Builder $query)
  65. {
  66. $sql = [];
  67. foreach ($this->selectComponents as $component) {
  68. // To compile the query, we'll spin through each component of the query and
  69. // see if that component exists. If it does we'll just call the compiler
  70. // function for the component which is responsible for making the SQL.
  71. if (! is_null($query->$component)) {
  72. $method = 'compile'.ucfirst($component);
  73. $sql[$component] = $this->$method($query, $query->$component);
  74. }
  75. }
  76. return $sql;
  77. }
  78. /**
  79. * Compile an aggregated select clause.
  80. *
  81. * @param \Illuminate\Database\Query\Builder $query
  82. * @param array $aggregate
  83. * @return string
  84. */
  85. protected function compileAggregate(Builder $query, $aggregate)
  86. {
  87. $column = $this->columnize($aggregate['columns']);
  88. // If the query has a "distinct" constraint and we're not asking for all columns
  89. // we need to prepend "distinct" onto the column name so that the query takes
  90. // it into account when it performs the aggregating operations on the data.
  91. if ($query->distinct && $column !== '*') {
  92. $column = 'distinct '.$column;
  93. }
  94. return 'select '.$aggregate['function'].'('.$column.') as aggregate';
  95. }
  96. /**
  97. * Compile the "select *" portion of the query.
  98. *
  99. * @param \Illuminate\Database\Query\Builder $query
  100. * @param array $columns
  101. * @return string|null
  102. */
  103. protected function compileColumns(Builder $query, $columns)
  104. {
  105. // If the query is actually performing an aggregating select, we will let that
  106. // compiler handle the building of the select clauses, as it will need some
  107. // more syntax that is best handled by that function to keep things neat.
  108. if (! is_null($query->aggregate)) {
  109. return;
  110. }
  111. $select = $query->distinct ? 'select distinct ' : 'select ';
  112. return $select.$this->columnize($columns);
  113. }
  114. /**
  115. * Compile the "from" portion of the query.
  116. *
  117. * @param \Illuminate\Database\Query\Builder $query
  118. * @param string $table
  119. * @return string
  120. */
  121. protected function compileFrom(Builder $query, $table)
  122. {
  123. return 'from '.$this->wrapTable($table);
  124. }
  125. /**
  126. * Compile the "join" portions of the query.
  127. *
  128. * @param \Illuminate\Database\Query\Builder $query
  129. * @param array $joins
  130. * @return string
  131. */
  132. protected function compileJoins(Builder $query, $joins)
  133. {
  134. return collect($joins)->map(function ($join) {
  135. $table = $this->wrapTable($join->table);
  136. return trim("{$join->type} join {$table} {$this->compileWheres($join)}");
  137. })->implode(' ');
  138. }
  139. /**
  140. * Compile the "where" portions of the query.
  141. *
  142. * @param \Illuminate\Database\Query\Builder $query
  143. * @return string
  144. */
  145. protected function compileWheres(Builder $query)
  146. {
  147. // Each type of where clauses has its own compiler function which is responsible
  148. // for actually creating the where clauses SQL. This helps keep the code nice
  149. // and maintainable since each clause has a very small method that it uses.
  150. if (is_null($query->wheres)) {
  151. return '';
  152. }
  153. // If we actually have some where clauses, we will strip off the first boolean
  154. // operator, which is added by the query builders for convenience so we can
  155. // avoid checking for the first clauses in each of the compilers methods.
  156. if (count($sql = $this->compileWheresToArray($query)) > 0) {
  157. return $this->concatenateWhereClauses($query, $sql);
  158. }
  159. return '';
  160. }
  161. /**
  162. * Get an array of all the where clauses for the query.
  163. *
  164. * @param \Illuminate\Database\Query\Builder $query
  165. * @return array
  166. */
  167. protected function compileWheresToArray($query)
  168. {
  169. return collect($query->wheres)->map(function ($where) use ($query) {
  170. return $where['boolean'].' '.$this->{"where{$where['type']}"}($query, $where);
  171. })->all();
  172. }
  173. /**
  174. * Format the where clause statements into one string.
  175. *
  176. * @param \Illuminate\Database\Query\Builder $query
  177. * @param array $sql
  178. * @return string
  179. */
  180. protected function concatenateWhereClauses($query, $sql)
  181. {
  182. $conjunction = $query instanceof JoinClause ? 'on' : 'where';
  183. return $conjunction.' '.$this->removeLeadingBoolean(implode(' ', $sql));
  184. }
  185. /**
  186. * Compile a raw where clause.
  187. *
  188. * @param \Illuminate\Database\Query\Builder $query
  189. * @param array $where
  190. * @return string
  191. */
  192. protected function whereRaw(Builder $query, $where)
  193. {
  194. return $where['sql'];
  195. }
  196. /**
  197. * Compile a basic where clause.
  198. *
  199. * @param \Illuminate\Database\Query\Builder $query
  200. * @param array $where
  201. * @return string
  202. */
  203. protected function whereBasic(Builder $query, $where)
  204. {
  205. $value = $this->parameter($where['value']);
  206. return $this->wrap($where['column']).' '.$where['operator'].' '.$value;
  207. }
  208. /**
  209. * Compile a "where in" clause.
  210. *
  211. * @param \Illuminate\Database\Query\Builder $query
  212. * @param array $where
  213. * @return string
  214. */
  215. protected function whereIn(Builder $query, $where)
  216. {
  217. if (! empty($where['values'])) {
  218. return $this->wrap($where['column']).' in ('.$this->parameterize($where['values']).')';
  219. }
  220. return '0 = 1';
  221. }
  222. /**
  223. * Compile a "where not in" clause.
  224. *
  225. * @param \Illuminate\Database\Query\Builder $query
  226. * @param array $where
  227. * @return string
  228. */
  229. protected function whereNotIn(Builder $query, $where)
  230. {
  231. if (! empty($where['values'])) {
  232. return $this->wrap($where['column']).' not in ('.$this->parameterize($where['values']).')';
  233. }
  234. return '1 = 1';
  235. }
  236. /**
  237. * Compile a where in sub-select clause.
  238. *
  239. * @param \Illuminate\Database\Query\Builder $query
  240. * @param array $where
  241. * @return string
  242. */
  243. protected function whereInSub(Builder $query, $where)
  244. {
  245. return $this->wrap($where['column']).' in ('.$this->compileSelect($where['query']).')';
  246. }
  247. /**
  248. * Compile a where not in sub-select clause.
  249. *
  250. * @param \Illuminate\Database\Query\Builder $query
  251. * @param array $where
  252. * @return string
  253. */
  254. protected function whereNotInSub(Builder $query, $where)
  255. {
  256. return $this->wrap($where['column']).' not in ('.$this->compileSelect($where['query']).')';
  257. }
  258. /**
  259. * Compile a "where null" clause.
  260. *
  261. * @param \Illuminate\Database\Query\Builder $query
  262. * @param array $where
  263. * @return string
  264. */
  265. protected function whereNull(Builder $query, $where)
  266. {
  267. return $this->wrap($where['column']).' is null';
  268. }
  269. /**
  270. * Compile a "where not null" clause.
  271. *
  272. * @param \Illuminate\Database\Query\Builder $query
  273. * @param array $where
  274. * @return string
  275. */
  276. protected function whereNotNull(Builder $query, $where)
  277. {
  278. return $this->wrap($where['column']).' is not null';
  279. }
  280. /**
  281. * Compile a "between" where clause.
  282. *
  283. * @param \Illuminate\Database\Query\Builder $query
  284. * @param array $where
  285. * @return string
  286. */
  287. protected function whereBetween(Builder $query, $where)
  288. {
  289. $between = $where['not'] ? 'not between' : 'between';
  290. return $this->wrap($where['column']).' '.$between.' ? and ?';
  291. }
  292. /**
  293. * Compile a "where date" clause.
  294. *
  295. * @param \Illuminate\Database\Query\Builder $query
  296. * @param array $where
  297. * @return string
  298. */
  299. protected function whereDate(Builder $query, $where)
  300. {
  301. return $this->dateBasedWhere('date', $query, $where);
  302. }
  303. /**
  304. * Compile a "where time" clause.
  305. *
  306. * @param \Illuminate\Database\Query\Builder $query
  307. * @param array $where
  308. * @return string
  309. */
  310. protected function whereTime(Builder $query, $where)
  311. {
  312. return $this->dateBasedWhere('time', $query, $where);
  313. }
  314. /**
  315. * Compile a "where day" clause.
  316. *
  317. * @param \Illuminate\Database\Query\Builder $query
  318. * @param array $where
  319. * @return string
  320. */
  321. protected function whereDay(Builder $query, $where)
  322. {
  323. return $this->dateBasedWhere('day', $query, $where);
  324. }
  325. /**
  326. * Compile a "where month" clause.
  327. *
  328. * @param \Illuminate\Database\Query\Builder $query
  329. * @param array $where
  330. * @return string
  331. */
  332. protected function whereMonth(Builder $query, $where)
  333. {
  334. return $this->dateBasedWhere('month', $query, $where);
  335. }
  336. /**
  337. * Compile a "where year" clause.
  338. *
  339. * @param \Illuminate\Database\Query\Builder $query
  340. * @param array $where
  341. * @return string
  342. */
  343. protected function whereYear(Builder $query, $where)
  344. {
  345. return $this->dateBasedWhere('year', $query, $where);
  346. }
  347. /**
  348. * Compile a date based where clause.
  349. *
  350. * @param string $type
  351. * @param \Illuminate\Database\Query\Builder $query
  352. * @param array $where
  353. * @return string
  354. */
  355. protected function dateBasedWhere($type, Builder $query, $where)
  356. {
  357. $value = $this->parameter($where['value']);
  358. return $type.'('.$this->wrap($where['column']).') '.$where['operator'].' '.$value;
  359. }
  360. /**
  361. * Compile a where clause comparing two columns..
  362. *
  363. * @param \Illuminate\Database\Query\Builder $query
  364. * @param array $where
  365. * @return string
  366. */
  367. protected function whereColumn(Builder $query, $where)
  368. {
  369. return $this->wrap($where['first']).' '.$where['operator'].' '.$this->wrap($where['second']);
  370. }
  371. /**
  372. * Compile a nested where clause.
  373. *
  374. * @param \Illuminate\Database\Query\Builder $query
  375. * @param array $where
  376. * @return string
  377. */
  378. protected function whereNested(Builder $query, $where)
  379. {
  380. // Here we will calculate what portion of the string we need to remove. If this
  381. // is a join clause query, we need to remove the "on" portion of the SQL and
  382. // if it is a normal query we need to take the leading "where" of queries.
  383. $offset = $query instanceof JoinClause ? 3 : 6;
  384. return '('.substr($this->compileWheres($where['query']), $offset).')';
  385. }
  386. /**
  387. * Compile a where condition with a sub-select.
  388. *
  389. * @param \Illuminate\Database\Query\Builder $query
  390. * @param array $where
  391. * @return string
  392. */
  393. protected function whereSub(Builder $query, $where)
  394. {
  395. $select = $this->compileSelect($where['query']);
  396. return $this->wrap($where['column']).' '.$where['operator']." ($select)";
  397. }
  398. /**
  399. * Compile a where exists clause.
  400. *
  401. * @param \Illuminate\Database\Query\Builder $query
  402. * @param array $where
  403. * @return string
  404. */
  405. protected function whereExists(Builder $query, $where)
  406. {
  407. return 'exists ('.$this->compileSelect($where['query']).')';
  408. }
  409. /**
  410. * Compile a where exists clause.
  411. *
  412. * @param \Illuminate\Database\Query\Builder $query
  413. * @param array $where
  414. * @return string
  415. */
  416. protected function whereNotExists(Builder $query, $where)
  417. {
  418. return 'not exists ('.$this->compileSelect($where['query']).')';
  419. }
  420. /**
  421. * Compile the "group by" portions of the query.
  422. *
  423. * @param \Illuminate\Database\Query\Builder $query
  424. * @param array $groups
  425. * @return string
  426. */
  427. protected function compileGroups(Builder $query, $groups)
  428. {
  429. return 'group by '.$this->columnize($groups);
  430. }
  431. /**
  432. * Compile the "having" portions of the query.
  433. *
  434. * @param \Illuminate\Database\Query\Builder $query
  435. * @param array $havings
  436. * @return string
  437. */
  438. protected function compileHavings(Builder $query, $havings)
  439. {
  440. $sql = implode(' ', array_map([$this, 'compileHaving'], $havings));
  441. return 'having '.$this->removeLeadingBoolean($sql);
  442. }
  443. /**
  444. * Compile a single having clause.
  445. *
  446. * @param array $having
  447. * @return string
  448. */
  449. protected function compileHaving(array $having)
  450. {
  451. // If the having clause is "raw", we can just return the clause straight away
  452. // without doing any more processing on it. Otherwise, we will compile the
  453. // clause into SQL based on the components that make it up from builder.
  454. if ($having['type'] === 'Raw') {
  455. return $having['boolean'].' '.$having['sql'];
  456. }
  457. return $this->compileBasicHaving($having);
  458. }
  459. /**
  460. * Compile a basic having clause.
  461. *
  462. * @param array $having
  463. * @return string
  464. */
  465. protected function compileBasicHaving($having)
  466. {
  467. $column = $this->wrap($having['column']);
  468. $parameter = $this->parameter($having['value']);
  469. return $having['boolean'].' '.$column.' '.$having['operator'].' '.$parameter;
  470. }
  471. /**
  472. * Compile the "order by" portions of the query.
  473. *
  474. * @param \Illuminate\Database\Query\Builder $query
  475. * @param array $orders
  476. * @return string
  477. */
  478. protected function compileOrders(Builder $query, $orders)
  479. {
  480. if (! empty($orders)) {
  481. return 'order by '.implode(', ', $this->compileOrdersToArray($query, $orders));
  482. }
  483. return '';
  484. }
  485. /**
  486. * Compile the query orders to an array.
  487. *
  488. * @param \Illuminate\Database\Query\Builder $query
  489. * @param array $orders
  490. * @return array
  491. */
  492. protected function compileOrdersToArray(Builder $query, $orders)
  493. {
  494. return array_map(function ($order) {
  495. return ! isset($order['sql'])
  496. ? $this->wrap($order['column']).' '.$order['direction']
  497. : $order['sql'];
  498. }, $orders);
  499. }
  500. /**
  501. * Compile the random statement into SQL.
  502. *
  503. * @param string $seed
  504. * @return string
  505. */
  506. public function compileRandom($seed)
  507. {
  508. return 'RANDOM()';
  509. }
  510. /**
  511. * Compile the "limit" portions of the query.
  512. *
  513. * @param \Illuminate\Database\Query\Builder $query
  514. * @param int $limit
  515. * @return string
  516. */
  517. protected function compileLimit(Builder $query, $limit)
  518. {
  519. return 'limit '.(int) $limit;
  520. }
  521. /**
  522. * Compile the "offset" portions of the query.
  523. *
  524. * @param \Illuminate\Database\Query\Builder $query
  525. * @param int $offset
  526. * @return string
  527. */
  528. protected function compileOffset(Builder $query, $offset)
  529. {
  530. return 'offset '.(int) $offset;
  531. }
  532. /**
  533. * Compile the "union" queries attached to the main query.
  534. *
  535. * @param \Illuminate\Database\Query\Builder $query
  536. * @return string
  537. */
  538. protected function compileUnions(Builder $query)
  539. {
  540. $sql = '';
  541. foreach ($query->unions as $union) {
  542. $sql .= $this->compileUnion($union);
  543. }
  544. if (! empty($query->unionOrders)) {
  545. $sql .= ' '.$this->compileOrders($query, $query->unionOrders);
  546. }
  547. if (isset($query->unionLimit)) {
  548. $sql .= ' '.$this->compileLimit($query, $query->unionLimit);
  549. }
  550. if (isset($query->unionOffset)) {
  551. $sql .= ' '.$this->compileOffset($query, $query->unionOffset);
  552. }
  553. return ltrim($sql);
  554. }
  555. /**
  556. * Compile a single union statement.
  557. *
  558. * @param array $union
  559. * @return string
  560. */
  561. protected function compileUnion(array $union)
  562. {
  563. $conjuction = $union['all'] ? ' union all ' : ' union ';
  564. return $conjuction.$union['query']->toSql();
  565. }
  566. /**
  567. * Compile an exists statement into SQL.
  568. *
  569. * @param \Illuminate\Database\Query\Builder $query
  570. * @return string
  571. */
  572. public function compileExists(Builder $query)
  573. {
  574. $select = $this->compileSelect($query);
  575. return "select exists({$select}) as {$this->wrap('exists')}";
  576. }
  577. /**
  578. * Compile an insert statement into SQL.
  579. *
  580. * @param \Illuminate\Database\Query\Builder $query
  581. * @param array $values
  582. * @return string
  583. */
  584. public function compileInsert(Builder $query, array $values)
  585. {
  586. // Essentially we will force every insert to be treated as a batch insert which
  587. // simply makes creating the SQL easier for us since we can utilize the same
  588. // basic routine regardless of an amount of records given to us to insert.
  589. $table = $this->wrapTable($query->from);
  590. if (! is_array(reset($values))) {
  591. $values = [$values];
  592. }
  593. $columns = $this->columnize(array_keys(reset($values)));
  594. // We need to build a list of parameter place-holders of values that are bound
  595. // to the query. Each insert should have the exact same amount of parameter
  596. // bindings so we will loop through the record and parameterize them all.
  597. $parameters = collect($values)->map(function ($record) {
  598. return '('.$this->parameterize($record).')';
  599. })->implode(', ');
  600. return "insert into $table ($columns) values $parameters";
  601. }
  602. /**
  603. * Compile an insert and get ID statement into SQL.
  604. *
  605. * @param \Illuminate\Database\Query\Builder $query
  606. * @param array $values
  607. * @param string $sequence
  608. * @return string
  609. */
  610. public function compileInsertGetId(Builder $query, $values, $sequence)
  611. {
  612. return $this->compileInsert($query, $values);
  613. }
  614. /**
  615. * Compile an update statement into SQL.
  616. *
  617. * @param \Illuminate\Database\Query\Builder $query
  618. * @param array $values
  619. * @return string
  620. */
  621. public function compileUpdate(Builder $query, $values)
  622. {
  623. $table = $this->wrapTable($query->from);
  624. // Each one of the columns in the update statements needs to be wrapped in the
  625. // keyword identifiers, also a place-holder needs to be created for each of
  626. // the values in the list of bindings so we can make the sets statements.
  627. $columns = collect($values)->map(function ($value, $key) {
  628. return $this->wrap($key).' = '.$this->parameter($value);
  629. })->implode(', ');
  630. // If the query has any "join" clauses, we will setup the joins on the builder
  631. // and compile them so we can attach them to this update, as update queries
  632. // can get join statements to attach to other tables when they're needed.
  633. $joins = '';
  634. if (isset($query->joins)) {
  635. $joins = ' '.$this->compileJoins($query, $query->joins);
  636. }
  637. // Of course, update queries may also be constrained by where clauses so we'll
  638. // need to compile the where clauses and attach it to the query so only the
  639. // intended records are updated by the SQL statements we generate to run.
  640. $wheres = $this->compileWheres($query);
  641. return trim("update {$table}{$joins} set $columns $wheres");
  642. }
  643. /**
  644. * Prepare the bindings for an update statement.
  645. *
  646. * @param array $bindings
  647. * @param array $values
  648. * @return array
  649. */
  650. public function prepareBindingsForUpdate(array $bindings, array $values)
  651. {
  652. $cleanBindings = Arr::except($bindings, ['join', 'select']);
  653. return array_values(
  654. array_merge($bindings['join'], $values, Arr::flatten($cleanBindings))
  655. );
  656. }
  657. /**
  658. * Compile a delete statement into SQL.
  659. *
  660. * @param \Illuminate\Database\Query\Builder $query
  661. * @return string
  662. */
  663. public function compileDelete(Builder $query)
  664. {
  665. $wheres = is_array($query->wheres) ? $this->compileWheres($query) : '';
  666. return trim("delete from {$this->wrapTable($query->from)} $wheres");
  667. }
  668. /**
  669. * Prepare the bindings for a delete statement.
  670. *
  671. * @param array $bindings
  672. * @return array
  673. */
  674. public function prepareBindingsForDelete(array $bindings)
  675. {
  676. return Arr::flatten($bindings);
  677. }
  678. /**
  679. * Compile a truncate table statement into SQL.
  680. *
  681. * @param \Illuminate\Database\Query\Builder $query
  682. * @return array
  683. */
  684. public function compileTruncate(Builder $query)
  685. {
  686. return ['truncate '.$this->wrapTable($query->from) => []];
  687. }
  688. /**
  689. * Compile the lock into SQL.
  690. *
  691. * @param \Illuminate\Database\Query\Builder $query
  692. * @param bool|string $value
  693. * @return string
  694. */
  695. protected function compileLock(Builder $query, $value)
  696. {
  697. return is_string($value) ? $value : '';
  698. }
  699. /**
  700. * Determine if the grammar supports savepoints.
  701. *
  702. * @return bool
  703. */
  704. public function supportsSavepoints()
  705. {
  706. return true;
  707. }
  708. /**
  709. * Compile the SQL statement to define a savepoint.
  710. *
  711. * @param string $name
  712. * @return string
  713. */
  714. public function compileSavepoint($name)
  715. {
  716. return 'SAVEPOINT '.$name;
  717. }
  718. /**
  719. * Compile the SQL statement to execute a savepoint rollback.
  720. *
  721. * @param string $name
  722. * @return string
  723. */
  724. public function compileSavepointRollBack($name)
  725. {
  726. return 'ROLLBACK TO SAVEPOINT '.$name;
  727. }
  728. /**
  729. * Concatenate an array of segments, removing empties.
  730. *
  731. * @param array $segments
  732. * @return string
  733. */
  734. protected function concatenate($segments)
  735. {
  736. return implode(' ', array_filter($segments, function ($value) {
  737. return (string) $value !== '';
  738. }));
  739. }
  740. /**
  741. * Remove the leading boolean from a statement.
  742. *
  743. * @param string $value
  744. * @return string
  745. */
  746. protected function removeLeadingBoolean($value)
  747. {
  748. return preg_replace('/and |or /i', '', $value, 1);
  749. }
  750. /**
  751. * Get the grammar specific operators.
  752. *
  753. * @return array
  754. */
  755. public function getOperators()
  756. {
  757. return $this->operators;
  758. }
  759. }