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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql.pike:26: Inside #if defined(DEBUG)
     #ifdef DEBUG   #define PD(X ...) werror(X)   #define UNBUFFEREDIO 1 // Make all IO unbuffered   #else   #undef DEBUGMORE   #define PD(X ...)   #endif   //#define NO_LOCKING 1 // This breaks the driver, do not enable,    // only for benchmarking mutex performance + #define USEPGsql 1 // Doesn't use Stdio.FILE, but PG assist    -  + #ifdef USEPGsql + #define UNBUFFEREDIO 1 + #endif +    #define FETCHLIMIT 1024 // Initial upper limit on the    // number of rows to fetch across the    // network at a time    // 0 for no chunking    // Needs to be >0 for interleaved    // portals   #define FETCHLIMITLONGRUN 1 // for long running background queries   #define STREAMEXECUTES 1 // streams executes if defined - #define MINPREPARELENGTH 64 // statements shorter than this will not + #define MINPREPARELENGTH 16 // statements shorter than this will not    // be cached   #define PGSQL_DEFAULT_PORT 5432   #define PGSQL_DEFAULT_HOST "localhost"   #define PREPSTMTPREFIX "pike_prep_"   #define PORTALPREFIX "pike_portal_"   #define FACTORPLAN 8   #define DRIVERNAME "pgsql"   #define MARKSTART "{""{""{""{\n" // split string to avoid   #define MARKERROR ">>>>" // foldeditors from recognising   #define MARKEND "\n}""}""}""}" // it as a fold
