%PDF- %PDF-
| Direktori : /www/varak.net/losik.varak.net/vendor/dibi/dibi/src/Dibi/Drivers/ |
| Current File : /www/varak.net/losik.varak.net/vendor/dibi/dibi/src/Dibi/Drivers/PostgreReflector.php |
<?php
/**
* This file is part of the Dibi, smart database abstraction layer (https://dibiphp.com)
* Copyright (c) 2005 David Grudl (https://davidgrudl.com)
*/
declare(strict_types=1);
namespace Dibi\Drivers;
use Dibi;
/**
* The reflector for PostgreSQL database.
*/
class PostgreReflector implements Dibi\Reflector
{
use Dibi\Strict;
/** @var Dibi\Driver */
private $driver;
/** @var string */
private $version;
public function __construct(Dibi\Driver $driver, string $version)
{
$this->driver = $driver;
$this->version = $version;
}
/**
* Returns list of tables.
*/
public function getTables(): array
{
$query = "
SELECT
table_name AS name,
CASE table_type
WHEN 'VIEW' THEN 1
ELSE 0
END AS view
FROM
information_schema.tables
WHERE
table_schema = ANY (current_schemas(false))";
if ($this->version >= 9.3) {
$query .= '
UNION ALL
SELECT
matviewname, 1
FROM
pg_matviews
WHERE
schemaname = ANY (current_schemas(false))';
}
$res = $this->driver->query($query);
$tables = [];
while ($row = $res->fetch(true)) {
$tables[] = $row;
}
return $tables;
}
/**
* Returns metadata for all columns in a table.
*/
public function getColumns(string $table): array
{
$_table = $this->driver->escapeText($this->driver->escapeIdentifier($table));
$res = $this->driver->query("
SELECT indkey
FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid AND pg_index.indisprimary
WHERE pg_class.oid = $_table::regclass
");
$primary = (int) $res->fetch(true)['indkey'];
$res = $this->driver->query("
SELECT *
FROM information_schema.columns c
JOIN pg_class ON pg_class.relname = c.table_name
JOIN pg_namespace nsp ON nsp.oid = pg_class.relnamespace AND nsp.nspname = c.table_schema
WHERE pg_class.oid = $_table::regclass
ORDER BY c.ordinal_position
");
if (!$res->getRowCount()) {
$res = $this->driver->query("
SELECT
a.attname AS column_name,
pg_type.typname AS udt_name,
a.attlen AS numeric_precision,
a.atttypmod-4 AS character_maximum_length,
NOT a.attnotnull AS is_nullable,
a.attnum AS ordinal_position,
pg_get_expr(adef.adbin, adef.adrelid) AS column_default
FROM
pg_attribute a
JOIN pg_type ON a.atttypid = pg_type.oid
JOIN pg_class cls ON a.attrelid = cls.oid
LEFT JOIN pg_attrdef adef ON adef.adnum = a.attnum AND adef.adrelid = a.attrelid
WHERE
cls.relkind IN ('r', 'v', 'mv')
AND a.attrelid = $_table::regclass
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY ordinal_position
");
}
$columns = [];
while ($row = $res->fetch(true)) {
$size = (int) max($row['character_maximum_length'], $row['numeric_precision']);
$columns[] = [
'name' => $row['column_name'],
'table' => $table,
'nativetype' => strtoupper($row['udt_name']),
'size' => $size > 0 ? $size : null,
'nullable' => $row['is_nullable'] === 'YES' || $row['is_nullable'] === 't' || $row['is_nullable'] === true,
'default' => $row['column_default'],
'autoincrement' => (int) $row['ordinal_position'] === $primary && substr($row['column_default'] ?? '', 0, 7) === 'nextval',
'vendor' => $row,
];
}
return $columns;
}
/**
* Returns metadata for all indexes in a table.
*/
public function getIndexes(string $table): array
{
$_table = $this->driver->escapeText($this->driver->escapeIdentifier($table));
$res = $this->driver->query("
SELECT
a.attnum AS ordinal_position,
a.attname AS column_name
FROM
pg_attribute a
JOIN pg_class cls ON a.attrelid = cls.oid
WHERE
a.attrelid = $_table::regclass
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY ordinal_position
");
$columns = [];
while ($row = $res->fetch(true)) {
$columns[$row['ordinal_position']] = $row['column_name'];
}
$res = $this->driver->query("
SELECT pg_class2.relname, indisunique, indisprimary, indkey
FROM pg_class
LEFT JOIN pg_index on pg_class.oid = pg_index.indrelid
INNER JOIN pg_class as pg_class2 on pg_class2.oid = pg_index.indexrelid
WHERE pg_class.oid = $_table::regclass
");
$indexes = [];
while ($row = $res->fetch(true)) {
$indexes[$row['relname']]['name'] = $row['relname'];
$indexes[$row['relname']]['unique'] = $row['indisunique'] === 't' || $row['indisunique'] === true;
$indexes[$row['relname']]['primary'] = $row['indisprimary'] === 't' || $row['indisprimary'] === true;
$indexes[$row['relname']]['columns'] = [];
foreach (explode(' ', $row['indkey']) as $index) {
if (isset($columns[$index])) {
$indexes[$row['relname']]['columns'][] = $columns[$index];
}
}
}
return array_values($indexes);
}
/**
* Returns metadata for all foreign keys in a table.
*/
public function getForeignKeys(string $table): array
{
$_table = $this->driver->escapeText($this->driver->escapeIdentifier($table));
$res = $this->driver->query("
SELECT
c.conname AS name,
lt.attname AS local,
c.confrelid::regclass AS table,
ft.attname AS foreign,
CASE c.confupdtype
WHEN 'a' THEN 'NO ACTION'
WHEN 'r' THEN 'RESTRICT'
WHEN 'c' THEN 'CASCADE'
WHEN 'n' THEN 'SET NULL'
WHEN 'd' THEN 'SET DEFAULT'
ELSE 'UNKNOWN'
END AS \"onUpdate\",
CASE c.confdeltype
WHEN 'a' THEN 'NO ACTION'
WHEN 'r' THEN 'RESTRICT'
WHEN 'c' THEN 'CASCADE'
WHEN 'n' THEN 'SET NULL'
WHEN 'd' THEN 'SET DEFAULT'
ELSE 'UNKNOWN'
END AS \"onDelete\",
c.conkey,
lt.attnum AS lnum,
c.confkey,
ft.attnum AS fnum
FROM
pg_constraint c
JOIN pg_attribute lt ON c.conrelid = lt.attrelid AND lt.attnum = ANY (c.conkey)
JOIN pg_attribute ft ON c.confrelid = ft.attrelid AND ft.attnum = ANY (c.confkey)
WHERE
c.contype = 'f'
AND
c.conrelid = $_table::regclass
");
$fKeys = $references = [];
while ($row = $res->fetch(true)) {
if (!isset($fKeys[$row['name']])) {
$fKeys[$row['name']] = [
'name' => $row['name'],
'table' => $row['table'],
'local' => [],
'foreign' => [],
'onUpdate' => $row['onUpdate'],
'onDelete' => $row['onDelete'],
];
$l = explode(',', trim($row['conkey'], '{}'));
$f = explode(',', trim($row['confkey'], '{}'));
$references[$row['name']] = array_combine($l, $f);
}
if (
isset($references[$row['name']][$row['lnum']])
&& $references[$row['name']][$row['lnum']] === $row['fnum']
) {
$fKeys[$row['name']]['local'][] = $row['local'];
$fKeys[$row['name']]['foreign'][] = $row['foreign'];
}
}
return $fKeys;
}
}