23 RCSID(
"$Id: dbc618f877e16611086a524dd4e31b384e55c655 $")
25 #define LOG_PREFIX "sql - oracle"
27 #include <freeradius-devel/server/base.h>
28 #include <freeradius-devel/util/debug.h>
42 #if defined(__STDC__) && __STDC__
102 #define MAX_DATASTR_LEN 64
123 OCIErrorGet((dvoid *) conn->
error, 1, (OraText *) NULL, &errcode, (OraText *)
out,
124 outlen, OCI_HTYPE_ERROR);
125 if (!errcode)
return -1;
150 if (ret < 0)
return 0;
153 out[0].msg = talloc_strdup(ctx, errbuff);
162 if (
inst->pool) OCISessionPoolDestroy((dvoid *)
inst->pool, (dvoid *)
inst->error, OCI_DEFAULT );
163 if (
inst->error) OCIHandleFree((dvoid *)
inst->error, OCI_HTYPE_ERROR);
164 if (
inst->env) OCIHandleFree((dvoid *)
inst->env, OCI_HTYPE_ENV);
176 OraText *sql_password = NULL;
177 OraText *sql_login = NULL;
180 ERROR(
"Couldn't load mctx->configuration of session pool(\"spool\" section in driver mctx->config)");
187 if (OCIEnvCreate(&
inst->env, OCI_DEFAULT | OCI_THREADED, NULL, NULL, NULL, NULL, 0, NULL)) {
188 ERROR(
"Couldn't init Oracle OCI environment (OCIEnvCreate())");
196 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&
inst->error, OCI_HTYPE_ERROR, 0, NULL)) {
197 ERROR(
"Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
205 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&
inst->pool, OCI_HTYPE_SPOOL, 0, NULL)) {
206 ERROR(
"Couldn't init Oracle session pool (OCIHandleAlloc())");
213 DEBUG2(
"OCISessionPoolCreate min=%d max=%d inc=%d",
inst->spool_min,
inst->spool_max,
inst->spool_inc);
216 memcpy(&sql_login, &
config->sql_login,
sizeof(sql_login));
217 memcpy(&sql_password, &
config->sql_password,
sizeof(sql_password));
219 if (OCISessionPoolCreate((dvoid *)
inst->env, (dvoid *)
inst->error, (dvoid *)
inst->pool,
220 (OraText**)&
inst->pool_name, (ub4*)&
inst->pool_name_len,
221 (CONST OraText *)
config->sql_db, strlen(
config->sql_db),
223 sql_login, strlen(
config->sql_login),
224 sql_password, strlen(
config->sql_password),
225 OCI_SPC_STMTCACHE | OCI_SPC_HOMOGENEOUS)) {
228 OCIErrorGet((dvoid *)
inst->error, 1, (OraText *) NULL, &errcode, (OraText *) errbuff,
229 sizeof(errbuff), OCI_HTYPE_ERROR);
232 ERROR(
"Oracle create session pool failed: '%s'", errbuff);
236 if (
inst->spool_timeout > 0) {
237 if (OCIAttrSet(
inst->pool, OCI_HTYPE_SPOOL, &
inst->spool_timeout, 0,
238 OCI_ATTR_SPOOL_TIMEOUT,
inst->error) != OCI_SUCCESS) {
239 ERROR(
"Couldn't set Oracle session idle time");
244 if (OCIAttrSet(
inst->pool, OCI_HTYPE_SPOOL, &
inst->stmt_cache_size, 0,
245 OCI_ATTR_SPOOL_STMTCACHESIZE,
inst->error) != OCI_SUCCESS) {
246 ERROR(
"Couldn't set Oracle default statement cache size");
259 if (strstr(errbuff,
"ORA-03113") || strstr(errbuff,
"ORA-03114")) {
260 ERROR(
"OCI_SERVER_NOT_CONNECTED");
269 if (conn->
ctx) OCISessionRelease(conn->
ctx, conn->
error, NULL, 0, OCI_DEFAULT);
270 if (conn->
error) OCIHandleFree((dvoid *)conn->
error, OCI_HTYPE_ERROR);
288 if (OCIHandleAlloc((dvoid *)
inst->env, (dvoid **)&conn->
error, OCI_HTYPE_ERROR, 0, NULL)) {
289 ERROR(
"Couldn't init Oracle ERROR handle (OCIHandleAlloc())");
297 if (OCISessionGet((dvoid *)
inst->env, conn->
error, &conn->
ctx, NULL,
298 (OraText *)
inst->pool_name,
inst->pool_name_len,
299 NULL, 0, NULL, NULL, NULL,
300 OCI_SESSGET_SPOOL | OCI_SESSGET_STMTCACHE) != OCI_SUCCESS) {
301 ERROR(
"Oracle get sessin from pool[%s] failed: '%s'",
317 if (OCIAttrGet((dvoid *)conn->
query, OCI_HTYPE_STMT, (dvoid *)&
count, NULL, OCI_ATTR_PARAM_COUNT,
318 conn->
error))
return -1;
326 int fields, i, status;
333 MEM(
names = talloc_array(handle,
char const *, fields));
335 for (i = 0; i < fields; i++) {
336 OraText *pcol_name = NULL;
339 status = OCIParamGet(conn->
query, OCI_HTYPE_STMT, conn->
error, (dvoid **)¶m, i + 1);
340 if (status != OCI_SUCCESS) {
341 ERROR(
"OCIParamGet(OCI_HTYPE_STMT) failed in sql_fields()");
348 status = OCIAttrGet((dvoid **)param, OCI_DTYPE_PARAM, &pcol_name, &pcol_size,
349 OCI_ATTR_NAME, conn->
error);
350 if (status != OCI_SUCCESS) {
351 ERROR(
"OCIParamGet(OCI_ATTR_NAME) failed in sql_fields()");
356 names[i] = (
char const *)pcol_name;
370 ERROR(
"Socket not connected");
375 if (OCIStmtPrepare2(conn->
ctx, &conn->
query, conn->
error, (
const OraText *)query, strlen(query),
376 NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
377 ERROR(
"prepare failed in sql_query");
382 status = OCIStmtExecute(conn->
ctx, conn->
query, conn->
error, 1, 0,
383 NULL, NULL, OCI_COMMIT_ON_SUCCESS);
386 if (status == OCI_ERROR) {
387 ERROR(
"execute query failed in sql_query");
411 if (OCIStmtPrepare2(conn->
ctx, &conn->
query, conn->
error, (
const OraText *)query, strlen(query),
412 NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT)) {
413 ERROR(
"prepare failed in sql_select_query");
421 status = OCIStmtExecute(conn->
ctx, conn->
query, conn->
error, 0, 0, NULL, NULL, OCI_DEFAULT);
423 if (status != OCI_SUCCESS) {
424 ERROR(
"query failed in sql_select_query");
439 MEM(row = talloc_zero_array(conn,
char*, conn->
col_count + 1));
443 status = OCIParamGet(conn->
query, OCI_HTYPE_STMT, conn->
error, (dvoid **)¶m, i + 1);
444 if (status != OCI_SUCCESS) {
445 ERROR(
"OCIParamGet() failed in sql_select_query");
450 status = OCIAttrGet((dvoid*)param, OCI_DTYPE_PARAM, (dvoid*)&dtype, NULL, OCI_ATTR_DATA_TYPE,
452 if (status != OCI_SUCCESS) {
453 ERROR(
"OCIAttrGet() failed in sql_select_query");
474 status = OCIAttrGet((dvoid *)param, OCI_DTYPE_PARAM, (dvoid *)&dsize, NULL,
475 OCI_ATTR_DATA_SIZE, conn->
error);
476 if (status != OCI_SUCCESS) {
477 ERROR(
"OCIAttrGet() failed in sql_select_query");
482 MEM(row[i] = talloc_zero_array(row,
char, dsize + 1));
492 MEM(row[i] = talloc_zero_array(row,
char, dsize + 1));
506 status = OCIDefineByPos(conn->
query, &
define, conn->
error, i + 1, (ub1 *)row[i], dsize + 1, SQLT_STR,
507 (dvoid *)&
ind[i], NULL, NULL, OCI_DEFAULT);
509 if (status != OCI_SUCCESS) {
510 ERROR(
"OCIDefineByPos() failed in sql_select_query");
530 ub4 size =
sizeof(ub4);
532 OCIAttrGet((CONST dvoid *)conn->
query, OCI_HTYPE_STMT, (dvoid *)&rows, &size, OCI_ATTR_ROW_COUNT, conn->
error);
545 ERROR(
"Socket not connected");
552 status = OCIStmtFetch(conn->
query, conn->
error, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
553 if (status == OCI_SUCCESS) {
559 if (status == OCI_NO_DATA) {
565 if (status == OCI_ERROR) {
566 ERROR(
"fetch failed in sql_fetch_row");
578 (void) OCIStmtFetch(conn->
query, conn->
error, 0, OCI_FETCH_NEXT, OCI_DEFAULT);
580 TALLOC_FREE(conn->
row);
584 if (OCIStmtRelease (conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
585 ERROR(
"OCI release failed in sql_finish_query");
596 if (OCIStmtRelease(conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
597 ERROR(
"OCI release failed in sql_finish_query");
608 TALLOC_FREE(conn->
row);
612 if (OCIStmtRelease (conn->
query, conn->
error, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS ) {
613 ERROR(
"OCI release failed in sql_finish_query");
629 .name =
"sql_oracle",
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
char const * name1
Name of the CONF_ITEM to parse.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
static fr_time_delta_t timeout
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_inst_t const * inst
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
main_config_t const * main_config
Main server configuration.
uint32_t max_workers
for the scheduler
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for instantiation calls.
static const conf_parser_t config[]
rlm_sql_t const * inst
The rlm_sql instance this connection belongs to.
void * conn
Database specific connection handle.
sql_rcode_t
Action to take at end of an SQL query.
@ RLM_SQL_RECONNECT
Stale connection, should reconnect.
@ RLM_SQL_ERROR
General connection/server error.
@ RLM_SQL_NO_MORE_ROWS
No more rows available.
rlm_sql_row_t row
Row data from the last query.
int col_count
Number of columns associated with the result set.
rlm_sql_driver_t rlm_sql_oracle
static int mod_detach(module_detach_ctx_t const *mctx)
static sql_rcode_t sql_fetch_row(rlm_sql_row_t *out, rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
uint32_t spool_min
Specifies the minimum number of sessions in the session pool.
ub4 pool_name_len
Length of pool_name in bytes.
uint32_t stmt_cache_size
Statement cache size for each of the sessions in a session pool.
static int max_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
uint32_t spool_timeout
The sessions idle time (in seconds) (0 disable).
static int _sql_socket_destructor(rlm_sql_oracle_conn_t *conn)
uint32_t spool_inc
Specifies the increment for sessions to be started if the current number of sessions are less than se...
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static sql_rcode_t sql_free_result(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
uint32_t spool_max
Specifies the maximum number of sessions that can be opened in the session pool.
static sql_rcode_t sql_finish_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
OCIEnv * env
Number of columns associated with the result set.
OCIError * error
Oracle error handle.
static const conf_parser_t spool_config[]
static int sql_affected_rows(rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
static int sql_num_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
static sql_rcode_t sql_fields(char const **out[], rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
static const conf_parser_t driver_config[]
static sql_rcode_t sql_finish_select_query(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
char * pool_name
The name of the session pool returned by OCISessionPoolCreate.
static sql_rcode_t sql_select_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
static int sql_check_reconnect(rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
OCISPool * pool
Oracle session pool handle.
static int sql_num_fields(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
static sql_rcode_t sql_query(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, char const *query)
static size_t sql_error(TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen, rlm_sql_handle_t *handle, rlm_sql_config_t const *config)
Retrieves any errors associated with the connection handle.
static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t const *config, UNUSED fr_time_delta_t timeout)
static int sql_snprint_error(char *out, size_t outlen, rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t const *config)
Write the last Oracle error out to a buffer.
dl_module_inst_t * dl_inst
Structure containing the module's instance data, configuration, and dl handle.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
module_t common
Common fields for all loadable modules.
module_instance_t * driver_submodule
Driver's submodule.
static const char * names[8]
A time delta, a difference in time measured in nanoseconds.
static size_t char ** out