├── .gitignore ├── ExcelScreenShot.png ├── .gitattributes ├── install.sql ├── TE_TEMPLATES.sql ├── TE_DEFAULT_HELPER_TEMPLATES.pks ├── demos ├── basic example.sql ├── html example.sql ├── BUILD_HELLO_WORLD.sql ├── TEST_BUILD_TAPI.sql └── xlsx example.sql ├── LICENSE ├── test ├── test_build.pks └── test_build.pkb ├── TE_TEMPLATES_API.md ├── TE_SYNTAX.pks ├── tePLSQL.pks ├── TE_SYNTAX.pkb ├── DefaultHelperTemplates.md ├── TE_TEMPLATES_API.pks ├── TE_TEMPLATES_API.pkb ├── TE_DEFAULT_HELPER_TEMPLATES.pkb └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .Rhistory 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /ExcelScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/osalvador/tePLSQL/HEAD/ExcelScreenShot.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /install.sql: -------------------------------------------------------------------------------- 1 | Prompt creating table 2 | @@TE_TEMPLATES.sql 3 | 4 | Prompt creating Syntax checking package 5 | @@TE_SYNTAX.pks 6 | @@TE_SYNTAX.pkb 7 | 8 | Prompt create template api package 9 | @@TE_TEMPLATES_API.pks 10 | @@TE_TEMPLATES_API.pkb 11 | 12 | Prompt create template package 13 | @@tePLSQL.pks 14 | @@tePLSQL.pkb 15 | 16 | Prompt installing default helper templates 17 | @@TE_DEFAULT_HELPER_TEMPLATES.pks 18 | @@TE_DEFAULT_HELPER_TEMPLATES.pkb 19 | 20 | exec te_default_helper_templates.install_templates; 21 | commit; 22 | 23 | 24 | Prompt done 25 | -------------------------------------------------------------------------------- /TE_TEMPLATES.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE TE_TEMPLATES 2 | ( 3 | NAME VARCHAR2(300 BYTE), 4 | TEMPLATE CLOB, 5 | DESCRIPTION VARCHAR2(300 BYTE), 6 | CREATED_BY VARCHAR2(100 BYTE) DEFAULT user NOT NULL, 7 | CREATED_DATE DATE DEFAULT SYSDATE NOT NULL, 8 | MODIFIED_BY VARCHAR2(100 BYTE) DEFAULT user NOT NULL, 9 | MODIFIED_DATE DATE DEFAULT SYSDATE NOT NULL 10 | ); 11 | 12 | CREATE UNIQUE INDEX TE_TEMPLATES_PK ON TE_TEMPLATES 13 | (NAME); 14 | 15 | ALTER TABLE TE_TEMPLATES ADD ( 16 | CONSTRAINT TE_TEMPLATES_PK 17 | PRIMARY KEY 18 | (NAME)); 19 | -------------------------------------------------------------------------------- /TE_DEFAULT_HELPER_TEMPLATES.pks: -------------------------------------------------------------------------------- 1 | create or replace 2 | package te_default_helper_templates 3 | as 4 | /** 5 | * This package is for distributing 6 | * the default Helper Templates for tePLSQL. 7 | * 8 | * execute the install procedure to load 9 | * the templates into TE_TEMPLATES 10 | * 11 | * @headcom 12 | */ 13 | 14 | g_base_name constant te_templates.name%type := 'teplsql.helper.default'; 15 | 16 | /** 17 | * installs the templates into TE_TEMPLATES 18 | */ 19 | procedure install_templates; 20 | 21 | /** 22 | * Returns the Base Name of the default templates. 23 | * Used in SQL statements. 24 | */ 25 | function base_name return te_templates.name%type; 26 | 27 | end te_default_helper_templates; 28 | / 29 | -------------------------------------------------------------------------------- /demos/basic example.sql: -------------------------------------------------------------------------------- 1 | set timing on; 2 | set serveroutput on; 3 | 4 | DECLARE 5 | p_template VARCHAR2 (32000); 6 | p_vars teplsql.t_assoc_array; 7 | BEGIN 8 | p_template := 9 | q'[<%/* Using variables */%> 10 | Hi ${FullName}! 11 | 12 | <%/* Using expressions */%> 13 | Today <%= TO_CHAR(SYSDATE, 'DD-MM-YYYY') %> is a great day! 14 | 15 | <% --Using external variable in the query loop 16 | for c1 in (select username, user_id from all_users where username = upper('${username}')) loop %> 17 | Username: <%= c1.username %>, ID:<%= c1.user_id %>. 18 | <% end loop; %> 19 | 20 | <%/* Escaping chars */%> 21 | This is the tePLSQL code block syntax <\\% ... %\\> 22 | 23 | <%/* Regards */%> 24 | Bye <%=UPPER('${username}')%>.]'; 25 | 26 | --Key-value variables. 27 | p_vars ('FullName') := 'Oscar Salvador Magallanes'; 28 | p_vars ('username') := 'test'; 29 | 30 | p_template := teplsql.render (p_vars, p_template); 31 | 32 | DBMS_OUTPUT.put_line (p_template); 33 | END; 34 | -------------------------------------------------------------------------------- /demos/html example.sql: -------------------------------------------------------------------------------- 1 | set timing on; 2 | set serveroutput on; 3 | 4 | DECLARE 5 | p_template CLOB; 6 | p_vars teplsql.t_assoc_array; 7 | BEGIN 8 | p_template := 9 | q'[ 10 | 11 | 12 | ${title} 13 | 14 | 15 |

