У меня есть данные датчика в таблице Postgres measurements
со столбцами id
, timestamp
, s0
, s1
, s2
, ...
Кроме того, есть индекс по столбцам (id, timestamp)
. Я хочу разрешить динамические математические выражения (в приведенном ниже примере: sin(s3)*0.1000/s5
) для вычисления производных значений.
SELECT
timestamp,
trunc((sin(s3) * 0.1000/s5)::numeric, 3) AS "calculated"
FROM measurements
WHERE id = 42
ORDER BY timestamp DESC
LIMIT 10000;
Очевидно, что это может привести к ошибке «деление на ноль», которая приведет к сбою запроса. Есть ли способ отловить эту ошибку и вернуть, например, NULL
для расчетного значения, в котором возникнет ошибка?
Вдохновлен
Я уже пытался определить postgres
функцию eval_numeric(sensors int[], formula text)
, которая анализирует формулу и возвращает NULL
в случае исключения. Третья строка приведенного выше оператора SQL теперь выглядит как
trunc(eval_numeric(ARRAY[s3,s5],'sin(var1)*0.1/var2'), 3) AS "calculated"
Это дает желаемое поведение, но время выполнения, сообщаемое EXPLAIN ANALYZE
, увеличивается в 20 раз (~ 20 мс -> ~ 400 мс). Есть еще идеи?
UPDATE
Динамическое выражение для оценки происходит от пользователя веб-приложения. Таким образом, приведенная выше формула является лишь примером (может потребоваться проверка отрицательного аргумента для квадратного корня). Я предпочел бы иметь общую возможность проверки ошибок и предпочел бы, чтобы в математическом выражении не было логики. Это было бы проще для конечного пользователя, и я мог бы проверить допустимую математику, например. с математическим парсером, тем самым предотвращая внедрение SQL.