Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Get columns of a table #48357

Merged
merged 7 commits into from
Oct 26, 2023
Merged

Conversation

hafezdivandari
Copy link
Contributor

@hafezdivandari hafezdivandari commented Sep 11, 2023

Previous attempt (PR #45598) was a breaking change and tabled a few days before Laravel 10 release. This PR has more features than the previous one and is not a breaking change.

Usage

Schema::getColumns()

  • name (string): Name of the column
  • type_name (string): Type name
  • type (string): Full definition of the column type
  • collation (?string): Collation of the column
  • nullable (boolean): Is column nullable?
  • default (?string): Default expression of the column if defined
  • auto_increment (boolean): Does column auto increment?
  • comment (?string): Comment of the column if exists
  • generation (null|array) (added on Laravel 11 via [11.x] Add support for modifying generated columns #50329):
    • type (string): Generation type: 'stored' or 'virtual'.
    • expression (string): Generation expression.

Changes

This PR:

  1. Adds a new Schema::getColumns():
    Currently, we are using doctrine/dbal to get columns of a table and their attributes, for example on model:show artisan command. This PR adds Schema::getColumns($table) for MySQL, PostgreSQL, SQLite and SQL Server without Doctrine DBAL type mapping issues and full support for all native types. This function returns a list of columns and their attributes:

    use Illuminate\Support\Facades\Schema;
    
    Schema::getColumns('products');
    
     /*
         [
             'name' => 'id',
             'type_name' => 'bigint',
             'type' => 'bigint unsigned,
             'collation' => null,
             'nullable' => false,
             'default' => null,
             'auto_increment' => true,
             'comment' => null,
         ], [
             'name' => 'name',
             'type_name' => 'varchar',
             'type' => 'varchar(255)',
             'collation' => 'utf8mb4_0900_ai_ci',
             'nullable' => false,
             'default' => null,
             'auto_increment' => false,
             'comment' => 'The product name',
         ], [
             'name' => 'status',
             'type_name' => 'enum',
             'type' => "enum('in_stock','out_of_stock')",
             'collation' => 'utf8mb4_0900_ai_ci',
             'nullable' => true,
             'default' => null,
             'auto_increment' => false,
             'comment' =>null,
         ],
     */
  2. Adds native support for Schema::getColumnType():
    Currently we are using Doctrine DBAL to get column type using Schema::getColumnType method. DBAL maps every native column type to its Doctrine type equivalent and doesn't support many column types used by Laravel on different databases.

    After this PR you won't need to install doctrine/dbal to get type of a column, you'll be able to get eighter data type name or full type definition of the given column:

    Schema::getColumnType('products', 'id');           // bigint
    Schema::getColumnType('products', 'id', true);     // bigint unsigned
    Schema::getColumnType('products', 'status');       // enum
    Schema::getColumnType('products', 'status', true); // enum('active','suspended','deleted')
    Schema::getColumnType('products', 'name');         // varchar
    Schema::getColumnType('products', 'name', true);   // varchar(255)
    Schema::getColumnType('products', 'price');        // decimal
    Schema::getColumnType('products', 'price', true);  // decimal(8,2)

    Just like [10.x] Add support for native column modifying #45487, if you have already installed doctrine/dbal, you have to call Schema::useNativeSchemaOperationsIfPossible() method within the boot method of your App\Providers\AppServiceProvider class to be able to use native schema operations.

  3. Deprecates a few functions:
    This PR makes Schema::getColumnListing() function to use newly added Schema::getColumns() method under the hood, so we don't need any of the following functions any more. This PR deprecates:

    • \Illuminate\Database\Query\Processors\Processor::processColumnListing
    • \Illuminate\Database\Query\Processors\MySqlProcessor::processColumnListing
    • \Illuminate\Database\Query\Processors\PostgresProcessor::processColumnListing
    • \Illuminate\Database\Query\Processors\SQLiteProcessor::processColumnListing
    • \Illuminate\Database\Query\Processors\SqlServerProcessor::processColumnListing
    • \Illuminate\Database\Schema\Grammars\MySqlGrammar::compileColumnListing
    • \Illuminate\Database\Schema\Grammars\PostgresGrammar::compileColumnListing
    • \Illuminate\Database\Schema\Grammars\SQLiteGrammar::compileColumnListing
    • \Illuminate\Database\Schema\Grammars\SqlServerGrammar::compileColumnListing

@morloderex
Copy link
Contributor

morloderex commented Sep 27, 2023

@hafezdivandari I am curious about the third point if I haven't add Schema::useNativeSchemaOperationsIfPossible() shouldn't we still use Processor's processColumnListing method in order to be fully backwards compatible with the doctrine/dbal since it looks like the processing from doctrine/dbal was implemented differently than this new native type column types implementation?

Am i missing something here?

@hafezdivandari
Copy link
Contributor Author

hafezdivandari commented Sep 27, 2023

@morloderex These are separated matters, you have to call Schema::useNativeSchemaOperationsIfPossible() if you have doctrine/dbal installed and want to use native Schema::getColumnType(), it's not related to processColumnListing that were used on Schema::getColumnListing before this PR. It's fully backward compatible right now.

Feature Before After
Schema::getColumns() (N/A) Calls Grammar::compileColumns and Processor::processColumns
Schema::getColumnListing() Calls Grammar::compileColumnListing and Processor::processColumnListing Uses Schema::getColumns()
Schema::getColumnType() Uses doctrine/dbal Uses doctrine/dbal if installed (for backward compatibility) otherwise uses Schema::getColumns()

@taylorotwell taylorotwell merged commit 85a5146 into laravel:10.x Oct 26, 2023
20 checks passed
@hafezdivandari hafezdivandari deleted the 10.x-patch-4 branch October 27, 2023 08:33
@hafezdivandari hafezdivandari mentioned this pull request Oct 31, 2023
30 tasks
crynobone added a commit that referenced this pull request Nov 1, 2023
@hafezdivandari hafezdivandari changed the title [10.x] Add support for getting native columns' attributes [10.x] Get columns of a table Dec 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants