42.5. ÐбÑаÑение к базе даннÑÑ Ð¸Ð· PL/Tcl #
Ð ÑÑом Ñазделе Ð´Ð»Ñ Ð¾Ð±Ð¾Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð½ÐµÐ¾Ð±ÑзаÑелÑнÑÑ ÑлеменÑов в опиÑании ÑинÑакÑиÑа иÑполÑзÑÑÑÑÑ Ð·Ð½Ð°ÐºÐ¸ вопÑоÑа (а не квадÑаÑнÑе Ñкобки), как ÑÑо пÑинÑÑо в Tcl. ÐмеÑÑÑÑ ÑледÑÑÑие ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð»Ñ Ð´Ð¾ÑÑÑпа к базе даннÑÑ Ð¸Ð· Ñела ÑÑнкÑии PL/Tcl:
spi_exec?-countn? ?-arrayимÑ?команда?Ñело-Ñикла?ÐÑполнÑÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL, заданнÑÑ Ð² виде ÑÑÑоки. Ð ÑлÑÑае оÑибки в ÑÑой команде вÑдаÑÑÑÑ Ð¾Ñибка в Tcl. РпÑоÑивном ÑлÑÑае
spi_execвозвÑаÑÐ°ÐµÑ ÑиÑло обÑабоÑаннÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹ ÑÑÑок (вÑбÑаннÑÑ , добавленнÑÑ , изменÑннÑÑ Ð¸Ð»Ð¸ ÑдалÑннÑÑ ), либо нолÑ, еÑли ÑÑа команда â ÑлÑжебнÑй опеÑаÑоÑ. ÐÑоме Ñого, еÑли команда â опеÑаÑоÑSELECT, знаÑÐµÐ½Ð¸Ñ Ð²ÑбÑаннÑÑ ÑÑолбÑов помеÑаÑÑÑÑ Ð² пеÑеменнÑе Tcl, как опиÑано ниже.ÐеобÑзаÑелÑнÑй аÑгÑменÑ
-countÑказÑÐ²Ð°ÐµÑ ÑÑнкÑииspi_execоÑÑановиÑÑÑÑ Ð¿Ð¾Ñле полÑÑениÑnÑÑÑок, как еÑли Ð±Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð²ÐºÐ»ÑÑал пÑедложениеLIMIT. ÐÑлиnÑавно нÑлÑ, запÑÐ¾Ñ Ð²ÑполнÑеÑÑÑ Ð´Ð¾ конÑа, Ñак же, как без ÑказаниÑ-count.ÐÑли в каÑеÑÑве ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²ÑполнÑеÑÑÑ Ð¾Ð¿ÐµÑаÑоÑ
SELECT, знаÑÐµÐ½Ð¸Ñ ÑезÑлÑÑиÑÑÑÑÐ¸Ñ ÑÑолбÑов помеÑаÑÑÑÑ Ð² пеÑеменнÑе Tcl, названнÑе по именам ÑÑолбÑов. ÐÑли пеÑедаÑÑÑÑ-array, знаÑÐµÐ½Ð¸Ñ ÑÑолбÑов вмеÑÑо ÑÑого ÑÑановÑÑÑÑ ÑлеменÑами названного аÑÑоÑиаÑивного маÑÑива, индекÑами в коÑоÑом ÑÑановÑÑÑÑ Ð¸Ð¼ÐµÐ½Ð° ÑÑолбÑов. ÐÑоме Ñого, в ÑлеменÑе Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ «.tupno» ÑÐ¾Ñ ÑанÑеÑÑÑ Ð½Ð¾Ð¼ÐµÑ ÑекÑÑей ÑÑÑоки в ÑезÑлÑÑиÑÑÑÑем набоÑе (оÑÑÑиÑÑÐ²Ð°Ñ Ð¾Ñ Ð½ÑлÑ), еÑли ÑолÑко ÑÑо Ð¸Ð¼Ñ Ð½Ðµ занÑÑо одним из ÑÑолбÑов ÑезÑлÑÑаÑа.ÐÑли в каÑеÑÑве ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²ÑполнÑеÑÑÑ
SELECTбез ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ ÑкÑипÑаÑело-Ñикла, в пеÑеменнÑÑ Tcl или ÑлеменÑÐ°Ñ Ð¼Ð°ÑÑива ÑÐ¾Ñ ÑанÑеÑÑÑ ÑолÑко пеÑÐ²Ð°Ñ ÑÑÑока ÑезÑлÑÑаÑов; оÑÑавÑиеÑÑ ÑÑÑоки (еÑли они еÑÑÑ), игноÑиÑÑÑÑÑÑ. ÐÑли запÑÐ¾Ñ Ð½Ðµ возвÑаÑÐ°ÐµÑ ÑÑÑоки, не ÑÐ¾Ñ ÑанÑеÑÑÑ Ð½Ð¸Ñего. (ÐÑÐ¾Ñ ÑлÑÑай можно оÑÑледиÑÑ, пÑовеÑив ÑезÑлÑÑаÑspi_exec.) ÐапÑимеÑ, команда:spi_exec "SELECT count(*) AS cnt FROM pg_proc"
пÑиÑÐ²Ð¾Ð¸Ñ Ð¿ÐµÑеменной
$cntв Tcl ÑиÑло ÑÑÑок, ÑодеÑжаÑÐ¸Ñ ÑÑ Ð² ÑиÑÑемном каÑалогеpg_proc.ÐÑли пеÑедаÑÑÑÑ Ð½ÐµÐ¾Ð±ÑзаÑелÑнÑй аÑгÑменÑ
Ñело-Ñикла, заданнÑй в нÑм блок ÑкÑипÑа Tcl бÑÐ´ÐµÑ Ð²ÑполнÑÑÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки ÑезÑлÑÑаÑа запÑоÑа. (ÐÑгÑменÑÑело-ÑиклаигноÑиÑÑеÑÑÑ, еÑли ÑÐµÐ»ÐµÐ²Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° â неSELECT.) ÐÑи ÑÑом знаÑÐµÐ½Ð¸Ñ ÑÑолбÑов ÑекÑÑей ÑÑÑоки ÑÐ¾Ñ ÑанÑÑÑÑÑ Ð² пеÑеменнÑÑ Tcl или ÑлеменÑÐ°Ñ Ð¼Ð°ÑÑива пеÑед каждой иÑеÑаÑией ÑÑого Ñикла. ÐапÑимеÑ, код:spi_exec -array C "SELECT * FROM pg_class" { elog DEBUG "have table $C(relname)" }бÑÐ´ÐµÑ Ð²ÑводиÑÑ Ð² жÑÑнал ÑообÑение Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки
pg_class. ÐÑо ÑабоÑÐ°ÐµÑ Ð¿Ð¾Ð´Ð¾Ð±Ð½Ð¾ дÑÑгим конÑÑÑÑкÑиÑм Ñиклов в Tcl; в ÑаÑÑноÑÑи, командÑcontinueиbreakв Ñеле Ñикла бÑдÑÑ Ð´ÐµÐ¹ÑÑвоваÑÑ Ð¾Ð±ÑÑнÑм обÑазом.ÐÑли в ÑÑолбÑе ÑезÑлÑÑаÑа запÑоÑа вÑдаÑÑÑÑ NULL, ÑÐµÐ»ÐµÐ²Ð°Ñ Ð¿ÐµÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð»Ñ Ð½ÐµÑ Ð½Ðµ ÑÑÑанавливаеÑÑÑ, и оказÑваеÑÑÑ Â«Ð½ÐµÑÑÑановленной».
spi_preparequeryÑпиÑок-ÑиповÐодгоÑÐ°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¸ ÑÐ¾Ñ ÑанÑÐµÑ Ð¿Ð»Ð°Ð½ запÑоÑа Ð´Ð»Ñ Ð¿Ð¾ÑледÑÑÑего вÑполнениÑ. Ð¡Ð¾Ñ ÑанÑннÑй план бÑÐ´ÐµÑ Ð¿ÑодолжаÑÑ ÑÑÑеÑÑвование до завеÑÑÐµÐ½Ð¸Ñ ÑекÑÑего ÑеанÑа.
ÐапÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑинимаÑÑ Ð¿Ð°ÑамеÑÑÑ, Ñо еÑÑÑ Ð¼ÐµÑÑозаполниÑели Ð´Ð»Ñ Ð·Ð½Ð°Ñений, коÑоÑÑе бÑдÑÑ Ð¿ÐµÑедаваÑÑÑÑ, когда план бÑÐ´ÐµÑ ÑобÑÑвенно вÑполнÑÑÑÑÑ. Ð ÑÑÑоке запÑоÑа ÑÑи паÑамеÑÑÑ Ð¾Ð±Ð¾Ð·Ð½Ð°ÑаÑÑÑÑ ÐºÐ°Ðº
$1...$. ÐÑли в запÑоÑе иÑполÑзÑÑÑÑÑ Ð¿Ð°ÑамеÑÑÑ, нÑжно задаÑÑ Ð¸Ð¼ÐµÐ½Ð° Ñипов ÑÑÐ¸Ñ Ð¿Ð°ÑамеÑÑов в виде ÑпиÑка Tcl. (ÐÑли паÑамеÑÑÑ Ð¾ÑÑÑÑÑÑвÑÑÑ, задайÑе пÑÑÑойnÑпиÑок_Ñипов.)ФÑнкÑиÑ
spi_prepareвозвÑаÑÐ°ÐµÑ Ð¸Ð´ÐµÐ½ÑиÑикаÑÐ¾Ñ Ð·Ð°Ð¿ÑоÑа, коÑоÑÑй Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð² поÑледÑÑÑÐ¸Ñ Ð²ÑзоваÑspi_execp. ÐÑÐ¸Ð¼ÐµÑ Ð¿ÑиведÑн в опиÑанииspi_execp.spi_execp?-countn? ?-arrayимÑ? ?-nullsÑÑÑока?ид-запÑоÑа?ÑпиÑок-знаÑений? ?Ñело-Ñикла?ÐÑполнÑÐµÑ Ð·Ð°Ð¿ÑоÑ, Ñанее подгоÑовленнÑй ÑÑнкÑией
spi_prepare. РкаÑеÑÑвеид_запÑоÑапеÑедаÑÑÑÑ Ð¸Ð´ÐµÐ½ÑиÑикаÑоÑ, возвÑаÑÑннÑй ÑÑнкÑиейspi_prepare. ÐÑли в запÑоÑе задейÑÑвÑÑÑÑÑ Ð¿Ð°ÑамеÑÑÑ, Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑказаÑÑÑпиÑок-знаÑений. ÐÑо должен бÑÑÑ Ð¿ÑинÑÑÑй в Tcl ÑпиÑок паÑамеÑÑов. Ðн должен имеÑÑ ÑÑ Ð¶Ðµ длинÑ, ÑÑо и ÑпиÑок Ñипов паÑамеÑÑов, Ñанее пеÑеданнÑйspi_prepare. ÐпÑÑÑиÑеÑпиÑок-знаÑений, еÑли Ñ Ð·Ð°Ð¿ÑоÑа Ð½ÐµÑ Ð¿Ð°ÑамеÑÑов.ÐеобÑзаÑелÑнÑй аÑгÑменÑ
-nullsпÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑÑÑÐ¾ÐºÑ Ð¸Ð· пÑобелов и Ñимволов'n', коÑоÑÑе оÑмеÑаÑÑ, в ÐºÐ°ÐºÐ¸Ñ Ð¿Ð°ÑамеÑÑаÑspi_execpпеÑедаÑÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL. ÐÑли пÑиÑÑÑÑÑвÑеÑ, ÑÑа ÑÑÑока должна имеÑÑ ÑÑ Ð¶Ðµ длинÑ, ÑÑо иÑпиÑок-знаÑений. Ð ÑлÑÑае ÐµÑ Ð¾ÑÑÑÑÑÑÐ²Ð¸Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð²ÑÐµÑ Ð¿Ð°ÑамеÑÑов ÑÑиÑаÑÑÑÑ Ð¾ÑлиÑнÑми Ð¾Ñ NULL.Ðе ÑÑиÑÐ°Ñ Ð¾ÑлиÑий в ÑпоÑобе пеÑедаÑи запÑоÑа и паÑамеÑÑов,
spi_execpÑабоÑÐ°ÐµÑ Ñак же, какspi_exec. ÐаÑамеÑÑÑ-count,-arrayиÑело-ÑиклазадаÑÑÑÑ Ñак же, и Ñак же пеÑедаÑÑÑÑ Ð²Ð¾Ð·Ð²ÑаÑаемое знаÑение.ÐзглÑниÑе на пÑÐ¸Ð¼ÐµÑ ÑÑнкÑии на PL/Tcl, иÑполÑзÑÑÑей подгоÑовленнÑй план:
CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$ if {![ info exists GD(plan) ]} { # подгоÑовиÑÑ ÑÐ¾Ñ ÑанÑннÑй план пÑи пеÑвом вÑзове set GD(plan) [ spi_prepare \ "SELECT count(*) AS cnt FROM t1 WHERE num >= \$1 AND num <= \$2" \ [ list int4 int4 ] ] } spi_execp -count 1 $GD(plan) [ list $1 $2 ] return $cnt $$ LANGUAGE pltcl;ÐбÑаÑнÑе коÑÑе ÑеÑÑÑ Ð²Ð½ÑÑÑи ÑÑÑоки запÑоÑа, пеÑедаваемой ÑÑнкÑии
spi_prepare, нÑÐ¶Ð½Ñ Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð¼Ð°ÑкеÑÑ$пеÑедавалиÑÑ ÑÑнкÑииnspi_prepareкак еÑÑÑ, а не заменÑлиÑÑ Ð¿Ñи подÑÑановке пеÑеменнÑÑ Tcl.subtransactionкомандаСкÑÐ¸Ð¿Ñ Tcl, коÑоÑÑй ÑодеÑжиÑ
команда, вÑполнÑеÑÑÑ Ð² подÑÑанзакÑии SQL. ÐÑли ÑÑÐ¾Ñ ÑкÑÐ¸Ð¿Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ Ð¾ÑибкÑ, вÑÑ Ð¿Ð¾Ð´ÑÑанзакÑÐ¸Ñ Ð¾ÑкаÑÑваеÑÑÑ Ð½Ð°Ð·Ð°Ð´, а заÑем в окÑÑжаÑÑий код Tcl возвÑаÑаеÑÑÑ Ð¾Ñибка. Ðа дополниÑелÑнÑми подÑобноÑÑÑми и пÑимеÑом обÑаÑиÑеÑÑ Ðº РазделÑ 42.9.quoteÑÑÑокаÐÑблиÑÑÐµÑ Ð²Ñе Ð²Ñ Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð°Ð¿Ð¾ÑÑÑоÑа и обÑаÑной коÑой ÑеÑÑÑ Ð² заданной ÑÑÑоке. ÐÑо можно иÑполÑзоваÑÑ Ð´Ð»Ñ Ð·Ð°ÑиÑÑ ÑÑÑок, коÑоÑÑе бÑдÑÑ Ð²ÑÑавлÑÑÑÑÑ Ð² ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL, пеÑедаваемÑе в
spi_execилиspi_prepare. ÐапÑимеÑ, пÑедÑÑавÑÑе, ÑÑо пÑи вÑполнении Ñакой ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL:"SELECT '$val' AS ret"
пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÑзÑка Tcl
valÑодеÑжиÑdoesn't. ÐÑо пÑиведÑÑ Ðº ÑоÑмиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ñакой оконÑаÑелÑной ÑÑÑоки командÑ:SELECT 'doesn't' AS ret
пÑи ÑазбоÑе коÑоÑой в пÑоÑеÑÑе
spi_execилиspi_prepareÐ²Ð¾Ð·Ð½Ð¸ÐºÐ½ÐµÑ Ð¾Ñибка. ЧÑÐ¾Ð±Ñ ÑÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ ÑабоÑал пÑавилÑно, иÑÐ¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° должна вÑглÑдеÑÑ Ñак:SELECT 'doesn''t' AS ret
ÐолÑÑиÑÑ ÐµÑ Ð² PL/Tcl можно Ñак:
"SELECT '[ quote $val ]' AS ret"
ÐÑеимÑÑеÑÑвом
spi_execpÑвлÑеÑÑÑ Ñо, ÑÑо Ð´Ð»Ñ Ð½ÐµÑ Ð·Ð°ÐºÐ»ÑÑаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑов в кавÑÑки подобнÑм обÑазом не нÑжно, Ñак как паÑамеÑÑÑ Ð½Ð¸ÐºÐ¾Ð³Ð´Ð° не ÑазбиÑаÑÑÑÑ Ð² ÑоÑÑаве ÑÑÑоки ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL.-
elogÑÑовенÑÑообÑение ÐÑдаÑÑ ÑлÑжебное ÑообÑение или ÑообÑение об оÑибке. ÐозможнÑе ÑÑовни ÑообÑений:
DEBUG(ÐТÐÐÐÐÐ),LOG(СÐÐÐЩÐÐÐÐ),INFO(ÐÐФÐÐ ÐÐЦÐЯ),NOTICE(ÐÐÐÐЧÐÐÐÐ),WARNING(ÐÐ ÐÐУÐÐ ÐÐÐÐÐÐÐ),ERROR(ÐШÐÐÐÐ) иFATAL(ÐÐÐÐÐ). С ÑÑовнемERRORвÑдаÑÑÑÑ Ð¾Ñибка; еÑли она не пеÑÐµÑ Ð²Ð°ÑÑваеÑÑÑ Ð¾ÐºÑÑжаÑÑим кодом Tcl, она ÑаÑпÑоÑÑÑанÑеÑÑÑ Ð² вÑзÑваÑÑий запÑоÑ, ÑÑо пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ðº пÑеÑÑÐ²Ð°Ð½Ð¸Ñ ÑекÑÑей ÑÑанзакÑии или подÑÑанзакÑии. Ðо ÑÑÑи Ñо же Ñамое Ð´ÐµÐ»Ð°ÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°errorÑзÑка Tcl. СообÑение ÑÑовнÑFATALпÑеÑÑÐ²Ð°ÐµÑ ÑÑанзакÑÐ¸Ñ Ð¸ пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ðº завеÑÑÐµÐ½Ð¸Ñ ÑекÑÑего ÑеанÑа. (ÐеÑоÑÑно, Ð½ÐµÑ Ð¾Ð±Ð¾Ñнованной пÑиÑÐ¸Ð½Ñ Ð¸ÑполÑзоваÑÑ ÑÑÐ¾Ñ ÑÑÐ¾Ð²ÐµÐ½Ñ Ð¾Ñибок в ÑÑнкÑиÑÑ PL/Tcl, но он поддеÑживаеÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑ.) ÐÑи иÑполÑзовании дÑÑÐ³Ð¸Ñ ÑÑовней пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ð¿ÑоÑÑо вÑвод ÑообÑÐµÐ½Ð¸Ñ Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñм ÑÑовнем важноÑÑи. ÐÑдÑÑ Ð»Ð¸ ÑообÑÐµÐ½Ð¸Ñ Ð¾Ð¿ÑеделÑнного ÑÑÐ¾Ð²Ð½Ñ Ð¿ÐµÑедаваÑÑÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑ Ð¸/или запиÑÑваÑÑÑÑ Ð² жÑÑнал, опÑеделÑеÑÑÑ ÐºÐ¾Ð½ÑигÑÑаÑионнÑми пеÑеменнÑми log_min_messages и client_min_messages. Ðа дополниÑелÑнÑми ÑведениÑми обÑаÑиÑеÑÑ Ðº Ðлаве 18 и РазделÑ 42.8.