diff --git a/all.sas b/all.sas index fb42ac1..615bb67 100644 --- a/all.sas +++ b/all.sas @@ -2449,11 +2449,13 @@ create table &outds as label x='blah'; run; proc sql; describe table &syslast; - %mp_getddl(work,test,flavour=tsql,showlog=YES) +

Dependencies

+ @li mp_getconstraints.sas + @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 be assigned to TEMP. @param flavour= The type of DDL to create (default=SAS). Supported=TSQL @@ -2462,11 +2464,9 @@ create table &outds as ,else libref) @param applydttm= for non SAS DDL, choose if columns are created with native datetime2 format or regular decimal type - @version 9.3 @author Allan Bowe @source https://github.com/sasjs/core - **/ %macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema= @@ -2490,16 +2490,6 @@ create table _data_ as ; %local tabinfo; %let tabinfo=&syslast; -create table _data_ as - select * from dictionary.indexes - where upcase(libname)="%upcase(&libref)" - %if %length(&ds)>0 %then %do; - and upcase(memname)="%upcase(&ds)" - %end; - order by idxusage, indxname, indxpos - ; -%local idxinfo; %let idxinfo=&syslast; - create table _data_ as select * from dictionary.columns where upcase(libname)="%upcase(&libref)" @@ -2508,10 +2498,43 @@ create table _data_ as %end; ; %local colinfo; %let colinfo=&syslast; + %local dsnlist; -select distinct upcase(memname) into: dsnlist + select distinct upcase(memname) into: dsnlist separated by ' ' - from &syslast; + from &syslast +; +quit; + +/* Extract all Primary Key and Unique data constraints */ +%mp_getconstraints(lib=%upcase(&libref),ds=%upcase(&ds),outds=_data_) +%local colconst; %let colconst=&syslast; + +%macro addConst(); + data _null_; + length ctype $11; + set &colconst (where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))) end=last; + file &fref mod; + by constraint_type 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; + put " ,CONSTRAINT " constraint_name ctype "(" ; + put ' ' column_name; + end; + else put ' ,' column_name; + if last.constraint_name then put " )"; + run; +%mend; + data _null_; file &fref; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; @@ -2520,13 +2543,14 @@ run; %local x curds; %if &flavour=SAS %then %do; data _null_; - file &fref; + file &fref mod; put "proc sql;"; run; %do x=1 %to %sysfunc(countw(&dsnlist)); %let curds=%scan(&dsnlist,&x); data _null_; file &fref mod; + if _n_ eq 1 then put "/* SAS Flavour DDL for %upcase(&libref).&curds */"; length nm lab $1024; set &colinfo (where=(upcase(memname)="&curds")) end=last; @@ -2545,22 +2569,14 @@ run; lab=" label="!!quote(trim(label)); if notnull='yes' then notnul=' not null'; put name type len fmt notnul lab; - if last then put ');'; run; + /* Extra step for data constraints */ + %addConst() + data _null_; - length ds $128; - set &idxinfo (where=(memname="&curds")) end=last; file &fref mod; - by idxusage indxname; - if unique='yes' then uniq=' unique'; - ds=cats(libname,'.',memname); - if first.indxname then do; - put 'create ' uniq ' index ' indxname; - put ' on ' ds '(' name @@; - end; - else put ',' name @@; - if last.indxname then put ');'; + put ');'; run; /* ods output IntegrityConstraints=ic; @@ -2582,7 +2598,7 @@ run; %let curds=%scan(&dsnlist,&x); data _null_; file &fref mod; - put "/* DDL for &schema..&curds */"; + put "/* TSQL Flavour DDL for &schema..&curds */"; data _null_; file &fref mod; set &colinfo (where=(upcase(memname)="&curds")) end=last; @@ -2605,31 +2621,12 @@ run; else if length le 8000 then fmt='[varchar]('!!cats(length)!!')'; else fmt=cats('[varchar](max)'); if notnull='yes' then notnul=' NOT NULL'; - put name fmt notnul; - run; - data _null_; - length ds $128; - set &idxinfo (where=(memname="&curds")); - file &fref mod; - by idxusage indxname; - if unique='yes' then uniq=' unique'; - ds=cats(libname,'.',memname); - if first.indxname then do; - if unique='yes' and nomiss='yes' then do; - put ' ,constraint [' indxname '] PRIMARY KEY'; - end; - else if unique='yes' then do; - /* add nonclustered in case of multiple unique indexes */ - put ' ,index [' indxname '] UNIQUE NONCLUSTERED'; - end; - put ' ('; - put ' [' name ']'; - end; - else put ' ,[' name ']'; - if last.indxname then do; - put ' )'; - end; + put "[" name +(-1) "]" fmt notnul; run; + + /* Extra step for data constraints */ + %addConst() + data _null_; file &fref mod; put ')'; @@ -2661,7 +2658,9 @@ run; 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_; @@ -2689,34 +2688,19 @@ run; else if type='num' then fmt=' DOUBLE PRECISION'; else fmt='VARCHAR('!!cats(length)!!')'; if notnull='yes' then notnul=' NOT NULL'; - put name fmt notnul; - run; - data _null_; - length ds $128; - set &idxinfo (where=(memname="&curds")); - file &fref mod; - by idxusage indxname; - if unique='yes' then uniq=' unique'; - ds=cats(libname,'.',memname); - if first.indxname then do; - if unique='yes' and nomiss='yes' then do; - put ' ,PRIMARY KEY '; - end; - else if unique='yes' then do; - /* add nonclustered in case of multiple unique indexes */ - put ' ,UNIQUE '; - end; - put ' (' name ; - end; - else put ' ,' name ; - if last.indxname then do; - put ' )'; - end; + /* 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; + %end; %end; %if &showlog=YES %then %do; @@ -2728,8 +2712,7 @@ run; run; %end; -%mend; -/** +%mend;/** @file mp_getmaxvarlengths.sas @brief Scans a dataset to find the max length of the variable values @details @@ -3928,64 +3911,6 @@ proc sql %mp_binarycopy(inloc="&inloc",outref=_webout) -%mend;/** - @file mp_testwritespeedlibrary.sas - @brief Tests the write speed of a new table in a SAS library - @details Will create a new table of a certain size in an - existing SAS library. The table will have one column, - and will be subsequently deleted. - - %mp_testwritespeedlibrary( - lib=work - ,size=0.5 - ,outds=work.results - ) - - @param lib= (WORK) The library in which to create the table - @param size= (0.1) The size in GB of the table to create - @param outds= (WORK.RESULTS) The output dataset to be created. - -

Dependencies

- @li mf_getuniquename.sas - @li mf_existds.sas - - @version 9.4 - @author Allan Bowe - -**/ - -%macro mp_testwritespeedlibrary(lib=WORK - ,outds=work.results - ,size=0.1 -)/*/STORE SOURCE*/; -%local ds start; - -/* find an unused, unique name for the new table */ -%let ds=%mf_getuniquename(); -%do %until(%mf_existds(&lib..&ds)=0); - %let ds=%mf_getuniquename(); -%end; - -%let start=%sysfunc(datetime()); - -data &lib..&ds(compress=no keep=x); - header=128*1024; - size=(1073741824/8 * &size) - header; - do x=1 to size; - output; - end; -run; - -proc sql; -drop table &lib..&ds; - -data &outds; - lib="&lib"; - start_dttm=put(&start,datetime19.); - end_dttm=put(datetime(),datetime19.); - duration_seconds=end_dttm-start_dttm; -run; - %mend;/** @file mp_unzip.sas @brief Unzips a zip file diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index b638032..9b18f31 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -222,7 +222,9 @@ run; 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_;