Print Sequence numbers

16 |
17 | <%for i in ${initValue} .. ${lastValue} loop %> 18 | <%= i %>
19 | <% end loop;%> 20 |

Print the Odd numbers of sequence

21 |
22 | <% /*You can insert PLSQL comments as always*/ 23 | for i in ${initValue} .. ${lastValue} 24 | loop 25 | if mod(i,2) <> 0 26 | then %> 27 | <%= i %>
28 | <% end if; 29 | end loop; %> 30 | 31 | ]'; 32 | 33 | --Key-value variables. 34 | p_vars ('title') := 'Number sequence'; 35 | p_vars ('initValue') := 5; 36 | p_vars ('lastValue') := 20; 37 | 38 | p_template := teplsql.render (p_vars, p_template); 39 | 40 | DBMS_OUTPUT.put_line (p_template); 41 | END; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Oscar Salvador Magallanes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/test_build.pks: -------------------------------------------------------------------------------- 1 | create or replace 2 | package test_build 3 | authid current_user 4 | as 5 | /* 6 | * Generates test code for each Helper Template type. 7 | * 8 | * To generate *just the code*, use the `make_code()` function. 9 | * To automatically display via DBMS_OUTPUT, use the `output_code` procedure. 10 | * 11 | * The only Parameters, for both function and procedure, represents the Helper Template you want to test. 12 | * 13 | * The Global Constants of the Helper Templates you can test have the form `generate_*type*` 14 | * 15 | * The actual Build Templates are in the package BODY. 16 | * 17 | * @headcom 18 | */ 19 | subtype template_name_t is te_templates.name%type; 20 | 21 | generate_variables constant template_name_t := 'variable'; 22 | generate_plsql_types constant template_name_t := 'plsql-type'; 23 | generate_packages constant template_name_t := 'package'; -- todo 24 | generate_procedures constant template_name_t := 'procedure'; 25 | generate_exceptions constant template_name_t := 'exception'; 26 | generate_select constant template_name_t := 'select'; 27 | generate_build constant template_name_t := 'build'; 28 | 29 | template_not_implemented exception; 30 | pragma exception_init( template_not_implemented, -20000); 31 | 32 | /* 33 | * Common code generator for testing Build Template. 34 | * 35 | * Used by the `oddgen` plugin 36 | * 37 | * @param template_name Name of the template to generate 38 | * @return Resulting template (or error) 39 | */ 40 | function make_code( template_name in template_name_t ) return clob; 41 | 42 | /* 43 | * Wrapper for `make_code()`. 44 | * Displays the results to DBMS_OUTPUT 45 | * 46 | * @param template_name in template_name_t 47 | */ 48 | procedure output_code( template_name in template_name_t ); 49 | 50 | end; 51 | / -------------------------------------------------------------------------------- /TE_TEMPLATES_API.md: -------------------------------------------------------------------------------- 1 | Application Program Interface [API] against the TE_TEMPLATES table for the tePLSQL project. 2 | === 3 | 4 | This package imports and exports a series of tePLSQL templates for the TE_TEMPLATES using XML. 5 | 6 | ## File Format 7 | Example XML Format: 8 | 9 | ```xml 10 | 11 | 12 | 21 | 22 | 23 | ``` 24 | 25 | - File Extenstion should be .xml or .teplsql 26 | - DATE columns are those imported/exported via XML SQL. YYYY-MM-DD 27 | - The Node "/teplsql/templates/template/TEMPLATE" can be CDATA type data. 28 | - Multiple /teplsql/templates/template Nodes are expected. 29 | 30 | ## Security 31 | This is an AUTHID CURRENT_USER package. 32 | 33 | The caller must have appropriate INSERT/UPDATE/SELECT permission on the TE_TEMPLATES table. 34 | 35 | For APEX: 36 | 37 | - The 'parsing schema' needs EXECUTE permission in order to run. (This is in addtion to INSERT/SELECT/UPDATE on TE_TEMPLATES 38 | 39 | For Oracle Directory: 40 | 41 | - The caller needs INSERT/SELECT/UPDATE permissions on the table TE_TEMPLATES 42 | - The caller must also have appropriate READ/WRITE permission on the Oracle Directory if the "directory_*" interfaces are used. 43 | 44 | ## Primative Functions 45 | These functions are the main functions of the package. 46 | 47 | - `xml_import` - imports an XML LOB into the TE_TEMPLATES table 48 | - `xml_export` - returns the XML in CLOB format (todo: this should return an XMLType) 49 | - `assert` - this verifies that the XML is valid for import() 50 | 51 | ## PL/SQL Interfaces 52 | These procedures allow you to import from/export to a file using an Oracle Directoyr 53 | 54 | - `file_import` - imports templates from an XML file found in an Oracle Directory. 55 | - `file_export` - exports templates into an XML file located in an Oracle Directory. 56 | 57 | ## APEX Interfaces 58 | These procedures are for use from within Oracle Application Express (APEX) 59 | 60 | - `apex_import` - use to import a file uploaded via "File Browse..." Item type into APEX_APPLICATION_TEMP_FILES. APEX 5.0 or higher is required 61 | - `apex_export` - a BEFORE HEADER process that allows the end-user to download the XML file. The Filename must end in xml or teplsql 62 | 63 | ## List of Values 64 | 65 | These are Pipelined Functions that allow you to create a List of Values for your application. 66 | 67 | - `import_options_lov` - returns a list of options for the import() series of procedures 68 | - `export_options_lov` - returns a list of option for the export() series of procedures 69 | 70 | ### IMPORT Options 71 | 72 | - `g_import_overwrite` - if NAME matches, always OVERWRITE 73 | - `g_import_ignore` - if NAME matches, ignore 74 | - `g_import_error` - if NAME mathches, raise an error 75 | 76 | ### EXPORTS Options 77 | 78 | - `g_export_exact` - Match p_search_values against NAME using a case insentive exact mathch. 79 | - `g_export_like` - Match p_search_values against NAME using a case insentive LIKE match. You must provide "%" keys. 80 | - `g_export_regexp` - Match p_search_values against NAME using a case sensitive Regular Expression match. 81 | -------------------------------------------------------------------------------- /demos/BUILD_HELLO_WORLD.sql: -------------------------------------------------------------------------------- 1 | create or replace procedure build_hello_world( indent_string in varchar2 default ' ' ) 2 | authid current_user 3 | as 4 | p_vars teplsql.t_assoc_array; 5 | v_returnvalue clob; 6 | p_template clob; 7 | begin 8 | p_vars( 'schema' ) := USER; 9 | p_vars( teplsql.g_set_indention_string ) := indent_string; 10 | 11 | 12 | v_returnvalue := teplsql.process_build( p_vars, 'HelloWorld', 'BUILD_HELLO_WORLD', 'PROCEDURE' ); 13 | 14 | dbms_output.put_line( v_returnvalue ); 15 | 16 | $if false $then 17 | <%@ template( template_name=HelloWorld, build=make ) %> 18 | <%@ extends( package, my_pkg) %> 19 | <%@ block( init ) %>-- package init block 20 | dbms_output.put_line( 'Package Initialization' ); 21 | <%@ enblock %> 22 | <%@ extends( variable, pi ) %> 23 | <%@ block( data-type ) %>number<%@ enblock %> 24 | <%@ block( constant-value ) %>3.14159<%@ enblock %> 25 | <%@ block( documentation ) %>-- the circle is now complete\\\\n<%@ enblock %> 26 | <%@ enextends %> 27 | <%@ extends( variable, g_hw ) %> 28 | <%@ block( data-type ) %><%@ include( ${super.super}.plsql-type.c1_t.name ) %><%@ enblock %> 29 | <%@ block( value ) %>'hello'<%@ enblock %> 30 | <%@ enextends %> 31 | <%@ extends( variable, foo ) %> 32 | <%@ block( data-type ) %>interval day to second<%@ enblock %> 33 | <%@ enextends %> 34 | <%@ extends( exception, exception1 ) %><%@ block( number ) %>-20101<%@ enblock %><%@ enextends %> 35 | <%@ extends( select, cursor_one ) %><%@ enextends %> 36 | <%@ extends( plsql-type, c1_t ) %> 37 | <%@ block( data-type ) %>varchar2(50)<%@ enblock %> 38 | <%@ block( nt-name ) %>nt_name<%@ enblock %> 39 | <%@ block( aa-name ) %>aa_name<%@ enblock %> 40 | <%@ block( ref-name ) %>make_no_ref<%@ enblock %> 41 | <%@ block( documentation ) %>-- subtype + nt,aa\\\\n<%@ enblock %> 42 | <%@ enextends %> 43 | <%@ extends( plsql-type, my_txt_t ) %> 44 | <%@ block( record ) %>( bob varchar2(10) )<%@ enblock %> 45 | <%@ block( ref-name ) %>ref_name<%@ enblock %> 46 | <%@ block( documentation ) %>-- record + ref\\\\n<%@ enblock %> 47 | <%@ enextends %> 48 | <%@ extends( procedure, outer_p ) %> 49 | <%@ block( bdy ) %><%@ include( ${this}.procedure.inner_p.name ) %>; 50 | <%@ enblock %> 51 | <%@ extends( exceptions-block, bad-boy ) %> 52 | <%@ block( body ) %><%@ include( ${super.super.super.super}.exception.exception1.when-clause ) %><%@ enblock %> 53 | <%@ enextends %> 54 | <%@ extends(procedure, inner_p ) %> 55 | <%@ block( bdy ) %>if dbms_random.value() > 0.5 then 56 | dbms_output.put_line( 'Hello World' ); 57 | else 58 | raise <%@ include( ${super.super.super.super}.exception.exception1.name ) %>; 59 | end if; 60 | <%@ enblock %> 61 | <%@ enextends %> 62 | <%@ enextends %> 63 | <%@ extends( procedure, outer_f ) %> 64 | <%@ block( return-variable-type ) %><%@ include( ${super.super}.plsql-type.c1_t.name ) %><%@ enblock %> 65 | <%@ extends( plsql-type, my_inner_txt_t ) %> 66 | <%@ block( data-type ) %>varchar2(50)<%@ enblock %> 67 | <%@ enextends %> 68 | <%@ extends( procedure, inner_f ) %> 69 | <%@ block( return-variable-type ) %><%@ include( ${super.super}.plsql-type.my_inner_txt_t.name ) %><%@ enblock %> 70 | <%@ block( return-variable-name ) %>inner_ret_val<%@ enblock %> 71 | <%@ block( bdy ) %><%@ include( ${this}.return-variable-name ) %> := 'Hello World';<%@ enblock %> 72 | <%@ enextends %> 73 | <%@ block(bdy)%><%@ include( ${this}.return-variable-name ) %> := <%@ include( ${this}.procedure.inner_f.name ) %>; 74 | <%@ enblock %> 75 | <%@ enextends %> 76 | -- package initialization exceptions 77 | <%@ extends( exceptions-block, bad-boy ) %> 78 | <%@ block( body ) %><%@ include( ${super.super}.exception.exception1.when-clause ) %><%@ enblock %> 79 | <%@ enextends %> 80 | 81 | <%@ enextends %> 82 | $end 83 | end; -------------------------------------------------------------------------------- /demos/TEST_BUILD_TAPI.sql: -------------------------------------------------------------------------------- 1 | create or replace procedure test_build_tapi( schema in varchar2 default USER 2 | ,table_name in varchar2 default 'TE_TEMPLATES' 3 | ,indent_string in varchar2 default ' ') 4 | as 5 | p_vars teplsql.t_assoc_array; 6 | v_returnvalue clob; 7 | p_template clob; 8 | begin 9 | p_vars( 'schema' ) := NVL( schema, USER ); 10 | p_vars( 'table_name' ) := nvl( table_name, 'TE_TEMPLATES' ); 11 | p_vars( teplsql.g_set_indention_string ) := indent_string; 12 | 13 | 14 | v_returnvalue := teplsql.process_build( p_vars, 'TestBuild', 'TEST_BUILD_TAPI', 'PROCEDURE' ); 15 | 16 | dbms_output.put_line( v_returnvalue ); 17 | 18 | $if false $then 19 | <%@ template( template_name=TestBuild, build=main ) %> 20 | <%@ extends object_type="build" object_name="TAPI" %> 21 | <%@ extends object_type="package" object_name="simple_tapi" %> 22 | <%@ block block_name="name" %>POC_${table_name}_API<%@ enblock %> 23 | <%@ extends object_type="exception" object_name="not_yet_implemented" %> 24 | <%@ block block_name="text" %>'This feature has not yet been implemented.'<%@ enblock %> 25 | <%@ block block_name="number" %>-20100<%@ enblock %> 26 | <%@ enextends %> 27 | <%@ extends object_type="function" object_name="ins" %> 28 | <%@ block block_name="spec" %>procedure <%@ include( ${this}.name ) %>( rcd in ${schema}.${table_name}%rowtype )<%@ enblock %> 29 | <%@ block block_name="documentation" %>/** 30 | * new row entry 31 | */<%@ enblock %> 32 | <%@ block block_name="bdy" %> 33 | insert into ${schema}.${table_name} ( 34 | <% for curr in "Columns"( '${schema}', '${table_name}', '-VC -ID' ) loop %> 35 | <%= curr.comma_first || curr.column_name %>\\\\n 36 | <% end loop; %> 37 | ) values ( 38 | <% for curr in "Columns"( '${schema}', '${table_name}', '-VC -ID' ) loop 39 | if curr.has_default='NO' then %> 40 | <%= curr.comma_first || 'rcd.' || curr.column_name %>\\\\n 41 | <% else 42 | declare 43 | str varchar2(4000) := curr.data_default; 44 | begin 45 | %> 46 | <%= curr.comma_first || 'nvl(rcd.' || curr.column_name || ', ' || trim(str) || ' )' %>\\\\n 47 | <% 48 | end; 49 | end if; 50 | end loop; %> 51 | );<%@ enblock %> 52 | <%@ enextends %> 53 | <%@ extends object_type="function" object_name="upd" %> 54 | <%@ block block_name="spec" %>procedure <%@ include( ${this}.name ) %>( rcd in ${schema}.${table_name}%rowtype )<%@ enblock %> 55 | <%@ block block_name="documentation" %>/** 56 | * updates a row 57 | */<%@ enblock %> 58 | <%@ block block_name="bdy" %>-- THIS = ${this} 59 | -- P = ${super} 60 | -- GP = ${super.super} 61 | update ${schema}.${table_name} a 62 | set 63 | <% for curr in "Columns"( '${schema}', '${table_name}', '-VC -PK' ) loop %> 64 | a.<%= curr.column_name %> = rcd.<%= curr.column_name || curr.comma_last %>\\\\n 65 | <% end loop; %> 66 | where 1=1 67 | <% for curr in "Columns"( '${schema}', '${table_name}', 'PK' ) loop %> 68 | and a.<%= curr.column_name %> = rcd.<%= curr.column_name %> 69 | <% end loop; %> 70 | ;<%@ enblock %> 71 | <%@ enextends %> 72 | <%@ extends object_type="function" object_name="del" %> 73 | <%@ block block_name="spec" %>procedure <%@ include( ${this}.name ) %>( rcd in ${schema}.${table_name}%rowtype )<%@ enblock %> 74 | <%@ block block_name="documentation" %>/** 75 | * deletes a record 76 | */<%@ enblock %> 77 | <%@ block block_name="bdy" %> 78 | delete from ${schema}.${table_name} a 79 | where 1=1 80 | <% for curr in "Columns"( '${schema}', '${table_name}', 'PK' ) loop %> 81 | and a.<%= curr.column_name %> = rcd.<%= curr.column_name %> 82 | <% end loop; %>;<%@ enblock %> 83 | <%@ enextends %> 84 | <%@ enextends %> 85 | <%@ enextends %> 86 | 87 | $end 88 | 89 | end; 90 | / 91 | -------------------------------------------------------------------------------- /TE_SYNTAX.pks: -------------------------------------------------------------------------------- 1 | create or replace 2 | package te_syntax 3 | authid current_user 4 | as 5 | /** 6 | * This package is for verifing and parsing of various tePLSQL Template Directives 7 | * 8 | * Currently supports: 9 | * - extends()/enextends 10 | * - block()/enblock 11 | * 12 | * @headcom 13 | **/ 14 | 15 | subtype language_token is varchar2(2000); 16 | 17 | -- list of simple tokens 18 | op constant language_token := '\('; 19 | cp constant language_token := '\)'; 20 | nspace constant language_token := '\s*'; 21 | comma constant language_token := '(' || nspace || ',' || nspace || ')'; 22 | 23 | single_word constant language_token := '[[:alnum:]_\$\{\}][[:alnum:]_.\$\{\}\-]*'; 24 | key_value constant language_token := '((' || single_word || ')=(' || single_word || '))'; 25 | 26 | param_search constant language_token := '(' || key_value || '|' || single_word || ')' || comma || '?'; 27 | 28 | /** 29 | * Describes the <%@ extends() %> syntax 30 | * 31 | * Valid format: 32 | * - extends( node-type, node-name, key=val_parms* ) 33 | **/ 34 | extends_command constant language_token := '^<%@' || nspace || 'extends' || op || nspace || '(' || single_word || comma || single_word 35 | || '(' || comma || single_word || ')*(' || comma || key_value || ')*' 36 | || ')' || nspace || cp || nspace || '%>$' ; 37 | enextends_command constant language_token := '^enextends$'; 38 | 39 | 40 | /** 41 | * Describes the <%@ block() %> syntax 42 | * 43 | * Valid format: 44 | * - block( block-name ) 45 | **/ 46 | block_command constant language_token := '^<%@' || nspace || 'block' || op || nspace || '(' || single_word || ')' || nspace || cp || nspace || '%>$'; 47 | enblock_command constant language_token := '^enblock$'; 48 | 49 | /** 50 | * Describs the <%@ include() %> syntax 51 | * 52 | * Valid format: 53 | * - include( template-name [[[[,object-name] ,object-type] ,schema] ,indent] [,key=val_parms]* ) 54 | **/ 55 | include_command constant language_token := '^<%@' || nspace || 'include' || op || nspace || '(' 56 | || single_word || '(' || comma || '(' || single_word || ')?){0,5}(' || comma || key_value || ')*' 57 | || ')' || nspace || cp || nspace || '%>$'; 58 | 59 | 60 | /** 61 | * Describs the <%@ template() %> syntax 62 | * 63 | * Valid format: 64 | * - template( key=val_parms [,key=val_parms]* ) 65 | * 66 | * HOWEVER: A key-value pair for "template_name" must exists 67 | **/ 68 | template_command constant language_token := '^<%@' || nspace || 'template' || op || nspace || '(' 69 | || key_value || '(' || comma || key_value || ')*)' || nspace || cp || nspace || '%>$'; 70 | 71 | /** 72 | * TYPES for parsed Directives 73 | */ 74 | subtype t_param is te_templates.name%type; 75 | subtype t_object_name is varchar2(128); 76 | 77 | type t_lov is table of t_param index by PLS_INTEGER; 78 | type t_key_value is table of t_param index by t_param; 79 | 80 | /** 81 | * All Template Directives fit this TYPE 82 | */ 83 | type t_generic_parameters is record ( lov t_lov, options t_key_value ); 84 | 85 | /** 86 | * Dirctive specific TYPEs 87 | */ 88 | type t_block_parameters is record ( block_name t_param ); 89 | type t_extends_parameters is record ( node_type t_param 90 | ,node_name t_param 91 | ,base_name t_param 92 | ,options t_key_value ); 93 | type t_include_parameters is record ( template_name t_param 94 | ,object_name t_object_name 95 | ,object_type t_object_name 96 | ,schema t_object_name 97 | ,indent int 98 | ,options t_key_value ); 99 | type t_template_parameters is record ( template_name t_param 100 | ,options t_key_value ); 101 | 102 | /** 103 | * common EXCEPTIONS 104 | */ 105 | invalid_syntax exception; 106 | missing_parameter exception; 107 | bad_key_value exception; 108 | unknown_parameter_format exception; 109 | 110 | /** 111 | * decodes the Parameter text into t_extends_parameters 112 | * 113 | * @param p_txt String containing just the arguments 114 | * @return Parsed arguments 115 | */ 116 | function decode_extends_parameters( p_txt in varchar2 ) return t_extends_parameters; 117 | 118 | /** 119 | * decodes the Parameter text into t_block_parameters 120 | * 121 | * @param p_txt String containing just the arguments 122 | * @returns The parsed arguments 123 | */ 124 | function decode_block_parameters( p_txt in varchar2 ) return t_block_parameters; 125 | 126 | /** 127 | * Validates the `block` Template Directive and parses its arguments 128 | * 129 | * @param p_txt A string containing the full Template Directive 130 | * @returns the paarsed argument 131 | */ 132 | function parse_block_declarative( p_txt in varchar2) return t_block_parameters; 133 | 134 | /** 135 | * Validates the `extends` Template Directive and parses its arguments 136 | * 137 | * @param p_txt A string containing the full Template Directive 138 | * @returns the paarsed argument 139 | */ 140 | function parse_extends_declarative( p_txt in varchar2) return t_extends_parameters; 141 | 142 | /** 143 | * Validate the 'template' Template Directive and parses its arguments 144 | * 145 | * @param p_txt A string containing the full Template Directive 146 | * @returns the paarsed argument 147 | */ 148 | function parse_template_declarative( p_txt in varchar2 ) return t_template_parameters; 149 | 150 | /** 151 | * Validate the 'include' Template Directive and parses its arguments 152 | * 153 | * @param p_txt A string containing the full Template Directive 154 | * @returns the paarsed argument 155 | */ 156 | function parse_include_declarative( p_txt in varchar2 ) return t_include_parameters; 157 | 158 | end te_syntax; 159 | / 160 | -------------------------------------------------------------------------------- /tePLSQL.pks: -------------------------------------------------------------------------------- 1 | create or replace PACKAGE teplsql 2 | AUTHID CURRENT_USER 3 | AS 4 | --Define data type for Template Variable names 5 | SUBTYPE t_template_variable_name IS VARCHAR2 (255); 6 | 7 | --Define data type for Template Variable values 8 | SUBTYPE t_template_variable_value IS VARCHAR2 (32767); 9 | 10 | --Define Associative Array 11 | TYPE t_assoc_array 12 | IS 13 | TABLE OF t_template_variable_value 14 | INDEX BY t_template_variable_name; 15 | 16 | null_assoc_array t_assoc_array; 17 | 18 | --Use these Template Variable Names to adjust the maximum number of includes (default=50) 19 | g_set_max_includes constant t_template_variable_name := 'tePLSQL.max_includes'; 20 | g_set_globbing_mode constant t_template_variable_name := 'tePLSQL.globbing.mode'; 21 | g_set_globbing_separator constant t_template_variable_name := 'tePLSQL.globbing.separator'; 22 | g_set_render_mode constant t_template_variable_name := 'tePLSQL.render.mode'; 23 | g_set_indention_string constant t_template_variable_name := 'tePLSQL.indention.string'; 24 | g_set_build_block constant t_template_variable_name := 'tePLSQL.build.block'; 25 | 26 | -- Valid values for globbing mode 27 | g_globbing_mode_off constant t_template_variable_value := 'off'; 28 | g_globbing_mode_on constant t_template_variable_value := 'on'; 29 | g_globbing_mode_regexp constant t_template_variable_value := 'regexp'; 30 | g_globbing_mode_like constant t_template_variable_value := 'like'; 31 | 32 | -- Valid values for reendering mode 33 | g_render_mode_hierarch_tags_only constant t_template_variable_value := 'parents'; 34 | g_render_mode_fetch_only constant t_template_variable_value := 'fetch'; 35 | g_render_mode_normal constant t_template_variable_value := 'all'; 36 | g_render_mode_build constant t_template_variable_value := 'build'; 37 | 38 | /** 39 | * Output CLOB data to the DBMS_OUTPUT.PUT_LINE 40 | * 41 | * @param p_clob the CLOB to print to the DBMS_OUTPUT 42 | */ 43 | PROCEDURE output_clob (p_clob IN CLOB); 44 | 45 | /** 46 | * Prints received data into the buffer 47 | * 48 | * @param p_data the data to print into buffer 49 | */ 50 | PROCEDURE PRINT (p_data IN CLOB); 51 | 52 | PROCEDURE p (p_data IN CLOB); 53 | 54 | PROCEDURE PRINT (p_data IN VARCHAR2); 55 | 56 | PROCEDURE p (p_data IN VARCHAR2); 57 | 58 | PROCEDURE PRINT (p_data IN NUMBER); 59 | 60 | PROCEDURE p (p_data IN NUMBER); 61 | 62 | /** 63 | * Renders the template received as parameter. 64 | * 65 | * @param p_vars the template's arguments and engine properties. 66 | * @param p_template the template's body. 67 | * @param p_error_template if an error occurs, the template processed with the error description 68 | * @return the processed template. 69 | */ 70 | FUNCTION render (p_vars IN t_assoc_array DEFAULT null_assoc_array 71 | , p_template IN CLOB 72 | , p_error_template OUT NOCOPY CLOB) 73 | RETURN CLOB; 74 | 75 | /** 76 | * Renders the template received as parameter. Overloaded function for backward compatibility. 77 | * 78 | * @param p_vars the template's arguments and engine properties. 79 | * @param p_template the template's body. 80 | * @return the processed template. 81 | */ 82 | FUNCTION render (p_vars IN t_assoc_array DEFAULT null_assoc_array , p_template IN CLOB) 83 | RETURN CLOB; 84 | 85 | /** 86 | * Receives the name of the object, usually a package, 87 | * which contains an embedded template. 88 | * The template is extracted and is rendered with `render` function 89 | * 90 | * @param p_vars the template's arguments and engine properties. 91 | * @param p_template_name the name of the template 92 | * @param p_object_name the name of the object (usually the name of the package) 93 | * @param p_object_type the type of the object (PACKAGE, PROCEDURE, FUNCTION...) 94 | * @param p_schema the object's schema name. 95 | * @return the processed template. 96 | */ 97 | FUNCTION process (p_vars IN t_assoc_array DEFAULT null_assoc_array 98 | , p_template_name IN VARCHAR2 DEFAULT NULL 99 | , p_object_name IN VARCHAR2 DEFAULT 'TE_TEMPLATES' 100 | , p_object_type IN VARCHAR2 DEFAULT 'PACKAGE' 101 | , p_schema IN VARCHAR2 DEFAULT NULL ) 102 | RETURN CLOB; 103 | 104 | function process_build (p_vars IN t_assoc_array DEFAULT null_assoc_array 105 | , p_template_name IN VARCHAR2 DEFAULT NULL 106 | , p_object_name IN VARCHAR2 DEFAULT 'TE_TEMPLATES' 107 | , p_object_type IN VARCHAR2 DEFAULT 'PACKAGE' 108 | , p_schema IN VARCHAR2 DEFAULT NULL ) 109 | RETURN CLOB; 110 | 111 | function copy_helper_template( to_base_name in varchar2 112 | ,from_base_name in varchar2 113 | ,object_type in varchar2 114 | ,object_name in varchar2 115 | ,use_gtt in varchar2 default null ) 116 | return varchar2; 117 | 118 | function build_code_from_xml( xml_build in xmltype, to_base_name in varchar2, use_gtt in varchar2 default null ) return varchar2; 119 | 120 | 121 | -- function indent_template( p_clob in clob 122 | -- , indent_size in int default 0 123 | -- , indent_txt in varchar2 default ' ' ) 124 | -- return clob; 125 | 126 | function convert_extends( p_clob in clob ) return clob; 127 | procedure validate_build_template( template_clob in clob ); 128 | 129 | procedure begin_indent(n in int default null); 130 | procedure end_indent; 131 | procedure set_tab( n in int ); 132 | procedure goto_tab( n in int ); 133 | 134 | END teplsql; 135 | / 136 | -------------------------------------------------------------------------------- /demos/xlsx example.sql: -------------------------------------------------------------------------------- 1 | set timing on; 2 | set serveroutput on; 3 | 4 | DECLARE 5 | p_template CLOB; 6 | p_vars teplsql.t_assoc_array; 7 | BEGIN 8 | p_template := 9 | q'[ 10 | 11 | 16 | 17 | Magallanes 18 | Magallanes 19 | 2015-09-18T10:32:16Z 20 | 2015-09-18T10:37:32Z 21 | 15.00 22 | 23 | 24 | 25 | 26 | 27 | 11045 28 | 17389 29 | 0 30 | 0 31 | False 32 | False 33 | 34 | 35 | 43 | 53 | 62 | 72 | 77 | 80 | 85 | 90 | 94 | 99 | 100 | 101 | 104 | 105 | column A 106 | column B 107 | column C 108 | column D 109 | column E 110 | 111 | <% for i in 1 .. 26 loop%> 112 | 113 | <%=i%> 114 | <%=CHR (i + 64)%> 115 | <%=i%> 116 | <%=i+10%> 117 | <%=i+20%> 118 | 119 | <% end loop; %> 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
135 | 136 | 137 |
138 |