├── CHANGELOG.md ├── src ├── MigrationPartition.php ├── Database │ ├── Schema │ │ ├── Grammars │ │ │ └── PostgresGrammar.php │ │ ├── Blueprint.php │ │ └── Builder.php │ └── Concerns │ │ └── CompilesPartitionQueries.php ├── Commands │ ├── Stubs │ │ ├── list-partition-migration.stub │ │ ├── hash-partition-migration.stub │ │ └── range-partition-migration.stub │ ├── ListTablePartitionsCommand.php │ ├── InitListPartitionCommand.php │ ├── InitHashPartitionCommand.php │ └── InitRangePartitionCommand.php ├── MigrationPartitionServiceProvider.php └── Support │ └── Facades │ └── Schema.php ├── _config.yml ├── LICENSE.md ├── composer.json └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-migration-partition` will be documented in this file. 4 | -------------------------------------------------------------------------------- /src/MigrationPartition.php: -------------------------------------------------------------------------------- 1 | name('laravel-migration-partition') 17 | ->hasCommands([ 18 | InitRangePartitionCommand::class, 19 | InitListPartitionCommand::class, 20 | InitHashPartitionCommand::class, 21 | ListTablePartitionsCommand::class 22 | ]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Commands/ListTablePartitionsCommand.php: -------------------------------------------------------------------------------- 1 | table = $this->ask('Table name'); 42 | $tables = Schema::getPartitions($this->table); 43 | foreach($tables as $table){ 44 | $this->info($table); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Arda Karaderi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orptech/laravel-migration-partition", 3 | "description": "Laravel extensions that extends Illuminate to enable partitioned table creation within Laravel migrations.", 4 | "keywords": [ 5 | "ORPtech", 6 | "laravel", 7 | "migrations", 8 | "database", 9 | "postgres", 10 | "postgre", 11 | "psql", 12 | "laravel-migration-partition" 13 | ], 14 | "homepage": "https://github.com/orptech/laravel-migration-partition", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Arda Karaderi", 19 | "email": "info@orptech.com", 20 | "role": "Software Engineer" 21 | } 22 | ], 23 | "require": { 24 | "php": "^8.2", 25 | "illuminate/contracts": "^12.0", 26 | "illuminate/database": "^12.0", 27 | "illuminate/support": "^12.0", 28 | "illuminate/console":"^12.0", 29 | "illuminate/filesystem":"^12.0", 30 | "spatie/laravel-package-tools": "^1.90" 31 | }, 32 | "require-dev": { 33 | "laravel/pint": "^1.2", 34 | "nunomaduro/collision": "^8.5", 35 | "larastan/larastan": "^3.0", 36 | "orchestra/testbench": "^10.0.0", 37 | "pestphp/pest": "^3.0", 38 | "pestphp/pest-plugin-arch": "^3.0", 39 | "pestphp/pest-plugin-laravel": "^3.0", 40 | "phpstan/extension-installer": "^1.4", 41 | "phpstan/phpstan-deprecation-rules": "^2.0", 42 | "phpstan/phpstan-phpunit": "^2.0", 43 | "spatie/laravel-ray": "^1.4" 44 | }, 45 | "autoload": { 46 | "psr-4": { 47 | "ORPTech\\MigrationPartition\\": "src", 48 | "ORPTech\\MigrationPartition\\Database\\Factories\\": "database/factories" 49 | } 50 | }, 51 | "autoload-dev": { 52 | "psr-4": { 53 | "ORPTech\\MigrationPartition\\Tests\\": "tests" 54 | } 55 | }, 56 | "scripts": { 57 | "analyse": "vendor/bin/phpstan analyse", 58 | "test": "vendor/bin/pest", 59 | "test-coverage": "vendor/bin/pest --coverage", 60 | "format": "vendor/bin/pint" 61 | }, 62 | "config": { 63 | "sort-packages": true, 64 | "allow-plugins": { 65 | "pestphp/pest-plugin": true, 66 | "phpstan/extension-installer": true 67 | } 68 | }, 69 | "extra": { 70 | "laravel": { 71 | "providers": [ 72 | "ORPTech\\MigrationPartition\\MigrationPartitionServiceProvider" 73 | ], 74 | "aliases": { 75 | "MigrationPartition": "ORPTech\\MigrationPartition\\Facades\\MigrationPartition" 76 | } 77 | } 78 | }, 79 | "minimum-stability": "stable", 80 | "prefer-stable": true 81 | } 82 | -------------------------------------------------------------------------------- /src/Commands/InitListPartitionCommand.php: -------------------------------------------------------------------------------- 1 | files = $files; 27 | } 28 | 29 | /** 30 | * The name and signature of the console command. 31 | * 32 | * @var string 33 | */ 34 | protected $signature = 'partition:list'; 35 | 36 | /** 37 | * The console command description. 38 | * 39 | * @var string 40 | */ 41 | protected $description = 'This command will create a new series of migrations for all list partitioned table.'; 42 | 43 | /** 44 | * The table name. 45 | * 46 | * @var string 47 | */ 48 | protected $table; 49 | 50 | /** 51 | * The suffix for the table. 52 | * 53 | * @var string 54 | */ 55 | protected $suffix; 56 | 57 | /** 58 | * Partition key value for the list partition. 59 | * 60 | * @var string 61 | */ 62 | protected $listKey; 63 | 64 | 65 | /** 66 | * Handler for the command. 67 | * 68 | */ 69 | public function handle() 70 | { 71 | $this->suffix = $this->ask('Define your table suffix'); 72 | $this->listKey = $this->ask('Define a key value for this list partition'); 73 | $tables = Schema::getAllListPartitionedTables(); 74 | foreach($tables as $table){ 75 | $this->table = $table; 76 | $path = $this->getSourceFilePath(); 77 | $contents = $this->getSourceFile(); 78 | $this->files->put($path, $contents); 79 | $this->info("File : {$path} created."); 80 | 81 | } 82 | } 83 | 84 | /** 85 | * Get the full path of generate class. 86 | * 87 | * @return string 88 | */ 89 | public function getSourceFilePath() 90 | { 91 | return base_path('database/migrations') . '/'.now()->format('Y_m_d_His').'_create_partition_' . $this->table.'_'.$this->suffix . '_table.php'; 92 | } 93 | 94 | /** 95 | * Build the directory for the class if necessary. 96 | * 97 | * @param string $path 98 | * @return string 99 | */ 100 | protected function makeDirectory($path) 101 | { 102 | if (!$this->files->isDirectory($path)) { 103 | $this->files->makeDirectory($path, 0755, true, true); 104 | } 105 | 106 | return $path; 107 | } 108 | 109 | /** 110 | * Get the stub path and the stub variables. 111 | * 112 | * @return array|false|string|string[] 113 | * 114 | */ 115 | public function getSourceFile() 116 | { 117 | return $this->getStubContents($this->getStubPath(), $this->getStubVariables()); 118 | } 119 | 120 | /** 121 | * Replace the stub variables(key) with the desire value. 122 | * 123 | * @param $stub 124 | * @param array $stubVariables 125 | * @return array|false|string|string[] 126 | */ 127 | public function getStubContents($stub, array $stubVariables = []) 128 | { 129 | $contents = file_get_contents($stub); 130 | 131 | foreach ($stubVariables as $search => $replace) { 132 | $contents = str_replace('$' . $search . '$', $replace, $contents); 133 | } 134 | 135 | return $contents; 136 | 137 | } 138 | 139 | /** 140 | * Return the stub file path. 141 | * @return string 142 | * 143 | */ 144 | public function getStubPath() 145 | { 146 | return __DIR__.'/Stubs/list-partition-migration.stub'; 147 | } 148 | 149 | /** 150 | ** 151 | * Map the stub variables present in stub to its value. 152 | * 153 | * @return array 154 | * 155 | */ 156 | public function getStubVariables() 157 | { 158 | return [ 159 | 'TABLE' => $this->table, 160 | 'SUFFIX' => $this->suffix, 161 | 'LIST_KEY' => $this->listKey, 162 | ]; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/Commands/InitHashPartitionCommand.php: -------------------------------------------------------------------------------- 1 | files = $files; 27 | } 28 | 29 | /** 30 | * The name and signature of the console command. 31 | * 32 | * @var string 33 | */ 34 | protected $signature = 'partition:hash'; 35 | 36 | /** 37 | * The console command description. 38 | * 39 | * @var string 40 | */ 41 | protected $description = 'This command will create a new series of migrations for all range partitioned table.'; 42 | 43 | /** 44 | * The table name. 45 | * 46 | * @var string 47 | */ 48 | protected $table; 49 | 50 | /** 51 | * The suffix for the table. 52 | * 53 | * @var string 54 | */ 55 | protected $suffix; 56 | 57 | /** 58 | * Modulus value for the partition. 59 | * 60 | * @var string 61 | */ 62 | protected $modulus; 63 | 64 | /** 65 | * Remainder value for the partition. 66 | * 67 | * @var string 68 | */ 69 | protected $remainder; 70 | 71 | 72 | /** 73 | * Handler for the command. 74 | * 75 | */ 76 | public function handle() 77 | { 78 | $this->suffix = $this->ask('Define your table suffix'); 79 | $this->modulus = $this->ask('Modulus value'); 80 | $this->remainder = $this->ask('Remainder value'); 81 | $tables = Schema::getAllHashPartitionedTables(); 82 | foreach($tables as $table){ 83 | $this->table = $table; 84 | $path = $this->getSourceFilePath(); 85 | $contents = $this->getSourceFile(); 86 | $this->files->put($path, $contents); 87 | $this->info("File : {$path} created."); 88 | } 89 | } 90 | 91 | /** 92 | * Get the full path of generate class. 93 | * 94 | * @return string 95 | */ 96 | public function getSourceFilePath() 97 | { 98 | return base_path('database/migrations') . '/'.now()->format('Y_m_d_His').'_create_partition_' . $this->table.'_'.$this->suffix . '_table.php'; 99 | } 100 | 101 | /** 102 | * Build the directory for the class if necessary. 103 | * 104 | * @param string $path 105 | * @return string 106 | */ 107 | protected function makeDirectory($path) 108 | { 109 | if (!$this->files->isDirectory($path)) { 110 | $this->files->makeDirectory($path, 0755, true, true); 111 | } 112 | 113 | return $path; 114 | } 115 | 116 | /** 117 | * Get the stub path and the stub variables. 118 | * 119 | * @return array|false|string|string[] 120 | * 121 | */ 122 | public function getSourceFile() 123 | { 124 | return $this->getStubContents($this->getStubPath(), $this->getStubVariables()); 125 | } 126 | 127 | /** 128 | * Replace the stub variables(key) with the desire value. 129 | * 130 | * @param $stub 131 | * @param array $stubVariables 132 | * @return array|false|string|string[] 133 | */ 134 | public function getStubContents($stub, array $stubVariables = []) 135 | { 136 | $contents = file_get_contents($stub); 137 | 138 | foreach ($stubVariables as $search => $replace) { 139 | $contents = str_replace('$' . $search . '$', $replace, $contents); 140 | } 141 | 142 | return $contents; 143 | 144 | } 145 | 146 | /** 147 | * Return the stub file path. 148 | * @return string 149 | * 150 | */ 151 | public function getStubPath() 152 | { 153 | return __DIR__.'/Stubs/hash-partition-migration.stub'; 154 | } 155 | 156 | /** 157 | ** 158 | * Map the stub variables present in stub to its value. 159 | * 160 | * @return array 161 | * 162 | */ 163 | public function getStubVariables() 164 | { 165 | return [ 166 | 'TABLE' => $this->table, 167 | 'SUFFIX' => $this->suffix, 168 | 'MODULUS' => $this->modulus, 169 | 'REMAINDER' => $this->remainder 170 | ]; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/Commands/InitRangePartitionCommand.php: -------------------------------------------------------------------------------- 1 | files = $files; 27 | } 28 | 29 | /** 30 | * The name and signature of the console command. 31 | * 32 | * @var string 33 | */ 34 | protected $signature = 'partition:range'; 35 | 36 | /** 37 | * The console command description. 38 | * 39 | * @var string 40 | */ 41 | protected $description = 'This command will create a new series of migrations for all range partitioned table.'; 42 | 43 | /** 44 | * The table name. 45 | * 46 | * @var string 47 | */ 48 | protected $table; 49 | 50 | /** 51 | * The suffix for the table. 52 | * 53 | * @var string 54 | */ 55 | protected $suffix; 56 | 57 | /** 58 | * Range start value for the partition. 59 | * 60 | * @var string 61 | */ 62 | protected $start; 63 | 64 | /** 65 | * Range end value for the partition. 66 | * 67 | * @var string 68 | */ 69 | protected $end; 70 | 71 | 72 | /** 73 | * Handler for the command. 74 | * 75 | */ 76 | public function handle() 77 | { 78 | $this->suffix = $this->ask('Define your table suffix (year, month, etc...)'); 79 | $this->start = $this->ask('Range start value'); 80 | $this->end = $this->ask('Range end value'); 81 | $tables = Schema::getAllRangePartitionedTables(); 82 | foreach($tables as $table){ 83 | $this->table = $table; 84 | $path = $this->getSourceFilePath(); 85 | $contents = $this->getSourceFile(); 86 | $this->files->put($path, $contents); 87 | $this->info("File : {$path} created."); 88 | 89 | } 90 | } 91 | 92 | /** 93 | * Get the full path of generate class. 94 | * 95 | * @return string 96 | */ 97 | public function getSourceFilePath() 98 | { 99 | return base_path('database/migrations') . '/'.now()->format('Y_m_d_His').'_create_partition_' . $this->table.'_'.$this->suffix . '_table.php'; 100 | } 101 | 102 | /** 103 | * Build the directory for the class if necessary. 104 | * 105 | * @param string $path 106 | * @return string 107 | */ 108 | protected function makeDirectory($path) 109 | { 110 | if (!$this->files->isDirectory($path)) { 111 | $this->files->makeDirectory($path, 0755, true, true); 112 | } 113 | 114 | return $path; 115 | } 116 | 117 | /** 118 | * Get the stub path and the stub variables. 119 | * 120 | * @return array|false|string|string[] 121 | * 122 | */ 123 | public function getSourceFile() 124 | { 125 | return $this->getStubContents($this->getStubPath(), $this->getStubVariables()); 126 | } 127 | 128 | /** 129 | * Replace the stub variables(key) with the desire value. 130 | * 131 | * @param $stub 132 | * @param array $stubVariables 133 | * @return array|false|string|string[] 134 | */ 135 | public function getStubContents($stub, array $stubVariables = []) 136 | { 137 | $contents = file_get_contents($stub); 138 | 139 | foreach ($stubVariables as $search => $replace) { 140 | $contents = str_replace('$' . $search . '$', $replace, $contents); 141 | } 142 | 143 | return $contents; 144 | 145 | } 146 | 147 | /** 148 | * Return the stub file path. 149 | * @return string 150 | * 151 | */ 152 | public function getStubPath() 153 | { 154 | return __DIR__.'/Stubs/range-partition-migration.stub'; 155 | } 156 | 157 | /** 158 | ** 159 | * Map the stub variables present in stub to its value. 160 | * 161 | * @return array 162 | * 163 | */ 164 | public function getStubVariables() 165 | { 166 | return [ 167 | 'TABLE' => $this->table, 168 | 'SUFFIX' => $this->suffix, 169 | 'START' => $this->start, 170 | 'END' => $this->end 171 | ]; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Support/Facades/Schema.php: -------------------------------------------------------------------------------- 1 | connection()))->$method(...$args); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Database/Schema/Blueprint.php: -------------------------------------------------------------------------------- 1 | commands)->contains(function ($command) { 111 | return in_array($command->name, $this->creators, false); 112 | }); 113 | } 114 | 115 | /** 116 | * Indicate that the table needs to be created with a range partition. 117 | * 118 | * @return Fluent 119 | */ 120 | public function createRangePartitioned(): Fluent 121 | { 122 | return $this->addCommand('createRangePartitioned'); 123 | } 124 | 125 | /** 126 | * Create a range partition and attach it to the partitioned table. 127 | * 128 | * @return Fluent 129 | */ 130 | public function createRangePartition(): Fluent 131 | { 132 | return $this->addCommand('createRangePartition'); 133 | } 134 | 135 | /** 136 | * Attach a range partition for existing table to the partitioned table. 137 | * 138 | * @return Fluent 139 | */ 140 | public function attachRangePartition(): Fluent 141 | { 142 | return $this->addCommand('attachRangePartition'); 143 | } 144 | 145 | /** 146 | * Indicate that the table needs to be created with a list partition. 147 | * 148 | * @return Fluent 149 | */ 150 | public function createListPartitioned(): Fluent 151 | { 152 | return $this->addCommand('createListPartitioned'); 153 | } 154 | 155 | /** 156 | * Attach a range partition for existing table to the partitioned table. 157 | * 158 | * @return Fluent 159 | */ 160 | public function attachListPartition(): Fluent 161 | { 162 | return $this->addCommand('attachListPartition'); 163 | } 164 | 165 | /** 166 | * Create a list partition and attach it to the partitioned table. 167 | * 168 | * @return Fluent 169 | */ 170 | public function createListPartition(): Fluent 171 | { 172 | return $this->addCommand('createListPartition'); 173 | } 174 | 175 | /** 176 | * Indicate that the table needs to be created with a hash partition. 177 | * 178 | * @return Fluent 179 | */ 180 | public function createHashPartitioned(): Fluent 181 | { 182 | return $this->addCommand('createHashPartitioned'); 183 | } 184 | 185 | /** 186 | * Create a hash partition and attach it to the partitioned table. 187 | * 188 | * @return Fluent 189 | */ 190 | public function createHashPartition(): Fluent 191 | { 192 | return $this->addCommand('createHashPartition'); 193 | } 194 | /** 195 | * Attach a range partition for existing table to the partitioned table. 196 | * 197 | * @return Fluent 198 | */ 199 | public function attachHashPartition(): Fluent 200 | { 201 | return $this->addCommand('attachHashPartition'); 202 | } 203 | 204 | /** 205 | * Create a hash partition and attach it to the partitioned table. 206 | * 207 | * @return Fluent 208 | */ 209 | public function getAllRangePartitionedTables(): Fluent 210 | { 211 | return $this->addCommand('getAllRangePartitionedTables'); 212 | } 213 | 214 | /** 215 | * Create a hash partition and attach it to the partitioned table. 216 | * 217 | * @return Fluent 218 | */ 219 | public function getAllHashPartitionedTables(): Fluent 220 | { 221 | return $this->addCommand('getAllHashPartitionedTables'); 222 | } 223 | 224 | /** 225 | * Create a hash partition and attach it to the partitioned table. 226 | * 227 | * @return Fluent 228 | */ 229 | public function getAllListPartitionedTables(): Fluent 230 | { 231 | return $this->addCommand('getAllListPartitionedTables'); 232 | } 233 | 234 | /** 235 | * Create a hash partition and attach it to the partitioned table. 236 | * 237 | * @return Fluent 238 | */ 239 | public function getPartitions(): Fluent 240 | { 241 | return $this->addCommand('getPartitions'); 242 | } 243 | /** 244 | * Indicate that the table needs to be created with a range partition. 245 | * 246 | * @return Fluent 247 | */ 248 | public function detachPartition(): Fluent 249 | { 250 | return $this->addCommand('detachPartition'); 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 |

4 |
5 | 6 | # Database Partitions via Migrations for Laravel (aka Laravel Migration Partitions) 7 | This package extends Illuminate to provide partitioned table creation in migrations for PostgreSQL. Support for other DMBS's will be added soon. 8 | 9 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/orptech/laravel-migration-partition.svg?style=flat-square)](https://packagist.org/packages/orptech/laravel-migration-partition) 10 | [![Total Downloads](https://img.shields.io/packagist/dt/orptech/laravel-migration-partition.svg?style=flat-square)](https://packagist.org/packages/orptech/laravel-migration-partition) 11 | 12 | ## ORPtech Software 13 | 14 | We are ORPtech. Here at ORPtech, we pride ourselves in ensuring that clients and services have a peaceful, safe and smooth interaction. We know how difficult it is to build trust for a service, therefore we are here to help bridge the gaps within the market via our robust applications. Please contact us for further information on how our services might help your business. 15 | 16 | ## Version Matching 17 | | **Package Version** | **Supported** | 18 | |---------------------|------------| 19 | | 11.x.x | **Laravel 11** | 20 | | 12.x.x | **Laravel 12** | 21 | 22 | ## Installation 23 | 24 | You can install the package via composer: 25 | 26 | ```bash 27 | composer require orptech/laravel-migration-partition 28 | ``` 29 | 30 | ## DBMS Support 31 | 32 | - PostgreSQL 33 | 34 | ### Planned Development 35 | 36 | - MySQL - Looking for Contributors 37 | - MariaDB - Looking for Contributors 38 | - SQL Server 2017+ 39 | - SQLite 3.8.8+ 40 | 41 | ## Usage 42 | This package currently, only supports PostgreSQL. 43 | 44 | ## PostgreSQL 45 | PostgreSQL also known as Postgres, is a free and open-source relational database management system (RDBMS) emphasizing extensibility and SQL compliance. 46 | 47 | ### Range Partitioning 48 | Instead of importing Illuminate's Schema import this package's schema: 49 | ```php 50 | use Illuminate\Database\Schema\Blueprint; 51 | use Illuminate\Support\Facades\Schema; 52 | ``` 53 | 54 | ## Template Usage 55 | 56 | ### Range Partition 57 | 58 | ```php 59 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 60 | use ORPTech\MigrationPartition\Support\Facades\Schema; 61 | 62 | Schema::createRangePartitioned('[YourTableNameHere]', function (Blueprint $table) { 63 | //... 64 | }, '[compositeKeyOne]', '[compositeKeyTwo]', '[rangePartitionKey]'); 65 | ``` 66 | 67 | Enter null for `[compositeKeyOne]`, `[compositeKeyTwo]` if you don't need a primary key. 68 | 69 | ##### Creating a Range Partition for a Partitioned Table 70 | 71 | ```php 72 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 73 | use ORPTech\MigrationPartition\Support\Facades\Schema; 74 | 75 | Schema::createRangePartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[startDate]', '[endDate]'); 76 | ``` 77 | 78 | ##### Attaching a Range Partition to a Partitioned Table 79 | 80 | ```php 81 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 82 | use ORPTech\MigrationPartition\Support\Facades\Schema; 83 | 84 | Schema::attachRangePartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[startDate]', '[endDate]'); 85 | ``` 86 | 87 | ### List Partition 88 | 89 | ```php 90 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 91 | use ORPTech\MigrationPartition\Support\Facades\Schema; 92 | 93 | Schema::createListPartitioned('[YourTableNameHere]', function (Blueprint $table) { 94 | //... 95 | }, '[compositeKeyOne]', '[compositeKeyTwo]', '[listPartitionKey]'); 96 | ``` 97 | 98 | Enter null for `[compositeKeyOne]`, `[compositeKeyTwo]` if you don't need a primary key. 99 | 100 | ##### Creating a List Partition for a Partitioned Table 101 | 102 | ```php 103 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 104 | use ORPTech\MigrationPartition\Support\Facades\Schema; 105 | 106 | Schema::createListPartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[listPartitionValue]'); 107 | ``` 108 | 109 | ##### Attaching a List Partition to a Partitioned Table 110 | 111 | ```php 112 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 113 | use ORPTech\MigrationPartition\Support\Facades\Schema; 114 | 115 | Schema::attachListPartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[listPartitionValue]'); 116 | ``` 117 | 118 | ### Hash Partition 119 | 120 | ```php 121 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 122 | use ORPTech\MigrationPartition\Support\Facades\Schema; 123 | 124 | Schema::createHashPartitioned('[YourTableNameHere]', function (Blueprint $table) { 125 | //... 126 | }, '[compositeKeyOne]', '[compositeKeyTwo]', '[hashPartitionKey]'); 127 | ``` 128 | 129 | Enter null for `[compositeKeyOne]`, `[compositeKeyTwo]` if you don't need a primary key. 130 | 131 | ##### Creating a Hash Partition for a Partitioned Table 132 | 133 | ```php 134 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 135 | use ORPTech\MigrationPartition\Support\Facades\Schema; 136 | 137 | Schema::createHashPartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[hashModulus]', '[hashRemainder]'); 138 | ``` 139 | 140 | ##### Attaching a Hash Partition to a Partitioned Table 141 | 142 | ```php 143 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 144 | use ORPTech\MigrationPartition\Support\Facades\Schema; 145 | 146 | Schema::attachHashPartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[suffixForPartition]', '[hashModulus]', '[hashRemainder]'); 147 | ``` 148 | 149 | #### Removing a Partition 150 | 151 | ```php 152 | use ORPTech\MigrationPartition\Database\Schema\Blueprint; 153 | use ORPTech\MigrationPartition\Support\Facades\Schema; 154 | 155 | Schema::detachPartition('[YourPartitionedTableNameHere]', function (Blueprint $table) {}, '[partitionTableName]'); 156 | ``` 157 | 158 | ## Commands 159 | 160 | ##### New Series of Range Partition Migrations 161 | This command will create a new series of migrations for all range partitioned tables. 162 | ```bash 163 | php artisan partition:range 164 | ``` 165 | 166 | ##### New Series of List Partition Migrations 167 | This command will create a new series of migrations for all list partitioned tables. 168 | ```bash 169 | php artisan partition:list 170 | ``` 171 | 172 | ##### New Series of Hash Partition Migrations 173 | This command will create a new series of migrations for all hash partitioned tables. 174 | ```bash 175 | php artisan partition:hash 176 | ``` 177 | 178 | ##### Listing Partitions 179 | This command will list all the partitioned tables. 180 | ```bash 181 | php artisan partition:partitions 182 | ``` 183 | 184 | ### Important 185 | - This package currently supports PostgreSQL Range Partitions. 186 | - You shouldn't define any primary keys in your migration. The package creates a composite key while setting up the table. 187 | - You need to create an initial partition to start using the tables. (PostgreSQL) 188 | 189 | ## Testing 190 | 191 | ```bash 192 | composer test 193 | ``` 194 | 195 | ## Changelog 196 | 197 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 198 | 199 | 200 | ## Security Vulnerabilities 201 | 202 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 203 | 204 | ## Credits 205 | 206 | - [ORPtech](https://github.com/orptech-com) 207 | - [Retrocket](https://github.com/retrocket) 208 | - [Laravel](https://github.com/laravel) 209 | 210 | ## License 211 | 212 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 213 | -------------------------------------------------------------------------------- /src/Database/Concerns/CompilesPartitionQueries.php: -------------------------------------------------------------------------------- 1 | getColumns($blueprint)); 21 | 22 | if ($primaryKey = $this->shouldUsePrimaryKey($blueprint)) 23 | { 24 | $columns = sprintf('%s, %s', $columns, sprintf('primary key (%s, %s)', $blueprint->pkCompositeOne, $blueprint->pkCompositeTwo)); 25 | } 26 | 27 | return array_values(array_filter(array_merge([sprintf( 28 | 'create table %s (%s) partition by range (%s)', 29 | $this->wrapTable($blueprint), 30 | $columns, 31 | $blueprint->rangeKey 32 | )], $primaryKey ? $this->compileAutoIncrementStartingValues($blueprint, $command) : []))); 33 | } 34 | 35 | /** 36 | * Compile a create table partition command for a range partitioned table. 37 | * 38 | * @param Blueprint $blueprint 39 | * @param Fluent $command 40 | * 41 | * @return array 42 | */ 43 | public function compileCreateRangePartition(Blueprint $blueprint, Fluent $command): array 44 | { 45 | return array_values(array_filter(array_merge([sprintf( 46 | 'create table %s_%s partition of %s for values from (\'%s\') to (\'%s\')', 47 | str_replace("\"", "", $this->wrapTable($blueprint)), 48 | $blueprint->suffixForPartition, 49 | str_replace("\"", "", $this->wrapTable($blueprint)), 50 | $blueprint->startDate, 51 | $blueprint->endDate 52 | )], $this->shouldUsePrimaryKey($blueprint) ? $this->compileAutoIncrementStartingValues($blueprint, $command) : []))); 53 | } 54 | 55 | /** 56 | * Compile a create table command with its list partitions. 57 | * 58 | * @param Blueprint $blueprint 59 | * @param Fluent $command 60 | * 61 | * @return string 62 | */ 63 | public function compileCreateListPartitioned(Blueprint $blueprint, Fluent $command): string 64 | { 65 | $columns = implode(', ', $this->getColumns($blueprint)); 66 | 67 | if ($this->shouldUsePrimaryKey($blueprint)) 68 | { 69 | $columns = sprintf('%s, %s', $columns, sprintf('primary key (%s, %s)', $blueprint->pkCompositeOne, $blueprint->pkCompositeTwo)); 70 | } 71 | 72 | return sprintf( 73 | 'create table %s (%s) partition by list(%s)', 74 | $this->wrapTable($blueprint), 75 | $columns, 76 | $blueprint->listPartitionKey 77 | ); 78 | } 79 | 80 | /** 81 | * Compile an attach partition command for a range partitioned table. 82 | * 83 | * @param Blueprint $blueprint 84 | * @param Fluent $command 85 | * 86 | * @return string 87 | */ 88 | public function compileAttachRangePartition(Blueprint $blueprint, Fluent $command): string 89 | { 90 | return sprintf( 91 | 'ALTER table %s attach partition %s for values from (\'%s\') to (\'%s\')', 92 | str_replace("\"", "", $this->wrapTable($blueprint)), 93 | $blueprint->partitionTableName, 94 | $blueprint->startDate, 95 | $blueprint->endDate 96 | ); 97 | } 98 | 99 | /** 100 | * Compile a create table partition command for a list partitioned table. 101 | * 102 | * @param Blueprint $blueprint 103 | * @param Fluent $command 104 | * 105 | * @return string 106 | */ 107 | public function compileCreateListPartition(Blueprint $blueprint, Fluent $command): string 108 | { 109 | return sprintf( 110 | 'create table %s_%s partition of %s for values in (\'%s\')', 111 | str_replace("\"", "", $this->wrapTable($blueprint)), 112 | $blueprint->suffixForPartition, 113 | str_replace("\"", "", $this->wrapTable($blueprint)), 114 | $blueprint->listPartitionValue, 115 | ); 116 | } 117 | 118 | /** 119 | * Compile an attach partition command for a list partitioned table. 120 | * 121 | * @param Blueprint $blueprint 122 | * @param Fluent $command 123 | * 124 | * @return string 125 | */ 126 | public function compileAttachListPartition(Blueprint $blueprint, Fluent $command): string 127 | { 128 | return sprintf( 129 | 'alter table %s partition of %s for values in (\'%s\')', 130 | str_replace("\"", "", $this->wrapTable($blueprint)), 131 | $blueprint->partitionTableName, 132 | $blueprint->listPartitionValue, 133 | ); 134 | } 135 | 136 | /** 137 | * Compile a create table partition command for a hash partitioned table. 138 | * 139 | * @param Blueprint $blueprint 140 | * @param Fluent $command 141 | * 142 | * @return string 143 | */ 144 | public function compileCreateHashPartition(Blueprint $blueprint, Fluent $command): string 145 | { 146 | return sprintf( 147 | 'create table %s_%s partition of %s for values with (modulus %s, remainder %s)', 148 | str_replace("\"", "", $this->wrapTable($blueprint)), 149 | $blueprint->suffixForPartition, 150 | str_replace("\"", "", $this->wrapTable($blueprint)), 151 | $blueprint->hashModulus, 152 | $blueprint->hashRemainder 153 | ); 154 | } 155 | 156 | /** 157 | * Compile a create table command with its hash partitions. 158 | * 159 | * @param Blueprint $blueprint 160 | * @param Fluent $command 161 | * 162 | * @return array 163 | */ 164 | public function compileCreateHashPartitioned(Blueprint $blueprint, Fluent $command): array 165 | { 166 | $columns = implode(', ', $this->getColumns($blueprint)); 167 | 168 | if ($primaryKey = $this->shouldUsePrimaryKey($blueprint)) 169 | { 170 | $columns = sprintf('%s, %s', $columns, sprintf('primary key (%s, %s)', $blueprint->pkCompositeOne, $blueprint->pkCompositeTwo)); 171 | } 172 | 173 | return array_values(array_filter(array_merge([sprintf( 174 | 'create table %s (%s) partition by hash(%s)', 175 | $this->wrapTable($blueprint), 176 | $columns, 177 | $blueprint->hashPartitionKey 178 | )], $primaryKey ? $this->compileAutoIncrementStartingValues($blueprint, $command) : []))); 179 | } 180 | 181 | /** 182 | * Compile an attach partition command for a hash partitioned table. 183 | * 184 | * @param Blueprint $blueprint 185 | * @param Fluent $command 186 | * 187 | * @return string 188 | */ 189 | public function compileAttachHashPartition(Blueprint $blueprint, Fluent $command): string 190 | { 191 | return sprintf( 192 | 'alter table %s partition of %s for values with (modulus %s, remainder %s)', 193 | str_replace("\"", "", $this->wrapTable($blueprint)), 194 | $blueprint->partitionTableName, 195 | $blueprint->hashModulus, 196 | $blueprint->hashRemainder, 197 | ); 198 | } 199 | 200 | /** 201 | * Get a list of all partitioned tables in the Database. 202 | * 203 | * @param string $table 204 | * 205 | * @return string 206 | */ 207 | public function compileGetPartitions(string $table): string 208 | { 209 | return sprintf( 210 | "SELECT inhrelid::regclass as tables 211 | FROM pg_catalog.pg_inherits 212 | WHERE inhparent = '%s'::regclass;", 213 | $table, 214 | ); 215 | } 216 | 217 | /** 218 | * Get all range partitioned tables. 219 | * 220 | * @return string 221 | */ 222 | public function compileGetAllRangePartitionedTables(): string 223 | { 224 | return "select pg_class.relname as tables from pg_class inner join pg_partitioned_table on pg_class.oid = pg_partitioned_table.partrelid where pg_partitioned_table.partstrat = 'r';"; 225 | } 226 | 227 | /** 228 | * Get all list partitioned tables. 229 | * 230 | * @return string 231 | */ 232 | public function compileGetAllListPartitionedTables(): string 233 | { 234 | return "select pg_class.relname as tables from pg_class inner join pg_partitioned_table on pg_class.oid = pg_partitioned_table.partrelid where pg_partitioned_table.partstrat = 'l';"; 235 | } 236 | 237 | /** 238 | * Get all hash partitioned tables. 239 | * 240 | * @return string 241 | */ 242 | public function compileGetAllHashPartitionedTables(): string 243 | { 244 | return "select pg_class.relname as tables from pg_class inner join pg_partitioned_table on pg_class.oid = pg_partitioned_table.partrelid where pg_partitioned_table.partstrat = 'h';"; 245 | } 246 | 247 | /** 248 | * Compile a detach query for a partitioned table. 249 | * 250 | * @param Blueprint $blueprint 251 | * @param Fluent $command 252 | * 253 | * @return string 254 | */ 255 | public function compileDetachPartition(Blueprint $blueprint, Fluent $command): string 256 | { 257 | return sprintf( 258 | 'alter table %s detach partition %s', 259 | str_replace("\"", "", $this->wrapTable($blueprint)), 260 | $blueprint->partitionTableName 261 | ); 262 | } 263 | 264 | /** 265 | * Checks if the table should have a primary key. 266 | * 267 | * @param Blueprint $blueprint 268 | * 269 | * @return bool 270 | */ 271 | public function shouldUsePrimaryKey(Blueprint $blueprint): bool 272 | { 273 | return $blueprint->pkCompositeOne && $blueprint->pkCompositeTwo; 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /src/Database/Schema/Builder.php: -------------------------------------------------------------------------------- 1 | grammar = new PostgresGrammar($connection); 19 | } 20 | 21 | /** 22 | * Create a new table on the schema with range partitions. 23 | * 24 | * @param string $table 25 | * @param Closure $callback 26 | * @param string|null $pkCompositeOne 27 | * @param string|null $pkCompositeTwo 28 | * @param string $rangeKey 29 | * @return void 30 | * @throws BindingResolutionException 31 | */ 32 | public function createRangePartitioned(string $table, Closure $callback, ?string $pkCompositeOne, ?string $pkCompositeTwo, string $rangeKey): void 33 | { 34 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $pkCompositeOne, $pkCompositeTwo, $rangeKey) { 35 | $blueprint->createRangePartitioned(); 36 | $blueprint->pkCompositeOne = $pkCompositeOne; 37 | $blueprint->pkCompositeTwo = $pkCompositeTwo; 38 | $blueprint->rangeKey = $rangeKey; 39 | 40 | $callback($blueprint); 41 | })); 42 | } 43 | 44 | /** 45 | * Create a new range partition on the table. 46 | * 47 | * @param string $table 48 | * @param Closure $callback 49 | * @param string $suffixForPartition 50 | * @param string $startDate 51 | * @param string $endDate 52 | * @return void 53 | * @throws BindingResolutionException 54 | */ 55 | public function createRangePartition(string $table, Closure $callback, string $suffixForPartition, string $startDate, string $endDate): void 56 | { 57 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $suffixForPartition, $startDate, $endDate) { 58 | $blueprint->createRangePartition(); 59 | $blueprint->suffixForPartition = $suffixForPartition; 60 | $blueprint->startDate = $startDate; 61 | $blueprint->endDate = $endDate; 62 | 63 | $callback($blueprint); 64 | })); 65 | } 66 | 67 | /** 68 | * Attach a new range partition to a partitioned table. 69 | * 70 | * @param string $table 71 | * @param Closure $callback 72 | * @param string $partitionTableName 73 | * @param string $startDate 74 | * @param string $endDate 75 | * @return void 76 | * @throws BindingResolutionException 77 | */ 78 | public function attachRangePartition(string $table, Closure $callback, string $partitionTableName, string $startDate, string $endDate): void 79 | { 80 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $partitionTableName, $startDate, $endDate) { 81 | $blueprint->attachRangePartition(); 82 | $blueprint->partitionTableName = $partitionTableName; 83 | $blueprint->startDate = $startDate; 84 | $blueprint->endDate = $endDate; 85 | $callback($blueprint); 86 | })); 87 | } 88 | 89 | /** 90 | * Create a new table on the schema with list partitions. 91 | * 92 | * @param string $table 93 | * @param Closure $callback 94 | * @param string|null $pkCompositeOne 95 | * @param string|null $pkCompositeTwo 96 | * @param string $listPartitionKey 97 | * @return void 98 | * @throws BindingResolutionException 99 | */ 100 | public function createListPartitioned(string $table, Closure $callback, ?string $pkCompositeOne, ?string $pkCompositeTwo, string $listPartitionKey): void 101 | { 102 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $pkCompositeOne, $pkCompositeTwo, $listPartitionKey) { 103 | $blueprint->createListPartitioned(); 104 | $blueprint->pkCompositeOne = $pkCompositeOne; 105 | $blueprint->pkCompositeTwo = $pkCompositeTwo; 106 | $blueprint->listPartitionKey = $listPartitionKey; 107 | 108 | $callback($blueprint); 109 | })); 110 | } 111 | 112 | /** 113 | * Create a list partition on the table. 114 | * 115 | * @param string $table 116 | * @param Closure $callback 117 | * @param string $suffixForPartition 118 | * @param string $listPartitionValue 119 | * @return void 120 | * @throws BindingResolutionException 121 | */ 122 | public function createListPartition(string $table, Closure $callback, string $suffixForPartition, string $listPartitionValue): void 123 | { 124 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $suffixForPartition, $listPartitionValue) { 125 | $blueprint->createListPartition(); 126 | $blueprint->suffixForPartition = $suffixForPartition; 127 | $blueprint->listPartitionValue = $listPartitionValue; 128 | 129 | $callback($blueprint); 130 | })); 131 | } 132 | 133 | /** 134 | * Attach a new list partition. 135 | * 136 | * @param string $table 137 | * @param Closure $callback 138 | * @param string $partitionTableName 139 | * @param string $listPartitionValue 140 | * @return void 141 | * @throws BindingResolutionException 142 | */ 143 | public function attachListPartition(string $table, Closure $callback, string $partitionTableName, string $listPartitionValue): void 144 | { 145 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $partitionTableName, $listPartitionValue) { 146 | $blueprint->attachListPartition(); 147 | $blueprint->partitionTableName = $partitionTableName; 148 | $blueprint->listPartitionValue = $listPartitionValue; 149 | $callback($blueprint); 150 | })); 151 | } 152 | 153 | /** 154 | * Create a table on the schema with hash partitions. 155 | * 156 | * @param string $table 157 | * @param Closure $callback 158 | * @param string|null $pkCompositeOne 159 | * @param string|null $pkCompositeTwo 160 | * @param string $hashPartitionKey 161 | * @return void 162 | * @throws BindingResolutionException 163 | */ 164 | public function createHashPartitioned(string $table, Closure $callback, ?string $pkCompositeOne, ?string $pkCompositeTwo, string $hashPartitionKey): void 165 | { 166 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $pkCompositeOne, $pkCompositeTwo, $hashPartitionKey) { 167 | $blueprint->createHashPartitioned(); 168 | $blueprint->pkCompositeOne = $pkCompositeOne; 169 | $blueprint->pkCompositeTwo = $pkCompositeTwo; 170 | $blueprint->hashPartitionKey = $hashPartitionKey; 171 | $callback($blueprint); 172 | })); 173 | } 174 | 175 | 176 | /** 177 | * Create and attach a new hash partition on the table. 178 | * 179 | * @param string $table 180 | * @param Closure $callback 181 | * @param string $suffixForPartition 182 | * @param int $hashModulus 183 | * @param int $hashRemainder 184 | * @return void 185 | * @throws BindingResolutionException 186 | */ 187 | public function createHashPartition(string $table, Closure $callback, string $suffixForPartition, int $hashModulus, int $hashRemainder): void 188 | { 189 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $suffixForPartition, $hashModulus, $hashRemainder) { 190 | $blueprint->createHashPartition(); 191 | $blueprint->suffixForPartition = $suffixForPartition; 192 | $blueprint->hashModulus = $hashModulus; 193 | $blueprint->hashRemainder = $hashRemainder; 194 | $callback($blueprint); 195 | })); 196 | } 197 | 198 | /** 199 | * Attach a hash partition. 200 | * 201 | * @param string $table 202 | * @param Closure $callback 203 | * @param string $partitionTableName 204 | * @param int $hashModulus 205 | * @param int $hashRemainder 206 | * @return void 207 | * @throws BindingResolutionException 208 | */ 209 | public function attachHashPartition(string $table, Closure $callback, string $partitionTableName, int $hashModulus, int $hashRemainder): void 210 | { 211 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $partitionTableName, $hashModulus, $hashRemainder) { 212 | $blueprint->attachHashPartition(); 213 | $blueprint->partitionTableName = $partitionTableName; 214 | $blueprint->hashModulus = $hashModulus; 215 | $blueprint->hashRemainder = $hashRemainder; 216 | $callback($blueprint); 217 | })); 218 | } 219 | 220 | /** 221 | * Get all the partitioned table names for the database. 222 | * 223 | * @param string $table 224 | * @return array 225 | */ 226 | public function getPartitions(string $table): array 227 | { 228 | return array_column(DB::select($this->grammar->compileGetPartitions($table)), 'tables'); 229 | } 230 | 231 | /** 232 | * Get all the range partitioned table names for the database. 233 | * 234 | * @return array 235 | */ 236 | public function getAllRangePartitionedTables(): array 237 | { 238 | return array_column(DB::select($this->grammar->compileGetAllRangePartitionedTables()), 'tables'); 239 | } 240 | 241 | /** 242 | * Get all the list partitioned table names for the database. 243 | * 244 | * @return array 245 | */ 246 | public function getAllListPartitionedTables(): array 247 | { 248 | return array_column(DB::select($this->grammar->compileGetAllListPartitionedTables()), 'tables'); 249 | } 250 | 251 | /** 252 | * Get all the hash partitioned table names for the database. 253 | * 254 | * @return array 255 | */ 256 | public function getAllHashPartitionedTables(): array 257 | { 258 | return array_column(DB::select($this->grammar->compileGetAllHashPartitionedTables()), 'tables'); 259 | } 260 | 261 | /** 262 | * Detaches a partition from a partitioned table. 263 | * 264 | * @param string $table 265 | * @param Closure $callback 266 | * @param string $partitionTableName 267 | * @return void 268 | * @throws BindingResolutionException 269 | */ 270 | public function detachPartition(string $table, Closure $callback, string $partitionTableName): void 271 | { 272 | $this->build(tap($this->createBlueprint($table), function ($blueprint) use ($callback, $partitionTableName) { 273 | $blueprint->detachPartition(); 274 | $blueprint->partitionTableName = $partitionTableName; 275 | $callback($blueprint); 276 | })); 277 | } 278 | 279 | /** 280 | * Create a new command set with a Closure. 281 | * 282 | * @param string $table 283 | * @param Closure|null $callback 284 | * @return Closure|mixed|object|Blueprint|null 285 | * @throws BindingResolutionException 286 | */ 287 | protected function createBlueprint($table, ?Closure $callback = null): mixed 288 | { 289 | $prefix = $this->connection->getConfig('prefix_indexes') 290 | ? $this->connection->getConfig('prefix') 291 | : ''; 292 | 293 | if (isset($this->resolver)) { 294 | return call_user_func($this->resolver, $table, $callback, $prefix); 295 | } 296 | 297 | return Container::getInstance()->make(Blueprint::class, compact('table', 'callback', 'prefix')); 298 | } 299 | 300 | } 301 | --------------------------------------------------------------------------------