Example #1
0
/**
 * if the connection is bad, disconnect
 * 
 * if the connection is established,
 *  call PQconsumeInput
 *  if PGisBusy returns != 0, a query is done, and we can process it
 *  while PQgetResult returns != NULL,
 *   we retrieve data and add it to our result
 *   we recognize bytea data by oid, and unescape it
 *   once this is done, we call the callback for the result
 *   while the callback is running
 *    we have to lock the connection, 
 *    to make sure the callback does not add a query 
 *    which could interfere with the current query.
 *   once the callback is done, check if there are queries to be sent, 
 *   if so, sent them
 *    
 * 
 * 
 * if the connection is pending,
 *  check if the previous call to PQconnectPoll
 *  told us we want to recv data, if so, call PQconnectPoll
 *  else, there is something wrong with the connection (connection refused)
 *  and we call PQconnectPoll and check for a dead connection.
 * 
 * @return 
 */
int32_t SQLHandlerPostgres::doRecv()
{
	logPF();

	switch ( PQstatus(m_PGConnection) )
	{
	case CONNECTION_BAD:
		disconnected();
		break;

	case CONNECTION_OK:
		{

			if ( PQconsumeInput(m_PGConnection) != 1 )
			{
				logInfo("PQcomsumeInput() failed %s\n",PQerrorMessage(m_PGConnection));
				disconnected();
				return 1;
			}

			if ( PQisBusy(m_PGConnection) != 0 )
				return 1;

			if ( PQstatus(m_PGConnection) == CONNECTION_BAD )
			{
				logInfo("PQstatus() says BAD %s\n",PQerrorMessage(m_PGConnection));
				disconnected();
				return 1;
			}

			if ( m_Queries.size() == 0 )
			{
//				logCrit("Why did I end up here %s:%i?\n status %i \n message %s? \n",__FILE__,__LINE__, PQstatus(m_PGConnection),PQerrorMessage(m_PGConnection));
				return 1;
			}

			PGresult   *res=NULL;
			PGSQLResult *sqlresult = NULL;
			SQLQuery *sqlquery = m_Queries.front();
			m_Queries.pop_front();

//	int foo = rand()%1024;

			vector< map<string,string> >        result;
			bool broken_query=false;

			while ( (res = PQgetResult(m_PGConnection)) != NULL )
			{
//		logCrit("README %i %x %x\n",foo,res,sqlquery);
				switch ( PQresultStatus(res) )
				{
				
				case PGRES_COMMAND_OK:
					break;

				case PGRES_TUPLES_OK:
					if ( sqlquery->getCallback() != NULL )
					{
						int i,j;
						for ( j = 0;  j < PQntuples(res); j++ )
						{
							map<string,string> foo;
							string bar;
							string baz;

							for ( i=0;i<PQnfields(res);i++ )
							{
								switch ( PQftype(res,i) )
								{
								case 17: // BYTEAOID
									bar = PQgetvalue(res, j, i);
									baz = unescapeBinary(&bar);
									foo[PQfname(res,i)] = string(baz.data(),baz.size());
									break;

								default:
									foo[PQfname(res,i)] = PQgetvalue(res, j, i);
								}
							}
							result.push_back(foo);
						}
					}
					break;

				default:
					logCrit("Query failure. Query'%s' Error '%s' ('%s')\n",
							sqlquery->getQuery().c_str(),
							PQresStatus(PQresultStatus(res)),
							PQresultErrorMessage(res));
					broken_query = true;
				}

				PQclear(res);

			}
			if ( sqlquery->getCallback() != NULL )
			{
				m_LockSend = true;

				sqlresult = new PGSQLResult(&result,sqlquery->getQuery(),sqlquery->getObject());
				if ( broken_query == true )
				{
					sqlquery->getCallback()->sqlFailure(sqlresult);
				}
				else
				{
					sqlquery->getCallback()->sqlSuccess(sqlresult);
				}

				delete sqlresult;
				m_LockSend = false;

			}

			delete sqlquery;



			if ( m_Queries.size() > 0 )
			{
				logInfo("sending query %s\n",m_Queries.front()->getQuery().c_str());
				int ret = PQsendQuery(m_PGConnection, m_Queries.front()->getQuery().c_str());
				if ( ret != 1 )
					logCrit("ERROR %i %s\n",ret,PQerrorMessage(m_PGConnection));
			}
		}
		break;

	default:
		if (m_PollingStatusType == PGRES_POLLING_READING)
		{
        		m_PollingStatusType = PQconnectPoll(m_PGConnection);
				if (PQstatus(m_PGConnection) == CONNECTION_OK)
					connected();
				else 
				if (PQstatus(m_PGConnection) == CONNECTION_BAD)
					logCrit("ERROR %s\n",PQerrorMessage(m_PGConnection));

		}else
		{
			m_PollingStatusType = PQconnectPoll(m_PGConnection);
			if (PQstatus(m_PGConnection) == CONNECTION_BAD)
			{
				logCrit("ERROR %s\n",PQerrorMessage(m_PGConnection));
			}
		}
	}

	m_LastAction = time(NULL);
	return 1;
}