Пакет · cdo

Определение драйвера и диалекты

CDO подстраивает свой SQL под ту базу данных, с которой действительно разговаривает. Эта страница объясняет, как он выясняет, что это за база, и каждое место, где порождаемый SQL ветвится по ней — написано по коду соединения, а не по памяти.

Проблема, которую оставляет открытой PDO

PDO::ATTR_DRIVER_NAME возвращает 'mysql' для обеих — MySQL и MariaDB. Но они расходятся в возможности, на которую CDO опирается: MariaDB ≥ 10.5 поддерживает INSERT ... RETURNING; MySQL — никогда. Считать их одинаковыми означало бы сломать путь возврата id на одной из них.

Как нормализуется драйвер

Во время подключения (applyDatabase()) CDO читает PDO::ATTR_DRIVER_NAME и для mysql инспектирует PDO::ATTR_SERVER_VERSION. Если строка версии содержит "MariaDB" (напр. "5.5.5-10.11.6-MariaDB" или "11.4.2-MariaDB"), драйвер записывается как mariadb. Нормализованное значение — одно из pgsql, mysql, mariadb, oci — кешируется и возвращается методом getDriverName().

text
ATTR_DRIVER_NAME = 'pgsql'                          → 'pgsql'
ATTR_DRIVER_NAME = 'mysql', в версии есть 'MariaDB' → 'mariadb'
ATTR_DRIVER_NAME = 'mysql', в версии нет 'MariaDB'  → 'mysql'
ATTR_DRIVER_NAME = 'oci'                            → 'oci'

Атрибуты PDO, устанавливаемые по драйверу

applyDatabase() также настраивает PDO на основе сырого драйвера:

Драйвер ATTR_EMULATE_PREPARES Обоснование
pgsql false Нативные серверные prepares
mysql true Эмулируемые prepares
oci true Эмулируемые prepares

Режим выборки по умолчанию устанавливается в PDO::FETCH_ASSOC для каждого драйвера, поэтому унаследованные fetch() / fetchAll() возвращают ассоциативные массивы, пока вы это не переопределите.

Где ветвится SQL: возврат id

insert() использует RETURNING только там, где он поддерживается, и lastInsertId() в остальных случаях:

Драйвер Стратегия insert()
pgsql INSERT … RETURNING pkfetchColumn()
mariadb INSERT … RETURNING pkfetchColumn()
mysql обычный INSERTlastInsertId()
oci обычный INSERTlastInsertId()

Ложный результат нормализуется в null — это означает «нет сгенерированного id для сообщения» (напр. INSERT в таблицу без колонки auto-increment/serial), а не ошибку. Настоящие SQL-ошибки приходят через PDOException и становятся CDOException.

RETURNING при апсерте уже

upsert() использует RETURNING только на PostgreSQL, хотя MariaDB поддерживает RETURNING для обычных вставок — MariaDB запрещает его вместе с ON DUPLICATE KEY UPDATE / INSERT IGNORE, поэтому там CDO откатывается к lastInsertId(). См. Плейсхолдеры апсерта.

Где ветвится SQL: диалект апсерта

Драйвер Игнорировать конфликты Обновить при конфликте
pgsql ON CONFLICT (cols) DO NOTHING ON CONFLICT (cols) DO UPDATE SET …
всё остальное INSERT IGNORE ON DUPLICATE KEY UPDATE …

Подстановка токенов :new / :current тоже зависит от драйвера — полная матрица в Плейсхолдерах апсерта.

Где ветвится SQL: часовой пояс

При подключении CDO устанавливает часовой пояс сессии базы данных в соответствие с PHP (date_default_timezone_get()), по драйверам:

Драйвер Инструкция
pgsql SET TIMEZONE TO '<tz>'
mysql (и MariaDB) SET time_zone = '<offset>'
oci ALTER SESSION SET TIME_ZONE = '<tz>'
прочие не реализовано — логирует предупреждение

Путь MySQL требует помощника смещения

Для MySQL/MariaDB CDO преобразует имя часового пояса PHP в числовое смещение через функцию timezoneToOffset(), которую ожидает найти в глобальной области. Она не поставляется этим пакетом — её предоставляет хост-фреймворк Winter. Вне этого фреймворка определите эквивалентную глобальную функцию (или шаг MySQL SET time_zone пропускается, когда помощник возвращает null). PostgreSQL и Oracle принимают имя часового пояса напрямую и такой зависимости не имеют.

Сводка возможностей по драйверам

Операция PostgreSQL MySQL MariaDB Oracle
insert возвращает id ✅ RETURNING ✅ lastInsertId ✅ RETURNING ⚠️ lastInsertId
insertGroup
upsert / upsertGroup
update / delete

Связанное