mirror of
https://github.com/sasjs/core.git
synced 2026-06-08 20:10:20 +00:00
feat: castabload macro
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mv_castabload macro
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_uid.sas
|
||||
@li mp_assert.sas
|
||||
@li mp_assertscope.sas
|
||||
@li mv_castabload.sas
|
||||
@li mv_createfile.sas
|
||||
|
||||
**/
|
||||
|
||||
options mprint;
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Setup: start a CAS session and stage a source 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();
|
||||
%let tab2=T%mf_uid();
|
||||
%let tab3=T%mf_uid();
|
||||
|
||||
/* Create a SASHDAT source file in the Public caslib from SASHELP.BASEBALL
|
||||
so that subsequent LOAD operations have something real to pick up. */
|
||||
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;
|
||||
|
||||
/* And a second hdat, with a name different from the table name, so that we
|
||||
can exercise the explicit srcfile= path. */
|
||||
proc casutil;
|
||||
load data=sashelp.cars outcaslib="&testcaslib" casout="&tab2" replace;
|
||||
save casdata="&tab2" incaslib="&testcaslib"
|
||||
casout="src_&tab2..sashdat" outcaslib="&testcaslib" replace;
|
||||
droptable casdata="&tab2" incaslib="&testcaslib" quiet;
|
||||
quit;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 1 - missing required parameters returns without setting RC to 0/1;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%let MV_CASTABLOAD_RC=;
|
||||
%mv_castabload(caslib=,table=,srcfile=)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&MV_CASTABLOAD_RC=3),
|
||||
desc=Check RC=3 (initial/failure value) when required params are missing
|
||||
)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 2 - load a table that does not yet exist (default srcfile=table.hdat);
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mv_castabload(caslib=&testcaslib,table=&tab1,mdebug=1)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&MV_CASTABLOAD_RC=1),
|
||||
desc=Check RC=1 when table is loaded and promoted for the first time
|
||||
)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 3 - calling again for the same table should be a no-op (RC=0);
|
||||
/* also verify no scope leakage of macro variables */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mp_assertscope(SNAPSHOT)
|
||||
|
||||
%mv_castabload(caslib=&testcaslib,table=&tab1,mdebug=1)
|
||||
|
||||
%mp_assertscope(COMPARE,
|
||||
desc=Check mv_castabload does not leak macro variables into GLOBAL scope,
|
||||
ignorelist=MV_CASTABLOAD_RC
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&MV_CASTABLOAD_RC=0),
|
||||
desc=Check RC=0 when table is already in-memory (skip load)
|
||||
)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 4 - explicit srcfile= where file name differs from table name;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mv_castabload(
|
||||
caslib=&testcaslib,
|
||||
table=&tab2,
|
||||
srcfile=src_&tab2..sashdat,
|
||||
mdebug=1
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&MV_CASTABLOAD_RC=1),
|
||||
desc=Check RC=1 when loading with explicit srcfile= parameter
|
||||
)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%put TEST 5 - load failure when srcfile does not exist in the caslib;
|
||||
/* ------------------------------------------------------------------------ */
|
||||
%mv_castabload(
|
||||
caslib=&testcaslib,
|
||||
table=&tab3,
|
||||
srcfile=doesnotexist_%mf_uid..sashdat,
|
||||
mdebug=1
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&MV_CASTABLOAD_RC=3),
|
||||
desc=Check RC=3 when source file cannot be found / load fails
|
||||
)
|
||||
|
||||
/* reset so that a downstream failure RC does not break testterm */
|
||||
%let syscc=0;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Teardown: drop promoted tables and remove source files */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
proc casutil;
|
||||
droptable casdata="&tab1" incaslib="&testcaslib" quiet;
|
||||
droptable casdata="&tab2" incaslib="&testcaslib" quiet;
|
||||
deletesource casdata="&tab1..sashdat" incaslib="&testcaslib" quiet;
|
||||
deletesource casdata="src_&tab2..sashdat" incaslib="&testcaslib" quiet;
|
||||
quit;
|
||||
|
||||
cas mysess terminate;
|
||||
|
||||
%let syscc=0;
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
@file mv_castabload.sas
|
||||
@brief Checks if a CAS table exists in a CASLIB; if not, loads & promotes it
|
||||
@details Runs in SPRE against an active CAS session. Uses
|
||||
`table.tableExists` to check whether the table is already in-memory,
|
||||
and PROC CASUTIL LOAD with the PROMOTE option to load it if not.
|
||||
CASUTIL infers the file type from the source file extension.
|
||||
|
||||
A CAS session must already be established by the caller, eg:
|
||||
|
||||
cas mysess;
|
||||
%mv_castabload(caslib=Public, table=BASEBALL)
|
||||
|
||||
or (if not a hdat source with the same name as the table):
|
||||
|
||||
%mv_castabload(caslib=Public, table=BASEBALL,
|
||||
srcfile=MYBASEBALL.parquet)
|
||||
|
||||
@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
|
||||
@param [in] mdebug= (0) Set to 1 to enable verbose logging:
|
||||
- echoes resolved parameters
|
||||
- prints tableExists result
|
||||
- enables mprint/notes during PROC calls
|
||||
|
||||
@returns Sets global macro variable `MV_CASTABLOAD_RC`:
|
||||
0 = table already existed (no load performed)
|
||||
1 = table was loaded & promoted successfully
|
||||
3 = action failed
|
||||
**/
|
||||
|
||||
%macro mv_castabload(
|
||||
caslib=
|
||||
,table=
|
||||
,srcfile=0
|
||||
,mdebug=0
|
||||
);
|
||||
|
||||
%global MV_CASTABLOAD_RC;
|
||||
%let MV_CASTABLOAD_RC=3;
|
||||
|
||||
%local _sysopts;
|
||||
%let _sysopts=%sysfunc(getoption(mprint)) %sysfunc(getoption(notes));
|
||||
|
||||
/* ---- input validation -------------------------------------------------- */
|
||||
%if "&caslib"="" or "&table"="" or "&srcfile"="" %then %do;
|
||||
%put %str(ERR)OR: caslib=, table= and srcfile= are all required;
|
||||
%return;
|
||||
%end;
|
||||
%if "&srcfile"="0" %then %let srcfile=&table..hdat;
|
||||
|
||||
%if &mdebug=1 %then %do;
|
||||
%put &=caslib;
|
||||
%put &=table;
|
||||
%put &=srcfile;
|
||||
options mprint notes;
|
||||
%end;
|
||||
|
||||
/* ---- existence check --------------------------------------------------- */
|
||||
proc cas;
|
||||
table.tableExists result=r /
|
||||
caslib="&caslib"
|
||||
name="&table";
|
||||
%if &mdebug=1 %then %do;
|
||||
print r;
|
||||
%end;
|
||||
if r.exists = 0 then rc = 9;
|
||||
else rc = 0;
|
||||
symputx('MV_CASTABLOAD_RC', rc, 'G');
|
||||
quit;
|
||||
|
||||
|
||||
/* ---- load if absent ---------------------------------------------------- */
|
||||
%if &MV_CASTABLOAD_RC=9 %then %do;
|
||||
|
||||
proc casutil;
|
||||
load casdata="&srcfile"
|
||||
incaslib="&caslib"
|
||||
casout="&table"
|
||||
outcaslib="&caslib"
|
||||
promote;
|
||||
quit;
|
||||
|
||||
%if &syserr=0 %then %let MV_CASTABLOAD_RC=1;
|
||||
%else %let MV_CASTABLOAD_RC=3;
|
||||
|
||||
%end;
|
||||
|
||||
%if &MV_CASTABLOAD_RC=0 %then
|
||||
%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;
|
||||
|
||||
/* ---- restore options --------------------------------------------------- */
|
||||
%if &mdebug=1 %then %do;
|
||||
options &_sysopts;
|
||||
%end;
|
||||
|
||||
%mend mv_castabload;
|
||||
Reference in New Issue
Block a user