pike.git/lib/modules/Sql.pmod/pgsql.pike:81:   private mapping(string:mapping(string:mixed)) prepareds=([]);   private int pstmtcount;   private int pportalcount;   private int totalhits;   private int cachedepth=1024; // Maximum cachecountsum for prepared statements,    // may be tuned by the application   private int timeout=4096; // Queries running longer than this number of    // seconds are canceled automatically   private int portalbuffersize=64*1024; // Approximate buffer per portal   private int reconnected; // Number of times the connection was reset + #ifndef USEPGsql   private int flushed; -  + #endif      private string host, database, user, pass;   private int port;   private mapping(string:string) sessiondefaults=([]); // runtime parameters   private Thread.Mutex querymutex;   private Thread.Mutex stealmutex;      protected string _sprintf(int type, void|mapping flags) {    string res=UNDEFINED;    switch(type) {
pike.git/lib/modules/Sql.pmod/pgsql.pike:201:      //! @decl string host_info()   //!   //! This function returns a string describing what host are we talking to,   //! and how (TCP/IP or UNIX sockets).      string host_info() {    return sprintf("Via fd:%d over TCP/IP to %s:%d",conn->query_fd(),host,port);   }    - final private int sendcmd(string|array(string) data,void|int flush) { -  if(flush) { -  if(stringp(data)) -  data=({data,FLUSH}); -  else -  data+=({FLUSH}); -  PD("Flush\n"); -  flushed=1; -  } -  else -  flushed=0; -  return conn.write(data); - } + #ifdef USEPGsql + #define GETBYTE() conn.getbyte() + #define GETSTRING(x) conn.getstring(x) + #define GETINT16() conn.getint16() + #define GETINT32() conn.getint32() + #define FLUSHED conn.flushed + #else + #define GETBYTE() getbyte() + #define GETSTRING(x) getstring(x) + #define GETINT16() getint16() + #define GETINT32() getint32() + #define FLUSHED flushed      final private void sendflush() { -  sendcmd(({}),1); +  SENDCMD(({}),1);   }      inline final private int getbyte() { -  if(!flushed && !conn.peek(0)) +  if(!FLUSHED && !conn.peek(0))    sendflush();   #ifdef UNBUFFEREDIO    return conn.read(1)[0];   #else    return conn.getchar();   #endif   }    - final private string getstring(int len) { + final private string getstring(void|int len) { +  if(!zero_type(len)) {    string acc="",res;    do { -  if(!flushed && !conn.peek(0)) +  if(!FLUSHED && !conn.peek(0))    sendflush(); -  res=conn.read(len,!flushed); +  res=conn.read(len,!FLUSHED);    if(res) {    if(!sizeof(res))    return acc;    acc+=res;    }    }    while(sizeof(acc)<len&&res);    return sizeof(acc)?acc:res;    } -  +  array(int) acc=({}); +  int c; +  while((c=GETBYTE())>0) +  acc+=({c}); +  return `+("",@map(acc,String.int2char)); + }      inline final private int getint16() { -  int s0=getbyte(); -  int r=(s0&0x7f)<<8|getbyte(); +  int s0=GETBYTE(); +  int r=(s0&0x7f)<<8|GETBYTE();    return s0&0x80 ? r-(1<<15) : r ;   }      inline final private int getint32() { -  int r=getint16(); -  r=r<<8|getbyte(); -  return r<<8|getbyte(); +  int r=GETINT16(); +  r=r<<8|GETBYTE(); +  return r<<8|GETBYTE();   }      inline final private int getint64() { -  int r=getint32(); -  r=r<<8|getbyte(); -  r=r<<8|getbyte(); -  r=r<<8|getbyte(); -  return r<<8|getbyte(); +  int r=GETINT32(); +  return r<<32|GETINT32()&0xffffffff;   } -  + #endif    -  + #define SENDCMD(x ...) sendcmd(x) +  + final private int sendcmd(string|array(string) data,void|int flush) { +  if(flush) { +  if(stringp(data)) +  data=({data,FLUSH}); +  else +  data+=({FLUSH}); +  PD("Flush\n"); +  FLUSHED=1; +  } +  else if(FLUSHED!=-1) +  FLUSHED=0; +  return conn.write(data); + } +    #define plugstring(x) (sprintf x)      #define plugbyte(x) sprintf("%c",x)      inline final private string plugint16(int x) {    return sprintf("%c%c",x>>8&255,x&255);   }      inline final private string plugint32(int x) {    return sprintf("%c%c%c%c",x>>24&255,x>>16&255,x>>8&255,x&255);   }      inline final private string plugint64(int x) {    return sprintf("%c%c%c%c%c%c%c%c",    x>>56&255,x>>48&255,x>>40&255,x>>32&255,x>>24&255,x>>16&255,x>>8&255,x&255);   }    -  + #ifdef USEPGsql + class PGassist { +  inherit Stdio.File:std; +  inherit _PGsql.PGsql:pg; +  void create() { +  std::create(); +  } +  int connect(string host,int port) { +  int res=std::connect(host,port); +  if(res) +  pg::create(std::query_fd()); +  return res; +  } + } + #endif +    final private object getsocket() { -  + #ifdef USEPGsql +  object lcon = PGassist(); + #else   #ifdef UNBUFFEREDIO    object lcon = Stdio.File();   #else    object lcon = Stdio.FILE();   #endif -  +  flushed=-1; + #endif    return lcon.connect(host,port) && lcon;   }      //! Cancels the currently running query.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   void cancelquery() {    if(qstate==inquery) {    qstate=cancelpending;
pike.git/lib/modules/Sql.pmod/pgsql.pike:315:    }   }      //! Returns the old cachedepth, sets the new cachedepth for prepared   //! statements automatic caching.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   int setcachedepth(void|int newdepth) {    int olddepth=cachedepth; -  if(intp(newdepth) && newdepth>=0) +  if(!zero_type(newdepth) && newdepth>=0)    cachedepth=newdepth;    return olddepth;   }      //! Returns the old timeout, sets the new timeout for long running   //! queries.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   int settimeout(void|int newtimeout) {    int oldtimeout=timeout; -  if(intp(newtimeout) && newtimeout>0) +  if(!zero_type(newtimeout) && newtimeout>0)    timeout=newtimeout;    return oldtimeout;   }      //! Returns the old portalbuffersize, sets the new portalbuffersize   //! for buffering partially concurrent queries.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   int setportalbuffersize(void|int newportalbuffersize) {    int oldportalbuffersize=portalbuffersize; -  if(intp(newportalbuffersize) && newportalbuffersize>0) +  if(!zero_type(newportalbuffersize) && newportalbuffersize>0)    portalbuffersize=newportalbuffersize;    return oldportalbuffersize;   }      //! Returns the old fetchlimit, sets the new fetchlimit to interleave   //! queries.   //!   //! This function is PostgreSQL-specific, and thus it is not available   //! through the generic SQL-interface.   int setfetchlimit(void|int newfetchlimit) {    int oldfetchlimit=_fetchlimit; -  if(intp(newfetchlimit) && newfetchlimit>=0) +  if(!zero_type(newfetchlimit) && newfetchlimit>=0)    _fetchlimit=newfetchlimit;    return oldfetchlimit;   }      final private string glob2reg(string glob) {    if (!glob||!sizeof(glob))    return "%";    return replace(glob,({"*","?","\\","%","_"}),({"%","_","\\\\","\\%","\\_"}));   }   
pike.git/lib/modules/Sql.pmod/pgsql.pike:388: Inside #if defined(DEBUG) and #if defined(DEBUGMORE)
  #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) {    if(qstate==cancelpending)    qstate=canceled,sendclose(); -  if(flushed && qstate==inquery && !conn.peek(0)) { +  if(FLUSHED && qstate==inquery && !conn.peek(0)) {    int tcurr=time();    int told=tcurr+timeout; -  while(!conn.peek(tcurr-told)) +  while(!conn.peek(told-tcurr))    if((tcurr=time())-told>=timeout) {    sendclose();cancelquery();    break;    }    }    } -  int msgtype=getbyte(); -  int msglen=getint32(); +  int msgtype=GETBYTE(); +  int msglen=GETINT32();    enum errortype { noerror=0, protocolerror, protocolunsupported };    errortype errtype=noerror;    switch(msgtype) {    void getcols() { -  int bintext=getbyte(); +  int bintext=GETBYTE();    array a; -  int cols=getint16(); +  int cols=GETINT16();    msglen-=4+1+2+2*cols;    foreach(a=allocate(cols,([]));;mapping m) -  m->type=getint16(); +  m->type=GETINT16();    if(_portal) {    a=({(["type":bintext?BYTEAOID:TEXTOID,"name":"line"])});    _portal->_datarowdesc=a;    }    mstate=gotrowdescription;    };    array(string) getstrings() {    string s;    if(msglen<1)    errtype=protocolerror; -  s=getstring(msglen); +  s=GETSTRING(msglen);    if(s[--msglen])    errtype=protocolerror;    if(!msglen)    return ({});    s=s[..msglen-1];msglen=0;    return s/"\0";    };    void getresponse() {    msglen-=4;    msgresponse=([]);    foreach(getstrings();;string f)    if(sizeof(f))    msgresponse[f[..0]]=f[1..];    PD("%O\n",msgresponse);    };    case 'R':PD("Authentication\n");    { string sendpass;    int authtype;    msglen-=4+4; -  switch(authtype=getint32()) { +  switch(authtype=GETINT32()) {    case 0:PD("Ok\n");    mstate=authenticated;    break;    case 2:PD("KerberosV5\n");    errtype=protocolunsupported;    break;    case 3:PD("ClearTextPassword\n");    sendpass=pass;    break;    case 4:PD("CryptPassword\n");    if(msglen<2)    errtype=protocolerror; -  sendpass=getstring(msglen);msglen=0; +  sendpass=GETSTRING(msglen);msglen=0;    errtype=protocolunsupported;    break;    case 5:PD("MD5Password\n");    if(msglen<4)    errtype=protocolerror;   #if constant(Crypto.MD5.hash)   #define md5hex(x) String.string2hex(Crypto.MD5.hash(x))    sendpass=md5hex(pass+user); -  sendpass="md5"+md5hex(sendpass+getstring(msglen)); +  sendpass="md5"+md5hex(sendpass+GETSTRING(msglen));   #else -  getstring(msglen); +  GETSTRING(msglen);    errtype=protocolunsupported;   #endif    msglen=0;    break;    case 6:PD("SCMCredential\n");    errtype=protocolunsupported;    break;    case 7:PD("GSS\n");    errtype=protocolunsupported;    break;    case 9:PD("SSPI\n");    errtype=protocolunsupported;    break;    case 8:PD("GSSContinue\n");    errtype=protocolunsupported;    if(msglen<1)    errtype=protocolerror; -  SSauthdata=getstring(msglen);msglen=0; +  SSauthdata=GETSTRING(msglen);msglen=0;    break;    default:PD("Unknown Authentication Method %c\n",authtype);    errtype=protocolunsupported;    break;    }    switch(errtype) {    case noerror:    if(mstate==unauthenticated) -  sendcmd(({"p",plugint32(4+sizeof(sendpass)+1), +  SENDCMD(({"p",plugint32(4+sizeof(sendpass)+1),    sendpass,"\0"}));    break;    default:    case protocolunsupported:    ERROR("Unsupported authenticationmethod %c\n",authtype);    break;    }    break;    }    case 'K':PD("BackendKeyData\n"); -  msglen-=4+4;backendpid=getint32();cancelsecret=getstring(msglen); +  msglen-=4+4;backendpid=GETINT32();cancelsecret=GETSTRING(msglen);    msglen=0;    break;    case 'S':PD("ParameterStatus\n");    msglen-=4;    { array(string) ts=getstrings();    if(sizeof(ts)==2) {    runtimeparameter[ts[0]]=ts[1];    PD("%s=%s\n",ts[0],ts[1]);    }    else    errtype=protocolerror;    }    break;    case 'Z':PD("ReadyForQuery\n");    msglen-=4+1; -  backendstatus=getbyte(); +  backendstatus=GETBYTE();    mstate=readyforquery;    qstate=queryidle;    _closesent=0;    break;    case '1':PD("ParseComplete\n");    msglen-=4;    mstate=parsecomplete;    break;    case 't':    PD("ParameterDescription (for %s)\n",    _portal?_portal->_portalname:"DISCARDED");    { array a; -  int cols=getint16(); +  int cols=GETINT16();    msglen-=4+2+4*cols;    foreach(a=allocate(cols);int i;) -  a[i]=getint32(); +  a[i]=GETINT32();   #ifdef DEBUGMORE    PD("%O\n",a);   #endif    if(_portal)    _portal->_datatypeoid=a;    mstate=gotparameterdescription;    break;    }    case 'T':    PD("RowDescription (for %s)\n",    _portal?_portal->_portalname:"DISCARDED");    msglen-=4+2;    { array a; -  foreach(a=allocate(getint16());int i;) { -  string s="",ts; -  while(msglen--,(ts=getstring(1))[0]) -  s+=ts; +  foreach(a=allocate(GETINT16());int i;) { +  string s; +  msglen-=sizeof(s=GETSTRING())+1;    mapping(string:mixed) res=(["name":s]);    msglen-=4+2+4+2+4+2; -  res->tableoid=getint32()||UNDEFINED; -  res->tablecolattr=getint16()||UNDEFINED; -  res->type=getint32(); -  { int len=getint16(); +  res->tableoid=GETINT32()||UNDEFINED; +  res->tablecolattr=GETINT16()||UNDEFINED; +  res->type=GETINT32(); +  { int len=GETINT16();    res->length=len>=0?len:"variable";    } -  res->atttypmod=getint32();res->formatcode=getint16(); +  res->atttypmod=GETINT32();res->formatcode=GETINT16();    a[i]=res;    }   #ifdef DEBUGMORE    PD("%O\n",a);   #endif    if(_portal)    _portal->_datarowdesc=a;    mstate=gotrowdescription;    break;    }    case 'n':PD("NoData\n");    msglen-=4;    _portal->_datarowdesc=({});    mstate=gotrowdescription;    break;    case '2':PD("BindComplete\n");    msglen-=4;    mstate=bindcomplete;    break;    case 'D':PD("DataRow\n"); -  msglen-=4+2; -  { array a, datarowdesc; +  msglen-=4;    if(_portal) { -  +  array a, datarowdesc;    _portal->_bytesreceived+=msglen;    datarowdesc=_portal->_datarowdesc; -  } -  int cols=getint16(); -  msglen-=4*cols; -  foreach(a=allocate(cols,"");int i;) { -  int collen=getint32(); + #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; -  if(datarowdesc) { +     switch(datarowdesc[i]->type) { -  default:value=getstring(collen); +  default:value=GETSTRING(collen);    break;    case CHAROID: -  case BOOLOID:value=getbyte(); +  case BOOLOID:value=GETBYTE();    break;    case INT8OID:value=getint64();    break; -  case FLOAT4OID:value=(float)getstring(collen); +  case FLOAT4OID:value=(float)GETSTRING(collen);    break; -  case INT2OID:value=getint16(); +  case INT2OID:value=GETINT16();    break;    case OIDOID: -  case INT4OID:value=getint32(); +  case INT4OID:value=GETINT32();    }    a[i]=value;    } -  +  else if(!collen) +  a[i]="";    } -  else if(collen) -  a[i]=UNDEFINED; // NULL + #endif +  _portal->_datarows+=({a}); +  _portal->_inflight--;    } -  if(_portal) -  _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");    { msglen-=4;    if(msglen<1)    errtype=protocolerror; -  string s=getstring(msglen-1); +  string s=GETSTRING(msglen-1);    if(_portal)    _portal->_statuscmdcomplete=s;    PD("%s\n",s); -  if(getbyte()) +  if(GETBYTE())    errtype=protocolerror;    msglen=0;    mstate=commandcomplete;    break;    }    case 'I':PD("EmptyQueryResponse\n");    msglen-=4;    mstate=commandcomplete;    break;    case '3':PD("CloseComplete\n");    msglen-=4;    _closesent=0;    break;    case 'd':PD("CopyData\n");    msglen-=4;    if(msglen<0)    errtype=protocolerror;    if(_portal) {    _portal->_bytesreceived+=msglen; -  _portal->_datarows+=({({getstring(msglen)})}); +  _portal->_datarows+=({({GETSTRING(msglen)})});    }    msglen=0;    mstate=dataready;    break;    case 'H':PD("CopyOutResponse\n");    getcols();    if(_portal)    _portal->_fetchlimit=0; // disables further Executes    break;    case 'G':PD("CopyInResponse\n");
