06-04-2015 11:41 PM
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 1||Test 2|
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 1||Test 2|
06-05-2015 09:40 AM
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.
06-06-2015 01:40 AM
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.
06-07-2015 12:34 PM
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:
foo = cat('x', repeat(' ', &k.), 'x');
len = length(foo);
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.
%macro foo(session, k);
len = length("x%sysfunc(repeat(%bquote( ),&k.))x");
put ">>>&session. " len=;
/* 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 */
libname tmp "%sysfunc(pathname(work,l))/mstore";
proc catalog c=work.sasmacr et=macro;
signon t sascmd='!sascmd' inheritlib=(tmp);
options mstored sasmstore=tmp;
call execute('signon t sascmd="!sascmd" inheritlib=(tmp);');
call execute('%nrstr(%syslput k=&k.');
call execute('rsubmit t;');
call execute('options noquotelenmax;');
call execute('options mstored sasmstore=tmp;');
call execute('%nrstr(%foo(remote, &k.)');
call execute('signoff t;');
06-08-2015 01:42 AM
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.