Faster migrations, recalculate fixes point order, egg seed guard
Migrations: - Batch PRAGMA table_info per table instead of N separate hasColumn calls - Reduced IPC calls from ~22 to ~10 per startup - Egg product_units seed only runs once (checks COUNT first) - Removed unused hasColumn function Recalculation: - recalculateSession now re-orders points by timestamp - Assigns seq = 1,2,3... in timestamp order - Only updates if order is wrong (skips if already correct) - Fixes tracks where points were recorded out of order
This commit is contained in:
parent
23db25dc8c
commit
606481103c
2 changed files with 49 additions and 54 deletions
|
|
@ -807,25 +807,15 @@ window.DB.updateSessionBike = updateSessionBike;
|
|||
|
||||
// JS-side migrations — safe for any DB state (checks before altering)
|
||||
async function runMigrations() {
|
||||
async function hasColumn(table, col) {
|
||||
const info = await select(`PRAGMA table_info(${table})`);
|
||||
return info.some(r => r.name === col);
|
||||
}
|
||||
if (!(await hasColumn("products", "composition"))) {
|
||||
await execute("ALTER TABLE products ADD COLUMN composition TEXT");
|
||||
}
|
||||
if (!(await hasColumn("products", "name_lower"))) {
|
||||
await execute("ALTER TABLE products ADD COLUMN name_lower TEXT");
|
||||
}
|
||||
if (!(await hasColumn("gps_points", "seq"))) {
|
||||
await execute("ALTER TABLE gps_points ADD COLUMN seq INTEGER");
|
||||
}
|
||||
// Batch column checks — one PRAGMA per table instead of N separate IPC calls
|
||||
const productCols = (await select("PRAGMA table_info(products)")).map(r => r.name);
|
||||
const addProdCol = async (col, type) => { if (!productCols.includes(col)) await execute(`ALTER TABLE products ADD COLUMN ${col} ${type}`); };
|
||||
await addProdCol("composition", "TEXT");
|
||||
await addProdCol("name_lower", "TEXT");
|
||||
await addProdCol("nutrients_guessed", "INTEGER DEFAULT 0");
|
||||
|
||||
if (!(await hasColumn("products", "nutrients_guessed"))) {
|
||||
await execute("ALTER TABLE products ADD COLUMN nutrients_guessed INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
console.log("[db.js] base migrations done, starting cooking_methods...");
|
||||
const gpsCols = (await select("PRAGMA table_info(gps_points)")).map(r => r.name);
|
||||
if (!gpsCols.includes("seq")) await execute("ALTER TABLE gps_points ADD COLUMN seq INTEGER");
|
||||
|
||||
// --- Cooking methods table ---
|
||||
await execute(`CREATE TABLE IF NOT EXISTS cooking_methods (
|
||||
|
|
@ -865,23 +855,14 @@ async function runMigrations() {
|
|||
console.log("[db.js] Seeded 6 cooking methods");
|
||||
}
|
||||
|
||||
// --- Recipes table: add missing columns ---
|
||||
if (!(await hasColumn("recipes", "cooking_method_id"))) {
|
||||
await execute("ALTER TABLE recipes ADD COLUMN cooking_method_id INTEGER REFERENCES cooking_methods(id)");
|
||||
}
|
||||
if (!(await hasColumn("recipes", "created_at"))) {
|
||||
await execute("ALTER TABLE recipes ADD COLUMN created_at TEXT DEFAULT (datetime('now'))");
|
||||
}
|
||||
// Ensure servings column exists (Rust creates it as INTEGER, we need REAL for half-portions)
|
||||
// Column already exists from Rust, so we leave it as is.
|
||||
// --- Recipes + ingredients: batch column checks ---
|
||||
const recipeCols = (await select("PRAGMA table_info(recipes)")).map(r => r.name);
|
||||
if (!recipeCols.includes("cooking_method_id")) await execute("ALTER TABLE recipes ADD COLUMN cooking_method_id INTEGER");
|
||||
if (!recipeCols.includes("created_at")) await execute("ALTER TABLE recipes ADD COLUMN created_at TEXT DEFAULT (datetime('now'))");
|
||||
|
||||
// --- Recipe ingredients: add missing columns ---
|
||||
if (!(await hasColumn("recipe_ingredients", "custom_name"))) {
|
||||
await execute("ALTER TABLE recipe_ingredients ADD COLUMN custom_name TEXT");
|
||||
}
|
||||
if (!(await hasColumn("recipe_ingredients", "cooking_method_id"))) {
|
||||
await execute("ALTER TABLE recipe_ingredients ADD COLUMN cooking_method_id INTEGER REFERENCES cooking_methods(id)");
|
||||
}
|
||||
const riCols = (await select("PRAGMA table_info(recipe_ingredients)")).map(r => r.name);
|
||||
if (!riCols.includes("custom_name")) await execute("ALTER TABLE recipe_ingredients ADD COLUMN custom_name TEXT");
|
||||
if (!riCols.includes("cooking_method_id")) await execute("ALTER TABLE recipe_ingredients ADD COLUMN cooking_method_id INTEGER");
|
||||
|
||||
// --- Serving units table ---
|
||||
await execute(`CREATE TABLE IF NOT EXISTS serving_units (
|
||||
|
|
@ -902,12 +883,9 @@ async function runMigrations() {
|
|||
)`);
|
||||
|
||||
// --- Add unit columns to food_log ---
|
||||
if (!(await hasColumn("food_log", "unit_id"))) {
|
||||
await execute("ALTER TABLE food_log ADD COLUMN unit_id INTEGER");
|
||||
}
|
||||
if (!(await hasColumn("food_log", "unit_amount"))) {
|
||||
await execute("ALTER TABLE food_log ADD COLUMN unit_amount REAL");
|
||||
}
|
||||
const flCols = (await select("PRAGMA table_info(food_log)")).map(r => r.name);
|
||||
if (!flCols.includes("unit_id")) await execute("ALTER TABLE food_log ADD COLUMN unit_id INTEGER");
|
||||
if (!flCols.includes("unit_amount")) await execute("ALTER TABLE food_log ADD COLUMN unit_amount REAL");
|
||||
|
||||
// Seed serving_units if empty
|
||||
const suCnt = await select("SELECT COUNT(*) as cnt FROM serving_units");
|
||||
|
|
@ -928,19 +906,20 @@ async function runMigrations() {
|
|||
console.log("[db.js] Seeded 5 serving units");
|
||||
}
|
||||
|
||||
// Seed product_units for eggs: link products with "яйц" AND "кур" to unit 1 (шт), 60g each
|
||||
// Seed product_units for eggs (one-time)
|
||||
try {
|
||||
const eggProducts = await select(
|
||||
`SELECT id FROM products WHERE name_lower LIKE '%яйц%' AND name_lower LIKE '%кур%'`
|
||||
);
|
||||
for (const ep of eggProducts) {
|
||||
await execute(
|
||||
`INSERT OR IGNORE INTO product_units (product_id, unit_id, grams_per_unit)
|
||||
VALUES (?1, 1, 60)`, [ep.id]
|
||||
const puCnt = await select("SELECT COUNT(*) as cnt FROM product_units");
|
||||
if (puCnt[0].cnt === 0) {
|
||||
const eggProducts = await select(
|
||||
`SELECT id FROM products WHERE name_lower LIKE '%яйц%' AND name_lower LIKE '%кур%'`
|
||||
);
|
||||
}
|
||||
if (eggProducts.length > 0) {
|
||||
console.log(`[db.js] Linked ${eggProducts.length} egg products to шт unit`);
|
||||
for (const ep of eggProducts) {
|
||||
await execute(
|
||||
`INSERT OR IGNORE INTO product_units (product_id, unit_id, grams_per_unit)
|
||||
VALUES (?1, 1, 60)`, [ep.id]
|
||||
);
|
||||
}
|
||||
if (eggProducts.length > 0) console.log(`[db.js] Linked ${eggProducts.length} egg products`);
|
||||
}
|
||||
} catch (e) { console.error("[db.js] egg unit seeding error:", e); }
|
||||
|
||||
|
|
@ -959,9 +938,8 @@ async function runMigrations() {
|
|||
)`);
|
||||
|
||||
// Add bike_id column to gps_sessions
|
||||
if (!(await hasColumn("gps_sessions", "bike_id"))) {
|
||||
await execute("ALTER TABLE gps_sessions ADD COLUMN bike_id INTEGER");
|
||||
}
|
||||
const gsCols = (await select("PRAGMA table_info(gps_sessions)")).map(r => r.name);
|
||||
if (!gsCols.includes("bike_id")) await execute("ALTER TABLE gps_sessions ADD COLUMN bike_id INTEGER");
|
||||
|
||||
// Seed default bike if table is empty
|
||||
const bikeCnt = await select("SELECT COUNT(*) as cnt FROM bikes");
|
||||
|
|
|
|||
|
|
@ -876,6 +876,23 @@ GPS.recalculateSession = async function(sessionId) {
|
|||
const points = await DB.getGpsPoints(sessionId);
|
||||
if (points.length < 2) return null;
|
||||
|
||||
// Fix point ordering: re-assign seq by timestamp
|
||||
const sorted = points.slice().sort((a, b) => new Date(a.ts) - new Date(b.ts));
|
||||
let needsReorder = false;
|
||||
for (let i = 0; i < sorted.length; i++) {
|
||||
if (sorted[i].seq !== i + 1) { needsReorder = true; break; }
|
||||
}
|
||||
if (needsReorder) {
|
||||
for (let i = 0; i < sorted.length; i++) {
|
||||
await window.__TAURI__.core.invoke("plugin:sql|execute", {
|
||||
db: "sqlite:baldav.db",
|
||||
query: "UPDATE gps_points SET seq = ?1 WHERE session_id = ?2 AND ts = ?3",
|
||||
values: [i + 1, sessionId, sorted[i].ts],
|
||||
});
|
||||
}
|
||||
console.log(`[GPS] Reordered ${sorted.length} points for session ${sessionId}`);
|
||||
}
|
||||
|
||||
// Get user weight: latest weight log, or profile, or 80
|
||||
const latestW = await DB.getLatestWeight();
|
||||
const profile = await DB.getFullProfile();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue