static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
static int sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
-/*************************************************************************
+/** Establish connection to the db
*
- * Function: sql_init_socket
- *
- * Purpose: Establish connection to the db
- *
- *************************************************************************/
+ */
static int sql_init_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- rlm_sql_firebird_sock *firebird_sock;
- long res;
-
-
- if (!handle->conn) {
- handle->conn = (rlm_sql_firebird_sock *)rad_malloc(sizeof(rlm_sql_firebird_sock));
- if (!handle->conn) return -1;
- }
-
- firebird_sock = handle->conn;
-
- res=fb_init_socket(firebird_sock);
- if (res) return -1;
-
- if (fb_connect(firebird_sock,config)) {
- radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n", firebird_sock->lasterror);
- return SQL_DOWN;
- }
-
- return 0;
+ rlm_sql_firebird_sock *firebird_sock;
+
+ long res;
+
+ if (!handle->conn) {
+ handle->conn = rad_malloc(sizeof(rlm_sql_firebird_sock));
+ if (!handle->conn) {
+ return -1;
+ }
+ }
+
+ firebird_sock = handle->conn;
+
+ res = fb_init_socket(firebird_sock);
+ if (res) {
+ return -1;
+ }
+
+ if (fb_connect(firebird_sock,config)) {
+ radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n",
+ firebird_sock->lasterror);
+
+ return SQL_DOWN;
+ }
+
+ return 0;
}
-
-/*************************************************************************
- *
- * Function: sql_destroy_socket
- *
- * Purpose: Free socket and private connection data
+/** Free socket and private connection data
*
- *************************************************************************/
-static int sql_destroy_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
+ */
+static int sql_destroy_socket(rlm_sql_handle_t *handle,
+ rlm_sql_config_t *config)
{
- free(handle->conn);
- handle->conn = NULL;
- return 0;
+ free(handle->conn);
+
+ handle->conn = NULL;
+
+ return 0;
}
-/*************************************************************************
- *
- * Function: sql_query
+/** Issue a non-SELECT query (ie: update/delete/insert) to the database.
*
- * Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
- * the database.
- *
- *************************************************************************/
-
-static int sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr) {
- rlm_sql_firebird_sock *firebird_sock = handle->conn;
- int deadlock=0;
+ */
+static int sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config,
+ char *querystr) {
+ rlm_sql_firebird_sock *firebird_sock = handle->conn;
+
+ int deadlock = 0;
#ifdef _PTHREAD_H
- pthread_mutex_lock(&firebird_sock->mut);
+ pthread_mutex_lock(&firebird_sock->mut);
#endif
-TryAgain:
- if (fb_sql_query(firebird_sock,querystr)) {
-//Try again query when deadlock, beacuse in any case it will be retried.
-// but may be lost for short sessions
- if ((firebird_sock->sql_code==DEADLOCK_SQL_CODE) && !deadlock) {
- radlog(L_DBG,"sock_id deadlock. Retry query %s\n",querystr);
-//For non READ_COMMITED transactions put rollback here
-// fb_rollback(sock);
- deadlock=1;
- goto TryAgain;
- }
- radlog(L_ERR, "sock_id rlm_sql_firebird,sql_query error:sql_code=%li, error='%s', query=%s\n",
- firebird_sock->sql_code,
- firebird_sock->lasterror,
- querystr);
-
- if ((firebird_sock->sql_code==DOWN_SQL_CODE)) return SQL_DOWN;
-//free problem query
- if (fb_rollback(firebird_sock)) {
- //assume the network is down if rollback had failed
- radlog(L_ERR,"Fail to rollback transaction after previous error. Error: %s\n",
- firebird_sock->lasterror);
- return SQL_DOWN;
- }
-// firebird_sock->in_use=0;
- return -1;
- }
-
- if (firebird_sock->statement_type!=isc_info_sql_stmt_select) {
- if (fb_commit(firebird_sock)) return -1;
- }
-
- return 0;
+ try_again:
+ /*
+ * Try again query when deadlock, beacuse in any case it
+ * will be retried.
+ */
+ if (fb_sql_query(firebird_sock,querystr)) {
+ /* but may be lost for short sessions */
+ if ((firebird_sock->sql_code == DEADLOCK_SQL_CODE) &&
+ !deadlock) {
+ radlog(L_DBG,"sock_id deadlock. Retry query %s",
+ querystr);
+
+ /*
+ * @todo For non READ_COMMITED transactions put
+ * rollback here
+ * fb_rollback(sock);
+ */
+ deadlock = 1;
+ goto try_again;
+ }
+
+ radlog(L_ERR, "sock_id rlm_sql_firebird,sql_query error: "
+ "sql_code=%li, error='%s', query=%s",
+ (long int) firebird_sock->sql_code,
+ firebird_sock->lasterror,
+ querystr);
+
+ if (firebird_sock->sql_code == DOWN_SQL_CODE) {
+ return SQL_DOWN;
+ }
+
+ /* Free problem query */
+ if (fb_rollback(firebird_sock)) {
+ //assume the network is down if rollback had failed
+ radlog(L_ERR,"Fail to rollback transaction after "
+ "previous error. Error: %s",
+ firebird_sock->lasterror);
+
+ return SQL_DOWN;
+ }
+ // firebird_sock->in_use=0;
+ return -1;
+ }
+
+ if (firebird_sock->statement_type != isc_info_sql_stmt_select) {
+ if (fb_commit(firebird_sock)) {
+ return -1;
+ }
+ }
+
+ return 0;
}
-
-/*************************************************************************
- *
- * Function: sql_select_query
+/** Issue a select query to the database.
*
- * Purpose: Issue a select query to the database
- *
- *************************************************************************/
-static int sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr) {
-// rlm_sql_firebird_sock *firebird_sock = handle->conn;
- return (sql_query(handle, config, querystr));
-
+ */
+static int sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config,
+ char *querystr) {
+ return sql_query(handle, config, querystr);
}
-
-/*************************************************************************
- *
- * Function: sql_store_result
- *
- * Purpose: database specific store_result function. Returns a result
- * set for the query.
+/** Returns a result set for the query.
*
- *************************************************************************/
-static int sql_store_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- /* Not used */
- return 0;
+ */
+static int sql_store_result(UNUSED rlm_sql_handle_t *handle,
+ UNUSED rlm_sql_config_t *config) {
+ return 0;
}
-
-/*************************************************************************
- *
- * Function: sql_num_fields
- *
- * Purpose: database specific num_fields function. Returns number
- * of columns from query
+/** Returns number of columns from query.
*
- *************************************************************************/
-static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- return ((rlm_sql_firebird_sock *) handle->conn)->sqlda_out->sqld;
+ */
+static int sql_num_fields(rlm_sql_handle_t *handle,
+ UNUSED rlm_sql_config_t *config) {
+ return ((rlm_sql_firebird_sock *) handle->conn)->sqlda_out->sqld;
}
-
-/*************************************************************************
- *
- * Function: sql_num_rows
- *
- * Purpose: database specific num_rows. Returns number of rows in
- * query
+/** Returns number of rows in query.
*
- *************************************************************************/
+ */
static int sql_num_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- int res=sql_affected_rows(handle, config);
- return res;
+ return sql_affected_rows(handle, config);
}
-
-/*************************************************************************
- *
- * Function: sql_fetch_row
- *
- * Purpose: database specific fetch_row. Returns a rlm_sql_row_t struct
- * with all the data for the query in 'handle->row'. Returns
- * 0 on success, -1 on failure, SQL_DOWN if 'database is down'.
+/** Returns an individual row.
*
- *************************************************************************/
+ */
static int sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- rlm_sql_firebird_sock *firebird_sock = handle->conn;
- int res;
-
- handle->row = NULL;
- if (firebird_sock->statement_type!=isc_info_sql_stmt_exec_procedure) {
- res=fb_fetch(firebird_sock);
- if (res==100) return 0;
- if (res) {
- radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'\n", firebird_sock->lasterror);
- return -1;
- }
- } else firebird_sock->statement_type=0;
- fb_store_row(firebird_sock);
-
- handle->row = firebird_sock->row;
- return 0;
+ rlm_sql_firebird_sock *firebird_sock = handle->conn;
+ int res;
+
+ handle->row = NULL;
+
+ if (firebird_sock->statement_type != isc_info_sql_stmt_exec_procedure) {
+ res = fb_fetch(firebird_sock);
+ if (res == 100) {
+ return 0;
+ }
+
+ if (res) {
+ radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'",
+ firebird_sock->lasterror);
+
+ return -1;
+ }
+ } else {
+ firebird_sock->statement_type=0;
+ }
+
+ fb_store_row(firebird_sock);
+
+ handle->row = firebird_sock->row;
+
+ return 0;
}
-
-/*************************************************************************
+/** End the select query, such as freeing memory or result.
*
- * Function: sql_finish_select_query
- *
- * Purpose: End the select query, such as freeing memory or result
- *
- *************************************************************************/
-static int sql_finish_select_query(rlm_sql_handle_t * handle, rlm_sql_config_t *config) {
- rlm_sql_firebird_sock *sock=(rlm_sql_firebird_sock *) handle->conn;
- fb_commit(sock);
- fb_close_cursor(sock);
- return 0;
+ */
+static int sql_finish_select_query(rlm_sql_handle_t *handle,
+ UNUSED rlm_sql_config_t *config) {
+
+ rlm_sql_firebird_sock *sock = (rlm_sql_firebird_sock *) handle->conn;
+
+ fb_commit(sock);
+ fb_close_cursor(sock);
+
+ return 0;
}
-/*************************************************************************
- *
- * Function: sql_finish_query
+/** End the query
*
- * Purpose: End the query, such as freeing memory
- *
- *************************************************************************/
-static int sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
-// sql_free_result(handle,config);
- return 0;
+ */
+static int sql_finish_query(rlm_sql_handle_t *handle,
+ rlm_sql_config_t *config) {
+ sql_free_result(handle, config);
+
+ return 0;
}
-/*************************************************************************
- *
- * Function: sql_free_result
- *
- * Purpose: database specific free_result. Frees memory allocated
- * for a result set
+/** Frees memory allocated for a result set.
*
- *************************************************************************/
-static int sql_free_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- return 0;
+ */
+static int sql_free_result(UNUSED rlm_sql_handle_t *handle,
+ UNUSED rlm_sql_config_t *config) {
+ return 0;
}
-/*************************************************************************
- *
- * Function: sql_close
+/** Closes an open database connection and cleans up any open handles.
*
- * Purpose: database specific close. Closes an open database
- * connection and cleans up any open handles.
- *
- *************************************************************************/
+ */
static int sql_close(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- fb_destroy_socket((rlm_sql_firebird_sock *) handle->conn);
- return 0;
+ fb_destroy_socket((rlm_sql_firebird_sock *) handle->conn);
+ return 0;
}
-/*************************************************************************
+/** Returns error associated with connection.
*
- * Function: sql_error
- *
- * Purpose: database specific error. Returns error associated with
- * connection
- *
- *************************************************************************/
-static const char *sql_error(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- rlm_sql_firebird_sock *firebird_sock = handle->conn;
- return firebird_sock->lasterror;
+ */
+static const char *sql_error(rlm_sql_handle_t *handle,
+ UNUSED rlm_sql_config_t *config) {
+ rlm_sql_firebird_sock *firebird_sock = handle->conn;
+
+ return firebird_sock->lasterror;
}
-/*************************************************************************
- *
- * Function: sql_affected_rows
- *
- * Purpose: Return the number of rows affected by the query (update,
- * or insert)
+
+/** Return the number of rows affected by the query (update, or insert)
*
- *************************************************************************/
+ */
static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
- int affected_rows=fb_affected_rows(handle->conn);
- if (affected_rows<0)
- radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n", sql_error(handle,config));
- return affected_rows;
+ int affected_rows=fb_affected_rows(handle->conn);
+
+ if (affected_rows < 0) {
+ radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n",
+ sql_error(handle,config));
+ }
+
+ return affected_rows;
}
/* Exported to rlm_sql */
#include <stdarg.h>
int fb_lasterror(rlm_sql_firebird_sock *sock) {
- char msg[512+2];
- int l;
- ISC_LONG *pstatus;
- char *p=0;
-
- sock->sql_code=0;
-
- if (IS_ISC_ERROR(sock->status)) {
-//if error occured, free the previous error's text and create a new one
- pstatus=sock->status;
- if (sock->lasterror) free(sock->lasterror);
- sock->lasterror=0;
- sock->sql_code=isc_sqlcode(sock->status);
- isc_interprete(msg,&pstatus);
- p=strdup(msg);
- msg[0]='.';msg[1]=' ';
- while (isc_interprete(msg+2,&pstatus)) {
- l=strlen(p);
- p=(char *) realloc(p,l+strlen(msg)+2);
- strcat(p,msg);
- }
- sock->lasterror=p;
- } else {
-//return empty (but not null) string if there are no error
- if (sock->lasterror) *sock->lasterror=0;
- else sock->lasterror=strdup("");
- }
- return sock->sql_code;
+ char msg[512+2];
+ int l;
+ ISC_LONG *pstatus;
+ char *p = 0;
+
+ sock->sql_code = 0;
+
+ if (IS_ISC_ERROR(sock->status)) {
+ /*
+ * If error occured, free the previous error's text
+ * and create a new one.
+ */
+ pstatus = sock->status;
+ if (sock->lasterror) {
+ free(sock->lasterror);
+ }
+
+ sock->lasterror = 0;
+ sock->sql_code = isc_sqlcode(sock->status);
+
+ isc_interprete(msg,&pstatus);
+ p = strdup(msg);
+
+ msg[0] = '.';
+ msg[1] = ' ';
+
+ while (isc_interprete(msg + 2, &pstatus)) {
+ l = strlen(p);
+ p = realloc(p, l + strlen(msg) + 2);
+
+ strcat(p, msg);
+ }
+
+ sock->lasterror=p;
+ } else {
+ //return empty (but not null) string if there are no error
+ if (sock->lasterror) {
+ *(sock->lasterror) = '\0';
+ } else {
+ sock->lasterror = strdup("");
+ }
+ }
+
+ return sock->sql_code;
}
-void fb_set_tpb(rlm_sql_firebird_sock * sock, int count,...) {
- int i;
- va_list arg;
- va_start(arg,count);
- sock->tpb=(char *) malloc(count);
- for (i=0; i<count; i++) {
- sock->tpb[i]=(char ) va_arg(arg,int);
- }
- sock->tpb_len=count;
+void fb_set_tpb(rlm_sql_firebird_sock * sock, int count, ...) {
+ int i;
+ va_list arg;
+
+ va_start(arg, count);
+ sock->tpb = malloc(count);
+
+ for (i = 0; i < count; i++) {
+ sock->tpb[i] = (char) va_arg(arg, int);
+ }
+
+ sock->tpb_len=count;
}
void fb_dpb_add_str(char **dpb, char name, char *value) {
- int l;
- if (!value) return;
- l=strlen(value);
-
- *(*dpb)++ = name;
- *(*dpb)++ = (char ) l;
- memmove(*dpb,value,l);
- *dpb+=l;
-
+ int l;
+
+ if (!value) {
+ return;
+ }
+
+ l = strlen(value);
+
+ *(*dpb)++ = name;
+ *(*dpb)++ = (char) l;
+
+ memmove(*dpb, value, l);
+
+ *dpb += l;
}
void fb_free_sqlda(XSQLDA *sqlda) {
- int i;
- for (i=0; i<sqlda->sqld; i++) {
- free(sqlda->sqlvar[i].sqldata);
- free(sqlda->sqlvar[i].sqlind);
- }
- sqlda->sqld=0;
+ int i;
+ for (i = 0; i < sqlda->sqld; i++) {
+ free(sqlda->sqlvar[i].sqldata);
+ free(sqlda->sqlvar[i].sqlind);
+ }
+ sqlda->sqld = 0;
}
void fb_set_sqlda(XSQLDA *sqlda) {
- int i;
- for (i=0; i<sqlda->sqld; i++) {
- if ((sqlda->sqlvar[i].sqltype & ~1)==SQL_VARYING)
- sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen + sizeof(short));
- else
- sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen);
-
- if (sqlda->sqlvar[i].sqltype & 1) sqlda->sqlvar[i].sqlind = (short*)calloc(sizeof(short),1);
- else sqlda->sqlvar[i].sqlind = 0;
- }
+ int i;
+
+ for (i = 0; i < sqlda->sqld; i++) {
+ if ((sqlda->sqlvar[i].sqltype & ~1) == SQL_VARYING) {
+ sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen + sizeof(short));
+ } else {
+ sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen);
+ }
+
+ if (sqlda->sqlvar[i].sqltype & 1) {
+ sqlda->sqlvar[i].sqlind = (short*)calloc(sizeof(short),1);
+ } else {
+ sqlda->sqlvar[i].sqlind = 0;
+ }
+ }
}
//Structure to manage a SQL_VARYING Firebird's data types
typedef struct vary_fb {
- short vary_length;
- char vary_string[1];
+ short vary_length;
+ char vary_string[1];
} VARY;
//function fb_store_row based on fiebird's apifull example
void fb_store_row(rlm_sql_firebird_sock *sock) {
- int dtype;
- struct tm times;
- ISC_QUAD bid;
- int i;
- XSQLVAR *var;
- VARY * vary;
-
-//assumed: id,username,attribute,value,op
- if (sock->row_fcount<sock->sqlda_out->sqld) {
- i=sock->row_fcount;
- sock->row_fcount=sock->sqlda_out->sqld;
- sock->row=(char **) realloc(sock->row,sock->row_fcount*sizeof(char *));
- sock->row_sizes=(int *) realloc(sock->row_sizes,sock->row_fcount*sizeof(int));
- while(i<sock->row_fcount) {
- sock->row[i]=0;
- sock->row_sizes[i++]=0;
- }
- }
-
-for (i=0, var=sock->sqlda_out->sqlvar; i<sock->sqlda_out->sqld; var++,i++) {
-//Initial buffer size to store field's data is 256 bytes
- if (sock->row_sizes[i]<256) {
- sock->row[i]=(char *) realloc(sock->row[i],256);
- sock->row_sizes[i]=256;
- }
-
- if (IS_NULL(var)) {
- strcpy(sock->row[i],"NULL");
- continue;
- }
- dtype=var->sqltype & ~1;
- switch (dtype) {
- case SQL_TEXT:
- if (sock->row_sizes[i]<=var->sqllen) {
- sock->row_sizes[i]=var->sqllen+1;
- sock->row[i]=(char *) realloc(sock->row[i],sock->row_sizes[i]);
- }
- memmove(sock->row[i],var->sqldata,var->sqllen);
- sock->row[i][var->sqllen]=0;
- break;
- case SQL_VARYING:
- vary = (VARY*) var->sqldata;
- if (sock->row_sizes[i]<=vary->vary_length) {
- sock->row_sizes[i]=vary->vary_length+1;
- sock->row[i]=(char *) realloc(sock->row[i],sock->row_sizes[i]);
- }
- memmove(sock->row[i],vary->vary_string,vary->vary_length);
- sock->row[i][vary->vary_length] =0;
- break;
-
- case SQL_FLOAT:
- snprintf(sock->row[i],sock->row_sizes[i], "%15g", *(float ISC_FAR *) (var->sqldata));
- break;
- case SQL_SHORT:
- case SQL_LONG:
- case SQL_INT64:
- {
- ISC_INT64 value = 0;
- short field_width = 0;
- short dscale = 0;
- char *p;
- p=sock->row[i];
- switch (dtype)
- {
- case SQL_SHORT:
- value = (ISC_INT64) *(short *) var->sqldata;
- field_width = 6;
+ int dtype;
+ struct tm times;
+ ISC_QUAD bid;
+ int i;
+ XSQLVAR *var;
+ VARY * vary;
+
+ /* assumed: id,username,attribute,value,op */
+ if (sock->row_fcount<sock->sqlda_out->sqld) {
+ i=sock->row_fcount;
+ sock->row_fcount=sock->sqlda_out->sqld;
+ sock->row = (char **) realloc(sock->row, sock->row_fcount * sizeof(char *));
+ sock->row_sizes = (int *) realloc(sock->row_sizes, sock->row_fcount * sizeof(int));
+
+ while( i <sock->row_fcount) {
+ sock->row[i] = 0;
+ sock->row_sizes[i++] = 0;
+ }
+ }
+
+ for (i=0, var=sock->sqlda_out->sqlvar; i<sock->sqlda_out->sqld; var++,i++) {
+ /*
+ * Initial buffer size to store field's data is 256 bytes
+ */
+ if (sock->row_sizes[i]<256) {
+ sock->row[i]=(char *) realloc(sock->row[i],256);
+ sock->row_sizes[i]=256;
+ }
+
+ if (IS_NULL(var)) {
+ strcpy(sock->row[i],"NULL");
+ continue;
+ }
+
+ dtype = var->sqltype & ~1;
+
+ switch (dtype) {
+ case SQL_TEXT:
+ if (sock->row_sizes[i]<=var->sqllen) {
+ sock->row_sizes[i] = var->sqllen + 1;
+ sock->row[i] = realloc(sock->row[i],
+ sock->row_sizes[i]);
+ }
+
+ memmove(sock->row[i], var->sqldata, var->sqllen);
+ sock->row[i][var->sqllen] = 0;
+
break;
- case SQL_LONG:
- value = (ISC_INT64) *(int *) var->sqldata;
- field_width = 11;
+ case SQL_VARYING:
+ vary = (VARY*) var->sqldata;
+ if (sock->row_sizes[i] <= vary->vary_length) {
+ sock->row_sizes[i] = vary->vary_length+1;
+ sock->row[i] = realloc(sock->row[i],
+ sock->row_sizes[i]);
+ }
+ memmove(sock->row[i],vary->vary_string,vary->vary_length);
+ sock->row[i][vary->vary_length] = 0;
+
break;
- case SQL_INT64:
- value = (ISC_INT64) *(ISC_INT64 *) var->sqldata;
- field_width = 21;
+
+ case SQL_FLOAT:
+ snprintf(sock->row[i], sock->row_sizes[i], "%15g",
+ *(float ISC_FAR *) (var->sqldata));
break;
- }
- dscale = var->sqlscale;
- if (dscale < 0)
- {
- ISC_INT64 tens;
- short j;
-
- tens = 1;
- for (j = 0; j > dscale; j--) tens *= 10;
-
- if (value >= 0)
- sprintf (p, "%*lld.%0*lld",
- field_width - 1 + dscale,
- (ISC_INT64) value / tens,
- -dscale,
- (ISC_INT64) value % tens);
- else if ((value / tens) != 0)
- sprintf (p, "%*lld.%0*lld",
- field_width - 1 + dscale,
- (ISC_INT64) (value / tens),
- -dscale,
- (ISC_INT64) -(value % tens));
- else
- sprintf (p, "%*s.%0*lld",
- field_width - 1 + dscale,
- "-0",
- -dscale,
- (ISC_INT64) -(value % tens));
- }
- else if (dscale)
- sprintf (p, "%*lld%0*d",
- field_width,
- (ISC_INT64) value,
- dscale, 0);
- else
- sprintf (p, "%*lld",
- field_width,
- (ISC_INT64) value);
+ case SQL_SHORT:
+ case SQL_LONG:
+ case SQL_INT64:
+ {
+ ISC_INT64 value = 0;
+ short field_width = 0;
+ short dscale = 0;
+ char *p;
+ p=sock->row[i];
+
+ switch (dtype)
+ {
+ case SQL_SHORT:
+ value = (ISC_INT64) *(short *)var->sqldata;
+ field_width = 6;
+ break;
+ case SQL_LONG:
+ value = (ISC_INT64) *(int *)var->sqldata;
+ field_width = 11;
+ break;
+ case SQL_INT64:
+ value = (ISC_INT64) *(ISC_INT64 *)var->sqldata;
+ field_width = 21;
+ break;
+ }
+ dscale = var->sqlscale;
+
+ if (dscale < 0) {
+ ISC_INT64 tens;
+ short j;
+
+ tens = 1;
+ for (j = 0; j > dscale; j--) {
+ tens *= 10;
+ }
+
+ if (value >= 0) {
+ sprintf(p, "%*lld.%0*lld",
+ field_width - 1 + dscale,
+ (ISC_INT64) value / tens,
+ -dscale,
+ (ISC_INT64) value % tens);
+ } else if ((value / tens) != 0) {
+ sprintf (p, "%*lld.%0*lld",
+ field_width - 1 + dscale,
+ (ISC_INT64) (value / tens),
+ -dscale,
+ (ISC_INT64) -(value % tens));
+ } else {
+ sprintf(p, "%*s.%0*lld", field_width - 1 + dscale,
+ "-0", -dscale, (ISC_INT64) - (value % tens));
+ }
+ } else if (dscale) {
+ sprintf(p, "%*lld%0*d", field_width,
+ (ISC_INT64) value, dscale, 0);
+ } else {
+ sprintf(p, "%*lld", field_width,
+ (ISC_INT64) value);
+ }
+ }
+ break;
+
+ case SQL_D_FLOAT:
+ case SQL_DOUBLE:
+ snprintf(sock->row[i],sock->row_sizes[i], "%24f",
+ *(double ISC_FAR *) (var->sqldata));
+ break;
+
+ case SQL_TIMESTAMP:
+ isc_decode_timestamp((ISC_TIMESTAMP ISC_FAR *)var->sqldata, ×);
+ snprintf(sock->row[i],sock->row_sizes[i],"%04d-%02d-%02d %02d:%02d:%02d.%04d",
+ times.tm_year + 1900,
+ times.tm_mon+1,
+ times.tm_mday,
+ times.tm_hour,
+ times.tm_min,
+ times.tm_sec,
+ ((ISC_TIMESTAMP *)var->sqldata)->timestamp_time % 10000);
+ break;
+
+ case SQL_TYPE_DATE:
+ isc_decode_sql_date((ISC_DATE ISC_FAR *)var->sqldata, ×);
+ snprintf(sock->row[i],sock->row_sizes[i], "%04d-%02d-%02d",
+ times.tm_year + 1900,
+ times.tm_mon+1,
+ times.tm_mday);
+ break;
+
+ case SQL_TYPE_TIME:
+ isc_decode_sql_time((ISC_TIME ISC_FAR *)var->sqldata, ×);
+ snprintf(sock->row[i],sock->row_sizes[i], "%02d:%02d:%02d.%04d",
+ times.tm_hour,
+ times.tm_min,
+ times.tm_sec,
+ (*((ISC_TIME *)var->sqldata)) % 10000);
+ break;
+
+ case SQL_BLOB:
+ case SQL_ARRAY:
+ /* Print the blob id on blobs or arrays */
+ bid = *(ISC_QUAD ISC_FAR *) var->sqldata;
+ snprintf(sock->row[i],sock->row_sizes[i],"%08lx:%08lx", bid.gds_quad_high, bid.gds_quad_low);
+ break;
+
}
- break;
-
-
- case SQL_DOUBLE: case SQL_D_FLOAT:
- snprintf(sock->row[i],sock->row_sizes[i], "%24f", *(double ISC_FAR *) (var->sqldata));
- break;
-
- case SQL_TIMESTAMP:
- isc_decode_timestamp((ISC_TIMESTAMP ISC_FAR *)var->sqldata, ×);
- snprintf(sock->row[i],sock->row_sizes[i],"%04d-%02d-%02d %02d:%02d:%02d.%04d",
- times.tm_year + 1900,
- times.tm_mon+1,
- times.tm_mday,
- times.tm_hour,
- times.tm_min,
- times.tm_sec,
- ((ISC_TIMESTAMP *)var->sqldata)->timestamp_time % 10000);
- break;
-
- case SQL_TYPE_DATE:
- isc_decode_sql_date((ISC_DATE ISC_FAR *)var->sqldata, ×);
- snprintf(sock->row[i],sock->row_sizes[i], "%04d-%02d-%02d",
- times.tm_year + 1900,
- times.tm_mon+1,
- times.tm_mday);
- break;
-
- case SQL_TYPE_TIME:
- isc_decode_sql_time((ISC_TIME ISC_FAR *)var->sqldata, ×);
- snprintf(sock->row[i],sock->row_sizes[i], "%02d:%02d:%02d.%04d",
- times.tm_hour,
- times.tm_min,
- times.tm_sec,
- (*((ISC_TIME *)var->sqldata)) % 10000);
- break;
-
- case SQL_BLOB:
- case SQL_ARRAY:
- /* Print the blob id on blobs or arrays */
- bid = *(ISC_QUAD ISC_FAR *) var->sqldata;
- snprintf(sock->row[i],sock->row_sizes[i],"%08lx:%08lx", bid.gds_quad_high, bid.gds_quad_low);
- break;
-
- } //END SWITCH
-} //END FOR
+ }
}
-
-//=================
int fb_init_socket(rlm_sql_firebird_sock *sock) {
- memset(sock, 0, sizeof(*sock));
- sock->sqlda_out = (XSQLDA ISC_FAR *) calloc(XSQLDA_LENGTH (5),1);
- sock->sqlda_out->sqln = 5;
- sock->sqlda_out->version = SQLDA_VERSION1;
- sock->sql_dialect=3;
+ memset(sock, 0, sizeof(*sock));
+ sock->sqlda_out = (XSQLDA ISC_FAR *) calloc(XSQLDA_LENGTH (5),1);
+ sock->sqlda_out->sqln = 5;
+ sock->sqlda_out->version = SQLDA_VERSION1;
+ sock->sql_dialect = 3;
#ifdef _PTHREAD_H
- pthread_mutex_init (&sock->mut, NULL);
- radlog(L_DBG,"Init mutex %p\n",&sock->mut);
+ pthread_mutex_init (&sock->mut, NULL);
+ radlog(L_DBG,"Init mutex %p\n",&sock->mut);
#endif
-
-//set tpb to read_committed/wait/no_rec_version
- fb_set_tpb(sock,5,
- isc_tpb_version3,
- isc_tpb_wait,
- isc_tpb_write,
- isc_tpb_read_committed,
- isc_tpb_no_rec_version);
- if (!sock->tpb) return -1;
- return 0;
+ /*
+ * Set tpb to read_committed/wait/no_rec_version
+ */
+ fb_set_tpb(sock, 5, isc_tpb_version3, isc_tpb_wait, isc_tpb_write,
+ isc_tpb_read_committed, isc_tpb_no_rec_version);
+ if (!sock->tpb) {
+ return -1;
+ }
+
+ return 0;
}
int fb_connect(rlm_sql_firebird_sock * sock,rlm_sql_config_t *config) {
- char *p;
- char * database;
-
- sock->dpb_len=4;
- if (config->sql_login) sock->dpb_len+=strlen(config->sql_login)+2;
- if (config->sql_password) sock->dpb_len+=strlen(config->sql_password)+2;
-
- sock->dpb=(char *) malloc(sock->dpb_len);
- p=sock->dpb;
-
- *sock->dpb++ = isc_dpb_version1;
- *sock->dpb++ = isc_dpb_num_buffers;
- *sock->dpb++ = 1;
- *sock->dpb++ = 90;
-
- fb_dpb_add_str(&sock->dpb,isc_dpb_user_name,config->sql_login);
- fb_dpb_add_str(&sock->dpb,isc_dpb_password,config->sql_password);
-
- sock->dpb=p;
-// Check if database and server in the form of server:database.
-// If config->sql_server contains ':', then config->sql_db
-// parameter ignored
- if (strchr(config->sql_server,':')) database=strdup(config->sql_server);
- else {
-// Make database and server to be in the form of server:database
- int ls=strlen(config->sql_server);
- int ld=strlen(config->sql_db);
- database=(char *) calloc(ls+ld+2,1);
- strcpy(database,config->sql_server);
- database[ls]=':';
- memmove(database+ls+1,config->sql_db,ld);
- }
- isc_attach_database(sock->status, 0, database, &sock->dbh, sock->dpb_len, sock->dpb);
- free(database);
- return fb_lasterror(sock);
+ char *p;
+ char *database;
+
+ sock->dpb_len = 4;
+ if (config->sql_login) {
+ sock->dpb_len+=strlen(config->sql_login) + 2;
+ }
+
+ if (config->sql_password) {
+ sock->dpb_len += strlen(config->sql_password) + 2;
+ }
+
+ sock->dpb = (char *) malloc(sock->dpb_len);
+ p = sock->dpb;
+
+ *sock->dpb++ = isc_dpb_version1;
+ *sock->dpb++ = isc_dpb_num_buffers;
+ *sock->dpb++ = 1;
+ *sock->dpb++ = 90;
+
+ fb_dpb_add_str(&sock->dpb, isc_dpb_user_name, config->sql_login);
+ fb_dpb_add_str(&sock->dpb, isc_dpb_password, config->sql_password);
+
+ sock->dpb = p;
+
+ /*
+ * Check if database and server in the form of server:database.
+ * If config->sql_server contains ':', then config->sql_db
+ * parameter ignored.
+ */
+ if (strchr(config->sql_server,':')) {
+ database=strdup(config->sql_server);
+ } else {
+ /*
+ * Make database and server to be in the form
+ * of server:database
+ */
+ int ls = strlen(config->sql_server);
+ int ld = strlen(config->sql_db);
+ database=(char *) calloc(ls+ld+2,1);
+ strcpy(database,config->sql_server);
+ database[ls]=':';
+ memmove(database+ls+1,config->sql_db,ld);
+ }
+ isc_attach_database(sock->status, 0, database, &sock->dbh,
+ sock->dpb_len, sock->dpb);
+ free(database);
+
+ return fb_lasterror(sock);
}
int fb_fetch(rlm_sql_firebird_sock *sock) {
- long fetch_stat;
- if (sock->statement_type!=isc_info_sql_stmt_select) return 100;
- fetch_stat=isc_dsql_fetch(sock->status, &sock->stmt, SQL_DIALECT_V6, sock->sqlda_out);
- if (fetch_stat) {
- if (fetch_stat!=100L) fb_lasterror(sock);
- else sock->sql_code=0;
- }
- return fetch_stat;
+ long fetch_stat;
+ if (sock->statement_type!=isc_info_sql_stmt_select) {
+ return 100;
+ }
+
+ fetch_stat = isc_dsql_fetch(sock->status, &sock->stmt,
+ SQL_DIALECT_V6, sock->sqlda_out);
+ if (fetch_stat) {
+ if (fetch_stat!=100L) {
+ fb_lasterror(sock);
+ } else {
+ sock->sql_code=0;
+ }
+ }
+
+ return fetch_stat;
}
int fb_prepare(rlm_sql_firebird_sock *sock,char *sqlstr) {
- static char stmt_info[] = { isc_info_sql_stmt_type };
- char info_buffer[128];
- short l;
-
- if (!sock->trh) {
- isc_start_transaction(sock->status,&sock->trh,1,&sock->dbh,sock->tpb_len,sock->tpb);
- if (!sock->trh) return -4;
- }
-
- fb_free_statement(sock);
- if (!sock->stmt) {
- isc_dsql_allocate_statement(sock->status, &sock->dbh, &sock->stmt);
- if (!sock->stmt) return -1;
- }
-
- fb_free_sqlda(sock->sqlda_out);
- isc_dsql_prepare(sock->status, &sock->trh, &sock->stmt, 0, sqlstr, sock->sql_dialect, sock->sqlda_out);
- if (IS_ISC_ERROR(sock->status)) return -2;
-
- if (sock->sqlda_out->sqln<sock->sqlda_out->sqld) {
- sock->sqlda_out->sqln=sock->sqlda_out->sqld;
- sock->sqlda_out = (XSQLDA ISC_FAR *) realloc(sock->sqlda_out, XSQLDA_LENGTH (sock->sqlda_out->sqld));
- isc_dsql_describe(sock->status,&sock->stmt,SQL_DIALECT_V6,sock->sqlda_out);
- if (IS_ISC_ERROR(sock->status)) return -3;
- }
-
-//get statement type
- isc_dsql_sql_info(sock->status, &sock->stmt, sizeof (stmt_info), stmt_info,sizeof (info_buffer), info_buffer);
- if (IS_ISC_ERROR(sock->status)) return -4;
-
- l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2);
- sock->statement_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l);
-
- if (sock->sqlda_out->sqld) fb_set_sqlda(sock->sqlda_out); //set out sqlda
-
- return 0;
+ static char stmt_info[] = { isc_info_sql_stmt_type };
+ char info_buffer[128];
+ short l;
+
+ if (!sock->trh) {
+ isc_start_transaction(sock->status, &sock->trh, 1, &sock->dbh,
+ sock->tpb_len,sock->tpb);
+ if (!sock->trh) {
+ return -4;
+ }
+ }
+
+ fb_free_statement(sock);
+ if (!sock->stmt) {
+ isc_dsql_allocate_statement(sock->status, &sock->dbh,
+ &sock->stmt);
+ if (!sock->stmt) {
+ return -1;
+ }
+ }
+
+ fb_free_sqlda(sock->sqlda_out);
+ isc_dsql_prepare(sock->status, &sock->trh, &sock->stmt, 0, sqlstr,
+ sock->sql_dialect, sock->sqlda_out);
+ if (IS_ISC_ERROR(sock->status)) {
+ return -2;
+ }
+
+ if (sock->sqlda_out->sqln<sock->sqlda_out->sqld) {
+ sock->sqlda_out->sqln=sock->sqlda_out->sqld;
+ sock->sqlda_out = (XSQLDA ISC_FAR *) realloc(sock->sqlda_out,
+ XSQLDA_LENGTH(sock->sqlda_out->sqld));
+ isc_dsql_describe(sock->status, &sock->stmt, SQL_DIALECT_V6,
+ sock->sqlda_out);
+
+ if (IS_ISC_ERROR(sock->status)) {
+ return -3;
+ }
+ }
+ /*
+ * Get statement type
+ */
+ isc_dsql_sql_info(sock->status, &sock->stmt, sizeof(stmt_info),
+ stmt_info,sizeof(info_buffer), info_buffer);
+ if (IS_ISC_ERROR(sock->status)) return -4;
+
+ l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2);
+ sock->statement_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3,
+ l);
+
+ if (sock->sqlda_out->sqld) {
+ fb_set_sqlda(sock->sqlda_out); //set out sqlda
+ }
+
+ return 0;
}
int fb_sql_query(rlm_sql_firebird_sock *sock,char *sqlstr) {
- if (fb_prepare(sock,sqlstr)) return fb_lasterror(sock);
- switch (sock->statement_type) {
- case isc_info_sql_stmt_exec_procedure:
- isc_dsql_execute2(sock->status, &sock->trh, &sock->stmt, SQL_DIALECT_V6,0,sock->sqlda_out);
- break;
- default:
- isc_dsql_execute(sock->status, &sock->trh, &sock->stmt, SQL_DIALECT_V6,0);
- break;
- }
- return fb_lasterror(sock);
+ if (fb_prepare(sock,sqlstr)) {
+ return fb_lasterror(sock);
+ }
+
+ switch (sock->statement_type) {
+ case isc_info_sql_stmt_exec_procedure:
+ isc_dsql_execute2(sock->status, &sock->trh, &sock->stmt,
+ SQL_DIALECT_V6, 0, sock->sqlda_out);
+ break;
+ default:
+ isc_dsql_execute(sock->status, &sock->trh, &sock->stmt,
+ SQL_DIALECT_V6, 0);
+ break;
+ }
+ return fb_lasterror(sock);
}
int fb_affected_rows(rlm_sql_firebird_sock *sock) {
- static char count_info[] = {isc_info_sql_records};
- char info_buffer[128];
- char *p ;
- int affected_rows=-1;
-
- if (!sock->stmt) return -1;
-
- isc_dsql_sql_info(sock->status, &sock->stmt,
- sizeof (count_info), count_info,sizeof (info_buffer), info_buffer);
- if (IS_ISC_ERROR(sock->status)) return fb_lasterror(sock);
-
- p=info_buffer+3;
- while (*p != isc_info_end) {
- p++;
- short len = (short)isc_vax_integer(p,2);
- p+=2;
- affected_rows = isc_vax_integer(p,len);
- if (affected_rows>0) break;
- p += len;
- }
- return affected_rows;
+ static char count_info[] = {isc_info_sql_records};
+ char info_buffer[128];
+ char *p ;
+ int affected_rows = -1;
+
+ if (!sock->stmt) return -1;
+
+ isc_dsql_sql_info(sock->status, &sock->stmt,
+ sizeof (count_info), count_info,
+ sizeof (info_buffer), info_buffer);
+
+ if (IS_ISC_ERROR(sock->status)) {
+ return fb_lasterror(sock);
+ }
+
+ p = info_buffer + 3;
+ while (*p != isc_info_end) {
+ p++;
+ short len = (short)isc_vax_integer(p, 2);
+ p += 2;
+
+ affected_rows = isc_vax_integer(p, len);
+ if (affected_rows > 0) {
+ break;
+ }
+ p += len;
+ }
+ return affected_rows;
}
int fb_close_cursor(rlm_sql_firebird_sock *sock) {
- isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_close);
- return fb_lasterror(sock);
+ isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_close);
+
+ return fb_lasterror(sock);
}
void fb_free_statement(rlm_sql_firebird_sock *sock) {
- if (sock->stmt) {
- isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_drop);
- sock->stmt=0;
- }
+ if (sock->stmt) {
+ isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_drop);
+ sock->stmt = 0;
+ }
}
int fb_rollback(rlm_sql_firebird_sock *sock) {
- sock->sql_code=0;
- if (sock->trh) {
- isc_rollback_transaction (sock->status,&sock->trh);
-// sock->in_use=0;
+ sock->sql_code = 0;
+ if (sock->trh) {
+ isc_rollback_transaction(sock->status, &sock->trh);
+// sock->in_use=0;
#ifdef _PTHREAD_H
- pthread_mutex_unlock(&sock->mut);
+ pthread_mutex_unlock(&sock->mut);
#endif
- if (IS_ISC_ERROR(sock->status)) {
- return fb_lasterror(sock);
- }
- }
- return sock->sql_code;
+ if (IS_ISC_ERROR(sock->status)) {
+ return fb_lasterror(sock);
+ }
+ }
+ return sock->sql_code;
}
int fb_commit(rlm_sql_firebird_sock *sock) {
- sock->sql_code=0;
- if (sock->trh) {
- isc_commit_transaction (sock->status,&sock->trh);
- if (IS_ISC_ERROR(sock->status)) {
- fb_lasterror(sock);
- radlog(L_ERR,"Fail to commit. Error: %s. Try to rollback.\n",sock->lasterror);
- return fb_rollback(sock);
- }
- }
-// sock->in_use=0;
+ sock->sql_code=0;
+ if (sock->trh) {
+ isc_commit_transaction (sock->status,&sock->trh);
+ if (IS_ISC_ERROR(sock->status)) {
+ fb_lasterror(sock);
+ radlog(L_ERR, "Fail to commit. Error: %s. Try to rollback.",
+ sock->lasterror);
+ return fb_rollback(sock);
+ }
+ }
+// sock->in_use=0;
#ifdef _PTHREAD_H
- pthread_mutex_unlock(&sock->mut);
+ pthread_mutex_unlock(&sock->mut);
#endif
- return sock->sql_code;
+ return sock->sql_code;
}
int fb_disconnect(rlm_sql_firebird_sock *sock) {
- if (sock->dbh) {
- fb_free_statement(sock);
- isc_detach_database(sock->status,&sock->dbh);
- return fb_lasterror(sock);
- }
- return 0;
+ if (sock->dbh) {
+ fb_free_statement(sock);
+ isc_detach_database(sock->status,&sock->dbh);
+ return fb_lasterror(sock);
+ }
+ return 0;
}
void fb_destroy_socket(rlm_sql_firebird_sock *sock) {
- int i;
- fb_commit(sock);
- if (fb_disconnect(sock)) {
- radlog(L_ERR,"Fatal. Fail to disconnect DB. Error :%s\n",sock->lasterror);
- }
+ int i;
+ fb_commit(sock);
+
+ if (fb_disconnect(sock)) {
+ radlog(L_ERR, "Fatal. Fail to disconnect DB. Error :%s\n",
+ sock->lasterror);
+ }
+
#ifdef _PTHREAD_H
- pthread_mutex_destroy (&sock->mut);
+ pthread_mutex_destroy (&sock->mut);
#endif
- for (i=0; i<sock->row_fcount;i++) free(sock->row[i]);
- free(sock->row);free(sock->row_sizes);
- fb_free_sqlda(sock->sqlda_out);
- free(sock->sqlda_out);
- free(sock->tpb);
- free(sock->dpb);
- if (sock->lasterror) free(sock->lasterror);
- memset(sock,0,sizeof(rlm_sql_firebird_sock));
+ for (i=0; i<sock->row_fcount;i++) {
+ free(sock->row[i]);
+ }
+
+ free(sock->row);free(sock->row_sizes);
+ fb_free_sqlda(sock->sqlda_out);
+
+ free(sock->sqlda_out);
+ free(sock->tpb);
+ free(sock->dpb);
+
+ if (sock->lasterror) {
+ free(sock->lasterror);
+ }
+
+ memset(sock,0,sizeof(rlm_sql_firebird_sock));
}