From 45e646565f5b5e902e23c36b81e1831ee26ec6ec Mon Sep 17 00:00:00 2001 From: rafgag <69139928+rafgag@users.noreply.github.com> Date: Mon, 3 Aug 2020 16:51:14 +0200 Subject: [PATCH] FEAT: adding Primary Key constraints --- .gitignore | 1 + base/mp_getddl.sas | 126 ++++++++++++++++++++------------------------- 2 files changed, 56 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 3c3629e..28f1ba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.DS_Store \ No newline at end of file diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index b9425b4..6cb8946 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -4,18 +4,14 @@ @details Data Definition Language relates to a set of SQL instructions used to create tables in SAS or a database. The macro can be used at table or library level. The default behaviour is to create DDL in SAS format. - Usage: - data test(index=(pk=(x y)/unique /nomiss)); x=1; y='blah'; label x='blah'; run; proc sql; describe table &syslast; - %mp_getddl(work,test,flavour=tsql,showlog=YES) - @param lib libref of the library to create DDL for. Should be assigned. @param ds dataset to create ddl for @param fref= the fileref to which to write the DDL. If not preassigned, will @@ -26,11 +22,9 @@ ,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= @@ -54,16 +48,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)" @@ -72,10 +56,28 @@ create table _data_ as %end; ; %local colinfo; %let colinfo=&syslast; + %local 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; +data _data_ (drop=column_name); + set &colconst (where = (constraint_type in ('PRIMARY','UNIQUE'))); + by libref table_name constraint_type constraint_name; + length column_list $ 500; + retain column_list; + if first.constraint_name then column_list=''; + column_list = catx(', ', column_list, column_name); + if last.constraint_name then output; +run; +%local tabconst; %let tabconst=&syslast; + data _null_; file &fref; put "/* DDL generated by &sysuserid on %sysfunc(datetime(),datetime19.) */"; @@ -84,13 +86,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; @@ -109,22 +112,23 @@ 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 */ + data _null_; + set &tabconst (where=(table_name="&curds")) end=last; + length ctype $11; + file &fref mod; + by constraint_type constraint_name; + if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY'; + else ctype=strip(constraint_type); + column_list=strip(column_list); + put " ,CONSTRAINT " constraint_name " " ctype "(" column_list ")"; run; 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; @@ -146,7 +150,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; @@ -172,28 +176,16 @@ run; put name fmt notnul; run; data _null_; - length ds $128; - set &idxinfo (where=(memname="&curds")); + length ctype $11; + set &tabconst (where=(table_name="&curds")) end=last; 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; + by constraint_type constraint_name; + if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY'; + else ctype=strip(constraint_type); + column_list=strip(column_list); + put " ,CONSTRAINT " constraint_name " " ctype "(" column_list ")"; run; + data _null_; file &fref mod; put ')'; @@ -255,32 +247,24 @@ run; if notnull='yes' then notnul=' NOT NULL'; put name fmt notnul; run; + + /* Extra step for data constraints */ data _null_; - length ds $128; - set &idxinfo (where=(memname="&curds")); + length ctype $11; + set &tabconst (where=(table_name="&curds")) end=last; 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; + by constraint_type constraint_name; + if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='PRIMARY KEY'; + else ctype=strip(constraint_type); + column_list=strip(column_list); + put " ,CONSTRAINT " constraint_name " " ctype "(" column_list ")"; run; + data _null_; file &fref mod; put ');'; run; + %end; %end; %if &showlog=YES %then %do; @@ -292,4 +276,4 @@ run; run; %end; -%mend; +%mend; \ No newline at end of file