Pg meta data: примеры (PHP)

Использование pg_meta_data для анализа структуры таблиц PostgreSQL в PHP
Раздел: Базы данных (PostgreSQL)
pg_meta_data(PgSql\Connection $connection, string $table_name, bool $extended = false): array|false
Описание функции pg_meta_data

Функция pg_meta_data в PHP используется для получения метаинформации о таблицах в базе данных PostgreSQL. Она возвращает массив, описывающий столбцы указанной таблицы, включая их имена, типы данных, длину, атрибуты и другие свойства.

Назначение и применение

Функция применяется для динамического анализа структуры таблицы, что полезно при генерации форм, валидации данных, создании инструментов администрирования или ORM-систем. Она позволяет получить информацию о типах полей без написания прямых SQL-запросов к системным каталогам.

Аргументы функции
array pg_meta_data(PgSql\Connection $connection, string $table_name, bool $extended = false): array
  • $connection (обязательный): Объект соединения с PostgreSQL, полученный с помощью функций pg_connect() или pg_pconnect().
  • $table_name (обязательный): Имя таблицы, для которой запрашивается метаинформация. Имя может включать имя схемы (например, 'public.users').
  • $extended (опциональный): Флаг, определяющий детализацию возвращаемой информации. При значении false возвращаются основные сведения (имя, тип, длина, возможность NULL). При значении true добавляется информация о модификаторах (таких как not null, первичный ключ) и значениях по умолчанию.

Функция возвращает ассоциативный массив, где ключи - имена столбцов, а значения - массивы с их характеристиками. В случае ошибки возвращается false.

Короткие примеры использования
Пример 1: Базовое использование
<?php
$conn = pg_connect('host=localhost dbname=test user=postgres');
$meta = pg_meta_data($conn, 'users');
print_r($meta);
?>
Array
(
    [id] => Array
        (
            [type] => int4
            [len] => 4
            [not null] => 1
            [has default] => 1
        )
    [name] => Array
        (
            [type] => varchar
            [len] => 255
            [not null] => 
            [has default] => 
        )
)
Пример 2: Использование с флагом extended=true
<?php
$meta = pg_meta_data($conn, 'orders', true);
print_r($meta['order_date']);
?>
Array
(
    [type] => date
    [len] => 4
    [not null] => 1
    [has default] => 
    [array] => 
    [enum] => 
    [pkey] => 
    [default] => 
)
Пример 3: Обращение к таблице в схеме
<?php
$meta = pg_meta_data($conn, 'public.products');
?>
Похожие функции в PHP

В PHP существуют другие функции для работы с метаданными баз данных.

pg_field_info

Функция pg_field_info возвращает информацию о конкретном столбце в результате запроса. Она используется после выполнения запроса с помощью pg_query().

<?php
$result = pg_query($conn, 'SELECT * FROM users');
$info = pg_field_info($result, 0); // информация о первом столбце
?>

Функция pg_meta_data предпочтительнее для получения структуры таблицы без выполнения запроса на выборку данных, тогда как pg_field_info подходит для анализа столбцов уже выполненного запроса.

PDO::getColumnMeta

При использовании расширения PDO метод getColumnMeta предоставляет метаинформацию о столбце в результирующем наборе. Он не специфичен для PostgreSQL и работает с различными СУБД.

<?php
$stmt = $pdo->query('SELECT * FROM users');
$meta = $stmt->getColumnMeta(0);
?>

PDO является более универсальным и современным подходом, но pg_meta_data предлагает более детализированную информацию именно для PostgreSQL.

Альтернативы в других языках
Python (psycopg2)
import psycopg2
conn = psycopg2.connect('dbname=test')
cursor = conn.cursor()
cursor.execute('''
    SELECT column_name, data_type, is_nullable
    FROM information_schema.columns
    WHERE table_name = 'users'
''')
for col in cursor.fetchall():
    print(col)
('id', 'integer', 'NO')
('name', 'character varying', 'YES')

В Python аналогом является прямой запрос к системным представлениям information_schema или pg_catalog. Функции, аналогичной pg_meta_data, в psycopg2 нет.

