diff --git a/sas/sasjs/services/editors/stagedata.test.4.sas b/sas/sasjs/services/editors/stagedata.test.4.sas index ee7701d..b35d416 100644 --- a/sas/sasjs/services/editors/stagedata.test.4.sas +++ b/sas/sasjs/services/editors/stagedata.test.4.sas @@ -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