diff --git a/packages/SQLinDS/000_libname/dssql.sas b/packages/SQLinDS/000_libname/dssql.sas index 8b520bf..4e64c51 100644 --- a/packages/SQLinDS/000_libname/dssql.sas +++ b/packages/SQLinDS/000_libname/dssql.sas @@ -1,19 +1,21 @@ /*** HELP START ***/ +/* +## >>> library `dsSQL`: <<< ######################## -/* >>> dsSQL library: <<< - * - * The dsSQL library stores temporary views - * generated during the %SQL() macro execution. - * If possible a subdirectory of WORK is created as: +The `dsSQL` library stores temporary views +generated during the `%SQL()` macro execution. - LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))/dsSQLtmp"; - - * if not possible then redirects to WORK as: - - LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))"; - -**/ +If possible a subdirectory of the `WORK` location is created, like: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))/dsSQLtmp"; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if not possible, then redirects to the `WORK` location, like: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))"; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- +*/ /*** HELP END ***/ data _null_; @@ -25,5 +27,5 @@ data _null_; rc1 = LIBNAME("dsSQL", "%sysfunc(pathname(work))", "BASE"); run; -/* list details about the library in the log */ +/* list the details about the library in the log */ libname dsSQL LIST; diff --git a/packages/SQLinDS/001_macro/dssql_inner.sas b/packages/SQLinDS/001_macro/dssql_inner.sas index b179e5c..26256e0 100644 --- a/packages/SQLinDS/001_macro/dssql_inner.sas +++ b/packages/SQLinDS/001_macro/dssql_inner.sas @@ -1,19 +1,15 @@ /*** HELP START ***/ +/* +## >>> `%dsSQL_Inner()` macro: <<< ############# -/* >>> %dsSQL_Inner() macro: <<< - * - * Internal macro called by dsSQL() function. - * The macro generates a uniqualy named sql view on the fly - * which is stored in DSSQL library. - * - * Recommended for SAS 9.3 and higher. - * Based on paper: - * "Use the Full Power of SAS in Your Function-Style Macros" - * by Mike Rhoads, Westat, Rockville, MD - * https://support.sas.com/resources/papers/proceedings12/004-2012.pdf - * -**/ +**Internal** macro called by `dsSQL()` function. +The macro generates a uniquely named SQL view on the fly +which is then stored in the `dsSQL` library. + +Recommended for *SAS 9.3* and higher. +--- +*/ /*** HELP END ***/ /* inner macro */ @@ -57,7 +53,7 @@ %put *****************; proc sql; - %include &tempfile2.; /* &query */ + %include &tempfile2.; /* the &query */ ; quit; filename &tempfile1. clear; diff --git a/packages/SQLinDS/001_macro/sql.sas b/packages/SQLinDS/001_macro/sql.sas index 67f0ecf..407869b 100644 --- a/packages/SQLinDS/001_macro/sql.sas +++ b/packages/SQLinDS/001_macro/sql.sas @@ -1,41 +1,47 @@ /*** HELP START ***/ +/* +## >>> `%SQL()` macro: <<< ########################### -/* >>> %SQL() macro: <<< - * - * Main macro which allows to use - * SQL's queries in the data step. - * Recommended for SAS 9.3 and higher. - * Based on paper: - * "Use the Full Power of SAS in Your Function-Style Macros" - * by Mike Rhoads, Westat, Rockville, MD - * https://support.sas.com/resources/papers/proceedings12/004-2012.pdf - * - * SYNTAX: +The **main** macro which allows to use +SQL queries in the data step. + +Recommended for *SAS 9.3* and higher. + +Based on the article *"Use the Full Power of SAS in Your Function-Style Macros"* +by *Mike Rhoads* (Westat, Rockville), available at: +[https://support.sas.com/resources/papers/proceedings12/004-2012.pdf](https://support.sas.com/resources/papers/proceedings12/004-2012.pdf) - %sql() +### SYNTAX: ################################################################### +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +%sql() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * The sql querry code is limited to 32000 bytes. - * - * EXAMPLE 1: simple sql query +The sql query code is limited to *32000* bytes. - data class_subset; - set %SQL(select name, sex, height from sashelp.class where age > 12); - run; +### EXAMPLES: ################################################################# - * EXAMPLE 2: query with dataset options +**EXAMPLE 1**: simple SQL query +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data class_subset; + set %SQL(select name, sex, height from sashelp.class where age > 12); +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - data renamed; - set %SQL(select * from sashelp.class where sex = "F")(rename = (age=age2)); - run; - - * EXAMPLE 3: dictionaries in datastep - - data dictionary; - set %SQL(select * from dictionary.macros); - run; - -**/ +**EXAMPLE 2**: query with dataset options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data renamed; + set %SQL(select * from sashelp.class where sex = "F")(rename = (age=age2)); +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +**EXAMPLE 3**: dictionaries in the data step +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +data dictionary; + set %SQL(select * from dictionary.macros); +run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +--- +*/ /*** HELP END ***/ diff --git a/packages/SQLinDS/002_function/dssql.sas b/packages/SQLinDS/002_function/dssql.sas index da6ffd3..fd351bd 100644 --- a/packages/SQLinDS/002_function/dssql.sas +++ b/packages/SQLinDS/002_function/dssql.sas @@ -1,19 +1,26 @@ /*** HELP START ***/ +/* +## >>> `dsSQL()` function: <<< #################### -/* >>> dsSQL() function: <<< - * - * Internal function called by %SQL() macro. - * The function pass query code from the %SQL() - * macro to the %dsSQL_Inner() innternal macreo. - * - * Recommended for SAS 9.3 and higher. - * Based on paper: - * "Use the Full Power of SAS in Your Function-Style Macros" - * by Mike Rhoads, Westat, Rockville, MD - * https://support.sas.com/resources/papers/proceedings12/004-2012.pdf - * -**/ +**Internal** function called by the `%SQL()` macro. +The function pass a query code from the `%SQL()` +macro to the `%dsSQL_Inner()` internal macro. +Recommended for *SAS 9.3* and higher. + +### SYNTAX: ################################################################### +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas +dsSQL(unique_index_2, query) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Arguments description**: + +1. `unique_index_2` - *Numeric*, internal variable, a unique index for views. + +2. `query` - *Character*, internal variable, contains query text. + +--- +*/ /*** HELP END ***/ proc fcmp diff --git a/packages/SQLinDS/description.sas b/packages/SQLinDS/description.sas index 91214c3..8fc2ee1 100644 --- a/packages/SQLinDS/description.sas +++ b/packages/SQLinDS/description.sas @@ -6,7 +6,7 @@ Type: Package :/*required, not null, constant value*/ Package: SQLinDS :/*required, not null, up to 24 characters, naming restrictions like for a dataset name! */ Title: SQL queries in Data Step :/*required, not null*/ -Version: 2.1 :/*required, not null*/ +Version: 2.2 :/*required, not null*/ Author: Mike Rhoads (RhoadsM1@Westat.com) :/*required, not null*/ Maintainer: Bartosz Jablonski (yabwon@gmail.com) :/*required, not null*/ License: MIT :/*required, not null, values: MIT, GPL2, BSD, etc.*/ @@ -18,28 +18,32 @@ Required: "Base SAS Software" :/*optional, COMMA separated, Q /* All the text below will be used in help */ DESCRIPTION START: -The SQLinDS package is an implementation of -the macro-function-sandwich concept introduced in: -"Use the Full Power of SAS in Your Function-Style Macros" -the article by Mike Rhoads, Westat, Rockville, MD +# The SQLinDS package [ver. 2.2] ############################################### + +The **SQLinDS** package is an implementation of +the *macro-function-sandwich* concept introduced in the +*"Use the Full Power of SAS in Your Function-Style Macros"*, +the article by *Mike Rhoads (Westat, Rockville)*. Copy of the article is available at: -https://support.sas.com/resources/papers/proceedings12/004-2012.pdf - -Package provides ability to "execute" SQL queries inside a datastep, e.g. +[https://support.sas.com/resources/papers/proceedings12/004-2012.pdf](https://support.sas.com/resources/papers/proceedings12/004-2012.pdf) +Package provides ability to *execute* SQL queries inside a data step, e.g. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas data class; set %SQL(select * from sashelp.class); run; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See the help for the `%SQL()` macro to find more examples. + +### Content ################################################################### SQLinDS package contains the following components: - 1) %SQL() macro - the main package macro available for the User - - 2) dsSQL() function (internal) - 3) %dsSQL_inner() macro (internal) - 4) Library DSSQL (created in a subdirectory of the WORK library) - -See help for the %SQL() macro to find more examples. +1. `%SQL()` macro - the main package macro available for the User +2. `dsSQL()` function (internal) +3. `%dsSQL_inner()` macro (internal) +4. Library `DSSQL` (created as a subdirectory of the `WORK` library) +--- DESCRIPTION END: diff --git a/packages/SQLinDS/generate_package_sqlinds.sas b/packages/SQLinDS/generate_package_sqlinds.sas index b5c5fdf..59b431d 100644 --- a/packages/SQLinDS/generate_package_sqlinds.sas +++ b/packages/SQLinDS/generate_package_sqlinds.sas @@ -1,6 +1,6 @@ +resetline; - -filename packages "C:\SAS_PACKAGES\SASPackagesFramework"; +filename packages "C:\SAS_PACKAGES\SPF"; %include packages(SPFinit.sas); ods html; diff --git a/packages/SQLinDS/macrofunctionsandwich.sas b/packages/SQLinDS/macrofunctionsandwich.sas deleted file mode 100644 index 6dd2092..0000000 --- a/packages/SQLinDS/macrofunctionsandwich.sas +++ /dev/null @@ -1,82 +0,0 @@ - -options dlCreateDir; -libname dsSQL "%sysfunc(pathname(work))/dsSQLtmp"; - -/* makro zewnetrzne */ -%MACRO SQL() / PARMBUFF SECURE; - %let SYSPBUFF = %superq(SYSPBUFF); /* maskujemy znaki specjalne */ - %let SYSPBUFF = %substr(&SYSPBUFF,2,%LENGTH(&SYSPBUFF) - 2); /* kasujemy otwierajÄ…cy i zamykajÄ…cy nawias */ - %let SYSPBUFF = %superq(SYSPBUFF); /* maskujemy jeszcze raz */ - %let SYSPBUFF = %sysfunc(quote(&SYSPBUFF)); /* dodajemy cudzyslowy */ - %put ***the querry***; - %put &SYSPBUFF.; - %put ****************; - - %local UNIQUE_INDEX; /* dodatkowa zmienna indeksujaca, zeby tworzony widok byl unikalny */ - %let UNIQUE_INDEX = &SYSINDEX; /* przypisujemy jej wartosc */ - %sysfunc(dsSQL(&UNIQUE_INDEX, &SYSPBUFF)) /* <-- wywolulemy funkcje dsSQL */ -%MEND SQL; - -/* funkcja */ -%macro MacroFunctionSandwich_functions(); - -%local _cmplib_; -options APPEND=(cmplib = WORK.DATASTEPSQLFUNCTIONS) ; -%let _cmplib_ = %sysfunc(getoption(cmplib)); -%put NOTE:[&sysmacroname.] *&=_cmplib_*; - -options cmplib = _null_; - -proc fcmp outlib=work.datastepSQLfunctions.package; - function dsSQL(unique_index_2, query $) $ 41; - - length query query_arg $ 32000 viewname $ 41; /* query_arg mozna zmienic na dluzszy, np. 32000 :-) */ - query_arg = dequote(query); - rc = run_macro('dsSQL_Inner', unique_index_2, query_arg, viewname); /* <-- wywolulemy makro wewnetrzne dsSQL_Inner */ - if rc = 0 then return(trim(viewname)); - else do; - return(" "); - put 'ERROR:[function dsSQL] A problem with the function'; - end; - endsub; -run; - -options cmplib = &_cmplib_.; -%let _cmplib_ = %sysfunc(getoption(cmplib)); -%put NOTE:[&sysmacroname.] *&=_cmplib_*; - -%mend MacroFunctionSandwich_functions; -%MacroFunctionSandwich_functions() - -/* delete macro MacroFunctionSandwich_functions since it is not needed */ -proc sql; - create table _%sysfunc(datetime(), hex16.)_ as - select memname, objname - from dictionary.catalogs - where - objname = upcase('MACROFUNCTIONSANDWICH_FUNCTIONS') - and objtype = 'MACRO' - and libname = 'WORK' - order by memname, objname - ; -quit; -data _null_; - set _last_; - call execute('proc catalog cat = work.' !! strip(memname) !! ' et = macro force;'); - call execute('delete ' !! strip(objname) !! '; run;'); - call execute('quit;'); -run; -proc delete data = _last_; -run; - -/* makro wewnetrzne */ -%MACRO dsSQL_Inner() / SECURE; - %local query; - %let query = %superq(query_arg); - %let query = %sysfunc(dequote(&query)); - - %let viewname = dsSQL.dsSQLtmpview&UNIQUE_INDEX_2; - proc sql; - create view &viewname as &query; - quit; -%MEND dsSQL_Inner;