2012-12-01 9 views
6

Sto lavorando con l'API C PostgreSQL. Leggendo il documentation si dice che una query è finita quando PQgetResult restituisce NULL e PQgetResult si bloccherà se PQisBusy non restituisce 0. Tuttavia PQisBusy restituisce 1 se non c'è più input, quindi non posso chiamare PQgetResult e ottenere il NULL. Pertanto non posso sapere se la query è finita. C'è un altro modo per sapere se la query è stata eseguita? Ho frainteso l'API asincrona?Postgres Async API che rileva la fine della query

---- ----- modificare

L'idea di base come codice C è:

PQsendQuery(conn, query) 

while(true) 
{ 
    PQconsumeInput(conn) 
    if(PQisBusy(conn) == 0) 
    { 
     PGresult* res = PQgetResult(conn); 
     if(res) 
     { 
      //print result 
     } 
     else 
     { 
      //res == NULL 
      //indicates query is over 
      break; 
     } 
    } 
} 

Il risultato verrà stampato, ma il ciclo non termina. Perché PQisBusy restituisce 0 solo una volta.

+1

Potrebbe valere la pena ideare questo fuori con il codice che mostra quello che stai facendo. –

+0

Penso che PQgetResult controlli e attenda il segnale di occupato prima di restituire il risultato. Quindi potrebbe non essere necessario se (PQisBusy (conn) == 0) controllare. –

+0

@MuhammadUsama il punto del codice è che non può mai bloccare, quindi l'asincrono. So che fare l'I/O asincrono in un ciclo occupato è inutile ma avevo bisogno di un esempio minimo. – JustMaximumPower

risposta

0

È possibile visualizzare un problema con il codice. Non si sta verificando il ritorno della funzione PQconsumeInput (conn). Poiché è responsabilità di PQconsumeInput eliminare la bandiera occupata. Quello che potrebbe accadere è che PQconsumeInput fallirebbe senza elaborare alcun dato e cancellare la bandiera di occupato.

Penso che controllare il risultato di PQconsumeInput prima di chiamare PQisBusy dovrebbe funzionare correttamente.

while (PQconsumeInput(conn) == 1) 
{ 
    if(PQisBusy(conn) == 0) 
    { 
     PGresult* res = PQgetResult(conn); 
     if(res) 
     { 
      //print result 
     } 
     else 
     { 
      //res == NULL 
      //indicates query is over 
      break; 
     } 
    } 
} 
+0

PQconsumeInput restituisce 0 indica un errore la documentazione specifica che anche in caso di un errore PQgetResult deve essere chiamato fino a quando non restituisce NULL. Inoltre, ancora, il codice sopra riportato è solo un esempio minimalista. Nel codice reale eseguo il controllo degli errori. – JustMaximumPower

+0

Nota: anche quando PQresultStatus indica un errore irreversibile, PQgetResult deve essere chiamato fino a quando non restituisce un puntatore nullo, per consentire a libpq di elaborare completamente le informazioni sull'errore. –

+0

scusa ho spinto il reso troppo presto e ora non posso modificare il mio commento, quindi per favore ignora quanto sopra. Il documento dice "Anche quando PQresultStatus indica un errore irreversibile, PQgetResult dovrebbe essere chiamato fino a quando non restituisce un puntatore nullo, per consentire a libpq di elaborare completamente le informazioni sull'errore." Quindi penso che sia valido solo per l'errore durante la chiamata alla funzione PQGetResult, non per l'errore avvenuto in PQconsumeInput. Inoltre nel tuo caso stai aspettando che PQisBusy restituisca "non occupato" prima di chiamare PQGetResult e credo che PQisBusy non possa essere considerato attendibile in caso di errore restituito dalla funzione PQconsumeInput. –

1

In base a quello che ho capito dal link nel mio commento, vorrei provare qualcosa di simile (i parametri da select() e le altre chiamate di funzione può essere molto diverso):

if (select(sock 1, &input_mask, NULL, NULL, NULL) < 0) { 

    fprintf(stderr, "select() failed: %s\n", strerror(errno)); 
    exit_nicely(conn); 
} 

PQconsumeInput(conn); 

while (PQisBusy(conn) != 0) { 

    /* wait here */ 

} 

while (PGresult* res = PQgetResult(conn)) { /* not sure this is OK, test for not null */ 

    /* do something with res */ 

} 
+0

Questo non aiuta. Il tuo codice potrebbe bloccarsi da quando chiami PQgetResult in un ciclo senza testare se la connessione è occupata. – JustMaximumPower

+0

Dal momento che aspetta su 'PQisBusy()' fino a quando non è più occupato e solo allora chiama 'PQgetResult()', io proprio non la penso così. (Potrei sbagliarmi lo stesso). Hai provato questo? – dezso

+0

A meno che non ho completamente frainteso il punto di PQsendQuery, allora una query mia essere raccolti in più blocchi, Ie frammenti di un grande tavolo. Quindi PQisBusy return 0 non indica che la query è finita, in quel caso la mia domanda sarebbe stata mood, indica solo che qualche input è disponibile. Convalidare questo codice testandolo non è in realtà una buona idea; il codice potrebbe non essere bloccato negli ambienti di laboratorio ma non garantisce che il codice non blocchi la produzione. – JustMaximumPower

3

penso quello che ti serve è PQsetSingleRowMode lasciare che PQgetResult restituisca una riga ogni volta.

da http://www.postgresql.org/docs/9.2/static/libpq-single-row-mode.html

Ordinariamente, libpq raccoglie intero risultato di un comando SQL e restituisce alla domanda di come un singolo PGresult. Questo può non essere possibile per i comandi che restituiscono un numero elevato di righe. Per tali casi, le applicazioni possono utilizzare PQsendQuery e PQgetResult in modalità a riga singola. In questa modalità, le righe dei risultati vengono restituite all'applicazione uno a in un momento, poiché vengono ricevute dal server.

Se la query restituisce tutte le righe, sono restituiti come singoli oggetti PGresult, che sembrano normali risultati delle query tranne avere il codice di stato PGRES_SINGLE_TUPLE invece di PGRES_TUPLES_OK. Dopo l'ultima riga, o immediatamente se la query restituisce zero righe, viene restituito un oggetto a riga zero con stato PGRES_TUPLES_OK; questo è il segnale che non arriveranno più righe.

check out il codice di esempio: https://github.com/markokr/libpq-rowproc-demos/blob/master/demo-onerow-async.c

+0

Il codice di esempio che è stato collegato per valutare il valore restituito da PQresultStatus per determinare se la query è terminata. Non mi piace lo stile di questo, ma credo che sia la soluzione migliore finora. Perciò ti darò la grazia, prima che sia perduta. – JustMaximumPower