Fix proposal preparation derivation transaction

This commit is contained in:
fy59 2026-09-18 05:27:47 +02:00
parent a856451875
commit f57682790d
2 changed files with 41 additions and 8 deletions

View file

@ -923,18 +923,14 @@ TrainlogStatus trainlog_web_sessions_save_json(TrainlogDatabase *database,
if ((preparation_id == NULL || preparation_id[0] == '\0') && source_proposal != NULL) {
if (sqlite3_prepare_v2(
database->connection,
"UPDATE session_preparations SET source_proposal_id=?1,source_payload_sha256=?2 "
"WHERE preparation_id=?3 AND EXISTS(SELECT 1 FROM ai_session_draft_imports i WHERE "
"i.draft_id=?1 AND i.payload_sha256=?2)",
"SELECT 1 FROM ai_session_draft_imports WHERE draft_id=?1 AND payload_sha256=?2",
-1,
&statement,
NULL) != SQLITE_OK ||
sqlite3_bind_text(statement, 1, source_proposal, -1, SQLITE_TRANSIENT) != SQLITE_OK ||
sqlite3_bind_text(statement, 2, source_fingerprint, -1, SQLITE_TRANSIENT) !=
SQLITE_OK ||
sqlite3_bind_text(statement, 3, actual_preparation, -1, SQLITE_TRANSIENT) !=
SQLITE_OK ||
sqlite3_step(statement) != SQLITE_DONE || sqlite3_changes(database->connection) != 1) {
sqlite3_step(statement) != SQLITE_ROW) {
status = TRAINLOG_STATUS_CONFLICT;
goto rollback;
}
@ -964,7 +960,7 @@ TrainlogStatus trainlog_web_sessions_save_json(TrainlogDatabase *database,
statement = NULL;
} else if (sqlite3_prepare_v2(
database->connection,
"INSERT INTO session_preparations VALUES(?1,?2,?3,?3,?4,'local',NULL,NULL)",
"INSERT INTO session_preparations VALUES(?1,?2,?3,?3,?4,'local',?5,?6)",
-1,
&statement,
NULL) != SQLITE_OK ||
@ -973,6 +969,14 @@ TrainlogStatus trainlog_web_sessions_save_json(TrainlogDatabase *database,
sqlite3_bind_text(statement, 2, revision, -1, SQLITE_TRANSIENT) != SQLITE_OK ||
sqlite3_bind_text(statement, 3, now, -1, SQLITE_TRANSIENT) != SQLITE_OK ||
sqlite3_bind_text(statement, 4, editing_state, -1, SQLITE_TRANSIENT) != SQLITE_OK ||
(source_proposal == NULL
? sqlite3_bind_null(statement, 5)
: sqlite3_bind_text(statement, 5, source_proposal, -1, SQLITE_TRANSIENT)) !=
SQLITE_OK ||
(source_fingerprint == NULL
? sqlite3_bind_null(statement, 6)
: sqlite3_bind_text(statement, 6, source_fingerprint, -1, SQLITE_TRANSIENT)) !=
SQLITE_OK ||
sqlite3_step(statement) != SQLITE_DONE) {
status = TRAINLOG_STATUS_DATABASE_ERROR;
goto rollback;

View file

@ -44,6 +44,13 @@ static bool creation_replay_revision_and_pagination(void) {
"{\"title\":\"Réordonnée\",\"session_type\":\"training\","
"\"planned_for\":null,\"notes\":null,\"editing_state\":\"draft\","
"\"occurrences\":[]}";
static const char DERIVED_BODY[] =
"{\"title\":\"Derived\",\"session_type\":\"training\","
"\"planned_for\":null,\"notes\":null,\"editing_state\":\"draft\","
"\"occurrences\":[],\"source_proposal_id\":"
"\"aid_11111111-1111-4111-8111-111111111111\","
"\"source_payload_sha256\":"
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"}";
TrainlogDatabase *database = NULL;
TrainlogWebSessionsPageQuery query = {TRAINLOG_WEB_SESSION_PREPARATIONS, 0U, 1U, "échappée"};
char *created = NULL;
@ -70,6 +77,17 @@ static bool creation_replay_revision_and_pagination(void) {
TRAINLOG_TRACKING_REPS,
TRAINLOG_RECORDING_SETS,
0U) == TRAINLOG_STATUS_OK);
CHECK(sqlite3_exec(database->connection,
"INSERT INTO ai_session_drafts(draft_id,created_at,session_type,title) "
"VALUES('aid_11111111-1111-4111-8111-111111111111','2026-09-18T00:00:00Z',"
"'training','Source');"
"INSERT INTO ai_session_draft_imports VALUES("
"last_insert_rowid(),'aid_11111111-1111-4111-8111-111111111111',"
"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"
"'2026-09-18T00:00:00Z');",
NULL,
NULL,
NULL) == SQLITE_OK);
CHECK(trainlog_web_sessions_save_json(database,
NULL,
"",
@ -122,6 +140,17 @@ static bool creation_replay_revision_and_pagination(void) {
&updated_size) == TRAINLOG_STATUS_OK);
CHECK(updated_size > 0U);
CHECK(scalar(database, "SELECT COUNT(*) FROM session_preparation_revisions") == 2);
CHECK(trainlog_web_sessions_save_json(database,
NULL,
"",
"request-derived-1",
DERIVED_BODY,
strlen(DERIVED_BODY),
&detail,
&detail_size) == TRAINLOG_STATUS_OK);
CHECK(scalar(database,
"SELECT COUNT(*) FROM session_preparations WHERE source_proposal_id="
"'aid_11111111-1111-4111-8111-111111111111'") == 1);
free(detail);
detail = NULL;
detail_size = 0U;
@ -133,7 +162,7 @@ static bool creation_replay_revision_and_pagination(void) {
strlen(UPDATE_BODY),
&detail,
&detail_size) == TRAINLOG_STATUS_CONFLICT);
CHECK(scalar(database, "SELECT COUNT(*) FROM session_preparation_revisions") == 2);
CHECK(scalar(database, "SELECT COUNT(*) FROM session_preparation_revisions") == 3);
free(created);
free(replayed);
free(detail);