pike.git
/
lib
/
modules
/
Sql.pmod
/
pgsql.pike
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Sql.pmod/pgsql.pike:91:
int _packetssent; // Number of packets sent int _bytessent; // Number of bytes sent private int warningsdropcount; // Number of uncollected warnings private int prepstmtused; // Number of times prepared statements were used private int warningscollected; private string host, database, user, pass; private int port; private object fetchprefix =Regexp("^[ \t\f\r\n]*[Ff][Ee][Tt][Cc][Hh][ \t\f\r\n]");
+
private object limitpostfix
+
=Regexp("[ \t\f\r\n][Ll][Ii][Mm][Ii][Tt][ \t\f\r\n]+[12][; \t\f\r\n]*$");
Thread.Mutex _querymutex; Thread.Mutex _stealmutex; protected string _sprintf(int type, void|mapping flags) { string res=UNDEFINED; switch(type) { case 'O': res=sprintf(DRIVERNAME"://%s@%s:%d/%s pid:%d %s reconnected:%d\n" "mstate: %O qstate: %O pstmtcount: %d pportalcount: %d prepcache: %d\n" "Last message: %s",
pike.git/lib/modules/Sql.pmod/pgsql.pike:1289:
return 1; //binary } return 0; // text } final void _sendexecute(int fetchlimit) { 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);
-
_c.portal->_inflight+=fetchlimit;
+
if(!fetchlimit) {
-
+
_c.portal->_fetchlimit=0; // disables further Executes
earlyclose=1; if(sizeof(portalname)) { PD("Close portal %s & Sync\n",portalname); _c.sendcmd(({"C",_c.plugint32(4+1+sizeof(portalname)+1), "P",portalname,"\0"})); } _c.sendcmd(({"S",_c.plugint32(4)}),2); }
-
+
else
+
_c.portal->_inflight+=fetchlimit;
} final private void sendclose(void|int hold) { string portalname; if(_c.portal && (portalname=_c.portal->_portalname)) { _c.portal->_portalname = UNDEFINED; _c.setportal(); portalsinflight--; #ifdef DEBUGMORE PD("Closetrace %O\n",backtrace());
pike.git/lib/modules/Sql.pmod/pgsql.pike:1355:
//! database. If you wish to use the simpler "query" function, you need to //! use the @[Sql.Sql] generic SQL-object. //! //! It returns a pgsql_result object (which conforms to the //! @[Sql.sql_result] standard interface for accessing data). I //! recommend using @[query()] for simpler queries (because it is //! easier to handle, but stores all the result in memory), and //! @[big_query()] for queries you expect to return huge amounts of //! data (it's harder to handle, but fetches results on demand). //!
+
//! Bindings are supported natively straight through the network.
+
//! Special bindings supported are: ":_cache", to force caching or
+
//! not caching for the query at hand depending on the mappingvalue.
+
//!
//! @note //! This function @b{can@} raise exceptions. //! //! @note //! This function does not support multiple queries in one querystring. //! I.e. it allows for but does not require a trailing semicolon, but it //! simply ignores any commands after the first semicolon. This can be //! viewed as a limited protection against SQL-injection attacks. //! //! @seealso //! @[Sql.Sql], @[Sql.sql_result], @[Sql.pgsql_util.pgsql_result] object big_query(string q,void|mapping(string|int:mixed) bindings) { string preparedname=""; string portalname="";
-
+
int forcecache=-1;
if(stringp(q) && String.width(q)>8) q=string_to_utf8(q); array(string|int) paramValues; if(bindings) { int pi=0,rep=0; paramValues=allocate(sizeof(bindings)); array(string) 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]!=':') name=":"+name; if(name[1]=='_') { // Special option parameter
-
//
No
options
supported
at
the
moment
+
switch(name)
{
+
case
":_cache":forcecache=(int)value;
+
break;
+
}
continue; } } from[rep]=name; string rval; if(multisetp(value)) { rval=sizeof(value) ? indices(value)[0] : ""; } else { if(zero_type(value))
pike.git/lib/modules/Sql.pmod/pgsql.pike:1411:
to[rep++]=rval; } if(rep--) q=replace(q,from[..rep],to[..rep]); paramValues= pi ? paramValues[..pi-1] : ({}); } else paramValues = ({}); mapping(string:mixed) tp; int tstart;
-
if(sizeof(q)>=MINPREPARELENGTH) {
+
if(
forcecache==1 || forcecache!=0 &&
sizeof(q)>=MINPREPARELENGTH) {
if(tp=prepareds[q]) { if(tp->preparedname) prepstmtused++, preparedname=tp->preparedname; else if((tstart=tp->trun) && tp->tparse*FACTORPLAN>=tstart) preparedname=PREPSTMTPREFIX+(string)pstmtcount++; } else { if(totalhits>=cachedepth) { array(string) plugbuf=({});
pike.git/lib/modules/Sql.pmod/pgsql.pike:1529:
value=(string)value; if(sizeof(value)!=1) ERROR("\"char\" types must be 1 byte wide, got %d\n", sizeof(value)); plugbuf+=({value}); } break; case INT8OID:len+=8; plugbuf+=({_c.plugint32(8),_c.plugint64((int)value)}); break;
+
case OIDOID:
case INT4OID:len+=4; plugbuf+=({_c.plugint32(4),_c.plugint32((int)value)}); break; case INT2OID:len+=2; plugbuf+=({_c.plugint32(2),_c.plugint16((int)value)}); break; } } if(!tp || !tp->datarowdesc) { if(tp && fetchprefix->match(q)) // Don't cache FETCH
pike.git/lib/modules/Sql.pmod/pgsql.pike:1558:
plugbuf+=({_c.plugint16(oidformat(col->type))}); } plugbuf[1]=_c.plugint32(len); PD("Bind portal %s statement %s\n",portalname,preparedname); _c.sendcmd(plugbuf); #ifdef DEBUGMORE PD("%O\n",plugbuf); #endif } _c.portal->_statuscmdcomplete=UNDEFINED;
-
_sendexecute(_fetchlimit && FETCHLIMITLONGRUN);
+
_sendexecute(_fetchlimit
+
&&
!limitpostfix->match(q) // Optimisation for LIMIT 1
+
&&
FETCHLIMITLONGRUN);
if(tp) { _decodemsg(bindcomplete); int tend=gethrtime(); if(tend==tstart) m_delete(prepareds,q); else { tp->hits++; totalhits++; if(!tp->preparedname) { if(sizeof(preparedname))