/// A cursor for the Series virtual table #[repr(C)] struct SeriesTabCursor<'vtab> { /// Base class. Must be first
base: ffi::sqlite3_vtab_cursor, /// True to count down rather than up
is_desc: bool, /// The rowid
row_id: i64, /// Current value ("value")
value: i64, /// Minimum value ("start")
min_value: i64, /// Maximum value ("stop")
max_value: i64, /// Increment ("step")
step: i64,
phantom: PhantomData<&'vtab SeriesTab>,
}
impl SeriesTabCursor<'_> { fn new<'vtab>() -> SeriesTabCursor<'vtab> {
SeriesTabCursor {
base: ffi::sqlite3_vtab_cursor::default(),
is_desc: false,
row_id: 0,
value: 0,
min_value: 0,
max_value: 0,
step: 0,
phantom: PhantomData,
}
}
} #[allow(clippy::comparison_chain)] unsafeimpl VTabCursor for SeriesTabCursor<'_> { fn filter(&mutself, idx_num: c_int, _idx_str: Option<&str>, args: &Values<'_>) -> Result<()> { letmut idx_num = QueryPlanFlags::from_bits_truncate(idx_num); letmut i = 0; if idx_num.contains(QueryPlanFlags::START) { self.min_value = args.get::<Option<_>>(i)?.unwrap_or_default();
i += 1;
} else { self.min_value = 0;
} if idx_num.contains(QueryPlanFlags::STOP) { self.max_value = args.get::<Option<_>>(i)?.unwrap_or_default();
i += 1;
} else { self.max_value = 0xffff_ffff;
} if idx_num.contains(QueryPlanFlags::STEP) { self.step = args.get::<Option<_>>(i)?.unwrap_or_default(); ifself.step == 0 { self.step = 1;
} elseifself.step < 0 { self.step = -self.step; if !idx_num.contains(QueryPlanFlags::ASC) {
idx_num |= QueryPlanFlags::DESC;
}
}
} else { self.step = 1;
}; for arg in args.iter() { if arg.data_type() == Type::Null { // If any of the constraints have a NULL value, then return no rows. self.min_value = 1; self.max_value = 0; break;
}
} self.is_desc = idx_num.contains(QueryPlanFlags::DESC); ifself.is_desc { self.value = self.max_value; ifself.step > 0 { self.value -= (self.max_value - self.min_value) % self.step;
}
} else { self.value = self.min_value;
} self.row_id = 1;
Ok(())
}
#[cfg(test)] mod test { usecrate::ffi; usecrate::vtab::series; usecrate::{Connection, Result}; use fallible_iterator::FallibleIterator;
#[test] fn test_series_module() -> Result<()> { let version = unsafe { ffi::sqlite3_libversion_number() }; if version < 3_008_012 { return Ok(());
}
let db = Connection::open_in_memory()?;
series::load_module(&db)?;
letmut s = db.prepare("SELECT * FROM generate_series(0,20,5)")?;
let series = s.query_map([], |row| row.get::<_, i32>(0))?;
letmut expected = 0; for value in series {
assert_eq!(expected, value?);
expected += 5;
}
letmut s =
db.prepare("SELECT * FROM generate_series WHERE start=1 AND stop=9 AND step=2")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(vec![1, 3, 5, 7, 9], series); letmut s = db.prepare("SELECT * FROM generate_series LIMIT 5")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(vec![0, 1, 2, 3, 4], series); letmut s = db.prepare("SELECT * FROM generate_series(0,32,5) ORDER BY value DESC")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(vec![30, 25, 20, 15, 10, 5, 0], series);
letmut s = db.prepare("SELECT * FROM generate_series(NULL)")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?; let empty = Vec::<i32>::new();
assert_eq!(empty, series); letmut s = db.prepare("SELECT * FROM generate_series(5,NULL)")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(empty, series); letmut s = db.prepare("SELECT * FROM generate_series(5,10,NULL)")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(empty, series); letmut s = db.prepare("SELECT * FROM generate_series(NULL,10,2)")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(empty, series); letmut s = db.prepare("SELECT * FROM generate_series(5,NULL,2)")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(empty, series); letmut s = db.prepare("SELECT * FROM generate_series(NULL) ORDER BY value DESC")?; let series: Vec<i32> = s.query([])?.map(|r| r.get(0)).collect()?;
assert_eq!(empty, series);
Ok(())
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.