refactor(db): separate workout plans from completed sessions

This commit is contained in:
2026-08-12 11:35:16 +02:00
parent f14c2e5827
commit 2bb4225260
16 changed files with 1222 additions and 170 deletions
+35
View File
@@ -0,0 +1,35 @@
CREATE TABLE `workout_sessions` (
`id` text PRIMARY KEY NOT NULL,
`workout_id` text,
`name` text,
`pool_length` real DEFAULT 25 NOT NULL,
`started_at` text NOT NULL,
`finished_at` text,
`total_distance` integer,
`total_duration` real,
`calories` real,
`avg_heart_rate` integer,
`source` text DEFAULT 'manual' NOT NULL,
FOREIGN KEY (`workout_id`) REFERENCES `workouts`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `workout_sessions` (`id`, `workout_id`, `name`, `pool_length`, `started_at`, `finished_at`, `total_distance`, `total_duration`, `calories`, `avg_heart_rate`, `source`)
SELECT `id`, `id`, `name`, `pool_length`, `started_at`, `finished_at`, `total_distance`, `total_duration`, `calories`, `avg_heart_rate`, `source`
FROM `workouts`
WHERE `finished_at` IS NOT NULL;
--> statement-breakpoint
ALTER TABLE `laps` RENAME COLUMN `workout_id` TO `session_id`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `started_at`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `finished_at`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `total_distance`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `total_duration`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `calories`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `avg_heart_rate`;
--> statement-breakpoint
ALTER TABLE `workouts` DROP COLUMN `source`;
+36
View File
@@ -0,0 +1,36 @@
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE `__new_laps` (
`id` text PRIMARY KEY NOT NULL,
`session_id` text NOT NULL,
`set_position` integer NOT NULL,
`rep_number` integer NOT NULL,
`distance` integer NOT NULL,
`duration` real NOT NULL,
`stroke_count` integer,
`heart_rate` integer,
`swolf` real,
FOREIGN KEY (`session_id`) REFERENCES `workout_sessions`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO `__new_laps`("id", "session_id", "set_position", "rep_number", "distance", "duration", "stroke_count", "heart_rate", "swolf") SELECT "id", "session_id", "set_position", "rep_number", "distance", "duration", "stroke_count", "heart_rate", "swolf" FROM `laps`;--> statement-breakpoint
DROP TABLE `laps`;--> statement-breakpoint
ALTER TABLE `__new_laps` RENAME TO `laps`;--> statement-breakpoint
PRAGMA foreign_keys=ON;--> statement-breakpoint
CREATE TABLE `__new_workout_sessions` (
`id` text PRIMARY KEY NOT NULL,
`workout_id` text,
`name` text,
`pool_length` real DEFAULT 25 NOT NULL,
`started_at` text NOT NULL,
`finished_at` text,
`total_distance` integer,
`total_duration` real,
`calories` real,
`avg_heart_rate` integer,
`source` text DEFAULT 'manual' NOT NULL
);
--> statement-breakpoint
INSERT INTO `__new_workout_sessions`("id", "workout_id", "name", "pool_length", "started_at", "finished_at", "total_distance", "total_duration", "calories", "avg_heart_rate", "source") SELECT "id", "workout_id", "name", "pool_length", "started_at", "finished_at", "total_distance", "total_duration", "calories", "avg_heart_rate", "source" FROM `workout_sessions`;--> statement-breakpoint
DROP TABLE `workout_sessions`;--> statement-breakpoint
ALTER TABLE `__new_workout_sessions` RENAME TO `workout_sessions`;--> statement-breakpoint
ALTER TABLE `workouts` ADD `created_at` text NOT NULL;
+397
View File
@@ -0,0 +1,397 @@
{
"version": "6",
"dialect": "sqlite",
"id": "1a621e4a-ea8a-4479-a98c-0f02fc8e14e3",
"prevId": "a9688cc9-9314-4d59-9b68-b7e202f3e3ff",
"tables": {
"laps": {
"name": "laps",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"session_id": {
"name": "workout_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"set_position": {
"name": "set_position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rep_number": {
"name": "rep_number",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"distance": {
"name": "distance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"duration": {
"name": "duration",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"stroke_count": {
"name": "stroke_count",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"heart_rate": {
"name": "heart_rate",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"swolf": {
"name": "swolf",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"laps_workout_id_workouts_id_fk": {
"name": "laps_session_id_workout_sessions_id_fk",
"tableFrom": "laps",
"tableTo": "workout_sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"sets": {
"name": "sets",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workout_id": {
"name": "workout_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"position": {
"name": "position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"stroke": {
"name": "stroke",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"distance_per_rep": {
"name": "distance_per_rep",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rep_count": {
"name": "rep_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rest_type": {
"name": "rest_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'fixed_rest'"
},
"rest_duration": {
"name": "rest_duration",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"target_time": {
"name": "target_time",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"sets_workout_id_workouts_id_fk": {
"name": "sets_workout_id_workouts_id_fk",
"tableFrom": "sets",
"tableTo": "workouts",
"columnsFrom": [
"workout_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"templates": {
"name": "templates",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
},
"json_data": {
"name": "json_data",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"is_favorite": {
"name": "is_favorite",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"workouts": {
"name": "workouts",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"template_id": {
"name": "template_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"workout_sessions": {
"name": "workout_sessions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workout_id": {
"name": "workout_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
},
"started_at": {
"name": "started_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"finished_at": {
"name": "finished_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"total_distance": {
"name": "total_distance",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"total_duration": {
"name": "total_duration",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"calories": {
"name": "calories",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"avg_heart_rate": {
"name": "avg_heart_rate",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'manual'"
}
},
"indexes": {},
"foreignKeys": {
"workout_sessions_workout_id_workouts_id_fk": {
"name": "workout_sessions_workout_id_workouts_id_fk",
"tableFrom": "workout_sessions",
"tableTo": "workouts",
"columnsFrom": [
"workout_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
+390
View File
@@ -0,0 +1,390 @@
{
"version": "6",
"dialect": "sqlite",
"id": "3e3e9dde-1e8c-4a6a-94ac-b5a750829d2b",
"prevId": "1a621e4a-ea8a-4479-a98c-0f02fc8e14e3",
"tables": {
"laps": {
"name": "laps",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"session_id": {
"name": "session_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"set_position": {
"name": "set_position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rep_number": {
"name": "rep_number",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"distance": {
"name": "distance",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"duration": {
"name": "duration",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"stroke_count": {
"name": "stroke_count",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"heart_rate": {
"name": "heart_rate",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"swolf": {
"name": "swolf",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"laps_session_id_workout_sessions_id_fk": {
"name": "laps_session_id_workout_sessions_id_fk",
"tableFrom": "laps",
"tableTo": "workout_sessions",
"columnsFrom": [
"session_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"sets": {
"name": "sets",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workout_id": {
"name": "workout_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"position": {
"name": "position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"stroke": {
"name": "stroke",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"distance_per_rep": {
"name": "distance_per_rep",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rep_count": {
"name": "rep_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"rest_type": {
"name": "rest_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'fixed_rest'"
},
"rest_duration": {
"name": "rest_duration",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"target_time": {
"name": "target_time",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"sets_workout_id_workouts_id_fk": {
"name": "sets_workout_id_workouts_id_fk",
"tableFrom": "sets",
"tableTo": "workouts",
"columnsFrom": [
"workout_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"templates": {
"name": "templates",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
},
"json_data": {
"name": "json_data",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"is_favorite": {
"name": "is_favorite",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"workout_sessions": {
"name": "workout_sessions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workout_id": {
"name": "workout_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
},
"started_at": {
"name": "started_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"finished_at": {
"name": "finished_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"total_distance": {
"name": "total_distance",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"total_duration": {
"name": "total_duration",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"calories": {
"name": "calories",
"type": "real",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"avg_heart_rate": {
"name": "avg_heart_rate",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'manual'"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"workouts": {
"name": "workouts",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"template_id": {
"name": "template_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"pool_length": {
"name": "pool_length",
"type": "real",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 25
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
+14
View File
@@ -8,6 +8,20 @@
"when": 1785854381700,
"tag": "0000_mushy_groot",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1785940781700,
"tag": "0001_workout_sessions",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1786525398056,
"tag": "0002_gifted_annihilus",
"breakpoints": true
}
]
}
+81 -2
View File
@@ -54,9 +54,88 @@ CREATE TABLE \`workouts\` (
);
`;
const m0001 = `
CREATE TABLE \`workout_sessions\` (
\`id\` text PRIMARY KEY NOT NULL,
\`workout_id\` text,
\`name\` text,
\`pool_length\` real DEFAULT 25 NOT NULL,
\`started_at\` text NOT NULL,
\`finished_at\` text,
\`total_distance\` integer,
\`total_duration\` real,
\`calories\` real,
\`avg_heart_rate\` integer,
\`source\` text DEFAULT 'manual' NOT NULL,
FOREIGN KEY (\`workout_id\`) REFERENCES \`workouts\`(\`id\`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO \`workout_sessions\` (\`id\`, \`workout_id\`, \`name\`, \`pool_length\`, \`started_at\`, \`finished_at\`, \`total_distance\`, \`total_duration\`, \`calories\`, \`avg_heart_rate\`, \`source\`)
SELECT \`id\`, \`id\`, \`name\`, \`pool_length\`, \`started_at\`, \`finished_at\`, \`total_distance\`, \`total_duration\`, \`calories\`, \`avg_heart_rate\`, \`source\`
FROM \`workouts\`
WHERE \`finished_at\` IS NOT NULL;
--> statement-breakpoint
ALTER TABLE \`laps\` RENAME COLUMN \`workout_id\` TO \`session_id\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`started_at\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`finished_at\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`total_distance\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`total_duration\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`calories\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`avg_heart_rate\`;
--> statement-breakpoint
ALTER TABLE \`workouts\` DROP COLUMN \`source\`;
`;
const m0002 = `
PRAGMA foreign_keys=OFF;--> statement-breakpoint
CREATE TABLE \`__new_laps\` (
\`id\` text PRIMARY KEY NOT NULL,
\`session_id\` text NOT NULL,
\`set_position\` integer NOT NULL,
\`rep_number\` integer NOT NULL,
\`distance\` integer NOT NULL,
\`duration\` real NOT NULL,
\`stroke_count\` integer,
\`heart_rate\` integer,
\`swolf\` real,
FOREIGN KEY (\`session_id\`) REFERENCES \`workout_sessions\`(\`id\`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
INSERT INTO \`__new_laps\`("id", "session_id", "set_position", "rep_number", "distance", "duration", "stroke_count", "heart_rate", "swolf") SELECT "id", "session_id", "set_position", "rep_number", "distance", "duration", "stroke_count", "heart_rate", "swolf" FROM \`laps\`;--> statement-breakpoint
DROP TABLE \`laps\`;--> statement-breakpoint
ALTER TABLE \`__new_laps\` RENAME TO \`laps\`;--> statement-breakpoint
PRAGMA foreign_keys=ON;--> statement-breakpoint
CREATE TABLE \`__new_workout_sessions\` (
\`id\` text PRIMARY KEY NOT NULL,
\`workout_id\` text,
\`name\` text,
\`pool_length\` real DEFAULT 25 NOT NULL,
\`started_at\` text NOT NULL,
\`finished_at\` text,
\`total_distance\` integer,
\`total_duration\` real,
\`calories\` real,
\`avg_heart_rate\` integer,
\`source\` text DEFAULT 'manual' NOT NULL
);
--> statement-breakpoint
INSERT INTO \`__new_workout_sessions\`("id", "workout_id", "name", "pool_length", "started_at", "finished_at", "total_distance", "total_duration", "calories", "avg_heart_rate", "source") SELECT "id", "workout_id", "name", "pool_length", "started_at", "finished_at", "total_distance", "total_duration", "calories", "avg_heart_rate", "source" FROM \`workout_sessions\`;--> statement-breakpoint
DROP TABLE \`workout_sessions\`;--> statement-breakpoint
ALTER TABLE \`__new_workout_sessions\` RENAME TO \`workout_sessions\`;--> statement-breakpoint
ALTER TABLE \`workouts\` ADD \`created_at\` text NOT NULL;
`;
export default {
journal,
migrations: {
m0000
m0000,
m0001,
m0002
}
}
}