├── .gitignore ├── README.md ├── composer.json └── src └── TransformMigration.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel SQLite Migrations 2 | A trait to translate Laravel migrations into SQLite safe migrations. 3 | This avoids the `Cannot add a NOT NULL column with default value NULL` issue that you receive when trying to add a non-nullable column to 4 | an existing table in a migration by initially adding the column as nullable and then modifying the column in a separate migration. 5 | It also maps Laravel datatypes that aren't supported in SQLite to avoid [this](https://github.com/laravel/framework/issues/8840). 6 | 7 | ## Installation 8 | `composer require jjclane/laravel-sqlite-migrations --dev` 9 | 10 | ## How to use 11 | ````php 12 | table('table', function (Blueprint $table) { 30 | // Normal migrations 31 | $table->decimal('my_col', 10, 1)->unsigned()->after('my_other_col'); 32 | }); 33 | 34 | // or if you prefer to be more explicit 35 | $this->transformMigration('table', function (Blueprint $table) { 36 | // Normal migrations 37 | $table->decimal('my_col', 10, 1)->unsigned()->after('my_other_col'); 38 | }); 39 | } 40 | } 41 | ```` 42 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jjclane/laravel-sqlite-migrations", 3 | "description": "A trait to translate Laravel migrations into SQLite safe migrations.", 4 | "type": "laravel-package", 5 | "require": { 6 | "illuminate/database": "^7.0||^8.0||^9.0||^10.0" 7 | }, 8 | "license": "MIT", 9 | "authors": [ 10 | { 11 | "name": "Jordan Lane", 12 | "email": "contact@jordanlane.me" 13 | } 14 | ], 15 | "autoload": { 16 | "psr-4": { 17 | "JJCLane\\SQLiteMigration\\": "src/" 18 | } 19 | }, 20 | "minimum-stability": "stable" 21 | } 22 | -------------------------------------------------------------------------------- /src/TransformMigration.php: -------------------------------------------------------------------------------- 1 | 'smallInteger', 12 | 'tinyIncrements' => 'smallIncrements', 13 | 'mediumInteger' => 'integer', 14 | 'mediumIncrements' => 'increments', 15 | 'char' => 'string', 16 | 'double' => 'float', 17 | //'enum' => 'string', ? 18 | 'geomety' => 'string', 19 | 'geometryCollection' => 'string', 20 | 'ipAddress' => 'string', 21 | 'jsonb' => 'json', 22 | 'lineString' => 'string', 23 | 'macAddress' => 'string', 24 | 'multiLineString' => 'string', 25 | 'multiPoint' => 'string', 26 | 'multiPolygon' => 'string', 27 | 'point' => 'string', 28 | 'polygon' => 'string', 29 | 'timestamp' => 'string', 30 | 'timestampTz' => 'string', 31 | 'uuid' => 'string', 32 | 'year' => 'integer' 33 | ]; 34 | 35 | private function table($table, $callback) 36 | { 37 | $this->transformMigration($table, $callback); 38 | } 39 | 40 | private function transformMigration($table, $callback) 41 | { 42 | $blueprint = new Blueprint($table); 43 | call_user_func($callback, $blueprint); 44 | $usingSqlLite = Schema::connection($this->getConnection()) 45 | ->getConnection()->getDriverName() === 'sqlite'; 46 | $nonNullableCols = []; 47 | $userInput = []; 48 | 49 | foreach ($blueprint->getColumns() as &$col) { 50 | $obj = $col->getAttributes(); 51 | 52 | if ($usingSqlLite && !$col->nullable) { 53 | $obj['nullable'] = true; 54 | $obj['type'] = $this->mapType($obj['type']); 55 | 56 | if (!isset($obj['default'])) { 57 | switch ($obj['type']) { 58 | case 'string': 59 | $obj['default'] = ''; 60 | break; 61 | default: 62 | $obj['default'] = null; 63 | break; 64 | } 65 | } 66 | $userInput[] = $obj; 67 | 68 | $obj['nullable'] = false; 69 | $obj['change'] = true; 70 | $nonNullableCols[] = $obj; 71 | continue; 72 | } 73 | 74 | $userInput[] = $obj; 75 | } 76 | // For some reason running a dropColumn command overwrites addColumn 77 | // so we need to run a seperate blueprint. 78 | $commands = $blueprint->getCommands(); 79 | if ($commands) { 80 | $this->runMigration($table, [], $commands); 81 | } 82 | $this->runMigration($table, $userInput); 83 | if ($usingSqlLite) { 84 | $this->runMigration($table, $nonNullableCols); 85 | } 86 | } 87 | 88 | private function mapType($type) 89 | { 90 | if (array_key_exists($type, $this->types)) { 91 | return $this->types[$type]; 92 | } 93 | return $type; 94 | } 95 | 96 | private function runMigration($tableName, $input = [], $commands = []) 97 | { 98 | Schema::table($tableName, function (Blueprint $table) use ($tableName, $input, $commands) { 99 | foreach ($input as $col) { 100 | $table->addColumn($col['type'], $col['name'], $col); 101 | } 102 | foreach ($commands as $command) { 103 | $func = $command->name; 104 | $table->$func($command->columns); 105 | } 106 | }); 107 | } 108 | } 109 | --------------------------------------------------------------------------------