<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
	<channel>
		<title><![CDATA[Forum PostgreSQL - Przesyłanie wiadomości od serwera do klienta - struct PGresult]]></title>
		<link>https://forum.postgresql.org.pl/viewtopic.php?id=602</link>
		<description><![CDATA[Najświeższe odpowiedzi w Przesyłanie wiadomości od serwera do klienta - struct PGresult.]]></description>
		<lastBuildDate>Wed, 15 Jun 2011 21:40:13 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Odp: Przesyłanie wiadomości od serwera do klienta - struct PGresult]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2570#p2570</link>
			<description><![CDATA[Bardzo dziękuję za odpowiedź i zainteresowanie tematem.

Dokładnie tak. Serwer łączy się via libpq z serwerem na którym jest baza danych(ten sam host). Klient formułuje zapytania sqlove:) i wysyła je w stringu do serwera. Tam zawartość stringa jest wstawiana do funkcji:

[code]PGresult* PQexec(PGconn* connection, char* query);[/code]

jako parametr przechowujący zapytanie do bd.
Niestety nie da rady przesłać struktury:

[code]struct PGresult;[/code]

przez wartość, gdyż dostepny jest jedynie wskaźnik do niej.
Oczywiście skorzystałem z metod akcesora. Zrobiłem to w następujący sposób. Zdefiniowałem własną strukturę:

[code]static struct MessageStruc{
    std::string** tab;
    int numberOfRows;
    int numberOfCols;
    } myStruc, *myStruc_ptr;[/code]

i w niej chciałem przekazywać dane uzyskane za pomocą:

[code]int    PQntuples(const PGresult *res);
int    PQnfields(const PGresult *res);[/code]

oraz wartości z komórek bazy danych za pomocą:

[code]char *PQgetvalue(const PGresult *res, int tup_num, int field_num);[/code]

Tak wypełnioną strukturę rzutuję:

[code]char* buffer = reinterpret_cast<char*>(myStruc_ptr);[/code]

i wysyłam:

[code]send(clientSocket, buffer, sizeof(myStruc), 0);[/code]


Po stronie klienta również mam zdefiniowaną strukturę:

[code]static struct MessageStruc{
        std::string** tab;
        int numberOfRows;
        int numberOfCols;
    } myStruc, *myStruc_ptr;[/code]

i daltego mogę utworzyć wskaźnik do niej i rzutować nań tablicę znaków z komunikatem zwrotnym:

Fragment kodu, który ilustruje wyżej opisane czynności:

[code]char buffer[2048];
int result = recv(s, buffer, sizeof(buffer), 0);

myStruc_ptr = reinterpret_cast<MessageStruc*>(buffer);[/code]

Jak przychodzi do wypisania wartości to zmienne: 

[code]int numberOfRows;
int numberOfCols;[/code]

zwracają oczekiwane wartości, natomiast w tablicy stringów są krzaki.

Zreflektowałem się że przesyłając adres do tablicy nie przesyłam zawartości tej tablicy. Z tego co mi wiadomo inaczej nie da się, a co klientowi po adresie komórek które są na hoscie serwera? Stąd też zamieniłem tablicę stringów na wektor.

Przesyłana struktura wygląda zatem tak:

[code]static struct MessageStruc{
    std::vector<std::string> v;
    int numberOfRows;
    int numberOfCols;
    } myStruc, *myStruc_ptr;[/code]

Niestety przy wypisywaniu elementów wektora kompilator wyrzuca błędy nad którymi teraz pracuję.

Nie mam pewności czy wektor jest dobrym pomysłem na rozwiązanie tego problemu.

Natomiast jeśli chodzi o bibliotekę libpq-int.h z definicją struktury to napotkałem taką oto radę:

[quote]Beginning in Postgres release 6.4, the definition of struct PGresult is not even provided in libpq-fe.h. If you have old code that accesses PGresult fields directly, you can keep using it by including libpq-int.h too, but you are encouraged to fix the code soon.[/quote]

Jednak próbowałem załączyć tenże plik nagłówkowy. Niestety bez powodzenia. Nie rozumiem co masz na myśli pisąc:

[quote=gszpetkowski](...) "niepubliczny" plik nagłówkowy libpq-int.h (...)[/quote]

Mam ten plik i inne potrzebne w katalogu:

[quote]C:\Program Files\PostgreSQL\8.4\include\internal[/quote]

W związku z tym że wspomniany plik nagłówkowy jest "niepubliczny", czy muszę podać jego ścieżkę dostępu wpisując ją gdzieś we właściwościach projektu w Visualu?]]></description>
			<author><![CDATA[dummy@example.com (tata tasiemkaliga)]]></author>
			<pubDate>Wed, 15 Jun 2011 21:40:13 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2570#p2570</guid>
		</item>
		<item>
			<title><![CDATA[Odp: Przesyłanie wiadomości od serwera do klienta - struct PGresult]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2569#p2569</link>
			<description><![CDATA[Czyli serwer łączy się via libpq z "właściwym" serwerem bazodanowym, pobiera wynik zapytania i odsyła je klientowi, który sam w sobie nie ma styczności z PostgreSQL. Rzeczywiście piszą w kodzie pliku nagłówkowego (odnośnie PGresult):

[code]* The contents of this struct are not supposed to be known to applications.[/code]

Są jednak dostępne metody akcesora, które można wykorzystać tj. pod:

[code]/* Accessor functions for PGresult objects */
..
extern int    PQntuples(const PGresult *res);
extern int    PQnfields(const PGresult *res);
..
extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num);
..[/code]

Jak rozumiem ta funkcja send przesyła dane zawarte w buf, który jak podałeś jest wskaźnikiem do stałej typu char. Czyli o ile dobrze rozumuję należałoby użyć powyższych funkcji akcesora i samodzielnie zbudować taki bufor.

Nieco podobne pytanie znalazłem też na [url]http://stackoverflow.com/questions/2779927/how-to-convert-a-pgresult-to-custom-data-type-with-libpq-postgresql[/url]

Drugi pomysł jaki mi przychodzi do głowy to załączyć "niepubliczny" plik nagłówkowy libpq-int.h, który zawiera definicję tej struktury (konkretnie pg_result, ale wcześniej był prosty typedef do PGresult), dzięku czemu powinna udać się użyta przez Ciebie konwersja do tablicy bajtów.

[code] * libpq-int.h
 *      This file contains internal definitions meant to be used only by
 *      the frontend libpq library, not by applications that call it.
 *
 *      An application can include this file if it wants to bypass the
 *      official API defined by libpq-fe.h, but code that does so is much
 *      more likely to break across PostgreSQL releases than code that uses
 *      only the official API.[/code]]]></description>
			<author><![CDATA[dummy@example.com (gszpetkowski)]]></author>
			<pubDate>Thu, 09 Jun 2011 12:18:30 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2569#p2569</guid>
		</item>
		<item>
			<title><![CDATA[Przesyłanie wiadomości od serwera do klienta - struct PGresult]]></title>
			<link>https://forum.postgresql.org.pl/viewtopic.php?pid=2568#p2568</link>
			<description><![CDATA[Moje pytanie dotyczy przesyłania wiadomości z serwera do klienta. Korzystam z funkcji send(...) w aplikacji serwera.

int send(
  __in  SOCKET s,
  __in  const char *buf,
  __in  int len,
  __in  int flags
);

Funkcja send(...) wysyła do klienta odpowiedź na zapytanie do bazy danych. Bazę mam w PostgreSQL. Do obsługi bazy wykorzystuje funkcje z biblioteki libpq.lib.

Funkcja PQexec(...) wysyła zapytanie do bazy.

PGresult *PQexec(
  PGconn *conn, 
  const char *command
);

Funkcja ta generuje odpowiedź z bazy w postaci struktury PQresult. W związku z tym chciałbym przesłać tą strukturę z serwera do klienta. 

Znalazłem podobny wątek na innym forum, w którym ktoś sugerował, żeby: "skonwertować strukture jako zwykly wskaznik, i wysłać dane, a jako rozmiar struktury uzyć operatora sizeof(struct struktura)". Jednak kiedy piszę:


(...)
  PGconn* conn = PQconnectdb("user=postgres password=pass dbname=mydb hostaddr=127.0.0.1 port=5432");;
  string query;

  PGresult* result = PQexec(conn, query.c_str());
  char* buffer = reinterpret_cast<char*>(result);

  send(clientSocket, buffer, sizeof(PGresult), 0);

kompilator protestuje wskazując że PGresult jest typem niezdefiniowanym. Faktycznie załączona biblioteka libpq-fe.h nie definiuje tego typu.

Prosze o jakieś sugestie dotyczące sposobu przesłania wyniku zapytania do bazy z aplikacji serwera do aplikacji klienta. Jak to wysłać i jak odebrać po stronie klienta?

Funkcja odbierająca komunkiaty po stronie klienta.

int recv(
  __in   SOCKET s,
  __out  char *buf,
  __in   int len,
  __in   int flags
);]]></description>
			<author><![CDATA[dummy@example.com (tata tasiemkaliga)]]></author>
			<pubDate>Wed, 08 Jun 2011 16:52:36 +0000</pubDate>
			<guid>https://forum.postgresql.org.pl/viewtopic.php?pid=2568#p2568</guid>
		</item>
	</channel>
</rss>
