1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-12 06:54:35 +00:00

Compare commits

..

21 Commits

Author SHA1 Message Date
vrh
029c1a29ed feat: xlsx support in mp_streamfile 2020-08-18 23:09:13 +02:00
vrh
c4dbd5971f docs: formatting 2020-08-08 15:26:02 +02:00
vrh
40ac3bba9a merge 2020-08-08 14:32:12 +02:00
vrh
21946e74f1 feat: mm_gettableid macro 2020-08-08 14:29:55 +02:00
Allan Bowe
6443e2d2ef Merge pull request #3 from sasjs/mp_rafal
Fix: Unique Indexes Added
2020-08-05 13:57:00 +02:00
rafgag
17f03b7507 Fix: previous changes restored 2020-08-05 13:48:16 +02:00
rafgag
c6a18a4168 Fix: Unique Indexes Added 2020-08-05 12:42:27 +02:00
vrh
dd18d1d5a8 fix: adding schema to pg output 2020-08-04 21:19:00 +02:00
vrh
fc8a39bbca fix: quoting reserved words 2020-08-04 18:45:00 +02:00
vrh
8beec7dc19 fix: quoting for instances of reserved words in pgsql 2020-08-04 18:13:22 +02:00
vrh
e3f6cb7b45 chore: editor config file 2020-08-04 14:45:54 +02:00
Allan Bowe
041aff9bc0 Merge pull request #2 from rafgag/mp_rafal
FEAT: adding Primary Key constraints
2020-08-04 12:00:28 +02:00
rafgag
1986732573 Update mp_getddl.sas 2020-08-04 12:00:05 +02:00
rafgag
958f509894 Update mp_getddl.sas 2020-08-04 11:34:19 +02:00
rafgag
1373957031 Update mp_getddl.sas 2020-08-04 11:30:12 +02:00
rafgag
8466acc7a7 Update mp_getddl.sas 2020-08-04 11:25:59 +02:00
rafgag
45e646565f FEAT: adding Primary Key constraints 2020-08-03 16:51:14 +02:00
Allan Bowe
9d9a72220f fix: syscc value (not length) assertion 2020-07-30 02:42:13 +02:00
Allan Bowe
53865a3909 feat: Postgres support for getddl macro 2020-07-29 12:32:54 +02:00
Allan Bowe
98a0d185ff fix: compatibility with compute sessions 2020-07-15 09:58:48 +02:00
Allan Bowe
888e07468c fix: pretty option always in proc json 2020-07-11 11:57:56 +02:00
12 changed files with 575 additions and 140 deletions

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = false
trim_trailing_whitespace = true

1
.gitignore vendored
View File

@@ -1 +1,2 @@
node_modules node_modules
.DS_Store

350
all.sas
View File

