653 {
654 if (
record.series_uid.empty()) {
655 return make_error<int64_t>(-1, "Series Instance UID is required",
656 "storage");
657 }
658
659 if (
record.series_uid.length() > 64) {
660 return make_error<int64_t>(
661 -1, "Series Instance UID exceeds maximum length of 64 characters",
662 "storage");
663 }
664
665 if (
record.study_pk <= 0) {
666 return make_error<int64_t>(-1, "Valid study_pk is required", "storage");
667 }
668
669 const char* sql = R"(
670 INSERT INTO series (
671 study_pk, series_uid, modality, series_number,
672 series_description, body_part_examined, station_name,
673 updated_at
674 ) VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
675 ON CONFLICT(series_uid) DO UPDATE SET
676 study_pk = excluded.study_pk,
677 modality = excluded.modality,
678 series_number = excluded.series_number,
679 series_description = excluded.series_description,
680 body_part_examined = excluded.body_part_examined,
681 station_name = excluded.station_name,
682 updated_at = datetime('now')
683 RETURNING series_pk;
684 )";
685
686 sqlite3_stmt* stmt = nullptr;
687 auto rc = sqlite3_prepare_v2(
db_, sql, -1, &stmt,
nullptr);
688 if (rc != SQLITE_OK) {
689 return make_error<int64_t>(
690 rc,
691 kcenon::pacs::compat::format("Failed to prepare statement: {}",
692 sqlite3_errmsg(
db_)),
693 "storage");
694 }
695
696 sqlite3_bind_int64(stmt, 1,
record.study_pk);
697 sqlite3_bind_text(stmt, 2,
record.series_uid.c_str(), -1, SQLITE_TRANSIENT);
698 sqlite3_bind_text(stmt, 3,
record.modality.c_str(), -1, SQLITE_TRANSIENT);
699
700 if (
record.series_number.has_value()) {
701 sqlite3_bind_int(stmt, 4, *
record.series_number);
702 } else {
703 sqlite3_bind_null(stmt, 4);
704 }
705
706 sqlite3_bind_text(stmt, 5,
record.series_description.c_str(), -1,
707 SQLITE_TRANSIENT);
708 sqlite3_bind_text(stmt, 6,
record.body_part_examined.c_str(), -1,
709 SQLITE_TRANSIENT);
710 sqlite3_bind_text(stmt, 7,
record.station_name.c_str(), -1,
711 SQLITE_TRANSIENT);
712
713 rc = sqlite3_step(stmt);
714 if (rc != SQLITE_ROW) {
715 auto error_msg = sqlite3_errmsg(
db_);
716 sqlite3_finalize(stmt);
717 return make_error<int64_t>(
718 rc, kcenon::pacs::compat::format("Failed to upsert series: {}", error_msg),
719 "storage");
720 }
721
722 auto pk = sqlite3_column_int64(stmt, 0);
723 sqlite3_finalize(stmt);
724 return pk;
725}