int
saf_find_subset_relations(SAF_ParMode pmode, /* The parallel mode. */
SAF_Db *db, /* Database in which to limit the search. */
SAF_Set *sup, /* The superset to limit search to. */
SAF_Set *sub, /* The subset to limit search to. */
SAF_Cat *sup_cat, /* The collection category on the superset to limit search to. Pass
* SAF_ANY_CAT if you do not want to limit the search to any particular
* category. */
SAF_Cat *sub_cat, /* The collection category on the subset to limit search to. Pass SAF_ANY_CAT
* if you do not want to limit the search to any particular category. */
SAF_BoundMode sbmode, /* If SAF_BOUNDARY_TRUE, limit search to relations in which the subset is the
* boundary of the superset. */
SAF_BoundMode cbmode, /* If SAF_BOUNDARY_TRUE, limit search to relations in which the members of the
* subset are on the boundaries of the members of the superset. */
int *num, /* For this and the succeeding argument, (see Returned Handles). */
SAF_Rel **found /* For this and the preceding argument, (see Returned Handles). */
)
{
SAF_ENTER(saf_find_subset_relations, SAF_PRECONDITION_ERROR);
SAF_KEYMASK(SAF_Rel, key, mask);
size_t nfound;
ss_scope_t scope=SS_SCOPE_NULL;
SAF_REQUIRE(_saf_valid_pmode(pmode), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("PMODE must be valid"));
if (!_saf_is_participating_proc(pmode)) SAF_RETURN(-1);
SAF_REQUIRE(ss_file_isopen(db, NULL)>0, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("DB must be a valid database"));
SAF_REQUIRE(!sup_cat || SS_CAT(sup_cat), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("SUP_CAT must either be a valid category handle or SAF_ANY_CAT"));
SAF_REQUIRE(!sub_cat || SS_CAT(sub_cat), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("SUB_CAT must either be a valid category handle or SAF_ANY_CAT"));
SAF_REQUIRE(SS_SET(sub), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("SUB must be a valid set handle"));
SAF_REQUIRE(SS_SET(sup), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("SUP must be a valid set handle"));
SAF_REQUIRE(_saf_valid_memhints(num, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("NUM and FOUND must be compatible for the return value allocation"));
ss_file_topscope(db, &scope);
/* See if the superset's bnd_set matches the sbmode search criteria. */
if ((sbmode==SAF_BOUNDARY_TRUE && SAF_EQUIV(SS_SET_P(sup,bnd_set),sub)) || sbmode==SAF_BOUNDARY_FALSE) {
/* The sbmode search criteria matches. Continue to find the subset relations matching the other criteria. */
SAF_SEARCH(SAF_Rel, key, mask, sub, *sub);
SAF_SEARCH(SAF_Rel, key, mask, sup, *sup);
if (sup_cat) SAF_SEARCH(SAF_Rel, key, mask, sup_cat, *sup_cat);
if (sub_cat) SAF_SEARCH(SAF_Rel, key, mask, sub_cat, *sub_cat);
SAF_SEARCH(SAF_Rel, key, mask, kind, cbmode==SAF_BOUNDARY_TRUE?SAF_RELKIND_BOUND:SAF_RELKIND_EQUAL);
if (!found) {
/* Count the matches */
assert(num);
nfound = SS_NOSIZE;
ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, SS_PERS_TEST, NULL);
*num = nfound;
} else if (!*found) {
/* Find all matches; library allocates results */
nfound = SS_NOSIZE;
*found = (ss_rel_t*)ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound,
NULL, NULL);
if (num) *num = nfound;
} else {
/* Find limited matches; client allocates result buffer */
assert(num);
nfound = *num;
if (NULL==ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, (ss_pers_t*)*found,
_SAF_GLOBALS.find_detect_overflow)) {
SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
}
*num = nfound;
}
} else {
if (!found || *found) {
/* Count the matches or client allocates result buffer */
assert(num);
*num = 0;
} else {
/* library allocates results */
if (num) *num = nfound;
}
}
SAF_LEAVE(SAF_SUCCESS);
}