예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}