This commit is contained in:
lougeniac64 2020-12-10 17:49:08 -05:00 коммит произвёл Mark Hammond
Родитель b054d0ece9
Коммит 02592aad3d
7 изменённых файлов: 1349 добавлений и 2 удалений

Просмотреть файл

@ -61,7 +61,6 @@ CREATE TABLE IF NOT EXISTS credit_cards_data (
cc_exp_month INTEGER,
cc_exp_year INTEGER,
cc_type TEXT NOT NULL,
-- cc_exp TEXT NOT NULL, -- text format of the expiration date e.g. "[cc_exp_year]-[cc_exp_month]"
time_created INTEGER NOT NULL,
time_last_used INTEGER,
@ -79,7 +78,6 @@ CREATE TABLE IF NOT EXISTS credit_cards_mirror (
cc_exp_month INTEGER,
cc_exp_year INTEGER,
cc_type TEXT NOT NULL,
-- cc_exp TEXT NOT NULL, -- text format of the expiration date e.g. "[cc_exp_year]-[cc_exp_month]"
time_created INTEGER NOT NULL,
time_last_used INTEGER,

Просмотреть файл

@ -0,0 +1,27 @@
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.
CREATE TEMP TABLE addresses_sync_staging (
guid TEXT NOT NULL PRIMARY KEY,
given_name TEXT NOT NULL,
additional_name TEXT NOT NULL,
family_name TEXT NOT NULL,
organization TEXT NOT NULL,
street_address TEXT NOT NULL,
address_level3 TEXT NOT NULL,
address_level2 TEXT NOT NULL,
address_level1 TEXT NOT NULL,
postal_code TEXT NOT NULL,
country TEXT NOT NULL,
tel TEXT NOT NULL,
email TEXT NOT NULL,
time_created INTEGER NOT NULL,
time_last_used INTEGER,
time_last_modified INTEGER NOT NULL,
times_used INTEGER NOT NULL DEFAULT 0
);
CREATE TEMP TABLE addresses_tombstone_sync_staging (
guid TEXT NOT NULL PRIMARY KEY
);

Просмотреть файл

@ -74,6 +74,7 @@ pub const CREDIT_CARD_COMMON_VALS: &str = "
#[allow(dead_code)]
const CREATE_SHARED_SCHEMA_SQL: &str = include_str!("../../sql/create_shared_schema.sql");
const CREATE_SHARED_TRIGGERS_SQL: &str = include_str!("../../sql/create_shared_triggers.sql");
const CREATE_SYNC_TEMP_TABLES_SQL: &str = include_str!("../../sql/create_sync_temp_tables.sql");
#[allow(dead_code)]
pub fn init(db: &Connection) -> Result<()> {
@ -94,3 +95,9 @@ fn create(db: &Connection) -> Result<()> {
Ok(())
}
pub fn create_empty_sync_temp_tables(db: &Connection) -> Result<()> {
log::debug!("Initializing sync temp tables");
db.execute_batch(CREATE_SYNC_TEMP_TABLES_SQL)?;
Ok(())
}

Просмотреть файл

@ -8,6 +8,7 @@
pub mod db;
pub mod error;
pub mod sync;
// Expose stuff needed by the uniffi generated code.
use crate::db::models::address::*;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,89 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
pub mod incoming;
use crate::error::*;
use rusqlite::Row;
use serde::Serialize;
use serde_derive::*;
use types::Timestamp;
type Record = crate::sync::Record<RecordData>;
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default)]
#[serde(rename_all = "camelCase")]
#[serde(default)]
pub struct RecordData {
pub given_name: String,
pub additional_name: String,
pub family_name: String,
pub organization: String,
pub street_address: String,
pub address_level3: String,
pub address_level2: String,
pub address_level1: String,
pub postal_code: String,
pub country: String,
pub tel: String,
pub email: String,
pub time_created: Timestamp,
pub time_last_used: Timestamp,
pub time_last_modified: Timestamp,
pub times_used: i64,
pub sync_change_counter: Option<i64>,
}
impl RecordData {
pub fn from_row(row: &Row<'_>, column_prefix: &str) -> Result<RecordData> {
Ok(RecordData {
given_name: row
.get::<_, String>(format!("{}{}", column_prefix, "given_name").as_str())?,
additional_name: row
.get::<_, String>(format!("{}{}", column_prefix, "additional_name").as_str())?,
family_name: row
.get::<_, String>(format!("{}{}", column_prefix, "family_name").as_str())?,
organization: row
.get::<_, String>(format!("{}{}", column_prefix, "organization").as_str())?,
street_address: row
.get::<_, String>(format!("{}{}", column_prefix, "street_address").as_str())?,
address_level3: row
.get::<_, String>(format!("{}{}", column_prefix, "address_level3").as_str())?,
address_level2: row
.get::<_, String>(format!("{}{}", column_prefix, "address_level2").as_str())?,
address_level1: row
.get::<_, String>(format!("{}{}", column_prefix, "address_level1").as_str())?,
postal_code: row
.get::<_, String>(format!("{}{}", column_prefix, "postal_code").as_str())?,
country: row.get::<_, String>(format!("{}{}", column_prefix, "country").as_str())?,
tel: row.get::<_, String>(format!("{}{}", column_prefix, "tel").as_str())?,
email: row.get::<_, String>(format!("{}{}", column_prefix, "email").as_str())?,
time_created: row.get(format!("{}{}", column_prefix, "time_created").as_str())?,
time_last_used: row.get(format!("{}{}", column_prefix, "time_last_used").as_str())?,
time_last_modified: row
.get(format!("{}{}", column_prefix, "time_last_modified").as_str())?,
times_used: row.get(format!("{}{}", column_prefix, "times_used").as_str())?,
sync_change_counter: row
.get(format!("{}{}", column_prefix, "sync_change_counter").as_str())
.ok(),
})
}
}

Просмотреть файл

@ -0,0 +1,157 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
pub mod address;
// pub mod credit_card;
use serde::Serialize;
use serde_derive::*;
use sync_guid::Guid as SyncGuid;
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default)]
#[serde(rename_all = "camelCase")]
pub struct Record<T> {
#[serde(rename = "id", default)]
pub guid: SyncGuid,
#[serde(flatten)]
data: T,
}
impl<T> Record<T> {
fn new(guid: SyncGuid, data: T) -> Record<T> {
Record { guid, data }
}
}
// Helpers for tests
#[cfg(test)]
pub mod test {
use crate::db::{schema::create_empty_sync_temp_tables, test::new_mem_db, AutofillDb};
pub fn new_syncable_mem_db() -> AutofillDb {
let _ = env_logger::try_init();
let db = new_mem_db();
create_empty_sync_temp_tables(&db).expect("should work");
db
}
}
/// The distinct states of records to be synced which determine the `IncomingAction` to be taken.
#[derive(Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum IncomingState<T> {
// Only the incoming record exists. An associated local or mirror record doesn't exist.
IncomingOnly {
guid: SyncGuid,
incoming: T,
},
// The incoming record is a tombstone.
IncomingTombstone {
guid: SyncGuid,
local: Option<T>,
has_local_changes: bool,
has_local_tombstone: bool,
},
// The incoming record has an associated local record.
HasLocal {
guid: SyncGuid,
incoming: T,
merged: Record<T>,
has_local_changes: bool,
},
// The incoming record doesn't have an associated local record with the same GUID.
// A local record with the same data but a different GUID has been located.
HasLocalDupe {
guid: SyncGuid,
dupe_guid: SyncGuid,
merged: Record<T>,
},
// The incoming record doesn't have an associated local or local duplicate record but does
// have a local tombstone.
NonDeletedIncoming {
guid: SyncGuid,
incoming: T,
},
}
/// The distinct incoming sync actions to be preformed for incoming records.
#[derive(Debug, PartialEq)]
#[allow(clippy::large_enum_variant)]
pub enum IncomingAction<T> {
DeleteLocalRecord {
guid: SyncGuid,
},
TakeMergedRecord {
new_record: Record<T>,
},
UpdateLocalGuid {
old_guid: SyncGuid,
dupe_guid: SyncGuid,
new_record: Record<T>,
},
TakeRemote {
new_record: Record<T>,
},
DeleteLocalTombstone {
remote_record: Record<T>,
},
DoNothing,
}
/// Given an `IncomingState` returns the `IncomingAction` that should be performed.
pub fn plan_incoming<T>(s: IncomingState<T>) -> IncomingAction<T> {
match s {
IncomingState::IncomingOnly { guid, incoming } => IncomingAction::TakeRemote {
new_record: Record::<T>::new(guid, incoming),
},
IncomingState::IncomingTombstone {
guid,
local,
has_local_changes,
has_local_tombstone,
} => match local {
Some(_) => {
// Note: On desktop, when there's a local record for an incoming tombstone, a local tombstone
// would created. But we don't actually need to create a local tombstone here. If we did it would
// immediately be deleted after being uploaded to the server.
if has_local_changes || has_local_tombstone {
IncomingAction::DoNothing
} else {
IncomingAction::DeleteLocalRecord {
guid: SyncGuid::new(&guid),
}
}
}
None => IncomingAction::DoNothing,
},
IncomingState::HasLocal {
guid,
incoming,
merged,
has_local_changes,
} => match has_local_changes {
true => IncomingAction::TakeMergedRecord { new_record: merged },
false => IncomingAction::TakeRemote {
new_record: Record::<T>::new(guid, incoming),
},
},
IncomingState::HasLocalDupe {
guid,
dupe_guid,
merged,
} => IncomingAction::UpdateLocalGuid {
old_guid: guid,
dupe_guid,
new_record: merged,
},
IncomingState::NonDeletedIncoming { guid, incoming } => {
IncomingAction::DeleteLocalTombstone {
remote_record: Record::<T>::new(guid, incoming),
}
}
}
}