@@ -2449,11 +2449,13 @@ create table &outds as
label x='blah'; label x='blah';
run; run;
proc sql; describe table &syslast; proc sql; describe table &syslast;
%mp_getddl(work,test,flavour=tsql,showlog=YES) %mp_getddl(work,test,flavour=tsql,showlog=YES)
<h4> Dependencies </h4>
@li mp_getconstraints.sas
@param lib libref of the library to create DDL for. Should be assigned. @param lib libref of the library to create DDL for. Should be assigned.
@param ds dataset to create ddl for @param ds dataset to create ddl for (optional)
@param fref= the fileref to which to write the DDL. If not preassigned, will @param fref= the fileref to which to write the DDL. If not preassigned, will
be assigned to TEMP. be assigned to TEMP.
@param flavour= The type of DDL to create (default=SAS). Supported=TSQL @param flavour= The type of DDL to create (default=SAS). Supported=TSQL
@@ -2462,11 +2464,9 @@ create table &outds as
,else libref) ,else libref)
@param applydttm= for non SAS DDL, choose if columns are created with native @param applydttm= for non SAS DDL, choose if columns are created with native
datetime2 format or regular decimal type datetime2 format or regular decimal type
@version 9.3 @version 9.3
@author Allan Bowe @author Allan Bowe
@source https://github.com/sasjs/core @source https://github.com/sasjs/core
**/ **/
%macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema= %macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema=
@@ -2490,6 +2490,21 @@ create table _data_ as
; ;
%local tabinfo; %let tabinfo=&syslast; %local tabinfo; %let tabinfo=&syslast;
create table _data_ as
select * from dictionary.columns
where upcase(libname)="%upcase(&libref)"
%if %length(&ds)>0 %then %do;
and upcase(memname)="%upcase(&ds)"
%end;
;
%local colinfo; %let colinfo=&syslast;
%local dsnlist;
select distinct upcase(memname) into: dsnlist
separated by ' '
from &syslast
;
create table _data_ as create table _data_ as
select * from dictionary.indexes select * from dictionary.indexes
where upcase(libname)="%upcase(&libref)" where upcase(libname)="%upcase(&libref)"
@@ -2500,18 +2515,43 @@ create table _data_ as
; ;
%local idxinfo; %let idxinfo=&syslast; %local idxinfo; %let idxinfo=&syslast;
create table _data_ as /* Extract all Primary Key and Unique data constraints */
select * from dictionary.columns %mp_getconstraints(lib=%upcase(&libref),ds=%upcase(&ds),outds=_data_)
where upcase(libname)="%upcase(&libref)" %local colconst; %let colconst=&syslast;
%if %length(&ds)>0 %then %do;
and upcase(memname)="%upcase(&ds)" %macro addConst();
%end; %global constraints_used;
; data _null_;
%local colinfo; %let colinfo=&syslast; length ctype $11 constraint_name_orig $256 constraints_used $5000;
%local dsnlist; set &colconst (where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))) end=last;
select distinct upcase(memname) into: dsnlist file &fref mod;
separated by ' ' by constraint_type constraint_name;
from &syslast; retain constraints_used;
constraint_name_orig=constraint_name;
if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY';
else ctype=strip(constraint_type);
%if &flavour=TSQL %then %do;
column_name=catt('[',column_name,']');
constraint_name=catt('[',constraint_name,']');
%end;
%else %if &flavour=PGSQL %then %do;
column_name=catt('"',column_name,'"');
constraint_name=catt('"',constraint_name,'"');
%end;
if first.constraint_name then do;
constraints_used = catx(' ', constraints_used, constraint_name_orig);
put " ,CONSTRAINT " constraint_name ctype "(" ;
put ' ' column_name;
end;
else put ' ,' column_name;
if last.constraint_name then do;
put " )";
call symput('constraints_used',strip(constraints_used));
end;
run;
%put &=constraints_used;
%mend;
data _null_; data _null_;
file &fref; file &fref;
put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
@@ -2520,7 +2560,8 @@ run;
%local x curds; %local x curds;
%if &flavour=SAS %then %do; %if &flavour=SAS %then %do;
data _null_; data _null_;
file &fref; file &fref mod;
put "/* SAS Flavour DDL for %upcase(&libref).&curds */";
put "proc sql;"; put "proc sql;";
run; run;
%do x=1 %to %sysfunc(countw(&dsnlist)); %do x=1 %to %sysfunc(countw(&dsnlist));
@@ -2545,23 +2586,34 @@ run;
lab=" label="!!quote(trim(label)); lab=" label="!!quote(trim(label));
if notnull='yes' then notnul=' not null'; if notnull='yes' then notnul=' not null';
put name type len fmt notnul lab; put name type len fmt notnul lab;
if last then put ');';
run; run;
/* Extra step for data constraints */
%addConst()
data _null_; data _null_;
length ds $128; file &fref mod;
set &idxinfo (where=(memname="&curds")) end=last; put ');';
run;
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_;
*length ds $128;
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod; file &fref mod;
by idxusage indxname; by idxusage indxname;
if unique='yes' then uniq=' unique'; /* ds=cats(libname,'.',memname); */
ds=cats(libname,'.',memname);
if first.indxname then do; if first.indxname then do;
put 'create ' uniq ' index ' indxname; put 'CREATE UNIQUE INDEX ' indxname "ON &libref..&curds (" ;
put ' on ' ds '(' name @@; put ' ' name ;
end;
else put ' ,' name ;
*else put ' ,' name ;
if last.indxname then do;
put ');';
end; end;
else put ',' name @@;
if last.indxname then put ');';
run; run;
/* /*
ods output IntegrityConstraints=ic; ods output IntegrityConstraints=ic;
proc contents data=testali out2=info; proc contents data=testali out2=info;
@@ -2582,7 +2634,7 @@ run;
%let curds=%scan(&dsnlist,&x); %let curds=%scan(&dsnlist,&x);
data _null_; data _null_;
file &fref mod; file &fref mod;
put "/* DDL for &schema..&curds */"; put "/* TSQL Flavour DDL for &schema..&curds */";
data _null_; data _null_;
file &fref mod; file &fref mod;
set &colinfo (where=(upcase(memname)="&curds")) end=last; set &colinfo (where=(upcase(memname)="&curds")) end=last;
@@ -2605,31 +2657,30 @@ run;
else if length le 8000 then fmt='[varchar]('!!cats(length)!!')'; else if length le 8000 then fmt='[varchar]('!!cats(length)!!')';
else fmt=cats('[varchar](max)'); else fmt=cats('[varchar](max)');
if notnull='yes' then notnul=' NOT NULL'; if notnull='yes' then notnul=' NOT NULL';
put name fmt notnul; put "[" name +(-1) "]" fmt notnul;
run; run;
/* Extra step for data constraints */
%addConst()
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_; data _null_;
length ds $128; *length ds $128;
set &idxinfo (where=(memname="&curds")); set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod; file &fref mod;
by idxusage indxname; by idxusage indxname;
if unique='yes' then uniq=' unique'; *ds=cats(libname,'.',memname);
ds=cats(libname,'.',memname);
if first.indxname then do; if first.indxname then do;
if unique='yes' and nomiss='yes' then do; /* add nonclustered in case of multiple unique indexes */
put ' ,constraint [' indxname '] PRIMARY KEY'; put ' ,index [' indxname +(-1) '] UNIQUE NONCLUSTERED (';
end; put ' [' name +(-1) ']';
else if unique='yes' then do;
/* add nonclustered in case of multiple unique indexes */
put ' ,index [' indxname '] UNIQUE NONCLUSTERED';
end;
put ' (';
put ' [' name ']';
end; end;
else put ' ,[' name ']'; else put ' ,[' name +(-1) ']';
if last.indxname then do; if last.indxname then do;
put ' )'; put ' )';
end; end;
run; run;
data _null_; data _null_;
file &fref mod; file &fref mod;
put ')'; put ')';
@@ -2653,7 +2704,77 @@ run;
run; run;
%end; %end;
%end; %end;
%else %if &flavour=PGSQL %then %do;
/* if schema does not exist, set to be same as libref */
%local schemaactual;
proc sql noprint;
select sysvalue into: schemaactual
from dictionary.libnames
where libname="&libref" and engine='POSTGRES';
%let schema=%sysfunc(coalescec(&schemaactual,&schema,&libref));
data _null_;
file &fref mod;
put "CREATE SCHEMA &schema;";
%do x=1 %to %sysfunc(countw(&dsnlist));
%let curds=%scan(&dsnlist,&x);
data _null_;
file &fref mod;
put "/* Postgres Flavour DDL for &schema..&curds */";
data _null_;
file &fref mod;
set &colinfo (where=(upcase(memname)="&curds")) end=last;
length fmt $32;
if _n_=1 then do;
if memtype='DATA' then do;
put "CREATE TABLE &schema..&curds (";
end;
else do;
put "CREATE VIEW &schema..&curds (";
end;
put " "@@;
end;
else put " ,"@@;
format=upcase(format);
if 1=0 then; /* dummy if */
%if &applydttm=YES %then %do;
else if format=:'DATETIME' then fmt=' TIMESTAMP ';
%end;
else if type='num' then fmt=' DOUBLE PRECISION';
else fmt='VARCHAR('!!cats(length)!!')';
if notnull='yes' then notnul=' NOT NULL';
/* quote column names in case they represent reserved words */
name2=quote(trim(name));
put name2 fmt notnul;
run;
/* Extra step for data constraints */
%addConst()
data _null_;
file &fref mod;
put ');';
run;
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_;
*length ds $128;
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod;
by idxusage indxname;
/* ds=cats(libname,'.',memname); */
if first.indxname then do;
put 'CREATE UNIQUE INDEX "' indxname +(-1) '" ' "ON &schema..&curds (" ;
put ' "' name +(-1) '"' ;
end;
else put ' ,"' name +(-1) '"';
*else put ' ,' name ;
if last.indxname then do;
put ');';
end;
run;
%end;
%end;
%if &showlog=YES %then %do; %if &showlog=YES %then %do;
options ps=max; options ps=max;
data _null_; data _null_;
@@ -2663,8 +2784,7 @@ run;
run; run;
%end; %end;
%mend; %mend;/**
/**
@file mp_getmaxvarlengths.sas @file mp_getmaxvarlengths.sas
@brief Scans a dataset to find the max length of the variable values @brief Scans a dataset to find the max length of the variable values
@details @details
@@ -3080,7 +3200,9 @@ create table &outds (rename=(
* PROCJSON (default) * PROCJSON (default)
* DATASTEP * DATASTEP
@param dbg= Typically used with an _debug (numeric) option @param dbg= DEPRECATED - was used to conditionally add PRETTY to
proc json but this can cause line truncation in large files.
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@@ -3106,9 +3228,8 @@ create table &outds (rename=(
proc sql;drop table &tempds; proc sql;drop table &tempds;
data &tempds /view=&tempds;set &ds; data &tempds /view=&tempds;set &ds;
%if &fmt=N %then format _numeric_ best32.;; %if &fmt=N %then format _numeric_ best32.;;
proc json out=&jref proc json out=&jref pretty
%if &action=ARR %then nokeys ; %if &action=ARR %then nokeys ;
%if &dbg ge 131 %then pretty ;
;export &tempds / nosastags fmtnumeric; ;export &tempds / nosastags fmtnumeric;
run; run;
proc sql;drop view &tempds; proc sql;drop view &tempds;
@@ -3811,6 +3932,7 @@ proc sql
%end; %end;
%end; %end;
%else %if &contentype=EXCEL %then %do; %else %if &contentype=EXCEL %then %do;
/* suitable for XLS format */
%if &platform=SASMETA %then %do; %if &platform=SASMETA %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/vnd.ms-excel'); rc=stpsrv_header('Content-type','application/vnd.ms-excel');
@@ -3823,6 +3945,19 @@ proc sql
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%end; %end;
%else %if &contentype=XLSX %then %do;
%if &platform=SASMETA %then %do;
data _null_;
rc=stpsrv_header('Content-type','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
run;
%end;
%else %if &platform=SASVIYA %then %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name='_webout.xls'
contenttype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
contentdisp="attachment; filename=&outname";
%end;
%end;
%else %if &contentype=TEXT %then %do; %else %if &contentype=TEXT %then %do;
%if &platform=SASMETA %then %do; %if &platform=SASMETA %then %do;
data _null_; data _null_;
@@ -4099,19 +4234,20 @@ ods package publish archive properties
ods package close; ods package close;
%mend;/** %mend;/**
@file @file mm_adduser2group.sas
@brief Adds a user to a group @brief Adds a user to a group
@details Adds a user to a metadata group. The macro first checks whether the @details Adds a user to a metadata group. The macro first checks whether the
user is in that group, and if not, the user is added. user is in that group, and if not, the user is added.
Usage: Usage:
%mm_adduser2group(user=sasdemo %mm_adduser2group(user=sasdemo
,group=someGroup) ,group=someGroup)
@param user= the user name (not displayname) @param user= the user name (not displayname)
@param group= the group to which to add the user @param group= the group to which to add the user
@param mdebug= set to 1 to show debug info in log
@warning the macro does not check inherited group memberships - it looks at @warning the macro does not check inherited group memberships - it looks at
direct members only direct members only
@@ -4168,7 +4304,7 @@ run;
%return; %return;
%end; %end;
%if %length(&syscc) ge 4 %then %do; %if &syscc ge 4 %then %do;
%put WARNING: SYSCC=&syscc, exiting &sysmacroname; %put WARNING: SYSCC=&syscc, exiting &sysmacroname;
%return; %return;
%end; %end;
@@ -6053,9 +6189,8 @@ data _null_;
put ' proc sql;drop table &tempds; '; put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; '; put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; '; put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' proc json out=&jref '; put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; '; put ' %if &action=ARR %then nokeys ; ';
put ' %if &dbg ge 131 %then pretty ; ';
put ' ;export &tempds / nosastags fmtnumeric; '; put ' ;export &tempds / nosastags fmtnumeric; ';
put ' run; '; put ' run; ';
put ' proc sql;drop view &tempds; '; put ' proc sql;drop view &tempds; ';
@@ -7962,6 +8097,72 @@ run;
%mend; %mend;
/** /**
@file mm_gettableid.sas
@brief Get the metadata id for a particular table
@details Provide a libref and table name to return the corresponding metadata id
in an output datataset.
Usage:
- get a table id
%mm_gettableid(libref=METALIB,ds=SOMETABLE,outds=iwant)
@param libref= The libref to search
@param ds= The input dataset to check
@param outds= the dataset to create that contains the `tableuri`
@param mDebug= set to 1 to show debug messages in the log
@returns outds dataset containing `tableuri` and `tablename`
@version 9.3
@author Allan Bowe
**/
%macro mm_gettableid(
libref=
,ds=
,outds=work.mm_gettableid
,mDebug=0
)/*/STORE SOURCE*/;
%local mD;
%if &mDebug=1 %then %let mD=;
%else %let mD=%str(*);
%&mD.put Executing &sysmacroname..sas;
%&mD.put _local_;
data &outds;
length uri usingpkguri id type tableuri tablename tmpuri $256;
call missing(of _all_);
keep tableuri tablename;
n=1;
rc=0;
if metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",n,uri)<1 then do;
put "Library &libref not found";
stop;
end;
&mD.putlog "uri is " uri;
if metadata_getnasn(uri, "UsingPackages", 1, usingpkguri)>0 then do;
rc=metadata_resolve(usingpkguri,type,id);
&mD.putlog "Type is " type;
end;
if type='DatabaseSchema' then tmpuri=usingpkguri;
else tmpuri=uri;
t=1;
do while(metadata_getnasn(tmpuri, "Tables", t, tableuri)>0);
t+1;
rc= metadata_getattr(tableuri, "Name", tablename);
&mD.putlog "Table is " tablename;
if upcase(tablename)="%upcase(&ds)" then do;
output;
end;
end;
run;
%mend;/**
@file @file
@brief Creates a dataset with all metadata tables for a particular library @brief Creates a dataset with all metadata tables for a particular library
@details Will only show the tables to which a user has the requisite @details Will only show the tables to which a user has the requisite
@@ -9840,9 +10041,8 @@ data _null_;
put ' proc sql;drop table &tempds; '; put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; '; put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; '; put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' proc json out=&jref '; put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; '; put ' %if &action=ARR %then nokeys ; ';
put ' %if &dbg ge 131 %then pretty ; ';
put ' ;export &tempds / nosastags fmtnumeric; '; put ' ;export &tempds / nosastags fmtnumeric; ';
put ' run; '; put ' run; ';
put ' proc sql;drop view &tempds; '; put ' proc sql;drop view &tempds; ';
@@ -9938,7 +10138,7 @@ data _null_;
put '%mend; '; put '%mend; ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); '; put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name '; put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables; '; put ' sasjs_tables SYS_JES_JOB_URI; ';
put '%if %index("&_debug",log) %then %let _debug=131; '; put '%if %index("&_debug",log) %then %let _debug=131; ';
put ' '; put ' ';
put '%local i tempds; '; put '%local i tempds; ';
@@ -10041,8 +10241,13 @@ data _null_;
put '%else %if &action=OPEN %then %do; '; put '%else %if &action=OPEN %then %do; ';
put ' /* setup webout */ '; put ' /* setup webout */ ';
put ' OPTIONS NOBOMFILE; '; put ' OPTIONS NOBOMFILE; ';
put ' filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" '; put ' %if "X&SYS_JES_JOB_URI.X"="XX" %then %do; ';
put ' name="_webout.json" lrecl=999999 mod; '; put ' filename _webout temp lrecl=999999 mod; ';
put ' %end; ';
put ' %else %do; ';
put ' filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" ';
put ' name="_webout.json" lrecl=999999 mod; ';
put ' %end; ';
put ' '; put ' ';
put ' /* setup temp ref */ '; put ' /* setup temp ref */ ';
put ' %if %upcase(&fref) ne _WEBOUT %then %do; '; put ' %if %upcase(&fref) ne _WEBOUT %then %do; ';
@@ -10072,13 +10277,13 @@ data _null_;
put ' i+1; '; put ' i+1; ';
put ' call symputx(''wt''!!left(i),name); '; put ' call symputx(''wt''!!left(i),name); ';
put ' call symputx(''wtcnt'',i); '; put ' call symputx(''wtcnt'',i); ';
put ' data _null_; file &fref; put ",""WORK"":{"; '; put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
put ' %do i=1 %to &wtcnt; '; put ' %do i=1 %to &wtcnt; ';
put ' %let wt=&&wt&i; '; put ' %let wt=&&wt&i; ';
put ' proc contents noprint data=&wt '; put ' proc contents noprint data=&wt ';
put ' out=_data_ (keep=name type length format:); '; put ' out=_data_ (keep=name type length format:); ';
put ' run;%let tempds=%scan(&syslast,2,.); '; put ' run;%let tempds=%scan(&syslast,2,.); ';
put ' data _null_; file &fref; '; put ' data _null_; file &fref mod; ';
put ' dsid=open("WORK.&wt",''is''); '; put ' dsid=open("WORK.&wt",''is''); ';
put ' nlobs=attrn(dsid,''NLOBS''); '; put ' nlobs=attrn(dsid,''NLOBS''); ';
put ' nvars=attrn(dsid,''NVARS''); '; put ' nvars=attrn(dsid,''NVARS''); ';
@@ -10089,9 +10294,9 @@ data _null_;
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) '; put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) ';
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) '; put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) ';
put ' data _null_; file &fref;put "}"; '; put ' data _null_; file &fref mod;put "}"; ';
put ' %end; '; put ' %end; ';
put ' data _null_; file &fref;put "}";run; '; put ' data _null_; file &fref mod;put "}";run; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
put ' /* close off json */ '; put ' /* close off json */ ';
@@ -11961,7 +12166,7 @@ filename &fref1 clear;
**/ **/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); %macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y);
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name %global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables; sasjs_tables SYS_JES_JOB_URI;
%if %index("&_debug",log) %then %let _debug=131; %if %index("&_debug",log) %then %let _debug=131;
%local i tempds; %local i tempds;
@@ -12064,8 +12269,13 @@ filename &fref1 clear;
%else %if &action=OPEN %then %do; %else %if &action=OPEN %then %do;
/* setup webout */ /* setup webout */
OPTIONS NOBOMFILE; OPTIONS NOBOMFILE;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" %if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
name="_webout.json" lrecl=999999 mod; filename _webout temp lrecl=999999 mod;
%end;
%else %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
name="_webout.json" lrecl=999999 mod;
%end;
/* setup temp ref */ /* setup temp ref */
%if %upcase(&fref) ne _WEBOUT %then %do; %if %upcase(&fref) ne _WEBOUT %then %do;
@@ -12095,13 +12305,13 @@ filename &fref1 clear;
i+1; i+1;
call symputx('wt'!!left(i),name); call symputx('wt'!!left(i),name);
call symputx('wtcnt',i); call symputx('wtcnt',i);
data _null_; file &fref; put ",""WORK"":{"; data _null_; file &fref mod; put ",""WORK"":{";
%do i=1 %to &wtcnt; %do i=1 %to &wtcnt;
%let wt=&&wt&i; %let wt=&&wt&i;
proc contents noprint data=&wt proc contents noprint data=&wt
out=_data_ (keep=name type length format:); out=_data_ (keep=name type length format:);
run;%let tempds=%scan(&syslast,2,.); run;%let tempds=%scan(&syslast,2,.);
data _null_; file &fref; data _null_; file &fref mod;
dsid=open("WORK.&wt",'is'); dsid=open("WORK.&wt",'is');
nlobs=attrn(dsid,'NLOBS'); nlobs=attrn(dsid,'NLOBS');
nvars=attrn(dsid,'NVARS'); nvars=attrn(dsid,'NVARS');
@@ -12112,9 +12322,9 @@ filename &fref1 clear;
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP)
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP)
data _null_; file &fref;put "}"; data _null_; file &fref mod;put "}";
%end; %end;
data _null_; file &fref;put "}";run; data _null_; file &fref mod;put "}";run;
%end; %end;
/* close off json */ /* close off json */