pike.git/lib/modules/Sql.pmod/pgsql.pike:699:    ERROR(lastmessage);    }    break;    case 'N':PD("NoticeResponse\n");    getresponse();    lastmessage=sprintf("%s %s: %s",    msgresponse->S,msgresponse->C,msgresponse->M);    break;    case 'A':PD("NotificationResponse\n");    { msglen-=4+4; -  int pid=getint32(); +  int pid=GETINT32();    string condition,extrainfo=UNDEFINED;    { array(string) ts=getstrings();    switch(sizeof(ts)) {    case 0:errtype=protocolerror;    break;    default:errtype=protocolerror;    case 2:extrainfo=ts[1];    case 1:condition=ts[0];    }    }    PD("%d %s\n%s\n",pid,condition,extrainfo);    array cb;    if((cb=notifylist[condition]||notifylist[""])    && (pid!=backendpid || sizeof(cb)>1 && cb[1]))    cb[0](pid,condition,extrainfo,@cb[2..]);    break;    }    default:PD("Unknown message received %c\n",msgtype); -  msglen-=4;PD("%O\n",getstring(msglen));msglen=0; +  msglen-=4;PD("%O\n",GETSTRING(msglen));msglen=0;    errtype=protocolunsupported;    break;    }    if(msglen)    errtype=protocolerror;    switch(errtype) {    case protocolunsupported:    ERROR("Unsupported servermessage received %c\n",msgtype);    break;    case protocolerror:
pike.git/lib/modules/Sql.pmod/pgsql.pike:752:      private int read_cb(mixed foo, string d) {    conn.unread(d);    do decodemsg();    while(conn.peek(0)==1);    return 0;   }      final private void sendterminate() {    PD("Terminate\n"); -  sendcmd(({"X",plugint32(4)})); +  SENDCMD(({"X",plugint32(4)}));    conn.close();   }      void destroy() {    sendterminate();   }      private void reconnect(void|int force) {    if(conn) {    reconnected++;
pike.git/lib/modules/Sql.pmod/pgsql.pike:790:    plugbuf+=({"user\0",user,"\0"});    if(database)    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); +  SENDCMD(plugbuf);    PD("%O\n",plugbuf);    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); +  SENDCMD(({"S",plugint32(4)}),1);    didsync=1; -  if(!special) +  if(!special) {    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);   #ifndef UNBUFFEREDIO    conn.set_read_callback(read_cb);   #endif   }
pike.git/lib/modules/Sql.pmod/pgsql.pike:1110:    case CTIDOID:    case UUIDOID:    return 1; //binary    }    return 0; // text   }      final private 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, +  SENDCMD(({"E",plugint32(4+sizeof(portalname)+1+4),portalname,    "\0",plugint32(fetchlimit)}),1);    _portal->_inflight+=fetchlimit;   }      final private void sendclose() {    string portalname;    portalsinflight--;    if(_portal && (portalname=_portal->_portalname)) {    _portal->_portalname = UNDEFINED;    _portal = UNDEFINED;    if(!sizeof(portalname))    unnamedportalinuse--;   #ifdef DEBUGMORE    PD("Closetrace %O\n",backtrace());   #endif    PD("Close portal %s\n",portalname); -  sendcmd(({"C",plugint32(4+1+sizeof(portalname)+1), +  SENDCMD(({"C",plugint32(4+1+sizeof(portalname)+1),    "P",portalname,"\0"}));    _closesent=1;    }   }      final private string trbackendst(int c) {    switch(c) {    case 'I':return "idle";    case 'T':return "intransaction";    case 'E':return "infailedtransaction";
pike.git/lib/modules/Sql.pmod/pgsql.pike:1241:    string oldprep=tprepared->preparedname;    if(oldprep) {    PD("Close statement %s\n",oldprep);    plugbuf+=({"C",plugint32(4+1+sizeof(oldprep)+1),    "S",oldprep,"\0"});    }    m_delete(prepareds,ind);    }    }    if(sizeof(plugbuf)) -  sendcmd(plugbuf); // close expireds +  SENDCMD(plugbuf); // close expireds    PD("%O\n",plugbuf);    }    prepareds[q]=tprepared=([]);    }    tstart=gethrtime();    } // pgsql_result autoassigns to portal    pgsql_result(this,tprepared,q,_fetchlimit,portalbuffersize);    if(unnamedportalinuse)    portalname=PORTALPREFIX+(string)pportalcount++;    else    unnamedportalinuse++;    _portal->_portalname=portalname;    qstate=inquery;    portalsinflight++;    mixed err;    if(err = catch {    if(!sizeof(preparedname) || !tprepared || !tprepared->preparedname) {    PD("Parse statement %s\n",preparedname); -  sendcmd(({"P",plugint32(4+sizeof(preparedname)+1+sizeof(q)+1+2), +  SENDCMD(({"P",plugint32(4+sizeof(preparedname)+1+sizeof(q)+1+2),    preparedname,"\0",q,"\0",plugint16(0)}));    PD("Query: %O\n",q);    } // sends Parameter- and RowDescription for 'S' -  PD("Describe statement %s\n",preparedname); +     conn.set_read_callback(0); -  sendcmd(({"D",plugint32(4+1+sizeof(preparedname)+1), +  if(!tprepared || !tprepared->datatypeoid) { +  PD("Describe statement %s\n",preparedname); +  SENDCMD(({"D",plugint32(4+1+sizeof(preparedname)+1),    "S",preparedname,"\0"}),1); -  +  } +  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); -  +  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    else    switch(dtoid[i]) {    default:
pike.git/lib/modules/Sql.pmod/pgsql.pike:1325:    plugbuf+=({plugint32(8),plugint64((int)value)});    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); -  +  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); +  SENDCMD(plugbuf);   #ifdef DEBUGMORE    PD("%O\n",plugbuf);   #endif    }    _portal->_statuscmdcomplete=UNDEFINED;    sendexecute(_fetchlimit && FETCHLIMITLONGRUN);    if(tprepared) {    decodemsg(bindcomplete);    int tend=gethrtime();    if(tend==tstart)
pike.git/lib/modules/Sql.pmod/pgsql.pike:1490:   }      array(mapping(string:mixed)) fetch_fields() {    return _datarowdesc+({});   }      private void releasesession() {    if(pgsqlsession) {    if(copyinprogress) {    PD("CopyDone\n"); -  pgsqlsession->sendmsg("c\0\0\0\4"); +  pgsqlsession.SENDCMD("c\0\0\0\4");    }    pgsqlsession->reload(2);    }    _qmtxkey=UNDEFINED;    pgsqlsession=UNDEFINED;   }      void destroy() {    catch { // inside destructors, exceptions don't work    releasesession();
pike.git/lib/modules/Sql.pmod/pgsql.pike:1548:    _qmtxkey=1;   #endif    pgsqlsession._portal=this;    PD("Stealing successful\n");   }      int|array(string|int) fetch_row(void|int|string buffer) {    if(copyinprogress) {    if(stringp(buffer)) {    PD("CopyData\n"); -  pgsqlsession->sendmsg(({"d",plugint32(4+sizeof(buffer)),buffer})); +  pgsqlsession.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();
pike.git/lib/modules/Sql.pmod/pgsql.pike:1570:    if(buffer!=2 && (err=delayederror)) {    delayederror=UNDEFINED;    throw(err);    }    err = catch {    if(_portalname) {    if(buffer!=2 && !_qmtxkey) {    steallock();    sendexecute(_fetchlimit);    } -  while(_closesent) +  while(pgsqlsession->_closesent)    decodemsg(); // Flush previous portal sequence    for(;;) {   #ifdef DEBUGMORE    PD("buffer: %d nextportal: %d lock: %d\n",    buffer,pgsqlsession._nextportal,!!_qmtxkey);   #endif    switch(decodemsg()) {    case copyinresponse:    copyinprogress=1;    return UNDEFINED; -  case dataready: { +  case dataready:    if(tprepared) {    tprepared->trun=gethrtime()-tprepared->trunstart;    m_delete(tprepared,"trunstart");    tprepared = UNDEFINED;    }    mstate=dataprocessed;    rowsreceived++;    switch(buffer) {    case 0:    case 1:
pike.git/lib/modules/Sql.pmod/pgsql.pike:1612:    _interruptable=1;    if(pgsqlsession._nextportal)    continue;    return UNDEFINED;    }   #if STREAMEXECUTES    if(_fetchlimit && _inflight<=_fetchlimit-1)    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();    }