2 * sql_firebird.c Part of Firebird rlm_sql driver
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Copyright 2006 The FreeRADIUS server project
19 * Copyright 2006 Vitaly Bodzhgua <vitaly@eastera.net>
23 #include "sql_fbapi.h"
26 /* Forward declarations */
27 static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config);
28 static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config);
29 static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config);
30 static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config);
31 static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config);
33 /*************************************************************************
35 * Function: sql_init_socket
37 * Purpose: Establish connection to the db
39 *************************************************************************/
40 static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
41 rlm_sql_firebird_sock *firebird_sock;
45 if (!sqlsocket->conn) {
46 sqlsocket->conn = (rlm_sql_firebird_sock *)rad_malloc(sizeof(rlm_sql_firebird_sock));
47 if (!sqlsocket->conn) return -1;
50 firebird_sock = sqlsocket->conn;
52 res=fb_init_socket(firebird_sock);
55 if (fb_connect(firebird_sock,config)) {
56 radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n", firebird_sock->lasterror);
64 /*************************************************************************
66 * Function: sql_destroy_socket
68 * Purpose: Free socket and private connection data
70 *************************************************************************/
71 static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
73 free(sqlsocket->conn);
74 sqlsocket->conn = NULL;
79 /*************************************************************************
83 * Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
86 *************************************************************************/
88 static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
89 rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
92 radlog(L_DBG, "sock_id %i: query: %s", sqlsocket->id,querystr);
95 pthread_mutex_lock(&firebird_sock->mut);
99 if (fb_sql_query(firebird_sock,querystr)) {
100 //Try again query when deadlock, beacuse in any case it will be retried.
101 // but may be lost for short sessions
102 if ((firebird_sock->sql_code==DEADLOCK_SQL_CODE) && !deadlock) {
103 radlog(L_DBG,"sock_id %i: deadlock. Retry query %s\n",sqlsocket->id,querystr);
104 //For non READ_COMMITED transactions put rollback here
105 // fb_rollback(sock);
109 radlog(L_ERR, "sock_id %i: rlm_sql_firebird,sql_query error:sql_code=%i, error='%s', query=%s\n",
111 firebird_sock->sql_code,
112 firebird_sock->lasterror,
115 if ((firebird_sock->sql_code==DOWN_SQL_CODE)) return SQL_DOWN;
117 if (fb_rollback(firebird_sock)) {
118 //assume the network is down if rollback had failed
119 radlog(L_ERR,"Fail to rollback transaction after previous error. Error: %s\n",
120 firebird_sock->lasterror);
123 // firebird_sock->in_use=0;
127 if (firebird_sock->statement_type!=isc_info_sql_stmt_select) {
128 if (fb_commit(firebird_sock)) return -1;
135 /*************************************************************************
137 * Function: sql_select_query
139 * Purpose: Issue a select query to the database
141 *************************************************************************/
142 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
143 // rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
144 return (sql_query(sqlsocket, config, querystr));
149 /*************************************************************************
151 * Function: sql_store_result
153 * Purpose: database specific store_result function. Returns a result
156 *************************************************************************/
157 static int sql_store_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
163 /*************************************************************************
165 * Function: sql_num_fields
167 * Purpose: database specific num_fields function. Returns number
168 * of columns from query
170 *************************************************************************/
171 static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
172 return ((rlm_sql_firebird_sock *) sqlsocket->conn)->sqlda_out->sqld;
176 /*************************************************************************
178 * Function: sql_num_rows
180 * Purpose: database specific num_rows. Returns number of rows in
183 *************************************************************************/
184 static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
185 int res=sql_affected_rows(sqlsocket, config);
186 radlog(L_DBG,"sock_id %i: sql_num_rows: %i\n",sqlsocket->id,res);
191 /*************************************************************************
193 * Function: sql_fetch_row
195 * Purpose: database specific fetch_row. Returns a SQL_ROW struct
196 * with all the data for the query in 'sqlsocket->row'. Returns
197 * 0 on success, -1 on failure, SQL_DOWN if 'database is down'.
199 *************************************************************************/
200 static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
201 rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
204 sqlsocket->row = NULL;
205 if (firebird_sock->statement_type!=isc_info_sql_stmt_exec_procedure) {
206 res=fb_fetch(firebird_sock);
207 if (res==100) return 0;
209 radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'\n", firebird_sock->lasterror);
212 } else firebird_sock->statement_type=0;
213 fb_store_row(firebird_sock);
215 sqlsocket->row = firebird_sock->row;
220 /*************************************************************************
222 * Function: sql_finish_select_query
224 * Purpose: End the select query, such as freeing memory or result
226 *************************************************************************/
227 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
228 rlm_sql_firebird_sock *sock=(rlm_sql_firebird_sock *) sqlsocket->conn;
230 fb_close_cursor(sock);
234 /*************************************************************************
236 * Function: sql_finish_query
238 * Purpose: End the query, such as freeing memory
240 *************************************************************************/
241 static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
242 // sql_free_result(sqlsocket,config);
246 /*************************************************************************
248 * Function: sql_free_result
250 * Purpose: database specific free_result. Frees memory allocated
253 *************************************************************************/
254 static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
258 /*************************************************************************
260 * Function: sql_close
262 * Purpose: database specific close. Closes an open database
263 * connection and cleans up any open handles.
265 *************************************************************************/
266 static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
267 // radlog(L_INFO,"Closing sql\n");
268 fb_destroy_socket((rlm_sql_firebird_sock *) sqlsocket->conn);
272 /*************************************************************************
274 * Function: sql_error
276 * Purpose: database specific error. Returns error associated with
279 *************************************************************************/
280 static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
281 rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
282 return firebird_sock->lasterror;
284 /*************************************************************************
286 * Function: sql_affected_rows
288 * Purpose: Return the number of rows affected by the query (update,
291 *************************************************************************/
292 static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
293 int affected_rows=fb_affected_rows(sqlsocket->conn);
295 radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n", sql_error(sqlsocket,config));
296 radlog(L_DBG,"sock_id %i: affected_rows: %i\n",sqlsocket->id,affected_rows);
297 return affected_rows;
300 /* Exported to rlm_sql */
301 rlm_sql_module_t rlm_sql_firebird = {
315 sql_finish_select_query,