pike.git
/
lib
/
modules
/
Sql.pmod
/
pgsql.pike
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Sql.pmod/pgsql.pike:64:
inherit __builtin.Sql.Connection; final int _fetchlimit=FETCHLIMIT; final Thread.Mutex _unnamedportalmux; private Thread.Mutex unnamedstatement; private Thread.MutexKey termlock; final int _portalsinflight; final int _statementsinflight; final int _wasparallelisable;
+
final int _intransaction;
private .pgsql_util.conxion c; private string cancelsecret; private int backendpid, backendstatus; final mapping(string:mixed) _options; private array(string) lastmessage=({}); private int clearmessage; private mapping(string:array(mixed)) notifylist=([]); final mapping(string:string) _runtimeparameter; final mapping(string:mapping(string:mixed)) _prepareds=([]);
pike.git/lib/modules/Sql.pmod/pgsql.pike:637:
private void procmessage() { mixed err; int terminating=0; err = catch { .pgsql_util.conxion ci=c; // cache value FIXME sensible? .pgsql_util.conxiin cr=ci->i; // cache value FIXME sensible? #ifdef PG_DEBUG PD("Processloop\n");
+
#ifdef PG_DEBUGMORE
+
void showportalstack(string label) {
+
PD(sprintf(">>>>>>>>>>> Portalstack %s: %O\n", label, portal));
+
foreach(qportals->peek_array();;int|.pgsql_util.sql_result qp)
+
PD(" =========== Portal: %O\n",qp);
+
PD("<<<<<<<<<<<<<< Portalstack end\n");
+
};
+
#endif
void showportal(int msgtype) { if(objectp(portal)) PD("%d<%O %d %c switch portal\n", ci->socket->query_fd(),portal._portalname,++ci->queueinidx,msgtype); else if(portal>0) PD("%d<Sync %d %d %c portal\n", ci->socket->query_fd(),++ci->queueinidx,portal,msgtype); }; #endif for(;;) { err=catch { #ifdef PG_DEBUG if(!portal && datarowdebug) { PD("%s rows %d\n",datarowdebug,datarowdebugcount); datarowdebug=0; datarowdebugcount=0; } #endif
-
+
#ifdef PG_DEBUGMORE
+
showportalstack("LOOPTOP");
+
#endif
if(!sizeof(cr)) { // Preliminary check, fast path Thread.MutexKey lock=cr->fillreadmux->lock(); if(!sizeof(cr)) { // Check for real if(!cr->fillread) { lock=0; throw(MAGICTERMINATE); // Force proper termination } cr->procmsg=1; lock=0; return; // Terminate thread, wait for callback
pike.git/lib/modules/Sql.pmod/pgsql.pike:822:
errtype=PROTOCOLERROR; #endif break; } case '3': #ifdef PG_DEBUG PD("CloseComplete\n"); msglen-=4; #endif break;
-
case 'Z':
+
case 'Z':
{
backendstatus=cr->read_int8(); #ifdef PG_DEBUG msglen-=4+1; PD("ReadyForQuery %c\n",backendstatus); #endif
-
for(;objectp(portal);portal=qportals->read()) {
+
#ifdef
PG_DEBUGMORE
+
showportalstack("READYFORQUERY");
+
#endif
+
int keeplooking;
+
do
+
for(
keeplooking = 0
;
objectp(portal);
portal
=
qportals->read()) {
#ifdef PG_DEBUG showportal(msgtype); #endif
-
+
if (backendstatus == 'I' && _intransaction
+
&& portal->transtype != TRANSEND)
+
keeplooking = 1;
portal->_purgeportal(); }
-
+
while (keeplooking && (portal = qportals->read()));
+
if (backendstatus == 'I')
+
_intransaction = 0;
foreach(qportals->peek_array();;.pgsql_util.sql_result qp) { if(objectp(qp) && qp._synctransact && qp._synctransact<=portal) { PD("Checking portal %O %d<=%d\n", qp._portalname,qp._synctransact,portal); qp->_purgeportal(); } } portal=0;
-
+
#ifdef PG_DEBUGMORE
+
showportalstack("AFTER READYFORQUERY");
+
#endif
_readyforquerycount--; if(readyforquery_cb) readyforquery_cb(),readyforquery_cb=0; destruct(waitforauthready); break;
-
+
}
case '1': #ifdef PG_DEBUG
-
PD("
ParseComplete\n
");
+
PD("
ParseComplete portal %O\n
"
, portal
);
msglen-=4; #endif break; case 't': { array a; #ifdef PG_DEBUG int cols=cr->read_int16(); PD("%O ParameterDescription %d values\n",portal._query,cols); msglen-=4+2+4*cols; a=cr->read_ints(cols,4);
pike.git/lib/modules/Sql.pmod/pgsql.pike:940:
case 'H': portal->_processrowdesc(@getcols()); PD("CopyOutResponse %O\n",portal._query); break; case '2': { mapping tp; #ifdef PG_DEBUG msglen-=4; PD("%O BindComplete\n",portal._portalname); #endif
-
if(tp=portal._tprepared) {
-
int tend=gethrtime();
-
int tstart=tp.trun;
-
if(tend==tstart)
+
if
(tp=portal._tprepared) {
+
int tend
=
gethrtime();
+
int tstart
=
tp.trun;
+
if
(tend
==
tstart)
m_delete(_prepareds,portal._query); else { tp.hits++; totalhits++;
-
if(!tp.preparedname) {
-
if(sizeof(portal._preparedname))
-
tp.preparedname=portal._preparedname;
-
tstart=tend-tstart;
-
if(!tp
.
tparse || tp.tparse>tstart
)
-
tp.
tparse
=
tstart
;
+
if
(!tp.preparedname) {
+
if
(sizeof(portal._preparedname))
{
+
PD("Finalising stored statement %s\n",
portal._preparedname
)
;
+
tp.
preparedname
=
portal
.
_preparedname
;
}
-
tp.
trunstart
=
tend
;
+
tstart = tend - tstart;
+
if (!
tp.
tparse || tp.tparse>tstart)
+
tp.tparse
=
tstart
;
}
-
+
tp.trunstart = tend;
}
-
+
}
break; } case 'D': msglen-=4; #ifdef PG_DEBUG #ifdef PG_DEBUGMORE PD("%O DataRow %d bytes\n",portal._portalname,msglen); #endif datarowdebugcount++;
-
if(!datarowdebug)
-
datarowdebug=sprintf(
+
if
(!datarowdebug)
+
datarowdebug
=
sprintf(
"%O DataRow %d bytes",portal._portalname,msglen); #endif #ifdef PG_DEBUG msglen= #endif portal->_decodedata(msglen,_runtimeparameter[CLIENT_ENCODING]); break; case 's': #ifdef PG_DEBUG PD("%O PortalSuspended\n",portal._portalname);
pike.git/lib/modules/Sql.pmod/pgsql.pike:999:
string s=cr->read(msglen-1); portal->_storetiming(); PD("%O CommandComplete %O\n",portal._portalname,s); #ifdef PG_DEBUG if(cr->read_int8()) errtype=PROTOCOLERROR; msglen=0; #else cr->consume(1); #endif
+
#ifdef PG_DEBUGMORE
+
showportalstack("COMMANDCOMPLETE");
+
#endif
portal->_releasesession(s); portal=0; break; } case 'I': #ifdef PG_DEBUG PD("EmptyQueryResponse %O\n",portal._portalname); msglen-=4; #endif
-
+
#ifdef PG_DEBUGMORE
+
showportalstack("EMPTYQUERYRESPONSE");
+
#endif
portal->_releasesession(); portal=0; break; case 'd': PD("%O CopyData\n",portal._portalname); portal->_storetiming(); msglen-=4; #ifdef PG_DEBUG if(msglen<0) errtype=PROTOCOLERROR;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1038:
portal._state=COPYINPROGRESS; break; case 'c': #ifdef PG_DEBUG PD("%O CopyDone\n",portal._portalname); msglen-=4; #endif portal=0; break; case 'E': {
-
if (_portalsinflight
<= 1
&& !_readyforquerycount)
+
#ifdef
PG_DEBUGMORE
+
showportalstack("ERRORRESPONSE");
+
#endif
+
if (
!
_portalsinflight && !_readyforquerycount)
sendsync(); PD("%O ErrorResponse %O\n", objectp(portal)&&(portal._portalname||portal._preparedname), objectp(portal)&&portal._query); mapping(string:string) msgresponse; msgresponse=getresponse(); warningsdropcount+=warningscollected; warningscollected=0; switch(msgresponse.C) { case "P0001":
pike.git/lib/modules/Sql.pmod/pgsql.pike:1077:
lastmessage+=({ pinpointerror(objectp(portal)&&portal._query,msgresponse.P)+ pinpointerror(msgresponse.q,msgresponse.p)}); if(msgresponse.W) lastmessage+=({msgresponse.W}); if(objectp(portal)) lastmessage+=showbindings(portal); switch(msgresponse.S) { case "PANIC":werror(a2nls(lastmessage)); }
-
case "25P02": // Preserve last error message
-
USERERROR(a2nls(lastmessage));
+
case "25P02":
// Preserve last error message
+
USERERROR(a2nls(lastmessage));
// Implicitly closed portal
} break; } case 'N': { PD("NoticeResponse\n"); mapping(string:string) msgresponse; msgresponse=getresponse(); if(clearmessage) { warningsdropcount+=warningscollected; clearmessage=warningscollected=0;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1175:
CHAIN(cs)->add("X\0\0\0\4"); cs->sendcmd(SENDOUT); terminating=1; err=0; } else if(stringp(err)) { .pgsql_util.sql_result or; if(!objectp(or=portal)) or=this; if(!or._delayederror) or._delayederror=err;
+
#ifdef PG_DEBUGMORE
+
showportalstack("THROWN");
+
#endif
if(objectp(portal)) portal->_releasesession(); portal=0; if(!waitforauthready) continue; // Only continue if authentication did not fail } break; } PD("Closing database processloop %O\n",err); _delayederror=err;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1872:
from=({from,to,paramValues}); } } else paramValues=({}); if(String.width(q)>8) ERROR("Wide string literals in %O not supported\n",q); if(has_value(q,"\0")) ERROR("Querystring %O contains invalid literal nul-characters\n",q); mapping(string:mixed) tp; int tstart;
+
/*
+
* FIXME What happens with regards to this detection when presented with
+
* multistatement text-queries?
+
*/
+
int transtype = .pgsql_util.transendprefix->match(q) ? TRANSEND
+
: .pgsql_util.transbeginprefix->match(q) ? TRANSBEGIN : NOTRANS;
if(!forcetext && forcecache==1 || forcecache!=0
-
&& (sizeof(q)>=MINPREPARELENGTH ||
.pgsql_util.cachealways[q]
)) {
+
&& (sizeof(q)>=MINPREPARELENGTH ||
transtype != NOTRANS
)) {
object plugbuffer; while(catch(plugbuffer=c->start())) reconnect(); if(tp=_prepareds[q]) { if(tp.preparedname) { #ifdef PG_STATS prepstmtused++; #endif preparedname=tp.preparedname; } else if((tstart=tp.trun)
pike.git/lib/modules/Sql.pmod/pgsql.pike:1922:
} if(sizeof(CHAIN(plugbuffer))) { PD("%O\n",(string)CHAIN(plugbuffer)); plugbuffer->sendcmd(FLUSHSEND); // close expireds } else plugbuffer->sendcmd(KEEP); // close start() tstart=gethrtime(); } else // sql_result autoassigns to portal tp=UNDEFINED; .pgsql_util.sql_result portal;
-
portal=.pgsql_util.sql_result(this,c,q,
-
portalbuffersize, _alltyped, from, forcetext, timeout, syncparse);
+
portal=.pgsql_util.sql_result(this,c,q, portalbuffersize, _alltyped, from,
+
forcetext, timeout, syncparse
, transtype
);
portal._tprepared=tp; #ifdef PG_STATS portalsopened++; #endif clearmessage=1; if(forcetext) { // FIXME What happens if portals are still open? portal._unnamedportalkey=_unnamedportalmux->lock(1); portal._portalname=""; portal->_parseportal(); portal->_bindportal(); _readyforquerycount++;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1961:
Inside #if 0
->add_hstring(({preparedname,0,q,"\0\0\0"}),4,4) #if 0 // Even though the protocol doesn't require the Parse command to be // followed by a flush, it makes a VERY noticeable difference in // performance if it is omitted; seems like a flaw in the PostgreSQL // server v8.3.3 // In v8.4 and later, things speed up slightly when it is omitted. ->add(PGFLUSH) #endif ;
-
}
+
}
else
+
PD("Using prepared statement for %O\n", q);
portal._preparedname=preparedname; if(!tp || !tp.datatypeoid) { PD("Describe statement %O\n",preparedname); if (!plugbuffer) plugbuffer = c->start(); CHAIN(plugbuffer)->add_int8('D') ->add_hstring(({'S', preparedname, 0}), 4, 4); plugbuffer->sendcmd(FLUSHSEND,portal); } else { if(plugbuffer)