Search code examples
sassas-macro

how to correctly read error code in SAS macro loop?


I'm attempting to build SAS code that looks through past logs, reruns failed reports and informs about rerun status. I'm using &syscc. macro to check whether there was an error within my rerun attempt and resetting it between each attempt. However I'm running into a problem using syscc within a macro %do loop as syscc does not show the correct error code. I.e. it didn't show any error for the first loop although it should've and then it failed to reset back to 0. ( shared the piece of code below ) . Is there alternative approach to using syscc or another way of writing the macro?

%macro rerunner();
    %do i=1 %to &numrecs;
    %put &i;
    

        /*selecting a log and code*/
        proc sql;
            select cname into :  selected_code separated by ','
            from code_logs
            where rown=&i;
        quit;   
        proc sql;
            select lname into :  selected_log separated by ','
            from code_logs
            where rown=&i;
        quit;

        /*counting errors*/
        data _null_; 
            infile "&loglocation./&selected_log."  end=last;
            input;
            if _infile_  =: 'ERROR' then error_count+1;
            if last and error_count >=1 then CALL EXECUTE('%rerun(&selected_log. ,         &selected_code.)') ;
            if last and error_count < 1 then CALL EXECUTE('%no_rerun(&selected_log.)') ;
        run;


    %end;



%mend;


%macro rerun(log,code);


    %let syscc = 0;
    %include "&codelocation./&code." ;

    %if &syscc. <= 6 %then %do;
            %success(&log.);
        %end;

    %else %do;
            %failure(&log.)
        %end;

%mend;


...
    
%rerunner();

Solution

  • As Joe mentions you seem to be falling into a classic misuse of CALL EXECUTE() to run macro code. Since the code that CALL EXECUTE() submits does not run until after the data step you also want the macro calls in the code to not run until after the data step. Otherwise the macro logic will be evaluated before the code that the macro generates has a chance to run.

    So wrap the macro call with %NRSTR(). You will notice the difference immediately in the lines of code that call execute echoes to the SAS log. Without the macro quoting the CODE that macro generates is echoed. With the macro quoting the actual macro call itself is echoed.

    Example:

    92   %macro print(ds);
    93   proc print data=&ds; run;
    94   %mend print;
    95
    96   data _null_;
    97    call execute('%print(sashelp.class)');
    98    call execute('%nrstr(%print)(sashelp.class)');
    99   run;
    
    NOTE: DATA statement used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
    
    
    NOTE: CALL EXECUTE generated line.
    1   + proc print data=sashelp.class; run;
    
    NOTE: There were 19 observations read from the data set SASHELP.CLASS.
    NOTE: PROCEDURE PRINT used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
    
    
    2   + %print(sashelp.class)
    
    NOTE: There were 19 observations read from the data set SASHELP.CLASS.
    NOTE: PROCEDURE PRINT used (Total process time):
          real time           0.00 seconds
          cpu time            0.00 seconds
    

    It does not matter for this trivial example because the macro does not have any macro logic that makes decisions about what code to run based on the results of code that the macro had generated earlier. But your %RERUN() macro does.

    Another easy way to avoid this trap is not use CALL EXECUTE. Instead write the code to a file and then use %INCLUDE to run the code at the end of the data step.

    So something like this:

    filename code temp;
    data _null_;
      set somedataset;
      file code;
      if (some condition) then put '%rerun(' somevar ')' ;
    run;
    %include code / source2;