SQLiteGrammar.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. <?php
  2. namespace Illuminate\Database\Schema\Grammars;
  3. use Illuminate\Database\Connection;
  4. use Illuminate\Database\Query\Expression;
  5. use Illuminate\Database\Schema\Blueprint;
  6. use Illuminate\Database\Schema\ColumnDefinition;
  7. use Illuminate\Database\Schema\ForeignKeyDefinition;
  8. use Illuminate\Database\Schema\IndexDefinition;
  9. use Illuminate\Support\Arr;
  10. use Illuminate\Support\Fluent;
  11. use RuntimeException;
  12. class SQLiteGrammar extends Grammar
  13. {
  14. /**
  15. * The possible column modifiers.
  16. *
  17. * @var string[]
  18. */
  19. protected $modifiers = ['Increment', 'Nullable', 'Default', 'Collate', 'VirtualAs', 'StoredAs'];
  20. /**
  21. * The columns available as serials.
  22. *
  23. * @var string[]
  24. */
  25. protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger'];
  26. /**
  27. * Compile the query to determine the SQL text that describes the given object.
  28. *
  29. * @param string $name
  30. * @param string $type
  31. * @return string
  32. */
  33. public function compileSqlCreateStatement($name, $type = 'table')
  34. {
  35. return sprintf('select "sql" from sqlite_master where type = %s and name = %s',
  36. $this->quoteString($type),
  37. $this->quoteString(str_replace('.', '__', $name))
  38. );
  39. }
  40. /**
  41. * Compile the query to determine if the dbstat table is available.
  42. *
  43. * @return string
  44. */
  45. public function compileDbstatExists()
  46. {
  47. return "select exists (select 1 from pragma_compile_options where compile_options = 'ENABLE_DBSTAT_VTAB') as enabled";
  48. }
  49. /**
  50. * Compile the query to determine the tables.
  51. *
  52. * @param bool $withSize
  53. * @return string
  54. */
  55. public function compileTables($withSize = false)
  56. {
  57. return $withSize
  58. ? 'select m.tbl_name as name, sum(s.pgsize) as size from sqlite_master as m '
  59. .'join dbstat as s on s.name = m.name '
  60. ."where m.type in ('table', 'index') and m.tbl_name not like 'sqlite_%' "
  61. .'group by m.tbl_name '
  62. .'order by m.tbl_name'
  63. : "select name from sqlite_master where type = 'table' and name not like 'sqlite_%' order by name";
  64. }
  65. /**
  66. * Compile the query to determine the views.
  67. *
  68. * @return string
  69. */
  70. public function compileViews()
  71. {
  72. return "select name, sql as definition from sqlite_master where type = 'view' order by name";
  73. }
  74. /**
  75. * Compile the query to determine the columns.
  76. *
  77. * @param string $table
  78. * @return string
  79. */
  80. public function compileColumns($table)
  81. {
  82. return sprintf(
  83. 'select name, type, not "notnull" as "nullable", dflt_value as "default", pk as "primary", hidden as "extra" '
  84. .'from pragma_table_xinfo(%s) order by cid asc',
  85. $this->quoteString(str_replace('.', '__', $table))
  86. );
  87. }
  88. /**
  89. * Compile the query to determine the indexes.
  90. *
  91. * @param string $table
  92. * @return string
  93. */
  94. public function compileIndexes($table)
  95. {
  96. return sprintf(
  97. 'select \'primary\' as name, group_concat(col) as columns, 1 as "unique", 1 as "primary" '
  98. .'from (select name as col from pragma_table_info(%s) where pk > 0 order by pk, cid) group by name '
  99. .'union select name, group_concat(col) as columns, "unique", origin = \'pk\' as "primary" '
  100. .'from (select il.*, ii.name as col from pragma_index_list(%s) il, pragma_index_info(il.name) ii order by il.seq, ii.seqno) '
  101. .'group by name, "unique", "primary"',
  102. $table = $this->quoteString(str_replace('.', '__', $table)),
  103. $table
  104. );
  105. }
  106. /**
  107. * Compile the query to determine the foreign keys.
  108. *
  109. * @param string $table
  110. * @return string
  111. */
  112. public function compileForeignKeys($table)
  113. {
  114. return sprintf(
  115. 'select group_concat("from") as columns, "table" as foreign_table, '
  116. .'group_concat("to") as foreign_columns, on_update, on_delete '
  117. .'from (select * from pragma_foreign_key_list(%s) order by id desc, seq) '
  118. .'group by id, "table", on_update, on_delete',
  119. $this->quoteString(str_replace('.', '__', $table))
  120. );
  121. }
  122. /**
  123. * Compile a create table command.
  124. *
  125. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  126. * @param \Illuminate\Support\Fluent $command
  127. * @return string
  128. */
  129. public function compileCreate(Blueprint $blueprint, Fluent $command)
  130. {
  131. return sprintf('%s table %s (%s%s%s)',
  132. $blueprint->temporary ? 'create temporary' : 'create',
  133. $this->wrapTable($blueprint),
  134. implode(', ', $this->getColumns($blueprint)),
  135. $this->addForeignKeys($this->getCommandsByName($blueprint, 'foreign')),
  136. $this->addPrimaryKeys($this->getCommandByName($blueprint, 'primary'))
  137. );
  138. }
  139. /**
  140. * Get the foreign key syntax for a table creation statement.
  141. *
  142. * @param \Illuminate\Database\Schema\ForeignKeyDefinition[] $foreignKeys
  143. * @return string|null
  144. */
  145. protected function addForeignKeys($foreignKeys)
  146. {
  147. return collect($foreignKeys)->reduce(function ($sql, $foreign) {
  148. // Once we have all the foreign key commands for the table creation statement
  149. // we'll loop through each of them and add them to the create table SQL we
  150. // are building, since SQLite needs foreign keys on the tables creation.
  151. return $sql.$this->getForeignKey($foreign);
  152. }, '');
  153. }
  154. /**
  155. * Get the SQL for the foreign key.
  156. *
  157. * @param \Illuminate\Support\Fluent $foreign
  158. * @return string
  159. */
  160. protected function getForeignKey($foreign)
  161. {
  162. // We need to columnize the columns that the foreign key is being defined for
  163. // so that it is a properly formatted list. Once we have done this, we can
  164. // return the foreign key SQL declaration to the calling method for use.
  165. $sql = sprintf(', foreign key(%s) references %s(%s)',
  166. $this->columnize($foreign->columns),
  167. $this->wrapTable($foreign->on),
  168. $this->columnize((array) $foreign->references)
  169. );
  170. if (! is_null($foreign->onDelete)) {
  171. $sql .= " on delete {$foreign->onDelete}";
  172. }
  173. // If this foreign key specifies the action to be taken on update we will add
  174. // that to the statement here. We'll append it to this SQL and then return
  175. // this SQL so we can keep adding any other foreign constraints to this.
  176. if (! is_null($foreign->onUpdate)) {
  177. $sql .= " on update {$foreign->onUpdate}";
  178. }
  179. return $sql;
  180. }
  181. /**
  182. * Get the primary key syntax for a table creation statement.
  183. *
  184. * @param \Illuminate\Support\Fluent|null $primary
  185. * @return string|null
  186. */
  187. protected function addPrimaryKeys($primary)
  188. {
  189. if (! is_null($primary)) {
  190. return ", primary key ({$this->columnize($primary->columns)})";
  191. }
  192. }
  193. /**
  194. * Compile alter table commands for adding columns.
  195. *
  196. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  197. * @param \Illuminate\Support\Fluent $command
  198. * @return array
  199. */
  200. public function compileAdd(Blueprint $blueprint, Fluent $command)
  201. {
  202. $columns = $this->prefixArray('add column', $this->getColumns($blueprint));
  203. return collect($columns)->map(function ($column) use ($blueprint) {
  204. return 'alter table '.$this->wrapTable($blueprint).' '.$column;
  205. })->all();
  206. }
  207. /**
  208. * Compile a change column command into a series of SQL statements.
  209. *
  210. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  211. * @param \Illuminate\Support\Fluent $command
  212. * @param \Illuminate\Database\Connection $connection
  213. * @return array|string
  214. *
  215. * @throws \RuntimeException
  216. */
  217. public function compileChange(Blueprint $blueprint, Fluent $command, Connection $connection)
  218. {
  219. $schema = $connection->getSchemaBuilder();
  220. $table = $blueprint->getTable();
  221. $changedColumns = collect($blueprint->getChangedColumns());
  222. $columnNames = [];
  223. $autoIncrementColumn = null;
  224. $columns = collect($schema->getColumns($table))
  225. ->map(function ($column) use ($blueprint, $changedColumns, &$columnNames, &$autoIncrementColumn) {
  226. $column = $changedColumns->first(fn ($col) => $col->name === $column['name'], $column);
  227. if ($column instanceof Fluent) {
  228. $name = $this->wrap($column);
  229. $autoIncrementColumn = $column->autoIncrement ? $column->name : $autoIncrementColumn;
  230. if (is_null($column->virtualAs) && is_null($column->virtualAsJson) &&
  231. is_null($column->storedAs) && is_null($column->storedAsJson)) {
  232. $columnNames[] = $name;
  233. }
  234. return $this->addModifiers($name.' '.$this->getType($column), $blueprint, $column);
  235. } else {
  236. $name = $this->wrap($column['name']);
  237. $autoIncrementColumn = $column['auto_increment'] ? $column['name'] : $autoIncrementColumn;
  238. $isGenerated = ! is_null($column['generation']);
  239. if (! $isGenerated) {
  240. $columnNames[] = $name;
  241. }
  242. return $this->addModifiers($name.' '.$column['type'], $blueprint,
  243. new ColumnDefinition([
  244. 'change' => true,
  245. 'type' => $column['type_name'],
  246. 'nullable' => $column['nullable'],
  247. 'default' => is_null($column['default']) ? null : new Expression($column['default']),
  248. 'autoIncrement' => $column['auto_increment'],
  249. 'collation' => $column['collation'],
  250. 'comment' => $column['comment'],
  251. 'virtualAs' => $isGenerated && $column['generation']['type'] === 'virtual'
  252. ? $column['generation']['expression'] : null,
  253. 'storedAs' => $isGenerated && $column['generation']['type'] === 'stored'
  254. ? $column['generation']['expression'] : null,
  255. ])
  256. );
  257. }
  258. })->all();
  259. $foreignKeys = collect($schema->getForeignKeys($table))->map(fn ($foreignKey) => new ForeignKeyDefinition([
  260. 'columns' => $foreignKey['columns'],
  261. 'on' => $foreignKey['foreign_table'],
  262. 'references' => $foreignKey['foreign_columns'],
  263. 'onUpdate' => $foreignKey['on_update'],
  264. 'onDelete' => $foreignKey['on_delete'],
  265. ]))->all();
  266. [$primary, $indexes] = collect($schema->getIndexes($table))->map(fn ($index) => new IndexDefinition([
  267. 'name' => match (true) {
  268. $index['primary'] => 'primary',
  269. $index['unique'] => 'unique',
  270. default => 'index',
  271. },
  272. 'index' => $index['name'],
  273. 'columns' => $index['columns'],
  274. ]))->partition(fn ($index) => $index->name === 'primary');
  275. $indexes = collect($indexes)->reject(fn ($index) => str_starts_with('sqlite_', $index->index))->map(
  276. fn ($index) => $this->{'compile'.ucfirst($index->name)}($blueprint, $index)
  277. )->all();
  278. $tempTable = $this->wrap('__temp__'.$blueprint->getPrefix().$table);
  279. $table = $this->wrapTable($blueprint);
  280. $columnNames = implode(', ', $columnNames);
  281. $foreignKeyConstraintsEnabled = $connection->scalar('pragma foreign_keys');
  282. return array_filter(array_merge([
  283. $foreignKeyConstraintsEnabled ? $this->compileDisableForeignKeyConstraints() : null,
  284. sprintf('create table %s (%s%s%s)',
  285. $tempTable,
  286. implode(', ', $columns),
  287. $this->addForeignKeys($foreignKeys),
  288. $autoIncrementColumn ? '' : $this->addPrimaryKeys($primary->first())
  289. ),
  290. sprintf('insert into %s (%s) select %s from %s', $tempTable, $columnNames, $columnNames, $table),
  291. sprintf('drop table %s', $table),
  292. sprintf('alter table %s rename to %s', $tempTable, $table),
  293. ], $indexes, [$foreignKeyConstraintsEnabled ? $this->compileEnableForeignKeyConstraints() : null]));
  294. }
  295. /**
  296. * Compile a unique key command.
  297. *
  298. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  299. * @param \Illuminate\Support\Fluent $command
  300. * @return string
  301. */
  302. public function compileUnique(Blueprint $blueprint, Fluent $command)
  303. {
  304. return sprintf('create unique index %s on %s (%s)',
  305. $this->wrap($command->index),
  306. $this->wrapTable($blueprint),
  307. $this->columnize($command->columns)
  308. );
  309. }
  310. /**
  311. * Compile a plain index key command.
  312. *
  313. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  314. * @param \Illuminate\Support\Fluent $command
  315. * @return string
  316. */
  317. public function compileIndex(Blueprint $blueprint, Fluent $command)
  318. {
  319. return sprintf('create index %s on %s (%s)',
  320. $this->wrap($command->index),
  321. $this->wrapTable($blueprint),
  322. $this->columnize($command->columns)
  323. );
  324. }
  325. /**
  326. * Compile a spatial index key command.
  327. *
  328. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  329. * @param \Illuminate\Support\Fluent $command
  330. * @return void
  331. *
  332. * @throws \RuntimeException
  333. */
  334. public function compileSpatialIndex(Blueprint $blueprint, Fluent $command)
  335. {
  336. throw new RuntimeException('The database driver in use does not support spatial indexes.');
  337. }
  338. /**
  339. * Compile a foreign key command.
  340. *
  341. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  342. * @param \Illuminate\Support\Fluent $command
  343. * @return string|null
  344. */
  345. public function compileForeign(Blueprint $blueprint, Fluent $command)
  346. {
  347. // Handled on table creation...
  348. }
  349. /**
  350. * Compile a drop table command.
  351. *
  352. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  353. * @param \Illuminate\Support\Fluent $command
  354. * @return string
  355. */
  356. public function compileDrop(Blueprint $blueprint, Fluent $command)
  357. {
  358. return 'drop table '.$this->wrapTable($blueprint);
  359. }
  360. /**
  361. * Compile a drop table (if exists) command.
  362. *
  363. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  364. * @param \Illuminate\Support\Fluent $command
  365. * @return string
  366. */
  367. public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
  368. {
  369. return 'drop table if exists '.$this->wrapTable($blueprint);
  370. }
  371. /**
  372. * Compile the SQL needed to drop all tables.
  373. *
  374. * @return string
  375. */
  376. public function compileDropAllTables()
  377. {
  378. return "delete from sqlite_master where type in ('table', 'index', 'trigger')";
  379. }
  380. /**
  381. * Compile the SQL needed to drop all views.
  382. *
  383. * @return string
  384. */
  385. public function compileDropAllViews()
  386. {
  387. return "delete from sqlite_master where type in ('view')";
  388. }
  389. /**
  390. * Compile the SQL needed to rebuild the database.
  391. *
  392. * @return string
  393. */
  394. public function compileRebuild()
  395. {
  396. return 'vacuum';
  397. }
  398. /**
  399. * Compile a drop column command.
  400. *
  401. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  402. * @param \Illuminate\Support\Fluent $command
  403. * @param \Illuminate\Database\Connection $connection
  404. * @return array
  405. */
  406. public function compileDropColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
  407. {
  408. $table = $this->wrapTable($blueprint);
  409. $columns = $this->prefixArray('drop column', $this->wrapArray($command->columns));
  410. return collect($columns)->map(fn ($column) => 'alter table '.$table.' '.$column)->all();
  411. }
  412. /**
  413. * Compile a drop unique key command.
  414. *
  415. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  416. * @param \Illuminate\Support\Fluent $command
  417. * @return string
  418. */
  419. public function compileDropUnique(Blueprint $blueprint, Fluent $command)
  420. {
  421. $index = $this->wrap($command->index);
  422. return "drop index {$index}";
  423. }
  424. /**
  425. * Compile a drop index command.
  426. *
  427. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  428. * @param \Illuminate\Support\Fluent $command
  429. * @return string
  430. */
  431. public function compileDropIndex(Blueprint $blueprint, Fluent $command)
  432. {
  433. $index = $this->wrap($command->index);
  434. return "drop index {$index}";
  435. }
  436. /**
  437. * Compile a drop spatial index command.
  438. *
  439. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  440. * @param \Illuminate\Support\Fluent $command
  441. * @return void
  442. *
  443. * @throws \RuntimeException
  444. */
  445. public function compileDropSpatialIndex(Blueprint $blueprint, Fluent $command)
  446. {
  447. throw new RuntimeException('The database driver in use does not support spatial indexes.');
  448. }
  449. /**
  450. * Compile a rename table command.
  451. *
  452. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  453. * @param \Illuminate\Support\Fluent $command
  454. * @return string
  455. */
  456. public function compileRename(Blueprint $blueprint, Fluent $command)
  457. {
  458. $from = $this->wrapTable($blueprint);
  459. return "alter table {$from} rename to ".$this->wrapTable($command->to);
  460. }
  461. /**
  462. * Compile a rename index command.
  463. *
  464. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  465. * @param \Illuminate\Support\Fluent $command
  466. * @param \Illuminate\Database\Connection $connection
  467. * @return array
  468. *
  469. * @throws \RuntimeException
  470. */
  471. public function compileRenameIndex(Blueprint $blueprint, Fluent $command, Connection $connection)
  472. {
  473. $indexes = $connection->getSchemaBuilder()->getIndexes($blueprint->getTable());
  474. $index = Arr::first($indexes, fn ($index) => $index['name'] === $command->from);
  475. if (! $index) {
  476. throw new RuntimeException("Index [{$command->from}] does not exist.");
  477. }
  478. if ($index['primary']) {
  479. throw new RuntimeException('SQLite does not support altering primary keys.');
  480. }
  481. if ($index['unique']) {
  482. return [
  483. $this->compileDropUnique($blueprint, new IndexDefinition(['index' => $index['name']])),
  484. $this->compileUnique($blueprint,
  485. new IndexDefinition(['index' => $command->to, 'columns' => $index['columns']])
  486. ),
  487. ];
  488. }
  489. return [
  490. $this->compileDropIndex($blueprint, new IndexDefinition(['index' => $index['name']])),
  491. $this->compileIndex($blueprint,
  492. new IndexDefinition(['index' => $command->to, 'columns' => $index['columns']])
  493. ),
  494. ];
  495. }
  496. /**
  497. * Compile the command to enable foreign key constraints.
  498. *
  499. * @return string
  500. */
  501. public function compileEnableForeignKeyConstraints()
  502. {
  503. return 'PRAGMA foreign_keys = ON;';
  504. }
  505. /**
  506. * Compile the command to disable foreign key constraints.
  507. *
  508. * @return string
  509. */
  510. public function compileDisableForeignKeyConstraints()
  511. {
  512. return 'PRAGMA foreign_keys = OFF;';
  513. }
  514. /**
  515. * Compile the SQL needed to enable a writable schema.
  516. *
  517. * @return string
  518. */
  519. public function compileEnableWriteableSchema()
  520. {
  521. return 'PRAGMA writable_schema = 1;';
  522. }
  523. /**
  524. * Compile the SQL needed to disable a writable schema.
  525. *
  526. * @return string
  527. */
  528. public function compileDisableWriteableSchema()
  529. {
  530. return 'PRAGMA writable_schema = 0;';
  531. }
  532. /**
  533. * Create the column definition for a char type.
  534. *
  535. * @param \Illuminate\Support\Fluent $column
  536. * @return string
  537. */
  538. protected function typeChar(Fluent $column)
  539. {
  540. return 'varchar';
  541. }
  542. /**
  543. * Create the column definition for a string type.
  544. *
  545. * @param \Illuminate\Support\Fluent $column
  546. * @return string
  547. */
  548. protected function typeString(Fluent $column)
  549. {
  550. return 'varchar';
  551. }
  552. /**
  553. * Create the column definition for a tiny text type.
  554. *
  555. * @param \Illuminate\Support\Fluent $column
  556. * @return string
  557. */
  558. protected function typeTinyText(Fluent $column)
  559. {
  560. return 'text';
  561. }
  562. /**
  563. * Create the column definition for a text type.
  564. *
  565. * @param \Illuminate\Support\Fluent $column
  566. * @return string
  567. */
  568. protected function typeText(Fluent $column)
  569. {
  570. return 'text';
  571. }
  572. /**
  573. * Create the column definition for a medium text type.
  574. *
  575. * @param \Illuminate\Support\Fluent $column
  576. * @return string
  577. */
  578. protected function typeMediumText(Fluent $column)
  579. {
  580. return 'text';
  581. }
  582. /**
  583. * Create the column definition for a long text type.
  584. *
  585. * @param \Illuminate\Support\Fluent $column
  586. * @return string
  587. */
  588. protected function typeLongText(Fluent $column)
  589. {
  590. return 'text';
  591. }
  592. /**
  593. * Create the column definition for an integer type.
  594. *
  595. * @param \Illuminate\Support\Fluent $column
  596. * @return string
  597. */
  598. protected function typeInteger(Fluent $column)
  599. {
  600. return 'integer';
  601. }
  602. /**
  603. * Create the column definition for a big integer type.
  604. *
  605. * @param \Illuminate\Support\Fluent $column
  606. * @return string
  607. */
  608. protected function typeBigInteger(Fluent $column)
  609. {
  610. return 'integer';
  611. }
  612. /**
  613. * Create the column definition for a medium integer type.
  614. *
  615. * @param \Illuminate\Support\Fluent $column
  616. * @return string
  617. */
  618. protected function typeMediumInteger(Fluent $column)
  619. {
  620. return 'integer';
  621. }
  622. /**
  623. * Create the column definition for a tiny integer type.
  624. *
  625. * @param \Illuminate\Support\Fluent $column
  626. * @return string
  627. */
  628. protected function typeTinyInteger(Fluent $column)
  629. {
  630. return 'integer';
  631. }
  632. /**
  633. * Create the column definition for a small integer type.
  634. *
  635. * @param \Illuminate\Support\Fluent $column
  636. * @return string
  637. */
  638. protected function typeSmallInteger(Fluent $column)
  639. {
  640. return 'integer';
  641. }
  642. /**
  643. * Create the column definition for a float type.
  644. *
  645. * @param \Illuminate\Support\Fluent $column
  646. * @return string
  647. */
  648. protected function typeFloat(Fluent $column)
  649. {
  650. return 'float';
  651. }
  652. /**
  653. * Create the column definition for a double type.
  654. *
  655. * @param \Illuminate\Support\Fluent $column
  656. * @return string
  657. */
  658. protected function typeDouble(Fluent $column)
  659. {
  660. return 'double';
  661. }
  662. /**
  663. * Create the column definition for a decimal type.
  664. *
  665. * @param \Illuminate\Support\Fluent $column
  666. * @return string
  667. */
  668. protected function typeDecimal(Fluent $column)
  669. {
  670. return 'numeric';
  671. }
  672. /**
  673. * Create the column definition for a boolean type.
  674. *
  675. * @param \Illuminate\Support\Fluent $column
  676. * @return string
  677. */
  678. protected function typeBoolean(Fluent $column)
  679. {
  680. return 'tinyint(1)';
  681. }
  682. /**
  683. * Create the column definition for an enumeration type.
  684. *
  685. * @param \Illuminate\Support\Fluent $column
  686. * @return string
  687. */
  688. protected function typeEnum(Fluent $column)
  689. {
  690. return sprintf(
  691. 'varchar check ("%s" in (%s))',
  692. $column->name,
  693. $this->quoteString($column->allowed)
  694. );
  695. }
  696. /**
  697. * Create the column definition for a json type.
  698. *
  699. * @param \Illuminate\Support\Fluent $column
  700. * @return string
  701. */
  702. protected function typeJson(Fluent $column)
  703. {
  704. return 'text';
  705. }
  706. /**
  707. * Create the column definition for a jsonb type.
  708. *
  709. * @param \Illuminate\Support\Fluent $column
  710. * @return string
  711. */
  712. protected function typeJsonb(Fluent $column)
  713. {
  714. return 'text';
  715. }
  716. /**
  717. * Create the column definition for a date type.
  718. *
  719. * @param \Illuminate\Support\Fluent $column
  720. * @return string
  721. */
  722. protected function typeDate(Fluent $column)
  723. {
  724. return 'date';
  725. }
  726. /**
  727. * Create the column definition for a date-time type.
  728. *
  729. * @param \Illuminate\Support\Fluent $column
  730. * @return string
  731. */
  732. protected function typeDateTime(Fluent $column)
  733. {
  734. return $this->typeTimestamp($column);
  735. }
  736. /**
  737. * Create the column definition for a date-time (with time zone) type.
  738. *
  739. * Note: "SQLite does not have a storage class set aside for storing dates and/or times."
  740. *
  741. * @link https://www.sqlite.org/datatype3.html
  742. *
  743. * @param \Illuminate\Support\Fluent $column
  744. * @return string
  745. */
  746. protected function typeDateTimeTz(Fluent $column)
  747. {
  748. return $this->typeDateTime($column);
  749. }
  750. /**
  751. * Create the column definition for a time type.
  752. *
  753. * @param \Illuminate\Support\Fluent $column
  754. * @return string
  755. */
  756. protected function typeTime(Fluent $column)
  757. {
  758. return 'time';
  759. }
  760. /**
  761. * Create the column definition for a time (with time zone) type.
  762. *
  763. * @param \Illuminate\Support\Fluent $column
  764. * @return string
  765. */
  766. protected function typeTimeTz(Fluent $column)
  767. {
  768. return $this->typeTime($column);
  769. }
  770. /**
  771. * Create the column definition for a timestamp type.
  772. *
  773. * @param \Illuminate\Support\Fluent $column
  774. * @return string
  775. */
  776. protected function typeTimestamp(Fluent $column)
  777. {
  778. if ($column->useCurrent) {
  779. $column->default(new Expression('CURRENT_TIMESTAMP'));
  780. }
  781. return 'datetime';
  782. }
  783. /**
  784. * Create the column definition for a timestamp (with time zone) type.
  785. *
  786. * @param \Illuminate\Support\Fluent $column
  787. * @return string
  788. */
  789. protected function typeTimestampTz(Fluent $column)
  790. {
  791. return $this->typeTimestamp($column);
  792. }
  793. /**
  794. * Create the column definition for a year type.
  795. *
  796. * @param \Illuminate\Support\Fluent $column
  797. * @return string
  798. */
  799. protected function typeYear(Fluent $column)
  800. {
  801. return $this->typeInteger($column);
  802. }
  803. /**
  804. * Create the column definition for a binary type.
  805. *
  806. * @param \Illuminate\Support\Fluent $column
  807. * @return string
  808. */
  809. protected function typeBinary(Fluent $column)
  810. {
  811. return 'blob';
  812. }
  813. /**
  814. * Create the column definition for a uuid type.
  815. *
  816. * @param \Illuminate\Support\Fluent $column
  817. * @return string
  818. */
  819. protected function typeUuid(Fluent $column)
  820. {
  821. return 'varchar';
  822. }
  823. /**
  824. * Create the column definition for an IP address type.
  825. *
  826. * @param \Illuminate\Support\Fluent $column
  827. * @return string
  828. */
  829. protected function typeIpAddress(Fluent $column)
  830. {
  831. return 'varchar';
  832. }
  833. /**
  834. * Create the column definition for a MAC address type.
  835. *
  836. * @param \Illuminate\Support\Fluent $column
  837. * @return string
  838. */
  839. protected function typeMacAddress(Fluent $column)
  840. {
  841. return 'varchar';
  842. }
  843. /**
  844. * Create the column definition for a spatial Geometry type.
  845. *
  846. * @param \Illuminate\Support\Fluent $column
  847. * @return string
  848. */
  849. protected function typeGeometry(Fluent $column)
  850. {
  851. return 'geometry';
  852. }
  853. /**
  854. * Create the column definition for a spatial Geography type.
  855. *
  856. * @param \Illuminate\Support\Fluent $column
  857. * @return string
  858. */
  859. protected function typeGeography(Fluent $column)
  860. {
  861. return $this->typeGeometry($column);
  862. }
  863. /**
  864. * Create the column definition for a generated, computed column type.
  865. *
  866. * @param \Illuminate\Support\Fluent $column
  867. * @return void
  868. *
  869. * @throws \RuntimeException
  870. */
  871. protected function typeComputed(Fluent $column)
  872. {
  873. throw new RuntimeException('This database driver requires a type, see the virtualAs / storedAs modifiers.');
  874. }
  875. /**
  876. * Get the SQL for a generated virtual column modifier.
  877. *
  878. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  879. * @param \Illuminate\Support\Fluent $column
  880. * @return string|null
  881. */
  882. protected function modifyVirtualAs(Blueprint $blueprint, Fluent $column)
  883. {
  884. if (! is_null($virtualAs = $column->virtualAsJson)) {
  885. if ($this->isJsonSelector($virtualAs)) {
  886. $virtualAs = $this->wrapJsonSelector($virtualAs);
  887. }
  888. return " as ({$virtualAs})";
  889. }
  890. if (! is_null($virtualAs = $column->virtualAs)) {
  891. return " as ({$this->getValue($virtualAs)})";
  892. }
  893. }
  894. /**
  895. * Get the SQL for a generated stored column modifier.
  896. *
  897. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  898. * @param \Illuminate\Support\Fluent $column
  899. * @return string|null
  900. */
  901. protected function modifyStoredAs(Blueprint $blueprint, Fluent $column)
  902. {
  903. if (! is_null($storedAs = $column->storedAsJson)) {
  904. if ($this->isJsonSelector($storedAs)) {
  905. $storedAs = $this->wrapJsonSelector($storedAs);
  906. }
  907. return " as ({$storedAs}) stored";
  908. }
  909. if (! is_null($storedAs = $column->storedAs)) {
  910. return " as ({$this->getValue($column->storedAs)}) stored";
  911. }
  912. }
  913. /**
  914. * Get the SQL for a nullable column modifier.
  915. *
  916. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  917. * @param \Illuminate\Support\Fluent $column
  918. * @return string|null
  919. */
  920. protected function modifyNullable(Blueprint $blueprint, Fluent $column)
  921. {
  922. if (is_null($column->virtualAs) &&
  923. is_null($column->virtualAsJson) &&
  924. is_null($column->storedAs) &&
  925. is_null($column->storedAsJson)) {
  926. return $column->nullable ? '' : ' not null';
  927. }
  928. if ($column->nullable === false) {
  929. return ' not null';
  930. }
  931. }
  932. /**
  933. * Get the SQL for a default column modifier.
  934. *
  935. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  936. * @param \Illuminate\Support\Fluent $column
  937. * @return string|null
  938. */
  939. protected function modifyDefault(Blueprint $blueprint, Fluent $column)
  940. {
  941. if (! is_null($column->default) && is_null($column->virtualAs) && is_null($column->virtualAsJson) && is_null($column->storedAs)) {
  942. return ' default '.$this->getDefaultValue($column->default);
  943. }
  944. }
  945. /**
  946. * Get the SQL for an auto-increment column modifier.
  947. *
  948. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  949. * @param \Illuminate\Support\Fluent $column
  950. * @return string|null
  951. */
  952. protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
  953. {
  954. if (in_array($column->type, $this->serials) && $column->autoIncrement) {
  955. return ' primary key autoincrement';
  956. }
  957. }
  958. /**
  959. * Get the SQL for a collation column modifier.
  960. *
  961. * @param \Illuminate\Database\Schema\Blueprint $blueprint
  962. * @param \Illuminate\Support\Fluent $column
  963. * @return string|null
  964. */
  965. protected function modifyCollate(Blueprint $blueprint, Fluent $column)
  966. {
  967. if (! is_null($column->collation)) {
  968. return " collate '{$column->collation}'";
  969. }
  970. }
  971. /**
  972. * Wrap the given JSON selector.
  973. *
  974. * @param string $value
  975. * @return string
  976. */
  977. protected function wrapJsonSelector($value)
  978. {
  979. [$field, $path] = $this->wrapJsonFieldAndPath($value);
  980. return 'json_extract('.$field.$path.')';
  981. }
  982. }