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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql.pike:423:      final private string pinpointerror(void|string query,void|string offset) {    if(!query)    return "";    int k=(int)offset;    if(k<=0)    return MARKSTART+query+MARKEND;    return MARKSTART+(k>1?query[..k-2]:"")+MARKERROR+query[k-1..]+MARKEND;   }    - final private int decodemsg(void|state waitforstate) { + final int _decodemsg(void|state waitforstate) {   #ifdef DEBUG    { array line;   #ifdef DEBUGMORE    line=backtrace();   #endif    PD("Waiting for state %O %O\n",waitforstate,line&&line[sizeof(line)-2]);    }   #endif    while(mstate!=waitforstate) {    if(mstate!=unauthenticated) {
pike.git/lib/modules/Sql.pmod/pgsql.pike:630:    _portal->_datarowdesc=({});    mstate=gotrowdescription;    break;    case '2':PD("BindComplete\n");    msglen-=4;    mstate=bindcomplete;    break;    case 'D':PD("DataRow\n");    msglen-=4;    if(_portal) { + #ifdef USEPGsql +  conn.decodedatarow(msglen,_portal);msglen=0; + #else    array a, datarowdesc;    _portal->_bytesreceived+=msglen;    datarowdesc=_portal->_datarowdesc; - #ifdef USEPGsql -  a=conn.decodedatarow(msglen,datarowdesc);msglen=0; - #else +     int cols=GETINT16();    a=allocate(cols,UNDEFINED);    msglen-=2+4*cols;    foreach(a;int i;) {    int collen=GETINT32();    if(collen>0) {    msglen-=collen;    mixed value;    switch(datarowdesc[i]->type) {    default:value=GETSTRING(collen);
pike.git/lib/modules/Sql.pmod/pgsql.pike:664:    case INT2OID:value=GETINT16();    break;    case OIDOID:    case INT4OID:value=GETINT32();    }    a[i]=value;    }    else if(!collen)    a[i]="";    } +  a=({a}); +  _portal->_datarows+=a; +  _portal->_inflight-=sizeof(a);   #endif -  _portal->_datarows+=({a}); -  _portal->_inflight--; +     }    else    GETSTRING(msglen),msglen=0;    mstate=dataready;    break;    case 's':PD("PortalSuspended\n");    msglen-=4;    mstate=portalsuspended;    break;    case 'C':PD("CommandComplete\n");
pike.git/lib/modules/Sql.pmod/pgsql.pike:797:    if(zero_type(waitforstate))    break;    }    PD("Found state %O\n",mstate);    return mstate;   }      #ifndef UNBUFFEREDIO   private int read_cb(mixed foo, string d) {    conn.unread(d); -  do decodemsg(); +  do _decodemsg();    while(conn.peek(0)==1);    return 0;   }   #endif      final private void sendterminate() {    PD("Terminate\n");    SENDCMD(({"X",plugint32(4)}));    conn.close();   }
pike.git/lib/modules/Sql.pmod/pgsql.pike:845:    plugbuf+=({"database\0",database,"\0"});    foreach(sessiondefaults;string name;string value)    plugbuf+=({name,"\0",value,"\0"});    plugbuf+=({"\0"});    int len=4;    foreach(plugbuf;;string s)    len+=sizeof(s);    plugbuf[0]=plugint32(len);    SENDCMD(plugbuf);    PD("%O\n",plugbuf); -  decodemsg(readyforquery); +  _decodemsg(readyforquery);    PD("%O\n",runtimeparameter);   }      //! @decl void reload()   //!   //! Resets the connection to the database. Can be used for   //! a variety of reasons, for example to detect the status of a connection.   void reload(void|int special) {    mixed err;    int didsync;    if(err = catch {    sendclose();    PD("Portalsinflight: %d\n",portalsinflight);    if(!portalsinflight) {    PD("Sync\n");    SENDCMD(({"S",plugint32(4)}),1);    didsync=1;    if(!special) { -  decodemsg(readyforquery); +  _decodemsg(readyforquery);    foreach(prepareds;;mapping tprepared) {    m_delete(tprepared,"datatypeoid");    m_delete(tprepared,"datarowdesc");    }    }    }    }) {    PD("%O\n",err);    reconnect(1);    }    else if(didsync && special==2) -  decodemsg(readyforquery); +  _decodemsg(readyforquery);   #ifndef UNBUFFEREDIO    conn.set_read_callback(read_cb);   #endif   }      //! @decl void select_db(string dbname)   //!   //! This function allows you to connect to a database. Due to   //! restrictions of the Postgres frontend-backend protocol, you always   //! have to be connected to a database, so in fact this function just
pike.git/lib/modules/Sql.pmod/pgsql.pike:1165:    case INETOID:    case BPCHAROID:    case VARCHAROID:    case CTIDOID:    case UUIDOID:    return 1; //binary    }    return 0; // text   }    - final private void sendexecute(int fetchlimit) { + final void _sendexecute(int fetchlimit) {    string portalname=_portal->_portalname;    PD("Execute portal %s fetchlimit %d\n",portalname,fetchlimit);    SENDCMD(({"E",plugint32(4+sizeof(portalname)+1+4),portalname,    "\0",plugint32(fetchlimit)}),1);    _portal->_inflight+=fetchlimit;   }      final private void sendclose() {    string portalname;    portalsinflight--;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1338:    else {    _portal->_datatypeoid=tprepared->datatypeoid;    _portal->_datarowdesc=tprepared->datarowdesc;    }    { array(string) plugbuf=({"B",UNDEFINED});    int len=4+sizeof(portalname)+1+sizeof(preparedname)+1    +2+sizeof(paramValues)*(2+4)+2+2;    plugbuf+=({portalname,"\0",preparedname,"\0",    plugint16(sizeof(paramValues))});    if(!tprepared || !tprepared->datatypeoid) { -  decodemsg(gotparameterdescription); +  _decodemsg(gotparameterdescription);    if(tprepared)    tprepared->datatypeoid=_portal->_datatypeoid;    }    array dtoid=_portal->_datatypeoid;    foreach(dtoid;;int textbin)    plugbuf+=({plugint16(oidformat(textbin))});    plugbuf+=({plugint16(sizeof(paramValues))});    foreach(paramValues;int i;mixed value) {    if(zero_type(value))    plugbuf+=({plugint32(-1)}); // NULL
pike.git/lib/modules/Sql.pmod/pgsql.pike:1394:    break;    case INT4OID:len+=4;    plugbuf+=({plugint32(4),plugint32((int)value)});    break;    case INT2OID:len+=2;    plugbuf+=({plugint32(2),plugint16((int)value)});    break;    }    }    if(!tprepared || !tprepared->datarowdesc) { -  decodemsg(gotrowdescription); +  _decodemsg(gotrowdescription);    if(tprepared)    tprepared->datarowdesc=_portal->_datarowdesc;    }    { array a;int i;    len+=(i=sizeof(a=_portal->_datarowdesc))*2;    plugbuf+=({plugint16(i)});    foreach(a;;mapping col)    plugbuf+=({plugint16(oidformat(col->type))});    }    plugbuf[1]=plugint32(len);    PD("Bind portal %s statement %s\n",portalname,preparedname);    SENDCMD(plugbuf);   #ifdef DEBUGMORE    PD("%O\n",plugbuf);   #endif    }    _portal->_statuscmdcomplete=UNDEFINED; -  sendexecute(_fetchlimit && FETCHLIMITLONGRUN); +  _sendexecute(_fetchlimit && FETCHLIMITLONGRUN);    if(tprepared) { -  decodemsg(bindcomplete); +  _decodemsg(bindcomplete);    int tend=gethrtime();    if(tend==tstart)    m_delete(prepareds,q);    else {    tprepared->hit++;    totalhits++;    if(!tprepared->preparedname) {    if(sizeof(preparedname))    tprepared->preparedname=preparedname;    tstart=tend-tstart;
pike.git/lib/modules/Sql.pmod/pgsql.pike:1456:   //! streaming of multiple simultaneous queries through the same connection.   //!   //! @seealso   //! @[big_query], @[Sql.Sql], @[Sql.sql_result]   object streaming_query(string q,void|mapping(string|int:mixed) bindings) {    return big_query(q,bindings);   }      class pgsql_result {    - private object pgsqlsession; + object _pgsqlsess;   private int numrows;   private int eoffound;   private mixed delayederror;   private int copyinprogress;   int _fetchlimit;      private mapping tprepared;   #ifdef NO_LOCKING   int _qmtxkey;   #else   Thread.MutexKey _qmtxkey;   #endif      string query;   string _portalname;      int _bytesreceived; - private int rowsreceived; + int _rowsreceived;   int _interruptable;   int _inflight; -  + int _portalbuffersize;   string _statuscmdcomplete;   array(array(mixed)) _datarows;   array(mapping(string:mixed)) _datarowdesc;   array(int) _datatypeoid; -  + #ifdef USEPGsql + int _buffer; + #endif      private object fetchmutex;;      protected string _sprintf(int type, void|mapping flags) {    string res=UNDEFINED;    switch(type) {    case 'O':    res=sprintf(DRIVERNAME"_result numrows: %d eof: %d querylock: %d"    " inflight: %d portalname: %O\n"    "query: %O\n"    "laststatus: %s\n"    "%O\n"    "%O\n",    numrows,eoffound,!!_qmtxkey,_inflight,_portalname,    query,    _statuscmdcomplete||"",    _datarowdesc, -  pgsqlsession); +  _pgsqlsess);    break;    }    return res;   }    - void create(object _pgsqlsession,mapping(string:mixed) _tprepared, -  string _query,int fetchlimit,int _portalbuffersize) { -  pgsqlsession = _pgsqlsession; + void create(object pgsqlsess,mapping(string:mixed) _tprepared, +  string _query,int fetchlimit,int portalbuffersize) { +  _pgsqlsess = pgsqlsess;    tprepared = _tprepared; query = _query;    _datarows = ({ }); numrows = UNDEFINED;    fetchmutex = Thread.Mutex();    _fetchlimit=fetchlimit; -  portalbuffersize=_portalbuffersize; +  _portalbuffersize=portalbuffersize;    steallock();   }      //! Returns the command-complete status for this query.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   //!   //! @seealso   //! @[affected_rows]
pike.git/lib/modules/Sql.pmod/pgsql.pike:1559:      int eof() {    return eoffound;   }      array(mapping(string:mixed)) fetch_fields() {    return _datarowdesc+({});   }      private void releasesession() { -  if(pgsqlsession) { +  if(_pgsqlsess) {    if(copyinprogress) {    PD("CopyDone\n"); -  pgsqlsession.SENDCMD("c\0\0\0\4"); +  _pgsqlsess.SENDCMD("c\0\0\0\4");    } -  pgsqlsession->reload(2); +  _pgsqlsess.reload(2);    }    _qmtxkey=UNDEFINED; -  pgsqlsession=UNDEFINED; +  _pgsqlsess=UNDEFINED;   }      void destroy() {    catch { // inside destructors, exceptions don't work    releasesession();    };   }      inline private array(mixed) getdatarow() {    array(mixed) datarow=_datarows[0];    _datarows=_datarows[1..];    return datarow;   }      private void steallock() {   #ifndef NO_LOCKING -  PD("Going to steal oldportal %d\n",!!pgsqlsession._portal); +  PD("Going to steal oldportal %d\n",!!_pgsqlsess._portal);    Thread.MutexKey stealmtxkey = stealmutex.lock();    do    if(_qmtxkey = querymutex.current_locking_key()) {    pgsql_result portalb; -  if(portalb=pgsqlsession._portal) { -  pgsqlsession._nextportal++; +  if(portalb=_pgsqlsess._portal) { +  _pgsqlsess._nextportal++;    if(portalb->_interruptable)    portalb->fetch_row(2);    else {    PD("Waiting for the querymutex\n");    if((_qmtxkey=querymutex.lock(2))) {    if(copyinprogress)    ERROR("COPY needs to be finished first\n");    ERROR("Driver bug, please report, "    "conflict while interleaving SQL-operations\n");    }    PD("Got the querymutex\n");    } -  pgsqlsession._nextportal--; +  _pgsqlsess._nextportal--;    }    break;    }    while(!(_qmtxkey=querymutex.trylock()));   #else    PD("Skipping lock\n");    _qmtxkey=1;   #endif -  pgsqlsession._portal=this; +  _pgsqlsess._portal=this;    PD("Stealing successful\n");   }      int|array(string|int) fetch_row(void|int|string buffer) { -  + #ifndef NO_LOCKING +  Thread.MutexKey fetchmtxkey = fetchmutex.lock(); + #endif +  if(!buffer && sizeof(_datarows)) +  return getdatarow();    if(copyinprogress) { -  +  fetchmtxkey = UNDEFINED;    if(stringp(buffer)) {    PD("CopyData\n"); -  pgsqlsession.SENDCMD(({"d",plugint32(4+sizeof(buffer)),buffer})); +  _pgsqlsess.SENDCMD(({"d",plugint32(4+sizeof(buffer)),buffer}));    }    else    releasesession();    return UNDEFINED;    } - #ifndef NO_LOCKING -  Thread.MutexKey fetchmtxkey = fetchmutex.lock(); - #endif -  if(!buffer && sizeof(_datarows)) -  return getdatarow(); +     mixed err;    if(buffer!=2 && (err=delayederror)) {    delayederror=UNDEFINED;    throw(err);    }    err = catch {    if(_portalname) {    if(buffer!=2 && !_qmtxkey) {    steallock(); -  sendexecute(_fetchlimit); +  _pgsqlsess._sendexecute(_fetchlimit);    } -  while(pgsqlsession->_closesent) -  decodemsg(); // Flush previous portal sequence +  while(_pgsqlsess._closesent) +  _pgsqlsess._decodemsg(); // Flush previous portal sequence    for(;;) {   #ifdef DEBUGMORE    PD("buffer: %d nextportal: %d lock: %d\n", -  buffer,pgsqlsession._nextportal,!!_qmtxkey); +  buffer,_pgsqlsess._nextportal,!!_qmtxkey);   #endif -  switch(decodemsg()) { + #ifdef USEPGsql +  _buffer=buffer; + #endif +  switch(_pgsqlsess._decodemsg()) {    case copyinresponse:    copyinprogress=1;    return UNDEFINED;    case dataready:    if(tprepared) {    tprepared->trun=gethrtime()-tprepared->trunstart;    m_delete(tprepared,"trunstart");    tprepared = UNDEFINED;    }    mstate=dataprocessed; -  rowsreceived++; +  _rowsreceived++;    switch(buffer) {    case 0:    case 1:    if(_fetchlimit)    _fetchlimit= -  min(portalbuffersize/2*rowsreceived/_bytesreceived || 1, -  pgsqlsession->_fetchlimit); +  min(_portalbuffersize/2*_rowsreceived/_bytesreceived || 1, +  _pgsqlsess._fetchlimit);    }    switch(buffer) {    case 2:    case 3:    continue;    case 1:    _interruptable=1; -  if(pgsqlsession._nextportal) +  if(_pgsqlsess._nextportal)    continue; -  + #if STREAMEXECUTES +  if(_fetchlimit && _inflight<=_fetchlimit-1) +  _pgsqlsess._sendexecute(_fetchlimit); + #endif    return UNDEFINED;    }   #if STREAMEXECUTES    if(_fetchlimit && _inflight<=_fetchlimit-1) -  sendexecute(_fetchlimit); // Overlap Executes +  _pgsqlsess._sendexecute(_fetchlimit); // Overlap Executes   #endif    return getdatarow();    case commandcomplete:    releasesession();    switch(buffer) {    case 1:    case 2:    return UNDEFINED;    case 3:    if(sizeof(_datarows))    return getdatarow();    }    break;    case portalsuspended:    if(_inflight)    continue; -  if(pgsqlsession._nextportal) { +  if(_pgsqlsess._nextportal) {    switch(buffer) {    case 1:    case 2:    _qmtxkey = UNDEFINED;    return UNDEFINED;    case 3:    _qmtxkey = UNDEFINED;    return getdatarow();    }    _fetchlimit=FETCHLIMITLONGRUN;    if(sizeof(_datarows)) {    _qmtxkey = UNDEFINED;    return getdatarow();    }    buffer=3;    } -  sendexecute(_fetchlimit); +  _pgsqlsess._sendexecute(_fetchlimit);    default:    continue;    }    break;    }    }    eoffound=1;    return UNDEFINED;    };    PD("Exception %O\n",err); -  pgsqlsession->reload(); +  _pgsqlsess.reload();    if(buffer!=2)    throw(err);    if(!delayederror)    delayederror=err;    return UNDEFINED;   }      };