pike.git / lib / modules / Sql.pmod / pgsql.pike

version» Context lines:

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)