use crate::constants::FetchOrientation;
use crate::row::Row;
use crate::statement::ColumnInfo;
#[derive(Debug)]
pub struct ScrollableCursor {
pub(crate) cursor_id: u16,
pub(crate) columns: Vec<ColumnInfo>,
pub(crate) is_open: bool,
pub(crate) position: i64,
pub(crate) row_count: Option<u64>,
}
impl ScrollableCursor {
pub(crate) fn new(cursor_id: u16, columns: Vec<ColumnInfo>) -> Self {
Self {
cursor_id,
columns,
is_open: true,
position: 0,
row_count: None,
}
}
pub fn cursor_id(&self) -> u16 {
self.cursor_id
}
pub fn columns(&self) -> &[ColumnInfo] {
&self.columns
}
pub fn is_open(&self) -> bool {
self.is_open
}
pub fn position(&self) -> i64 {
self.position
}
pub fn row_count(&self) -> Option<u64> {
self.row_count
}
pub(crate) fn mark_closed(&mut self) {
self.is_open = false;
}
pub(crate) fn update_position(&mut self, new_position: i64) {
self.position = new_position;
}
}
#[derive(Debug, Clone, Default)]
pub struct ScrollableCursorOptions {
pub array_size: u32,
}
impl ScrollableCursorOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_array_size(mut self, size: u32) -> Self {
self.array_size = size;
self
}
}
#[derive(Debug)]
pub struct ScrollResult {
pub rows: Vec<Row>,
pub position: i64,
pub at_beginning: bool,
pub at_end: bool,
}
impl ScrollResult {
pub fn new(rows: Vec<Row>, position: i64) -> Self {
Self {
rows,
position,
at_beginning: false,
at_end: false,
}
}
pub fn first(&self) -> Option<&Row> {
self.rows.first()
}
pub fn is_empty(&self) -> bool {
self.rows.is_empty()
}
pub fn len(&self) -> usize {
self.rows.len()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScrollMode {
First,
Last,
Relative,
Absolute,
}
impl Default for ScrollMode {
fn default() -> Self {
Self::Relative
}
}
impl From<ScrollMode> for FetchOrientation {
fn from(mode: ScrollMode) -> Self {
match mode {
ScrollMode::First => FetchOrientation::First,
ScrollMode::Last => FetchOrientation::Last,
ScrollMode::Relative => FetchOrientation::Relative,
ScrollMode::Absolute => FetchOrientation::Absolute,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants::OracleType;
#[test]
fn test_scrollable_cursor_creation() {
let columns = vec![
ColumnInfo::new("ID", OracleType::Number),
ColumnInfo::new("NAME", OracleType::Varchar),
];
let cursor = ScrollableCursor::new(123, columns);
assert_eq!(cursor.cursor_id(), 123);
assert_eq!(cursor.columns().len(), 2);
assert!(cursor.is_open());
assert_eq!(cursor.position(), 0);
}
#[test]
fn test_scrollable_cursor_close() {
let mut cursor = ScrollableCursor::new(1, Vec::new());
assert!(cursor.is_open());
cursor.mark_closed();
assert!(!cursor.is_open());
}
#[test]
fn test_scroll_result() {
let rows = vec![Row::new(vec![crate::row::Value::Integer(1)])];
let result = ScrollResult::new(rows, 5);
assert_eq!(result.len(), 1);
assert!(!result.is_empty());
assert_eq!(result.position, 5);
assert!(result.first().is_some());
}
#[test]
fn test_scroll_mode_conversion() {
assert_eq!(FetchOrientation::from(ScrollMode::First), FetchOrientation::First);
assert_eq!(FetchOrientation::from(ScrollMode::Last), FetchOrientation::Last);
assert_eq!(FetchOrientation::from(ScrollMode::Relative), FetchOrientation::Relative);
assert_eq!(FetchOrientation::from(ScrollMode::Absolute), FetchOrientation::Absolute);
}
#[test]
fn test_scrollable_cursor_options() {
let opts = ScrollableCursorOptions::new()
.with_array_size(50);
assert_eq!(opts.array_size, 50);
}
}