use newtypes for distinguishing between second and millisecond stamps

This commit is contained in:
Damien Elmes 2020-03-26 12:59:51 +10:00
parent 65b8988817
commit eb89a2db3f
7 changed files with 71 additions and 16 deletions

View file

@ -28,5 +28,5 @@ pub mod storage;
pub mod template; pub mod template;
pub mod template_filters; pub mod template_filters;
pub mod text; pub mod text;
pub mod time; pub mod timestamp;
pub mod types; pub mod types;

View file

@ -5,10 +5,10 @@
/// the media DB check. /// the media DB check.
use crate::err::{AnkiError, DBErrorKind, Result}; use crate::err::{AnkiError, DBErrorKind, Result};
use crate::text::strip_html_preserving_image_filenames; use crate::text::strip_html_preserving_image_filenames;
use crate::time::i64_unix_secs; use crate::timestamp::TimestampSecs;
use crate::{ use crate::{
notetypes::NoteType, notetypes::NoteType,
types::{ObjID, Timestamp, Usn}, types::{ObjID, Usn},
}; };
use rusqlite::{params, Connection, Row, NO_PARAMS}; use rusqlite::{params, Connection, Row, NO_PARAMS};
use std::convert::TryInto; use std::convert::TryInto;
@ -17,7 +17,7 @@ use std::convert::TryInto;
pub(super) struct Note { pub(super) struct Note {
pub id: ObjID, pub id: ObjID,
pub mid: ObjID, pub mid: ObjID,
pub mtime_secs: Timestamp, pub mtime: TimestampSecs,
pub usn: Usn, pub usn: Usn,
fields: Vec<String>, fields: Vec<String>,
} }
@ -73,7 +73,7 @@ fn row_to_note(row: &Row) -> Result<Note> {
Ok(Note { Ok(Note {
id: row.get(0)?, id: row.get(0)?,
mid: row.get(1)?, mid: row.get(1)?,
mtime_secs: row.get(2)?, mtime: row.get(2)?,
usn: row.get(3)?, usn: row.get(3)?,
fields: row fields: row
.get_raw(4) .get_raw(4)
@ -85,7 +85,7 @@ fn row_to_note(row: &Row) -> Result<Note> {
} }
pub(super) fn set_note(db: &Connection, note: &mut Note, note_type: &NoteType) -> Result<()> { pub(super) fn set_note(db: &Connection, note: &mut Note, note_type: &NoteType) -> Result<()> {
note.mtime_secs = i64_unix_secs(); note.mtime = TimestampSecs::now();
// hard-coded for now // hard-coded for now
note.usn = -1; note.usn = -1;
let field1_nohtml = strip_html_preserving_image_filenames(&note.fields()[0]); let field1_nohtml = strip_html_preserving_image_filenames(&note.fields()[0]);
@ -106,7 +106,7 @@ pub(super) fn set_note(db: &Connection, note: &mut Note, note_type: &NoteType) -
let mut stmt = let mut stmt =
db.prepare_cached("update notes set mod=?,usn=?,flds=?,sfld=?,csum=? where id=?")?; db.prepare_cached("update notes set mod=?,usn=?,flds=?,sfld=?,csum=? where id=?")?;
stmt.execute(params![ stmt.execute(params![
note.mtime_secs, note.mtime,
note.usn, note.usn,
note.fields().join("\x1f"), note.fields().join("\x1f"),
sort_field, sort_field,

View file

@ -1,3 +1,4 @@
mod sqlite; mod sqlite;
mod timestamp;
pub(crate) use sqlite::{SqliteStorage, StorageContext}; pub(crate) use sqlite::{SqliteStorage, StorageContext};

View file

@ -5,7 +5,7 @@ use crate::collection::CollectionOp;
use crate::config::Config; use crate::config::Config;
use crate::err::Result; use crate::err::Result;
use crate::err::{AnkiError, DBErrorKind}; use crate::err::{AnkiError, DBErrorKind};
use crate::time::{i64_unix_millis, i64_unix_secs}; use crate::timestamp::{TimestampMillis, TimestampSecs};
use crate::{ use crate::{
decks::Deck, decks::Deck,
notetypes::NoteType, notetypes::NoteType,
@ -168,7 +168,10 @@ impl SqliteStorage {
if create { if create {
db.prepare_cached("begin exclusive")?.execute(NO_PARAMS)?; db.prepare_cached("begin exclusive")?.execute(NO_PARAMS)?;
db.execute_batch(include_str!("schema11.sql"))?; db.execute_batch(include_str!("schema11.sql"))?;
db.execute("update col set crt=?, ver=?", params![i64_unix_secs(), ver])?; db.execute(
"update col set crt=?, ver=?",
params![TimestampSecs::now(), ver],
)?;
db.prepare_cached("commit")?.execute(NO_PARAMS)?; db.prepare_cached("commit")?.execute(NO_PARAMS)?;
} else { } else {
if ver > SCHEMA_MAX_VERSION { if ver > SCHEMA_MAX_VERSION {
@ -278,7 +281,7 @@ impl StorageContext<'_> {
pub(crate) fn mark_modified(&self) -> Result<()> { pub(crate) fn mark_modified(&self) -> Result<()> {
self.db self.db
.prepare_cached("update col set mod=?")? .prepare_cached("update col set mod=?")?
.execute(params![i64_unix_millis()])?; .execute(params![TimestampMillis::now()])?;
Ok(()) Ok(())
} }
@ -339,7 +342,7 @@ impl StorageContext<'_> {
self.timing_today = Some(sched_timing_today( self.timing_today = Some(sched_timing_today(
crt, crt,
i64_unix_secs(), TimestampSecs::now().0,
conf.creation_offset, conf.creation_offset,
now_offset, now_offset,
conf.rollover, conf.rollover,

View file

@ -0,0 +1,40 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::timestamp::{TimestampMillis, TimestampSecs};
use rusqlite::{
types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef},
ToSql,
};
impl FromSql for TimestampSecs {
fn column_result(value: ValueRef<'_>) -> std::result::Result<Self, FromSqlError> {
if let ValueRef::Integer(i) = value {
Ok(TimestampSecs(i))
} else {
Err(FromSqlError::InvalidType)
}
}
}
impl ToSql for TimestampSecs {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
}
}
impl FromSql for TimestampMillis {
fn column_result(value: ValueRef<'_>) -> std::result::Result<Self, FromSqlError> {
if let ValueRef::Integer(i) = value {
Ok(TimestampMillis(i))
} else {
Err(FromSqlError::InvalidType)
}
}
}
impl ToSql for TimestampMillis {
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
}
}

View file

@ -3,12 +3,24 @@
use std::time; use std::time;
pub(crate) fn i64_unix_secs() -> i64 { #[repr(transparent)]
elapsed().as_secs() as i64 #[derive(Debug, Clone)]
pub struct TimestampSecs(pub i64);
impl TimestampSecs {
pub fn now() -> Self {
Self(elapsed().as_secs() as i64)
}
} }
pub(crate) fn i64_unix_millis() -> i64 { #[repr(transparent)]
elapsed().as_millis() as i64 #[derive(Debug, Clone)]
pub struct TimestampMillis(pub i64);
impl TimestampMillis {
pub fn now() -> Self {
Self(elapsed().as_millis() as i64)
}
} }
#[cfg(not(test))] #[cfg(not(test))]

View file

@ -6,4 +6,3 @@
pub type ObjID = i64; pub type ObjID = i64;
pub type Usn = i32; pub type Usn = i32;
pub type Timestamp = i64;