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 1/5] 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 From 8466acc7a7dfafb053e7ad6214bc0efa21e1b31f Mon Sep 17 00:00:00 2001 From: rafgag <69139928+rafgag@users.noreply.github.com> Date: Tue, 4 Aug 2020 11:25:59 +0200 Subject: [PATCH 2/5] Update mp_getddl.sas --- base/mp_getddl.sas | 74 ++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index 6cb8946..073bf46 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -12,6 +12,10 @@ 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 fref= the fileref to which to write the DDL. If not preassigned, will @@ -58,7 +62,7 @@ create table _data_ as %local colinfo; %let colinfo=&syslast; %local dsnlist; -select distinct upcase(memname) into: dsnlist + select distinct upcase(memname) into: dsnlist separated by ' ' from &syslast ; @@ -67,16 +71,27 @@ 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; + +%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; + 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; @@ -115,16 +130,7 @@ run; 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; + %addConst data _null_; file &fref mod; @@ -173,19 +179,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 ctype $11; - set &tabconst (where=(table_name="&curds")) 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); - column_list=strip(column_list); - put " ,CONSTRAINT " constraint_name " " ctype "(" column_list ")"; + put "[" name +(-1) "]" fmt notnul; run; + /* Extra step for data constraints */ + %addConst + data _null_; file &fref mod; put ')'; @@ -249,16 +248,7 @@ run; run; /* Extra step for data constraints */ - data _null_; - length ctype $11; - set &tabconst (where=(table_name="&curds")) 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); - column_list=strip(column_list); - put " ,CONSTRAINT " constraint_name " " ctype "(" column_list ")"; - run; + %addConst data _null_; file &fref mod; From 1373957031290434a06fd13d2d3017cca11b2696 Mon Sep 17 00:00:00 2001 From: rafgag <69139928+rafgag@users.noreply.github.com> Date: Tue, 4 Aug 2020 11:30:12 +0200 Subject: [PATCH 3/5] Update mp_getddl.sas --- base/mp_getddl.sas | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index 073bf46..cd08e4e 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -4,7 +4,9 @@ @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'; From 958f5098942c873101607d5264aadb1a76211b42 Mon Sep 17 00:00:00 2001 From: rafgag <69139928+rafgag@users.noreply.github.com> Date: Tue, 4 Aug 2020 11:34:19 +0200 Subject: [PATCH 4/5] Update mp_getddl.sas --- base/mp_getddl.sas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index cd08e4e..457613d 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -74,7 +74,7 @@ quit; %mp_getconstraints(lib=%upcase(&libref),ds=%upcase(&ds),outds=_data_) %local colconst; %let colconst=&syslast; -%macro addConst; +%macro addConst(); data _null_; length ctype $11; set &colconst (where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))) end=last; From 1986732573c445e476d702be88e1fe8c3b803f2a Mon Sep 17 00:00:00 2001 From: rafgag <69139928+rafgag@users.noreply.github.com> Date: Tue, 4 Aug 2020 12:00:05 +0200 Subject: [PATCH 5/5] Update mp_getddl.sas --- base/mp_getddl.sas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/mp_getddl.sas b/base/mp_getddl.sas index 457613d..ce3dca6 100644 --- a/base/mp_getddl.sas +++ b/base/mp_getddl.sas @@ -132,7 +132,7 @@ run; run; /* Extra step for data constraints */ - %addConst + %addConst() data _null_; file &fref mod; @@ -185,7 +185,7 @@ run; run; /* Extra step for data constraints */ - %addConst + %addConst() data _null_; file &fref mod; @@ -250,7 +250,7 @@ run; run; /* Extra step for data constraints */ - %addConst + %addConst() data _null_; file &fref mod;