1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-10 02:40:05 +00:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Allan Bowe
f99adf5c3e Merge pull request #55 from sasjs/insertforpg
feat: updating mp_ds2inserts to support postgres database
2021-07-28 19:11:38 +03:00
Allan Bowe
69f8e91a2d feat: adding salt as option for mp_hashdataset 2021-07-28 17:04:41 +03:00
Allan Bowe
5b5d01993f fix: updating mp_getddl to enable append to a fileref 2021-07-28 17:01:49 +03:00
Allan Bowe
00fa464a7c feat: updating mp_ds2inserts to support postgres database 2021-07-27 11:07:12 +03:00
Allan Bowe
a5baf46233 chore: removing unnecessary proc format and generating the all.sas file 2021-07-26 22:30:02 +03:00
4 changed files with 236 additions and 40 deletions

190
all.sas
View File

@@ -2250,7 +2250,7 @@ run;
%if &outfound=0 %then %do; %if &outfound=0 %then %do;
filename &outref temp lrecl=2097088; filename &outref temp lrecl=2097088;
%%end; %end;
%if &action=ENCODE %then %do; %if &action=ENCODE %then %do;
data _null_; data _null_;
@@ -2258,12 +2258,12 @@ run;
retain line ""; retain line "";
infile &inref recfm=F lrecl= 1 end=eof; infile &inref recfm=F lrecl= 1 end=eof;
input @1 stream $char1.; input @1 stream $char1.;
file &outref lrecl=76; file &outref recfm=N;
substr(line,(_N_-(CEIL(_N_/57)-1)*57),1) = byte(rank(stream)); substr(line,(_N_-(CEIL(_N_/57)-1)*57),1) = byte(rank(stream));
if mod(_N_,57)=0 or EOF then do; if mod(_N_,57)=0 or EOF then do;
if eof then b64=put(trim(line),$base64X76.); if eof then b64=put(trim(line),$base64X76.);
else b64=put(line, $base64X76.); else b64=put(line, $base64X76.);
put b64; put b64 + (-1) @;
line=""; line="";
end; end;
run; run;
@@ -2275,19 +2275,13 @@ run;
fileout = fopen("&outref",'O',3,'B'); fileout = fopen("&outref",'O',3,'B');
char= '20'x; char= '20'x;
do while(fread(filein)=0); do while(fread(filein)=0);
raw="1234"; length raw $4;
do i=1 to 4; do i=1 to 4;
rc=fget(filein,char,1); rc=fget(filein,char,1);
substr(raw,i,1)=char; substr(raw,i,1)=char;
end; end;
val="123"; rc = fput(fileout,input(raw,$base64X4.));
val=input(raw,$base64X4.); rc = fwrite(fileout);
do i=1 to 3;
length byte $1;
byte=byte(rank(substr(val,i,1)));
rc = fput(fileout, byte);
end;
rc =fwrite(fileout);
end; end;
rc = fclose(filein); rc = fclose(filein);
rc = fclose(fileout); rc = fclose(fileout);
@@ -3429,6 +3423,159 @@ data &outds;
run; run;
%mend mp_ds2fmtds;/** %mend mp_ds2fmtds;/**
@file
@brief Export a dataset to SQL insert statements
@details Converts dataset values to SQL insert statements for use across
multiple database types.
Usage:
%mp_ds2inserts(sashelp.class,outref=myref,outds=class)
data class;
set sashelp.class;
stop;
proc sql;
%inc myref;
@param [in] ds The dataset to be exported
@param [out] outref= (0) The output fileref. If it does not exist, it is
created. If it does exist, new records are APPENDED.
@param [out] outlib= (0) The library (or schema) in which the target table is
located. If not provided, is ignored.
@param [out] outds= (0) The output table to load. If not provided, will
default to the table in the &ds parameter.
@param [in] flavour= (BASE) The SQL flavour to be applied to the output. Valid
options:
@li BASE (default) - suitable for regular proc sql
@li PGSQL - Used for Postgres databases
<h4> SAS Macros </h4>
@li mf_existfileref.sas
@li mf_getvarcount.sas
@li mf_getvarlist.sas
@li mf_getvartype.sas
@version 9.2
@author Allan Bowe (credit mjsq)
**/
%macro mp_ds2inserts(ds, outref=0,outlib=0,outds=0,flavour=BASE
)/*/STORE SOURCE*/;
%if not %sysfunc(exist(&ds)) %then %do;
%put %str(WAR)NING: &ds does not exist;
%return;
%end;
%if not %sysfunc(exist(&ds)) %then %do;
%put %str(WAR)NING: &ds does not exist;
%return;
%end;
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
%let flavour=%upcase(&flavour);
%if &flavour ne BASE and &flavour ne PGSQL %then %do;
%put %str(WAR)NING: &flavour is not supported;
%return;
%end;
%if &outref=0 %then %do;
%put %str(WAR)NING: Please provide a fileref;
%return;
%end;
%if %mf_existfileref(&outref)=0 %then %do;
filename &outref temp lrecl=66000;
%end;
%if &outlib=0 %then %let outlib=;
%else %let outlib=&outlib..;
%if &outds=0 %then %let outds=%scan(&ds,2,.);
%local nobs;
proc sql noprint;
select count(*) into: nobs TRIMMED from &ds;
%if &nobs=0 %then %do;
data _null_;
file &outref mod;
put "/* No rows found in &ds */";
run;
%end;
%local vars;
%let vars=%mf_getvarcount(&ds);
%if &vars=0 %then %do;
data _null_;
file &outref mod;
put "/* No columns found in &ds */";
run;
%end;
%local varlist varlistcomma;
%let varlist=%mf_getvarlist(&ds);
%let varlistcomma=%mf_getvarlist(&ds,dlm=%str(,),quote=double);
/* next, export data */
data _null_;
file &outref mod ;
if _n_=1 then put "/* &outlib.&outds (&nobs rows, &vars columns) */";
set &ds;
length _____str $32767;
format _numeric_ best.;
format _character_ ;
%local i comma var vtype;
%do i=1 %to %sysfunc(countw(&varlist));
%let var=%scan(&varlist,&i);
%let vtype=%mf_getvartype(&ds,&var);
%if &i=1 %then %do;
%if &flavour=BASE %then %do;
put "insert into &outlib.&outds set ";
put " &var="@;
%end;
%else %if &flavour=PGSQL %then %do;
_____str=cats(
"INSERT INTO &outlib.&outds ("
,symget('varlistcomma')
,") VALUES ("
);
put _____str;
put " "@;
%end;
%end;
%else %do;
%if &flavour=BASE %then %do;
put " ,&var="@;
%end;
%else %if &flavour=PGSQL %then %do;
put " ,"@;
%end;
%end;
%if &vtype=N %then %do;
%if &flavour=BASE %then %do;
put &var;
%end;
%else %if &flavour=PGSQL %then %do;
if missing(&var) then put 'NULL';
else put &var;
%end;
%end;
%else %do;
_____str="'"!!trim(tranwrd(&var,"'","''"))!!"'";
put _____str;
%end;
%end;
%if &flavour=BASE %then %do;
put ';';
%end;
%else %if &flavour=PGSQL %then %do;
put ');';
%end;
if _n_=&nobs then put /;
run;
%mend mp_ds2inserts;/**
@file @file
@brief Checks an input filter table for validity @brief Checks an input filter table for validity
@details Performs checks on the input table to ensure it arrives in the @details Performs checks on the input table to ensure it arrives in the
@@ -4250,12 +4397,13 @@ run;
%mp_getddl(work,test,flavour=tsql,showlog=YES) %mp_getddl(work,test,flavour=tsql,showlog=YES)
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_existfileref.sas
@li mp_getconstraints.sas @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 (optional) @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 _append_ the DDL. If it does not exist,
be assigned to TEMP. it will be created.
@param flavour= The type of DDL to create (default=SAS). Supported=TSQL @param flavour= The type of DDL to create (default=SAS). Supported=TSQL
@param showlog= Set to YES to show the DDL in the log @param showlog= Set to YES to show the DDL in the log
@param schema= Choose a preferred schema name (default is to use actual schema @param schema= Choose a preferred schema name (default is to use actual schema
@@ -4271,9 +4419,10 @@ run;
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
/* check fileref is assigned */ /* check fileref is assigned */
%if %sysfunc(fileref(&fref)) > 0 %then %do; %if %mf_existfileref(&outref)=0 %then %do;
filename &fref temp; filename &outref temp ;
%end; %end;
%if %length(&libref)=0 %then %let libref=WORK; %if %length(&libref)=0 %then %let libref=WORK;
%let flavour=%upcase(&flavour); %let flavour=%upcase(&flavour);
@@ -4352,7 +4501,7 @@ create table _data_ as
%mend addConst; %mend addConst;
data _null_; data _null_;
file &fref; file &fref mod;
put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
run; run;
@@ -5009,6 +5158,8 @@ create table &outds (rename=(
@li mf_getvartype.sas @li mf_getvartype.sas
@param [in] libds dataset to hash @param [in] libds dataset to hash
@param [in] salt= Provide a salt (could be, for instance, the name of the
dataset). Max 32 chars.
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This @param [out] outds= (work.mf_hashdataset) The output dataset to create. This
will contain one column (hashkey) with one observation (a hex32. will contain one column (hashkey) with one observation (a hex32.
representation of the input hash) representation of the input hash)
@@ -5022,7 +5173,8 @@ create table &outds (rename=(
%macro mp_hashdataset( %macro mp_hashdataset(
libds, libds,
outds= outds=,
salt=
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%if %mf_getattrn(&libds,NLOBS)=0 %then %do; %if %mf_getattrn(&libds,NLOBS)=0 %then %do;
%put %str(WARN)ING: Dataset &libds is empty;, or is not a dataset; %put %str(WARN)ING: Dataset &libds is empty;, or is not a dataset;
@@ -5042,7 +5194,7 @@ create table &outds (rename=(
%let varlist=%mf_getvarlist(&libds); %let varlist=%mf_getvarlist(&libds);
data &outds(rename=(&keyvar=hashkey) keep=&keyvar); data &outds(rename=(&keyvar=hashkey) keep=&keyvar);
length &prevkeyvar &keyvar $32; length &prevkeyvar &keyvar $32;
retain &prevkeyvar; retain &prevkeyvar "&salt";
set &libds end=&lastvar; set &libds end=&lastvar;
/* hash should include previous row */ /* hash should include previous row */
&keyvar=put(md5(&prevkeyvar &keyvar=put(md5(&prevkeyvar

View File

@@ -20,6 +20,10 @@
located. If not provided, is ignored. located. If not provided, is ignored.
@param [out] outds= (0) The output table to load. If not provided, will @param [out] outds= (0) The output table to load. If not provided, will
default to the table in the &ds parameter. default to the table in the &ds parameter.
@param [in] flavour= (BASE) The SQL flavour to be applied to the output. Valid
options:
@li BASE (default) - suitable for regular proc sql
@li PGSQL - Used for Postgres databases
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_existfileref.sas @li mf_existfileref.sas
@@ -31,18 +35,29 @@
@author Allan Bowe (credit mjsq) @author Allan Bowe (credit mjsq)
**/ **/
%macro mp_ds2inserts(ds, outref=0,outlib=0,outds=0 %macro mp_ds2inserts(ds, outref=0,outlib=0,outds=0,flavour=BASE
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%if not %sysfunc(exist(&ds)) %then %do; %if not %sysfunc(exist(&ds)) %then %do;
%put %str(WARN)ING: &ds does not exist; %put %str(WAR)NING: &ds does not exist;
%return;
%end;
%if not %sysfunc(exist(&ds)) %then %do;
%put %str(WAR)NING: &ds does not exist;
%return; %return;
%end; %end;
%if %index(&ds,.)=0 %then %let ds=WORK.&ds; %if %index(&ds,.)=0 %then %let ds=WORK.&ds;
%let flavour=%upcase(&flavour);
%if &flavour ne BASE and &flavour ne PGSQL %then %do;
%put %str(WAR)NING: &flavour is not supported;
%return;
%end;
%if &outref=0 %then %do; %if &outref=0 %then %do;
%put %str(WARN)ING: Please provide a fileref; %put %str(WAR)NING: Please provide a fileref;
%return; %return;
%end; %end;
%if %mf_existfileref(&outref)=0 %then %do; %if %mf_existfileref(&outref)=0 %then %do;
@@ -73,12 +88,10 @@ select count(*) into: nobs TRIMMED from &ds;
run; run;
%end; %end;
%local varlist; %local varlist varlistcomma;
%let varlist=%mf_getvarlist(&ds); %let varlist=%mf_getvarlist(&ds);
%let varlistcomma=%mf_getvarlist(&ds,dlm=%str(,),quote=double);
proc format; /* credit yabwon for special null removal */
value bart ._ - .z = null
other = [best.];
/* next, export data */ /* next, export data */
data _null_; data _null_;
file &outref mod ; file &outref mod ;
@@ -92,23 +105,49 @@ data _null_;
%let var=%scan(&varlist,&i); %let var=%scan(&varlist,&i);
%let vtype=%mf_getvartype(&ds,&var); %let vtype=%mf_getvartype(&ds,&var);
%if &i=1 %then %do; %if &i=1 %then %do;
put "insert into &outlib.&outds set "; %if &flavour=BASE %then %do;
put " &var="@; put "insert into &outlib.&outds set ";
put " &var="@;
%end;
%else %if &flavour=PGSQL %then %do;
_____str=cats(
"INSERT INTO &outlib.&outds ("
,symget('varlistcomma')
,") VALUES ("
);
put _____str;
put " "@;
%end;
%end; %end;
%else %do; %else %do;
put " ,&var="@; %if &flavour=BASE %then %do;
put " ,&var="@;
%end;
%else %if &flavour=PGSQL %then %do;
put " ,"@;
%end;
%end; %end;
%if &vtype=N %then %do; %if &vtype=N %then %do;
/* @todo - deal with nulls in other db flavours */ %if &flavour=BASE %then %do;
/* from ._ to .z */ put &var;
put &var; %end;
%else %if &flavour=PGSQL %then %do;
if missing(&var) then put 'NULL';
else put &var;
%end;
%end; %end;
%else %do; %else %do;
_____str="'"!!trim(tranwrd(&var,"'","''"))!!"'"; _____str="'"!!trim(tranwrd(&var,"'","''"))!!"'";
put _____str; put _____str;
%end; %end;
%end; %end;
put ';'; %if &flavour=BASE %then %do;
put ';';
%end;
%else %if &flavour=PGSQL %then %do;
put ');';
%end;
if _n_=&nobs then put /; if _n_=&nobs then put /;
run; run;

View File

@@ -16,12 +16,13 @@
%mp_getddl(work,test,flavour=tsql,showlog=YES) %mp_getddl(work,test,flavour=tsql,showlog=YES)
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_existfileref.sas
@li mp_getconstraints.sas @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 (optional) @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 _append_ the DDL. If it does not exist,
be assigned to TEMP. it will be created.
@param flavour= The type of DDL to create (default=SAS). Supported=TSQL @param flavour= The type of DDL to create (default=SAS). Supported=TSQL
@param showlog= Set to YES to show the DDL in the log @param showlog= Set to YES to show the DDL in the log
@param schema= Choose a preferred schema name (default is to use actual schema @param schema= Choose a preferred schema name (default is to use actual schema
@@ -37,9 +38,10 @@
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
/* check fileref is assigned */ /* check fileref is assigned */
%if %sysfunc(fileref(&fref)) > 0 %then %do; %if %mf_existfileref(&outref)=0 %then %do;
filename &fref temp; filename &outref temp ;
%end; %end;
%if %length(&libref)=0 %then %let libref=WORK; %if %length(&libref)=0 %then %let libref=WORK;
%let flavour=%upcase(&flavour); %let flavour=%upcase(&flavour);
@@ -118,7 +120,7 @@ create table _data_ as
%mend addConst; %mend addConst;
data _null_; data _null_;
file &fref; file &fref mod;
put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */";
run; run;

View File

@@ -20,6 +20,8 @@
@li mf_getvartype.sas @li mf_getvartype.sas
@param [in] libds dataset to hash @param [in] libds dataset to hash
@param [in] salt= Provide a salt (could be, for instance, the name of the
dataset). Max 32 chars.
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This @param [out] outds= (work.mf_hashdataset) The output dataset to create. This
will contain one column (hashkey) with one observation (a hex32. will contain one column (hashkey) with one observation (a hex32.
representation of the input hash) representation of the input hash)
@@ -33,7 +35,8 @@
%macro mp_hashdataset( %macro mp_hashdataset(
libds, libds,
outds= outds=,
salt=
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%if %mf_getattrn(&libds,NLOBS)=0 %then %do; %if %mf_getattrn(&libds,NLOBS)=0 %then %do;
%put %str(WARN)ING: Dataset &libds is empty;, or is not a dataset; %put %str(WARN)ING: Dataset &libds is empty;, or is not a dataset;
@@ -53,7 +56,7 @@
%let varlist=%mf_getvarlist(&libds); %let varlist=%mf_getvarlist(&libds);
data &outds(rename=(&keyvar=hashkey) keep=&keyvar); data &outds(rename=(&keyvar=hashkey) keep=&keyvar);
length &prevkeyvar &keyvar $32; length &prevkeyvar &keyvar $32;
retain &prevkeyvar; retain &prevkeyvar "&salt";
set &libds end=&lastvar; set &libds end=&lastvar;
/* hash should include previous row */ /* hash should include previous row */
&keyvar=put(md5(&prevkeyvar &keyvar=put(md5(&prevkeyvar