<%!-lpq%><%!-I/usr/include/postgresql%><%!-I/usr/include/postgresql/9.3/server%><%@ class mypage %><%#
#include <libpq-fe.h>
#include <postgres.h>
#include <catalog/pg_type.h>
#include <json/json.h>
#include <cpoll/threadpool.H>
#include <list>
#include "connectioninfo.H"
#include "generic_pool.H"
#include "world.H"

using namespace CP;
using namespace cppsp;
using namespace std;


struct myStatement
{
public:
	PGconn* db;
	int paramLengths[1];
	int paramFormats[1];
	File f;
	Poll* p;
	bool addedToPoll=false;
	myStatement() {
		db=doConnect_pg(NULL);
		Oid oid=INT4OID;
		PGresult* res;
		if((res=PQprepare(db, "zxcvb", "SELECT randomnumber FROM World where id=$1", 1, &oid))==NULL)
			goto fail;
		PQclear(res);
		paramLengths[0] = sizeof(int);
		paramFormats[0] = 1; //binary
		return;
	fail:
		doDisconnect_pg(NULL,db);
		throw runtime_error("error preparing statement");
	}
	~myStatement() {
		if(addedToPoll) {
			p->del(f);
		}
		f.deinit();
		doDisconnect_pg(NULL,db);
	}
	void exec(int id) {
		const char *params[1];
		id=htonl(id);
		params[0]=(const char*)&id;
		PQsendQueryPrepared(db,"zxcvb",1,params,paramLengths,paramFormats,1/*binary*/);
	}
};
myStatement* cStatement(void*) {
	return new myStatement();
}
void dStatement(void*, myStatement* s) {
	delete s;
}
genericPool<myStatement*,128> stmtPool(&cStatement,&dStatement);

%><%$
int queries=1;
world* items;
int n=0;
myStatement* stmt;
//asynchronously load the data in the doInit() function, and defer page rendering until data is available
void doInit() override {
	auto it=request->queryString.find("queries");
	if(it!=request->queryString.end()) {
		queries=atoi((*it).second);
	}
	if(queries<1)queries=1;
	if(queries>500)queries=500;
	int i;
	items=(world*)sp->alloc(sizeof(world)*queries);
	stmt=stmtPool.get();
	if(!stmt->addedToPoll) {
		poll->add(stmt->f);
		stmt->addedToPoll=true;
		stmt->p=poll;
	}
	beginGetItems();
}
void beginGetItems() {
	if(n>=queries) {
		stmtPool.put(stmt);
		Page::doInit();
		return;
	}
	items[n++].id=rand()%10000;
	stmt->exec(items[n-1].id);
	stmt->f.waitForEvent(Events::in,{&mypage::evtIn,this});
}
void evtIn(int) {
	PGresult* res;
	res=PQgetResult(stmt->db);
	PGresult* res1;
	while((res1=PQgetResult(stmt->db))!=NULL) {
		PQclear(res1);
	}
	int tmp;
	if(PQntuples(res)>0)
		tmp=*(const int*)PQgetvalue(res,0,0);
	else tmp=0;
	items[n-1].rnd=ntohl(tmp);
	PQclear(res);
	beginGetItems();
}
%><%
if(queries>1) {
	%>[<%
}
for (int i=0;i<queries;i++){
	if(i>0) output.write(',');
	%>{"id":<%=items[i].id%>,"randomNumber":<%=items[i].rnd%>}<%
}
if(queries>1) {
        %>]<%
}
%><%
response->headers["Content-Type"]="application/json";
response->headers["Server"]="cppsp/0.2";
%>
