Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetry committed Feb 26, 2024
1 parent 41d52c6 commit 640d684
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/Language/Cast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Tpetry\QueryExpressions\Language;

use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Database\Grammar;
use RuntimeException;
use Tpetry\QueryExpressions\Concerns\IdentifiesDriver;
use Tpetry\QueryExpressions\Concerns\StringizeExpression;

class Cast implements Expression
{
use IdentifiesDriver;
use StringizeExpression;

/**
* @param 'bigint'|'int' $type
*/
public function __construct(
private readonly string|Expression $expression,
private readonly string $type,
) {
}

public function getValue(Grammar $grammar): string
{
$expression = $this->stringize($grammar, $this->expression);
$type = match ($this->type) {
'bigint' => $this->typeBigInt($grammar),

'int' => $this->typeInt($grammar),
default => throw new RuntimeException("Unknown casting type '{$this->type}'."),

Check failure on line 34 in src/Language/Cast.php

View workflow job for this annotation

GitHub Actions / phpstan

Match arm is unreachable because previous comparison is always true.
};

return match ($this->identify($grammar)) {
'pgsql' => "({$expression})::{$type}",
default => "(cast({$expression} as {$type}))",
};
}

private function typeBigInt(Grammar $grammar): string
{
return match ($this->identify($grammar)) {
'mysql' => 'signed',
default => 'bigint',
};
}

private function typeInt(Grammar $grammar): string
{
return match ($this->identify($grammar)) {
'mysql' => 'signed',
default => 'int',
};
}
}
49 changes: 49 additions & 0 deletions tests/Language/CastTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Blueprint;
use Tpetry\QueryExpressions\Language\Cast;

it('can cast a column to an bigint')
->expect(new Cast('val', 'bigint'))
->toBeExecutable(function (Blueprint $table) {
$table->string('val');
})
->toBeMysql('cast(`val` as signed)')
->toBePgsql('("val")::bigint')
->toBeSqlite('cast("val" as bigint)')
->toBeSqlsrv('cast([val] as bigint)');

it('can cast an expression to an bigint')
->expect(new Cast(new Expression(3.1415), 'bigint'))
->toBeExecutable()
->toBeMysql('cast(3.1415` as signed)')
->toBePgsql('(3.1415)::bigint')
->toBeSqlite('cast(3.1415 as bigint)')
->toBeSqlsrv('cast(3.1415 as bigint)');

it('can cast a column to an int')
->expect(new Cast('val', 'int'))
->toBeExecutable(function (Blueprint $table) {
$table->string('val');
})
->toBeMysql('cast(`val` as signed)')
->toBePgsql('("val")::int')
->toBeSqlite('cast("val" as int)')
->toBeSqlsrv('cast([val] as int)');

it('can cast an expression to an int')
->expect(new Cast(new Expression(3.1415), 'int'))
->toBeExecutable()
->toBeMysql('cast(3.1415` as signed)')
->toBePgsql('(3.1415)::int')
->toBeSqlite('cast(3.1415 as int)')
->toBeSqlsrv('cast(3.1415 as int)');

it('throws an exception for unknown types', fn (string $type) => new Cast('0', $type))->with([
'enum',
'varchar',
'timestamptz',
]);

0 comments on commit 640d684

Please sign in to comment.