SQLinDS, source files updated

SQLinDS, source files updated
This commit is contained in:
yabwon
2020-10-14 16:33:07 +02:00
parent bfdcd238ec
commit 02f71de424
7 changed files with 102 additions and 169 deletions

View File

@@ -1,19 +1,21 @@
/*** HELP START ***/
/*
## >>> library `dsSQL`: <<< <a name="library-dssql"></a> ########################
/* >>> 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;

View File

@@ -1,19 +1,15 @@
/*** HELP START ***/
/*
## >>> `%dsSQL_Inner()` macro: <<< <a name="dssql-inner-macro"></a> #############
/* >>> %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;

View File

@@ -1,41 +1,47 @@
/*** HELP START ***/
/*
## >>> `%SQL()` macro: <<< <a name="dssql-macro"></a> ###########################
/* >>> %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(<nonempty sql querry code>)
### SYNTAX: ###################################################################
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
%sql(<nonempty sql querry code>)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 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 ***/

View File

@@ -1,19 +1,26 @@
/*** HELP START ***/
/*
## >>> `dsSQL()` function: <<< <a name="dssql-function"></a> ####################
/* >>> 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

View File

@@ -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] <a name="sqlinds-package"></a> ###############################################
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:

View File

@@ -1,6 +1,6 @@
resetline;
filename packages "C:\SAS_PACKAGES\SASPackagesFramework";
filename packages "C:\SAS_PACKAGES\SPF";
%include packages(SPFinit.sas);
ods html;

View File

@@ -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;