Skip to content
Snippets Groups Projects
Commit ea77efba authored by Stephen R. van den Berg's avatar Stephen R. van den Berg
Browse files

Enable true bindings for Postgres

Rev: lib/modules/Sql.pmod/postgres.pike:1.30
Rev: src/modules/Postgres/postgres.c:1.62
parent 2605fe70
Branches
Tags
No related merge requests found
/* /*
* This is part of the Postgres module for Pike. * This is part of the Postgres module for Pike.
* *
* $Id: postgres.pike,v 1.29 2008/06/28 16:49:55 nilsson Exp $ * $Id: postgres.pike,v 1.30 2008/07/04 08:25:39 srb Exp $
* *
*/ */
...@@ -384,9 +384,47 @@ array(mapping(string:mixed)) list_fields (string table, void|string wild) ...@@ -384,9 +384,47 @@ array(mapping(string:mixed)) list_fields (string table, void|string wild)
//! @[Sql.Sql], @[Sql.sql_result] //! @[Sql.Sql], @[Sql.sql_result]
int|object big_query(object|string q, mapping(string|int:mixed)|void bindings) int|object big_query(object|string q, mapping(string|int:mixed)|void bindings)
{ {
if(stringp(q) && String.width(q)>8)
q=string_to_utf8(q);
if (!bindings) if (!bindings)
return ::big_query(q); return ::big_query(q);
return ::big_query(.sql_util.emulate_bindings(q, bindings, this)); int pi=0,rep=0;
array(string|int) paramValues=allocate(sizeof(bindings)*2);
array(string) from=allocate(sizeof(bindings));
array(string) to=allocate(sizeof(bindings));
foreach(bindings; mixed name; mixed value) {
// Throws if mapping key is empty string.
if(stringp(name)) {
if(name[0]!=':')
name=":"+name;
if(name[1]=='_') {
// Special parameter
continue;
}
}
from[rep]=name;
string rval;
if(multisetp(value)) {
rval=sizeof(value) ? indices(value)[0] : "";
}
else {
paramValues[pi++]=name[sizeof(name)-1]=='_'; // Force binary mode
if(zero_type(value)) // when name ends in _
paramValues[pi++]=UNDEFINED;
else {
if(stringp(value) && String.width(value)>8)
value=string_to_utf8(value);
paramValues[pi++]=(string)value;
}
rval="$"+(string)(pi/2);
}
to[rep++]=rval;
}
paramValues= pi ? paramValues[..pi-1] : UNDEFINED;
if(rep--) {
q=replace(q,from[..rep],to[..rep]);
}
return ::big_query(q, paramValues);
} }
#else #else
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
|| This file is part of Pike. For copyright information see COPYRIGHT. || This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information. || for more information.
|| $Id: postgres.c,v 1.61 2008/06/30 12:10:48 srb Exp $ || $Id: postgres.c,v 1.62 2008/07/04 08:25:39 srb Exp $
*/ */
/* /*
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <string.h> #include <string.h>
/* Pike includes */ /* Pike includes */
#include "svalue.h"
#include "las.h" #include "las.h"
#include "machine.h" #include "machine.h"
#include "pike_memory.h" #include "pike_memory.h"
...@@ -381,21 +382,75 @@ static void f_big_query(INT32 args) ...@@ -381,21 +382,75 @@ static void f_big_query(INT32 args)
PGconn *conn = THIS->dblink; PGconn *conn = THIS->dblink;
PGresult * res; PGresult * res;
PGnotify * notification; PGnotify * notification;
char *query; struct array *bnds = 0;
char *query = 0;
int lastcommit,docommit,dofetch; int lastcommit,docommit,dofetch;
int cnt;
int nParams = 0;
const char** paramValues = 0;
int* paramLengths = 0;
int* paramFormats = 0;
int resultFormat = 0;
PQ_FETCH(); PQ_FETCH();
docommit=dofetch=0; docommit=dofetch=0;
lastcommit=THIS->lastcommit; lastcommit=THIS->lastcommit;
check_all_args("Postgres->big_query",args,BIT_STRING,0); check_all_args("Postgres->big_query",args,
BIT_STRING,
BIT_VOID | BIT_ARRAY,
0);
if (!conn) if (!conn)
Pike_error ("Not connected.\n"); Pike_error ("Not connected.\n");
switch(args)
{
default:
if(Pike_sp[1-args].type == PIKE_T_ARRAY)
bnds=Pike_sp[1-args].u.array;
case 1:
query=" ";
if(Pike_sp[-args].u.string->len) if(Pike_sp[-args].u.string->len)
query=Pike_sp[-args].u.string->str; query=Pike_sp[-args].u.string->str;
else }
query=" ";
if(bnds && (cnt=bnds->size)) {
int i;
struct svalue *item;
if(cnt & 1)
Pike_error ("Uneven number of arrayelements.\n");
nParams=cnt=cnt/2;
paramValues = xalloc(cnt*sizeof*paramValues);
paramLengths = xalloc(cnt*sizeof*paramLengths);
paramFormats = xalloc(cnt*sizeof*paramFormats);
for (i=0,item=bnds->item; cnt--; item++,i++) {
if (item->type != PIKE_T_INT)
Pike_error ("Expected integer element.\n");
paramFormats[i] = item->u.integer ? 1 : 0;
switch((++item)->type)
{ case PIKE_T_STRING:
paramValues[i] = item->u.string->str;
paramLengths[i] = item->u.string->len;
break;
case PIKE_T_INT:
case T_VOID:
paramValues[i] = 0; /* NULL */
paramLengths[i] = 0;
break;
default:
Pike_error ("Expected string or UNDEFINED element, Got %d.\n",
item->type);
break;
}
}
}
THREADS_ALLOW(); THREADS_ALLOW();
PQ_LOCK(); PQ_LOCK();
...@@ -431,11 +486,13 @@ static void f_big_query(INT32 args) ...@@ -431,11 +486,13 @@ static void f_big_query(INT32 args)
strcpy(nquery+CPREFLEN-1,query); strcpy(nquery+CPREFLEN-1,query);
if(lastcommit) if(lastcommit)
goto yupbegin; goto yupbegin;
res=PQexec(conn,nquery); res=PQexecParams(conn,nquery,
nParams,0,paramValues,paramLengths,paramFormats,resultFormat);
if(PQstatus(conn) != CONNECTION_OK) { if(PQstatus(conn) != CONNECTION_OK) {
PQclear(res); PQclear(res);
PQreset(conn); PQreset(conn);
res=PQexec(conn,nquery); res=PQexecParams(conn,nquery,
nParams,0,paramValues,paramLengths,paramFormats,resultFormat);
} }
if(res) if(res)
switch(PQresultStatus(res)) { switch(PQresultStatus(res)) {
...@@ -444,7 +501,8 @@ static void f_big_query(INT32 args) ...@@ -444,7 +501,8 @@ static void f_big_query(INT32 args)
yupbegin: res=PQexec(conn,"BEGIN"); yupbegin: res=PQexec(conn,"BEGIN");
if(res && PQresultStatus(res)==PGRES_COMMAND_OK) { if(res && PQresultStatus(res)==PGRES_COMMAND_OK) {
PQclear(res); PQclear(res);
res=PQexec(conn,nquery); res=PQexecParams(conn,nquery,nParams,0,
paramValues,paramLengths,paramFormats,resultFormat);
if(res && PQresultStatus(res)==PGRES_COMMAND_OK) if(res && PQresultStatus(res)==PGRES_COMMAND_OK)
docommit=1; docommit=1;
else { else {
...@@ -470,7 +528,8 @@ yupbegin: res=PQexec(conn,"BEGIN"); ...@@ -470,7 +528,8 @@ yupbegin: res=PQexec(conn,"BEGIN");
} }
lastcommit=0; lastcommit=0;
if(!res) if(!res)
res=PQexec(conn,query); res=PQexecParams(conn,query,
nParams,0,paramValues,paramLengths,paramFormats,resultFormat);
/* A dirty hack to fix the reconnect bug. /* A dirty hack to fix the reconnect bug.
* we don't need to store the host/user/pass/db... etc.. * we don't need to store the host/user/pass/db... etc..
* PQreset() does all the job. * PQreset() does all the job.
...@@ -481,7 +540,8 @@ yupbegin: res=PQexec(conn,"BEGIN"); ...@@ -481,7 +540,8 @@ yupbegin: res=PQexec(conn,"BEGIN");
(PQresultStatus(res) == PGRES_BAD_RESPONSE)) { (PQresultStatus(res) == PGRES_BAD_RESPONSE)) {
PQclear(res); PQclear(res);
PQreset(conn); PQreset(conn);
res=PQexec(conn,query); res=PQexecParams(conn,query,
nParams,0,paramValues,paramLengths,paramFormats,resultFormat);
} }
notification=PQnotifies(conn); notification=PQnotifies(conn);
...@@ -491,6 +551,10 @@ yupbegin: res=PQexec(conn,"BEGIN"); ...@@ -491,6 +551,10 @@ yupbegin: res=PQexec(conn,"BEGIN");
THIS->dofetch=dofetch; THIS->dofetch=dofetch;
THIS->lastcommit=lastcommit; THIS->lastcommit=lastcommit;
if (bnds) {
xfree(paramValues); xfree(paramLengths); xfree(paramFormats);
}
pop_n_elems(args); pop_n_elems(args);
if (notification!=NULL) { if (notification!=NULL) {
pgdebug("Incoming notification: \"%s\"\n",notification->relname); pgdebug("Incoming notification: \"%s\"\n",notification->relname);
...@@ -764,7 +828,8 @@ PIKE_MODULE_INIT ...@@ -764,7 +828,8 @@ PIKE_MODULE_INIT
ADD_FUNCTION("select_db", f_select_db, tFunc(tStr,tVoid), 0); ADD_FUNCTION("select_db", f_select_db, tFunc(tStr,tVoid), 0);
/* function(string:int|object) */ /* function(string:int|object) */
ADD_FUNCTION("big_query", f_big_query, tFunc(tStr,tOr(tInt,tObj)), 0); ADD_FUNCTION("big_query", f_big_query,
tFunc(tStr tOr(tVoid,tArr(tOr3(tInt,tStr,tVoid))), tOr(tInt,tObj)), 0);
/* function(void:string) */ /* function(void:string) */
ADD_FUNCTION("error", f_error, tFunc(tVoid,tStr), 0); ADD_FUNCTION("error", f_error, tFunc(tVoid,tStr), 0);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment