SQLiteGrammar.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. <?php
  2. namespace Illuminate\Database\Schema\Grammars;
  3. use RuntimeException;
  4. use Illuminate\Support\Fluent;
  5. use Illuminate\Database\Connection;
  6. use Illuminate\Database\Schema\Blueprint;
  7. class SQLiteGrammar extends Grammar
  8. {
  9. /**
  10. * The possible column modifiers.
  11. *
  12. * @var array
  13. */
  14. protected $modifiers = ['Nullable', 'Default', 'Increment'];
  15. /**
  16. * The columns available as serials.
  17. *
  18. * @var array
  19. */
  20. protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger'];
  21. /**
  22. * Compile the query to determine if a table exists.
  23. *
  24. * @return string
  25. */
  26. public function compileTableExists()
  27. {
  28. return "select * from sqlite_master where type = 'table' and name = ?";
  29. }
  30. /**
  31. * Compile the query to determine the list of columns.
  32. *
  33. * @param string $table
  34. * @return string
  35. */
  36. public function compileColumnListing($table)
  37. {
  38. return 'pragma table_info('.$this->wrap(str_replace('.', '__', $table)).')';
  39. }
  40. /**
  41. * Compile a create table command.
  42. *
  43. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  44. * @param \Illuminate\Support\Fluent $command
  45. * @return string
  46. */
  47. public function compileCreate(Blueprint $blueprint, Fluent $command)
  48. {
  49. return sprintf('%s table %s (%s%s%s)',
  50. $blueprint->temporary ? 'create temporary' : 'create',
  51. $this->wrapTable($blueprint),
  52. implode(', ', $this->getColumns($blueprint)),
  53. (string) $this->addForeignKeys($blueprint),
  54. (string) $this->addPrimaryKeys($blueprint)
  55. );
  56. }
  57. /**
  58. * Get the foreign key syntax for a table creation statement.
  59. *
  60. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  61. * @return string|null
  62. */
  63. protected function addForeignKeys(Blueprint $blueprint)
  64. {
  65. $foreigns = $this->getCommandsByName($blueprint, 'foreign');
  66. return collect($foreigns)->reduce(function ($sql, $foreign) {
  67. // Once we have all the foreign key commands for the table creation statement
  68. // we'll loop through each of them and add them to the create table SQL we
  69. // are building, since SQLite needs foreign keys on the tables creation.
  70. $sql .= $this->getForeignKey($foreign);
  71. if (! is_null($foreign->onDelete)) {
  72. $sql .= " on delete {$foreign->onDelete}";
  73. }
  74. // If this foreign key specifies the action to be taken on update we will add
  75. // that to the statement here. We'll append it to this SQL and then return
  76. // the SQL so we can keep adding any other foreign consraints onto this.
  77. if (! is_null($foreign->onUpdate)) {
  78. $sql .= " on update {$foreign->onUpdate}";
  79. }
  80. return $sql;
  81. }, '');
  82. }
  83. /**
  84. * Get the SQL for the foreign key.
  85. *
  86. * @param \Illuminate\Support\Fluent $foreign
  87. * @return string
  88. */
  89. protected function getForeignKey($foreign)
  90. {
  91. // We need to columnize the columns that the foreign key is being defined for
  92. // so that it is a properly formatted list. Once we have done this, we can
  93. // return the foreign key SQL declaration to the calling method for use.
  94. return sprintf(', foreign key(%s) references %s(%s)',
  95. $this->columnize($foreign->columns),
  96. $this->wrapTable($foreign->on),
  97. $this->columnize((array) $foreign->references)
  98. );
  99. }
  100. /**
  101. * Get the primary key syntax for a table creation statement.
  102. *
  103. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  104. * @return string|null
  105. */
  106. protected function addPrimaryKeys(Blueprint $blueprint)
  107. {
  108. if (! is_null($primary = $this->getCommandByName($blueprint, 'primary'))) {
  109. return ", primary key ({$this->columnize($primary->columns)})";
  110. }
  111. }
  112. /**
  113. * Compile alter table commands for adding columns.
  114. *
  115. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  116. * @param \Illuminate\Support\Fluent $command
  117. * @return array
  118. */
  119. public function compileAdd(Blueprint $blueprint, Fluent $command)
  120. {
  121. $columns = $this->prefixArray('add column', $this->getColumns($blueprint));
  122. return collect($columns)->map(function ($column) use ($blueprint) {
  123. return 'alter table '.$this->wrapTable($blueprint).' '.$column;
  124. })->all();
  125. }
  126. /**
  127. * Compile a unique key command.
  128. *
  129. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  130. * @param \Illuminate\Support\Fluent $command
  131. * @return string
  132. */
  133. public function compileUnique(Blueprint $blueprint, Fluent $command)
  134. {
  135. return sprintf('create unique index %s on %s (%s)',
  136. $this->wrap($command->index),
  137. $this->wrapTable($blueprint),
  138. $this->columnize($command->columns)
  139. );
  140. }
  141. /**
  142. * Compile a plain index key command.
  143. *
  144. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  145. * @param \Illuminate\Support\Fluent $command
  146. * @return string
  147. */
  148. public function compileIndex(Blueprint $blueprint, Fluent $command)
  149. {
  150. return sprintf('create index %s on %s (%s)',
  151. $this->wrap($command->index),
  152. $this->wrapTable($blueprint),
  153. $this->columnize($command->columns)
  154. );
  155. }
  156. /**
  157. * Compile a spatial index key command.
  158. *
  159. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  160. * @param \Illuminate\Support\Fluent $command
  161. * @throws \RuntimeException
  162. */
  163. public function compileSpatialIndex(Blueprint $blueprint, Fluent $command)
  164. {
  165. throw new RuntimeException('The database driver in use does not support spatial indexes.');
  166. }
  167. /**
  168. * Compile a foreign key command.
  169. *
  170. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  171. * @param \Illuminate\Support\Fluent $command
  172. * @return string
  173. */
  174. public function compileForeign(Blueprint $blueprint, Fluent $command)
  175. {
  176. // Handled on table creation...
  177. }
  178. /**
  179. * Compile a drop table command.
  180. *
  181. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  182. * @param \Illuminate\Support\Fluent $command
  183. * @return string
  184. */
  185. public function compileDrop(Blueprint $blueprint, Fluent $command)
  186. {
  187. return 'drop table '.$this->wrapTable($blueprint);
  188. }
  189. /**
  190. * Compile a drop table (if exists) command.
  191. *
  192. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  193. * @param \Illuminate\Support\Fluent $command
  194. * @return string
  195. */
  196. public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
  197. {
  198. return 'drop table if exists '.$this->wrapTable($blueprint);
  199. }
  200. /**
  201. * Compile the SQL needed to drop all tables.
  202. *
  203. * @return string
  204. */
  205. public function compileDropAllTables()
  206. {
  207. return "delete from sqlite_master where type in ('table', 'index', 'trigger')";
  208. }
  209. /**
  210. * Compile a drop column command.
  211. *
  212. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  213. * @param \Illuminate\Support\Fluent $command
  214. * @param \Illuminate\Database\Connection $connection
  215. * @return array
  216. */
  217. public function compileDropColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
  218. {
  219. $tableDiff = $this->getDoctrineTableDiff(
  220. $blueprint, $schema = $connection->getDoctrineSchemaManager()
  221. );
  222. foreach ($command->columns as $name) {
  223. $tableDiff->removedColumns[$name] = $connection->getDoctrineColumn(
  224. $this->getTablePrefix().$blueprint->getTable(), $name
  225. );
  226. }
  227. return (array) $schema->getDatabasePlatform()->getAlterTableSQL($tableDiff);
  228. }
  229. /**
  230. * Compile a drop unique key command.
  231. *
  232. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  233. * @param \Illuminate\Support\Fluent $command
  234. * @return string
  235. */
  236. public function compileDropUnique(Blueprint $blueprint, Fluent $command)
  237. {
  238. $index = $this->wrap($command->index);
  239. return "drop index {$index}";
  240. }
  241. /**
  242. * Compile a drop index command.
  243. *
  244. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  245. * @param \Illuminate\Support\Fluent $command
  246. * @return string
  247. */
  248. public function compileDropIndex(Blueprint $blueprint, Fluent $command)
  249. {
  250. $index = $this->wrap($command->index);
  251. return "drop index {$index}";
  252. }
  253. /**
  254. * Compile a drop spatial index command.
  255. *
  256. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  257. * @param \Illuminate\Support\Fluent $command
  258. * @throws \RuntimeException
  259. */
  260. public function compileDropSpatialIndex(Blueprint $blueprint, Fluent $command)
  261. {
  262. throw new RuntimeException('The database driver in use does not support spatial indexes.');
  263. }
  264. /**
  265. * Compile a rename table command.
  266. *
  267. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  268. * @param \Illuminate\Support\Fluent $command
  269. * @return string
  270. */
  271. public function compileRename(Blueprint $blueprint, Fluent $command)
  272. {
  273. $from = $this->wrapTable($blueprint);
  274. return "alter table {$from} rename to ".$this->wrapTable($command->to);
  275. }
  276. /**
  277. * Compile the command to enable foreign key constraints.
  278. *
  279. * @return string
  280. */
  281. public function compileEnableForeignKeyConstraints()
  282. {
  283. return 'PRAGMA foreign_keys = ON;';
  284. }
  285. /**
  286. * Compile the command to disable foreign key constraints.
  287. *
  288. * @return string
  289. */
  290. public function compileDisableForeignKeyConstraints()
  291. {
  292. return 'PRAGMA foreign_keys = OFF;';
  293. }
  294. /**
  295. * Compile the SQL needed to enable a writable schema.
  296. *
  297. * @return string
  298. */
  299. public function compileEnableWriteableSchema()
  300. {
  301. return 'PRAGMA writable_schema = 1;';
  302. }
  303. /**
  304. * Compile the SQL needed to disable a writable schema.
  305. *
  306. * @return string
  307. */
  308. public function compileDisableWriteableSchema()
  309. {
  310. return 'PRAGMA writable_schema = 0;';
  311. }
  312. /**
  313. * Create the column definition for a char type.
  314. *
  315. * @param \Illuminate\Support\Fluent $column
  316. * @return string
  317. */
  318. protected function typeChar(Fluent $column)
  319. {
  320. return 'varchar';
  321. }
  322. /**
  323. * Create the column definition for a string type.
  324. *
  325. * @param \Illuminate\Support\Fluent $column
  326. * @return string
  327. */
  328. protected function typeString(Fluent $column)
  329. {
  330. return 'varchar';
  331. }
  332. /**
  333. * Create the column definition for a text type.
  334. *
  335. * @param \Illuminate\Support\Fluent $column
  336. * @return string
  337. */
  338. protected function typeText(Fluent $column)
  339. {
  340. return 'text';
  341. }
  342. /**
  343. * Create the column definition for a medium text type.
  344. *
  345. * @param \Illuminate\Support\Fluent $column
  346. * @return string
  347. */
  348. protected function typeMediumText(Fluent $column)
  349. {
  350. return 'text';
  351. }
  352. /**
  353. * Create the column definition for a long text type.
  354. *
  355. * @param \Illuminate\Support\Fluent $column
  356. * @return string
  357. */
  358. protected function typeLongText(Fluent $column)
  359. {
  360. return 'text';
  361. }
  362. /**
  363. * Create the column definition for a integer type.
  364. *
  365. * @param \Illuminate\Support\Fluent $column
  366. * @return string
  367. */
  368. protected function typeInteger(Fluent $column)
  369. {
  370. return 'integer';
  371. }
  372. /**
  373. * Create the column definition for a big integer type.
  374. *
  375. * @param \Illuminate\Support\Fluent $column
  376. * @return string
  377. */
  378. protected function typeBigInteger(Fluent $column)
  379. {
  380. return 'integer';
  381. }
  382. /**
  383. * Create the column definition for a medium integer type.
  384. *
  385. * @param \Illuminate\Support\Fluent $column
  386. * @return string
  387. */
  388. protected function typeMediumInteger(Fluent $column)
  389. {
  390. return 'integer';
  391. }
  392. /**
  393. * Create the column definition for a tiny integer type.
  394. *
  395. * @param \Illuminate\Support\Fluent $column
  396. * @return string
  397. */
  398. protected function typeTinyInteger(Fluent $column)
  399. {
  400. return 'integer';
  401. }
  402. /**
  403. * Create the column definition for a small integer type.
  404. *
  405. * @param \Illuminate\Support\Fluent $column
  406. * @return string
  407. */
  408. protected function typeSmallInteger(Fluent $column)
  409. {
  410. return 'integer';
  411. }
  412. /**
  413. * Create the column definition for a float type.
  414. *
  415. * @param \Illuminate\Support\Fluent $column
  416. * @return string
  417. */
  418. protected function typeFloat(Fluent $column)
  419. {
  420. return 'float';
  421. }
  422. /**
  423. * Create the column definition for a double type.
  424. *
  425. * @param \Illuminate\Support\Fluent $column
  426. * @return string
  427. */
  428. protected function typeDouble(Fluent $column)
  429. {
  430. return 'float';
  431. }
  432. /**
  433. * Create the column definition for a decimal type.
  434. *
  435. * @param \Illuminate\Support\Fluent $column
  436. * @return string
  437. */
  438. protected function typeDecimal(Fluent $column)
  439. {
  440. return 'numeric';
  441. }
  442. /**
  443. * Create the column definition for a boolean type.
  444. *
  445. * @param \Illuminate\Support\Fluent $column
  446. * @return string
  447. */
  448. protected function typeBoolean(Fluent $column)
  449. {
  450. return 'tinyint(1)';
  451. }
  452. /**
  453. * Create the column definition for an enum type.
  454. *
  455. * @param \Illuminate\Support\Fluent $column
  456. * @return string
  457. */
  458. protected function typeEnum(Fluent $column)
  459. {
  460. return 'varchar';
  461. }
  462. /**
  463. * Create the column definition for a json type.
  464. *
  465. * @param \Illuminate\Support\Fluent $column
  466. * @return string
  467. */
  468. protected function typeJson(Fluent $column)
  469. {
  470. return 'text';
  471. }
  472. /**
  473. * Create the column definition for a jsonb type.
  474. *
  475. * @param \Illuminate\Support\Fluent $column
  476. * @return string
  477. */
  478. protected function typeJsonb(Fluent $column)
  479. {
  480. return 'text';
  481. }
  482. /**
  483. * Create the column definition for a date type.
  484. *
  485. * @param \Illuminate\Support\Fluent $column
  486. * @return string
  487. */
  488. protected function typeDate(Fluent $column)
  489. {
  490. return 'date';
  491. }
  492. /**
  493. * Create the column definition for a date-time type.
  494. *
  495. * @param \Illuminate\Support\Fluent $column
  496. * @return string
  497. */
  498. protected function typeDateTime(Fluent $column)
  499. {
  500. return 'datetime';
  501. }
  502. /**
  503. * Create the column definition for a date-time (with time zone) type.
  504. *
  505. * Note: "SQLite does not have a storage class set aside for storing dates and/or times."
  506. * @link https://www.sqlite.org/datatype3.html
  507. *
  508. * @param \Illuminate\Support\Fluent $column
  509. * @return string
  510. */
  511. protected function typeDateTimeTz(Fluent $column)
  512. {
  513. return $this->typeDateTime($column);
  514. }
  515. /**
  516. * Create the column definition for a time type.
  517. *
  518. * @param \Illuminate\Support\Fluent $column
  519. * @return string
  520. */
  521. protected function typeTime(Fluent $column)
  522. {
  523. return 'time';
  524. }
  525. /**
  526. * Create the column definition for a time (with time zone) type.
  527. *
  528. * @param \Illuminate\Support\Fluent $column
  529. * @return string
  530. */
  531. protected function typeTimeTz(Fluent $column)
  532. {
  533. return $this->typeTime($column);
  534. }
  535. /**
  536. * Create the column definition for a timestamp type.
  537. *
  538. * @param \Illuminate\Support\Fluent $column
  539. * @return string
  540. */
  541. protected function typeTimestamp(Fluent $column)
  542. {
  543. return $column->useCurrent ? 'datetime default CURRENT_TIMESTAMP' : 'datetime';
  544. }
  545. /**
  546. * Create the column definition for a timestamp (with time zone) type.
  547. *
  548. * @param \Illuminate\Support\Fluent $column
  549. * @return string
  550. */
  551. protected function typeTimestampTz(Fluent $column)
  552. {
  553. return $this->typeTimestamp($column);
  554. }
  555. /**
  556. * Create the column definition for a year type.
  557. *
  558. * @param \Illuminate\Support\Fluent $column
  559. * @return string
  560. */
  561. protected function typeYear(Fluent $column)
  562. {
  563. return $this->typeInteger($column);
  564. }
  565. /**
  566. * Create the column definition for a binary type.
  567. *
  568. * @param \Illuminate\Support\Fluent $column
  569. * @return string
  570. */
  571. protected function typeBinary(Fluent $column)
  572. {
  573. return 'blob';
  574. }
  575. /**
  576. * Create the column definition for a uuid type.
  577. *
  578. * @param \Illuminate\Support\Fluent $column
  579. * @return string
  580. */
  581. protected function typeUuid(Fluent $column)
  582. {
  583. return 'varchar';
  584. }
  585. /**
  586. * Create the column definition for an IP address type.
  587. *
  588. * @param \Illuminate\Support\Fluent $column
  589. * @return string
  590. */
  591. protected function typeIpAddress(Fluent $column)
  592. {
  593. return 'varchar';
  594. }
  595. /**
  596. * Create the column definition for a MAC address type.
  597. *
  598. * @param \Illuminate\Support\Fluent $column
  599. * @return string
  600. */
  601. protected function typeMacAddress(Fluent $column)
  602. {
  603. return 'varchar';
  604. }
  605. /**
  606. * Create the column definition for a spatial Geometry type.
  607. *
  608. * @param \Illuminate\Support\Fluent $column
  609. * @return string
  610. */
  611. public function typeGeometry(Fluent $column)
  612. {
  613. return 'geometry';
  614. }
  615. /**
  616. * Create the column definition for a spatial Point type.
  617. *
  618. * @param \Illuminate\Support\Fluent $column
  619. * @return string
  620. */
  621. public function typePoint(Fluent $column)
  622. {
  623. return 'point';
  624. }
  625. /**
  626. * Create the column definition for a spatial LineString type.
  627. *
  628. * @param \Illuminate\Support\Fluent $column
  629. * @return string
  630. */
  631. public function typeLineString(Fluent $column)
  632. {
  633. return 'linestring';
  634. }
  635. /**
  636. * Create the column definition for a spatial Polygon type.
  637. *
  638. * @param \Illuminate\Support\Fluent $column
  639. * @return string
  640. */
  641. public function typePolygon(Fluent $column)
  642. {
  643. return 'polygon';
  644. }
  645. /**
  646. * Create the column definition for a spatial GeometryCollection type.
  647. *
  648. * @param \Illuminate\Support\Fluent $column
  649. * @return string
  650. */
  651. public function typeGeometryCollection(Fluent $column)
  652. {
  653. return 'geometrycollection';
  654. }
  655. /**
  656. * Create the column definition for a spatial MultiPoint type.
  657. *
  658. * @param \Illuminate\Support\Fluent $column
  659. * @return string
  660. */
  661. public function typeMultiPoint(Fluent $column)
  662. {
  663. return 'multipoint';
  664. }
  665. /**
  666. * Create the column definition for a spatial MultiLineString type.
  667. *
  668. * @param \Illuminate\Support\Fluent $column
  669. * @return string
  670. */
  671. public function typeMultiLineString(Fluent $column)
  672. {
  673. return 'multilinestring';
  674. }
  675. /**
  676. * Create the column definition for a spatial MultiPolygon type.
  677. *
  678. * @param \Illuminate\Support\Fluent $column
  679. * @return string
  680. */
  681. public function typeMultiPolygon(Fluent $column)
  682. {
  683. return 'multipolygon';
  684. }
  685. /**
  686. * Get the SQL for a nullable column modifier.
  687. *
  688. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  689. * @param \Illuminate\Support\Fluent $column
  690. * @return string|null
  691. */
  692. protected function modifyNullable(Blueprint $blueprint, Fluent $column)
  693. {
  694. return $column->nullable ? ' null' : ' not null';
  695. }
  696. /**
  697. * Get the SQL for a default column modifier.
  698. *
  699. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  700. * @param \Illuminate\Support\Fluent $column
  701. * @return string|null
  702. */
  703. protected function modifyDefault(Blueprint $blueprint, Fluent $column)
  704. {
  705. if (! is_null($column->default)) {
  706. return ' default '.$this->getDefaultValue($column->default);
  707. }
  708. }
  709. /**
  710. * Get the SQL for an auto-increment column modifier.
  711. *
  712. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  713. * @param \Illuminate\Support\Fluent $column
  714. * @return string|null
  715. */
  716. protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
  717. {
  718. if (in_array($column->type, $this->serials) && $column->autoIncrement) {
  719. return ' primary key autoincrement';
  720. }
  721. }
  722. }