>case _triggerlevel = 1 > begin transaction > private plError > plError = .f. > release gaErrors > public gaErrors[1, 12] > aused(laUsed) > lcExact = set('EXACT') > lcANSI = set('ANSI') > lcDeleted = set('DELETED') > lcError = on('ERROR') > set exact on > set ansi on > set deleted on > on error LogRIError(ERROR(),MESSAGE()) &&plError = .t. any procedure that finds a violation of RI must return FALSE if an error occurs set plError to TRUE (in LogRIError() this is) any procedure must return return m.Success and !m.plError && where Success is the return value of the procedure each function must at some points check for Success (and plError) and avoid executing some parts RI procedures will never be called recursively (ie cascade) if you observe the rules above eg, if a delete on an Order returns FALSE, the trigger on the OrderLine will never be executed/called sample function Something local Success Success = TRUE .... do case case !m.Success or m.plError case !triggerOpen(...) Success = FALSE otherwise ..... ... && must close here without testing for success, the open was ok if( !TriggerClose(...) ) Success = FALSE endif endcase return m.Success and !m.plError endfunc >* If we're being called recursively and an error has occurred, exit now. > >case vartype(m.plError) = "L" and m.plError > return this should be return FALSE, and may be the cause >endcase >** First search in the parent column > >lnTParent = ascan(laRelations, m.lcTable, m.lnTParent + 1, ; > m.lnRelations , cnPARENTCOL, 8) > >do while m.lnTParent > 0 and not m.plError > lnI = m.lnTParent > ** Some staff > lnTParent = ascan(laRelations, m.lcTable, m.lnI + 1, ; > m.lnRelations, cnPARENTCOL, 8) >enddo >>