JavaScript (Node.js, pg package)
const { Client } = require('pg');
const client = new Client();
(async () => {
    await client.connect();
    const res = await client.query(`
        SELECT column_name, data_type, is_nullable
        FROM information_schema.columns
        WHERE table_name = 'users'
    `);
    console.log(res.rows);
})();

Аналогично Python, в Node.js метаданные получают через запросы к information_schema.

MySQL (SQL запрос)
DESCRIBE users;
-- Или
SHOW COLUMNS FROM users;

В MySQL используются специальные SQL-команды, а не отдельная функция в языке программирования.

Типичные ошибки
Ошибка 1: Неверное имя таблицы или схемы
<?php
$meta = pg_meta_data($conn, 'non_existent_table');
if ($meta === false) {
    echo 'Ошибка получения метаданных. Таблица может не существовать.';
}
?>
Ошибка получения метаданных. Таблица может не существовать.
Ошибка 2: Передача неверного типа аргумента
<?php
$meta = pg_meta_data('not a connection', 'users'); // Предупреждение
?>

Это приводит к предупреждению PHP и возврату false.

Ошибка 3: Отсутствие прав доступа к таблице

Если пользователь базы данных не имеет прав на чтение таблицы, функция вернет false. Необходимо проверить привилегии.

<?php
$meta = pg_meta_data($conn, 'users');
var_dump($meta); // bool(false)
?>
Изменения в PHP 8

В PHP 8.0 изменен тип возвращаемого значения при ошибке. Раньше функция могла вернуть false или массив. Теперь в случае ошибки выбрасывается исключение типа Exception. Это соответствует общей тенденции PHP 8 к более строгой обработке ошибок.

Обновлен тип параметра $connection: теперь ожидается объект PgSql\Connection вместо ресурса (resource). Это связано с переходом на объектно-ориентированный API для расширений баз данных.

<?php
// PHP 7 (ресурс)
$conn = pg_connect(...);
// PHP 8 (объект PgSql\Connection)
$conn = pg_connect(...); // Возвращает объект PgSql\Connection
?>
Расширенные примеры
Пример 1: Генерация формы на основе метаданных
Пример php
<?php
$table = 'users';
$meta = pg_meta_data($conn, $table, true);
if ($meta) {
    echo '<form>';
    foreach ($meta as $column => $info) {
        echo '<div>';
        echo '<label>' . htmlspecialchars($column) . '</label>';
        $type = $info['type'];
        if (strpos($type, 'int') !== false) {
            echo '<input type="number" name="' . $column . '">';
        } elseif (strpos($type, 'varchar') !== false) {
            echo '<input type="text" name="' . $column . '" maxlength="' . $info['len'] . '">';
        } else {
            echo '<input type="text" name="' . $column . '">';
        }
        echo '</div>';
    }
    echo '</form>';
}
?>
Пример 2: Сравнение структуры двух таблиц
Пример php
<?php
function compareTables($conn, $table1, $table2) {
    $meta1 = pg_meta_data($conn, $table1);
    $meta2 = pg_meta_data($conn, $table2);
    $diff = [];
    foreach ($meta1 as $col => $info1) {
        if (!isset($meta2[$col])) {
            $diff['only_in_' . $table1][] = $col;
        } elseif ($info1['type'] !== $meta2[$col]['type']) {
            $diff['type_mismatch'][$col] = [$info1['type'], $meta2[$col]['type']];
        }
    }
    return $diff;
}
?>
Пример 3: Проверка обязательных полей перед вставкой
Пример php
<?php
function validateInsertData($conn, $table, $data) {
    $meta = pg_meta_data($conn, $table, true);
    $errors = [];
    foreach ($meta as $column => $info) {
        if ($info['not null'] && empty($data[$column]) && !$info['has default']) {
            $errors[] = "Поле $column обязательно для заполнения.";
        }
    }
    return $errors;
}
?>
Пример 4: Работа с составными типами данных
Пример php
<?php
// Для таблицы с полем типа point
$meta = pg_meta_data($conn, 'geo_objects', true);
print_r($meta['coordinates']);
?>
Array
(
    [type] => point
    [len] => -1
    [not null] => 
    [has default] => 
    [array] => 
    [enum] => 
    [pkey] => 
    [default] => 
)

PHP pg_meta_data function comments

En
Pg meta data Get metadata for a table