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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:408:   //! @seealso   //! @[Sql.sql_result], @[Sql.pgsql], @[Sql.Sql], @[Sql.pgsql()->big_query()]   class sql_result {       private object pgsqlsess;    private int eoffound;    private conxion c;    final mixed _delayederror;    final int _state;    final int _fetchlimit; -  final int _alltext; +  private int alltext;    final int _forcetext;       final string _portalname;       private int rowsreceived;    private int inflight;    private int portalbuffersize;    private Stdio.Buffer prepbuffer;    private Thread.Condition prepbufferready;    private Thread.Mutex prepbuffermux;    private Thread.Mutex closemux;    private Thread.Queue datarows; -  +  private array(mapping(string:mixed)) datarowdesc;    private string statuscmdcomplete; -  final int _bytesreceived; +  private int bytesreceived;    final int _synctransact;    final Thread.Condition _ddescribe;    final Thread.Mutex _ddescribemux;    final Thread.MutexKey _unnamedportalkey,_unnamedstatementkey;    final array _params;    final string _query; -  final array(mapping(string:mixed)) _datarowdesc; +     final string _preparedname;    final mapping(string:mixed) _tprepared;       private string _sprintf(int type, void|mapping flags) {    string res=UNDEFINED;    switch(type) {    case 'O':    res=sprintf("sql_result state: %d numrows: %d eof: %d inflight: %d\n"    "query: %O\n"    "portalname: %O datarows: %d"    " laststatus: %s\n",    _state,rowsreceived,eoffound,inflight,    _query, -  _portalname,_datarowdesc&&sizeof(_datarowdesc), +  _portalname,datarowdesc&&sizeof(datarowdesc),    statuscmdcomplete||(_unnamedstatementkey?"*parsing*":""));    break;    }    return res;    }       protected void create(object _pgsqlsess,conxion _c,string query,    int _portalbuffersize,int alltyped,array params,int forcetext) {    pgsqlsess = _pgsqlsess;    c = _c;    _query = query;    datarows = Thread.Queue();    _ddescribe=Thread.Condition();    _ddescribemux=Thread.Mutex();    closemux=Thread.Mutex();    prepbufferready=Thread.Condition();    prepbuffermux=Thread.Mutex();    portalbuffersize=_portalbuffersize; -  _alltext = !alltyped; +  alltext = !alltyped;    _params = params;    _forcetext = forcetext;    _state = PORTALINIT;    }       //! Returns the command-complete status for this query.    //!    //! @seealso    //! @[affected_rows()]    //!
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:495:    //! @note    //! This function is PostgreSQL-specific, and thus it is not available    //! through the generic SQL-interface.    int affected_rows() {    int rows;    if(statuscmdcomplete)    sscanf(statuscmdcomplete,"%*s %d",rows);    return rows;    }    +  final void _storetiming() { +  if(_tprepared) { +  _tprepared.trun=gethrtime()-_tprepared.trunstart; +  m_delete(_tprepared,"trunstart"); +  _tprepared = UNDEFINED; +  } +  } +     private void waitfordescribe() {    Thread.MutexKey lock=_ddescribemux->lock(); -  if(!_datarowdesc) +  if(!datarowdesc)    _ddescribe->wait(lock);    lock=0;    }       //! @seealso    //! @[Sql.sql_result()->num_fields()]    int num_fields() { -  if(!_datarowdesc) +  if(!datarowdesc)    waitfordescribe();    trydelayederror(); -  return sizeof(_datarowdesc); +  return sizeof(datarowdesc);    }       //! @seealso    //! @[Sql.sql_result()->num_rows()]    int num_rows() {    trydelayederror();    return rowsreceived;    }       private inline void trydelayederror() {
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:533:    //! @seealso    //! @[Sql.sql_result()->eof()]    int eof() {    trydelayederror();    return eoffound;    }       //! @seealso    //! @[Sql.sql_result()->fetch_fields()]    array(mapping(string:mixed)) fetch_fields() { -  if(!_datarowdesc) +  if(!datarowdesc)    waitfordescribe();    trydelayederror(); -  return _datarowdesc+({}); +  return datarowdesc+({});    }    -  final void _setrowdesc(array(mapping(string:mixed)) datarowdesc) { + #ifdef PG_DEBUG +  final int + #else +  final void + #endif +  _decodedata(int msglen,string cenc) { +  _storetiming(); +  string serror; +  bytesreceived+=msglen; +  int cols=c->read_int16(); +  array a=allocate(cols,!alltext&&Val.null); + #ifdef PG_DEBUG +  msglen-=2+4*cols; + #endif +  foreach(datarowdesc;int i;mapping m) { +  int collen=c->read_sint(4); +  if(collen>0) { + #ifdef PG_DEBUG +  msglen-=collen; + #endif +  mixed value; +  switch(int typ=m.type) { +  case FLOAT4OID: + #if SIZEOF_FLOAT>=8 +  case FLOAT8OID: + #endif +  if(!alltext) { +  value=(float)c->read(collen); +  break; +  } +  default:value=c->read(collen); +  break; +  case CHAROID: +  value=alltext?c->read(1):c->read_int8(); +  break; +  case BOOLOID:value=c->read_int8(); +  switch(value) { +  case 'f':value=0; +  break; +  case 't':value=1; +  } +  if(alltext) +  value=value?"t":"f"; +  break; +  case TEXTOID: +  case BPCHAROID: +  case VARCHAROID: +  value=c->read(collen); +  if(cenc==UTF8CHARSET && catch(value=utf8_to_string(value)) +  && !serror) +  serror=SERROR("%O contains non-%s characters\n", +  value,UTF8CHARSET); +  break; +  case INT8OID:case INT2OID: +  case OIDOID:case INT4OID: +  if(_forcetext) { +  value=c->read(collen); +  if(!alltext) +  value=(int)value; +  } else { +  switch(typ) { +  case INT8OID:value=c->read_sint(8); +  break; +  case INT2OID:value=c->read_sint(2); +  break; +  case OIDOID: +  case INT4OID:value=c->read_sint(4); +  } +  if(alltext) +  value=(string)value; +  } +  } +  a[i]=value; +  } else if(!collen) +  a[i]=""; +  } +  _processdataready(a); +  if(serror) +  error(serror); + #ifdef PG_DEBUG +  return msglen; + #endif +  } +  +  final void _setrowdesc(array(mapping(string:mixed)) drowdesc) {    Thread.MutexKey lock=_ddescribemux->lock(); -  _datarowdesc=datarowdesc; +  datarowdesc=drowdesc;    _ddescribe->broadcast();    lock=0;    }       final void _preparebind(array dtoid) {    array(string|int) paramValues=_params?_params[2]:({});    if(sizeof(dtoid)!=sizeof(paramValues))    SUSERERROR("Invalid number of bindings, expected %d, got %d\n",    sizeof(dtoid),sizeof(paramValues));   #ifdef PG_DEBUGMORE
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:709:    if(!prepbuffer)    catch(prepbufferready->wait(lock));    plugbuffer=prepbuffer;    prepbuffer=0; // Free memory when plugbuffer leaves scope    }    if(!prepbufferready || _state==CLOSED)    lock=_unnamedstatementkey=0;    else {    destruct(prepbufferready); // Make sure we do this exactly once    lock=0; -  plugbuffer->add_int16(sizeof(_datarowdesc)); -  if(sizeof(_datarowdesc)) -  foreach(_datarowdesc;;mapping col) +  plugbuffer->add_int16(sizeof(datarowdesc)); +  if(sizeof(datarowdesc)) +  foreach(datarowdesc;;mapping col)    plugbuffer->add_int16(oidformat(col.type));    else if(commitprefix->match(_query)) {    lock=pgsqlsess->_commitmux->lock();    if(pgsqlsess->_portalsinflight) {    pgsqlsess->_waittocommit++;    PD("Commit waiting for portals to finish\n");    pgsqlsess->_readyforcommit->wait(lock);    pgsqlsess->_waittocommit--;    }    lock=0;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:805:    } else if(!alreadyfilled)    pgsqlsess->_readyforquerycount++, retval=SYNCSEND;    pgsqlsess->_pportalcount=0;    }    lockc=0;    }    lock=0;    return retval;    }    -  final void _processdataready(array datarow) { +  final void _processdataready(array datarow,void|int msglen) { +  bytesreceived+=msglen;    inflight--;    datarows->write(datarow); -  rowsreceived++; -  if(rowsreceived==1) +  if(++rowsreceived==1)    PD("<%O _fetchlimit %d=min(%d||1,%d), inflight %d\n",_portalname, -  _fetchlimit,(portalbuffersize>>1)*rowsreceived/_bytesreceived, +  _fetchlimit,(portalbuffersize>>1)*rowsreceived/bytesreceived,    pgsqlsess._fetchlimit,inflight);    if(_fetchlimit) {    _fetchlimit= -  min((portalbuffersize>>1)*rowsreceived/_bytesreceived||1, +  min((portalbuffersize>>1)*rowsreceived/bytesreceived||1,    pgsqlsess._fetchlimit);    Thread.MutexKey lock=closemux->lock();    if(_fetchlimit && inflight<=_fetchlimit-1)    _sendexecute(_fetchlimit);    else if(!_fetchlimit)    PD("<%O _fetchlimit %d, inflight %d, skip execute\n",    _portalname,_fetchlimit,inflight);    lock=0;    }    }       private void releaseconditions() {    pgsqlsess=0;    Thread.MutexKey lock;    if(prepbufferready) {    Thread.MutexKey lock=prepbuffermux->lock();    catch(prepbufferready->signal());    } -  if(!_datarowdesc) { +  if(!datarowdesc) {    lock=_ddescribemux->lock(); -  _datarowdesc=({}); +  datarowdesc=({});    _ddescribe->broadcast();    }    lock=0;    }       final void _releasesession(void|string statusccomplete) {    if(statusccomplete && !statuscmdcomplete)    statuscmdcomplete=statusccomplete;    inflight=0;    datarows->write(1); // Signal EOF