libpq i procedury
Maciej Piekielniak - 01-04-2006 00:19
libpq i procedury
Witam
W większości książek i materiałów można znaleźć, że funkcje postgresql można tworzyć w językach C, plpgsql, sql itd. Standardowo pisane funkcje w C służą głównie do obróbki przekazanych danych do funkcji. Co jednak zrobić gdy np bibloteka napisana w C jest podczepiona do funkcji i prócz obróbki danych/wyliczeń ma np. zrobić update wierszy? Służy do tego oczywiście funkcja PQexec z libpq-fe.h, ale jednym z parametrów przekazywanych do niej jest identyfikator połączenia tworzony przez PQconnectdb() i zamykany przez PQfinish(). I tu jest problem, z jednej strony muszę mieć identyfikator połączenia, z drugiej gdy go zamknę przez PQfinish() program traci połączenie z bazą ponieważ funkcja zamyka połączenie.
np:
wywoluje SELECT funkcja();
CREATE OR REPLACE FUNCTION funkcja() RETURNS INT4 AS '/lib/fun.so' LANGUAGE 'c';
fun.c:
#include <stdio.h> #include <stdlib.h> #include "libpq-fe.h"
int fun() { char zap[256]; PGconn *conn; PGresult *wynik;
conn = PQconnectdb("dbname=bazka user=postgres");
sprintf(zap,"UPDATE tabelka SET jakiespole=%d",1); wynik = PQexec(conn,zap); PQclear(wynik);
PQfinish(conn); return 0; }
hubert depesz lubaczewski - 02-04-2006 00:10
Maciej Piekielniak wrote: > wywoluje SELECT funkcja(); > CREATE OR REPLACE FUNCTION funkcja() > RETURNS INT4 AS > '/lib/fun.so' LANGUAGE 'c'; > fun.c: > #include <stdio.h> > #include <stdlib.h> > #include "libpq-fe.h" > conn = PQconnectdb("dbname=bazka user=postgres");
pisząc funkcje w c nie łącz się do bazy przez libpq. używaj interfejsu SPI. więcej o tym - w docach, albo przejrzyj źródła programów w conribie.
depesz
max - 02-04-2006 00:10
hubert depesz lubaczewski napisał(a): > Maciej Piekielniak wrote: >> wywoluje SELECT funkcja(); >> CREATE OR REPLACE FUNCTION funkcja() >> RETURNS INT4 AS >> '/lib/fun.so' LANGUAGE 'c'; >> fun.c: >> #include <stdio.h> >> #include <stdlib.h> >> #include "libpq-fe.h" >> conn = PQconnectdb("dbname=bazka user=postgres");
W sumie to ciekawy pomysł :) Wkapilowywać w biblioteke parametry polaczenia ;) i otwierac kolejne polaczenie.
Warto zajrzec do prostych przykładów w katalogu "contrib" Ja tam sie wzorowałem na tym i działa.
Maciej Piekielniak - 02-04-2006 00:11
Ok, cos tam znalazlem ale strasznie zagmatwane w porownaniu do libpq. Jakies SPITupleTable,TupleDesc,HeapTuple,elog,.. Praktycznie procz oryginalnej dokumentacji niewiele jest.
Na zakonczenie jak byscie to przerobili?
for(i=0;i<PQntuples(wynik);i++) { sprintf(zmienna1,"AAA %s\n",PQgetvalue(wynik,i,0)); sprintf(zmienna2,"BBB %s\n",PQgetvalue(wynik,i,0)); }
Maciej Piekielniak - 02-04-2006 00:11
Moze inaczej, po pierwsze czy poprawny sposób kompilowania to (podczas tworzenia funkcji odpalajacej ta bibloteke dostalem blad ERROR: could not load library "/lib/ala.so": /lib/ala.so: undefined symbol: SPI_EXEC)):
cc -I/usr/include/postgresql/server/ -fpic -c ala.c cc -shared -o ala.so ala.o -lpq
i jak tu uzupelnic? :)
#include <stdio.h> #include <stdlib.h> #include "executor/spi.h"
int ala() { char zap[256]; char komenda[256]; int i,j,ret,ret_k;
if(ret=SPI_connect()!=SPI_OK_CONNECT) elog(ERROR, "ERROR: %d",ret);
strcpy(zap,"SELECT * from komputer;"); ret = SPI_EXEC(zap,0); ret_k=SPI_processed;
if(ret == SPI_OK_SELECT && ret_k>0) { // Jak tu wyswietlic wszystkie wiersze lub kolumny // lub wszystkie wiersze z jedna kolumna }
SPI_finish(); return 0; }
Ronald Kuczek - 03-04-2006 00:07
Użytkownik Maciej Piekielniak napisał: > Moze inaczej, po pierwsze czy poprawny sposób kompilowania to > (podczas tworzenia funkcji odpalajacej ta bibloteke dostalem blad > ERROR: could not load library "/lib/ala.so": /lib/ala.so: undefined > symbol: SPI_EXEC)): > > cc -I/usr/include/postgresql/server/ -fpic -c ala.c > cc -shared -o ala.so ala.o -lpq > > i jak tu uzupelnic? :) Ech.. Maćku, skorzystaj z Makefile. Załóżmy,że kompiluję bibliotekę mojarzezba.c umieszczoną w source_tree postgresa w katalogu contrib/mojkatalog # #
subdir = contrib/mojkatalog top_builddir = ../.. include $(top_builddir)/src/Makefile.global
OBJS = mojarzezba.o #DOCS = README.mojarzezba #SQLS = $(OBJS:.o=.sql) #EXAMPLES= $(OBJS:.o=.example) MODS = $(OBJS:.o=$(DLSUFFIX))
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) override CFLAGS += $(CFLAGS_SL)
ifdef REFINT_VERBOSE override CPPFLAGS+= -DREFINT_VERBOSE endif
override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS)
all: $(MODS) $(SQLS)
%.sql: %.sql.in sed -e 's:MODULE_PATHNAME:$(libdir)/contrib/$(@:.sql=$(DLSUFFIX)):g' < $< > $@
install: all installdirs for inst_file in $(SQLS); do \ $(INSTALL_DATA) $$inst_file $(datadir)/contrib || exit; \ done for inst_file in $(MODS); do \ $(INSTALL_SHLIB) $$inst_file $(libdir)/contrib || exit; \ done for inst_file in $(EXAMPLES) README.mojarzezba; do \ $(INSTALL_DATA) $$inst_file $(docdir)/contrib/mojkatalog || exit; \ done
installdirs: $(mkinstalldirs) $(datadir)/contrib $(libdir)/contrib $(docdir)/contrib/spi
uninstall: rm -f $(addprefix $(datadir)/contrib/, $(SQLS)) \ $(addprefix $(libdir)/contrib/, $(MODS)) \ $(addprefix $(docdir)/contrib/mojkatalog/, $(EXAMPLES) README.mojarzezba)
clean distclean maintainer-clean: rm -f $(MODS) $(SQLS) $(OBJS)
depend dep: $(CC) -MM -MG $(CFLAGS) *.c > depend
ifeq (depend,$(wildcard depend)) include depend endif
> #include <stdio.h> > #include <stdlib.h> > #include "executor/spi.h" > > int ala() > { > char zap[256]; > char komenda[256]; > int i,j,ret,ret_k; > > if(ret=SPI_connect()!=SPI_OK_CONNECT) > elog(ERROR, "ERROR: %d",ret); > > > strcpy(zap,"SELECT * from komputer;"); > ret = SPI_EXEC(zap,0); > ret_k=SPI_processed; > > if(ret == SPI_OK_SELECT && ret_k>0) > { > // Jak tu wyswietlic wszystkie wiersze lub kolumny > // lub wszystkie wiersze z jedna kolumna > } > > SPI_finish(); > return 0; > } >
W dokumentacji jest przykład, zerknij (40.1), nie doczytałeś o SPI_getvalue. Przykład jest dość jasny, nie będę go tutaj powielał.
Pozdrawiam Rony
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[oracle] czy da =?ISO-8859-2?Q?si=EA_z_poziomu_procedury_?==?ISO-8859-2?Q?zrobi=E6_kopi=EA_zapasow=B1=3F?=
MSSQL 2005 i uruchamianie procedury o =?ISO-8859-2?Q?okre=B6lone?==?ISO-8859-2?Q?j_godzinie?=
[MS SQL 2000/2005] Procedura z dynamicznym SQL
=?iso-8859-2?q?Procedura_sk=B3adowalna_wywo=B3ywana_o_okreslo nej_godzinie?=
[ORACLE] Stored Procedures - jaki typ danych przy dostępnie poprzez ADO?
=?iso-8859-2?q?[Mysql_5=2E0]_Wywo=B3ywanie_procedury_jako_parametr_funkcji?=
[MySQL5] problem z zastosowanie funkcji, procedury w celu unikniecia powtórzeń kodu w zapytaniach
=?iso-8859-2?q?wysy=B3anie_emaila_za_pomoca_procedury_skladow anej_Oracle?=
=?iso-8859-2?Q?=5Boracle_pl/sql=5D_r=F3=BFnice_w_tworzeniu_procedur?=
=?iso-8859-2?q?Nazwa_Tabeli_jako_parametr_w_procedurze_sk=B3a dowanej?=
zanotowane.pldoc.pisz.plpdf.pisz.plnatalia97.htw.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|