static int fb_prepare(rlm_sql_firebird_conn_t *conn, char const *query) { static char stmt_info[] = { isc_info_sql_stmt_type }; char info_buffer[128]; short l; if (!conn->trh) { isc_start_transaction(conn->status, &conn->trh, 1, &conn->dbh, conn->tpb_len, conn->tpb); if (!conn->trh) { return -4; } } fb_free_statement(conn); if (!conn->stmt) { isc_dsql_allocate_statement(conn->status, &conn->dbh, &conn->stmt); if (!conn->stmt) { return -1; } } fb_free_sqlda(conn->sqlda_out); isc_dsql_prepare(conn->status, &conn->trh, &conn->stmt, 0, query, conn->sql_dialect, conn->sqlda_out); if (IS_ISC_ERROR(conn->status)) { return -2; } if (conn->sqlda_out->sqln<conn->sqlda_out->sqld) { conn->sqlda_out->sqln = conn->sqlda_out->sqld; conn->sqlda_out = (XSQLDA ISC_FAR *) realloc(conn->sqlda_out, XSQLDA_LENGTH(conn->sqlda_out->sqld)); isc_dsql_describe(conn->status, &conn->stmt, SQL_DIALECT_V6, conn->sqlda_out); if (IS_ISC_ERROR(conn->status)) { return -3; } } /* * Get statement type */ isc_dsql_sql_info(conn->status, &conn->stmt, sizeof(stmt_info), stmt_info, sizeof(info_buffer), info_buffer); if (IS_ISC_ERROR(conn->status)) return -4; l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2); conn->statement_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l); if (conn->sqlda_out->sqld) { fb_set_sqlda(conn->sqlda_out); //set out sqlda } return 0; }
int fb_affected_rows(rlm_sql_firebird_conn_t *conn) { static char count_info[] = {isc_info_sql_records}; char info_buffer[128]; char *p ; int affected_rows = -1; if (!conn->stmt) return -1; isc_dsql_sql_info(conn->status, &conn->stmt, sizeof (count_info), count_info, sizeof (info_buffer), info_buffer); if (IS_ISC_ERROR(conn->status)) { return fb_error(conn); } p = info_buffer + 3; while (*p != isc_info_end) { p++; short len = (short)isc_vax_integer(p, 2); p += 2; affected_rows = isc_vax_integer(p, len); if (affected_rows > 0) { break; } p += len; } return affected_rows; }
int fb_rollback(rlm_sql_firebird_conn_t *conn) { conn->sql_code = 0; if (conn->trh) { isc_rollback_transaction(conn->status, &conn->trh); // conn->in_use = 0; pthread_mutex_unlock(&conn->mut); if (IS_ISC_ERROR(conn->status)) { return fb_error(conn); } } return conn->sql_code; }
int fb_commit(rlm_sql_firebird_conn_t *conn) { conn->sql_code = 0; if (conn->trh) { isc_commit_transaction(conn->status, &conn->trh); if (IS_ISC_ERROR(conn->status)) { fb_error(conn); ERROR("Fail to commit. Error: %s. Try to rollback.", conn->error); return fb_rollback(conn); } } // conn->in_use = 0; pthread_mutex_unlock(&conn->mut); return conn->sql_code; }
int fb_error(rlm_sql_firebird_conn_t *conn) { ISC_SCHAR error[2048]; /* Only 1024 bytes should be written to this, but were playing it extra safe */ ISC_STATUS *pstatus; conn->sql_code = 0; /* * Free any previous errors. */ TALLOC_FREE(conn->error); /* * Check if the status array contains an error */ if (IS_ISC_ERROR(conn->status)) { conn->sql_code = isc_sqlcode(conn->status); /* * pstatus is a pointer into the status array which is * advanced by isc_interprete. It's initialised to the * first element of the status array. */ pstatus = &conn->status[0]; /* * It's deprecated because the size of the buffer isn't * passed and this isn't safe. But as were passing a very * large buffer it's unlikely this will be an issue, and * allows us to maintain compatibility with the interbase * API. */ isc_interprete(&error[0], &pstatus); conn->error = talloc_typed_asprintf(conn, "%s. ", &error[0]); while (isc_interprete(&error[0], &pstatus)) { conn->error = talloc_asprintf_append(conn->error, "%s. ", &error[0]); } memset(&conn->status, 0, sizeof(conn->status)); } return conn->sql_code; }