fix(derived): carry the placement sequence in mpe_derived
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:
1 parent
ee5d7c678e
commit
be50cb5d08
1 file changed
+25
-3
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user