mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-28 15:25:27 +08:00
refactor(database): make session id the primary key in sessions table
This commit is contained in:
@@ -57,7 +57,7 @@ const migrateLegacySessionNames = (db: Database): void => {
|
|||||||
if (hasSessionsTable) {
|
if (hasSessionsTable) {
|
||||||
console.log('Running migration: Merging session_names into sessions');
|
console.log('Running migration: Merging session_names into sessions');
|
||||||
db.exec(`
|
db.exec(`
|
||||||
INSERT OR REPLACE INTO sessions (session_id, provider, custom_name, created_at, updated_at)
|
INSERT INTO sessions (session_id, provider, custom_name, created_at, updated_at)
|
||||||
SELECT
|
SELECT
|
||||||
session_id,
|
session_id,
|
||||||
COALESCE(provider, 'claude'),
|
COALESCE(provider, 'claude'),
|
||||||
@@ -65,6 +65,11 @@ const migrateLegacySessionNames = (db: Database): void => {
|
|||||||
COALESCE(created_at, CURRENT_TIMESTAMP),
|
COALESCE(created_at, CURRENT_TIMESTAMP),
|
||||||
COALESCE(updated_at, CURRENT_TIMESTAMP)
|
COALESCE(updated_at, CURRENT_TIMESTAMP)
|
||||||
FROM session_names
|
FROM session_names
|
||||||
|
ON CONFLICT(session_id) DO UPDATE SET
|
||||||
|
provider = excluded.provider,
|
||||||
|
custom_name = COALESCE(excluded.custom_name, sessions.custom_name),
|
||||||
|
created_at = COALESCE(sessions.created_at, excluded.created_at),
|
||||||
|
updated_at = COALESCE(excluded.updated_at, sessions.updated_at)
|
||||||
`);
|
`);
|
||||||
db.exec('DROP TABLE session_names');
|
db.exec('DROP TABLE session_names');
|
||||||
return;
|
return;
|
||||||
@@ -245,9 +250,9 @@ const rebuildSessionsTableWithProjectSchema = (db: Database): void => {
|
|||||||
|
|
||||||
const shouldRebuild =
|
const shouldRebuild =
|
||||||
!columnNames.includes('project_path') ||
|
!columnNames.includes('project_path') ||
|
||||||
primaryKeyColumns.length !== 2 ||
|
primaryKeyColumns.length !== 1 ||
|
||||||
primaryKeyColumns[0] !== 'session_id' ||
|
primaryKeyColumns[0] !== 'session_id' ||
|
||||||
primaryKeyColumns[1] !== 'provider';
|
!columnNames.includes('provider');
|
||||||
|
|
||||||
if (!shouldRebuild) {
|
if (!shouldRebuild) {
|
||||||
addColumnToTableIfNotExists(db, 'sessions', columnNames, 'jsonl_path', 'TEXT');
|
addColumnToTableIfNotExists(db, 'sessions', columnNames, 'jsonl_path', 'TEXT');
|
||||||
@@ -299,14 +304,42 @@ const rebuildSessionsTableWithProjectSchema = (db: Database): void => {
|
|||||||
jsonl_path TEXT,
|
jsonl_path TEXT,
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (session_id, provider),
|
PRIMARY KEY (session_id),
|
||||||
FOREIGN KEY (project_path) REFERENCES projects(project_path)
|
FOREIGN KEY (project_path) REFERENCES projects(project_path)
|
||||||
ON DELETE SET NULL
|
ON DELETE SET NULL
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
db.exec(`
|
db.exec(`
|
||||||
INSERT OR REPLACE INTO sessions__new (
|
WITH source_rows AS (
|
||||||
|
SELECT
|
||||||
|
session_id,
|
||||||
|
${providerExpression} AS provider,
|
||||||
|
${customNameExpression} AS custom_name,
|
||||||
|
${projectPathExpression} AS project_path,
|
||||||
|
${jsonlPathExpression} AS jsonl_path,
|
||||||
|
${createdAtExpression} AS created_at,
|
||||||
|
${updatedAtExpression} AS updated_at,
|
||||||
|
rowid AS source_rowid
|
||||||
|
FROM sessions
|
||||||
|
WHERE session_id IS NOT NULL AND trim(session_id) <> ''
|
||||||
|
),
|
||||||
|
ranked_rows AS (
|
||||||
|
SELECT
|
||||||
|
session_id,
|
||||||
|
provider,
|
||||||
|
custom_name,
|
||||||
|
project_path,
|
||||||
|
jsonl_path,
|
||||||
|
created_at,
|
||||||
|
updated_at,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY session_id
|
||||||
|
ORDER BY datetime(COALESCE(updated_at, created_at)) DESC, source_rowid DESC
|
||||||
|
) AS session_rank
|
||||||
|
FROM source_rows
|
||||||
|
)
|
||||||
|
INSERT INTO sessions__new (
|
||||||
session_id,
|
session_id,
|
||||||
provider,
|
provider,
|
||||||
custom_name,
|
custom_name,
|
||||||
@@ -317,14 +350,14 @@ const rebuildSessionsTableWithProjectSchema = (db: Database): void => {
|
|||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
session_id,
|
session_id,
|
||||||
${providerExpression},
|
provider,
|
||||||
${customNameExpression},
|
custom_name,
|
||||||
${projectPathExpression},
|
project_path,
|
||||||
${jsonlPathExpression},
|
jsonl_path,
|
||||||
${createdAtExpression},
|
created_at,
|
||||||
${updatedAtExpression}
|
updated_at
|
||||||
FROM sessions
|
FROM ranked_rows
|
||||||
WHERE session_id IS NOT NULL AND trim(session_id) <> ''
|
WHERE session_rank = 1
|
||||||
`);
|
`);
|
||||||
db.exec('DROP TABLE sessions');
|
db.exec('DROP TABLE sessions');
|
||||||
db.exec('ALTER TABLE sessions__new RENAME TO sessions');
|
db.exec('ALTER TABLE sessions__new RENAME TO sessions');
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ export const sessionsDb = {
|
|||||||
db.prepare(
|
db.prepare(
|
||||||
`INSERT INTO sessions (session_id, provider, custom_name, project_path, jsonl_path, created_at, updated_at)
|
`INSERT INTO sessions (session_id, provider, custom_name, project_path, jsonl_path, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, COALESCE(?, CURRENT_TIMESTAMP), COALESCE(?, CURRENT_TIMESTAMP))
|
VALUES (?, ?, ?, ?, ?, COALESCE(?, CURRENT_TIMESTAMP), COALESCE(?, CURRENT_TIMESTAMP))
|
||||||
ON CONFLICT(session_id, provider) DO UPDATE SET
|
ON CONFLICT(session_id) DO UPDATE SET
|
||||||
|
provider = excluded.provider,
|
||||||
updated_at = excluded.updated_at,
|
updated_at = excluded.updated_at,
|
||||||
project_path = excluded.project_path,
|
project_path = excluded.project_path,
|
||||||
jsonl_path = excluded.jsonl_path,
|
jsonl_path = excluded.jsonl_path,
|
||||||
@@ -82,15 +83,6 @@ export const sessionsDb = {
|
|||||||
).run(customName, sessionId);
|
).run(customName, sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
createSessionName(sessionId: string, provider: string, customName: string): void {
|
|
||||||
const db = getConnection();
|
|
||||||
db.prepare(
|
|
||||||
`UPDATE sessions
|
|
||||||
SET custom_name = ?
|
|
||||||
WHERE session_id = ? AND provider = ?`
|
|
||||||
).run(customName, sessionId, provider);
|
|
||||||
},
|
|
||||||
|
|
||||||
getSessionById(sessionId: string): SessionMetadataLookupRow | null {
|
getSessionById(sessionId: string): SessionMetadataLookupRow | null {
|
||||||
const db = getConnection();
|
const db = getConnection();
|
||||||
const row = db
|
const row = db
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ CREATE TABLE IF NOT EXISTS sessions (
|
|||||||
jsonl_path TEXT,
|
jsonl_path TEXT,
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (session_id, provider),
|
PRIMARY KEY (session_id),
|
||||||
FOREIGN KEY (project_path) REFERENCES projects(project_path)
|
FOREIGN KEY (project_path) REFERENCES projects(project_path)
|
||||||
ON DELETE SET NULL
|
ON DELETE SET NULL
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
|
|||||||
Reference in New Issue
Block a user