External identifiers¶
Attach an industry, vendor, or application identifier to a PostProject object when another system needs to find that object by its own key. An identifier is a scheme, value, and optional qualifier; PostProject stores all three exactly as supplied and never rewrites or normalizes them.
The example attaches a camera serial number to an asset, reads the identifiers attached to that asset, and finds every object carrying the exact scheme and value:
static pp_error_code_t tag_camera_serial(pp_production_t *production,
const pp_uuid_t *asset_id,
pp_error_t **error) {
const pp_object_ref_t target = {PP_OBJECT_ASSET, *asset_id};
pp_transaction_t *transaction = NULL;
pp_external_identifier_set_t *attached = NULL;
pp_object_ref_set_t *matches = NULL;
pp_error_code_t status =
pp_production_begin_transaction(production, &transaction, error);
if (status == PP_OK) {
status = pp_transaction_add_external_identifier(
transaction, &target, "com.example.camera.serial", "A-0007", NULL,
error);
}
if (status == PP_OK) {
status = pp_transaction_commit(transaction, error);
}
if (status == PP_OK) {
status = pp_production_external_identifiers(production, &target,
&attached, error);
}
if (status == PP_OK) {
status = pp_production_find_by_external_identifier(
production, "com.example.camera.serial", "A-0007", &matches, error);
}
if (status == PP_OK) {
printf("identifiers: %llu, matching objects: %llu\n",
(unsigned long long)pp_external_identifier_set_count(attached),
(unsigned long long)pp_object_ref_set_count(matches));
}
pp_object_ref_set_release(matches);
pp_external_identifier_set_release(attached);
pp_transaction_release(transaction);
return status;
}
void tag_camera_serial(postproject::Production &production,
const postproject::Uuid &asset_id) {
const postproject::ObjectRef target{postproject::ObjectKind::asset, asset_id};
const postproject::ExternalIdentifier identifier{
"com.example.camera.serial", "A-0007", std::nullopt};
auto transaction = production.beginTransaction();
transaction.addExternalIdentifier(target, identifier);
transaction.commit();
const auto attached = production.externalIdentifiers(target);
const auto matches =
production.findByExternalIdentifier(identifier.scheme, identifier.value);
require(attached.size() == 1 && matches == std::vector{target},
"identifier lookup");
}
def tag_camera_serial(production: Production, asset_id: AssetId) -> None:
identifier = ExternalIdentifier("com.example.camera.serial", "A-0007")
with production.transaction() as transaction:
transaction.add_external_identifier(asset_id, identifier)
attached = production.external_identifiers[asset_id]
matches = production.objects_by_external_identifier[
identifier.scheme, identifier.value
]
assert attached == (identifier,)
assert matches == (asset_id,)
fn tag_camera_serial(production: &mut SqliteProduction, asset_id: AssetId) -> Result<()> {
let target = ObjectRef::Asset(asset_id);
let identifier = ExternalIdentifier::new(
IdentifierScheme::new("com.example.camera.serial")?,
"A-0007",
None,
)?;
{
let mut transaction = production.begin_transaction()?;
transaction.add_external_identifier(target, &identifier)?;
transaction.commit()?;
}
let attached = production.external_identifiers(target)?;
let matches =
production.find_by_external_identifier(identifier.scheme(), identifier.value())?;
assert_eq!(attached, vec![identifier]);
assert_eq!(matches, vec![target]);
Ok(())
}
postproject identifier add production.pproj asset "$ASSET_ID" \
com.example.camera.serial A-0007
postproject identifier list production.pproj asset "$ASSET_ID"
postproject identifier find production.pproj com.example.camera.serial A-0007
Attachment is a transactional mutation like any other: it stays pending until commit and appears in the revision feed. Removing an identifier requires the same exact scheme, value, and qualifier.
Lookup is exact. A scheme is not a namespace prefix, values are compared byte-for-byte, and a lookup may return several objects because an external system can reuse a value. Treat the result as candidates for the integration to interpret, not as proof of identity.
To refer from a host document to a PostProject object, persist a host-object binding instead; external identifiers are lookup aids and assertions, not PostProject identity.