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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql.pike:65:   int _nextportal;   int _closesent;   int _fetchlimit=FETCHLIMIT;   private int unnamedportalinuse;   private int portalsinflight;      private object conn;   private string SSauthdata,cancelsecret;   private int backendpid;   private int backendstatus; + private mapping(string:mixed) options;   private string lastmessage;   private mapping(string:array(mixed)) notifylist=([]);   private mapping(string:string) msgresponse;   private mapping(string:string) runtimeparameter;   private enum state {unauthenticated,authenticated,readyforquery,    parsecomplete,bindcomplete,commandcomplete,gotrowdescription,    gotparameterdescription,dataready,dataprocessed,portalsuspended,    copyinresponse};   private state mstate;   private enum querystate {queryidle,inquery,cancelpending,canceled};
pike.git/lib/modules/Sql.pmod/pgsql.pike:86:   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=32*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:139:   #define BPCHAROID 1042   #define VARCHAROID 1043   #define CTIDOID 1247   #define UUIDOID 2950      #define PG_PROTOCOL(m,n) (((m)<<16)|(n))   #define FLUSH "H\0\0\0\4"      //! @decl void create()   //! @decl void create(string host, void|string database, void|string user,@ - //! void|string password) + //! void|string password, void|mapping(string:mixed) options)   //!   //! With no arguments, this function initializes (reinitializes if a   //! connection had been previously set up) a connection to the   //! PostgreSQL backend. Since PostgreSQL requires a database to be   //! selected, it will try to connect to the default database. The   //! connection may fail however for a variety of reasons, in this case   //! the most likely of all is because you don't have enough authority   //! to connect to that database. So use of this particular syntax is   //! discouraged.   //!
pike.git/lib/modules/Sql.pmod/pgsql.pike:169:   //! @note   //! You need to have a database selected before using the sql-object,   //! otherwise you'll get exceptions when you try to query it. Also   //! notice that this function @b{can@} raise exceptions if the db   //! server doesn't respond, if the database doesn't exist or is not   //! accessible by you.   //!   //! @seealso   //! @[Postgres.postgres], @[Sql.Sql], @[postgres->select_db]   protected void create(void|string _host, void|string _database, -  void|string _user, void|string _pass) { +  void|string _user, void|string _pass, void|mapping(string:mixed) _options) {    pass = _pass; _pass = "CENSORED";    user = _user; database = _database; host = _host || PGSQL_DEFAULT_HOST; -  +  options = _options;    if(search(host,":")>=0 && sscanf(_host,"%s:%d",host,port)!=2)    ERROR("Error in parsing the hostname argument\n");    if(!port)    port = PGSQL_DEFAULT_PORT;    querymutex=Thread.Mutex();    stealmutex=Thread.Mutex();    reconnect();   }      //! @decl string error()
pike.git/lib/modules/Sql.pmod/pgsql.pike:208:      //! @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);   }    - #ifdef USEPGsql + #define SENDCMD(x ...) conn.sendcmd(x)   #define GETBYTE() conn.getbyte()   #define GETSTRING(x) conn.getstring(x)   #define GETINT16() conn.getint16()   #define GETINT32() conn.getint32()   #define FLUSHED conn.flushed -  +  + #ifdef USEPGsql + #define PEEK(x) conn.bpeek(x)   #else - #define GETBYTE() getbyte() - #define GETSTRING(x) getstring(x) - #define GETINT16() getint16() - #define GETINT32() getint32() - #define FLUSHED flushed + #define PEEK(x) conn.peek(x)    - final private void sendflush() { -  SENDCMD(({}),1); + #endif +  + #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 int getbyte() { -  if(!FLUSHED && !conn.peek(0)) + 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); + } +  + class PGassist { + #ifdef UNBUFFEREDIO +  inherit Stdio.File:std; + #else +  inherit Stdio.FILE:std; + #endif + #ifdef USEPGsql +  inherit _PGsql.PGsql:pg; + #else +  int flushed; + #endif +  void create(object pgsqlsess) { +  std::create(); + #ifdef USEPGsql +  pg::setpgsqlsess(pgsqlsess); + #else +  flushed=-1; + #endif +  } +  int connect(string host,int port) { +  int res=std::connect(host,port); + #ifdef USEPGsql +  if(res) +  pg::create(std::query_fd()); + #endif +  return res; +  } +  + #ifndef USEPGsql +  +  inline final int getbyte() { +  if(!FLUSHED && !PEEK(0))    sendflush();   #ifdef UNBUFFEREDIO -  return conn.read(1)[0]; +  return read(1)[0];   #else -  return conn.getchar(); +  return getchar();   #endif    }    - final private string getstring(void|int len) { +  final string getstring(void|int len) {    if(!zero_type(len)) {    string acc="",res;    do { -  if(!FLUSHED && !conn.peek(0)) +  if(!FLUSHED && !PEEK(0))    sendflush();    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() { +  inline final int getint16() {    int s0=GETBYTE();    int r=(s0&0x7f)<<8|GETBYTE();    return s0&0x80 ? r-(1<<15) : r ;    }    - inline final private int getint32() { +  inline final int getint32() {    int r=GETINT16();    r=r<<8|GETBYTE();    return r<<8|GETBYTE();    }    - inline final private int getint64() { +  inline final int getint64() {    int r=GETINT32();    return r<<32|GETINT32()&0xffffffff;    }   #endif    - #define SENDCMD(x ...) sendcmd(x) +  final protected void sendflush() { +  sendcmd(({}),1); +  }    - final private int sendcmd(string|array(string) data,void|int flush) { +  final 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); +  return 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(object pgsqlsess) { -  std::create(); -  pg::setpgsqlsess(pgsqlsess); -  } -  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(this); - #else - #ifdef UNBUFFEREDIO -  object lcon = Stdio.File(); - #else -  object lcon = Stdio.FILE(); +  if(!lcon.connect(host,port)) +  return UNDEFINED; + #if constant(SSL.sslfile) + #if 0 +  SSL.context context = SSL.context(); + #if 1 +  context->preferred_suites = ({ +  SSL_rsa_with_idea_cbc_sha, +  SSL_rsa_with_rc4_128_sha, +  SSL_rsa_with_rc4_128_md5, +  SSL_rsa_with_3des_ede_cbc_sha, +  SSL_rsa_export_with_rc4_40_md5, +  SSL_rsa_export_with_rc2_cbc_40_md5, +  SSL_rsa_export_with_des40_cbc_sha, +  });   #endif -  flushed=-1; +  context->random = Crypto.Random.random_string; +  object read_callback=con->query_read_callback(); +  object write_callback=con->query_write_callback(); +  object close_callback=con->query_close_callback(); +  +  ssl = SSL.sslfile(con, context, 1,blocking); +  if(!blocking) { +  ssl->set_read_callback(read_callback); +  ssl->set_write_callback(write_callback); +  ssl->set_close_callback(close_callback); +  } +  con=ssl;   #endif -  return lcon.connect(host,port) && lcon; + #endif +  return 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;    object lcon;
pike.git/lib/modules/Sql.pmod/pgsql.pike:437: 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 && !PEEK(0)) {    int tcurr=time();    int told=tcurr+timeout; -  while(!conn.peek(told-tcurr)) +  while(!PEEK(told-tcurr))    if((tcurr=time())-told>=timeout) {    sendclose();cancelquery();    break;    }    }    }    int msgtype=GETBYTE();    int msglen=GETINT32();    enum errortype { noerror=0, protocolerror, protocolunsupported };    errortype errtype=noerror;
pike.git/lib/modules/Sql.pmod/pgsql.pike:651:    int collen=GETINT32();    if(collen>0) {    msglen-=collen;    mixed value;    switch(datarowdesc[i]->type) {    default:value=GETSTRING(collen);    break;    case CHAROID:    case BOOLOID:value=GETBYTE();    break; -  case INT8OID:value=getint64(); +  case INT8OID:value=conn.getint64();    break;    case FLOAT4OID:value=(float)GETSTRING(collen);    break;    case INT2OID:value=GETINT16();    break;    case OIDOID:    case INT4OID:value=GETINT32();    }    a[i]=value;    }
pike.git/lib/modules/Sql.pmod/pgsql.pike:800:    break;    }    PD("Found state %O\n",mstate);    return mstate;   }      #ifndef UNBUFFEREDIO   private int read_cb(mixed foo, string d) {    conn.unread(d);    do _decodemsg(); -  while(conn.peek(0)==1); +  while(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:1320:    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); +  // 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    SENDCMD(({"P",plugint32(4+sizeof(preparedname)+1+sizeof(q)+1+2),    preparedname,"\0",q,"\0",plugint16(0)}),1);    PD("Query: %O\n",q);    } // sends Parameter- and RowDescription for 'S'    conn.set_read_callback(0);    if(!tprepared || !tprepared->datatypeoid) {    PD("Describe statement %s\n",preparedname);    SENDCMD(({"D",plugint32(4+1+sizeof(preparedname)+1),    "S",preparedname,"\0"}),1);    }