patch about OCI binding
zhongwei feng
fengzhw at gmail.com
Thu Aug 27 12:54:32 CEST 2009
--- sql_oracle.c Thu Aug 27 18:46:35 2009
+++ sql_oracle.c.new Thu Aug 27 18:38:47 2009
@@ -29,6 +29,25 @@
#include <oci.h>
#include "rlm_sql.h"
+#define MAXBIND 40
+/*
+ * SQL WITH BIND : <SQL>\P<BIND1>\P<BIND2>.....\P<BINDn>
+ * BIND1 : <NAME>=<VALUE> ; the <NAME> is optional, if none, bindbyindex
+ *
+ */
+typedef struct rlm_sql_oraclesockbind {
+ char * ptr ;
+ int idx ;
+ char * name ;
+ int namelen ;
+ char * value ;
+ int vallen;
+
+ OCIBind *bindp ;
+} rlm_sql_oraclesockbind;
+
+
+
typedef struct rlm_sql_oracle_sock {
OCIEnv *env;
OCIError *errHandle;
@@ -39,10 +58,108 @@
int id;
int in_use;
struct timeval tv;
+
+ rlm_sql_oraclesockbind binds[MAXBIND];
+ int bindcount;
} rlm_sql_oracle_sock;
#define MAX_DATASTR_LEN 64
+/*************************************************************************
+ *
+ * Function: sql_bindparse
+ *
+ * Purpose: split the sql statement for pure sql , each bind item , etc .
+ *
+ *
+ *************************************************************************/
+
+static int sql_bindparse(SQLSOCK *sqlsocket, char * query)
+{
+ char * p = query ;
+ int count = 0 , i , k;
+ rlm_sql_oracle_sock *oracle_sock = sqlsocket->conn ;
+ oracle_sock->bindcount = 0 ;
+
+ while ( *p ) {
+ switch ( *p ) {
+ case '\\' :
+ if (p[1]!='P') {
+ break;
+ }
+ *p = '\0';
+ oracle_sock->binds[count].ptr = p+2;
+ count ++ ;
+ p ++ ;
+ break;
+ //default
+ } /* end of switch(*p) */
+ p ++ ;
+ if (count>=MAXBIND)
+ break;
+ }
+
+ for(i = 0, k = 0 ; k<count; k ++){
+ if (oracle_sock->binds[k].ptr==NULL)
+ continue;
+ if (oracle_sock->binds[k].ptr[0]=='\0')
+ continue;
+ if ((p = strchr(oracle_sock->binds[k].ptr, '='))==NULL)
+ continue;
+ *p = '\0';
+ oracle_sock->binds[i].value = p+1;
+ oracle_sock->binds[i].vallen = strlen (oracle_sock->binds[i].value);
+ if (p==oracle_sock->binds[k].ptr){
+ oracle_sock->binds[i].name = NULL;
+ } else {
+ oracle_sock->binds[i].name = oracle_sock->binds[k].ptr;
+ oracle_sock->binds[i].namelen = p - oracle_sock->binds[k].ptr;
+ }
+ oracle_sock->binds[i].idx = i+1 ;
+ radlog(L_DBG, "bind[%d] v_p is<%s>(%d)-<%s>(%d)", i,
+ oracle_sock->binds[i].name,oracle_sock->binds[i].namelen,
+ oracle_sock->binds[i].value,oracle_sock->binds[i].vallen );
+ i ++ ; continue;
+ }
+
+ oracle_sock->bindcount = i ;
+
+ return 0 ;
+}
+
+
+static int sql_ocibind(SQLSOCK *sqlsocket)
+{
+ int i ;
+ rlm_sql_oracle_sock *oracle_sock = sqlsocket->conn ;
+ for(i = 0;i<oracle_sock->bindcount; i++){
+ if (oracle_sock->binds[i].name!=NULL){
+ OCIBindByName(
+ oracle_sock->queryHandle,
+ &oracle_sock->binds[i].bindp,
+ oracle_sock->errHandle,
+ oracle_sock->binds[i].name,
+ oracle_sock->binds[i].namelen,
+ (ub1 *) oracle_sock->binds[i].value,
+ oracle_sock->binds[i].vallen+1,
+ SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0,
+ OCI_DEFAULT);
+ } else {
+ OCIBindByPos(
+ oracle_sock->queryHandle,
+ &oracle_sock->binds[i].bindp,
+ oracle_sock->errHandle,
+ oracle_sock->binds[i].idx,
+ (ub1 *) oracle_sock->binds[i].value,
+ oracle_sock->binds[i].vallen+1,
+ SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2) 0, (ub4) 0, (ub4 *) 0,
+ OCI_DEFAULT);
+ }
+ }
+
+ return 0;
+}
+
/*************************************************************************
*
@@ -248,6 +365,8 @@
return SQL_DOWN;
}
+ sql_bindparse(sqlsocket, querystr);
+
if (OCIStmtPrepare (oracle_sock->queryHandle, oracle_sock->errHandle,
querystr, strlen(querystr),
OCI_NTV_SYNTAX, OCI_DEFAULT)) {
@@ -255,6 +374,9 @@
return -1;
}
+ if (oracle_sock->bindcount>0)
+ sql_ocibind(sqlsocket);
+
x = OCIStmtExecute(oracle_sock->conn,
oracle_sock->queryHandle,
oracle_sock->errHandle,
@@ -306,12 +428,17 @@
return SQL_DOWN;
}
+ sql_bindparse(sqlsocket, querystr);
+
if (OCIStmtPrepare (oracle_sock->queryHandle, oracle_sock->errHandle,
querystr, strlen(querystr),
OCI_NTV_SYNTAX, OCI_DEFAULT)) {
radlog(L_ERR,"rlm_sql_oracle: prepare failed in sql_select_query: %s",sql_error(sqlsocket, config));
return -1;
}
+
+ if (oracle_sock->bindcount>0)
+ sql_ocibind(sqlsocket);
/* Query only one row by default (for now) */
x = OCIStmtExecute(oracle_sock->conn,
More information about the Freeradius-Devel
mailing list