2014-08-16
2014-08-16 01:25:04 by Martin Nilsson <nilsson@opera.com>
-
11b13bac9aa6ee37adc3a6554f6e4d2b73d0d9c9
(1316 lines)
(+772/-544)
[
Show
| Annotate
]
Branch: 8.0
Less crazy coding style.
226:
//! @seealso
//! @[Postgres.postgres], @[Sql.Sql], @[select_db()],
//! @url{http://www.postgresql.org/search/?u=%2Fdocs%2Fcurrent%2F&q=client+connection+defaults@}
- protected void create(void|string _host, void|string _database,
- void|string _user, void|string _pass, void|mapping(string:mixed) _options)
- { pass = _pass; _pass = "CENSORED";
+ protected void create(void|string host, void|string database,
+ void|string user, void|string pass,
+ void|mapping(string:mixed) options)
+ {
+ this_program::pass = pass;
if(pass)
-
+ {
String.secure(pass);
- user = _user; database = _database; host = _host || PGSQL_DEFAULT_HOST;
- options = _options || ([]);
- if(has_value(host,":") && sscanf(_host,"%s:%d",host,port)!=2)
+ pass = "CENSORED";
+ }
+ this_program::user = user;
+ this_program::database = database;
+ this_program::options = options || ([]);
+
+ if(!host) host = PGSQL_DEFAULT_HOST;
+ if(has_value(host,":") && sscanf(host,"%s:%d",host,port)!=2)
ERROR("Error in parsing the hostname argument\n");
-
+ this_program::host = host;
+
if(!port)
port = PGSQL_DEFAULT_PORT;
_runtimeparameter=([]);
263:
//! @seealso
//! @[big_query()]
string error(void|int clear)
- { string s=lastmessage*"\n";
+ {
+ string s=lastmessage*"\n";
if(clear)
lastmessage=({});
warningscollected=0;
276:
//! @seealso
//! @[server_info()]
string host_info()
- { return sprintf("fd:%d TCP/IP %s:%d PID %d",
+ {
+ return sprintf("fd:%d TCP/IP %s:%d PID %d",
_c?_c.query_fd():-1,host,port,backendpid);
}
293:
//! @seealso
//! @[ping()]
int is_open()
- { return _c&&_c.query_fd()>=0;
+ {
+ return _c&&_c.query_fd()>=0;
}
//! @decl int ping()
314:
//! @seealso
//! @[is_open()]
int ping()
- { int oldbackendpid=backendpid;
+ {
+ int oldbackendpid=backendpid;
mixed err;
if(_c && (err = catch
- { _c.sendflush();
+ {
+ _c.sendflush();
return backendpid!=oldbackendpid;
}))
- { PD("%O\n",err);
+ {
+ PD("%O\n",err);
if(reconnect(1))
return 1;
}
328:
}
final private object getsocket(void|int nossl)
- { object lcon = Stdio.File();
+ {
+ object lcon = Stdio.File();
if(!lcon.connect(host,port))
return UNDEFINED;
object fcon;
#if constant(SSL.File)
if(!nossl && (options->use_ssl || options->force_ssl))
- { PD("SSLRequest\n");
- { object c=.pgsql_util.PGassist();
+ {
+ PD("SSLRequest\n");
+ {
+ object c=.pgsql_util.PGassist();
lcon.write(({c.plugint32(8),c.plugint32(PG_PROTOCOL(1234,5679))}));
}
switch(lcon.read(1))
- { case "S":
+ {
+ case "S":
SSL.Context context = SSL.Context();
fcon=.pgsql_util.PGconnS(lcon, context);
if(fcon)
372:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
void cancelquery()
- { if(qstate==inquery)
- { qstate=cancelpending;
+ {
+ if(qstate==inquery)
+ {
+ qstate=cancelpending;
object lcon;
PD("CancelRequest\n");
if(!(lcon=getsocket(1)))
394:
//! @[get_charset()], @[create()],
//! @url{http://www.postgresql.org/search/?u=%2Fdocs%2Fcurrent%2F&q=character+sets@}
void set_charset(string charset)
- { big_query(sprintf("SET CLIENT_ENCODING TO '%s'",quote(charset)));
+ {
+ big_query(sprintf("SET CLIENT_ENCODING TO '%s'",quote(charset)));
}
//! @returns
404:
//! @[set_charset()], @[getruntimeparameters()],
//! @url{http://www.postgresql.org/search/?u=%2Fdocs%2Fcurrent%2F&q=character+sets@}
string get_charset()
- { return _runtimeparameter[CLIENT_ENCODING];
+ {
+ return _runtimeparameter[CLIENT_ENCODING];
}
//! @returns
447:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
mapping(string:string) getruntimeparameters()
- { return _runtimeparameter+([]);
+ {
+ return _runtimeparameter+([]);
}
//! @returns
497:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
mapping(string:mixed) getstatistics()
- { mapping(string:mixed) stats=([
+ {
+ mapping(string:mixed) stats=([
"warnings_dropped":warningsdropcount,
"skipped_describe_count":skippeddescribe,
"used_prepared_statements":prepstmtused,
527:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
int setcachedepth(void|int newdepth)
- { int olddepth=cachedepth;
+ {
+ int olddepth=cachedepth;
if(!undefinedp(newdepth) && newdepth>=0)
cachedepth=newdepth;
return olddepth;
543:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
int settimeout(void|int newtimeout)
- { int oldtimeout=timeout;
+ {
+ int oldtimeout=timeout;
if(!undefinedp(newtimeout) && newtimeout>0)
timeout=newtimeout;
return oldtimeout;
559:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
int setportalbuffersize(void|int newportalbuffersize)
- { int oldportalbuffersize=portalbuffersize;
+ {
+ int oldportalbuffersize=portalbuffersize;
if(!undefinedp(newportalbuffersize) && newportalbuffersize>0)
portalbuffersize=newportalbuffersize;
return oldportalbuffersize;
575:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
int setfetchlimit(void|int newfetchlimit)
- { int oldfetchlimit=_fetchlimit;
+ {
+ int oldfetchlimit=_fetchlimit;
if(!undefinedp(newfetchlimit) && newfetchlimit>=0)
_fetchlimit=newfetchlimit;
return oldfetchlimit;
}
final private string glob2reg(string glob)
- { if(!glob||!sizeof(glob))
+ {
+ if(!glob||!sizeof(glob))
return "%";
return replace(glob,({"*","?","\\","%","_"}),({"%","_","\\\\","\\%","\\_"}));
}
final private string a2nls(array(string) msg)
- { return msg*"\n"+"\n";
+ {
+ return msg*"\n"+"\n";
}
final private string pinpointerror(void|string query,void|string offset)
- { if(!query)
+ {
+ if(!query)
return "";
int k=(int)offset;
if(k<=0)
601:
}
private void phasedreconnect()
- { if(!connectionclosed)
- { connectionclosed=1;
+ {
+ if(!connectionclosed)
+ {
+ connectionclosed=1;
if(!reconnect(1))
- { sleep(RECONNECTDELAY);
+ {
+ sleep(RECONNECTDELAY);
if(!reconnect(1))
- { do sleep(RECONNECTBACKOFF);
+ {
+ do sleep(RECONNECTBACKOFF);
while(!reconnect(1) && options->reconnect==-1);
}
}
616:
final int _decodemsg(void|state waitforstate)
{
#ifdef PG_DEBUG
- { array line;
+ {
+ array line;
#ifdef PG_DEBUGMORE
line=backtrace();
#endif
624:
}
#endif
while(_mstate!=waitforstate)
- { if(_mstate!=unauthenticated)
- { if(qstate==cancelpending)
+ {
+ if(_mstate!=unauthenticated)
+ {
+ if(qstate==cancelpending)
qstate=canceled,sendclose();
if(_c.flushed && qstate==inquery && !_c.bpeek(0))
- { int tcurr=time();
+ {
+ int tcurr=time();
int told=tcurr+timeout;
sessionblocked++;
while(!_c.bpeek(told-tcurr))
if((tcurr=time())-told>=timeout)
- { sendclose();cancelquery();
+ {
+ sendclose();cancelquery();
break;
}
}
642:
int msglen=_c.getint32();
_msgsreceived++;
_bytesreceived+=1+msglen;
- enum errortype { noerror=0, protocolerror, protocolunsupported };
+ enum errortype {
+ noerror=0,
+ protocolerror,
+ protocolunsupported
+ };
errortype errtype=noerror;
switch(msgtype)
- { void storetiming()
- { tprepared->trun=gethrtime()-tprepared->trunstart;
+ {
+ void storetiming()
+ {
+ tprepared->trun=gethrtime()-tprepared->trunstart;
m_delete(tprepared,"trunstart");
tprepared = UNDEFINED;
};
void getcols()
- { int bintext=_c.getbyte();
+ {
+ int bintext=_c.getbyte();
array a;
int cols=_c.getint16();
msglen-=4+1+2+2*cols;
foreach(a=allocate(cols,([]));;mapping m)
m->type=_c.getint16();
if(_c.portal) // Discard column info, and make it line oriented
- { a=({(["type":bintext?BYTEAOID:TEXTOID,"name":"line"])});
+ {
+ a=({(["type":bintext?BYTEAOID:TEXTOID,"name":"line"])});
_c.portal->_datarowdesc=a;
}
_mstate=gotrowdescription;
};
array(string) getstrings()
- { string s;
+ {
+ string s;
if(msglen<1)
errtype=protocolerror;
s=_c.getstring(msglen);
676:
return s/"\0";
};
mapping(string:string) getresponse()
- { mapping(string:string) msgresponse=([]);
+ {
+ mapping(string:string) msgresponse=([]);
msglen-=4;
foreach(getstrings();;string f)
if(sizeof(f))
685:
return msgresponse;
};
array(string) showbindings()
- { array(string) msgs=({});
+ {
+ array(string) msgs=({});
array from;
if(_c.portal && (from = _c.portal->_params))
- { array to,paramValues;
+ {
+ array to,paramValues;
[from,to,paramValues] = from;
if(sizeof(paramValues))
- { string val;
+ {
+ string val;
int i;
string fmt=sprintf("%%%ds %%3s %%.61s",max(@map(from,sizeof)));
foreach(paramValues;i;val)
700:
}
return msgs;
};
- case 'R':PD("Authentication\n");
- { string sendpass;
+ case 'R':
+ {
+ PD("Authentication\n");
+ string sendpass;
int authtype;
msglen-=4+4;
switch(authtype=_c.getint32())
- { case 0:PD("Ok\n");
+ {
+ case 0:
+ PD("Ok\n");
_mstate=authenticated;
break;
- case 2:PD("KerberosV5\n");
+ case 2:
+ PD("KerberosV5\n");
errtype=protocolunsupported;
break;
- case 3:PD("ClearTextPassword\n");
+ case 3:
+ PD("ClearTextPassword\n");
sendpass=pass;
break;
- case 4:PD("CryptPassword\n");
+ case 4:
+ PD("CryptPassword\n");
errtype=protocolunsupported;
break;
- case 5:PD("MD5Password\n");
+ 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+_c.getstring(msglen));
- #else
- _c.getstring(msglen);
- errtype=protocolunsupported;
- #endif
+
msglen=0;
break;
- case 6:PD("SCMCredential\n");
+ case 6:
+ PD("SCMCredential\n");
errtype=protocolunsupported;
break;
- case 7:PD("GSS\n");
+ case 7:
+ PD("GSS\n");
errtype=protocolunsupported;
break;
- case 9:PD("SSPI\n");
+ case 9:
+ PD("SSPI\n");
errtype=protocolunsupported;
break;
- case 8:PD("GSSContinue\n");
+ case 8:
+ PD("GSSContinue\n");
errtype=protocolunsupported;
if(msglen<1)
errtype=protocolerror;
SSauthdata=_c.getstring(msglen);msglen=0;
break;
- default:PD("Unknown Authentication Method %c\n",authtype);
+ default:
+ PD("Unknown Authentication Method %c\n",authtype);
errtype=protocolunsupported;
break;
}
switch(errtype)
- { case noerror:
+ {
+ case noerror:
if(_mstate==unauthenticated)
_c.sendcmd(({"p",_c.plugint32(4+sizeof(sendpass)+1),
sendpass,"\0"}),1);
762:
}
break;
}
- case 'K':PD("BackendKeyData\n");
+ case 'K':
+ PD("BackendKeyData\n");
msglen-=4+4;backendpid=_c.getint32();cancelsecret=_c.getstring(msglen);
msglen=0;
break;
- case 'S':PD("ParameterStatus\n");
+ case 'S':
+ PD("ParameterStatus\n");
msglen-=4;
- { array(string) ts=getstrings();
+ {
+ array(string) ts=getstrings();
if(sizeof(ts)==2)
- { _runtimeparameter[ts[0]]=ts[1];
+ {
+ _runtimeparameter[ts[0]]=ts[1];
PD("%s=%s\n",ts[0],ts[1]);
}
else
errtype=protocolerror;
}
break;
- case 'Z':PD("ReadyForQuery\n");
+ case 'Z':
+ PD("ReadyForQuery\n");
msglen-=4+1;
backendstatus=_c.getbyte();
_mstate=readyforquery;
qstate=queryidle;
_closesent=0;
break;
- case '1':PD("ParseComplete\n");
+ case '1':
+ PD("ParseComplete\n");
msglen-=4;
_mstate=parsecomplete;
break;
case 't':
PD("ParameterDescription (for %s)\n",
_c.portal?_c.portal->_portalname:"DISCARDED");
- { array a;
+ {
+ array a;
int cols=_c.getint16();
msglen-=4+2+4*cols;
foreach(a=allocate(cols);int i;)
808:
PD("RowDescription (for %s)\n",
_c.portal?_c.portal->_portalname:"DISCARDED");
msglen-=4+2;
- { array a;
+ {
+ array a;
foreach(a=allocate(_c.getint16());int i;)
- { string s;
+ {
+ string s;
msglen-=sizeof(s=_c.getstring())+1;
mapping(string:mixed) res=(["name":s]);
msglen-=4+2+4+2+4+2;
res->tableoid=_c.getint32()||UNDEFINED;
res->tablecolattr=_c.getint16()||UNDEFINED;
res->type=_c.getint32();
- { int len=_c.getint16();
+ {
+ int len=_c.getint16();
res->length=len>=0?len:"variable";
}
res->atttypmod=_c.getint32();
832:
_mstate=gotrowdescription;
break;
}
- case 'n':PD("NoData\n");
+ case 'n':
+ PD("NoData\n");
msglen-=4;
_c.portal->_datarowdesc=({});
_c.portal->_fetchlimit=0; // disables subsequent Executes
_mstate=gotrowdescription;
break;
- case '2':PD("BindComplete\n");
+ case '2':
+ PD("BindComplete\n");
msglen-=4;
_mstate=bindcomplete;
break;
- case 'D':PD("DataRow\n");
+ case 'D':
+ PD("DataRow\n");
msglen-=4;
if(_c.portal)
- { if(tprepared)
+ {
+ if(tprepared)
storetiming();
#ifdef USEPGsql
_c.decodedatarow(msglen);msglen=0;
860:
a=allocate(cols,UNDEFINED);
msglen-=2+4*cols;
foreach(datarowdesc;int i;mapping m)
- { int collen=_c.getint32();
+ {
+ int collen=_c.getint32();
if(collen>0)
- { msglen-=collen;
+ {
+ msglen-=collen;
mixed value;
switch(int typ=m->type)
- { case FLOAT4OID:
+ {
+ case FLOAT4OID:
#if SIZEOF_FLOAT>=8
case FLOAT8OID:
#endif
if(!atext)
- { value=(float)_c.getstring(collen);
+ {
+ value=(float)_c.getstring(collen);
break;
}
default:value=_c.getstring(collen);
880:
break;
case BOOLOID:value=_c.getbyte();
switch(value)
- { case 'f':value=0;
+ {
+ case 'f':value=0;
break;
case 't':value=1;
}
897:
case INT8OID:case INT2OID:
case OIDOID:case INT4OID:
if(forcetext)
- { value=_c.getstring(collen);
+ {
+ value=_c.getstring(collen);
if(!atext)
value=(int)value;
}
else
- { switch(typ)
- { case INT8OID:value=_c.getint64();
+ {
+ switch(typ)
+ {
+ case INT8OID:value=_c.getint64();
break;
case INT2OID:value=_c.getint16();
break;
922:
a=({a});
_c.portal->_datarows+=a;
_c.portal->_inflight-=sizeof(a);
- #endif
+ #endif // USEPGsql
}
else
_c.getstring(msglen),msglen=0;
_mstate=dataready;
break;
- case 's':PD("PortalSuspended\n");
+ case 's':
+ PD("PortalSuspended\n");
msglen-=4;
_mstate=portalsuspended;
break;
- case 'C':PD("CommandComplete\n");
- { msglen-=4;
+ case 'C':
+ PD("CommandComplete\n");
+ {
+ msglen-=4;
if(msglen<1)
errtype=protocolerror;
string s=_c.getstring(msglen-1);
if(_c.portal)
- { if(tprepared)
+ {
+ if(tprepared)
storetiming();
_c.portal->_statuscmdcomplete=s;
}
949:
_mstate=commandcomplete;
break;
}
- case 'I':PD("EmptyQueryResponse\n");
+ case 'I':
+ PD("EmptyQueryResponse\n");
msglen-=4;
_mstate=commandcomplete;
break;
- case '3':PD("CloseComplete\n");
+ case '3':
+ PD("CloseComplete\n");
msglen-=4;
_closesent=0;
break;
- case 'd':PD("CopyData\n");
+ case 'd':
+ PD("CopyData\n");
if(tprepared)
storetiming();
msglen-=4;
if(msglen<0)
errtype=protocolerror;
if(_c.portal)
- { _c.portal->_bytesreceived+=msglen;
+ {
+ _c.portal->_bytesreceived+=msglen;
_c.portal->_datarows+=({({_c.getstring(msglen)})});
}
msglen=0;
_mstate=dataready;
break;
- case 'H':PD("CopyOutResponse\n");
+ case 'H':
+ PD("CopyOutResponse\n");
getcols();
break;
- case 'G':PD("CopyInResponse\n");
+ case 'G':
+ PD("CopyInResponse\n");
getcols();
_mstate=copyinresponse;
break;
- case 'c':PD("CopyDone\n");
+ case 'c':
+ PD("CopyDone\n");
msglen-=4;
break;
- case 'E':PD("ErrorResponse\n");
- { mapping(string:string) msgresponse;
+ case 'E':
+ PD("ErrorResponse\n");
+ {
+ mapping(string:string) msgresponse;
msgresponse=getresponse();
void preplastmessage()
- { lastmessage=({sprintf("%s %s:%s %s\n (%s:%s:%s)",
- msgresponse->S,msgresponse->C,msgresponse->P||"",msgresponse->M,
- msgresponse->F||"",msgresponse->R||"",msgresponse->L||"")});
+ {
+ lastmessage=({
+ sprintf("%s %s:%s %s\n (%s:%s:%s)",
+ msgresponse->S,msgresponse->C,msgresponse->P||"",
+ msgresponse->M,msgresponse->F||"",msgresponse->R||"",
+ msgresponse->L||"")});
};
warningsdropcount+=warningscollected;
warningscollected=0;
switch(msgresponse->C)
- { case "P0001":
+ {
+ case "P0001":
lastmessage=({sprintf("%s: %s",msgresponse->S,msgresponse->M)});
USERERROR(a2nls(lastmessage
+({pinpointerror(_c.portal->_query,msgresponse->P)})
1016:
lastmessage+=({msgresponse->W});
lastmessage+=showbindings();
switch(msgresponse->S)
- { case "PANIC":werror(a2nls(lastmessage));
+ {
+ case "PANIC":werror(a2nls(lastmessage));
}
USERERROR(a2nls(lastmessage));
}
break;
}
- case 'N':PD("NoticeResponse\n");
- { mapping(string:string) msgresponse;
+ case 'N':
+ PD("NoticeResponse\n");
+ {
+ mapping(string:string) msgresponse;
msgresponse=getresponse();
if(clearmessage)
- { warningsdropcount+=warningscollected;
+ {
+ warningsdropcount+=warningscollected;
clearmessage=warningscollected=0;
lastmessage=({});
}
1035:
msgresponse->S,msgresponse->C,msgresponse->M)});
break;
}
- case 'A':PD("NotificationResponse\n");
- { msglen-=4+4;
+ case 'A':
+ PD("NotificationResponse\n");
+ {
+ msglen-=4+4;
int pid=_c.getint32();
string condition,extrainfo=UNDEFINED;
- { array(string) ts=getstrings();
+ {
+ array(string) ts=getstrings();
switch(sizeof(ts))
- { case 0:errtype=protocolerror;
+ {
+ case 0:
+ errtype=protocolerror;
break;
- default:errtype=protocolerror;
- case 2:extrainfo=ts[1];
- case 1:condition=ts[0];
+ default:
+ errtype=protocolerror;
+ case 2:
+ extrainfo=ts[1];
+ case 1:
+ condition=ts[0];
}
}
PD("%d %s\n%s\n",pid,condition,extrainfo);
1054:
}
default:
if(msgtype!=-1)
- { PD("Unknown message received %c\n",msgtype);
+ {
+ PD("Unknown message received %c\n",msgtype);
msglen-=4;PD("%O\n",_c.getstring(msglen));msglen=0;
errtype=protocolunsupported;
}
else
- { array(string) msg=lastmessage;
+ {
+ array(string) msg=lastmessage;
if(_mstate!=unauthenticated)
phasedreconnect(),msg+=lastmessage;
string s=sizeof(msg)?a2nls(msg):"";
1071:
if(msglen)
errtype=protocolerror;
switch(errtype)
- { case protocolunsupported:
+ {
+ case protocolunsupported:
ERROR("Unsupported servermessage received %c\n",msgtype);
break;
case protocolerror:
1092: Inside #if undefined(UNBUFFEREDIO)
#ifndef UNBUFFEREDIO
private int read_cb(mixed foo, string d)
- { _c.unread(d);
+ {
+ _c.unread(d);
do _decodemsg();
while(_c.bpeek(0)==1);
return 0;
1106:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
void close()
- { cancelquery();
+ {
+ cancelquery();
if(_c)
_c.sendterminate();
_c=0;
}
void destroy()
- { close();
+ {
+ close();
}
private int reconnect(void|int force)
- { Thread.MutexKey connectmtxkey;
+ {
+ Thread.MutexKey connectmtxkey;
if(_c)
- { reconnected++;
+ {
+ reconnected++;
prepstmtused=0;
if(!force)
_c.sendterminate();
1132:
return 0; // Recursive reconnect, bailing out
}
if(!(_c=getsocket()))
- { string msg=sprintf("Couldn't connect to database on %s:%d",host,port);
+ {
+ string msg=sprintf("Couldn't connect to database on %s:%d",host,port);
if(force)
- { if(!sizeof(lastmessage) || lastmessage[sizeof(lastmessage)-1]!=msg)
+ {
+ if(!sizeof(lastmessage) || lastmessage[sizeof(lastmessage)-1]!=msg)
lastmessage+=({msg});
return 0;
}
1164:
plugbuf[0]=_c.plugint32(len);
_c.write(plugbuf);
PD("%O\n",plugbuf);
- { mixed err=catch(_decodemsg(readyforquery));
+ {
+ mixed err=catch(_decodemsg(readyforquery));
if(err)
-
+ {
if(force)
return 0;
else
throw(err);
}
-
+ }
PD("%O\n",_runtimeparameter);
if(force)
- { lastmessage+=({sprintf("Reconnected to database %s",host_info())});
+ {
+ lastmessage+=({sprintf("Reconnected to database %s",host_info())});
runcallback(backendpid,"_reconnect","");
}
return 1;
1186:
//! @seealso
//! @[resync()], @[cancelquery()]
void reload()
- { resync();
+ {
+ resync();
}
//! @decl void resync()
1212:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
void resync(void|int special)
- { mixed err;
+ {
+ mixed err;
int didsync;
if(!is_open()&&!reconnect(1))
ERROR(a2nls(lastmessage));
if(err = catch
- { sendclose(1);
+ {
+ sendclose(1);
PD("Portalsinflight: %d\n",portalsinflight);
if(!portalsinflight)
- { if(!earlyclose)
- { PD("Sync\n");
+ {
+ if(!earlyclose)
+ {
+ PD("Sync\n");
_c.sendcmd(({"S",_c.plugint32(4)}),2);
}
didsync=1;
if(!special)
- { _decodemsg(readyforquery);
+ {
+ _decodemsg(readyforquery);
switch(backendstatus)
- { case 'T':case 'E':
+ {
+ case 'T':case 'E':
foreach(prepareds;;mapping tp)
- { m_delete(tp,"datatypeoid");
+ {
+ m_delete(tp,"datatypeoid");
m_delete(tp,"datarowdesc");
}
big_query("ROLLBACK");
1242:
}
earlyclose=0;
})
- { earlyclose=0;
+ {
+ earlyclose=0;
PD("%O\n",err);
if(!reconnect(1))
ERROR(a2nls(lastmessage));
1266:
//! @seealso
//! @[create()]
void select_db(string dbname)
- { database=dbname;
+ {
+ database=dbname;
reconnect();
reconnected=0;
}
1308:
void set_notify_callback(string condition,
void|function(int,string,string,mixed ...:void) notify_cb,void|int selfnotify,
mixed ... args)
- { if(!notify_cb)
+ {
+ if(!notify_cb)
m_delete(notifylist,condition);
else
- { array old=notifylist[condition];
+ {
+ array old=notifylist[condition];
if(!old)
old=({notify_cb});
if(selfnotify||args)
1323:
}
final private void runcallback(int pid,string condition,string extrainfo)
- { array cb;
+ {
+ array cb;
if((cb=notifylist[condition]||notifylist[""])
&& (pid!=backendpid || sizeof(cb)>1 && cb[1]))
cb[0](pid,condition,extrainfo,@cb[2..]);
1340:
//! @seealso
//! @[big_query()], @[quotebinary()], @[create()]
string quote(string s)
- { string r=_runtimeparameter->standard_conforming_strings;
+ {
+ string r=_runtimeparameter->standard_conforming_strings;
if(r && r=="on")
return replace(s, "'", "''");
return replace(s, ({ "'", "\\" }), ({ "''", "\\\\" }) );
1360:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
string quotebinary(string s)
- { return replace(s, ({ "'", "\\", "\0" }), ({ "''", "\\\\", "\\000" }) );
+ {
+ return replace(s, ({ "'", "\\", "\0" }), ({ "''", "\\\\", "\\000" }) );
}
//! This function creates a new database (assuming we
1372:
//! @seealso
//! @[drop_db()]
void create_db(string db)
- { big_query("CREATE DATABASE :db",([":db":db]));
+ {
+ big_query("CREATE DATABASE :db",([":db":db]));
}
//! This function destroys a database and all the data it contains (assuming
1386:
//! @seealso
//! @[create_db()]
void drop_db(string db)
- { big_query("DROP DATABASE :db",([":db":db]));
+ {
+ big_query("DROP DATABASE :db",([":db":db]));
}
//! @returns
1398:
//! @seealso
//! @[host_info()]
string server_info ()
- { return DRIVERNAME"/"+(_runtimeparameter->server_version||"unknown");
+ {
+ return DRIVERNAME"/"+(_runtimeparameter->server_version||"unknown");
}
//! @returns
1407:
//! @param glob
//! If specified, list only those databases matching it.
array(string) list_dbs (void|string glob)
- { array row,ret=({});
+ {
+ array row,ret=({});
object res=big_query("SELECT d.datname "
"FROM pg_database d "
"WHERE d.datname ILIKE :glob "
1425:
//! @param glob
//! If specified, list only the tables with matching names.
array(string) list_tables (void|string glob)
- { array row,ret=({}); // This query might not work on PostgreSQL 7.4
+ {
+ array row,ret=({}); // This query might not work on PostgreSQL 7.4
object res=big_query( // due to missing schemasupport
"SELECT CASE WHEN 'public'=n.nspname THEN '' ELSE n.nspname||'.' END "
" ||c.relname AS name "
1482:
//! If specified, list only the tables with matching names.
//! Setting it to @expr{*@} will include system columns in the list.
array(mapping(string:mixed)) list_fields(void|string table, void|string glob)
- { array row, ret=({});
+ {
+ array row, ret=({});
string schema=UNDEFINED;
sscanf(table||"*", "%s.%s", schema, table);
1532:
":glob":glob2reg(glob),":realglob":glob]));
array colnames=res->fetch_fields();
- { mapping(string:string) renames=([
+ {
+ mapping(string:string) renames=([
"attname":"name",
"nspname":"schema",
"relname":"table",
1548:
"reltuples":"rowcount",
]);
foreach(colnames;int i;mapping m)
- { string nf,field=m->name;
+ {
+ string nf,field=m->name;
if(nf=renames[field])
field=nf;
colnames[i]=field;
1558:
#define delifzero(m,field) if(!(m)[field]) m_delete(m,field)
while(row=res->fetch_row())
- { mapping m=mkmapping(colnames,row);
+ {
+ mapping m=mkmapping(colnames,row);
delifzero(m,"is_shared");
delifzero(m,"has_index");
delifzero(m,"has_primarykey");
1569:
}
private int oidformat(int oid)
- { switch(oid)
- { case BOOLOID:
+ {
+ switch(oid)
+ {
+ case BOOLOID:
case BYTEAOID:
case CHAROID:
case INT8OID:
1590:
}
final void _sendexecute(int fetchlimit)
- { string portalname=_c.portal->_portalname;
+ {
+ string portalname=_c.portal->_portalname;
PD("Execute portal %s fetchlimit %d\n",portalname,fetchlimit);
_c.sendcmd(({"E",_c.plugint32(4+sizeof(portalname)+1+4),portalname,
"\0",_c.plugint32(fetchlimit)}),!!fetchlimit);
if(!fetchlimit)
- { _c.portal->_fetchlimit=0; // disables further Executes
+ {
+ _c.portal->_fetchlimit=0; // disables further Executes
earlyclose=1;
if(sizeof(portalname))
- { PD("Close portal %s & Sync\n",portalname);
+ {
+ PD("Close portal %s & Sync\n",portalname);
_c.sendcmd(({"C",_c.plugint32(4+1+sizeof(portalname)+1),
"P",portalname,"\0"}));
}
1609:
}
final private void sendclose(void|int hold)
- { string portalname;
+ {
+ string portalname;
if(!_c)
portalsinflight=unnamedportalinuse=0;
else if(_c.portal && (portalname=_c.portal->_portalname))
- { _c.portal->_portalname = UNDEFINED;
+ {
+ _c.portal->_portalname = UNDEFINED;
_c.setportal();
portalsinflight--;
#ifdef PG_DEBUGMORE
1622:
if(!sizeof(portalname))
unnamedportalinuse--;
if(sizeof(portalname))
- { if(!earlyclose)
- { PD("Close portal %s\n",portalname);
+ {
+ if(!earlyclose)
+ {
+ PD("Close portal %s\n",portalname);
_c.sendcmd(({"C",_c.plugint32(4+1+sizeof(portalname)+1),
"P",portalname,"\0"}),!hold||portalsinflight?1:0);
}
1633:
}
final private string trbackendst(int c)
- { switch(c)
- { case 'I':return "idle";
- case 'T':return "intransaction";
- case 'E':return "infailedtransaction";
+ {
+ switch(c)
+ {
+ case 'I': return "idle";
+ case 'T': return "intransaction";
+ case 'E': return "infailedtransaction";
}
return "";
}
1653:
//! This function is PostgreSQL-specific, and thus it is not available
//! through the generic SQL-interface.
final string status_commit()
- { return trbackendst(backendstatus);
+ {
+ return trbackendst(backendstatus);
}
final private array(string) closestatement(mapping tp)
- { string oldprep=tp->preparedname;
+ {
+ string oldprep=tp->preparedname;
array(string) ret=({});
if(oldprep)
- { PD("Close statement %s\n",oldprep);
+ {
+ PD("Close statement %s\n",oldprep);
ret=({"C",_c.plugint32(4+1+sizeof(oldprep)+1),
"S",oldprep,"\0"});
}
1717:
//! @[Sql.Sql()->query()], @[Sql.pgsql_util.pgsql_result]
object big_query(string q,void|mapping(string|int:mixed) bindings,
void|int _alltyped)
- { string preparedname="";
+ {
+ string preparedname="";
string portalname="";
int forcecache=-1;
int forcetext=options->text_query;
string cenc=_runtimeparameter[CLIENT_ENCODING];
switch(cenc)
- { case UTF8CHARSET:
+ {
+ case UTF8CHARSET:
q=string_to_utf8(q);
break;
default:
1733:
array(string|int) paramValues;
array from;
if(bindings)
- { int pi=0,rep=0;
+ {
+ int pi=0,rep=0;
paramValues=allocate(sizeof(bindings));
from=allocate(sizeof(bindings));
array(string) to=allocate(sizeof(bindings));
foreach(bindings; mixed name; mixed value)
- { if(stringp(name)) // Throws if mapping key is empty string
- { if(name[0]!=':')
+ {
+ if(stringp(name)) // Throws if mapping key is empty string
+ {
+ if(name[0]!=':')
name=":"+name;
if(name[1]=='_') // Special option parameter
- { switch(name)
- { case ":_cache":forcecache=(int)value;
+ {
+ switch(name)
+ {
+ case ":_cache":
+ forcecache=(int)value;
break;
- case ":_text":forcetext=(int)value;
+ case ":_text":
+ forcetext=(int)value;
break;
}
continue;
1758:
if(multisetp(value)) // multisets are taken literally
rval=indices(value)*","; // and bypass the encoding logic
else
- { paramValues[pi++]=value;
+ {
+ paramValues[pi++]=value;
rval=sprintf("$%d",pi);
}
to[rep++]=rval;
1777:
mapping(string:mixed) tp;
int tstart;
if(forcetext)
- { if(bindings)
+ {
+ if(bindings)
q = .sql_util.emulate_bindings(q, bindings, this);
if(unnamedportalinuse)
throw("Unnamed portal in use, needed for simple query");
}
else if(forcecache==1
|| forcecache!=0 && (sizeof(q)>=MINPREPARELENGTH || cachealways[q]))
- { array(string) plugbuf=({});
+ {
+ array(string) plugbuf=({});
if(tp=prepareds[q])
- { if(tp->preparedname)
+ {
+ if(tp->preparedname)
prepstmtused++, preparedname=tp->preparedname;
else if((tstart=tp->trun)
&& tp->tparse*FACTORPLAN>=tstart
1795:
preparedname=PREPSTMTPREFIX+(string)pstmtcount++;
}
else
- { if(totalhits>=cachedepth)
- { foreach(prepareds;string ind;tp)
- { int oldhits=tp->hits;
+ {
+ if(totalhits>=cachedepth)
+ {
+ foreach(prepareds;string ind;tp)
+ {
+ int oldhits=tp->hits;
totalhits-=oldhits-(tp->hits=oldhits>>1);
if(oldhits<=1)
- { plugbuf+=closestatement(tp);
+ {
+ plugbuf+=closestatement(tp);
m_delete(prepareds,ind);
}
}
}
if(forcecache!=1 && createprefix->match(q)) // Flush cache on CREATE
- invalidatecache=1,tp=UNDEFINED;
+ {
+ invalidatecache=1;
+ tp=UNDEFINED;
+ }
else
prepareds[q]=tp=([]);
}
if(invalidatecache)
- { invalidatecache=0;
+ {
+ invalidatecache=0;
foreach(prepareds;;mapping np)
- { plugbuf+=closestatement(np);
+ {
+ plugbuf+=closestatement(np);
m_delete(np,"preparedname");
}
}
if(sizeof(plugbuf))
- { _c.sendcmd(plugbuf,1); // close expireds
+ {
+ _c.sendcmd(plugbuf,1); // close expireds
PD("%O\n",plugbuf);
}
tstart=gethrtime();
1826:
else
tp=UNDEFINED;
for(;;)
- { connectionclosed=0;
+ {
+ connectionclosed=0;
.pgsql_util.pgsql_result(this,q,_fetchlimit,
portalbuffersize,_alltyped,from,forcetext);
if(unnamedportalinuse)
1839:
clearmessage=1;
mixed err;
if(!(err = catch
- { if(forcetext)
- { _c.sendcmd(({"Q",_c.plugint32(4+sizeof(q)+1),q,"\0"}),1);
+ {
+ if(forcetext)
+ {
+ _c.sendcmd(({"Q",_c.plugint32(4+sizeof(q)+1),q,"\0"}),1);
PD("Simple query: %O\n",q);
}
else
- { if(!sizeof(preparedname) || !tp || !tp->preparedname)
- { PD("Parse statement %s\n",preparedname);
+ {
+ if(!sizeof(preparedname) || !tp || !tp->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
1855:
PD("Query: %O\n",q);
} // sends Parameter- and RowDescription for 'S'
if(!tp || !tp->datatypeoid)
- { PD("Describe statement %s\n",preparedname);
+ {
+ PD("Describe statement %s\n",preparedname);
_c.sendcmd(({"D",_c.plugint32(4+1+sizeof(preparedname)+1),
"S",preparedname,"\0"}),1);
}
else
- { skippeddescribe++;
+ {
+ skippeddescribe++;
_c.portal->_datatypeoid=tp->datatypeoid;
_c.portal->_datarowdesc=tp->datarowdesc;
}
- { array(string) plugbuf=({"B",UNDEFINED});
+ {
+ 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",
_c.plugint16(sizeof(paramValues))});
if(!tp || !tp->datatypeoid)
- { _decodemsg(gotparameterdescription);
+ {
+ _decodemsg(gotparameterdescription);
if(tp)
tp->datatypeoid=_c.portal->_datatypeoid;
}
1883:
plugbuf+=({_c.plugint16(oidformat(textbin))});
plugbuf+=({_c.plugint16(sizeof(paramValues))});
foreach(paramValues;int i;mixed value)
- { if(undefinedp(value))
+ {
+ if(undefinedp(value))
plugbuf+=({_c.plugint32(-1)}); // NULL
else if(stringp(value) && !sizeof(value))
- { int k=0;
+ {
+ int k=0;
switch(dtoid[i])
- { default:
+ {
+ default:
k=-1; // cast empty strings to NULL for non-string types
case BYTEAOID:
case TEXTOID:
1900:
}
else
switch(dtoid[i])
- { case TEXTOID:
+ {
+ case TEXTOID:
case BPCHAROID:
case VARCHAROID:
- { if(!value)
- { plugbuf+=({_c.plugint32(-1)});
+ {
+ if(!value)
+ {
+ plugbuf+=({_c.plugint32(-1)});
break;
}
value=(string)value;
switch(cenc)
- { case UTF8CHARSET:
+ {
+ case UTF8CHARSET:
value=string_to_utf8(value);
break;
default:
1923:
break;
}
default:
- { int k;
+ {
+ int k;
if(!value)
- { plugbuf+=({_c.plugint32(-1)});
+ {
+ plugbuf+=({_c.plugint32(-1)});
break;
}
value=(string)value;
1941:
}
case BOOLOID:plugbuf+=({_c.plugint32(1)});len++;
do
- { int tval;
+ {
+ int tval;
if(stringp(value))
tval=value[0];
else if(!intp(value))
- { value=!!value; // cast to boolean
+ {
+ value=!!value; // cast to boolean
break;
}
else
tval=value;
switch(tval)
- { case 'o':case 'O':
+ {
+ case 'o':case 'O':
catch
- { tval=value[1];
+ {
+ tval=value[1];
value=tval=='n'||tval=='N';
};
break;
1972:
if(intp(value))
len++,plugbuf+=({_c.plugint32(1),_c.plugbyte(value)});
else
- { value=(string)value;
+ {
+ value=(string)value;
switch(sizeof(value))
- { default:
+ {
+ default:
ERROR("\"char\" types must be 1 byte wide, got %O\n",
value);
case 0:
plugbuf+=({_c.plugint32(-1)}); // NULL
break;
- case 1:len++;
+ case 1:
+ len++;
plugbuf+=({_c.plugint32(1),_c.plugbyte(value[0])});
}
}
break;
- case INT8OID:len+=8;
+ case INT8OID:
+ len+=8;
plugbuf+=({_c.plugint32(8),_c.plugint64((int)value)});
break;
case OIDOID:
- case INT4OID:len+=4;
+ case INT4OID:
+ len+=4;
plugbuf+=({_c.plugint32(4),_c.plugint32((int)value)});
break;
- case INT2OID:len+=2;
+ case INT2OID:
+ len+=2;
plugbuf+=({_c.plugint32(2),_c.plugint16((int)value)});
break;
}
}
if(!tp || !tp->datarowdesc)
- { if(tp && dontcacheprefix->match(q)) // Don't cache FETCH/COPY
+ {
+ if(tp && dontcacheprefix->match(q)) // Don't cache FETCH/COPY
m_delete(prepareds,q),tp=0;
_decodemsg(gotrowdescription);
if(tp)
tp->datarowdesc=_c.portal->_datarowdesc;
}
- { array a;int i;
+ {
+ array a;int i;
len+=(i=sizeof(a=_c.portal->_datarowdesc))*2;
plugbuf+=({_c.plugint16(i)});
foreach(a;;mapping col)
2020:
_c.portal->_statuscmdcomplete=UNDEFINED;
_sendexecute(_fetchlimit
&& !(cachealways[q]
- || sizeof(q)>=MINPREPARELENGTH && execfetchlimit->match(q))
+ || sizeof(q)>=MINPREPARELENGTH &&
+ execfetchlimit->match(q))
&& FETCHLIMITLONGRUN);
if(tp)
- { _decodemsg(bindcomplete);
+ {
+ _decodemsg(bindcomplete);
int tend=gethrtime();
if(tend==tstart)
m_delete(prepareds,q);
else
- { tp->hits++;
+ {
+ tp->hits++;
totalhits++;
if(!tp->preparedname)
- { if(sizeof(preparedname))
+ {
+ if(sizeof(preparedname))
tp->preparedname=preparedname;
tstart=tend-tstart;
if(!tp->tparse || tp->tparse>tstart)
2051:
throw(err);
tp=UNDEFINED;
}
- { object tportal=_c.portal; // Make copy, because it might dislodge
+ {
+ object tportal=_c.portal; // Make copy, because it might dislodge
tportal->fetch_row(1); // upon initial fetch_row()
return tportal;
}
2063:
//! @seealso
//! @[big_query()], @[big_typed_query()], @[Sql.Sql], @[Sql.sql_result]
object streaming_query(string q,void|mapping(string|int:mixed) bindings)
- { return big_query(q,bindings);
+ {
+ return big_query(q,bindings);
}
//! This function returns an object that allows streaming and typed
2072:
//! @seealso
//! @[big_query()], @[Sql.Sql], @[Sql.sql_result]
object big_typed_query(string q,void|mapping(string|int:mixed) bindings)
- { return big_query(q,bindings,1);
+ {
+ return big_query(q,bindings,1);
}