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>
22 #include <freeradius-devel/ident.h>
25 #include "sql_fbapi.h"
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);
35 /*************************************************************************
37 * Function: sql_init_socket
39 * Purpose: Establish connection to the db
41 *************************************************************************/
42 static int sql_init_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
43 rlm_sql_firebird_sock *firebird_sock;
48 handle->conn = (rlm_sql_firebird_sock *)rad_malloc(sizeof(rlm_sql_firebird_sock));
49 if (!handle->conn) return -1;
52 firebird_sock = handle->conn;
54 res=fb_init_socket(firebird_sock);
57 if (fb_connect(firebird_sock,config)) {
58 radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n", firebird_sock->lasterror);
66 /*************************************************************************
68 * Function: sql_destroy_socket
70 * Purpose: Free socket and private connection data
72 *************************************************************************/
73 static int sql_destroy_socket(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
81 /*************************************************************************
85 * Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
88 *************************************************************************/
90 static int sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr) {
91 rlm_sql_firebird_sock *firebird_sock = handle->conn;
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 deadlock. Retry query %s\n",querystr);
104 //For non READ_COMMITED transactions put rollback here
105 // fb_rollback(sock);
109 radlog(L_ERR, "sock_id rlm_sql_firebird,sql_query error:sql_code=%li, error='%s', query=%s\n",
110 firebird_sock->sql_code,
111 firebird_sock->lasterror,
114 if ((firebird_sock->sql_code==DOWN_SQL_CODE)) return SQL_DOWN;
116 if (fb_rollback(firebird_sock)) {
117 //assume the network is down if rollback had failed
118 radlog(L_ERR,"Fail to rollback transaction after previous error. Error: %s\n",
119 firebird_sock->lasterror);
122 // firebird_sock->in_use=0;
126 if (firebird_sock->statement_type!=isc_info_sql_stmt_select) {
127 if (fb_commit(firebird_sock)) return -1;
134 /*************************************************************************
136 * Function: sql_select_query
138 * Purpose: Issue a select query to the database
140 *************************************************************************/
141 static int sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char *querystr) {
142 // rlm_sql_firebird_sock *firebird_sock = handle->conn;
143 return (sql_query(handle, config, querystr));
148 /*************************************************************************
150 * Function: sql_store_result
152 * Purpose: database specific store_result function. Returns a result
155 *************************************************************************/
156 static int sql_store_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
162 /*************************************************************************
164 * Function: sql_num_fields
166 * Purpose: database specific num_fields function. Returns number
167 * of columns from query
169 *************************************************************************/
170 static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
171 return ((rlm_sql_firebird_sock *) handle->conn)->sqlda_out->sqld;
175 /*************************************************************************
177 * Function: sql_num_rows
179 * Purpose: database specific num_rows. Returns number of rows in
182 *************************************************************************/
183 static int sql_num_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
184 int res=sql_affected_rows(handle, config);
189 /*************************************************************************
191 * Function: sql_fetch_row
193 * Purpose: database specific fetch_row. Returns a rlm_sql_row_t struct
194 * with all the data for the query in 'handle->row'. Returns
195 * 0 on success, -1 on failure, SQL_DOWN if 'database is down'.
197 *************************************************************************/
198 static int sql_fetch_row(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
199 rlm_sql_firebird_sock *firebird_sock = handle->conn;
203 if (firebird_sock->statement_type!=isc_info_sql_stmt_exec_procedure) {
204 res=fb_fetch(firebird_sock);
205 if (res==100) return 0;
207 radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'\n", firebird_sock->lasterror);
210 } else firebird_sock->statement_type=0;
211 fb_store_row(firebird_sock);
213 handle->row = firebird_sock->row;
218 /*************************************************************************
220 * Function: sql_finish_select_query
222 * Purpose: End the select query, such as freeing memory or result
224 *************************************************************************/
225 static int sql_finish_select_query(rlm_sql_handle_t * handle, rlm_sql_config_t *config) {
226 rlm_sql_firebird_sock *sock=(rlm_sql_firebird_sock *) handle->conn;
228 fb_close_cursor(sock);
232 /*************************************************************************
234 * Function: sql_finish_query
236 * Purpose: End the query, such as freeing memory
238 *************************************************************************/
239 static int sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
240 // sql_free_result(handle,config);
244 /*************************************************************************
246 * Function: sql_free_result
248 * Purpose: database specific free_result. Frees memory allocated
251 *************************************************************************/
252 static int sql_free_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
256 /*************************************************************************
258 * Function: sql_close
260 * Purpose: database specific close. Closes an open database
261 * connection and cleans up any open handles.
263 *************************************************************************/
264 static int sql_close(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
265 fb_destroy_socket((rlm_sql_firebird_sock *) handle->conn);
269 /*************************************************************************
271 * Function: sql_error
273 * Purpose: database specific error. Returns error associated with
276 *************************************************************************/
277 static const char *sql_error(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
278 rlm_sql_firebird_sock *firebird_sock = handle->conn;
279 return firebird_sock->lasterror;
281 /*************************************************************************
283 * Function: sql_affected_rows
285 * Purpose: Return the number of rows affected by the query (update,
288 *************************************************************************/
289 static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config) {
290 int affected_rows=fb_affected_rows(handle->conn);
292 radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n", sql_error(handle,config));
293 return affected_rows;
296 /* Exported to rlm_sql */
297 rlm_sql_module_t rlm_sql_firebird = {
311 sql_finish_select_query,