Aug 16, 2008 20:34
Понадобилось мне тут написать для базы данных функцию, выполняемую по триггеру при вставке. Написал на PL/PGSQL, не проблема. Сложности начались, когда я попытался сделать её универсальной. Ну, то есть таблицы разные, названия полей разные (я в курсе, что можно их делать одинаковыми, но такое ограничение на БД нам накладывать весьма нежелательно), а функция чтобы выполнялась одна. Ладно, в триггере на каждую таблицу можно передавать в функцию имена полей в качестве параметров. Значение этих полей можно вытаскивать запросом из таблицы. Это если триггер запускается после вставки. А если до? В таблице этих данных ещё нет. Правда, триггер благородно передаёт их в функцию в виде системной переменной.
Вот тут закавыка. Имеем системную переменную NEW типа record, это вроде ассоциативного массива, т.е. массива, поля в котором не пронумерованы, а поименованы. Имеем поле с именем kod. Как мы получаем его значение? Правильно, NEW.kod. Но ведь в другой таблице оно может называться как-нибудь по-другому! Это название мы получаем в параметре kod_name. Что делаем? Пишем NEW[kod_name] - а вот фиг там! Не работает! Нет такой конструкции в PL/PGSQL, нет оператора разыменования! То есть вообще нет.
Возникает мысль, что можно пойти извращённым путём - засунуть строку NEW во временную таблицу (INSERT NEW.* INTO temp_table) и считать оттуда нужное поле запросом, благо текст запроса можно собрать примерно таким образом 'SELECT '||kod_name||' FROM temp_table' - сюда значение параметра прекрасно подставится. Не я первый такой хитрый, страждущие уже нашли такое решение, а я нашёл их в Интернете - и заодно узнал, почему такое замечательное извращение тоже не работает. Оказывается, такой INSERT работает сугубо в PostgreSQL 8.0-8.1, но не в семёрке (а у нас 7.4 и поменять её нельзя), и уже в версии 8.2 эта возможность перекрыта.
Я не говорю, что PostgreSQL разрабатывают враги человечества. Но они явно не сочувствуют тем, кто пытается программировать под эту БД на родном скриптовом языке. "Юзайте для своих триггеров C или Perl!" - как будто говорят он. Не дурак, намёк понял. Но обошёлся без таких ужасов, переложив часть работы на клиентскую часть приложения. Некрасиво, но не строить же вавилонский зиккурат, чтобы достать бананы с потолка.
Между тем подумалось: "Программист должен быть прежде всего сам запрограммирован" и "Программировать можно научить даже обезьяну. И научим!". Что здесь марксизм, а что мицголизм - разбирайтесь сами.
программирование,
pl/pgsql