mirror of
https://github.com/yabwon/SAS_PACKAGES.git
synced 2025-12-11 03:04:35 +00:00
version 2.1
recompiled with new framework setup
This commit is contained in:
29
packages/SQLinDS/000_libname/dssql.sas
Normal file
29
packages/SQLinDS/000_libname/dssql.sas
Normal file
@@ -0,0 +1,29 @@
|
||||
/*** HELP START ***/
|
||||
|
||||
/* >>> dsSQL library: <<<
|
||||
*
|
||||
* The dsSQL library stores temporary views
|
||||
* generated during the %SQL() macro execution.
|
||||
* If possible a subdirectory of WORK is created as:
|
||||
|
||||
LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))/dsSQLtmp";
|
||||
|
||||
* if not possible then redirects to WORK as:
|
||||
|
||||
LIBNAME dsSQL BASE "%sysfunc(pathname(WORK))";
|
||||
|
||||
**/
|
||||
|
||||
/*** HELP END ***/
|
||||
|
||||
data _null_;
|
||||
length rc0 $ 32767 rc1 rc2 8;
|
||||
rc0 = DCREATE("dsSQLtmp", "%sysfunc(pathname(work))/" );
|
||||
rc1 = LIBNAME("dsSQL", "%sysfunc(pathname(work))/dsSQLtmp", "BASE");
|
||||
rc2 = LIBREF ("dsSQL" );
|
||||
if rc2 NE 0 then
|
||||
rc1 = LIBNAME("dsSQL", "%sysfunc(pathname(work))", "BASE");
|
||||
run;
|
||||
|
||||
/* list details about the library in the log */
|
||||
libname dsSQL LIST;
|
||||
65
packages/SQLinDS/001_macro/dssql_inner.sas
Normal file
65
packages/SQLinDS/001_macro/dssql_inner.sas
Normal file
@@ -0,0 +1,65 @@
|
||||
/*** HELP START ***/
|
||||
|
||||
/* >>> %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
|
||||
*
|
||||
**/
|
||||
|
||||
/*** HELP END ***/
|
||||
|
||||
/* inner macro */
|
||||
%MACRO dsSQL_Inner() / secure;
|
||||
%local query tempfile1 tempfile2 ps_tmp;
|
||||
%let query = %superq(query_arg);
|
||||
%let query = %sysfunc(dequote(&query));
|
||||
|
||||
%let viewname = dsSQL.dsSQLtmpview&UNIQUE_INDEX_2.;
|
||||
|
||||
%let tempfile1 = A%sysfunc(datetime(), hex7.);
|
||||
%let tempfile2 = B%sysfunc(datetime(), hex7.);
|
||||
|
||||
filename &tempfile1. temp;
|
||||
filename &tempfile2. temp;
|
||||
|
||||
%let ps_tmp = %sysfunc(getoption(ps));
|
||||
options ps = MAX;
|
||||
proc printto log = &tempfile1.;
|
||||
run;
|
||||
/* get the query shape i.e. the executed one */
|
||||
proc sql feedback noexec;
|
||||
&query
|
||||
;
|
||||
quit;
|
||||
proc printto;
|
||||
run;
|
||||
options ps = &ps_tmp.;
|
||||
|
||||
%put *** executed as ***;
|
||||
data _null_;
|
||||
infile &tempfile1. FIRSTOBS = 2; /* <- 2 to ignore header */
|
||||
file &tempfile2.;
|
||||
/* create the view name */
|
||||
if _N_ = 1 then
|
||||
put " create view &viewname. as ";
|
||||
input;
|
||||
put _infile_;
|
||||
putlog ">" _infile_;
|
||||
run;
|
||||
%put *****************;
|
||||
|
||||
proc sql;
|
||||
%include &tempfile2.; /* &query */
|
||||
;
|
||||
quit;
|
||||
filename &tempfile1. clear;
|
||||
filename &tempfile2. clear;
|
||||
%MEND dsSQL_Inner;
|
||||
56
packages/SQLinDS/001_macro/sql.sas
Normal file
56
packages/SQLinDS/001_macro/sql.sas
Normal file
@@ -0,0 +1,56 @@
|
||||
/*** HELP START ***/
|
||||
|
||||
/* >>> %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:
|
||||
|
||||
%sql(<nonempty sql querry code>)
|
||||
|
||||
* The sql querry code is limited to 32000 bytes.
|
||||
*
|
||||
* EXAMPLE 1: simple sql query
|
||||
|
||||
data class_subset;
|
||||
set %SQL(select name, sex, height from sashelp.class where age > 12);
|
||||
run;
|
||||
|
||||
* EXAMPLE 2: query with dataset options
|
||||
|
||||
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;
|
||||
|
||||
**/
|
||||
|
||||
/*** HELP END ***/
|
||||
|
||||
|
||||
/* Main User macro */
|
||||
%MACRO SQL() / PARMBUFF SECURE;
|
||||
%let SYSPBUFF = %superq(SYSPBUFF); /* macroquoting */
|
||||
%let SYSPBUFF = %substr(&SYSPBUFF, 2, %LENGTH(&SYSPBUFF) - 2); /* remove brackets */
|
||||
%let SYSPBUFF = %superq(SYSPBUFF); /* macroquoting */
|
||||
%let SYSPBUFF = %sysfunc(quote(&SYSPBUFF)); /* quotes */
|
||||
%put NOTE:*** the query ***; /* print out the query in the log */
|
||||
%put NOTE-&SYSPBUFF.;
|
||||
%put NOTE-*****************;
|
||||
|
||||
%local UNIQUE_INDEX; /* internal variable, a unique index for views */
|
||||
%let UNIQUE_INDEX = &SYSINDEX;
|
||||
%sysfunc(dsSQL(&UNIQUE_INDEX, &SYSPBUFF)) /* <-- call dsSQL() function,
|
||||
see the WORK.SQLinDSfcmp dataset */
|
||||
%MEND SQL;
|
||||
42
packages/SQLinDS/002_function/dssql.sas
Normal file
42
packages/SQLinDS/002_function/dssql.sas
Normal file
@@ -0,0 +1,42 @@
|
||||
/*** HELP START ***/
|
||||
|
||||
/* >>> 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
|
||||
*
|
||||
**/
|
||||
|
||||
/*** HELP END ***/
|
||||
|
||||
proc fcmp
|
||||
/*inlib = work.&packageName.fcmp*/
|
||||
outlib = work.&packageName.fcmp.package
|
||||
;
|
||||
function dsSQL(unique_index_2, query $) $ 41;
|
||||
length
|
||||
query query_arg $ 32000 /* max query length */
|
||||
viewname $ 41
|
||||
;
|
||||
query_arg = dequote(query);
|
||||
rc = run_macro('dsSQL_Inner' /* <-- inner macro */
|
||||
,unique_index_2
|
||||
,query_arg
|
||||
,viewname
|
||||
);
|
||||
if rc = 0 then return(trim(viewname));
|
||||
else
|
||||
do;
|
||||
put 'ERROR:[function dsSQL] A problem with the dsSQL() function';
|
||||
return(" ");
|
||||
end;
|
||||
endsub;
|
||||
run;
|
||||
quit;
|
||||
10
packages/SQLinDS/999_test/test1.sas
Normal file
10
packages/SQLinDS/999_test/test1.sas
Normal file
@@ -0,0 +1,10 @@
|
||||
proc sort data=sashelp.class out=test1;
|
||||
by age name;
|
||||
run;
|
||||
|
||||
data class;
|
||||
set %SQL(select * from sashelp.class order by age, name);
|
||||
run;
|
||||
|
||||
proc compare base = test1 compare = class;
|
||||
run;
|
||||
29
packages/SQLinDS/999_test/test2.sas
Normal file
29
packages/SQLinDS/999_test/test2.sas
Normal file
@@ -0,0 +1,29 @@
|
||||
data class_work;
|
||||
set sashelp.class;
|
||||
run;
|
||||
|
||||
data test_work;
|
||||
set %sql(select * from class_work);
|
||||
run;
|
||||
|
||||
options dlcreatedir;
|
||||
libname user "%sysfunc(pathname(work))/user";
|
||||
%put *%sysfunc(pathname(user))*;
|
||||
|
||||
data cars_user cars_user2;
|
||||
set sashelp.cars;
|
||||
run;
|
||||
|
||||
data test_user;
|
||||
set %sql(select * from cars_user);
|
||||
run;
|
||||
|
||||
data test_user2;
|
||||
set %sql(select * from user.cars_user2);
|
||||
run;
|
||||
|
||||
libname user clear;
|
||||
%put *%sysfunc(pathname(user))*;
|
||||
|
||||
proc datasets lib = work;
|
||||
run;
|
||||
45
packages/SQLinDS/description.sas
Normal file
45
packages/SQLinDS/description.sas
Normal file
@@ -0,0 +1,45 @@
|
||||
/* This is the description file for the package. */
|
||||
/* The colon (:) is a field separator and is restricted */
|
||||
/* in lines of the header part. */
|
||||
|
||||
/* **HEADER** */
|
||||
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*/
|
||||
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.*/
|
||||
Encoding: UTF8 :/*required, not null, values: UTF8, WLATIN1, LATIN2, etc. */
|
||||
|
||||
Required: "Base SAS Software" :/*optional, COMMA separated, QUOTED list, names of required SAS products, values must be like from proc setinit;run; output */
|
||||
|
||||
/* **DESCRIPTION** */
|
||||
/* 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
|
||||
|
||||
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.
|
||||
|
||||
data class;
|
||||
set %SQL(select * from sashelp.class);
|
||||
run;
|
||||
|
||||
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.
|
||||
|
||||
DESCRIPTION END:
|
||||
25
packages/SQLinDS/generate_package_sqlinds.sas
Normal file
25
packages/SQLinDS/generate_package_sqlinds.sas
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
filename packages "C:\SAS_PACKAGES\SASPackagesFramework";
|
||||
%include packages(SPFinit.sas);
|
||||
|
||||
ods html;
|
||||
%generatePackage(filesLocation=C:\SAS_PACKAGES_DEV\SQLinDS)
|
||||
|
||||
|
||||
/*
|
||||
* filename reference "packages" and "package" are keywords;
|
||||
* the first one should be used to point folder with packages;
|
||||
* the second is used internally by macros;
|
||||
|
||||
filename packages "C:\SAS_PACKAGES";
|
||||
%include packages(SPFinit.sas);
|
||||
|
||||
dm 'log;clear';
|
||||
%loadpackage(SQLinDS)
|
||||
|
||||
%helpPackage(SQLinDS)
|
||||
%helpPackage(SQLinDS,*)
|
||||
|
||||
%unloadPackage(SQLinDS)
|
||||
*/
|
||||
19
packages/SQLinDS/license.sas
Normal file
19
packages/SQLinDS/license.sas
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2012 Mike Rhoads
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
82
packages/SQLinDS/macrofunctionsandwich.sas
Normal file
82
packages/SQLinDS/macrofunctionsandwich.sas
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
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;
|
||||
BIN
packages/sqlinds.zip
Normal file
BIN
packages/sqlinds.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user