Restoring any load that touched a special missing numeric (._ or .A-.Z) failed
in mp_stripdiffs, which writes the old value into a generated UPDATE statement.
PUT writes a special missing as its letter only, so the statement carried
"set SOME_BESTNUM =_" and PROC SQL read the bare underscore as a column name:
ERROR: The following columns were not found in the contributing tables: _.
ERROR: SOME_BESTNUM, a numeric column, can only be updated with a numeric
expression.
Every statement in the generated block then failed NOEXEC, so the revert
produced the wrong data; the service's syscc check is what surfaced it.
Fixed upstream in sasjs/core#499 (the period is now written first) and
released as 7.0.1. v7.0.0's breaking change - mf_existvarlist warns and returns
0 instead of aborting on blank input - does not affect DC: there are no direct
callers, and the full SAS suite covers the core macros that do use it.
Adds restore.test.2.sas, which seeds some_bestnum=._ on mpe_x_test, changes it
to a number through stagedata and approves it, reverts that load, approves the
reversion, and asserts the cell is back to ._ rather than blank. It fails on
6.1.4 and passes on 7.0.1.
173 lines
3.9 KiB
SAS
173 lines
3.9 KiB
SAS
/**
|
|
@file
|
|
@brief testing restore of a change to a special missing value
|
|
|
|
@details A cell holding a special missing (._ .A-.Z) and changed to an
|
|
ordinary number must be reverted to that special missing. mp_stripdiffs
|
|
writes the old value into a generated UPDATE statement, and PUT drops the
|
|
leading period of a special missing, so the statement used to be
|
|
"set SOME_BESTNUM =_" - which PROC SQL reads as a column name.
|
|
|
|
<h4> SAS Macros </h4>
|
|
@li mp_assert.sas
|
|
@li mx_execute.sas
|
|
|
|
**/
|
|
|
|
%let _program=&appLoc/services/editors/restore;
|
|
|
|
/* seed the base table with a special missing - the audit stores whatever the
|
|
base holds, so this is the value the revert has to write back */
|
|
proc sql noprint;
|
|
update &dclib..mpe_x_test set some_bestnum=._
|
|
where primary_key_field=3;
|
|
quit;
|
|
|
|
/**
|
|
* load 1 - change that cell to an ordinary number
|
|
*/
|
|
data work.sascontroltable;
|
|
action='LOAD';
|
|
message="special missing prep";
|
|
libds="&dclib..MPE_X_TEST";
|
|
output;
|
|
stop;
|
|
run;
|
|
|
|
data work.jsdata;
|
|
set &dclib..mpe_x_test(where=(primary_key_field=3)
|
|
rename=(some_date=dt2 SOME_DATETIME=dttm2 SOME_TIME=tm2)
|
|
);
|
|
/* the adapter sends these as strings */
|
|
some_date=put(dt2,date9.);
|
|
SOME_DATETIME=put(dttm2,datetime19.);
|
|
some_time=put(tm2,time.);
|
|
drop dt2 dttm2 tm2;
|
|
_____DELETE__THIS__RECORD_____='No';
|
|
some_bestnum=42;
|
|
run;
|
|
|
|
%mx_execute(&appLoc/services/editors/stagedata,
|
|
viyacontext=&defaultcontext,
|
|
inputdatasets=work.jsdata work.sascontroltable,
|
|
outlib=web1,
|
|
mdebug=&sasjs_mdebug
|
|
)
|
|
|
|
%let status=0;
|
|
data _null_;
|
|
set web1.sasparams;
|
|
if status='SUCCESS' then call symputx('status',1);
|
|
call symputx('dsid',dsid);
|
|
run;
|
|
%mp_assert(
|
|
iftrue=(&status=1 and &syscc=0),
|
|
desc=Checking the special missing change was staged,
|
|
outds=work.test_results
|
|
)
|
|
|
|
data work.sascontroltable;
|
|
ACTION='APPROVE_TABLE';
|
|
TABLE="&dsid";
|
|
DIFFTIME="%sysfunc(datetime())";
|
|
output;
|
|
stop;
|
|
run;
|
|
%mx_execute(&appLoc/services/auditors/postdata,
|
|
viyacontext=&defaultcontext,
|
|
inputdatasets=work.sascontroltable,
|
|
outlib=web3,
|
|
outref=wb3,
|
|
mdebug=&sasjs_mdebug
|
|
)
|
|
|
|
%let status=0;
|
|
data _null_;
|
|
set web3.apparams;
|
|
if response='SUCCESS!' then call symputx('status',1);
|
|
run;
|
|
%mp_assert(
|
|
iftrue=(&status=1 and &syscc=0),
|
|
desc=Checking the change was approved,
|
|
outds=work.test_results
|
|
)
|
|
|
|
/* the load reference to revert */
|
|
%let loadref=0;
|
|
data _null_;
|
|
set &dclib..mpe_submit end=last;
|
|
if last then call symputx('loadref',table_id);
|
|
run;
|
|
|
|
/**
|
|
* revert it - the old value in the diff is the special missing
|
|
*/
|
|
data work.restore_in;
|
|
load_ref="&loadref";
|
|
output;
|
|
stop;
|
|
run;
|
|
%mx_execute(&_program,
|
|
viyacontext=&defaultcontext,
|
|
inputdatasets=work.restore_in,
|
|
outlib=web1,
|
|
mdebug=&sasjs_mdebug
|
|
)
|
|
|
|
%let newref=0;
|
|
data _null_;
|
|
set web1.restore_out;
|
|
call symputx('newref',loadref);
|
|
run;
|
|
%mp_assert(
|
|
iftrue=(&newref ne 0 and &syscc=0),
|
|
desc=Checking the revert was submitted,
|
|
outds=work.test_results
|
|
)
|
|
|
|
/* approve the reversion */
|
|
data work.sascontroltable;
|
|
ACTION='APPROVE_TABLE';
|
|
TABLE="&newref";
|
|
DIFFTIME="%sysfunc(datetime())";
|
|
output;
|
|
stop;
|
|
run;
|
|
%mx_execute(&appLoc/services/auditors/postdata,
|
|
viyacontext=&defaultcontext,
|
|
inputdatasets=work.sascontroltable,
|
|
outlib=web3,
|
|
outref=wb3,
|
|
mdebug=&sasjs_mdebug
|
|
)
|
|
|
|
%let status=0;
|
|
data _null_;
|
|
set web3.apparams;
|
|
if response='SUCCESS!' then call symputx('status',1);
|
|
run;
|
|
%mp_assert(
|
|
iftrue=(&status=1 and &syscc=0),
|
|
desc=Checking the reversion was approved,
|
|
outds=work.test_results
|
|
)
|
|
|
|
/* and the cell is back to the special missing, not a number and not blank */
|
|
%let spmcheck=0;
|
|
data _null_;
|
|
set &dclib..mpe_x_test(where=(primary_key_field=3));
|
|
if some_bestnum=._ then call symputx('spmcheck',1);
|
|
putlog some_bestnum=;
|
|
run;
|
|
%mp_assert(
|
|
iftrue=(&spmcheck=1),
|
|
desc=Checking the special missing was restored,
|
|
outds=work.test_results
|
|
)
|
|
|
|
/* put the fixture back as makedata left it */
|
|
proc sql noprint;
|
|
update &dclib..mpe_x_test set some_bestnum=44
|
|
where primary_key_field=3;
|
|
quit;
|