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:874:
} private inline string int2hex(int i) { return String.int2hex(i); } private inline void throwdelayederror(object parent) { .pgsql_util.throwdelayederror(parent); }
+
private void startquery(int forcetext, .pgsql_util.Result portal, string q,
+
mapping(string:mixed) tp, string preparedname) {
+
.pgsql_util.conxion c = proxy.c;
+
if (forcetext) { // FIXME What happens if portals are still open?
+
portal._unnamedportalkey = proxy.unnamedportalmux->lock(1);
+
portal._portalname = "";
+
portal->_parseportal(); portal->_bindportal();
+
proxy.readyforquerycount++;
+
{
+
Thread.MutexKey lock = proxy.unnamedstatement->lock(1);
+
.pgsql_util.conxsess cs = c->start(1);
+
CHAIN(cs)->add_int8('Q')->add_hstring(({q, 0}), 4, 4);
+
cs->sendcmd(FLUSHLOGSEND, portal);
+
}
+
PD("Simple query: %O\n", q);
+
} else {
+
object plugbuffer;
+
portal->_parseportal();
+
if (!sizeof(preparedname) || !tp || !tp.preparedname) {
+
if (!sizeof(preparedname))
+
preparedname =
+
(portal._unnamedstatementkey = proxy.unnamedstatement->trylock(1))
+
? "" : PTSTMTPREFIX + int2hex(ptstmtcount++);
+
PD("Parse statement %O=%O\n", preparedname, q);
+
plugbuffer = c->start();
+
CHAIN(plugbuffer)->add_int8('P')
+
->add_hstring(({preparedname, 0, q, "\0\0\0"}), 4, 4)
+
#if 0
+
// 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 v8.3.3
+
// In v8.4 and later, things speed up slightly when it is omitted.
+
->add(PGFLUSH)
+
#endif
+
;
+
} else { // Use the name from the cache
+
preparedname = tp.preparedname; // to shortcut a potential race
+
PD("Using prepared statement %s for %O\n", preparedname, q);
+
}
+
portal._preparedname = preparedname;
+
if (!tp || !tp.datatypeoid) {
+
PD("Describe statement %O\n", preparedname);
+
if (!plugbuffer)
+
plugbuffer = c->start();
+
CHAIN(plugbuffer)->add_int8('D')
+
->add_hstring(({'S', preparedname, 0}), 4, 4);
+
plugbuffer->sendcmd(FLUSHSEND, portal);
+
} else {
+
if (plugbuffer)
+
plugbuffer->sendcmd(KEEP);
+
#ifdef PG_STATS
+
skippeddescribe++;
+
#endif
+
portal->_setrowdesc(tp.datarowdesc, tp.datarowtypes);
+
}
+
if ((portal._tprepared=tp) && tp.datatypeoid) {
+
mixed e = catch(portal->_preparebind(tp.datatypeoid));
+
if (e && !portal.delayederror) {
+
portal._unnamedstatementkey = 0; // Release early, release often
+
throw(e);
+
}
+
}
+
if (!proxy.unnamedstatement)
+
portal._unnamedstatementkey = 0; // Cover for a destruct race
+
}
+
}
+
//! This is the only provided direct interface which allows you to query the //! database. A simpler synchronous interface can be used through @[query()]. //! //! Bindings are supported natively straight across the network. //! Special bindings supported are: //! @mapping //! @member int ":_cache" //! Forces caching on or off for the query at hand. //! @member int ":_text" //! Forces text mode in communication with the database for queries on or off
pike.git/lib/modules/Sql.pmod/pgsql.pike:1007:
paramValues = pi ? paramValues[..pi-1] : .pgsql_util.emptyarray; from = ({from, to, paramValues}); } } else paramValues = .pgsql_util.emptyarray; if (String.width(q) > 8) ERROR("Wide string literals in %O not supported\n", q); if (has_value(q, "\0")) ERROR("Querystring %O contains invalid literal nul-characters\n", q); mapping(string:mixed) tp;
-
int tstart;
+
/* * FIXME What happens with regards to this detection when presented with * multistatement text-queries? * The primary function of this detection is to ensure a SYNC * right after a COMMIT, and no SYNC after a BEGIN. */ int transtype = .pgsql_util.transendprefix->match(q) ? TRANSEND : .pgsql_util.transbeginprefix->match(q) ? TRANSBEGIN : NOTRANS; if (transtype != NOTRANS) tp = .pgsql_util.describenodata; // Description already known else if (!forcetext && forcecache == 1 || forcecache && sizeof(q) >= MINPREPARELENGTH) { object plugbuffer = c->start(); if (tp = proxy.prepareds[q]) { if (tp.preparedname) { #ifdef PG_STATS prepstmtused++; #endif preparedname = tp.preparedname;
-
} else if(
(tstart =
tp.trun
)
-
&& tp.tparse*FACTORPLAN >=
tstart
+
} else if(tp.trun && tp.tparse*FACTORPLAN >=
tp.trun
&& (undefinedp(options.cache_autoprepared_statements) || options.cache_autoprepared_statements)) preparedname = PREPSTMTPREFIX + int2hex(pstmtcount++); } else { if (proxy.totalhits >= cachedepth) foreach (proxy.prepareds; string ind; tp) { int oldhits = tp.hits; proxy.totalhits -= oldhits-(tp.hits = oldhits >> 1); if (oldhits <= 1) { closestatement(plugbuffer, tp.preparedname);
pike.git/lib/modules/Sql.pmod/pgsql.pike:1057:
proxy.prepareds[q] = tp = ([]); } if (proxy.invalidatecache) { proxy.invalidatecache = 0; foreach (proxy.prepareds; ; mapping np) { closestatement(plugbuffer, np.preparedname); m_delete(np, "preparedname"); } } if (sizeof(CHAIN(plugbuffer))) {
-
PD("%O\n",(string)CHAIN(plugbuffer));
+
PD("%O\n",
(string)CHAIN(plugbuffer));
plugbuffer->sendcmd(FLUSHSEND); // close expireds } else plugbuffer->sendcmd(KEEP); // close start()
-
tstart = gethrtime();
+
} else // Result autoassigns to portal tp = 0; .pgsql_util.Result portal; portal = .pgsql_util.Result(proxy, c, q, portalbuffersize, _alltyped, from, forcetext, timeout, syncparse, transtype); portal._tprepared = tp; #ifdef PG_STATS portalsopened++; #endif proxy.clearmessage = 1;
-
if (forcetext) {
//
FIXME
What
happens
if
portals
are
still
open?
-
portal.
_
unnamedportalkey
=
proxy.unnamedportalmux->lock(1);
-
portal._portalname = "";
-
portal->_parseportal
(
); portal->
_
bindportal
()
;
-
proxy.readyforquerycount++;
-
{
-
Thread.MutexKey lock
=
proxy
.
unnamedstatement->lock(1);
-
.
pgsql_util.
conxsess cs = c->start(1);
-
CHAIN(cs)->add
_
int8('Q')->add_hstring(({q, 0}), 4, 4);
-
cs->sendcmd(FLUSHLOGSEND, portal);
-
}
-
PD("Simple query: %O\n", q);
-
} else {
-
object plugbuffer;
-
portal->_parseportal();
-
if (!sizeof(preparedname) || !tp || !tp
.
preparedname) {
-
if (!sizeof(preparedname))
-
preparedname=
-
(portal.
_
unnamedstatementkey = proxy.unnamedstatement->trylock
(
1
))
-
? "" : PTSTMTPREFIX+int2hex(ptstmtcount++);
-
PD("Parse statement %O=%O\n", preparedname, q);
-
plugbuffer = c->start();
-
CHAIN(plugbuffer)->add
_
int8
(
'P')
-
->add_hstring(({preparedname
, 0,
q
,
"\0\0\0"})
,
4
,
4)
-
#if 0
-
// 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 v8.3.3
-
// In v8.4 and later, things speed up slightly when it is omitted.
-
->add(PGFLUSH
)
-
#endif
-
;
-
}
else
{ // Use the name from the cache
-
preparedname = tp.preparedname; // to shortcut a potential race
-
PD
(
"Using prepared statement %s for %O\n"
,
preparedname
, q
);
-
}
-
portal._preparedname = preparedname;
-
if (!
tp
|| !tp.datatypeoid) {
-
PD("Describe statement %O\n"
, preparedname);
-
if (!plugbuffer)
-
plugbuffer = c->start();
-
CHAIN(plugbuffer)->add_int8('D')
-
->add_hstring(({'S', preparedname, 0}), 4, 4);
-
plugbuffer->sendcmd(FLUSHSEND, portal);
-
} else {
-
if (plugbuffer)
-
plugbuffer->sendcmd(KEEP);
-
#ifdef PG_STATS
-
skippeddescribe++;
-
#endif
-
portal->_setrowdesc(tp.datarowdesc, tp.datarowtypes);
-
}
-
if ((portal._tprepared=tp) && tp.datatypeoid) {
-
mixed e = catch(portal->_preparebind(tp.datatypeoid));
-
if (e && !portal.delayederror) {
-
portal._unnamedstatementkey = 0; // Release early, release often
-
throw(e);
-
}
-
}
-
if (!proxy.unnamedstatement)
-
portal._unnamedstatementkey = 0; // Cover for a destruct race
-
}
+
//
Do
not
run
a
query
in
the
local
_
backend
to
prevent
deadlocks
+
if
(
Thread.this
_
thread
() =
=
.pgsql_util.
local
_
backend
.
executing
_
thread
())
+
call
_
out
(
startquery
, 0,
forcetext
,
portal
,
q
,
tp
,
preparedname
);
+
else
+
startquery
(
forcetext
,
portal
, q
,
tp, preparedname);
throwdelayederror(portal); return portal; } //! This is an alias for @[big_query()], since @[big_query()] already supports //! streaming of multiple simultaneous queries through the same connection. //! //! @seealso //! @[big_query()], @[big_typed_query()], @[Sql.Connection], @[Sql.Result] /*semi*/final variant inline .pgsql_util.Result streaming_query(string q,