fix(derived): carry the placement sequence in mpe_derived
Build / Build-and-ng-test (pull_request) Failing after 1m53s
Build / Build-and-test-development (pull_request) Skipped
Lighthouse Checks / lighthouse (pull_request) Successful in 21m11s

Same defect as the core review found in mp_derivedvars: the final assemble
merged the placement table by name, but that table is built in dependency
rounds and is not name ordered, so the BY-merge failed whenever the rounds
were not alphabetical, and seq was a BY-group counter rather than the
dependency order.

Each round now stamps seq=_n_+nplaced, the merge runs on the name-sorted
tables, and the result is sorted by seq.  Also guards the physical-column
in-list for a zero-column table, and checks libds exists before running.
This commit is contained in:
dc committed 2026-10-20 21:24:03 +00:00
1 parent ee5d7c678e
commit be50cb5d08
1 file changed
+25 -3
+25 -3
View File
@@ -77,7 +77,7 @@
outview=0
);
%local physlist derived_err resv_list i w left nready
%local physlist derived_err resv_list i w left nready nplaced
cyc_start cyc_cur cyc_next cyc_path cyc_seen cyc_i;
%mp_abort(iftrue= (%length(&libds)=0 or %length(&dclib)=0)
@@ -88,6 +88,10 @@
,mac=&sysmacroname
,msg=%str(Please provide an outref for the generated statements)
)
%mp_abort(iftrue= (%mf_existds(libds=&libds) ne 1)
,mac=&sysmacroname
,msg=%str(Target table not found: &libds)
)
filename &outref temp;
@@ -146,8 +150,10 @@ data work.derived_bad;
then reason='VAR_NM must be a valid SAS name';
else if verify(substr(name,1,1),'0123456789')=0
then reason='VAR_NM must not start with a digit';
%if %length(&physlist)>0 %then %do;
else if name in (%unquote(&physlist))
then reason='VAR_NM collides with a column in the target table';
%end;
else if name in (%unquote(&resv_list))
then reason='VAR_NM is reserved';
else if type not in ('C','N')
@@ -322,13 +328,15 @@ data work.derived_todo(keep=name);
set work.derived_byname;
run;
data work.derived_placed(keep=name);
data work.derived_placed(keep=name seq);
length name $32;
name='';
seq=0;
if 0;
run;
%let left=%mf_nobs(work.derived_todo);
%let nplaced=0;
%do %while (&left>0);
proc sql;
@@ -376,8 +384,15 @@ run;
)
%end;
/* seq carries the dependency order - the placement rounds are not name
ordered, so the final merge must not rely on by name alone */
data work.derived_ready;
set work.derived_ready;
seq=_n_+&nplaced;
run;
proc append base=work.derived_placed data=work.derived_ready force;
run;
%let nplaced=%eval(&nplaced+&nready);
proc sql;
delete from work.derived_todo
@@ -387,11 +402,18 @@ run;
%let left=%mf_nobs(work.derived_todo);
%end;
proc sort data=work.derived_placed;
by name;
run;
data work.derived_srt;
merge work.derived_placed(in=in1) work.derived_byname(in=in2);
by name;
if in1 and in2;
seq=_n_;
run;
proc sort data=work.derived_srt;
by seq;
run;
/**