Дата последнего изменения: 12.07.2024
Модули из Битрикс24.Маркет будут работать. В этом маркетплейсе размещаются модули, работающие на REST методах и напрямую к БД не обращаются.
Модули из Маркетплейс 1С-Битрикс могут не заработать.
Если модуль сделан на Bitrix ORM то он не потребует доработок и заработает сразу. Если используемый модуль старый, либо написан не на ядре D7, то вероятность что он отвалится высока.
Если модуль написан на D7, но в нём используются прямые запросы к СУБД, какие-то специфичные функции, то он не заработает. В этом случае рекомендуется обратиться к разработчикам модуля для внесения ими изменений в код.
Разработчикам модулей следует адаптировать свои модули по рекомендациям ниже.
Для квотирования идентификаторов в Postgres используются двойные кавычки.
Все неквотированные идентификаторы сначала преобразуются к НИЖНЕМУ регистру, а потом ищутся в метаданных базы.
Для совместимости к кодом «1С-Битрикс: Управление сайтом» в методе fetch ВСЕ колонки преобразуются к верхнему регистру.
Поэтому, если создана табличка:
create table test (ID int)то по факту будет создана табличка test с колонкой id в нижнем регистре.
При выборке «из 1С-Битрикс: Управление сайтом»:
$rs = $DB->Query('SELECT ID from test');
Неквотированный ID будет сначала преобразован в нижний регистр, найден в метаданных и запрос выполнится.
Вот пример неправильного запроса:$rs = $DB->Query('SELECT "ID" from test');
При выборке данных:
$ar = $rs->Fetch();
Метод Fetch автоматически преобразует колонку id в ID.
Если идентификатор нужно квотировать, то воспользуйтесь методом quote (SqlHelper или CDatabase). Для MySQL с регистром ничего делаться не будет, а вот для PostgresSQL идентификатор сначала будет приведён к нижнему регистру, а потом обрамлён двойными кавычками. Например:
Код$sql = 'SELECT ' . $DB->quote('ID') . ' from ' . $DB->quote('test');
для MySql сформирует строку:
SELECT `ID` from `test`
а для Postgres:
SELECT "id" from "test"
Это будет рабочим кодом для обеих баз данных.
|
В MySql имена индексов «локальные» по отношению к таблице и вполне возможна ситуация когда разные индексы у разных таблиц называются одинаково.
CREATE TABLE author (id int, name varchar(50), primary key (id), key ix_search(name)); CREATE TABLE book (id int, title varchar(50), primary key (id), key ix_search(title));
В PostgreSQL имена индексов должны быть уникальны в рамках схемы данных. Поэтому рекомендуется «составлять» имена индексов для удобства последующих манипуляций из:
$cd mymodule $mkdir install/db/pgsql $cp install/mysql/uninstall.sql install/pgsql/uninstall.sql $php -f ../perfmon/tools/mysql_to_pgsql.php -- install/mysql/install.sql > install/pgsql/install.sql
Использование обратных кавычек для экранирования идентификаторов в MySql не подходит для PostgreSQL.
Такие использования необходимо переписать с использованием методов CDatabase::quote
или SqlHelper::quote
или убрать как ненужное/избыточное. При этом необходимо помнить, что названия таблиц всегда в нижнем регистре, а названия столбцов в верхнем.
В отличие от MySql в PostgresQL не допускается использование двойных кавычек для строковых литералов. Необходимо заменить их на одиночные кавычки.
Также MySql и PostgreSQL имеют различие в интерпретации обратных слешей в строковых литералах.
Например, запрос:
select '\Bitrix'
в MySql вернет "Bitrix"
, а в PostgreSQL — "\Bitrix"
.
А запрос:
select '\\Bitrix'
в MySql вернет "\Bitrix"
, а в PostgreSQL — "\\Bitrix"
.
Чтобы избежать этого, используйте функцию ForSql (SqlHelper или CDatabase):
$rs = $DB->Query("SELECT '" . $DB->ForSql("\\Bitrix") . "'")
Для обеих баз данных запрос вернет "\Bitrix"
.
|
Перепишите с прямых запросов на методы SqlHelper.
$sql = 'INSERT IGNORE INTO b_user_group (USER_ID, GROUP_ID, DATE_ACTIVE_FROM, DATE_ACTIVE_TO) VALUES (...)'; $sql = 'INSERT IGNORE INTO b_user_access_check (USER_ID, PROVIDER_ID) SELECT ...';
Замените на:
$connection = \Bitrix\Main\Application::getConnection(); $helper = $connection->getSqlHelper(); $sql = $helper->getInsertIgnore("b_user_group", "(USER_ID, GROUP_ID, DATE_ACTIVE_FROM, DATE_ACTIVE_TO)", "VALUES (...)"); $sql = $helper->getInsertIgnore("b_user_access_check", "(USER_ID, PROVIDER_ID)", "SELECT ...");
Различия в CDatabase::PrepareInsert и SqlHelper::prepareInsert
UPDATE IGNOREАналогичного по логике выполнения запроса в PostgreSQL нет. В принципе идея обновления значений первичного или альтернативного ключа не очень хорошая. Но запрос можно заменить на два. Это не вполне соответствует исходной логике, но обе БД будут вести себя одинаково.
INSERT IGNORE INTO ... SELECT ... WHERE DELETE FROM ... WHEREREPLACE INTO
Перепишите с прямых запросов на методы SqlHelper
$sql = 'REPLACE INTO b_module_table (KEY_ID, DATA) VALUES (...)';
Измените на:
$connection = \Bitrix\Main\Application::getConnection(); $helper = $connection->getSqlHelper(); $update = [ 'KEY_ID' => 1, 'DATA' => 'a', ]; $merge = $helper->prepareMerge('b_module_table', ['KEY_ID'], $update, $update); if ($merge[0]) { $connection->query($merge[0]); } //or another helper method //$update - is a row in a rows array foreach ($helper->prepareMergeMultiple('b_module_table', ['KEY_ID'], [$update]) as $sql) { $connection->query($sql); }
Различия в CDatabase::PrepareInsert и SqlHelper::prepareInsert
DELETE ... LIMITПерепишите с прямых запросов на методы SqlHelper:
$sql = 'DELETE FROM b_test WHERE ACTIVE = 'N' ORDER BY TIMESTAMP_X ASC LIMIT 50';
Измените на:
$connection = \Bitrix\Main\Application::getConnection(); $helper = $connection->getSqlHelper(); $sql = $helper->prepareDeleteLimit('b_test', ['ID'], "ACTIVE = 'N'", ['TIMESTAMP_X' => 'ASC'], 50);
С этими запросами нужно быть осторожными, они очень специфичны. Рекомендуется их переписать.
Код, использующий эти классы, также требует внимания.
CDatabase::Add
в табличку без автоинкремента:
$DB->Add("b_iblock_fields", $arAdd, array("DEFAULT_VALUE"));
Перепишите на прямой запрос:
$arInsert = $DB->PrepareInsert("b_iblock_fields", $arAdd); $DB->Query("INSERT INTO b_iblock_fields (".$arInsert[0].") VALUES (".$arInsert[1].")");
Поэтому в методы хеспера передавайте объект даты/времени созданный методом \Bitrix\Main\Type\DateTime::createFromUserTime. Например:
$fields = [ 'DATE_REGISTER' => '01.01.2023 00:00:00', ]; print_r($DB->PrepareInsert('b_user', $fields)); $fields = [ 'DATE_REGISTER' => new \Bitrix\Main\Type\DateTime('01.01.2023 00:00:00'), ]; print_r(\Bitrix\Main\Application::getConnection()->getSqlHelper()->prepareInsert('b_user', $fields)); $fields = [ 'DATE_REGISTER' => \Bitrix\Main\Type\DateTime::createFromUserTime('01.01.2023 00:00:00'), ]; print_r(\Bitrix\Main\Application::getConnection()->getSqlHelper()->prepareInsert('b_user', $fields));
Выведет
Array ( [0] => `DATE_REGISTER` [1] => DATE_ADD('2023-01-01 00:00:00', INTERVAL 3600 SECOND) ) Array ( [0] => `DATE_REGISTER` [1] => '2023-01-01 00:00:00' [2] => Array ( ) ) Array ( [0] => `DATE_REGISTER` [1] => '2023-01-01 01:00:00' [2] => Array ( ) + −)
В PostgreSQL не допускается для строковых литералов. Необходимо менять на одинарные кавычки.