This repository has been archived by the owner on Jan 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
136 changed files
with
341 additions
and
2 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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
36 changes: 36 additions & 0 deletions
36
source/Spiral/Database/Drivers/Postgres/Schemas/PostgresIndex.php
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,36 @@ | ||
<?php | ||
/** | ||
* Spiral, Core Components | ||
* | ||
* @author Wolfy-J | ||
*/ | ||
|
||
namespace Spiral\Database\Drivers\Postgres\Schemas; | ||
|
||
use Spiral\Database\Schemas\Prototypes\AbstractIndex; | ||
|
||
class PostgresIndex extends AbstractIndex | ||
{ | ||
/** | ||
* @param string $table Table name. | ||
* @param array $schema | ||
* | ||
* @return PostgresIndex | ||
*/ | ||
public static function createInstance(string $table, array $schema): self | ||
{ | ||
$index = new self($table, $schema['indexname']); | ||
$index->type = strpos($schema['indexdef'], ' UNIQUE ') ? self::UNIQUE : self::NORMAL; | ||
|
||
if (preg_match('/\(([^)]+)\)/', $schema['indexdef'], $matches)) { | ||
$columns = explode(',', $matches[1]); | ||
|
||
foreach ($columns as $column) { | ||
//Postgres adds quotes to all columns with uppercase letters | ||
$index->columns[] = trim($column, ' "\''); | ||
} | ||
} | ||
|
||
return $index; | ||
} | ||
} |
File renamed without changes.
221 changes: 221 additions & 0 deletions
221
source/Spiral/Database/Drivers/Postgres/Schemas/PostgresTable.php
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,221 @@ | ||
<?php | ||
/** | ||
* Spiral, Core Components | ||
* | ||
* @author Wolfy-J | ||
*/ | ||
|
||
namespace Spiral\Database\Drivers\Postgres\Schemas; | ||
|
||
use Psr\Log\LoggerInterface; | ||
use Spiral\Database\Entities\AbstractHandler as Behaviour; | ||
use Spiral\Database\Schemas\Prototypes\AbstractColumn; | ||
use Spiral\Database\Schemas\Prototypes\AbstractIndex; | ||
use Spiral\Database\Schemas\Prototypes\AbstractReference; | ||
use Spiral\Database\Schemas\Prototypes\AbstractTable; | ||
|
||
|
||
class PostgresTable extends AbstractTable | ||
{ | ||
/** | ||
* Found table sequences. | ||
* | ||
* @var array | ||
*/ | ||
private $sequences = []; | ||
|
||
/** | ||
* Sequence object name usually defined only for primary keys and required by ORM to correctly | ||
* resolve inserted row id. | ||
* | ||
* @var string|null | ||
*/ | ||
private $primarySequence = null; | ||
|
||
/** | ||
* Sequence object name usually defined only for primary keys and required by ORM to correctly | ||
* resolve inserted row id. | ||
* | ||
* @return string|null | ||
*/ | ||
public function getSequence() | ||
{ | ||
return $this->primarySequence; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* SQLServer will reload schemas after successful savw. | ||
*/ | ||
public function save( | ||
int $behaviour = Behaviour::DO_ALL, | ||
LoggerInterface $logger = null, | ||
bool $reset = true | ||
) { | ||
parent::save($behaviour, $logger, $reset); | ||
|
||
if ($reset) { | ||
foreach ($this->fetchColumns() as $column) { | ||
$currentColumn = $this->current->findColumn($column->getName()); | ||
if (!empty($currentColumn) && $column->compare($currentColumn)) { | ||
//Ensure constrained columns | ||
$this->current->registerColumn($column); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function fetchColumns(): array | ||
{ | ||
//Required for constraints fetch | ||
$tableOID = $this->driver->query('SELECT oid FROM pg_class WHERE relname = ?', [ | ||
$this->getName(), | ||
])->fetchColumn(); | ||
|
||
$query = $this->driver->query( | ||
'SELECT * FROM information_schema.columns JOIN pg_type ON (pg_type.typname = columns.udt_name) WHERE table_name = ?', | ||
[$this->getName()] | ||
); | ||
|
||
$result = []; | ||
foreach ($query->bind('column_name', $name) as $schema) { | ||
if (preg_match( | ||
'/^nextval\([\'"]([a-z0-9_"]+)[\'"](?:::regclass)?\)$/i', | ||
$schema['column_default'], | ||
$matches | ||
)) { | ||
//Column is sequential | ||
$this->sequences[$name] = $matches[1]; | ||
} | ||
|
||
$result[] = PostgresColumn::createInstance( | ||
$this->getName(), | ||
$schema + ['tableOID' => $tableOID], | ||
$this->driver | ||
); | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function fetchIndexes(bool $all = false): array | ||
{ | ||
$query = "SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = ?"; | ||
|
||
$result = []; | ||
foreach ($this->driver->query($query, [$this->getName()]) as $schema) { | ||
$conType = $this->driver->query( | ||
'SELECT contype FROM pg_constraint WHERE conname = ?', | ||
[$schema['indexname']] | ||
)->fetchColumn(); | ||
|
||
if ($conType == 'p') { | ||
//Skipping primary keys | ||
continue; | ||
} | ||
|
||
$result[] = PostgresIndex::createInstance($this->getName(), $schema); | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function fetchReferences(): array | ||
{ | ||
//Mindblowing | ||
$query = 'SELECT tc.constraint_name, tc.table_name, kcu.column_name, rc.update_rule, ' | ||
. 'rc.delete_rule, ccu.table_name AS foreign_table_name, ' | ||
. "ccu.column_name AS foreign_column_name\n" | ||
. "FROM information_schema.table_constraints AS tc\n" | ||
. "JOIN information_schema.key_column_usage AS kcu\n" | ||
. " ON tc.constraint_name = kcu.constraint_name\n" | ||
. "JOIN information_schema.constraint_column_usage AS ccu\n" | ||
. " ON ccu.constraint_name = tc.constraint_name\n" | ||
. "JOIN information_schema.referential_constraints AS rc\n" | ||
. " ON rc.constraint_name = tc.constraint_name\n" | ||
. "WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = ?"; | ||
|
||
$result = []; | ||
|
||
foreach ($this->driver->query($query, [$this->getName()]) as $schema) { | ||
$result[] = PostgresReference::createInstance( | ||
$this->getName(), | ||
$this->getPrefix(), | ||
$schema | ||
); | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function fetchPrimaryKeys(): array | ||
{ | ||
$query = "SELECT * FROM pg_indexes WHERE schemaname = 'public' AND tablename = ?"; | ||
|
||
foreach ($this->driver->query($query, [$this->getName()]) as $schema) { | ||
$conType = $this->driver->query( | ||
'SELECT contype FROM pg_constraint WHERE conname = ?', | ||
[$schema['indexname']] | ||
)->fetchColumn(); | ||
|
||
if ($conType != 'p') { | ||
//Skipping primary keys | ||
continue; | ||
} | ||
|
||
//To simplify definitions | ||
$index = PostgresIndex::createInstance($this->getName(), $schema); | ||
|
||
if (is_array($this->primarySequence) && count($index->getColumns()) === 1) { | ||
$column = $index->getColumns()[0]; | ||
|
||
if (isset($this->sequences[$column])) { | ||
//We found our primary sequence | ||
$this->primarySequence = $this->sequences[$column]; | ||
} | ||
} | ||
|
||
return $index->getColumns(); | ||
} | ||
|
||
return []; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function createColumn(string $name): AbstractColumn | ||
{ | ||
return new PostgresColumn($this->getName(), $name, $this->driver->getTimezone()); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function createIndex(string $name): AbstractIndex | ||
{ | ||
return new PostgresIndex($this->getName(), $name); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function createForeign(string $name): AbstractReference | ||
{ | ||
return new PostgresReference($this->getName(), $this->getPrefix(), $name); | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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,65 @@ | ||
<?php | ||
/** | ||
* Spiral Framework. | ||
* | ||
* @license MIT | ||
* @author Anton Titov (Wolfy-J) | ||
*/ | ||
|
||
namespace Spiral\Database\Injections; | ||
|
||
/** | ||
* Default implementation of SQLFragmentInterface, provides ability to inject custom SQL code into | ||
* query builders. Usually used to mock database specific functions. | ||
* | ||
* Example: ...->where('time_created', '>', new SQLFragment("NOW()")); | ||
*/ | ||
class Fragment implements FragmentInterface | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
protected $statement = null; | ||
|
||
/** | ||
* @param string $statement | ||
*/ | ||
public function __construct(string $statement) | ||
{ | ||
$this->statement = $statement; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function sqlStatement(): string | ||
{ | ||
return $this->statement; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function __toString(): string | ||
{ | ||
return $this->sqlStatement(); | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function __debugInfo() | ||
{ | ||
return ['statement' => $this->sqlStatement()]; | ||
} | ||
|
||
/** | ||
* @param array $an_array | ||
* | ||
* @return Fragment | ||
*/ | ||
public static function __set_state(array $an_array): Fragment | ||
{ | ||
return new static($an_array['statement']); | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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,18 @@ | ||
<?php | ||
/** | ||
* Spiral Framework, SpiralScout LLC. | ||
* | ||
* @author Anton Titov (Wolfy-J) | ||
*/ | ||
define('SPIRAL_INITIAL_TIME', microtime(true)); | ||
|
||
error_reporting(E_ALL | E_STRICT); | ||
ini_set('display_errors', true); | ||
mb_internal_encoding('UTF-8'); | ||
|
||
//Composer | ||
require dirname(__DIR__) . '/vendor/autoload.php'; | ||
|
||
//File component fixtures | ||
define('FIXTURE_DIRECTORY', __DIR__ . '/Files/fixtures/'); | ||
define('ENABLE_PROFILING', getenv('PROFILING') ?? false); |