Help using Base SAS procedures

Bug In SAS/Connect

Reply
New Contributor
Posts: 4

Bug In SAS/Connect

This bug exists in both 9.4 and 9.2. Below are two tests.

If you run the tests and search for "len=2" or "len=1" in the log, you will find the following three outputs. The last one comes from RSubmit and is wrong.

Test 1Test 2

len=2001

len=2001

len=2002

len=1003

len=1003

len=15

This bug corrupts code containing spaces. I found this bug because an extra space is inserted into a column name, causing an SQL query to fail.

Test 1Test 2

%let k=1000;

%macro foo;
data _null_;
len = length("%sysfunc(repeat(x%bquote( ),&k.))");
put len=;
run;
%mend;

options noquotelenmax;

%foo;

data _null_;
call execute('%foo');
run;

data _null_;
call execute('signon t sascmd="!sascmdv";');
call execute('rsubmit t;');
call execute('options noquotelenmax;');
call execute('%foo');
call execute('endrsubmit;');
call execute('signoff t;');
run;

%let k=1000;

%macro foo;
data _null_;
len = length("x%sysfunc(repeat(%bquote( ),&k.))x");
put len=;
run;
%mend;

options noquotelenmax;

%foo;

data _null_;
call execute('%foo');
run;

data _null_;
call execute('signon t sascmd="!sascmdv";');
call execute('rsubmit t;');
call execute('options noquotelenmax;');
call execute('%foo');
call execute('endrsubmit;');
call execute('signoff t;');
run;

Super User
Posts: 5,429

Re: Bug In SAS/Connect

Posted in reply to GiovannaEdmonds

So, have you reported this to SAS tech support?

Data never sleeps
Trusted Advisor
Posts: 1,301

Re: Bug In SAS/Connect

Posted in reply to GiovannaEdmonds

This is not a bug, you have not programmed it correctly.  Why are you even using the call execute's?  That really only complicates things unnecessarily.

Rather than walking through how to fix this example.  If you care to share something closer to the situation you are actually dealing with (the SQL you mention...).  It would be easier to help, I feel.

New Contributor
Posts: 4

Re: Bug In SAS/Connect

Thank you for your reply. There are good reasons for using call execute, and the workarounds for this bug make compromises on those reasons. Imagine that the macro is thousands of lines long, or is user-supplied at run time. And then imagine a choreography of several such macros with potentially hundreds of RSubmits (both sequential and parallel). The value of call execute is clear. The workaround to this bug involves %include or sasautos. The drawbacks of saving the macro externally are inconvenience to the user and not being to use the version control inside enterprise guide. Furthermore, the macro is stored on the server, instead of beig encapsulating within a single EG project file, which are often stored on separate filesystems.

Trusted Advisor
Posts: 1,301

Re: Bug In SAS/Connect

Posted in reply to GiovannaEdmonds

You reasoning for using the CALL EXECUTE is to have you macro compile locally and transfer the generated SAS code/text to the remote server for execution.  I understand why you feel this should be treated as a bug, but, I also feel that your approach is mostly what is flawed.  As Linus said, the appropriate place to report bugs is with SAS Tech Support.

In your specific example, rewriting the FOO macro to something like the following resolves all your issues:

%macro foo;

data _null_;

foo = cat('x', repeat(' ', &k.), 'x');

len = length(foo);

put len=;

run;

%mend;


My recommendation would be to transfer the macro (even when compile in work on the client session) to the remote session and have it execute there.

%let k=1000;

%macro foo(session, k);

data _null_;

len = length("x%sysfunc(repeat(%bquote( ),&k.))x");

put ">>>&session. " len=;

run;

%mend;

/* transfer macro FOO to remote, for non-shared file systems using PROC UPLOAD could be used instead of inheritlib option, this is example for MP-CONNECT style rsubmit */

options dlcreatedir;

libname tmp "%sysfunc(pathname(work,l))/mstore";

proc catalog c=work.sasmacr et=macro;

copy out=tmp.sasmacr;

select foo;

run;

options noquotelenmax;

%foo(local, &k.)

signon t sascmd='!sascmd' inheritlib=(tmp);

%syslput k=&k.;

rsubmit t;

options noquotelenmax;

options mstored sasmstore=tmp;

%foo(remote, &k.);

endrsubmit;

signoff t;

data _null_;

call execute('signon t sascmd="!sascmd" inheritlib=(tmp);');

call execute('%nrstr(%syslput k=&k.Smiley Wink');

call execute('rsubmit t;');

call execute('options noquotelenmax;');

call execute('options mstored sasmstore=tmp;');

call execute('%nrstr(%foo(remote, &k.)Smiley Wink');

call execute('endrsubmit;');

call execute('signoff t;');

run;

New Contributor
Posts: 4

Re: Bug In SAS/Connect

Thank you for your reply. I am just posting here so people are aware of the bug. It's quite pernicious imo. call execute() is not a flawed approach. It is in fact the most elegant approach (if not for the bug described here). By elegant I mean it needs the fewest lines of code. The drawback with mstored is that “%syslput _user_;” is not available in 9.2, so more code is needed to hunt down all of the user’s macro variables. Imagine a dynamic environment where the users do whatever they want. (By "users" I really mean other programmers.) To give you a bit more background, my code is generated through a data step based on user input and a very complex logic. Each step, when generated, is inserted into a hash table (so they don't have to be generated in the same order as the actual execution). In the end of the data step, a hiter loop is used and call execute() is applied. As for %foo, I concocted it just to demonstrate the bug. I don't really need one thousand x's. If you have code that's written as state = "New York", the bug would have SAS run state = "New  York" instead (note the double spaces between New and York). No rewriting can avoid getting the wrong output in that case.

Ask a Question
Discussion stats
  • 5 replies
  • 341 views
  • 0 likes
  • 3 in conversation