about oracle performance improvement
zhongwei feng
fengzhw at gmail.com
Wed Aug 26 15:15:25 CEST 2009
--- org/sql_oracle.c
+++ new/sql_oracle.c
@@ -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,11 +58,110 @@
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) {
+ printf("DEBUG:%s\n",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;
+}
+
+
/*************************************************************************
*
* Function: sql_error
@@ -248,6 +366,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 +375,9 @@
return -1;
}
+ if (oracle_sock->bindcount>0)
+ sql_ocibind(sqlsocket);
+
x = OCIStmtExecute(oracle_sock->conn,
oracle_sock->queryHandle,
oracle_sock->errHandle,
@@ -306,6 +429,8 @@
return SQL_DOWN;
}
+ sql_bindparse(sqlsocket, querystr);
+
if (OCIStmtPrepare (oracle_sock->queryHandle, oracle_sock->errHandle,
querystr, strlen(querystr),
OCI_NTV_SYNTAX, OCI_DEFAULT)) {
@@ -313,6 +438,9 @@
return -1;
}
+ if (oracle_sock->bindcount>0)
+ sql_ocibind(sqlsocket);
+
/* Query only one row by default (for now) */
x = OCIStmtExecute(oracle_sock->conn,
oracle_sock->queryHandle,
============================================
diaup.conf
authorize_check_query = "SELECT id,UserName,Attribute,Value,op FROM ${authcheck_table} WHERE Username = :uname ORDER BY id\\P:uname=%{SQL-User-Name}"
accounting_update_query = "UPDATE ${acct_table1} \
SET FramedIPAddress = :framedip, \
AcctSessionTime = TO_NUMBER(:acctsesstime), \
AcctInputOctets = TO_NUMBER(:acct_in_oct) + TO_NUMBER(:acct_in_octG) * 4294967296, \
AcctOutputOctets = TO_NUMBER(:acct_out_oct) + TO_NUMBER(:acct_out_octG) * 4294967296 \
WHERE \
AcctSessionId = :acctsessid AND \
UserName = :uname AND \
NASIPAddress= :nasip AND \
AcctStopTime IS NULL\
\\P:framedip=%{Framed-IP-Address}\
\\P:acctsesstime=%{Acct-Session-Time}\
\\P:acct_in_oct=%{Acct-Input-Octets}\\P:acct_in_octG=%{Acct-Input-Gigawords}\
\\P:acct_out_oct=%{Acct-Input-Octets}\\P:acct_out_octG=%{Acct-Input-Gigawords}\
\\P:acctsessid=%{Acct-Session-Id}\
\\P:uname=%{SQL-User-Name}\
\\P:nasip=%{NAS-IP-Address}"
More information about the Freeradius-Devel
mailing list