View File

@@ -13,11 +13,13 @@
label x='blah'; label x='blah';
run; run;
proc sql; describe table &syslast; proc sql; describe table &syslast;
%mp_getddl(work,test,flavour=tsql,showlog=YES) %mp_getddl(work,test,flavour=tsql,showlog=YES)
<h4> Dependencies </h4>
@li mp_getconstraints.sas
@param lib libref of the library to create DDL for. Should be assigned. @param lib libref of the library to create DDL for. Should be assigned.
@param ds dataset to create ddl for @param ds dataset to create ddl for (optional)
@param fref= the fileref to which to write the DDL. If not preassigned, will @param fref= the fileref to which to write the DDL. If not preassigned, will
be assigned to TEMP. be assigned to TEMP.
@param flavour= The type of DDL to create (default=SAS). Supported=TSQL @param flavour= The type of DDL to create (default=SAS). Supported=TSQL
@@ -26,11 +28,9 @@
,else libref) ,else libref)
@param applydttm= for non SAS DDL, choose if columns are created with native @param applydttm= for non SAS DDL, choose if columns are created with native
datetime2 format or regular decimal type datetime2 format or regular decimal type
@version 9.3 @version 9.3
@author Allan Bowe @author Allan Bowe
@source https://github.com/sasjs/core @source https://github.com/sasjs/core
**/ **/
%macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema= %macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema=
@@ -54,6 +54,21 @@ create table _data_ as
; ;
%local tabinfo; %let tabinfo=&syslast; %local tabinfo; %let tabinfo=&syslast;
create table _data_ as
select * from dictionary.columns
where upcase(libname)="%upcase(&libref)"
%if %length(&ds)>0 %then %do;
and upcase(memname)="%upcase(&ds)"
%end;
;
%local colinfo; %let colinfo=&syslast;
%local dsnlist;
select distinct upcase(memname) into: dsnlist
separated by ' '
from &syslast
;
create table _data_ as create table _data_ as
select * from dictionary.indexes select * from dictionary.indexes
where upcase(libname)="%upcase(&libref)" where upcase(libname)="%upcase(&libref)"
@@ -64,18 +79,43 @@ create table _data_ as
; ;
%local idxinfo; %let idxinfo=&syslast; %local idxinfo; %let idxinfo=&syslast;
create table _data_ as /* Extract all Primary Key and Unique data constraints */
select * from dictionary.columns %mp_getconstraints(lib=%upcase(&libref),ds=%upcase(&ds),outds=_data_)
where upcase(libname)="%upcase(&libref)" %local colconst; %let colconst=&syslast;
%if %length(&ds)>0 %then %do;
and upcase(memname)="%upcase(&ds)" %macro addConst();
%end; %global constraints_used;
; data _null_;
%local colinfo; %let colinfo=&syslast; length ctype $11 constraint_name_orig $256 constraints_used $5000;
%local dsnlist; set &colconst (where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))) end=last;
select distinct upcase(memname) into: dsnlist file &fref mod;
separated by ' ' by constraint_type constraint_name;
from &syslast; retain constraints_used;
constraint_name_orig=constraint_name;
if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY';
else ctype=strip(constraint_type);
%if &flavour=TSQL %then %do;
column_name=catt('[',column_name,']');
constraint_name=catt('[',constraint_name,']');
%end;
%else %if &flavour=PGSQL %then %do;
column_name=catt('"',column_name,'"');
constraint_name=catt('"',constraint_name,'"');
%end;
if first.constraint_name then do;
constraints_used = catx(' ', constraints_used, constraint_name_orig);
put " ,CONSTRAINT " constraint_name ctype "(" ;
put ' ' column_name;
end;
else put ' ,' column_name;
if last.constraint_name then do;
put " )";
call symput('constraints_used',strip(constraints_used));
end;
run;
%put &=constraints_used;
%mend;
data _null_; data _null_;
file &fref; file &fref;
put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
@@ -84,7 +124,8 @@ run;
%local x curds; %local x curds;
%if &flavour=SAS %then %do; %if &flavour=SAS %then %do;
data _null_; data _null_;
file &fref; file &fref mod;
put "/* SAS Flavour DDL for %upcase(&libref).&curds */";
put "proc sql;"; put "proc sql;";
run; run;
%do x=1 %to %sysfunc(countw(&dsnlist)); %do x=1 %to %sysfunc(countw(&dsnlist));
@@ -109,23 +150,34 @@ run;
lab=" label="!!quote(trim(label)); lab=" label="!!quote(trim(label));
if notnull='yes' then notnul=' not null'; if notnull='yes' then notnul=' not null';
put name type len fmt notnul lab; put name type len fmt notnul lab;
if last then put ');';
run; run;
/* Extra step for data constraints */
%addConst()
data _null_; data _null_;
length ds $128; file &fref mod;
set &idxinfo (where=(memname="&curds")) end=last; put ');';
run;
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_;
*length ds $128;
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod; file &fref mod;
by idxusage indxname; by idxusage indxname;
if unique='yes' then uniq=' unique'; /* ds=cats(libname,'.',memname); */
ds=cats(libname,'.',memname);
if first.indxname then do; if first.indxname then do;
put 'create ' uniq ' index ' indxname; put 'CREATE UNIQUE INDEX ' indxname "ON &libref..&curds (" ;
put ' on ' ds '(' name @@; put ' ' name ;
end;
else put ' ,' name ;
*else put ' ,' name ;
if last.indxname then do;
put ');';
end; end;
else put ',' name @@;
if last.indxname then put ');';
run; run;
/* /*
ods output IntegrityConstraints=ic; ods output IntegrityConstraints=ic;
proc contents data=testali out2=info; proc contents data=testali out2=info;
@@ -146,7 +198,7 @@ run;
%let curds=%scan(&dsnlist,&x); %let curds=%scan(&dsnlist,&x);
data _null_; data _null_;
file &fref mod; file &fref mod;
put "/* DDL for &schema..&curds */"; put "/* TSQL Flavour DDL for &schema..&curds */";
data _null_; data _null_;
file &fref mod; file &fref mod;
set &colinfo (where=(upcase(memname)="&curds")) end=last; set &colinfo (where=(upcase(memname)="&curds")) end=last;
@@ -169,31 +221,30 @@ run;
else if length le 8000 then fmt='[varchar]('!!cats(length)!!')'; else if length le 8000 then fmt='[varchar]('!!cats(length)!!')';
else fmt=cats('[varchar](max)'); else fmt=cats('[varchar](max)');
if notnull='yes' then notnul=' NOT NULL'; if notnull='yes' then notnul=' NOT NULL';
put name fmt notnul; put "[" name +(-1) "]" fmt notnul;
run; run;
/* Extra step for data constraints */
%addConst()
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_; data _null_;
length ds $128; *length ds $128;
set &idxinfo (where=(memname="&curds")); set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod; file &fref mod;
by idxusage indxname; by idxusage indxname;
if unique='yes' then uniq=' unique'; *ds=cats(libname,'.',memname);
ds=cats(libname,'.',memname);
if first.indxname then do; if first.indxname then do;
if unique='yes' and nomiss='yes' then do; /* add nonclustered in case of multiple unique indexes */
put ' ,constraint [' indxname '] PRIMARY KEY'; put ' ,index [' indxname +(-1) '] UNIQUE NONCLUSTERED (';
end; put ' [' name +(-1) ']';
else if unique='yes' then do;
/* add nonclustered in case of multiple unique indexes */
put ' ,index [' indxname '] UNIQUE NONCLUSTERED';
end;
put ' (';
put ' [' name ']';
end; end;
else put ' ,[' name ']'; else put ' ,[' name +(-1) ']';
if last.indxname then do; if last.indxname then do;
put ' )'; put ' )';
end; end;
run; run;
data _null_; data _null_;
file &fref mod; file &fref mod;
put ')'; put ')';
@@ -217,7 +268,77 @@ run;
run; run;
%end; %end;
%end; %end;
%else %if &flavour=PGSQL %then %do;
/* if schema does not exist, set to be same as libref */
%local schemaactual;
proc sql noprint;
select sysvalue into: schemaactual
from dictionary.libnames
where libname="&libref" and engine='POSTGRES';
%let schema=%sysfunc(coalescec(&schemaactual,&schema,&libref));
data _null_;
file &fref mod;
put "CREATE SCHEMA &schema;";
%do x=1 %to %sysfunc(countw(&dsnlist));
%let curds=%scan(&dsnlist,&x);
data _null_;
file &fref mod;
put "/* Postgres Flavour DDL for &schema..&curds */";
data _null_;
file &fref mod;
set &colinfo (where=(upcase(memname)="&curds")) end=last;
length fmt $32;
if _n_=1 then do;
if memtype='DATA' then do;
put "CREATE TABLE &schema..&curds (";
end;
else do;
put "CREATE VIEW &schema..&curds (";
end;
put " "@@;
end;
else put " ,"@@;
format=upcase(format);
if 1=0 then; /* dummy if */
%if &applydttm=YES %then %do;
else if format=:'DATETIME' then fmt=' TIMESTAMP ';
%end;
else if type='num' then fmt=' DOUBLE PRECISION';
else fmt='VARCHAR('!!cats(length)!!')';
if notnull='yes' then notnul=' NOT NULL';
/* quote column names in case they represent reserved words */
name2=quote(trim(name));
put name2 fmt notnul;
run;
/* Extra step for data constraints */
%addConst()
data _null_;
file &fref mod;
put ');';
run;
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _null_;
*length ds $128;
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
file &fref mod;
by idxusage indxname;
/* ds=cats(libname,'.',memname); */
if first.indxname then do;
put 'CREATE UNIQUE INDEX "' indxname +(-1) '" ' "ON &schema..&curds (" ;
put ' "' name +(-1) '"' ;
end;
else put ' ,"' name +(-1) '"';
*else put ' ,' name ;
if last.indxname then do;
put ');';
end;
run;
%end;
%end;
%if &showlog=YES %then %do; %if &showlog=YES %then %do;
options ps=max; options ps=max;
data _null_; data _null_;
@@ -227,4 +348,4 @@ run;
run; run;
%end; %end;
%mend; %mend;

