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>
24 #include "sql_fbapi.h"
25 #include <freeradius-devel/rad_assert.h>
28 /* Forward declarations */
29 static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
30 static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
31 static int sql_num_fields(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
32 static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config);
34 static int _sql_socket_destructor(rlm_sql_firebird_conn_t *conn)
38 DEBUG2("rlm_sql_firebird: socket destructor called, closing socket");
42 fb_free_statement(conn);
43 isc_detach_database(conn->status, &(conn->dbh));
46 WARN("rlm_sql_firebird: Got error "
47 "when closing socket: %s", conn->error);
52 pthread_mutex_destroy (&conn->mut);
55 for (i = 0; i < conn->row_fcount; i++) free(conn->row[i]);
58 free(conn->row_sizes);
59 fb_free_sqlda(conn->sqlda_out);
61 free(conn->sqlda_out);
68 /** Establish connection to the db
71 static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
73 rlm_sql_firebird_conn_t *conn;
77 MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_firebird_conn_t));
78 talloc_set_destructor(conn, _sql_socket_destructor);
80 res = fb_init_socket(conn);
81 if (res) return RLM_SQL_ERROR;
83 if (fb_connect(conn, config)) {
84 ERROR("rlm_sql_firebird: Connection failed: %s", conn->error);
86 return RLM_SQL_RECONNECT;
92 /** Issue a non-SELECT query (ie: update/delete/insert) to the database.
95 static sql_rcode_t sql_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config, char const *query)
97 rlm_sql_firebird_conn_t *conn = handle->conn;
102 pthread_mutex_lock(&conn->mut);
107 * Try again query when deadlock, beacuse in any case it
110 if (fb_sql_query(conn, query)) {
111 /* but may be lost for short sessions */
112 if ((conn->sql_code == DEADLOCK_SQL_CODE) &&
114 DEBUG("conn_id deadlock. Retry query %s", query);
117 * @todo For non READ_COMMITED transactions put
125 ERROR("conn_id rlm_sql_firebird,sql_query error: sql_code=%li, error='%s', query=%s",
126 (long int) conn->sql_code, conn->error, query);
128 if (conn->sql_code == DOWN_SQL_CODE) {
131 pthread_mutex_unlock(&conn->mut);
133 return RLM_SQL_RECONNECT;
136 /* Free problem query */
137 if (fb_rollback(conn)) {
138 //assume the network is down if rollback had failed
139 ERROR("Fail to rollback transaction after previous error: %s", conn->error);
146 pthread_mutex_unlock(&conn->mut);
148 return RLM_SQL_ERROR;
151 if (conn->statement_type != isc_info_sql_stmt_select) {
152 if (fb_commit(conn)) goto fail;
156 pthread_mutex_unlock(&conn->mut);
161 /** Issue a select query to the database.
164 static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config, char const *query)
166 return sql_query(handle, config, query);
169 /** Returns number of columns from query.
172 static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
174 return ((rlm_sql_firebird_conn_t *) handle->conn)->sqlda_out->sqld;
177 /** Returns number of rows in query.
180 static int sql_num_rows(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
182 return sql_affected_rows(handle, config);
185 /** Returns name of fields.
188 static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
190 rlm_sql_firebird_conn_t *conn = handle->conn;
195 fields = conn->sqlda_out->sqld;
196 if (fields <= 0) return RLM_SQL_ERROR;
198 MEM(names = talloc_array(handle, char const *, fields));
200 for (i = 0; i < fields; i++) names[i] = conn->sqlda_out->sqlvar[i].sqlname;
206 /** Returns an individual row.
209 static sql_rcode_t sql_fetch_row(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
211 rlm_sql_firebird_conn_t *conn = handle->conn;
216 if (conn->statement_type != isc_info_sql_stmt_exec_procedure) {
217 res = fb_fetch(conn);
223 ERROR("rlm_sql_firebird. Fetch problem: %s", conn->error);
225 return RLM_SQL_ERROR;
228 conn->statement_type=0;
233 handle->row = conn->row;
238 /** End the select query, such as freeing memory or result.
241 static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
243 rlm_sql_firebird_conn_t *conn = (rlm_sql_firebird_conn_t *) handle->conn;
246 fb_close_cursor(conn);
254 static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, rlm_sql_config_t *config)
256 sql_free_result(handle, config);
261 /** Frees memory allocated for a result set.
264 static sql_rcode_t sql_free_result(UNUSED rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
269 /** Retrieves any errors associated with the connection handle
271 * @note Caller will free any memory allocated in ctx.
273 * @param ctx to allocate temporary error buffers in.
274 * @param out Array of sql_log_entrys to fill.
275 * @param outlen Length of out array.
276 * @param handle rlm_sql connection handle.
277 * @param config rlm_sql config.
278 * @return number of errors written to the sql_log_entry array.
280 static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], size_t outlen,
281 rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
283 rlm_sql_firebird_conn_t *conn = handle->conn;
286 rad_assert(outlen > 0);
288 if (!conn->error) return 0;
291 out[0].msg = conn->error;
296 /** Return the number of rows affected by the query (update, or insert)
299 static int sql_affected_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config)
301 return fb_affected_rows(handle->conn);
304 /* Exported to rlm_sql */
305 extern rlm_sql_module_t rlm_sql_firebird;
306 rlm_sql_module_t rlm_sql_firebird = {
307 .name = "rlm_sql_firebird",
308 .sql_socket_init = sql_socket_init,
309 .sql_query = sql_query,
310 .sql_select_query = sql_select_query,
311 .sql_num_fields = sql_num_fields,
312 .sql_num_rows = sql_num_rows,
313 .sql_affected_rows = sql_affected_rows,
314 .sql_fetch_row = sql_fetch_row,
315 .sql_fields = sql_fields,
316 .sql_free_result = sql_free_result,
317 .sql_error = sql_error,
318 .sql_finish_query = sql_finish_query,
319 .sql_finish_select_query = sql_finish_select_query