@@ -39,6 +39,32 @@ void query_failed(GLua::ILuaInterface* lua, Connection* state) {
3939 }
4040}
4141
42+ inline bool bad_result (PGresult* result) {
43+ if (!result) {
44+ return true ;
45+ }
46+
47+ auto status = PQresultStatus (result);
48+
49+ return status == PGRES_BAD_RESPONSE || status == PGRES_NONFATAL_ERROR ||
50+ status == PGRES_FATAL_ERROR;
51+ }
52+
53+ void query_result (GLua::ILuaInterface* lua, pg::result&& result,
54+ GLua::AutoReference& callback) {
55+ if (callback.Push ()) {
56+ if (!bad_result (result.get ())) {
57+ lua->PushBool (true );
58+ create_result_table (lua, result.get ());
59+ } else {
60+ lua->PushBool (false );
61+ lua->PushString (PQresultErrorMessage (result.get ()));
62+ }
63+
64+ pcall (lua, 2 , 0 );
65+ }
66+ }
67+
4268// returns true if poll was successful
4369// returns false if there was an error
4470inline bool poll_query (PGconn* conn, Query& query) {
@@ -55,15 +81,39 @@ inline bool poll_query(PGconn* conn, Query& query) {
5581 return true ;
5682}
5783
58- bool bad_result (PGresult* result) {
84+ void process_result (GLua::ILuaInterface* lua, Connection* state,
85+ pg::result&& result) {
86+ // query is done
5987 if (!result) {
60- return true ;
88+ state->query .reset ();
89+ return process_query (lua, state);
6190 }
6291
63- auto status = PQresultStatus (result);
92+ // next result might be empty,
93+ // that means that query is done
94+ // and we need to remove query from the state
95+ // so callback can add another query
96+ if (!pg::isBusy (state->conn )) {
97+ auto next_result = pg::getResult (state->conn );
98+ if (!next_result) {
99+ // query is done, we need to remove query from the state
100+ Query query = std::move (*state->query );
101+ state->query .reset ();
64102
65- return status == PGRES_BAD_RESPONSE || status == PGRES_NONFATAL_ERROR ||
66- status == PGRES_FATAL_ERROR;
103+ query_result (lua, std::move (result), query.callback );
104+
105+ // callback might added another query, process it rightaway
106+ process_query (lua, state);
107+ } else {
108+ // query is not done, but also since we own next result
109+ // we need to call query callback and process next result
110+ query_result (lua, std::move (result), state->query ->callback );
111+ process_result (lua, state, std::move (next_result));
112+ }
113+ } else {
114+ // query is not done, but we don't need to process next result
115+ query_result (lua, std::move (result), state->query ->callback );
116+ }
67117}
68118
69119void async_postgres::process_query (GLua::ILuaInterface* lua,
@@ -90,26 +140,8 @@ void async_postgres::process_query(GLua::ILuaInterface* lua,
90140 return process_query (lua, state);
91141 }
92142
93- while (PQisBusy (state->conn .get ()) == 0 ) {
94- auto result = pg::getResult (state->conn );
95- if (!result) {
96- // query is done
97- // TODO: remove query if we have a final result
98- state->query .reset ();
99- return process_query (lua, state);
100- }
101-
102- if (query.callback ) {
103- query.callback .Push ();
104- if (!bad_result (result.get ())) {
105- lua->PushBool (true );
106- create_result_table (lua, result.get ());
107- } else {
108- lua->PushBool (false );
109- lua->PushString (PQresultErrorMessage (result.get ()));
110- }
111-
112- pcall (lua, 2 , 0 );
113- }
143+ // ensure that getting result won't block
144+ if (!pg::isBusy (state->conn )) {
145+ return process_result (lua, state, pg::getResult (state->conn ));
114146 }
115147}
0 commit comments