import from HEAD
[freeradius.git] / src / modules / rlm_sql / drivers / rlm_sql_firebird / sql_firebird.c
1 /*
2  * sql_firebird.c  Part of Firebird rlm_sql driver
3  *
4  * Copyright 2006  Vitaly Bodzhgua <vitaly@easteara.net>
5  */
6
7
8 #include "sql_fbapi.h"
9
10 /* Forward declarations */
11 static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config);
12 static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config);
13 static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config);
14 static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config);
15 static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config);
16
17 /*************************************************************************
18  *
19  *      Function: sql_init_socket
20  *
21  *      Purpose: Establish connection to the db
22  *
23  *************************************************************************/
24 static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
25     rlm_sql_firebird_sock *firebird_sock;
26     long res;
27
28
29     if (!sqlsocket->conn) {
30         sqlsocket->conn = (rlm_sql_firebird_sock *)rad_malloc(sizeof(rlm_sql_firebird_sock));
31         if (!sqlsocket->conn) return -1;
32     }
33
34     firebird_sock = sqlsocket->conn;
35
36     res=fb_init_socket(firebird_sock);
37     if (res)  return -1;
38     
39     if (fb_connect(firebird_sock,config)) {
40      radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n", firebird_sock->lasterror);
41      return -1;
42     }
43     
44     return 0;
45 }
46
47
48 /*************************************************************************
49  *
50  *      Function: sql_destroy_socket
51  *
52  *      Purpose: Free socket and private connection data
53  *
54  *************************************************************************/
55 static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
56 {
57     free(sqlsocket->conn);
58     sqlsocket->conn = NULL;
59     return 0;
60 }
61
62
63 /*************************************************************************
64  *
65  *      Function: sql_query
66  *
67  *      Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
68  *               the database.
69  *
70  *************************************************************************/
71  
72 static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
73     rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
74  int deadlock_trys=1;     
75  if (config->sqltrace)
76         radlog(L_DBG, "query:  %s", querystr);
77
78 TryAgainIfDeadlock:    
79     /* Executing query */
80  if (fb_sql_query(firebird_sock,querystr)) {
81    if (firebird_sock->sql_code==DEADLOCK_SQL_CODE) {
82     deadlock_trys++;
83     if (deadlock_trys<=DEADLOCK_TRYS) {
84      radlog(L_INFO, "rlm_sql_firebird,sql_query: deadlock, try again query '%s'\n",querystr);
85      goto TryAgainIfDeadlock;
86     }
87    }
88    radlog(L_ERR, "rlm_sql_firebird,sql_query error:sql_code=%i, error='%s'\n", 
89      firebird_sock->sql_code,
90      firebird_sock->lasterror);
91    radlog(L_ERR, "rlm_sql_firebird, Problem with query: '%s'\n", querystr);
92    return -1;
93  }
94  return 0;
95 }
96
97
98 /*************************************************************************
99  *
100  *      Function: sql_select_query
101  *
102  *      Purpose: Issue a select query to the database
103  *
104  *************************************************************************/
105 static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
106     rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
107     if (sql_query(sqlsocket, config, querystr)) return -1;
108     return 0;
109     
110 }
111
112
113 /*************************************************************************
114  *
115  *      Function: sql_store_result
116  *
117  *      Purpose: database specific store_result function. Returns a result
118  *               set for the query.
119  *
120  *************************************************************************/
121 static int sql_store_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
122   /*   Not used   */
123     return 0;
124 }
125
126
127 /*************************************************************************
128  *
129  *      Function: sql_num_fields
130  *
131  *      Purpose: database specific num_fields function. Returns number
132  *               of columns from query
133  *
134  *************************************************************************/
135 static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
136     return  ((rlm_sql_firebird_sock *) sqlsocket->conn)->sqlda_out->sqld;
137 }
138
139
140 /*************************************************************************
141  *
142  *      Function: sql_num_rows
143  *
144  *      Purpose: database specific num_rows. Returns number of rows in
145  *               query
146  *
147  *************************************************************************/
148 static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
149     return -1;
150 }
151
152
153 /*************************************************************************
154  *
155  *      Function: sql_fetch_row
156  *
157  *      Purpose: database specific fetch_row. Returns a SQL_ROW struct
158  *               with all the data for the query in 'sqlsocket->row'. Returns
159  *               0 on success, -1 on failure, SQL_DOWN if 'database is down'.
160  *
161  *************************************************************************/
162 static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
163     rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
164     int res;
165
166     sqlsocket->row = NULL;
167     if (firebird_sock->statement_type!=isc_info_sql_stmt_exec_procedure) {
168      res=fb_fetch(firebird_sock);
169      if (res==100) return 0;
170      if (res) {
171        radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'\n", firebird_sock->lasterror);
172        return -1;
173      }  
174     } else firebird_sock->statement_type=0;
175     fb_store_row(firebird_sock);
176
177     sqlsocket->row = firebird_sock->row;
178     return 0;
179 }
180
181
182 /*************************************************************************
183  *
184  *      Function: sql_finish_select_query
185  *
186  *      Purpose: End the select query, such as freeing memory or result
187  *
188  *************************************************************************/
189 static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
190     sql_finish_query(sqlsocket,config);    
191     return 0;
192 }
193
194 /*************************************************************************
195  *
196  *      Function: sql_finish_query
197  *
198  *      Purpose: End the query, such as freeing memory
199  *
200  *************************************************************************/
201 static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
202     sql_free_result(sqlsocket,config);
203     return 0;
204 }
205
206 /*************************************************************************
207  *
208  *      Function: sql_free_result
209  *
210  *      Purpose: database specific free_result. Frees memory allocated
211  *               for a result set
212  *
213  *************************************************************************/
214 static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
215     fb_free_result((rlm_sql_firebird_sock *) sqlsocket->conn); 
216     return 0;
217 }
218
219
220 /*************************************************************************
221  *
222  *      Function: sql_close
223  *
224  *      Purpose: database specific close. Closes an open database
225  *               connection and cleans up any open handles.
226  *
227  *************************************************************************/
228 static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
229     fb_destroy_socket((rlm_sql_firebird_sock *) sqlsocket->conn); 
230     return 0;
231 }
232
233 /*************************************************************************
234  *
235  *      Function: sql_error
236  *
237  *      Purpose: database specific error. Returns error associated with
238  *               connection
239  *
240  *************************************************************************/
241 static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
242     rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
243     return firebird_sock->lasterror;
244     
245 }
246 /*************************************************************************
247  *
248  *      Function: sql_affected_rows
249  *
250  *      Purpose: Return the number of rows affected by the query (update,
251  *               or insert)
252  *
253  *************************************************************************/
254 static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
255     return -1;
256 }
257
258
259 /* Exported to rlm_sql */
260 rlm_sql_module_t rlm_sql_firebird = {
261         "rlm_sql_firebird",
262         sql_init_socket,
263         sql_destroy_socket,
264         sql_query,
265         sql_select_query,
266         sql_store_result,
267         sql_num_fields,
268         sql_num_rows,
269         sql_fetch_row,
270         sql_free_result,
271         sql_error,
272         sql_close,
273         sql_finish_query,
274         sql_finish_select_query,
275         sql_affected_rows
276 };