Mark parameters unused
[freeradius.git] / src / modules / rlm_sql / drivers / rlm_sql_firebird / rlm_sql_firebird.c
1 /*
2  * sql_firebird.c Part of Firebird rlm_sql driver
3  *
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.
8  *
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.
13  *
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
17  *
18  * Copyright 2006  The FreeRADIUS server project
19  * Copyright 2006  Vitaly Bodzhgua <vitaly@eastera.net>
20  */
21
22 #include <freeradius-devel/ident.h>
23 RCSID("$Id$")
24
25 #include "sql_fbapi.h"
26
27
28 /* Forward declarations */
29 static const char *sql_error(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
30 static int sql_free_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
31 static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
32 static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
33 static int sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
34
35 /** Establish connection to the db
36  *
37  */
38 static int sql_init_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
39         rlm_sql_firebird_sock   *firebird_sock;
40         
41         long res;
42
43         if (!handle->conn) {
44                 handle->conn = rad_malloc(sizeof(rlm_sql_firebird_sock));
45                 if (!handle->conn) {
46                         return -1;
47                 }
48         }
49
50         firebird_sock = handle->conn;
51
52         res = fb_init_socket(firebird_sock);
53         if (res) {
54                 return -1;
55         }
56         
57         if (fb_connect(firebird_sock,config)) {
58                 radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n",
59                        firebird_sock->lasterror);
60                        
61                 return SQL_DOWN;
62         }
63
64         return 0;
65 }
66
67 /** Free socket and private connection data
68  *
69  */
70 static int sql_destroy_socket(rlm_sql_handle_t *handle,
71                               UNUSED rlm_sql_config_t *config)
72 {
73         free(handle->conn);
74         
75         handle->conn = NULL;
76         
77         return 0;
78 }
79
80
81 /** Issue a non-SELECT query (ie: update/delete/insert) to the database.
82  *
83  */
84 static int sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config,
85                      char *querystr) {
86         rlm_sql_firebird_sock *firebird_sock = handle->conn;
87         
88         int deadlock = 0;
89
90 #ifdef _PTHREAD_H
91         pthread_mutex_lock(&firebird_sock->mut);
92 #endif
93
94         try_again:
95         /* 
96          *      Try again query when deadlock, beacuse in any case it
97          *      will be retried.
98          */
99         if (fb_sql_query(firebird_sock,querystr)) {
100                 /* but may be lost for short sessions */
101                 if ((firebird_sock->sql_code == DEADLOCK_SQL_CODE) &&
102                     !deadlock) {
103                         radlog(L_DBG,"sock_id deadlock. Retry query %s",
104                                querystr);
105                         
106                         /*
107                          *      @todo For non READ_COMMITED transactions put 
108                          *      rollback here
109                          *      fb_rollback(sock);
110                          */
111                         deadlock = 1;
112                         goto try_again;
113                 }
114         
115                 radlog(L_ERR, "sock_id rlm_sql_firebird,sql_query error: "
116                        "sql_code=%li, error='%s', query=%s",
117                        (long int) firebird_sock->sql_code,
118                        firebird_sock->lasterror,
119                        querystr);
120
121                 if (firebird_sock->sql_code == DOWN_SQL_CODE) {
122                         return SQL_DOWN;
123                 }
124         
125                 /* Free problem query */
126                 if (fb_rollback(firebird_sock)) {
127                         //assume the network is down if rollback had failed
128                         radlog(L_ERR,"Fail to rollback transaction after "
129                                "previous error. Error: %s",
130                                firebird_sock->lasterror);
131                 
132                         return SQL_DOWN;
133                 }
134                 //   firebird_sock->in_use=0;
135                 return -1;
136         }
137
138         if (firebird_sock->statement_type != isc_info_sql_stmt_select) {
139                 if (fb_commit(firebird_sock)) {
140                         return -1;
141                 }
142         }
143
144         return 0;
145 }
146
147 /** Issue a select query to the database.
148  *
149  */
150 static int sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config,
151                             char *querystr) {
152         return sql_query(handle, config, querystr);
153 }
154
155 /** Returns a result set for the query.
156  *
157  */
158 static int sql_store_result(UNUSED rlm_sql_handle_t *handle,
159                             UNUSED rlm_sql_config_t *config) {
160         return 0;
161 }
162
163 /** Returns number of columns from query.
164  *
165  */
166 static int sql_num_fields(rlm_sql_handle_t *handle,
167                           UNUSED rlm_sql_config_t *config) {
168         return ((rlm_sql_firebird_sock *) handle->conn)->sqlda_out->sqld;
169 }
170
171 /** Returns number of rows in query.
172  *
173  */
174 static int sql_num_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
175         return sql_affected_rows(handle, config);
176 }
177
178 /** Returns an individual row.
179  *
180  */
181 static int sql_fetch_row(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
182 {
183         rlm_sql_firebird_sock *firebird_sock = handle->conn;
184         int res;
185         
186         handle->row = NULL;
187         
188         if (firebird_sock->statement_type != isc_info_sql_stmt_exec_procedure) {
189                 res = fb_fetch(firebird_sock);
190                 if (res == 100) {
191                         return 0;
192                 }
193                 
194                 if (res) {
195                         radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'",
196                                firebird_sock->lasterror);
197                                
198                         return -1;
199                 }
200         } else {
201                 firebird_sock->statement_type=0;
202         }
203         
204         fb_store_row(firebird_sock);
205
206         handle->row = firebird_sock->row;
207         
208         return 0;
209 }
210
211 /** End the select query, such as freeing memory or result.
212  *
213  */
214 static int sql_finish_select_query(rlm_sql_handle_t *handle,
215                                    UNUSED rlm_sql_config_t *config) {
216                                    
217         rlm_sql_firebird_sock *sock = (rlm_sql_firebird_sock *) handle->conn;
218         
219         fb_commit(sock);
220         fb_close_cursor(sock);
221         
222         return 0;
223 }
224
225 /** End the query
226  *
227  */
228 static int sql_finish_query(rlm_sql_handle_t *handle,
229                             rlm_sql_config_t *config) {
230         sql_free_result(handle, config);
231         
232         return 0;
233 }
234
235 /** Frees memory allocated for a result set.
236  *
237  */
238 static int sql_free_result(UNUSED rlm_sql_handle_t *handle,
239                            UNUSED rlm_sql_config_t *config) {
240         return 0;
241 }
242
243 /** Closes an open database connection and cleans up any open handles.
244  *
245  */
246 static int sql_close(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
247 {
248         fb_destroy_socket((rlm_sql_firebird_sock *) handle->conn);
249         return 0;
250 }
251
252 /** Returns error associated with connection.
253  *
254  */
255 static const char *sql_error(rlm_sql_handle_t *handle,
256                              UNUSED rlm_sql_config_t *config) {
257         rlm_sql_firebird_sock *firebird_sock = handle->conn;
258         
259         return firebird_sock->lasterror;
260 }
261
262 /** Return the number of rows affected by the query (update, or insert)
263  *
264  */
265 static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
266         int affected_rows=fb_affected_rows(handle->conn);
267         
268         if (affected_rows < 0) {
269                 radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n",
270                        sql_error(handle,config));
271         }
272         
273         return affected_rows;
274 }
275
276 /* Exported to rlm_sql */
277 rlm_sql_module_t rlm_sql_firebird = {
278         "rlm_sql_firebird",
279         sql_init_socket,
280         sql_destroy_socket,
281         sql_query,
282         sql_select_query,
283         sql_store_result,
284         sql_num_fields,
285         sql_num_rows,
286         sql_fetch_row,
287         sql_free_result,
288         sql_error,
289         sql_close,
290         sql_finish_query,
291         sql_finish_select_query,
292         sql_affected_rows
293 };