39.11. СовеÑÑ Ð¿Ð¾ ÑазÑабоÑке на PL/pgSQL
ХоÑоÑий ÑпоÑоб ÑазÑабаÑÑваÑÑ Ð½Ð° PL/pgSQL заклÑÑаеÑÑÑ Ð² Ñом, ÑÑÐ¾Ð±Ñ Ð² одном окне Ñ ÑекÑÑовÑм ÑедакÑоÑом по вÑбоÑÑ ÑоздаваÑÑ ÑекÑÑÑ ÑÑнкÑий, а в дÑÑгом окне Ñ psql загÑÑжаÑÑ Ð¸ ÑеÑÑиÑоваÑÑ ÑÑи ÑÑнкÑии. Ð Ñаком ÑлÑÑае Ñдобно запиÑÑваÑÑ ÑÑнкÑиÑ, иÑполÑзÑÑ CREATE OR REPLACE FUNCTION. Таким обÑазом, можно легко загÑÑзиÑÑ Ñайл Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑнкÑии. ÐапÑимеÑ:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
....
$$ LANGUAGE plpgsql;Ð psql, можно загÑÑзиÑÑ Ð¸Ð»Ð¸ пеÑезагÑÑзиÑÑ Ñакой Ñайл опÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÑÑнкÑии, вÑполнив:
\i filename.sql
а заÑем ÑÑÐ°Ð·Ñ Ð²ÑполнÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL Ð´Ð»Ñ ÑеÑÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑÑнкÑии.
ÐÑÑ Ð¾Ð´Ð¸Ð½ Ñ Ð¾ÑоÑий ÑпоÑоб ÑазÑабаÑÑваÑÑ Ð½Ð° PL/pgSQL ÑвÑзан Ñ Ð¸ÑполÑзованием GUI инÑÑÑÑменÑов, облегÑаÑÑÐ¸Ñ ÑазÑабоÑÐºÑ Ð½Ð° пÑоÑедÑÑном ÑзÑке. Ðдин из пÑимеÑов Ñакого инÑÑÑÑменÑа pgAdmin, Ñ Ð¾ÑÑ ÐµÑÑÑ Ð¸ дÑÑгие. Такие инÑÑÑÑменÑÑ ÑаÑÑо пÑедоÑÑавлÑÑÑ ÑдобнÑе возможноÑÑи, Ñакие как ÑкÑаниÑование одинаÑнÑÑ ÐºÐ°Ð²ÑÑек, оÑладка и повÑоÑное Ñоздание ÑÑнкÑий.
39.11.1. ÐбÑабоÑка кавÑÑек
Ðод ÑÑнкÑии на PL/pgSQL ÑказÑваеÑÑÑ Ð² команде CREATE FUNCTION в виде ÑÑÑоки. ÐÑли запиÑÑваÑÑ ÑÑÑÐ¾ÐºÑ ÐºÐ°Ðº обÑÑно, внÑÑÑи одинаÑнÑÑ
кавÑÑек, Ñо лÑбой Ñимвол одинаÑной кавÑÑки должен дÑблиÑоваÑÑÑÑ, Ñак же как и должен дÑблиÑоваÑÑÑÑ ÐºÐ°Ð¶Ð´Ñй знак обÑаÑной коÑой ÑеÑÑÑ (еÑли иÑполÑзÑеÑÑÑ ÑинÑакÑÐ¸Ñ Ñ ÑкÑаниÑованием в ÑÑÑокаÑ
). ÐÑблиÑование кавÑÑек в лÑÑÑем ÑлÑÑае ÑÑомиÑелÑно, а в более ÑложнÑÑ
ÑлÑÑаÑÑ
код Ð¼Ð¾Ð¶ÐµÑ ÑÑаÑÑ ÑовеÑÑенно непонÑÑнÑм, Ñак как легко Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾ÑÑебоваÑÑÑÑ ÑеÑÑÑе или более идÑÑиÑ
подÑÑд кавÑÑек. ÐмеÑÑо ÑÑого пÑи Ñоздании Ñела ÑÑнкÑии ÑекомендÑеÑÑÑ Ð¸ÑполÑзоваÑÑ Ð·Ð½Ð°ÐºÐ¸ доллаÑа в каÑеÑÑве кавÑÑек (Ñм. ÐодÑаздел 4.1.2.4). ÐÑи Ñаком подÑ
оде никогда не поÑÑебÑеÑÑÑ Ð´ÑблиÑоваÑÑ ÐºÐ°Ð²ÑÑки, но пÑидÑÑÑÑ Ð¿Ð¾Ð·Ð°Ð±Ð¾ÑиÑÑÑÑ Ð¾ Ñом, ÑÑÐ¾Ð±Ñ Ð¸Ð¼ÐµÑÑ ÑазнÑе доллаÑовÑе ÑазделиÑели Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑÑÐ¾Ð²Ð½Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾ÑÑи. ÐапÑимеÑ, ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ CREATE FUNCTION можно запиÑаÑÑ Ñак:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$
....
$PROC$ LANGUAGE plpgsql; ÐнÑÑÑи можно иÑполÑзоваÑÑ ÐºÐ°Ð²ÑÑки Ð´Ð»Ñ Ð¿ÑоÑÑÑÑ
ÑекÑÑовÑÑ
ÑÑÑок и $$ Ð´Ð»Ñ ÑазгÑаниÑÐµÐ½Ð¸Ñ ÑÑагменÑов SQL-командÑ, ÑобиÑаемой из оÑделÑнÑÑ
ÑÑÑок. ÐÑли нÑжно взÑÑÑ Ð² кавÑÑки ÑекÑÑ, коÑоÑÑй вклÑÑÐ°ÐµÑ $$, можно иÑполÑзоваÑÑ $Q$, и Ñак далее.
СледÑÑÑÐ°Ñ ÑаблиÑа показÑваеÑ, как пÑименÑÑÑÑÑ Ð·Ð½Ð°ÐºÐ¸ кавÑÑек, еÑли не иÑполÑзÑеÑÑÑ ÑкÑаниÑование доллаÑами. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾ пÑи пеÑеводе кода, не иÑполÑзÑÑÑего ÑкÑаниÑование знаками доллаÑа, в неÑÑо более понÑÑное.
- 1 кавÑÑка
РнаÑале и конÑе Ñела ÑÑнкÑии, напÑимеÑ:
CREATE FUNCTION foo() RETURNS integer AS ' .... ' LANGUAGE plpgsql;ÐнÑÑÑи Ñакой ÑÑнкÑии лÑÐ±Ð°Ñ ÐºÐ°Ð²ÑÑка должна дÑблиÑоваÑÑÑÑ.
- 2 кавÑÑки
ÐÐ»Ñ ÑÑÑоковÑÑ Ð»Ð¸ÑеÑалов внÑÑÑи Ñела ÑÑнкÑии, напÑимеÑ:
a_output := ''Blah''; SELECT * FROM users WHERE f_name=''foobar'';
ÐÑи иÑполÑзовании знаков доллаÑа можно пÑоÑÑо напиÑаÑÑ:
a_output := 'Blah'; SELECT * FROM users WHERE f_name='foobar';
и именно ÑÑо ÑÐ²Ð¸Ð´Ð¸Ñ Ð¸ÑполниÑÐµÐ»Ñ PL/pgSQL в Ð¾Ð±Ð¾Ð¸Ñ ÑлÑÑаÑÑ .
- 4 кавÑÑки
Ðогда нÑÐ¶Ð½Ñ Ð¾Ð´Ð¸Ð½Ð°ÑнÑе кавÑÑки в ÑÑÑоковой конÑÑанÑе внÑÑÑи Ñела ÑÑнкÑии, напÑимеÑ:
a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
Ð
a_outputбÑÐ´ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¾:AND name LIKE 'foobar' AND xyzÐÑи иÑполÑзовании знаков доллаÑа ÑÑо запиÑÑваеÑÑÑ Ñак:
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
бÑдÑÑе внимаÑелÑнÑ, пÑи ÑÑом не должно бÑÑÑ Ð²Ð½ÐµÑнего доллаÑового ÑазделиÑелÑ
$$.- 6 кавÑÑек
Ðогда нÑÐ¶Ð½Ñ Ð¾Ð´Ð¸Ð½Ð°ÑнÑе кавÑÑки в ÑÑÑоковой конÑÑанÑе внÑÑÑи Ñела ÑÑнкÑии, пÑи ÑÑом кавÑÑки Ð½Ð°Ñ Ð¾Ð´ÑÑÑÑ Ð² конÑе ÑÑÑоковой конÑÑанÑÑ. ÐапÑимеÑ:
a_output := a_output || '' AND name LIKE ''''foobar''''''
Ð
a_outputбÑÐ´ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¾:AND name LIKE 'foobar'.ÐÑи иÑполÑзовании знаков доллаÑа ÑÑо запиÑÑваеÑÑÑ Ñак:
a_output := a_output || $$ AND name LIKE 'foobar'$$
- 10 кавÑÑек
Ðогда нÑÐ¶Ð½Ñ Ð´Ð²Ðµ одиноÑнÑе кавÑÑки в ÑÑÑоковой конÑÑанÑе (ÑÑо Ñже 8 кавÑÑек), пÑимÑкаÑÑие к конÑÑ ÑÑÑоковой конÑÑанÑÑ (еÑÑ 2). ÐеÑоÑÑно, Ñакое Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð½Ð°Ð´Ð¾Ð±Ð¸ÑÑÑÑ Ð¿Ñи ÑазÑабоÑке ÑÑнкÑии, коÑоÑÐ°Ñ Ð³ÐµÐ½ÐµÑиÑÑÐµÑ Ð´ÑÑгие ÑÑнкÑии, как показано в ÐÑимеÑе 39.9. ÐапÑимеÑ:
a_output := a_output || '' if v_'' || referrer_keys.kind || '' like '''''''''' || referrer_keys.key_string || '''''''''' then return '''''' || referrer_keys.referrer_type || ''''''; end if;'';ÐнаÑение
a_outputзаÑем бÑдеÑ:if v_... like ''...'' then return ''...''; end if;
ÐÑи иÑполÑзовании знаков доллаÑа:
a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$ || referrer_keys.key_string || $$' then return '$$ || referrer_keys.referrer_type || $$'; end if;$$;где пÑедполагаеÑÑÑ, ÑÑо нÑÐ¶Ð½Ñ ÑолÑко одиноÑнÑе кавÑÑки в
a_output, Ñак как поÑÑебÑеÑÑÑ Ð¿Ð¾Ð²ÑоÑное взÑÑие в кавÑÑки пеÑед иÑполÑзованием.
39.11.2. ÐополниÑелÑнÑе пÑовеÑки во вÑÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑÑии
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð¼Ð¾ÑÑ Ð½Ð°Ð¹Ñи и пÑедÑпÑедиÑÑ Ð¿ÑоÑÑÑе, но ÑаÑÑо вÑÑÑеÑаÑÑиеÑÑ Ð¿ÑоблемÑ, PL/PgSQL пÑедоÑÑавлÑÐµÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе пÑовеÑки. ÐÑли они вклÑÑÐµÐ½Ñ Ð² конÑигÑÑаÑии, Ñо во вÑÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»ÑÑии ÑÑнкÑий бÑдÑÑ Ð²ÑдаваÑÑÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе ÑообÑÐµÐ½Ð¸Ñ WARNING или оÑибки ERROR. ФÑнкÑиÑ, пÑи компилÑÑии коÑоÑой вÑдавалоÑÑ WARNING, пÑи поÑледÑÑÑем вÑполнении не бÑÐ´ÐµÑ Ð²ÑдаваÑÑ ÑÑо ÑообÑение и ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑоÑеÑÑиÑоваÑÑ Ð² оÑделÑной ÑÑеде ÑазÑабоÑки.
ÐÐ»Ñ Ð²ÐºÐ»ÑÑÐµÐ½Ð¸Ñ ÑÑиÑ
пÑовеÑок иÑполÑзÑÑÑÑÑ Ð¿Ð°ÑамеÑÑÑ ÐºÐ¾Ð½ÑигÑÑаÑии plpgsql.extra_warnings Ð´Ð»Ñ Ð¿ÑедÑпÑеждений и plpgsql.extra_errors Ð´Ð»Ñ Ð¾Ñибок. ÐÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð¸Ð· паÑамеÑÑов можно пÑиÑвоиÑÑ ÑпиÑок знаÑений, ÑазделÑннÑÑ
запÑÑÑми, знаÑение "none" или "all". Ðо ÑмолÑÐ°Ð½Ð¸Ñ Ð¸ÑполÑзÑеÑÑÑ "none". РнаÑÑоÑÑий Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð´Ð¾ÑÑÑпна ÑолÑко одна пÑовеÑка:
shadowed_variablesÐÑовеÑÑеÑ, ÑÑо обÑÑвление новой пеÑеменной не ÑкÑÑÐ²Ð°ÐµÑ Ñанее обÑÑвленнÑÑ Ð¿ÐµÑеменнÑÑ.
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÑÐµÐºÑ Ð¿ÑиÑÐ²Ð¾ÐµÐ½Ð¸Ñ plpgsql.extra_warnings знаÑÐµÐ½Ð¸Ñ shadowed_variables:
SET plpgsql.extra_warnings TO 'shadowed_variables';
CREATE FUNCTION foo(f1 int) RETURNS int AS $$
DECLARE
f1 int;
BEGIN
RETURN f1;
END;
$$ LANGUAGE plpgsql;
WARNING: variable "f1" shadows a previously defined variable
LINE 3: f1 int;
^
CREATE FUNCTION