use super::*;
use sys::*;
use std::marker::PhantomData;
#[derive(Debug)]
pub struct Statement<'con, 'param, 'col, C = NoCursor, A = Unprepared> {
cursor: PhantomData<C>,
access_plan: PhantomData<A>,
parameters: PhantomData<&'param [u8]>,
columns: PhantomData<&'col [u8]>,
handle: HStmt<'con>,
}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Open {}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum NoCursor {}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Positioned {}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Prepared {}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub enum Unprepared {}
pub trait CursorState {}
impl CursorState for Open {}
impl CursorState for Positioned {}
impl<'con, 'param, 'col, S, A> Statement<'con, 'param, 'col, S, A> {
pub fn as_raw(&self) -> SQLHSTMT {
self.handle.as_raw()
}
pub fn bind_input_parameter<'p, T>(
mut self,
parameter_number: SQLUSMALLINT,
parameter_type: DataType,
value: &'p T,
indicator: Option<&'p SQLLEN>,
) -> Return<Statement<'con, 'p, 'col, S, A>, Self>
where
T: CDataType + ?Sized,
'param: 'p,
{
unsafe {
match self.handle.bind_input_parameter(
parameter_number,
parameter_type,
value,
indicator,
) {
Success(()) => Success(self.transit()),
Info(()) => Info(self.transit()),
Error(()) => Error(self.transit()),
}
}
}
pub fn bind_col<'col_new, T>(
mut self,
column_number: SQLUSMALLINT,
value: &'col_new mut T,
indicator: Option<&'col_new mut SQLLEN>,
) -> Return<Statement<'con, 'param, 'col_new, S, A>, Self>
where
T: CDataType + ?Sized,
'col: 'col_new,
{
unsafe {
match self.handle.bind_col(column_number, value, indicator) {
Success(()) => Success(self.transit()),
Info(()) => Info(self.transit()),
Error(()) => Error(self.transit()),
}
}
}
pub fn reset_parameters(mut self) -> Statement<'con, 'static, 'col, S, A> {
self.handle.reset_parameters().unwrap();
self.transit()
}
pub fn reset_columns(mut self) -> Statement<'con, 'param, 'static, S, A> {
self.handle.reset_columns().unwrap();
self.transit()
}
fn transit<'p, 'c, S2, A2>(self) -> Statement<'con, 'p, 'c, S2, A2> {
Statement {
handle: self.handle,
parameters: PhantomData,
columns: PhantomData,
cursor: PhantomData,
access_plan: PhantomData,
}
}
}
impl<'con, 'param, 'col, C, A> Statement<'con, 'param, 'col, C, A>
where
C: CursorState,
{
pub fn num_result_cols(&self) -> Return<SQLSMALLINT> {
self.handle.num_result_cols()
}
pub fn affected_row_count(&self) -> Return<SQLLEN> { self.handle.affected_row_count() }
pub fn fetch(
mut self,
) -> ReturnOption<
Statement<'con, 'param, 'col, Positioned, A>,
Statement<'con, 'param, 'col, NoCursor, A>,
> {
match self.handle.fetch() {
ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
}
}
pub fn close_cursor(
mut self,
) -> Return<Statement<'con, 'param, 'col, NoCursor>, Statement<'con, 'param, 'col, C, A>> {
match self.handle.close_cursor() {
Success(()) => Success(self.transit()),
Info(()) => Info(self.transit()),
Error(()) => Error(self.transit()),
}
}
pub fn describe_col<T>(
&mut self,
column_number: SQLUSMALLINT,
column_name: &mut T,
column_name_indicator: &mut SQLSMALLINT,
nullable: &mut Nullable,
) -> Return<Option<DataType>>
where
T: OutputBuffer + ?Sized,
{
let mut data_type = SQL_UNKNOWN_TYPE;
let mut column_size = 0;
let mut decimal_digits = 0;
self.handle.describe_col(
column_number,
column_name,
column_name_indicator,
&mut data_type,
&mut column_size,
&mut decimal_digits,
nullable
).map(|()| DataType::new(data_type, column_size, decimal_digits))
}
}
impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Unprepared> {
pub fn with_parent<AC: AutocommitMode>(parent: &'con Connection<AC>) -> Return<Self> {
HStmt::allocate(parent.as_hdbc()).map(|handle| {
Statement {
handle,
parameters: PhantomData,
cursor: PhantomData,
columns: PhantomData,
access_plan: PhantomData,
}
})
}
pub fn prepare<T>(
mut self,
statement_text: &T,
) -> Return<
Statement<'con, 'param, 'col, NoCursor, Prepared>,
Statement<'con, 'param, 'col, NoCursor>,
>
where
T: SqlStr + ?Sized,
{
match self.handle.prepare(statement_text) {
Success(()) => Success(self.transit()),
Info(()) => Info(self.transit()),
Error(()) => Error(self.transit()),
}
}
pub fn exec_direct<T>(
mut self,
statement_text: &T,
) -> ReturnOption<
ResultSet<'con, 'param, 'col, Unprepared>,
Statement<'con, 'param, 'col, NoCursor>,
>
where
T: SqlStr + ?Sized,
{
match self.handle.exec_direct(statement_text) {
ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
}
}
}
impl<'con, 'param, 'col> Statement<'con, 'param, 'col, NoCursor, Prepared> {
pub fn describe_col<T>(
&mut self,
column_number: SQLUSMALLINT,
column_name: &mut T,
column_name_indicator: &mut SQLSMALLINT,
nullable: &mut Nullable,
) -> Return<Option<DataType>>
where
T: OutputBuffer + ?Sized,
{
let mut data_type = SQL_UNKNOWN_TYPE;
let mut column_size = 0;
let mut decimal_digits = 0;
self.handle.describe_col(
column_number,
column_name,
column_name_indicator,
&mut data_type,
&mut column_size,
&mut decimal_digits,
nullable
).map(|()| DataType::new(data_type, column_size, decimal_digits))
}
pub fn execute(mut self) -> ReturnOption<ResultSet<'con, 'param, 'col, Prepared>, Self> {
match self.handle.execute() {
ReturnOption::Success(()) => ReturnOption::Success(self.transit()),
ReturnOption::Info(()) => ReturnOption::Info(self.transit()),
ReturnOption::Error(()) => ReturnOption::Error(self.transit()),
ReturnOption::NoData(()) => ReturnOption::NoData(self.transit()),
}
}
}
impl<'con, 'param, 'col, A> Statement<'con, 'param, 'col, Positioned, A> {
pub fn get_data<T>(
&mut self,
col_or_param_num: SQLUSMALLINT,
target: &mut T,
) -> ReturnOption<Indicator>
where
T: CDataType + ?Sized,
{
self.handle.get_data(col_or_param_num, target)
}
}
impl<'con, 'param, 'col, C, A> Diagnostics for Statement<'con, 'param, 'col, C, A> {
fn diagnostics(
&self,
rec_number: SQLSMALLINT,
message_text: &mut [SQLCHAR],
) -> ReturnOption<DiagResult> {
self.handle.diagnostics(rec_number, message_text)
}
}