Loading db schema
This commit is contained in:
1 parent
4646dad2b8
commit
68c24dcec5
3 files changed
+231
No files matched your search
@@ -0,0 +1,65 @@
|
||||
// Числовые даты в БД JapLearn. Никаких TEXT/DATE-типов: всё — числа.
|
||||
//
|
||||
// Два формата:
|
||||
// 1. «Дата-только» — число дней от 1970-01-01 (UTC).
|
||||
// Поля: states.fsrs_opened, states.fsrs_open_day.
|
||||
// Помощники: dateToEpochDay / epochDayToIso / isoToEpochDay.
|
||||
// 2. Полный таймстамп — миллисекунды от 1970-01-01 (эпоха Unix, UTC).
|
||||
// Поля: history.timestamp, states.last_opened.
|
||||
// Помощники: dateToEpochMs / epochMsToIso / isoToEpochMs.
|
||||
// (Предположение о единице измерения — см. ниже.)
|
||||
|
||||
/** Миллисекунд в одних сутках (UTC). */
|
||||
export const DAY_MS = 86_400_000;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Формат «дата-только»: число дней от 1970-01-01.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Количество дней от 1970-01-01 (UTC) до указанной даты. */
|
||||
export function dateToEpochDay(date: Date): number {
|
||||
return Math.floor(date.getTime() / DAY_MS);
|
||||
}
|
||||
|
||||
/** Дата (полночь UTC) по номеру дня от 1970-01-01. */
|
||||
export function epochDayToDate(day: number): Date {
|
||||
return new Date(day * DAY_MS);
|
||||
}
|
||||
|
||||
/** ISO-формат 'YYYY-MM-DD' по номеру дня от 1970-01-01. */
|
||||
export function epochDayToIso(day: number): string {
|
||||
return epochDayToDate(day).toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
/** Номер дня от 1970-01-01 по ISO-дате 'YYYY-MM-DD'. */
|
||||
export function isoToEpochDay(iso: string): number {
|
||||
return Math.floor(Date.parse(`${iso}T00:00:00Z`) / DAY_MS);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Полный таймстамп: миллисекунды от 1970-01-01.
|
||||
//
|
||||
// ВАЖНО: единица измерения не зафиксирована в схеме. Здесь приняты
|
||||
// миллисекунды (нативный формат JS Date). Если десктопная версия хранит
|
||||
// секунды — поправить достаточно в одном месте (умножение на 1000).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Таймстамп (мс) для даты. */
|
||||
export function dateToEpochMs(date: Date): number {
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
/** Дата по таймстампу (мс). */
|
||||
export function epochMsToDate(ms: number): Date {
|
||||
return new Date(ms);
|
||||
}
|
||||
|
||||
/** ISO-строка (UTC) по таймстампу (мс). */
|
||||
export function epochMsToIso(ms: number): string {
|
||||
return epochMsToDate(ms).toISOString();
|
||||
}
|
||||
|
||||
/** Таймстамп (мс) по ISO-строке. */
|
||||
export function isoToEpochMs(iso: string): number {
|
||||
return Date.parse(iso);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
-- Схема базы данных JapLearn.
|
||||
-- Источник истины: /dbschema.sql (корень проекта).
|
||||
-- Здесь та же схема, но идемпотентная (CREATE TABLE IF NOT EXISTS),
|
||||
-- чтобы выполнять её при инициализации БД без ошибок на уже готовой базе.
|
||||
-- Все даты и таймстампы — числа. Поля-«даты» (fsrs_opened, fsrs_open_day)
|
||||
-- хранят число дней от 1970-01-01 (UTC), остальные — таймстампы.
|
||||
|
||||
create table if not exists custom_fields
|
||||
(
|
||||
id integer
|
||||
primary key,
|
||||
name text not null,
|
||||
identifier text not null
|
||||
);
|
||||
|
||||
create table if not exists decks
|
||||
(
|
||||
id INTEGER
|
||||
primary key autoincrement,
|
||||
name TEXT not null,
|
||||
forward TEXT not null,
|
||||
backward TEXT not null,
|
||||
filter TEXT not null
|
||||
);
|
||||
|
||||
create table if not exists settings
|
||||
(
|
||||
id text
|
||||
primary key,
|
||||
value text
|
||||
);
|
||||
|
||||
create table if not exists word_groups
|
||||
(
|
||||
id INTEGER
|
||||
primary key autoincrement,
|
||||
name TEXT not null
|
||||
);
|
||||
|
||||
create table if not exists words
|
||||
(
|
||||
id INTEGER
|
||||
primary key autoincrement,
|
||||
key TEXT not null,
|
||||
value TEXT not null,
|
||||
tags TEXT not null,
|
||||
more TEXT,
|
||||
group_id integer default 1 not null
|
||||
constraint words_word_group_id_fk
|
||||
references word_groups
|
||||
on update cascade on delete cascade
|
||||
);
|
||||
|
||||
create table if not exists history
|
||||
(
|
||||
id INTEGER
|
||||
primary key autoincrement,
|
||||
deck_id INTEGER not null
|
||||
references decks
|
||||
on delete cascade,
|
||||
word_id INTEGER not null
|
||||
references words
|
||||
on delete cascade,
|
||||
timestamp INTEGER not null,
|
||||
answer INTEGER not null,
|
||||
before INTEGER not null,
|
||||
after INTEGER not null,
|
||||
fsrs INTEGER not null
|
||||
);
|
||||
|
||||
create table if not exists states
|
||||
(
|
||||
id INTEGER
|
||||
primary key autoincrement,
|
||||
word_id INTEGER not null
|
||||
references words
|
||||
on delete cascade,
|
||||
deck_id INTEGER
|
||||
references decks
|
||||
on delete cascade,
|
||||
score INTEGER default 1 not null,
|
||||
last_opened integer not null,
|
||||
fsrs_opened integer not null,
|
||||
fsrs_memory integer not null,
|
||||
fsrs_open_day integer not null
|
||||
);
|
||||
Reference in new issue
Block a user