Используя Postgres 11.5, я смотрю на CREATE DOMAIN
со вчерашнего дня и хотел бы уточнить, как они могут / не могут помочь с параметрами функции. В идеале я хотел бы использовать домен для простого просмотра входных параметров, но с полезным ответом об ошибке. В качестве примера я использую простой пример, который блокирует пустые и пустые строки:
CREATE DOMAIN text_not_empty AS
text
NOT NULL
CHECK (value <> '');
Я опробовал это как тип поля для таблицы, и это здорово. Когда мы не разрешаем пустые строки, это кажется простым способом реализации ограничения без отдельного правила или триггера. Я надеюсь получить аналогичные преимущества по параметрам функции. Однако с функциями нам действительно нужны четкие сообщения об ошибках, так как вызывающий может быть из Node или из какой-либо другой среды.
В качестве примера, вот фиктивная функция, которая требует строку, используя явную проверку на входе:
CREATE OR REPLACE FUNCTION api.test_this_function(in_text text)
RETURNS int
LANGUAGE plpgsql
AS $function$
BEGIN
IF in_text = '' THEN
RAISE EXCEPTION USING
message = 'Input text must be supplied',
detail = 'Deets',
hint = 'Supply a search string',
errcode = 'KC123'; -- Custom code
END IF;
RETURN 1;
END;
$function$
Это отлично работает, но я надеюсь, что домен может упростить такие случаи. Насколько я могу судить, домен не улучшит , так как у функции никогда не будет возможности получить ошибку. Если я прочитал документы и правильно понял мои эксперименты, вы можете только RAISE
в пределах a BEGIN...END
блока. Если да, то как люди рекомендуют проверять исходные данные? И я упускаю возможность с доменами?
Чтобы вывести sh из того, на чем я основываю свои впечатления, вот функция, которая использует проверенный на основе домена, а также (глупый) пользовательский check:
CREATE OR REPLACE FUNCTION api.domain_test(in_text text_not_empty)
RETURNS timestamptz
AS $BODY$
BEGIN
IF in_text = 'foo' THEN
RAISE EXCEPTION USING
message = 'Invalid search string',
hint = 'Supply a search string other than ''foo''.',
errcode = 'KC123'; -- Custom code
END IF;
RETURN now();
END;
$BODY$
LANGUAGE plpgsql;
Таким образом, он не должен работать ни с одним параметром, с нулевым параметром, пустой строкой или строкой 'foo'. В противном случае он должен вернуть метку времени. Я опробовал эти пять случаев, показанных здесь:
select * from domain_test(); -- 1 : Fails to reach the method.
select * from domain_test(null); -- 2 : Fails before entering method.
select * from domain_test(''); -- 3 : Fails before entering method.
select * from domain_test('foo'); -- 4 : Fails on custom exception.
select * from domain_test('a'); -- 5 : Succeeds.
Я обрисовал, как далеко каждое из этих утверждений проходит через функцию. Диаграмма не более понятна, чем код, но иногда я нахожу полезным попытаться сделать диаграмму, просто чтобы посмотреть, есть ли у меня все части.
Я не спрашиваю конкретизировать c вопрос кода, но было бы очень полезно, если бы кто-то мог подтвердить, что моя модель того, как ошибки улавливаются и обрабатываются, является правильной и полной. Как только я пойму, как Postgres «думает» об этом, мне будет легче рассуждать об этом тоже.
null
и пустые строковые регистры никогда не попадают в блок BEGIN
, поэтому, похоже, нет способа использовать RAISE
для настройки message
, hint
и т. Д. c. Есть ли глобальный обработчик ошибок или более широкая система catch
, которую я пропускаю?
Относительно ORM
wildplasser предложил несколько комментариев об ORM и стратегиях, которые дают понять, что я не сделал не могу объяснить фон здесь. Я не хотел увязывать вопрос более подробно, но я полагаю, что добавлю некоторые пояснения.
Мы не собираемся использовать ORM. Кажется, что это добавляет другой уровень модели / абстракции, чтобы помочь людям привыкнуть к другому языку. Для меня это просто сложность, от которой я ничего не получаю, в данном случае. Я предпочел бы писать запросы прямо SQL без большого количества строительных лесов. Идея состоит в том, чтобы вывести sh логику запроса / SQL в Postgres. Тогда есть одно место для логики c.
План состоит в том, чтобы сделать наш API запросов PG серией функций с определенными входами / выходами. Я могу захватить или сохранить эти детали, используя pg_proc
, information_schema.parameters
и пользовательскую таблицу для определения правил параметров (разрешенные / исключенные значения, серии или диапазоны). Это большое количество лесов должно помочь, поскольку его довольно легко механизировать. Используя данные ввода / вывода, я могу автоматически генерировать объявления ввода / вывода, проверять код (над чем я здесь работаю), документацию и контрольные примеры. Фактическое тело запроса? Я напишу это от руки. Написание умного построителя запросов, который вычисляет все мои joins
et c.? Postgres лучше в этом сейчас, когда я когда-нибудь буду ... огромной задачей, я бы сделал дерьмовую работу. Таким образом, я могу написать тело запроса вручную, передать его планировщику / оптимизатору PG и настроить при необходимости. Он находится в чёрном ящике, поэтому внешние клиенты не пострадают от внутренних изменений.
Уровень HTTP API будет написан на двух языках для начала, возможно, с большим количеством языков, вероятно, с большим количеством диалектов. Затем Узел и др. c. инструменты могут обрабатывать вызовы маршрутизации и функций в своей собственной форме. последнее , которое я хочу сделать, - это вынести sh реализацию логики запросов c в избыточные реализации на разных языках. Кошмар на стольких уровнях. Для записи, функции будут в основном RETURN TABLE
, определенные в строке или через CREATE TYPE
.