View File

@@ -40,7 +40,9 @@
* PROCJSON (default) * PROCJSON (default)
* DATASTEP * DATASTEP
@param dbg= Typically used with an _debug (numeric) option @param dbg= DEPRECATED - was used to conditionally add PRETTY to
proc json but this can cause line truncation in large files.
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@@ -66,9 +68,8 @@
proc sql;drop table &tempds; proc sql;drop table &tempds;
data &tempds /view=&tempds;set &ds; data &tempds /view=&tempds;set &ds;
%if &fmt=N %then format _numeric_ best32.;; %if &fmt=N %then format _numeric_ best32.;;
proc json out=&jref proc json out=&jref pretty
%if &action=ARR %then nokeys ; %if &action=ARR %then nokeys ;
%if &dbg ge 131 %then pretty ;
;export &tempds / nosastags fmtnumeric; ;export &tempds / nosastags fmtnumeric;
run; run;
proc sql;drop view &tempds; proc sql;drop view &tempds;

View File

@@ -47,6 +47,7 @@
%end; %end;
%end; %end;
%else %if &contentype=EXCEL %then %do; %else %if &contentype=EXCEL %then %do;
/* suitable for XLS format */
%if &platform=SASMETA %then %do; %if &platform=SASMETA %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/vnd.ms-excel'); rc=stpsrv_header('Content-type','application/vnd.ms-excel');
@@ -59,6 +60,19 @@
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%end; %end;
%else %if &contentype=XLSX %then %do;
%if &platform=SASMETA %then %do;
data _null_;
rc=stpsrv_header('Content-type','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
run;
%end;
%else %if &platform=SASVIYA %then %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name='_webout.xls'
contenttype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
contentdisp="attachment; filename=&outname";
%end;
%end;
%else %if &contentype=TEXT %then %do; %else %if &contentype=TEXT %then %do;
%if &platform=SASMETA %then %do; %if &platform=SASMETA %then %do;
data _null_; data _null_;

View File

@@ -30,7 +30,7 @@ doxygen Doxyfile
# refresh github pages site # refresh github pages site
git clone git@github.com:sasjs/core.github.io.git git clone git@github.com:sasjs/core.github.io.git
cd core.github.io cd core.github.io
git rm -r * rm -r *
mv $BUILD_FOLDER/out/doxy/* . mv $BUILD_FOLDER/out/doxy/* .
echo 'core.sasjs.io' > CNAME echo 'core.sasjs.io' > CNAME
git add * git add *

View File

@@ -1,17 +1,18 @@
/** /**
@file @file mm_adduser2group.sas
@brief Adds a user to a group @brief Adds a user to a group
@details Adds a user to a metadata group. The macro first checks whether the @details Adds a user to a metadata group. The macro first checks whether the
user is in that group, and if not, the user is added. user is in that group, and if not, the user is added.
Usage: Usage:
%mm_adduser2group(user=sasdemo %mm_adduser2group(user=sasdemo
,group=someGroup) ,group=someGroup)
@param user= the user name (not displayname) @param user= the user name (not displayname)
@param group= the group to which to add the user @param group= the group to which to add the user
@param mdebug= set to 1 to show debug info in log
@warning the macro does not check inherited group memberships - it looks at @warning the macro does not check inherited group memberships - it looks at
direct members only direct members only
@@ -68,7 +69,7 @@ run;
%return; %return;
%end; %end;
%if %length(&syscc) ge 4 %then %do; %if &syscc ge 4 %then %do;
%put WARNING: SYSCC=&syscc, exiting &sysmacroname; %put WARNING: SYSCC=&syscc, exiting &sysmacroname;
%return; %return;
%end; %end;

View File

@@ -104,9 +104,8 @@ data _null_;
put ' proc sql;drop table &tempds; '; put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; '; put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; '; put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' proc json out=&jref '; put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; '; put ' %if &action=ARR %then nokeys ; ';
put ' %if &dbg ge 131 %then pretty ; ';
put ' ;export &tempds / nosastags fmtnumeric; '; put ' ;export &tempds / nosastags fmtnumeric; ';
put ' run; '; put ' run; ';
put ' proc sql;drop view &tempds; '; put ' proc sql;drop view &tempds; ';

67
meta/mm_gettableid.sas Normal file
View File

@@ -0,0 +1,67 @@
/**
@file mm_gettableid.sas
@brief Get the metadata id for a particular table
@details Provide a libref and table name to return the corresponding metadata id
in an output datataset.
Usage:
- get a table id
%mm_gettableid(libref=METALIB,ds=SOMETABLE,outds=iwant)
@param libref= The libref to search
@param ds= The input dataset to check
@param outds= the dataset to create that contains the `tableuri`
@param mDebug= set to 1 to show debug messages in the log
@returns outds dataset containing `tableuri` and `tablename`
@version 9.3
@author Allan Bowe
**/
%macro mm_gettableid(
libref=
,ds=
,outds=work.mm_gettableid
,mDebug=0
)/*/STORE SOURCE*/;
%local mD;
%if &mDebug=1 %then %let mD=;
%else %let mD=%str(*);
%&mD.put Executing &sysmacroname..sas;
%&mD.put _local_;
data &outds;
length uri usingpkguri id type tableuri tablename tmpuri $256;
call missing(of _all_);
keep tableuri tablename;
n=1;
rc=0;
if metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",n,uri)<1 then do;
put "Library &libref not found";
stop;
end;
&mD.putlog "uri is " uri;
if metadata_getnasn(uri, "UsingPackages", 1, usingpkguri)>0 then do;
rc=metadata_resolve(usingpkguri,type,id);
&mD.putlog "Type is " type;
end;
if type='DatabaseSchema' then tmpuri=usingpkguri;
else tmpuri=uri;
t=1;
do while(metadata_getnasn(tmpuri, "Tables", t, tableuri)>0);
t+1;
rc= metadata_getattr(tableuri, "Name", tablename);
&mD.putlog "Table is " tablename;
if upcase(tablename)="%upcase(&ds)" then do;
output;
end;
end;
run;
%mend;

View File

@@ -241,9 +241,8 @@ data _null_;
put ' proc sql;drop table &tempds; '; put ' proc sql;drop table &tempds; ';
put ' data &tempds /view=&tempds;set &ds; '; put ' data &tempds /view=&tempds;set &ds; ';
put ' %if &fmt=N %then format _numeric_ best32.;; '; put ' %if &fmt=N %then format _numeric_ best32.;; ';
put ' proc json out=&jref '; put ' proc json out=&jref pretty ';
put ' %if &action=ARR %then nokeys ; '; put ' %if &action=ARR %then nokeys ; ';
put ' %if &dbg ge 131 %then pretty ; ';
put ' ;export &tempds / nosastags fmtnumeric; '; put ' ;export &tempds / nosastags fmtnumeric; ';
put ' run; '; put ' run; ';
put ' proc sql;drop view &tempds; '; put ' proc sql;drop view &tempds; ';
@@ -339,7 +338,7 @@ data _null_;
put '%mend; '; put '%mend; ';
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); '; put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name '; put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables; '; put ' sasjs_tables SYS_JES_JOB_URI; ';
put '%if %index("&_debug",log) %then %let _debug=131; '; put '%if %index("&_debug",log) %then %let _debug=131; ';
put ' '; put ' ';
put '%local i tempds; '; put '%local i tempds; ';
@@ -442,8 +441,13 @@ data _null_;
put '%else %if &action=OPEN %then %do; '; put '%else %if &action=OPEN %then %do; ';
put ' /* setup webout */ '; put ' /* setup webout */ ';
put ' OPTIONS NOBOMFILE; '; put ' OPTIONS NOBOMFILE; ';
put ' filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" '; put ' %if "X&SYS_JES_JOB_URI.X"="XX" %then %do; ';
put ' name="_webout.json" lrecl=999999 mod; '; put ' filename _webout temp lrecl=999999 mod; ';
put ' %end; ';
put ' %else %do; ';
put ' filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" ';
put ' name="_webout.json" lrecl=999999 mod; ';
put ' %end; ';
put ' '; put ' ';
put ' /* setup temp ref */ '; put ' /* setup temp ref */ ';
put ' %if %upcase(&fref) ne _WEBOUT %then %do; '; put ' %if %upcase(&fref) ne _WEBOUT %then %do; ';
@@ -473,13 +477,13 @@ data _null_;
put ' i+1; '; put ' i+1; ';
put ' call symputx(''wt''!!left(i),name); '; put ' call symputx(''wt''!!left(i),name); ';
put ' call symputx(''wtcnt'',i); '; put ' call symputx(''wtcnt'',i); ';
put ' data _null_; file &fref; put ",""WORK"":{"; '; put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
put ' %do i=1 %to &wtcnt; '; put ' %do i=1 %to &wtcnt; ';
put ' %let wt=&&wt&i; '; put ' %let wt=&&wt&i; ';
put ' proc contents noprint data=&wt '; put ' proc contents noprint data=&wt ';
put ' out=_data_ (keep=name type length format:); '; put ' out=_data_ (keep=name type length format:); ';
put ' run;%let tempds=%scan(&syslast,2,.); '; put ' run;%let tempds=%scan(&syslast,2,.); ';
put ' data _null_; file &fref; '; put ' data _null_; file &fref mod; ';
put ' dsid=open("WORK.&wt",''is''); '; put ' dsid=open("WORK.&wt",''is''); ';
put ' nlobs=attrn(dsid,''NLOBS''); '; put ' nlobs=attrn(dsid,''NLOBS''); ';
put ' nvars=attrn(dsid,''NVARS''); '; put ' nvars=attrn(dsid,''NVARS''); ';
@@ -490,9 +494,9 @@ data _null_;
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) '; put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) ';
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) '; put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) ';
put ' data _null_; file &fref;put "}"; '; put ' data _null_; file &fref mod;put "}"; ';
put ' %end; '; put ' %end; ';
put ' data _null_; file &fref;put "}";run; '; put ' data _null_; file &fref mod;put "}";run; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
put ' /* close off json */ '; put ' /* close off json */ ';

View File

@@ -37,7 +37,7 @@
**/ **/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); %macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y);
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name %global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables; sasjs_tables SYS_JES_JOB_URI;
%if %index("&_debug",log) %then %let _debug=131; %if %index("&_debug",log) %then %let _debug=131;
%local i tempds; %local i tempds;
@@ -140,8 +140,13 @@
%else %if &action=OPEN %then %do; %else %if &action=OPEN %then %do;
/* setup webout */ /* setup webout */
OPTIONS NOBOMFILE; OPTIONS NOBOMFILE;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" %if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
name="_webout.json" lrecl=999999 mod; filename _webout temp lrecl=999999 mod;
%end;
%else %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
name="_webout.json" lrecl=999999 mod;
%end;
/* setup temp ref */ /* setup temp ref */
%if %upcase(&fref) ne _WEBOUT %then %do; %if %upcase(&fref) ne _WEBOUT %then %do;
@@ -171,13 +176,13 @@
i+1; i+1;
call symputx('wt'!!left(i),name); call symputx('wt'!!left(i),name);
call symputx('wtcnt',i); call symputx('wtcnt',i);
data _null_; file &fref; put ",""WORK"":{"; data _null_; file &fref mod; put ",""WORK"":{";
%do i=1 %to &wtcnt; %do i=1 %to &wtcnt;
%let wt=&&wt&i; %let wt=&&wt&i;
proc contents noprint data=&wt proc contents noprint data=&wt
out=_data_ (keep=name type length format:); out=_data_ (keep=name type length format:);
run;%let tempds=%scan(&syslast,2,.); run;%let tempds=%scan(&syslast,2,.);
data _null_; file &fref; data _null_; file &fref mod;
dsid=open("WORK.&wt",'is'); dsid=open("WORK.&wt",'is');
nlobs=attrn(dsid,'NLOBS'); nlobs=attrn(dsid,'NLOBS');
nvars=attrn(dsid,'NVARS'); nvars=attrn(dsid,'NVARS');
@@ -188,9 +193,9 @@
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP)
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP)
data _null_; file &fref;put "}"; data _null_; file &fref mod;put "}";
%end; %end;
data _null_; file &fref;put "}";run; data _null_; file &fref mod;put "}";run;
%end; %end;
/* close off json */ /* close off json */