- PVSM.RU - https://www.pvsm.ru -
В предыдущей статье [1] я рассказал о выходе Solid12 — версии IEM [2]-платформы для PostgreSQL. Как и обещал, рассказываем более детально о том, с чем придется столкнуться разработчикам (и с чем столкнулись мы при миграции).
Этот обзор не является исчерпывающим, скорее его нужно рассматривать как минимальную вводную для разработчика под Oracle, приступающего к работе на PostgreSQL.
Итак, вот список отличий, который мы признали наиболее значимыми:
От особенностей конкретных баз данных не всегда можно полностью абстрагироваться в прикладном коде. Нередко в командах или службах требуется сформировать и выполнить динамический SQL-запрос, вызвать хранимую процедуру и так далее. В прикладной схеме могут потребоваться триггеры, представления, ограничения или индексы, так что прикладному разработчику Oracle потребуется разобраться хотя бы в базовых свойствах PostgreSQL.
Ниже приводятся кое-какие инструкции, которые могут помочь справиться с некоторыми из описанных трудностей.
Динамическая привязка — это мощный механизм, который в некоторых случаях может заменить динамическое выполнение запросов (EXECUTE sql). Обратной стороной медали является хрупкость конструкции, отсутствие проверок во время компиляции. Компилятор не может статически проверить, ссылается ли данный символ на какой-нибудь объект базы данных.
Когда функция ссылается на символ, например на таблицу или функцию, конкретный объект будет найден по имени только во время выполнения функции. Кроме того, на этот поиск влияет содержимое переменной «search_path», а это означает, что символ может найтись в любой схеме, в зависимости от настроек текущей сессии.
Обычно это задумано не так.
Чтобы отключить динамическую привязку, мы придерживаемся двух простых правил:
Это не делает привязку статической (PostgreSQL все равно не проверяет валидность символов), но просто отключает возможность непреднамеренной привязки символа к чему-нибудь не тому.
Вот пример исходного кода функции PL/PgSQL, которая больше не страдает от динамической привязки:
-- current search_path = my_schema
create or replace function my_func(my_arg text) returns void as $$
declare v_id bigint;
begin
perform another_func(my_arg); -- same as perform my_schema.another_func(my_arg);
select id into v_id from kernel.users -- table name is qualified with kernel schema name where login = my_arg; -- the rest is skipped...
end $$ language plpgsql set search_path to my_schema;
По умолчанию функции PostgreSQL вызываются с набором разрешений текущего пользователя СУБД, подобно опции Oracle «AUTHID CURRENT_USER» (по умолчанию в Oracle действует другой режим — «AUTHID DEFINER»).
Чтобы эмулировать поведение Oracle, функция должна переопределить «security option» вот так:
create or replace function my_secure_func() returns void as $$
begin -- call here any functions available to the superuser
end $$ language plpgsql security definer; -- default is security invoker
Семантика временных таблиц в PostgreSQL существенно отличается от оракловой. Вот краткий обзор отличий:
Схема pack_temp содержит библиотеку для эмуляции временных таблиц в стиле Oracle. Нас интересуют всего две функции:
create_permanent_temp_table(table_name [, schema_name]);
drop_permanent_temp_table(table_name [, schema_name]);
Создание постоянной временной таблицы делается в два приема:
create temporary table if not exists another_temp_table ( first_name varchar, last_name varchar, date timestamp(0) with time zone, primary key(first_name, last_name) ) on commit drop;
-- create my_schema.another_temp_table select pack_temp.create_permanent_temp_table('another_temp_table', 'my_schema');
-- or create another_temp_table in the current schema -- select create_permanent_temp_table('another_temp_table');
-- don't forget to commit: PostgreSQL DDL is transactional commit;
При этом создается представление, которое ведет себя точь-в-точь как глобальная временная таблица Oracle. Удалить его можно функцией drop_permanent_temp_table.
Это наиболее досадное ограничение PostgreSQL: каждое соединение с базой данных может иметь только один открытый DataReader в каждый момент времени.
Новый запрос нельзя выполнить, пока предыдущий не будет выполнен и обработан.
Проблема регулярно всплывает в прикладных службах, LINQ-запросах и SQL-запросах во множестве разных форм. Вот несколько типичных случаев:
// было
var query = from a in DataContext.GetTable<Agent>()
where a.ID = Constants.TestAgentID select a;
// стало
var testAgentId = Constants.TestAgentID;
var query = from a in DataContext.GetTable<Agent>()
where a.ID = testAgentId select a;
// было
foreach (var langId in DataContext.GetTable<Language>().Select(x => x.ID))
{
using (LanguageService.UseLanguage(langId))
{
// do something language-specific
}
}
// стало
foreach (var langId in DataContext.GetTable<Language>().Select(x => x.ID).ToIDList())
{
using (LanguageService.UseLanguage(langId))
{
// do something language-specific
}
}
// было
var dictionary = DataContext.GetTable<CalendarDayStatus>().Where(d => dates.Contains(d.DT)) .GroupBy(g => g.DT, e => e.StatusID) .ToDictionary(k => k.Key, e => e.ToIDList());
// стало
var dictionary = DataContext.GetTable<CalendarDayStatus>() .Where(d => dates.Contains(d.DT)) .GroupBy(g => g.DT, e => e.StatusID) .ToDictionary(p => p.Key);
var dict = dictionary.ToDictionary(p => p.Key, p => p.Value.ToIDList());
К сожалению, этот вид ошибки очень сложно обнаружить статически. Поэтому каждый нетривиальный LINQ-запрос нужно тщательно протестировать, чтобы убедиться, что он не пытается открыть несколько DataReader-ов одновременно.
Мы планируем интенсивно развивать взаимодействие с командой PostgreSQL. Собственно, большинство из приведенных ограничений не выглядят непреодолимыми, возможно, мы сможем найти ресурсы для внесения соответствующих изменений в код PostgreSQL.
Мы не использовали некоторые функции, которые уже есть в PostgreSQL, например поддержку обработки геоданных, но надеемся что сможем использовать их в следующих версиях.
В любом случае, обе версии — light Solid12 и enteprise Ultimate Solid — будут развиваться параллельно, весь важный функционал будет поддерживаться в обоих вариантах поставки платформы.
Автор: Rupper
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-2/258879
Ссылки в тексте:
[1] предыдущей статье: https://habrahabr.ru/company/ultima/blog/329674/
[2] IEM: https://ru.wikipedia.org/wiki/IEM
[3] Источник: https://habrahabr.ru/post/329676/
Нажмите здесь для печати.