- WIP on Collation
This commit is contained in:
parent
b601939459
commit
b5e96eb7e0
|
@ -150,6 +150,7 @@ class MySQL implements AdapterInterface, MigrateInterface, SqlAdapterInterface {
|
|||
public static function escapeIdentifier(string $segment, int $type) : string
|
||||
{
|
||||
switch($type) {
|
||||
default:
|
||||
case static::IDENTIFIER_DATABASE:
|
||||
case static::IDENTIFIER_TABLE:
|
||||
case static::IDENTIFIER_FIELD:
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace Ulmus\Adapter;
|
||||
|
||||
use Collator;
|
||||
use Ulmus\Common\PdoObject;
|
||||
use Ulmus\ConnectionAdapter;
|
||||
|
||||
use Ulmus\Entity;
|
||||
use Ulmus\Migration\FieldDefinition;
|
||||
use Ulmus\{Migration\MigrateInterface, Repository, QueryBuilder};
|
||||
|
@ -37,6 +37,7 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
|
|||
};
|
||||
|
||||
$this->exportFunctions($pdo);
|
||||
$this->exportCollations($pdo);
|
||||
$this->registerPragma($pdo, $this->pragmaBegin);
|
||||
}
|
||||
catch(\PDOException $ex){
|
||||
|
@ -196,6 +197,37 @@ class SQLite implements AdapterInterface, MigrateInterface, SqlAdapterInterface
|
|||
$pdo->sqliteCreateFunction('year', fn($date) => ( new \DateTime($date) )->format('Y'), 1);
|
||||
}
|
||||
|
||||
|
||||
public function exportCollations(PdoObject $pdo) : void
|
||||
{
|
||||
|
||||
if ( class_exists('Locale') ) {
|
||||
# @TODO debug this, case-sensitivity not working properly !!
|
||||
$collator = new Collator(\Locale::getDefault());
|
||||
$collator->setStrength(Collator::TERTIARY);
|
||||
$collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
|
||||
|
||||
$pdo->sqliteCreateCollation('locale_cmp', fn($e1, $e2) => $collator->compare($e1, $e2));
|
||||
$pdo->sqliteCreateCollation('locale_cmp_desc', fn($e1, $e2) => $collator->compare($e2, $e1));
|
||||
|
||||
$collatorCi = new Collator(\Locale::getDefault());
|
||||
$collatorCi->setStrength(Collator::SECONDARY);
|
||||
$collatorCi->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
|
||||
|
||||
$pdo->sqliteCreateCollation('locale_cmp_ci', fn($e1, $e2) => $collatorCi->compare($e1, $e2));
|
||||
$pdo->sqliteCreateCollation('locale_cmp_ci_desc', fn($e1, $e2) => $collatorCi->compare($e2, $e1));
|
||||
}
|
||||
else {
|
||||
$comp = fn(string $e1, string $e2) => \iconv('UTF-8', 'ASCII//TRANSLIT', $e1) <=> \iconv('UTF-8', 'ASCII//TRANSLIT', $e2);
|
||||
$pdo->sqliteCreateCollation('locale_cmp', fn($e1, $e2) => $comp);
|
||||
$pdo->sqliteCreateCollation('locale_cmp_desc', fn($e2, $e1) => $comp);
|
||||
|
||||
$compCi = fn(string $e1, string $e2) => strtoupper(\iconv('UTF-8', 'ASCII//TRANSLIT', $e1)) <=> strtoupper(\iconv('UTF-8', 'ASCII//TRANSLIT', $e2));
|
||||
$pdo->sqliteCreateCollation('locale_cmp_ci', fn($e1, $e2) => $compCi);
|
||||
$pdo->sqliteCreateCollation('locale_cmp_ci_desc', fn($e2, $e1) => $compCi);
|
||||
}
|
||||
}
|
||||
|
||||
public static function registerPragma(PdoObject $pdo, array $pragmaList) : void
|
||||
{
|
||||
$builder = new QueryBuilder\Sql\SqliteQueryBuilder();
|
||||
|
|
|
@ -4,5 +4,7 @@ namespace Ulmus\Attribute\Obj;
|
|||
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||
class Collation {
|
||||
|
||||
public function __construct(
|
||||
public string $name = ""
|
||||
) {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Attribute\Property;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Collation {
|
||||
public function __construct(
|
||||
public string $name = ""
|
||||
) {}
|
||||
}
|
|
@ -84,8 +84,12 @@ abstract class Sql {
|
|||
return $value;
|
||||
}
|
||||
|
||||
public static function parameter($value) : string
|
||||
public static function collate(string $name) : string
|
||||
{
|
||||
if ( ! preg_match('/^[a-z0-9$_]+$/i',$name) ) {
|
||||
throw new \InvalidArgumentException(sprintf("Given identifier '%s' should contains supported characters in function name (a-Z, 0-9, $ and _)", $name));
|
||||
}
|
||||
|
||||
return static::raw(sprintf("COLLATE %s", $name));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ class OrderBy extends Fragment {
|
|||
public array $orderBy = [];
|
||||
|
||||
const SQL_TOKEN = "ORDER BY";
|
||||
const SQL_COLLATE = "COLLATE";
|
||||
|
||||
public function set(array $order) : self
|
||||
{
|
||||
|
@ -16,7 +17,7 @@ class OrderBy extends Fragment {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function add(object|string $field, ? string $direction = null) : self
|
||||
public function add(string|\Stringable $field, ? string $direction = null) : self
|
||||
{
|
||||
$this->validateFieldType($field);
|
||||
|
||||
|
@ -30,7 +31,7 @@ class OrderBy extends Fragment {
|
|||
$list = array_map(function($item) {
|
||||
list($field, $direction) = $item;
|
||||
|
||||
return $field . ( $direction ? " $direction" : "" );
|
||||
return implode(' ', array_filter([ $field , $direction ?? null ] ));
|
||||
}, $this->orderBy);
|
||||
|
||||
return $this->renderSegments([
|
||||
|
|
|
@ -260,7 +260,7 @@ class MysqlQueryBuilder extends SqlQueryBuilder
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function orderBy(string|\Stringable $field, ? string $direction = null) : self
|
||||
public function orderBy(string|\Stringable $field, null|string|\Stringable $direction = null) : self
|
||||
{
|
||||
if ( null === $orderBy = $this->getFragment(Query\OrderBy::class) ) {
|
||||
$orderBy = new Query\OrderBy();
|
||||
|
@ -272,7 +272,7 @@ class MysqlQueryBuilder extends SqlQueryBuilder
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function groupBy(string|object $field) : self
|
||||
public function groupBy(string|\Stringable $field) : self
|
||||
{
|
||||
if ( null === $groupBy = $this->getFragment(Query\GroupBy::class) ) {
|
||||
$groupBy = new Query\GroupBy();
|
||||
|
|
|
@ -548,7 +548,7 @@ class Repository implements RepositoryInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function orderBy(string|object $field, ? string $direction = null) : self
|
||||
public function orderBy(string|\Stringable $field, null|string|\Stringable $direction = null) : self
|
||||
{
|
||||
$this->queryBuilder->orderBy($field, $direction);
|
||||
|
||||
|
@ -558,7 +558,7 @@ class Repository implements RepositoryInterface
|
|||
# @UNTESTED
|
||||
public function randomizeOrder() : self
|
||||
{
|
||||
$this->queryBuilder->orderBy(Common\Sql::function('RAND', Sql::identifier('CURDATE()+0')));
|
||||
$this->queryBuilder->orderBy(Common\Sql::function('RAND', Common\Sql::identifier('CURDATE()+0')));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue