feat: publish derived images into existing captures

This commit is contained in:
fy59 2026-08-27 08:24:30 +02:00
parent 4b611ca723
commit 3bfbfc0534
3 changed files with 365 additions and 68 deletions

View file

@ -505,6 +505,11 @@ Lardon3DProjectDbResult lardon3d_project_db_register_image_asset(
Lardon3DProjectDb *database, Lardon3DProjectDb *database,
const unsigned char sha256[LARDON3D_PROJECT_DB_SHA256_SIZE], const char *asset_path, const unsigned char sha256[LARDON3D_PROJECT_DB_SHA256_SIZE], const char *asset_path,
uint64_t size_bytes, int64_t created_at, Lardon3DProjectDbImageAsset *asset); uint64_t size_bytes, int64_t created_at, Lardon3DProjectDbImageAsset *asset);
Lardon3DProjectDbResult lardon3d_project_db_publish_derived_capture_image(
Lardon3DProjectDb *database, uint64_t capture_id, uint64_t asset_id,
const char *original_name, const char *source_path, uint64_t producer_task_id,
int64_t imported_at, Lardon3DProjectDbImageRegisterStatus *status,
Lardon3DProjectDbImage *image);
Lardon3DProjectDbResult lardon3d_project_db_load_image(Lardon3DProjectDb *database, Lardon3DProjectDbResult lardon3d_project_db_load_image(Lardon3DProjectDb *database,
uint64_t image_id, uint64_t image_id,
Lardon3DProjectDbImage *image, Lardon3DProjectDbImage *image,

View file

@ -2584,6 +2584,55 @@ static Lardon3DProjectDbResult ensure_capture_for_registered_image_locked(
return result; return result;
} }
static Lardon3DProjectDbResult insert_or_find_image_locked(
Lardon3DProjectDb *database, uint64_t scanset_id, uint64_t asset_id,
const char *original_name, const char *source_path, uint64_t producer_task_id,
int64_t imported_at, int *inserted, uint64_t *image_id) {
sqlite3_stmt *statement = NULL;
Lardon3DProjectDbResult result = prepare(
database,
"INSERT INTO images(scanset_id,asset_id,original_name,source_path,producer_task_id,"
"imported_at) VALUES(?1,?2,?3,?4,?5,?6) ON CONFLICT(scanset_id,asset_id) DO NOTHING",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)scanset_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)asset_id);
(void)sqlite3_bind_text(statement, 3, original_name, -1, SQLITE_TRANSIENT);
(void)sqlite3_bind_text(statement, 4, source_path, -1, SQLITE_TRANSIENT);
if (producer_task_id) {
(void)sqlite3_bind_int64(statement, 5, (sqlite3_int64)producer_task_id);
} else {
(void)sqlite3_bind_null(statement, 5);
}
(void)sqlite3_bind_int64(statement, 6, imported_at);
result = step_done(database, statement, "insert logical image");
statement = NULL;
}
if (result == LARDON3D_PROJECT_DB_OK) {
*inserted = sqlite3_changes(database->connection);
result = prepare(database, "SELECT image_id FROM images WHERE scanset_id=?1 AND asset_id=?2",
&statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)scanset_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)asset_id);
int code = sqlite3_step(statement);
if (code == SQLITE_ROW) {
sqlite3_int64 stored_image_id = sqlite3_column_int64(statement, 0);
if (stored_image_id <= 0) {
result = LARDON3D_PROJECT_DB_CORRUPT;
} else {
*image_id = (uint64_t)stored_image_id;
}
} else {
result = code == SQLITE_DONE ? LARDON3D_PROJECT_DB_CORRUPT
: sqlite_result(database, code, "load registered image");
}
(void)sqlite3_finalize(statement);
}
return result;
}
Lardon3DProjectDbResult lardon3d_project_db_register_image_asset( Lardon3DProjectDbResult lardon3d_project_db_register_image_asset(
Lardon3DProjectDb *database, Lardon3DProjectDb *database,
const unsigned char sha256[LARDON3D_PROJECT_DB_SHA256_SIZE], const char *asset_path, const unsigned char sha256[LARDON3D_PROJECT_DB_SHA256_SIZE], const char *asset_path,
@ -2717,48 +2766,16 @@ Lardon3DProjectDbResult lardon3d_project_db_register_image(
(void)sqlite3_finalize(statement); (void)sqlite3_finalize(statement);
statement = NULL; statement = NULL;
} }
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(
database,
"INSERT INTO "
"images(scanset_id,asset_id,original_name,source_path,producer_task_id,imported_at) "
"VALUES(?1,?2,?3,?4,?5,?6) ON CONFLICT(scanset_id,asset_id) DO NOTHING",
&statement);
}
int inserted = 0; int inserted = 0;
uint64_t image_id = 0;
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)scanset_id); result = insert_or_find_image_locked(database, scanset_id, (uint64_t)asset_id, original_name,
(void)sqlite3_bind_int64(statement, 2, asset_id); source_path, producer_task_id, imported_at, &inserted,
(void)sqlite3_bind_text(statement, 3, original_name, -1, SQLITE_TRANSIENT); &image_id);
(void)sqlite3_bind_text(statement, 4, source_path, -1, SQLITE_TRANSIENT);
if (producer_task_id) {
(void)sqlite3_bind_int64(statement, 5, (sqlite3_int64)producer_task_id);
} else {
(void)sqlite3_bind_null(statement, 5);
}
(void)sqlite3_bind_int64(statement, 6, imported_at);
result = step_done(database, statement, "insert logical image");
statement = NULL;
inserted = sqlite3_changes(database->connection);
}
sqlite3_int64 image_id = 0;
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(database, "SELECT image_id FROM images WHERE scanset_id=?1 AND asset_id=?2",
&statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)scanset_id);
(void)sqlite3_bind_int64(statement, 2, asset_id);
int code = sqlite3_step(statement);
if (code != SQLITE_ROW || (image_id = sqlite3_column_int64(statement, 0)) <= 0) {
result = LARDON3D_PROJECT_DB_CORRUPT;
}
(void)sqlite3_finalize(statement);
statement = NULL;
} }
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
result = ensure_capture_for_registered_image_locked(database, scanset_id, (uint64_t)asset_id, result = ensure_capture_for_registered_image_locked(database, scanset_id, (uint64_t)asset_id,
(uint64_t)image_id); image_id);
} }
if (result == LARDON3D_PROJECT_DB_OK) { if (result == LARDON3D_PROJECT_DB_OK) {
result = execute(database, "COMMIT", "commit image register"); result = execute(database, "COMMIT", "commit image register");
@ -2772,7 +2789,164 @@ Lardon3DProjectDbResult lardon3d_project_db_register_image(
} }
*status = inserted == 1 ? LARDON3D_PROJECT_DB_IMAGE_REGISTERED *status = inserted == 1 ? LARDON3D_PROJECT_DB_IMAGE_REGISTERED
: LARDON3D_PROJECT_DB_IMAGE_ALREADY_PRESENT; : LARDON3D_PROJECT_DB_IMAGE_ALREADY_PRESENT;
return lardon3d_project_db_load_image(database, (uint64_t)image_id, image, return lardon3d_project_db_load_image(database, image_id, image,
&(Lardon3DProjectDbImageAsset){0});
}
Lardon3DProjectDbResult lardon3d_project_db_publish_derived_capture_image(
Lardon3DProjectDb *database, uint64_t capture_id, uint64_t asset_id,
const char *original_name, const char *source_path, uint64_t producer_task_id,
int64_t imported_at, Lardon3DProjectDbImageRegisterStatus *status,
Lardon3DProjectDbImage *image) {
if (!database || !valid_catalog_id(capture_id) || !valid_catalog_id(asset_id) ||
!valid_original_name(original_name) ||
!bounded_text(source_path, LARDON3D_PROJECT_DB_PATH_CAPACITY, false) ||
(producer_task_id != 0 && !valid_task_id(producer_task_id)) || imported_at < 0 || !status ||
!image) {
return LARDON3D_PROJECT_DB_INVALID_ARGUMENT;
}
memset(image, 0, sizeof(*image));
*status = LARDON3D_PROJECT_DB_IMAGE_REGISTERED;
(void)pthread_mutex_lock(&database->mutex);
Lardon3DProjectDbResult result =
execute(database, "BEGIN IMMEDIATE", "begin derived capture image publication");
sqlite3_stmt *statement = NULL;
sqlite3_int64 scanset_id = 0;
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(database, "SELECT scanset_id FROM captures WHERE capture_id=?1", &statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
int code = sqlite3_step(statement);
if (code == SQLITE_DONE) {
result = LARDON3D_PROJECT_DB_NOT_FOUND;
} else if (code != SQLITE_ROW || (scanset_id = sqlite3_column_int64(statement, 0)) <= 0) {
result = code == SQLITE_ROW ? LARDON3D_PROJECT_DB_CORRUPT
: sqlite_result(database, code, "load derived image capture");
}
(void)sqlite3_finalize(statement);
statement = NULL;
}
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(database, "SELECT 1 FROM image_assets WHERE asset_id=?1", &statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)asset_id);
int code = sqlite3_step(statement);
if (code == SQLITE_DONE) {
result = LARDON3D_PROJECT_DB_NOT_FOUND;
} else if (code != SQLITE_ROW) {
result = sqlite_result(database, code, "load derived image asset");
}
(void)sqlite3_finalize(statement);
statement = NULL;
}
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(
database,
"SELECT 1 FROM asset_derivations d JOIN capture_assets p "
"ON p.asset_id=d.parent_asset_id WHERE d.child_asset_id=?1 AND p.capture_id=?2",
&statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)asset_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)capture_id);
int code = sqlite3_step(statement);
if (code == SQLITE_DONE) {
result = LARDON3D_PROJECT_DB_CONSTRAINT;
} else if (code != SQLITE_ROW) {
result = sqlite_result(database, code, "load derived image provenance");
}
(void)sqlite3_finalize(statement);
statement = NULL;
}
int inserted = 0;
uint64_t image_id = 0;
if (result == LARDON3D_PROJECT_DB_OK) {
result = insert_or_find_image_locked(database, (uint64_t)scanset_id, asset_id, original_name,
source_path, producer_task_id, imported_at, &inserted,
&image_id);
}
sqlite3_int64 mapped_capture_id = 0;
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(database, "SELECT capture_id FROM capture_images WHERE image_id=?1", &statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)image_id);
int code = sqlite3_step(statement);
if (code == SQLITE_ROW) {
mapped_capture_id = sqlite3_column_int64(statement, 0);
if (mapped_capture_id <= 0) {
result = LARDON3D_PROJECT_DB_CORRUPT;
} else if ((uint64_t)mapped_capture_id != capture_id) {
result = LARDON3D_PROJECT_DB_CONSTRAINT;
}
} else if (code != SQLITE_DONE) {
result = sqlite_result(database, code, "find derived image capture");
}
(void)sqlite3_finalize(statement);
statement = NULL;
}
if (result == LARDON3D_PROJECT_DB_OK) {
result = prepare(database, "SELECT role FROM capture_assets WHERE capture_id=?1 AND asset_id=?2",
&statement);
}
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)asset_id);
int code = sqlite3_step(statement);
if (code == SQLITE_ROW) {
if (sqlite3_column_int(statement, 0) != LARDON3D_DB_CAPTURE_ASSET_DERIVED) {
result = LARDON3D_PROJECT_DB_CONSTRAINT;
}
} else if (code == SQLITE_DONE) {
(void)sqlite3_finalize(statement);
statement = NULL;
result = prepare(database,
"INSERT INTO capture_assets(capture_id,asset_id,role) VALUES(?1,?2,?3)",
&statement);
if (result == LARDON3D_PROJECT_DB_OK) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)asset_id);
(void)sqlite3_bind_int(statement, 3, LARDON3D_DB_CAPTURE_ASSET_DERIVED);
result = step_done(database, statement, "attach derived capture asset");
statement = NULL;
}
} else {
result = sqlite_result(database, code, "find derived capture asset");
}
if (statement) {
(void)sqlite3_finalize(statement);
statement = NULL;
}
}
if (result == LARDON3D_PROJECT_DB_OK && mapped_capture_id == 0) {
result = prepare(database, "INSERT INTO capture_images(capture_id,image_id) VALUES(?1,?2)",
&statement);
}
if (result == LARDON3D_PROJECT_DB_OK && mapped_capture_id == 0) {
(void)sqlite3_bind_int64(statement, 1, (sqlite3_int64)capture_id);
(void)sqlite3_bind_int64(statement, 2, (sqlite3_int64)image_id);
result = step_done(database, statement, "attach derived capture image");
statement = NULL;
}
if (result == LARDON3D_PROJECT_DB_OK) {
result = execute(database, "COMMIT", "commit derived capture image publication");
}
if (result != LARDON3D_PROJECT_DB_OK) {
(void)execute(database, "ROLLBACK", "rollback derived capture image publication");
}
(void)pthread_mutex_unlock(&database->mutex);
if (result != LARDON3D_PROJECT_DB_OK) {
return result;
}
*status = inserted == 1 ? LARDON3D_PROJECT_DB_IMAGE_REGISTERED
: LARDON3D_PROJECT_DB_IMAGE_ALREADY_PRESENT;
return lardon3d_project_db_load_image(database, image_id, image,
&(Lardon3DProjectDbImageAsset){0}); &(Lardon3DProjectDbImageAsset){0});
} }

View file

@ -1105,42 +1105,76 @@ static bool run_test(void) {
unsigned char developed_hash[LARDON3D_PROJECT_DB_SHA256_SIZE] = {6}; unsigned char developed_hash[LARDON3D_PROJECT_DB_SHA256_SIZE] = {6};
char developed_asset_path[LARDON3D_PROJECT_DB_PATH_CAPACITY]; char developed_asset_path[LARDON3D_PROJECT_DB_PATH_CAPACITY];
asset_path_for_hash(developed_hash, developed_asset_path); asset_path_for_hash(developed_hash, developed_asset_path);
Lardon3DProjectDbImageAsset developed_asset;
Lardon3DProjectDbImage developed_image; Lardon3DProjectDbImage developed_image;
CHECK(lardon3d_project_db_register_image( CHECK(lardon3d_project_db_register_image_asset(database, developed_hash, developed_asset_path, 3,
database, replacement_scanset.scanset_id, developed_hash, developed_asset_path, 3, 23, &developed_asset) ==
"developed.png", "/source/developed.png", 0, 23, &identity_status, LARDON3D_PROJECT_DB_OK);
&developed_image) == LARDON3D_PROJECT_DB_OK); CHECK(lardon3d_project_db_publish_derived_capture_image(
Lardon3DProjectDbCapture developed_capture; database, capture.capture_id, developed_asset.asset_id, "developed.png",
"/source/developed.png", 0, 23, &identity_status, &developed_image) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
Lardon3DProjectDbAssetDerivation derivation = {
.parent_asset_id = raw_asset.asset_id,
.child_asset_id = developed_asset.asset_id,
.kind = LARDON3D_DB_ASSET_DERIVATION_GENERIC_VERSIONED,
.version = 1,
.created_at = 24};
memset(derivation.parameter_fingerprint, 0xA5, sizeof(derivation.parameter_fingerprint));
CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DProjectDbCapture capture_page_before[8];
size_t capture_count_before = 0;
CHECK(lardon3d_project_db_list_captures(database, replacement_scanset.scanset_id, 0,
capture_page_before, 8, &capture_count_before) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, capture.capture_id, developed_asset.asset_id, "developed.png",
"/source/developed.png", 0, 23, &identity_status, &developed_image) ==
LARDON3D_PROJECT_DB_OK &&
identity_status == LARDON3D_PROJECT_DB_IMAGE_REGISTERED &&
developed_image.scanset_id == capture.scanset_id &&
developed_image.asset_id == developed_asset.asset_id);
Lardon3DProjectDbCapture mapped_developed_capture;
CHECK(lardon3d_project_db_find_capture_for_image(database, developed_image.image_id, CHECK(lardon3d_project_db_find_capture_for_image(database, developed_image.image_id,
&developed_capture) == LARDON3D_PROJECT_DB_OK); &mapped_developed_capture) ==
lardon3d_project_db_close(database); LARDON3D_PROJECT_DB_OK &&
database = NULL; mapped_developed_capture.capture_id == capture.capture_id);
char remove_developed_capture[256]; Lardon3DProjectDbCapture capture_page_after[8];
CHECK(snprintf(remove_developed_capture, sizeof(remove_developed_capture), size_t capture_count_after = 0;
"PRAGMA foreign_keys=ON;DELETE FROM captures WHERE capture_id=%llu", CHECK(lardon3d_project_db_list_captures(database, replacement_scanset.scanset_id, 0,
(unsigned long long)developed_capture.capture_id) > 0); capture_page_after, 8, &capture_count_after) ==
CHECK(execute_test_sql(database_path, remove_developed_capture)); LARDON3D_PROJECT_DB_OK &&
CHECK(lardon3d_project_db_open(database_path, &database, error) == LARDON3D_PROJECT_DB_OK); capture_count_after == capture_count_before);
CHECK(lardon3d_project_db_attach_capture_asset(
database, capture.capture_id, developed_image.asset_id,
LARDON3D_DB_CAPTURE_ASSET_DERIVED) == LARDON3D_PROJECT_DB_OK);
Lardon3DProjectDbCaptureAsset capture_assets[3]; Lardon3DProjectDbCaptureAsset capture_assets[3];
size_t capture_asset_count = 0; size_t capture_asset_count = 0;
CHECK(lardon3d_project_db_list_capture_assets(database, capture.capture_id, 0, capture_assets, CHECK(lardon3d_project_db_list_capture_assets(database, capture.capture_id, 0, capture_assets,
3, &capture_asset_count) == 3, &capture_asset_count) ==
LARDON3D_PROJECT_DB_OK && LARDON3D_PROJECT_DB_OK &&
capture_asset_count == 3); capture_asset_count == 3);
bool found_original_source = false;
bool found_derived_asset = false;
for (size_t i = 0; i < capture_asset_count; ++i) {
found_original_source = found_original_source ||
(capture_assets[i].asset_id == pair_image.asset_id &&
capture_assets[i].role == LARDON3D_DB_CAPTURE_ASSET_SOURCE);
found_derived_asset = found_derived_asset ||
(capture_assets[i].asset_id == developed_asset.asset_id &&
capture_assets[i].role == LARDON3D_DB_CAPTURE_ASSET_DERIVED);
}
CHECK(found_original_source && found_derived_asset);
CHECK(lardon3d_project_db_attach_capture_image(database, capture.capture_id, CHECK(lardon3d_project_db_attach_capture_image(database, capture.capture_id,
pair_image.image_id) == LARDON3D_PROJECT_DB_CONSTRAINT); pair_image.image_id) == LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_attach_capture_image(database, other_capture.capture_id, CHECK(lardon3d_project_db_attach_capture_image(database, other_capture.capture_id,
pair_image.image_id) == pair_image.image_id) ==
LARDON3D_PROJECT_DB_CONSTRAINT); LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_attach_capture_image(database, capture.capture_id,
developed_image.image_id) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_find_capture_for_image(database, pair_image.image_id, CHECK(lardon3d_project_db_find_capture_for_image(database, pair_image.image_id,
&mapped_capture) == LARDON3D_PROJECT_DB_OK && &mapped_capture) == LARDON3D_PROJECT_DB_OK &&
mapped_capture.capture_id == capture.capture_id); mapped_capture.capture_id == capture.capture_id);
CHECK(lardon3d_project_db_get_selected_capture_image(database, capture.capture_id,
&selected_image) ==
LARDON3D_PROJECT_DB_OK &&
selected_image == pair_image.image_id);
CHECK(lardon3d_project_db_set_selected_capture_image(database, capture.capture_id, CHECK(lardon3d_project_db_set_selected_capture_image(database, capture.capture_id,
pair_image.image_id) == pair_image.image_id) ==
LARDON3D_PROJECT_DB_OK); LARDON3D_PROJECT_DB_OK);
@ -1163,27 +1197,111 @@ static bool run_test(void) {
&selected_image) == &selected_image) ==
LARDON3D_PROJECT_DB_OK && LARDON3D_PROJECT_DB_OK &&
selected_image == developed_image.image_id); selected_image == developed_image.image_id);
CHECK(query_integer(database_path, "SELECT count(*) FROM asset_derivations", 0)); Lardon3DProjectDbImage republished_developed_image;
Lardon3DProjectDbAssetDerivation derivation = { CHECK(lardon3d_project_db_publish_derived_capture_image(
.parent_asset_id = raw_asset.asset_id, database, capture.capture_id, developed_asset.asset_id, "developed.png",
.child_asset_id = developed_image.asset_id, "/source/developed.png", 0, 23, &identity_status, &republished_developed_image) ==
.kind = LARDON3D_DB_ASSET_DERIVATION_GENERIC_VERSIONED, LARDON3D_PROJECT_DB_OK &&
.version = 1, identity_status == LARDON3D_PROJECT_DB_IMAGE_ALREADY_PRESENT &&
.created_at = 24}; republished_developed_image.image_id == developed_image.image_id);
memset(derivation.parameter_fingerprint, 0xA5, sizeof(derivation.parameter_fingerprint)); CHECK(lardon3d_project_db_get_selected_capture_image(database, capture.capture_id,
&selected_image) ==
LARDON3D_PROJECT_DB_OK &&
selected_image == developed_image.image_id);
size_t capture_count_republished = 0;
CHECK(lardon3d_project_db_list_captures(database, replacement_scanset.scanset_id, 0,
capture_page_after, 8, &capture_count_republished) ==
LARDON3D_PROJECT_DB_OK &&
capture_count_republished == capture_count_after);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, UINT64_C(999999), developed_asset.asset_id, "developed.png",
"/source/developed.png", 0, 23, &identity_status, &republished_developed_image) ==
LARDON3D_PROJECT_DB_NOT_FOUND);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, capture.capture_id, UINT64_C(999999), "missing.png", "/source/missing.png",
0, 23, &identity_status, &republished_developed_image) == LARDON3D_PROJECT_DB_NOT_FOUND);
unsigned char other_developed_hash[LARDON3D_PROJECT_DB_SHA256_SIZE] = {7};
char other_developed_asset_path[LARDON3D_PROJECT_DB_PATH_CAPACITY];
asset_path_for_hash(other_developed_hash, other_developed_asset_path);
Lardon3DProjectDbImageAsset other_developed_asset;
CHECK(lardon3d_project_db_register_image_asset(database, other_developed_hash,
other_developed_asset_path, 4, 25,
&other_developed_asset) ==
LARDON3D_PROJECT_DB_OK);
derivation.child_asset_id = other_developed_asset.asset_id;
derivation.parent_asset_id = raw_asset.asset_id;
derivation.created_at = 25;
CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) == CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) ==
LARDON3D_PROJECT_DB_OK); LARDON3D_PROJECT_DB_OK);
Lardon3DProjectDbImage other_developed_image;
uint64_t image_count_before_cross_capture = 0;
CHECK(lardon3d_project_db_count_images(database, replacement_scanset.scanset_id,
&image_count_before_cross_capture) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, other_capture.capture_id, other_developed_asset.asset_id, "other-developed.png",
"/source/other-developed.png", 0, 25, &identity_status, &other_developed_image) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
uint64_t image_count_after_cross_capture = 0;
CHECK(lardon3d_project_db_count_images(database, replacement_scanset.scanset_id,
&image_count_after_cross_capture) ==
LARDON3D_PROJECT_DB_OK &&
image_count_after_cross_capture == image_count_before_cross_capture);
Lardon3DProjectDbCaptureAsset other_capture_assets[1];
size_t other_capture_asset_count = 0;
CHECK(lardon3d_project_db_list_capture_assets(database, other_capture.capture_id, 0,
other_capture_assets, 1,
&other_capture_asset_count) ==
LARDON3D_PROJECT_DB_OK &&
other_capture_asset_count == 0);
unsigned char other_raw_hash[LARDON3D_PROJECT_DB_SHA256_SIZE] = {8};
char other_raw_asset_path[LARDON3D_PROJECT_DB_PATH_CAPACITY];
asset_path_for_hash(other_raw_hash, other_raw_asset_path);
Lardon3DProjectDbImageAsset other_raw_asset;
CHECK(lardon3d_project_db_register_image_asset(database, other_raw_hash, other_raw_asset_path, 5,
26, &other_raw_asset) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_attach_capture_asset(
database, other_capture.capture_id, other_raw_asset.asset_id,
LARDON3D_DB_CAPTURE_ASSET_SOURCE) == LARDON3D_PROJECT_DB_OK);
unsigned char owned_developed_hash[LARDON3D_PROJECT_DB_SHA256_SIZE] = {9};
char owned_developed_asset_path[LARDON3D_PROJECT_DB_PATH_CAPACITY];
asset_path_for_hash(owned_developed_hash, owned_developed_asset_path);
Lardon3DProjectDbImageAsset owned_developed_asset;
CHECK(lardon3d_project_db_register_image_asset(database, owned_developed_hash,
owned_developed_asset_path, 6, 27,
&owned_developed_asset) ==
LARDON3D_PROJECT_DB_OK);
derivation.parent_asset_id = other_raw_asset.asset_id;
derivation.child_asset_id = owned_developed_asset.asset_id;
derivation.created_at = 27;
CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, other_capture.capture_id, owned_developed_asset.asset_id,
"owned-developed.png", "/source/owned-developed.png", 0, 27, &identity_status,
&other_developed_image) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_publish_derived_capture_image(
database, capture.capture_id, owned_developed_asset.asset_id, "owned-developed.png",
"/source/owned-developed.png", 0, 27, &identity_status, &republished_developed_image) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_find_capture_for_image(database, other_developed_image.image_id,
&mapped_developed_capture) ==
LARDON3D_PROJECT_DB_OK &&
mapped_developed_capture.capture_id == other_capture.capture_id);
Lardon3DProjectDbAssetDerivation loaded_derivation; Lardon3DProjectDbAssetDerivation loaded_derivation;
CHECK(lardon3d_project_db_load_asset_derivation(database, developed_image.asset_id, CHECK(lardon3d_project_db_load_asset_derivation(database, developed_asset.asset_id,
&loaded_derivation) == LARDON3D_PROJECT_DB_OK && &loaded_derivation) == LARDON3D_PROJECT_DB_OK &&
loaded_derivation.parent_asset_id == raw_asset.asset_id && loaded_derivation.parent_asset_id == raw_asset.asset_id &&
loaded_derivation.version == 1 && loaded_derivation.version == 1 &&
memcmp(loaded_derivation.parameter_fingerprint, derivation.parameter_fingerprint, memcmp(loaded_derivation.parameter_fingerprint, derivation.parameter_fingerprint,
sizeof(derivation.parameter_fingerprint)) == 0); sizeof(derivation.parameter_fingerprint)) == 0);
derivation.child_asset_id = developed_asset.asset_id;
derivation.parent_asset_id = pair_image.asset_id; derivation.parent_asset_id = pair_image.asset_id;
CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) == CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) ==
LARDON3D_PROJECT_DB_CONSTRAINT); LARDON3D_PROJECT_DB_CONSTRAINT);
derivation.parent_asset_id = developed_image.asset_id; derivation.parent_asset_id = developed_asset.asset_id;
CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) == CHECK(lardon3d_project_db_record_asset_derivation(database, &derivation) ==
LARDON3D_PROJECT_DB_INVALID_ARGUMENT); LARDON3D_PROJECT_DB_INVALID_ARGUMENT);