Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extending creating unique indexes with conditions on where, example: ``` Schema::create('cities', static function (Blueprint $table) { ... $table->uniquePartial(['name', 'author_id']) ->where('editor_id', 1) ->whereRaw('field1 = ? and field2 <= ?', ['field1', 'field2']) ->whereNotNull('deleted_at') ->whereBetween('author_id', [1, 2, 3]); ... ``` PS. If you will use $table->uniquePartial() without extend methods after call uniquePartial(), it works as $table->unique().
- Loading branch information
Showing
8 changed files
with
401 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Umbrellio\Postgres\Compilers; | ||
|
||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Database\Schema\Grammars\Grammar; | ||
use Umbrellio\Postgres\Schema\Builders\UniquePartialBuilder; | ||
use Umbrellio\Postgres\Schema\Builders\UniqueWhereBuilder; | ||
|
||
class UniqueWhereCompiler | ||
{ | ||
public static function compile( | ||
Grammar $grammar, | ||
Blueprint $blueprint, | ||
UniquePartialBuilder $fluent, | ||
UniqueWhereBuilder $command | ||
): string { | ||
$wheres = collect($command->get('wheres')) | ||
->map(function ($where) use ($grammar, $blueprint) { | ||
return implode(' ', [ | ||
$where['boolean'], | ||
'(' . static::{"where{$where['type']}"}($grammar, $blueprint, $where) . ')', | ||
]); | ||
}) | ||
->all(); | ||
|
||
return sprintf( | ||
'CREATE UNIQUE INDEX %s ON %s (%s) WHERE %s', | ||
$fluent->get('index'), | ||
$blueprint->getTable(), | ||
implode(',', $fluent->get('columns')), | ||
static::removeLeadingBoolean(implode(' ', $wheres)) | ||
); | ||
} | ||
|
||
protected static function whereRaw(Grammar $grammar, Blueprint $blueprint, array $where = []): string | ||
{ | ||
return call_user_func_array('sprintf', array_merge( | ||
[str_replace('?', '%s', $where['sql'])], | ||
static::wrapValues($where['bindings']) | ||
)); | ||
} | ||
|
||
protected static function whereBasic(Grammar $grammar, Blueprint $blueprint, array $where): string | ||
{ | ||
return implode(' ', [ | ||
$grammar->wrap($where['column']), | ||
$where['operator'], | ||
static::wrapValue($where['value']), | ||
]); | ||
} | ||
|
||
protected static function whereColumn(Grammar $grammar, Blueprint $blueprint, array $where): string | ||
{ | ||
return implode(' ', [ | ||
$grammar->wrap($where['first']), | ||
$where['operator'], | ||
$grammar->wrap($where['second']), | ||
]); | ||
} | ||
|
||
protected static function whereIn(Grammar $grammar, Blueprint $blueprint, array $where = []): string | ||
{ | ||
if (!empty($where['values'])) { | ||
return implode(' ', [ | ||
$grammar->wrap($where['column']), | ||
'in', | ||
'(' . implode(',', static::wrapValues($where['values'])) . ')', | ||
]); | ||
} | ||
return '0 = 1'; | ||
} | ||
|
||
protected static function whereNotIn(Grammar $grammar, Blueprint $blueprint, array $where = []): string | ||
{ | ||
if (!empty($where['values'])) { | ||
return implode(' ', [ | ||
$grammar->wrap($where['column']), | ||
'not in', | ||
'(' . implode(',', static::wrapValues($where['values'])) . ')', | ||
]); | ||
} | ||
return '1 = 1'; | ||
} | ||
|
||
protected static function whereNull(Grammar $grammar, Blueprint $blueprint, array $where): string | ||
{ | ||
return implode(' ', [$grammar->wrap($where['column']), 'is null']); | ||
} | ||
|
||
protected static function whereNotNull(Grammar $grammar, Blueprint $blueprint, array $where): string | ||
{ | ||
return implode(' ', [$grammar->wrap($where['column']), 'is not null']); | ||
} | ||
|
||
protected static function whereBetween(Grammar $grammar, Blueprint $blueprint, array $where): string | ||
{ | ||
return implode(' ', [ | ||
$grammar->wrap($where['column']), | ||
$where['not'] ? 'not between' : 'between', | ||
static::wrapValue(reset($where['values'])), | ||
'and', | ||
static::wrapValue(end($where['values'])), | ||
]); | ||
} | ||
|
||
protected static function wrapValues(array $values = []): array | ||
{ | ||
return collect($values)->map(function ($value) { | ||
return static::wrapValue($value); | ||
})->toArray(); | ||
} | ||
|
||
protected static function wrapValue($value) | ||
{ | ||
if (is_string($value)) { | ||
return "'{$value}'"; | ||
} | ||
return (int) $value; | ||
} | ||
|
||
protected static function removeLeadingBoolean(string $value): string | ||
{ | ||
return preg_replace('/and |or /i', '', $value, 1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Umbrellio\Postgres\Schema\Builders; | ||
|
||
use Illuminate\Support\Fluent; | ||
|
||
class UniquePartialBuilder extends Fluent | ||
{ | ||
public function __call($method, $parameters) | ||
{ | ||
$command = new UniqueWhereBuilder(); | ||
$this->attributes['constraints'] = call_user_func_array([$command, $method], $parameters); | ||
return $command; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Umbrellio\Postgres\Schema\Builders; | ||
|
||
use Illuminate\Support\Fluent; | ||
|
||
class UniqueWhereBuilder extends Fluent | ||
{ | ||
public function whereRaw(string $sql, array $bindings = [], string $boolean = 'and'): self | ||
{ | ||
return $this->compileWhere('Raw', $boolean, compact('sql', 'bindings')); | ||
} | ||
|
||
public function where(string $column, string $operator, string $value, string $boolean = 'and'): self | ||
{ | ||
return $this->compileWhere('Basic', $boolean, compact('column', 'operator', 'value')); | ||
} | ||
|
||
public function whereColumn(string $first, string $operator, string $second, string $boolean = 'and'): self | ||
{ | ||
return $this->compileWhere('Column', $boolean, compact('first', 'operator', 'second')); | ||
} | ||
|
||
public function whereIn(string $column, array $values, string $boolean = 'and', bool $not = false): self | ||
{ | ||
return $this->compileWhere($not ? 'NotIn' : 'In', $boolean, compact('column', 'values')); | ||
} | ||
|
||
public function whereNotIn(string $column, array $values = [], string $boolean = 'and'): self | ||
{ | ||
return $this->whereIn($column, $values, $boolean, true); | ||
} | ||
|
||
public function whereNull(string $column, string $boolean = 'and', bool $not = false): self | ||
{ | ||
return $this->compileWhere($not ? 'NotNull' : 'Null', $boolean, compact('column')); | ||
} | ||
|
||
public function whereBetween(string $column, array $values = [], string $boolean = 'and', bool $not = false): self | ||
{ | ||
return $this->compileWhere('Between', $boolean, compact('column', 'values', 'not')); | ||
} | ||
|
||
public function whereNotBetween(string $column, array $values = [], string $boolean = 'and'): self | ||
{ | ||
return $this->whereBetween($column, $values, $boolean, true); | ||
} | ||
|
||
public function whereNotNull(string $column, string $boolean = 'and'): self | ||
{ | ||
return $this->whereNull($column, $boolean, true); | ||
} | ||
|
||
protected function compileWhere(string $type, string $boolean, array $parameters = []): self | ||
{ | ||
$this->attributes['wheres'][] = array_merge(compact('type', 'boolean'), $parameters); | ||
return $this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Umbrellio\Postgres\Schema\Definitions; | ||
|
||
use Illuminate\Support\Fluent; | ||
|
||
/** | ||
* @method UniqueDefinition where($column, $operator, $value, $boolean = 'and') | ||
* @method UniqueDefinition whereRaw($sql, $bindings = [], $boolean = 'and') | ||
* @method UniqueDefinition whereColumn($first, $operator, $second, $boolean = 'and') | ||
* @method UniqueDefinition whereIn($column, $values = [], $boolean = 'and', $not = false) | ||
* @method UniqueDefinition whereNotIn($column, $values = [], $boolean = 'and') | ||
* @method UniqueDefinition whereBetween($column, $values, $boolean = 'and', $not = false) | ||
* @method UniqueDefinition whereNotBetween($column, $values, $boolean = 'and') | ||
* @method UniqueDefinition whereNull($column, $boolean = 'and', $not = false) | ||
* @method UniqueDefinition whereNotNull($column, $boolean = 'and') | ||
*/ | ||
class UniqueDefinition extends Fluent | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.