tpetry / laravel-postgresql-enhanced

Support for many missing PostgreSQL specific features
MIT License
773 stars 31 forks source link

Is there a cleaner way to implement UUIDv4 within PostgreSQL? #93

Closed coolamit closed 3 months ago

coolamit commented 3 months ago

Is there a cleaner way to implement UUIDv4 within PostgreSQL via migration? Like if I want to set uuid_generate_v4() as default for my uuid column then it can't be done like this:

$table->uuid()->default( 'uuid_generate_v4()' );

The package has support for UUIDv7 via an expression class which adds a PostgreSQL expression as default value.

For now this is what I'm able to run:

Schema::createExtensionIfNotExists( 'uuid-ossp' );

Schema::create( 'users', function( Blueprint $table ) {
    $table->uuid( 'id' );
    $table->string( 'name' );
    $table->string( 'email' )->unique();
    $table->timestamp( 'email_verified_at' )->nullable();
    $table->timestamp( 'email_verified_on' )->nullable();
    $table->string( 'password' );
    $table->rememberToken();
    $table->timestamps();

    $table->primary( 'id' );
} );

DB::statement( 'ALTER TABLE users ALTER COLUMN id SET DEFAULT uuid_generate_v4();' );

but this exactly as clean as this

$table->uuid( 'id' )->default( new Uuid7() );
coolamit commented 3 months ago

Ok so I took the same approach Uuid7 class does & created Uuid4 class.

<?php
declare( strict_types=1 );

namespace App\Support\Expressions;

use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Database\Grammar;

class Uuid4 implements Expression {

    public function getValue( Grammar $grammar ) : string
    {
        return 'uuid_generate_v4()';
    }

}

Now all that needs to be done is this:

$table->uuid( 'id' )->default( new Uuid4() );

@tpetry Let me know if you would be willing to add this Uuid4 class in the package & I'll open a PR.

tpetry commented 3 months ago

A UUIDv4 expression [1] is available in my generic package working for all databases supported by Laravel. But this one emulates the uuid_generate_v4() function to also support older databases - which is slower. The expression you've posted is probably better but I won't add it as it is can also easily be done by new Expression('uuid_generate_v4()') in your migration.

[1] https://github.com/tpetry/laravel-query-expressions