mirror of
https://github.com/sasjs/core.git
synced 2026-06-08 12:00:21 +00:00
feat: adding tests, adding param to mfv_existsashdat, updating README
This commit is contained in:
@@ -201,7 +201,7 @@ When contributing to this library, it is therefore important to ensure that all
|
||||
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect, or the [USER](https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/lrcon/n18m1vkqmeo4esn1moikt23zhp8s.htm) library is active.
|
||||
- Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;`
|
||||
- Where global macro variables are absolutely necessary, they should make use of `&sasjs_prefix` - see mp_init.sas
|
||||
- The use of `quit;` for `proc sql` is optional unless you are looking to benefit from the timing statistics.
|
||||
- The use of `quit;` for `proc sql` is essential, to avoid `WARNING: You cannot disconnect or terminate session XXXX until the procedure completes.` when terminating CAS sessions in Viya.
|
||||
- Use [sasjs lint](https://github.com/sasjs/lint)!
|
||||
|
||||
## General Notes
|
||||
|
||||
@@ -52,5 +52,6 @@
|
||||
run;
|
||||
proc sql;
|
||||
drop table &ds;
|
||||
quit;
|
||||
|
||||
%mend mp_assert;
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mfv_existsashdat macro function
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_uid.sas
|
||||
@li mfv_existsashdat.sas
|
||||
@li mp_assert.sas
|
||||
@li mp_assertscope.sas
|
||||
|
||||
**/
|
||||
|
||||
options mprint;
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Setup: start a CAS session and stage a sashdat file in the Public caslib */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
cas mysess;
|
||||
caslib _all_ assign;
|
||||
|
||||
%let testcaslib = Public; /* change this if Public isn't available */
|
||||
proc cas;
|
||||
table.caslibInfo result=r / ;
|
||||
found = 0;
|
||||
do row over r.CASLibInfo;
|
||||
if upcase(row.Name) = upcase("&testcaslib") then found = 1;
|
||||
end;
|
||||
if found = 0 then do;
|
||||
print "ERROR: caslib &testcaslib not available";
|
||||
exit;
|
||||
end;
|
||||
quit;
|
||||
%put NOTE: Using testcaslib=&testcaslib;
|
||||
|
||||
%let tab1=T%mf_uid();
|
||||
|
||||
proc casutil;
|
||||
load data=sashelp.baseball outcaslib="&testcaslib" casout="&tab1" replace;
|
||||
save casdata="&tab1" incaslib="&testcaslib"
|
||||
casout="&tab1..sashdat" outcaslib="&testcaslib" replace;
|
||||
droptable casdata="&tab1" incaslib="&testcaslib" quiet;
|
||||
quit;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 1 - returns 1 when the sashdat file exists in the caslib;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mp_assert(
|
||||
iftrue=(%mfv_existsashdat(&testcaslib..&tab1)=1),
|
||||
desc=Test 1 - Check returns 1 for a sashdat that exists
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 2 - returns 0 when the file does not exist in the caslib;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mp_assertscope(SNAPSHOT)
|
||||
%mp_assert(
|
||||
iftrue=(%mfv_existsashdat(&testcaslib..DOESNOTEXIST_%mf_uid())=0),
|
||||
desc=Check returns 0 for a sashdat that does not exist
|
||||
)
|
||||
%mp_assertscope(COMPARE,
|
||||
desc=Check mfv_existsashdat does not leak macro variables into GLOBAL scope
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 3 - usecache= controls whether the cached dataset is reused;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* First call: populates the cache dataset work.testcache_&testcaslib */
|
||||
%let _rc=%mfv_existsashdat(&testcaslib..&tab1,outprefix=work.testcache);
|
||||
|
||||
/* Delete the sashdat from the caslib so a fresh scan would return 0 */
|
||||
proc casutil;
|
||||
deletesource casdata="&tab1..sashdat" incaslib="&testcaslib" quiet;
|
||||
quit;
|
||||
|
||||
/* usecache=1 (default): must return 1 from the cached dataset */
|
||||
%mp_assert(
|
||||
iftrue=(%mfv_existsashdat(&testcaslib..&tab1,outprefix=work.testcache)=1),
|
||||
desc=Check returns 1 from cache even after source file is deleted
|
||||
)
|
||||
|
||||
/* usecache=0: forces rescan and reflects the deletion */
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
%mfv_existsashdat(&testcaslib..&tab1,usecache=0,outprefix=work.testcache)=0
|
||||
),
|
||||
desc=Check returns 0 when usecache=0 forces a rescan after source file deleted
|
||||
)
|
||||
|
||||
%let syscc=0;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Teardown: terminate CAS session (sashdat already removed in TEST 4) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
cas mysess terminate;
|
||||
|
||||
%let syscc=0;
|
||||
@@ -69,7 +69,7 @@ quit;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 2 - load a table that does not yet exist (default srcfile=table.hdat);
|
||||
%put TEST 2 - load a table that does not yet exist (default srcfile=table.sashdat);
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mv_castabload(caslib=&testcaslib,table=&tab1,mdebug=1)
|
||||
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
%if %mfv_existsashdat(libds=casuser.sometable) %then %put yes it does!;
|
||||
|
||||
The function uses `dosubl()` to run the `table.fileinfo` action, for the
|
||||
specified library, filtering for `*.sashdat` tables. The results are stored
|
||||
in a WORK table (&outprefix._&lib). If that table already exists, it is
|
||||
queried instead, to avoid the dosubl() performance hit.
|
||||
specified library, filtering for `*.sashdat` tables.
|
||||
|
||||
IMPORTANT NOTE - The results are cached in a WORK table (&outprefix._&lib).
|
||||
If that table already exists, it is queried instead, to avoid the
|
||||
dosubl() performance hit.
|
||||
|
||||
To force a rescan, just use a new `&outprefix` value, or delete the table(s)
|
||||
before running the function.
|
||||
|
||||
@param [in] libds library.dataset
|
||||
@param [in] usecache= (1) Set to 0 to rebuild the cache
|
||||
@param [out] outprefix= (work.mfv_existsashdat)
|
||||
Used to store current HDATA tables to improve subsequent query performance.
|
||||
This reference is a prefix and is converted to `&prefix._{libref}`
|
||||
@@ -24,14 +27,14 @@
|
||||
@author Mathieu Blauw
|
||||
**/
|
||||
|
||||
%macro mfv_existsashdat(libds,outprefix=work.mfv_existsashdat
|
||||
%macro mfv_existsashdat(libds,usecache=1,outprefix=work.mfv_existsashdat
|
||||
);
|
||||
%local rc dsid name lib ds;
|
||||
%let lib=%upcase(%scan(&libds,1,'.'));
|
||||
%let ds=%upcase(%scan(&libds,-1,'.'));
|
||||
|
||||
/* if table does not exist, create it */
|
||||
%if %sysfunc(exist(&outprefix._&lib)) ne 1 %then %do;
|
||||
%if &usecache ne 1 or %sysfunc(exist(&outprefix._&lib)) ne 1 %then %do;
|
||||
%let rc=%sysfunc(dosubl(%nrstr(
|
||||
/* Read in table list (once per &lib per session) */
|
||||
proc cas;
|
||||
@@ -41,7 +44,7 @@
|
||||
quit;
|
||||
/* Only keep name, without file extension */
|
||||
data &outprefix._&lib;
|
||||
set &outprefix._&lib(where=(Name like '%.sashdat') keep=Name);
|
||||
set &outprefix._&lib(where=(upcase(Name) like '%.SASHDAT') keep=Name);
|
||||
Name=upcase(scan(Name,1,'.'));
|
||||
run;
|
||||
)));
|
||||
|
||||
+16
-5
@@ -19,7 +19,7 @@
|
||||
@param [in] caslib= CASLIB containing the source file
|
||||
@param [in] table= Name to give the in-memory CAS table
|
||||
@param [in] srcfile= (0) Source file name.ext in the caslib. If not provided,
|
||||
the code assumes that srcfile=&table..hdat
|
||||
the code assumes that srcfile=&table..sashdat
|
||||
@param [in] mdebug= (0) Set to 1 to enable verbose logging:
|
||||
- echoes resolved parameters
|
||||
- prints tableExists result
|
||||
@@ -28,7 +28,11 @@
|
||||
@returns Sets global macro variable `MV_CASTABLOAD_RC`:
|
||||
0 = table already existed (no load performed)
|
||||
1 = table was loaded & promoted successfully
|
||||
3 = action failed
|
||||
3 = action failed (including source file missing)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mfv_existsashdat.sas
|
||||
|
||||
**/
|
||||
|
||||
%macro mv_castabload(
|
||||
@@ -49,7 +53,7 @@
|
||||
%put %str(ERR)OR: caslib=, table= and srcfile= are all required;
|
||||
%return;
|
||||
%end;
|
||||
%if "&srcfile"="0" %then %let srcfile=&table..hdat;
|
||||
%if "&srcfile"="0" %then %let srcfile=&table..sashdat;
|
||||
|
||||
%if &mdebug=1 %then %do;
|
||||
%put &=caslib;
|
||||
@@ -58,6 +62,13 @@
|
||||
options mprint notes;
|
||||
%end;
|
||||
|
||||
/* ---- check source file exists ------------------------------------------ */
|
||||
%if not %mfv_existsashdat(&caslib..%scan(&srcfile,1,.)) %then %do;
|
||||
%put %str(ERR)OR: Source file "&srcfile" not found in caslib "&caslib";
|
||||
%let MV_CASTABLOAD_RC=3;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
/* ---- existence check --------------------------------------------------- */
|
||||
proc cas;
|
||||
table.tableExists result=r /
|
||||
@@ -92,11 +103,11 @@ quit;
|
||||
%put NOTE: Table &caslib..&table already loaded - skipping;
|
||||
%else %if &MV_CASTABLOAD_RC=1 %then
|
||||
%put NOTE: Table &caslib..&table loaded and promoted;
|
||||
%else %put ERROR: load failed for &caslib..&table;
|
||||
%else %put %str(ERR)OR: load failed for &caslib..&table;
|
||||
|
||||
/* ---- restore options --------------------------------------------------- */
|
||||
%if &mdebug=1 %then %do;
|
||||
options &_sysopts;
|
||||
%end;
|
||||
|
||||
%mend mv_castabload;
|
||||
%mend mv_castabload;
|
||||
Reference in New Issue
Block a user