Pg field type oid: примеры (PHP)

Использование pg_field_type_oid в PHP для работы с типами PostgreSQL
Раздел: Базы данных (PostgreSQL)
pg_field_type_oid(PgSql\Result $result, int $field): int|string

Описание функции pg_field_type_oid

Функция pg_field_type_oid является частью расширения PostgreSQL (pgsql) для PHP. Она применяется для получения идентификатора объекта (OID) типа данных конкретного поля в результате выполнения SQL-запроса. OID — это внутренний числовой идентификатор типа данных в системе каталогов PostgreSQL.

Назначение функции

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

Аргументы функции

Функция принимает два аргумента:

  1. $result (ресурс) — обязательный. Ресурс результата запроса, возвращаемый функциями pg_query, pg_query_params или pg_execute.
  2. $field_number (int) — обязательный. Порядковый номер поля в результате запроса. Нумерация начинается с нуля.

Функция возвращает целое число (int), которое представляет собой OID типа поля. В случае ошибки может вернуть false.

Краткие примеры использования

Пример 1: Базовое использование

Получение OID типа для первого поля в результате.

<?
$conn = pg_connect('dbname=test user=postgres');
$result = pg_query($conn, 'SELECT 123 as number, \'text\' as value');
$oid = pg_field_type_oid($result, 0);
echo 'OID первого поля: ' . $oid;
?>
OID первого поля: 23
Пример 2: Получение OID для разных типов данных
<?
$result = pg_query($conn, 'SELECT 1::int, 3.14::float, true::bool, now()::date');
for ($i = 0; $i < pg_num_fields($result); $i++) {
    $fieldName = pg_field_name($result, $i);
    $oid = pg_field_type_oid($result, $i);
    echo "Поле {$fieldName} имеет OID: {$oid}\n";
}
?>
Поле int4 имеет OID: 23
Поле float8 имеет OID: 701
Поле bool имеет OID: 16
Поле date имеет OID: 1082

Похожие функции в PHP

Для работы с метаданными полей результата запроса в расширении pgsql существуют другие функции:

  • pg_field_type — возвращает имя типа поля (например, 'int4', 'varchar'), а не его OID. Используется, когда важно текстовое представление типа.
  • pg_field_name — получает имя поля по его номеру.
  • pg_field_num — получает номер поля по его имени.
  • pg_field_size — возвращает внутренний размер хранилища для поля.

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

Аналоги в других языках и СУБД

Python (библиотека psycopg2)

В psycopg2 тип столбца доступен через свойство type_code объекта cursor description, который является числовым кодом, аналогичным OID.

import psycopg2
conn = psycopg2.connect('dbname=test user=postgres')
cur = conn.cursor()
cur.execute('SELECT 1::int')
oid = cur.description[0].type_code
print(f'OID поля: {oid}')
cur.close()
conn.close()
OID поля: 23
JavaScript (библиотека node-postgres)

В Node.js драйвер pg предоставляет информацию о типах через свойство types объекта результата, но для получения OID требуется анализ метаданных запроса, которые не всегда доступны напрямую на клиенте.

MySQL (PHP функция)

В MySQL аналогом можно считать функцию mysqli_fetch_field_direct()->type, которая возвращает числовой идентификатор типа поля. Однако это ID типа MySQL, а не OID, и архитектура типов отличается от PostgreSQL.

<?
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$result = $mysqli->query('SELECT 1');
$field = $result->fetch_field_direct(0);
echo 'ID типа MySQL: ' . $field->type; // MYSQLI_TYPE_LONG -> 3
?>
ID типа MySQL: 3

Типичные ошибки

Ошибка 1: Неверный номер поля

Передача номера поля, выходящего за пределы количества полей в результате.

<?
$result = pg_query($conn, 'SELECT 1');
$oid = pg_field_type_oid($result, 5); // Поля с индексом 5 не существует
var_dump($oid);
?>
bool(false)
Ошибка 2: Передача неверного ресурса
<?
$not_a_result = null;
$oid = pg_field_type_oid($not_a_result, 0);
?>
Warning: pg_field_type_oid() expects parameter 1 to be resource, null given
Ошибка 3: Использование после освобождения результата
<?
$result = pg_query($conn, 'SELECT 1');
pg_free_result($result);
$oid = pg_field_type_oid($result, 0);
?>
Warning: pg_field_type_oid(): supplied resource is not a valid PostgreSQL result resource

Изменения в последних версиях PHP

Функция pg_field_type_oid не претерпела значительных изменений в поведении или сигнатуре в последних основных версиях PHP, включая PHP 8.x. Она остается стабильной частью расширения pgsql. Однако, начиная с PHP 8.1, ресурсы (resource) постепенно заменяются на объекты. Для функций PostgreSQL, включая pg_field_type_oid, это означает, что параметр $result теперь ожидает объект PgSql\Result (ранее известный как resource). Код, написанный для PHP 7.x, продолжит работу, но тип аргумента в документации указан как объект.

Расширенные примеры использования

Пример 1: Динамическое определение обработчика для типа данных

Использование OID для выбора функции форматирования вывода.

Пример php
<?
function formatFieldByOid($value, $oid) {
    switch ($oid) {
        case 23: // int4
            return number_format($value, 0, ',', ' ');
        case 25: // text
            return htmlspecialchars($value);
        case 1184: // timestamptz
            return date('d.m.Y H:i', strtotime($value));
        default:
            return $value;
    }
}

$result = pg_query($conn, 'SELECT id, name, created_at FROM users LIMIT 1');
$row = pg_fetch_assoc($result);
foreach ($row as $fieldName => $value) {
    $fieldNum = pg_field_num($result, $fieldName);
    $oid = pg_field_type_oid($result, $fieldNum);
    echo formatFieldByOid($value, $oid) . "\n";
}
?>
Пример 2: Сравнение типов полей из разных запросов
Пример php
<?
$res1 = pg_query($conn, 'SELECT 1::int as col');
$res2 = pg_query($conn, 'SELECT 2::bigint as col');

$oid1 = pg_field_type_oid($res1, 0); // 23 (int4)
$oid2 = pg_field_type_oid($res2, 0); // 20 (int8)

if ($oid1 === $oid2) {
    echo 'Типы полей идентичны';
} else {
    echo 'Типы полей различаются';
}
?>
Типы полей различаются
Пример 3: Работа с пользовательскими типами (типами ENUM)
Пример php
<?
// Предположим, что в БД существует тип mood ENUM ('sad', 'ok', 'happy')
$result = pg_query($conn, "SELECT 'happy'::mood");
$oid = pg_field_type_oid($result, 0);
echo 'OID пользовательского типа ENUM: ' . $oid . "\n";
// Можно использовать pg_typeof для получения имени типа
$typeName = pg_fetch_result($result, 0, 0);
echo 'Имя типа: ' . $typeName;
?>
OID пользовательского типа ENUM: 12345
Имя типа: happy
Пример 4: Получение массива OID для всех полей
Пример php
<?
$result = pg_query($conn, 'SELECT * FROM information_schema.tables LIMIT 0');
$oids = [];
for ($i = 0; $i < pg_num_fields($result); $i++) {
    $oids[pg_field_name($result, $i)] = pg_field_type_oid($result, $i);
}
print_r($oids);
?>
Array
(
    [table_catalog] => 25
    [table_schema] => 25
    [table_name] => 25
    ...
)

PHP pg_field_type_oid function comments

En
Pg field type oid Returns the type ID (OID) for the corresponding field number