test(derived): correct the re-add rationale, cover re-activation
Build / Build-and-ng-test (pull_request) Successful in 5m3s
Lighthouse Checks / lighthouse (pull_request) Successful in 20m24s
Build / Build-and-test-development (pull_request) Successful in 31m16s

VAR_NM carries CASE=UPCASE and the post edit hook upcases every non-delete
staged row, so a name typed in the grid reaches submit uppercase: a delete plus
a re-add of it is the same raw primary key and mpe_loader's dup check rejects
that at approval. Test 6's comment claimed the opposite, so it now states the
truth - only a stored name that is not uppercase reaches submit as two PKs, ie
a name written outside the editor.

Test 7 covers the other arm of the exclusion in the same check: setting an
inactive row active again while another active row depends on it. That starting
state is also one the hook refuses to create, so the case is defensive; both
tests prove the guard does not block the submission that repairs the data.
This commit is contained in:
dc committed 2026-10-24 11:18:12 +00:00
1 parent 6b5bf3e6be
commit 56ed429183
1 file changed
+91 -3
@@ -15,6 +15,8 @@
rule is being removed, so its variables are not validated
5. a delete and re-add of the same variable is submitted together - the
re-added active row resolves the dependency
6. an inactive row is set active again while another active row depends on
it - the re-activation is what makes the dependency resolvable
The staged loads are aborted by the post edit hook inside the child service.
An aborted load leaves its MPE_LOADS row IN PROGRESS, so each assertion
@@ -408,9 +410,13 @@ quit;
/**
* Test 6 - a delete and re-add of the same variable in one submission must be
* accepted: the re-added active row resolves the dependency. The two rows
* differ only in case, which the loader's duplicate check leaves alone, so
* the case-variant delete copy is the shape a mixed edit reaches submit with.
* accepted: the re-added active row resolves the dependency. Only a stored
* name that is not already uppercase reaches submit this way - the grid's
* CASE=UPCASE rule is a validator, and the post edit hook upcases every
* non-delete staged row, so a value typed in the grid arrives uppercase and a
* delete plus re-add of it is a duplicate primary key (rejected at approval by
* mpe_loader's raw-PK dup check). The case variant therefore pins the shape
* for a name written outside the editor.
*/
proc sql noprint;
delete from &dc_libref..mpe_derived
@@ -490,6 +496,88 @@ run;
outds=work.test_results
)
/**
* Test 7 - re-activating an inactive row must be accepted when another active
* row depends on it: the control table still holds the inactive copy, and the
* dependency resolves against the row this submission stages. Like Test 6 the
* starting state is out of band - the hook refuses to deactivate a row an
* active row depends on - so the check must not block the submission that
* repairs it.
*/
proc sql noprint;
delete from &dc_libref..mpe_derived
where upcase(libref)='DCTEST' and upcase(dsn)='DC_DERIV';
insert into &dc_libref..mpe_derived
set tx_from=0
,tx_to='31DEC5999:23:59:59'dt
,libref='DCTEST'
,dsn='DC_DERIV'
,var_nm='BASE_X'
,var_deps=''
,var_type='N'
,var_len=8
,var_fmt=''
,var_logic='1'
,active=0;
insert into &dc_libref..mpe_derived
set tx_from=0
,tx_to='31DEC5999:23:59:59'dt
,libref='DCTEST'
,dsn='DC_DERIV'
,var_nm='USES_BASE'
,var_deps='BASE_X'
,var_type='N'
,var_len=8
,var_fmt=''
,var_logic='BASE_X + 1'
,active=1;
quit;
data work.sascontroltable;
action='LOAD';
message='Re-activating a relied-on derived row should not abort';
libds="&dc_libref..MPE_DERIVED";
output;
stop;
run;
data work.jsdata;
length LIBREF $8 DSN $32 VAR_NM $32 VAR_DEPS $4000 VAR_TYPE $1
VAR_LOGIC $4000 VAR_FMT $32
_____DELETE__THIS__RECORD_____ $3;
LIBREF='DCTEST';
DSN='DC_DERIV';
VAR_NM='BASE_X';
VAR_DEPS='';
VAR_TYPE='N';
VAR_LEN=8;
VAR_FMT='';
VAR_LOGIC='1';
ACTIVE=1;
_____DELETE__THIS__RECORD_____='No';
run;
%mx_execute(&_program,
viyacontext=&defaultcontext,
inputdatasets=work.sascontroltable work.jsdata,
outlib=web7,
outref=wb7,
mdebug=&sasjs_mdebug
)
%let status7=0;
data _null_;
set web7.sasparams;
putlog (_all_)(=);
if status='SUCCESS' then call symputx('status7',1);
run;
%mp_assert(
iftrue=(&status7=1),
desc=Checking re-activating a relied-on derived row is accepted,
outds=work.test_results
)
/* tidy up so repeated runs start clean */
proc sql noprint;
delete from &dc_libref..mpe_derived