it-place.net > Уроци > PostgreSQL
Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Разширяване функционалността на PostgreSQL: Програмиране на функции с PERL
  1. Разширяване функционалността на PostgreSQL: Програмиране на функции с PERL
  2. Разширяване функционалността на PostgreSQL: Програмиране на функции с PERL - II
SOMNIVM
     
Автор  SOMNIVM (30.08.2006 09:40)  съобщение до автора
Погледнат  7217 пъти  добави към любими
Оценка  добави коментар
Гласове  --  изпрати на приятел
Коментари  (0)  абонирай се за PostgreSQL
    Страница 2 / 2

 



Сега искаме да направим функция, която да ни връща имената и адресите, за да можем да разпечатаме пликове в които да им изпратим коледни премии – по 1 седмица почивка на планина:

CODE
1
2
3
4
CREATE FUNCTION plikowe(slujiteli) RETURNS text AS $$
       
my ($employes) = @_;
       
return $employes->{'ime'}.'n'.$employes->{'adres'};
$$
LANGUAGE plperl;

За да извикаме функцията е достатъчно да изпълним

CODE
1
SELECT plikowe(slujiteli.*) FROM slujiteli;

Знаейки, че сложните тиипове данни се представят като хешове в PERL, можем да напишем и функция, която връща сложен тип. За целта обаче трябва първо да създадем необходимия ни тип:

CODE
1
CREATE TYPE my_composite_type AS (t1 text, t2 integer, t3 bool, t4 real);

След това дефинираме една функция, която да връща стойност от този тип:

CODE
1
2
3
CREATE FUNCTION return_my_composite() RETURNS my_composite_type AS $$
       
return {t4 => 3.14, t1 => 'nqkakyw text', t2 => 2, t3 => true};
$$
LANGUAGE plperl;

Всяка колона, която сме изпуснали да върнем във функцията приема стойност NULL. Трябва обаче да внимаваме за съответствията между типовете, които връщаме и декларираните типове в сложния тип.
Функциите ни могат не само да връщат скаларни и сложни типове, а и цели масиви от такива типове. За пример ще вземем последната ни функция и ще я преобразуваме така, че да връща 4 стойности от тип my_composite_type:

CODE
1
2
3
4
5
6
CREATE FUNCTION return_setofmy_composite() RETURNS SETOF my_composite_type AS $$
       
return [ {t4 => 3.14, t1 => 'nqkakyw text', t2 => 2, t3 => true},
           
{t4 => 2.3, t1 => 'oshte text', t2 => 5, t3 => false},
           
{t4 => 9.8, t1 => 'treti text', t2 => 7, t3 => false},
           
{t4 => 0.13, t1 => 'posleden text', t2 => 78, t3 => true} ];
$$
LANGUAGE plperl;


PERL функциите в PostgreSQL могат да манипулират базата данни посредством специалната функция spi_exec_query(query) . Нека да се върнем на примера с гаровите служители. Решаваме, че ни трябва телефонен указател на персонала и съответно трябва да си напишем функцията, която ще го прави. Телефонният указател ще представлява таблица с две колони: името на служителя и телефонния му номер. За целта ще дефинираме нов тип phonebook:

CODE
1
CREATE TYPE phonebook AS (ime varchar(50), tel varchar(14));

Сега вече можем спокойно да напишем функцията „телефонен указател“:

CODE
1
2
3
4
5
6
7
8
9
10
CREATE FUNCTION phnbk() RETURNS SETOF phonebook AS $$
       
my $cel = [];
       
my $resultat = spi_exec_query('SELECT ime, tel FROM slujiteli');
       
my $n_zapisi = $resultat->{processed};
       
for($i=0;$i < $n_zapisi; $i++) {
           
my $red = $resultat->{rows}[$i];
           
push @$cel, $red;
       
}
       
return $cel;
$$
LANGUAGE plperl;

Можем да извикаме функцията си със SELECT * FROM phnbk(); и ще получим таблица, подобна на тази:

mytestdb=# SELECT * FROM phnbk();
     ime       |    tel
-------------+------------
 Petyr Dimow | 052/612000
 Iwan Iwanow | 052/612612
(2 rows)


В PERL имплементацията в PostgreSQL има един голям недостатък – PERL функциите не се „виждат“ една друга и в този смисъл не могат да се извикват. Все пак можем да използваме глобални стойности като съхраняваме информацията си в сподоления хеш %_SHARED.  %_SHARED ни дава възможнст също да извикваме функции една от друга с помощта на споделени референции, което премахва до голяма степен проблема с „видимостта“ между отделните функции. Ето един малък пример за функция, която премахва интервалите от даден низ:

CODE
1
2
3
4
5
6
7
CREATE FUNCTION strip_spaces() RETURNS void AS $$
       
$_SHARED{nospace} = sub {
           
my $txt = shift;
           
$txt =~ s/s//g;
           
return $txt;
       
};
$$
LANGUAGE plperl;

След като сме написали тази функция, трябва да я активираме. Това става като я изпълним със SELECT заявка: SELECT strip_spaces(); След това дефинираме функция, която да използва предната:

CODE
1
2
3
4
5
CREATE FUNCTION no_spaces(text) RETURNS text AS $$
       
my $string_with_spaces = shift;
       
my $stripper = $_SHARED{nospace};
       
return &$stripper($string_with_spaces);
$$
LANGUAGE plperl;

Използваме &$stripper след return, защото $stripper е референция към подпрограмата(функцията).

Употребата на PERL в PostgreSQL е ограчинена с оглед на сигурността, тъй като всеки потребител, който има база данни в една PostgreSQL DMBS може да дефинира PERL функции. Последните не могат да зареждат външни модули, да пишат и четат файлове от файловата система или по какъвто и да било начин да взаимодействат с платформата, придобивайки правата на сървъра. Когато все пак ни се налага да дефинираме такава функция и имаме администраторски достъп до сървъра просто трябва да променим plperl на plperlu. Когато използвате PERL, за да добавяте функции към PostgreSQL винаги мислете какво количество данни и в какви типове ще обработвате, защото PERL съхранява всички масиви и хешове в оперативната памет и това може да забави значително или даже да остави системата без свободна оперативна памет.



 << Предишна страница  


Ключови думи: postgresql база данни функция процедура процедурни езици


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 За автора: SOMNIVM  
Информатик!
   
 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

 

 
  • Интересно от Софтуер
 



IT-PLACE.NET © 2004 - 2008