diff --git a/all.sas b/all.sas
index 3d00f66..6cdd079 100644
--- a/all.sas
+++ b/all.sas
@@ -24415,74 +24415,79 @@ run;
)
%mend mfv_getpathuri;/**
@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.
+ @brief Checks if a CAS table is loaded; if not, loads and promotes it
+ @details Runs in SPRE against an active CAS session. Accepts a
+ SAS libref, derives the CAS caslib and session UUID from
+ sashelp.vlibnam, then checks whether the table is already
+ in-memory. If not, locates the owning CAS server via the
+ casManagement REST API, queries the table endpoint to discover
+ the source file and caslib, then loads and promotes the table.
A CAS session must already be established by the caller, eg:
cas mysess;
- %mv_castabload(caslib=Public, table=BASEBALL)
+ libname mylib cas caslib=Public;
+ %mv_castabload(lib=mylib, 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..sashdat
- @param [in] mdebug= (0) Set to 1 to enable verbose logging:
+ @param [in] lib= SAS libref for the CAS caslib
+ @param [in] table= Name of the CAS table to load
+ @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 (including source file missing)
-
SAS Macros
- @li mfv_existsashdat.sas
+ @li mf_getplatform.sas
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquelibref.sas
+ @li mp_abort.sas
**/
%macro mv_castabload(
- caslib=
+ lib=
,table=
- ,srcfile=0
,mdebug=0
);
-%global MV_CASTABLOAD_RC;
-%let MV_CASTABLOAD_RC=3;
-
-%local _sysopts;
+%local _sysopts base_uri caslib uuid server
+ srcfile srccaslib fname1 libref1 ftmp i _svcount _exists;
%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..sashdat;
+%mp_abort(
+ iftrue=("&lib"="" or "&table"=""),
+ msg=%str(lib= and table= are required)
+)
%if &mdebug=1 %then %do;
- %put &=caslib;
+ %put &=lib;
%put &=table;
- %put &=srcfile;
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;
+/* ---- derive caslib and session UUID from sashelp.vlibnam --------------- */
+data _null_;
+ set sashelp.vlibnam(
+ where=(libname="%upcase(&lib)"
+ and sysname in ("Caslib","Session UUID"))
+ );
+ if sysname="Caslib" then call symputx('caslib',sysvalue,'L');
+ else call symputx('uuid',sysvalue,'L');
+ %if &mdebug=1 %then %do;
+ putlog sysname sysvalue;
+ %end;
+run;
+
+%mp_abort(
+ iftrue=("&caslib"=""),
+ msg=%str(&lib is not an assigned CAS libref)
+)
+
+%mp_abort(
+ iftrue=("&uuid"=""),
+ msg=%str(No session UUID found for libref &lib)
+)
/* ---- existence check --------------------------------------------------- */
proc cas;
@@ -24492,40 +24497,130 @@ proc cas;
%if &mdebug=1 %then %do;
print r;
%end;
- if r.exists = 0 then rc = 9;
- else rc = 0;
- symputx('MV_CASTABLOAD_RC', rc, 'G');
+ if r.exists > 0 then call symputx('_exists', '1', 'L');
+ else call symputx('_exists', '0', 'L');
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;
-
+/* ---- already loaded: skip ---------------------------------------------- */
+%if &_exists=1 %then %do;
+ %put NOTE: Table &caslib..&table already loaded - skipping;
+ %return;
%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 %str(ERR)OR: load failed for &caslib..&table;
+/* ---- get list of CAS servers ----------------------------------------- */
+%let base_uri=%mf_getplatform(VIYARESTAPI);
+%let fname1=%mf_getuniquefileref();
+%let libref1=%mf_getuniquelibref();
+
+proc http method='GET' out=&fname1 oauth_bearer=sas_services
+ url="&base_uri/casManagement/servers";
+run;
+
+%mp_abort(
+ iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200),
+ msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
+)
+
+libname &libref1 JSON fileref=&fname1;
+
+data _null_;
+ set &libref1..items;
+ call symputx(cats('_sv_', _n_), name, 'L');
+ call symputx('_svcount', _n_, 'L');
+run;
+
+libname &libref1 clear;
+filename &fname1 clear;
+
+/* ---- find which server owns this session ------------------------------ */
+%do i=1 %to &_svcount;
+ %if "&server"="" %then %do;
+ %if &mdebug=1 %then %put checking server: &&_sv_&i;
+ %let ftmp=%mf_getuniquefileref();
+ proc http method='GET' out=&ftmp oauth_bearer=sas_services
+ url="&base_uri/casManagement/servers/&&_sv_&i/sessions/&uuid";
+ run;
+ %if &SYS_PROCHTTP_STATUS_CODE=200
+ %then %let server=&&_sv_&i;
+ filename &ftmp clear;
+ %end;
+%end;
+
+%mp_abort(
+ iftrue=("&server"=""),
+ msg=%str(Could not find owning server for CAS session &uuid)
+)
+
+%if &mdebug=1 %then %put &=server;
+
+/* ---- discover source file from REST endpoint -------------------------- */
+%let fname1=%mf_getuniquefileref();
+%let libref1=%mf_getuniquelibref();
+
+proc http method='GET' out=&fname1 oauth_bearer=sas_services
+ url="&base_uri/casManagement/servers/&server/caslibs/&caslib/tables/&table";
+run;
+
+%if &mdebug=1 %then %do;
+ %put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
+ data _null_;
+ infile &fname1;
+ input;
+ putlog _infile_;
+ run;
+%end;
+
+%mp_abort(
+ iftrue=(&SYS_PROCHTTP_STATUS_CODE=404),
+ msg=%str(&caslib..&table not found - is a source file registered?)
+)
+%mp_abort(
+ iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200),
+ msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
+)
+
+libname &libref1 JSON fileref=&fname1;
+
+data _null_;
+ set &libref1..tablereference;
+ call symputx('srcfile', sourceTableName, 'L');
+ call symputx('srccaslib', sourceCaslibName, 'L');
+ stop;
+run;
+
+libname &libref1 clear;
+filename &fname1 clear;
+
+%mp_abort(
+ iftrue=("&srcfile"="" or "&srccaslib"=""),
+ msg=%str(No sourceTableName/sourceCaslibName for &caslib..&table)
+)
+
+%if &mdebug=1 %then %put &=srcfile &=srccaslib;
+
+/* ---- load from discovered source -------------------------------------- */
+proc casutil;
+ load casdata="&srcfile"
+ incaslib="&srccaslib"
+ casout="&table"
+ outcaslib="&caslib"
+ promote;
+quit;
+
+%mp_abort(
+ iftrue=(&syscc ne 0),
+ msg=%str(Load failed for &caslib..&table)
+)
+
+%put NOTE: Table &caslib..&table loaded and promoted from &srcfile;
/* ---- restore options --------------------------------------------------- */
%if &mdebug=1 %then %do;
options &_sysopts;
%end;
-%mend mv_castabload;/**
+%mend mv_castabload;
+/**
@file mv_castabsave.sas
@brief Saves an in-memory CAS table back to persistent storage
@details Runs in SPRE against an active CAS session. Accepts a