mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 01:12:24 +00:00
@@ -0,0 +1,47 @@
|
||||
DROP INDEX idx_calobjs_uid;
|
||||
ALTER TABLE calendarobjects RENAME TO calendarobjects_old;
|
||||
|
||||
CREATE TABLE calendarobjects (
|
||||
principal TEXT NOT NULL,
|
||||
cal_id TEXT NOT NULL,
|
||||
id TEXT NOT NULL, -- filename
|
||||
ics TEXT NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME,
|
||||
|
||||
-- For more efficient calendar-queries
|
||||
first_occurence DATE,
|
||||
last_occurence DATE,
|
||||
etag TEXT,
|
||||
object_type INTEGER NOT NULL, -- VEVENT(0)/VTODO(1)/VJOURNAL(2)
|
||||
|
||||
CONSTRAINT pk_calendarobject_id PRIMARY KEY (principal, cal_id, id),
|
||||
CONSTRAINT fk_calendarobject_calendar FOREIGN KEY (principal, cal_id)
|
||||
REFERENCES calendars (principal, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO calendarobjects (
|
||||
principal,
|
||||
cal_id,
|
||||
id,
|
||||
ics,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
etag,
|
||||
object_type
|
||||
) SELECT
|
||||
principal,
|
||||
cal_id,
|
||||
id,
|
||||
ics,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
etag,
|
||||
object_type
|
||||
FROM calendarobjects_old;
|
||||
|
||||
DROP TABLE calendarobjects_old;
|
||||
@@ -0,0 +1,53 @@
|
||||
-- Adds the column "uid" and populates it with data from "id"
|
||||
ALTER TABLE calendarobjects RENAME TO calendarobjects_old;
|
||||
|
||||
CREATE TABLE calendarobjects (
|
||||
principal TEXT NOT NULL,
|
||||
cal_id TEXT NOT NULL,
|
||||
id TEXT NOT NULL, -- filename
|
||||
"uid" TEXT NOT NULL, -- global identifier
|
||||
ics TEXT NOT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME,
|
||||
|
||||
-- For more efficient calendar-queries
|
||||
first_occurence DATE,
|
||||
last_occurence DATE,
|
||||
etag TEXT,
|
||||
object_type INTEGER NOT NULL, -- VEVENT(0)/VTODO(1)/VJOURNAL(2)
|
||||
|
||||
CONSTRAINT pk_calendarobject_id PRIMARY KEY (principal, cal_id, id),
|
||||
CONSTRAINT uq_calendarobject_uid UNIQUE (principal, cal_id, "uid"),
|
||||
CONSTRAINT fk_calendarobject_calendar FOREIGN KEY (principal, cal_id)
|
||||
REFERENCES calendars (principal, id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_calobjs_uid ON calendarobjects (principal, cal_id, "uid");
|
||||
|
||||
INSERT INTO calendarobjects (
|
||||
principal,
|
||||
cal_id,
|
||||
id,
|
||||
"uid",
|
||||
ics,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
etag,
|
||||
object_type
|
||||
) SELECT
|
||||
principal,
|
||||
cal_id,
|
||||
id,
|
||||
id AS "uid",
|
||||
ics,
|
||||
updated_at,
|
||||
deleted_at,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
etag,
|
||||
object_type
|
||||
FROM calendarobjects_old;
|
||||
|
||||
DROP TABLE calendarobjects_old;
|
||||
@@ -17,19 +17,20 @@ use tracing::{error, instrument};
|
||||
struct CalendarObjectRow {
|
||||
id: String,
|
||||
ics: String,
|
||||
uid: String,
|
||||
}
|
||||
|
||||
impl TryFrom<CalendarObjectRow> for CalendarObject {
|
||||
type Error = rustical_store::Error;
|
||||
|
||||
fn try_from(value: CalendarObjectRow) -> Result<Self, Self::Error> {
|
||||
let object = Self::from_ics(value.ics)?;
|
||||
if object.get_uid() != value.id {
|
||||
let object = Self::from_ics(value.ics, Some(value.id))?;
|
||||
if object.get_uid() != value.uid {
|
||||
return Err(rustical_store::Error::IcalError(
|
||||
rustical_ical::Error::InvalidData(format!(
|
||||
"object_id={} and UID={} don't match",
|
||||
object.get_uid(),
|
||||
value.id
|
||||
"uid={} and UID={} don't match",
|
||||
value.uid,
|
||||
object.get_uid()
|
||||
)),
|
||||
));
|
||||
}
|
||||
@@ -281,7 +282,7 @@ impl SqliteCalendarStore {
|
||||
) -> Result<Vec<CalendarObject>, Error> {
|
||||
sqlx::query_as!(
|
||||
CalendarObjectRow,
|
||||
"SELECT id, ics FROM calendarobjects WHERE principal = ? AND cal_id = ? AND deleted_at IS NULL",
|
||||
"SELECT id, uid, ics FROM calendarobjects WHERE principal = ? AND cal_id = ? AND deleted_at IS NULL",
|
||||
principal,
|
||||
cal_id
|
||||
)
|
||||
@@ -306,7 +307,7 @@ impl SqliteCalendarStore {
|
||||
|
||||
sqlx::query_as!(
|
||||
CalendarObjectRow,
|
||||
r"SELECT id, ics FROM calendarobjects
|
||||
r"SELECT id, uid, ics FROM calendarobjects
|
||||
WHERE principal = ? AND cal_id = ? AND deleted_at IS NULL
|
||||
AND (last_occurence IS NULL OR ? IS NULL OR last_occurence >= date(?))
|
||||
AND (first_occurence IS NULL OR ? IS NULL OR first_occurence <= date(?))
|
||||
@@ -335,7 +336,7 @@ impl SqliteCalendarStore {
|
||||
) -> Result<CalendarObject, Error> {
|
||||
sqlx::query_as!(
|
||||
CalendarObjectRow,
|
||||
"SELECT id, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
|
||||
"SELECT id, uid, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
|
||||
principal,
|
||||
cal_id,
|
||||
object_id,
|
||||
@@ -355,7 +356,7 @@ impl SqliteCalendarStore {
|
||||
object: CalendarObject,
|
||||
overwrite: bool,
|
||||
) -> Result<(), Error> {
|
||||
let (object_id, ics) = (object.get_uid(), object.get_ics());
|
||||
let (object_id, uid, ics) = (object.get_id(), object.get_uid(), object.get_ics());
|
||||
|
||||
let first_occurence = object
|
||||
.get_first_occurence()
|
||||
@@ -374,10 +375,11 @@ impl SqliteCalendarStore {
|
||||
|
||||
(if overwrite {
|
||||
sqlx::query!(
|
||||
"REPLACE INTO calendarobjects (principal, cal_id, id, ics, first_occurence, last_occurence, etag, object_type) VALUES (?, ?, ?, ?, date(?), date(?), ?, ?)",
|
||||
"REPLACE INTO calendarobjects (principal, cal_id, id, uid, ics, first_occurence, last_occurence, etag, object_type) VALUES (?, ?, ?, ?, ?, date(?), date(?), ?, ?)",
|
||||
principal,
|
||||
cal_id,
|
||||
object_id,
|
||||
uid,
|
||||
ics,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
@@ -387,10 +389,11 @@ impl SqliteCalendarStore {
|
||||
} else {
|
||||
// If the object already exists a database error is thrown and handled in error.rs
|
||||
sqlx::query!(
|
||||
"INSERT INTO calendarobjects (principal, cal_id, id, ics, first_occurence, last_occurence, etag, object_type) VALUES (?, ?, ?, ?, date(?), date(?), ?, ?)",
|
||||
"INSERT INTO calendarobjects (principal, cal_id, id, uid, ics, first_occurence, last_occurence, etag, object_type) VALUES (?, ?, ?, ?, ?, date(?), date(?), ?, ?)",
|
||||
principal,
|
||||
cal_id,
|
||||
object_id,
|
||||
uid,
|
||||
ics,
|
||||
first_occurence,
|
||||
last_occurence,
|
||||
@@ -410,7 +413,7 @@ impl SqliteCalendarStore {
|
||||
executor: E,
|
||||
principal: &str,
|
||||
cal_id: &str,
|
||||
id: &str,
|
||||
object_id: &str,
|
||||
use_trashbin: bool,
|
||||
) -> Result<(), Error> {
|
||||
if use_trashbin {
|
||||
@@ -418,7 +421,7 @@ impl SqliteCalendarStore {
|
||||
"UPDATE calendarobjects SET deleted_at = datetime(), updated_at = datetime() WHERE (principal, cal_id, id) = (?, ?, ?)",
|
||||
principal,
|
||||
cal_id,
|
||||
id
|
||||
object_id
|
||||
)
|
||||
.execute(executor)
|
||||
.await.map_err(crate::Error::from)?;
|
||||
@@ -426,7 +429,7 @@ impl SqliteCalendarStore {
|
||||
sqlx::query!(
|
||||
"DELETE FROM calendarobjects WHERE cal_id = ? AND id = ?",
|
||||
cal_id,
|
||||
id
|
||||
object_id
|
||||
)
|
||||
.execute(executor)
|
||||
.await
|
||||
@@ -678,7 +681,7 @@ impl CalendarStore for SqliteCalendarStore {
|
||||
.await
|
||||
.map_err(crate::Error::from)?;
|
||||
|
||||
let object_id = object.get_uid().to_owned();
|
||||
let object_id = object.get_id().to_owned();
|
||||
|
||||
let calendar = Self::_get_calendar(&mut *tx, &principal, &cal_id, true).await?;
|
||||
if calendar.subscription_url.is_some() {
|
||||
|
||||
Reference in New Issue
Block a user