├── .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 |
13 | hello world
14 | This is a "Hello World" template
15 | SCOTT TIGER
16 | 2016-11-19
17 | SCOTT TIGHER
18 | 2016-11-19
19 | Hello World!
20 |
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 |
139 |
140 |
141 |
142 |
143 |
144 | 0
145 | 0
146 |
147 |
148 |
149 |
150 | 3
151 | 4
152 | 1
153 |
154 |
155 | False
156 | False
157 |
158 |
159 | ]';
160 |
161 | p_template := teplsql.render (p_vars, p_template);
162 |
163 | --Save the output as .xml file and open it with MS Excel.
164 | DBMS_OUTPUT.put_line (p_template);
165 |
166 | END;
--------------------------------------------------------------------------------
/TE_SYNTAX.pkb:
--------------------------------------------------------------------------------
1 | create or replace
2 | package body te_syntax
3 | as
4 | procedure parse_key_value( p_txt in varchar2, p_key out varchar2, p_value out varchar2 )
5 | as
6 | begin
7 | p_key := regexp_replace( trim(p_txt), key_value, '\2' );
8 | p_value := regexp_replace( trim(p_txt), key_value, '\3' );
9 | end parse_key_value;
10 |
11 | function parse_parameters( p_txt in varchar2 ) return t_generic_parameters
12 | as
13 | n int;
14 | current_parameter int := 1;
15 | token t_param;
16 |
17 | key_str t_param;
18 | val_str t_param;
19 |
20 | ret_val t_generic_parameters;
21 | begin
22 | null;
23 | n := regexp_count( p_txt, param_search );
24 |
25 | for i in 1 .. n
26 | loop
27 | token := regexp_replace( regexp_substr( p_txt, param_search, 1, i ), comma, '');
28 |
29 | case
30 | when regexp_like( token, key_value ) then
31 | parse_key_value( trim(token), key_str, val_str);
32 | ret_val.options(key_str) := val_str;
33 | when regexp_like( token, single_word ) then
34 | ret_val.lov(current_parameter) := trim(token);
35 |
36 | current_parameter := current_parameter + 1;
37 | else
38 | null;
39 | end case;
40 | end loop;
41 |
42 | return ret_val;
43 | end parse_parameters;
44 |
45 | function decode_extends_parameters( p_txt in varchar2 ) return t_extends_parameters
46 | as
47 | plist t_generic_parameters;
48 | ret_val t_extends_parameters;
49 | begin
50 | plist := parse_parameters( p_txt );
51 |
52 | if plist.lov.count < 2
53 | then
54 | raise missing_parameter;
55 | elsif plist.lov.count > 2
56 | then
57 | raise_application_error( -20111, 'Bad EXTENDS parameter "' || p_txt || '"' );
58 | raise invalid_syntax;
59 | end if;
60 |
61 | ret_val.node_type := plist.lov(1);
62 | ret_val.node_name := plist.lov(2);
63 |
64 | ret_val.options := plist.options;
65 |
66 | if ret_val.options.exists( 'base' )
67 | then
68 | ret_val.base_name := ret_val.options('base');
69 | end if;
70 |
71 | -- dbms_output.put_line( ' debug EXTENDS attribute type="' || ret_val.node_type || '" name="' || ret_val.node_name || '" base="' || ret_val.base_name || '"' );
72 |
73 | return ret_val;
74 | end decode_extends_parameters;
75 |
76 | function decode_block_parameters( p_txt in varchar2 ) return t_block_parameters
77 | as
78 | plist t_generic_parameters;
79 | ret_val t_block_parameters;
80 | begin
81 | plist := parse_parameters( p_txt );
82 |
83 | if plist.lov.count <> 1
84 | then
85 | raise invalid_syntax;
86 | elsif plist.options.count > 0
87 | then
88 | raise invalid_syntax;
89 | end if;
90 |
91 | ret_val.block_name := plist.lov(1);
92 |
93 |
94 | return ret_val;
95 | end decode_block_parameters;
96 |
97 | function decode_include_parameters( p_txt in varchar2 ) return t_include_parameters
98 | as
99 | plist t_generic_parameters;
100 | ret_val t_include_parameters;
101 | begin
102 | plist := parse_parameters( p_txt );
103 |
104 | if plist.lov.count > 5 or plist.lov.count = 0
105 | then
106 | raise invalid_syntax;
107 | end if;
108 |
109 | ret_val.template_name := plist.lov(1);
110 |
111 | if plist.lov.count > 1
112 | then
113 | ret_val.object_name := nvl( plist.lov(2), 'TE_TEMPLATES' );
114 | else
115 | ret_val.object_name := 'TE_TEMPLATES';
116 | end if;
117 |
118 | if plist.lov.count > 2
119 | then
120 | ret_val.object_type := nvl( plist.lov(3), 'PACKAGE' );
121 | else
122 | ret_val.object_type := 'PACKAGE';
123 | end if;
124 |
125 | if plist.lov.count > 3
126 | then
127 | ret_val.schema := plist.lov(4);
128 | end if;
129 |
130 | if plist.lov.count > 4 or plist.options.exists('indent')
131 | then
132 | ret_val.indent := 1;
133 | end if;
134 |
135 | ret_val.options := plist.options;
136 |
137 | return ret_val;
138 | end decode_include_parameters;
139 |
140 | function decode_template_parameters( p_txt in varchar2 ) return t_template_parameters
141 | as
142 | plist t_generic_parameters;
143 | ret_val t_template_parameters;
144 | begin
145 | plist := parse_parameters( p_txt );
146 |
147 | if not plist.options.exists( 'template_name' )
148 | then
149 | raise_application_error( -20113, 'Missing "template_name" in TEMPLATE directive "' || p_txt || '"' );
150 | end if;
151 |
152 | ret_val.template_name := plist.options( 'template_name' );
153 |
154 | ret_val.options := plist.options;
155 |
156 | return ret_val;
157 | end decode_template_parameters;
158 |
159 | function parse_block_declarative( p_txt in varchar2) return t_block_parameters
160 | as
161 | l_params t_param;
162 | begin
163 | if not regexp_like( trim(p_txt), block_command )
164 | then
165 | raise_application_error( -20112, 'Bad BLOCK directive "' || p_txt || '"' );
166 | end if;
167 |
168 | l_params := trim( regexp_replace( trim(p_txt), block_command, '\1' ) );
169 | -- dbms_output.put_line( ' debug block attributes "' || l_params || '"' );
170 |
171 | return decode_block_parameters( l_params );
172 | end parse_block_declarative;
173 |
174 | function parse_extends_declarative( p_txt in varchar2) return t_extends_parameters
175 | as
176 | l_params t_param;
177 | begin
178 | if not regexp_like( trim(p_txt), extends_command )
179 | then
180 | raise_application_error( -20110, 'Bad EXTENDS directive "' || p_txt || '"' );
181 | end if;
182 |
183 | l_params := trim( regexp_replace( trim(p_txt), extends_command, '\1' ) );
184 |
185 | return decode_extends_parameters( l_params );
186 | end parse_extends_declarative;
187 |
188 | function parse_include_declarative( p_txt in varchar2 ) return t_include_parameters
189 | as
190 | l_params t_param;
191 | begin
192 | if not regexp_like( trim(p_txt), include_command )
193 | then
194 | raise invalid_syntax;
195 | end if;
196 |
197 | l_params := trim( regexp_replace( trim(p_txt), include_command, '\1' ) );
198 |
199 | return decode_include_parameters( l_params );
200 | exception
201 | when invalid_syntax then
202 | raise_application_error( -20114, 'Bad INCLUDE directive "' || p_txt || '"' );
203 | end parse_include_declarative;
204 |
205 | function parse_template_declarative( p_txt in varchar2 ) return t_template_parameters
206 | as
207 | l_params t_param;
208 | begin
209 | if not regexp_like( trim(p_txt), template_command )
210 | then
211 | raise_application_error( -20114, 'Bad TEMPLATE directive "' || p_txt || '"' );
212 | end if;
213 |
214 | l_params := trim( regexp_replace( trim(p_txt), include_command, '\1' ) );
215 |
216 | return decode_template_parameters( l_params );
217 | end parse_template_declarative;
218 |
219 | end te_syntax;
220 | /
221 |
--------------------------------------------------------------------------------
/test/test_build.pkb:
--------------------------------------------------------------------------------
1 | create or replace
2 | package body test_build
3 | as
4 | type build_hash_t is table of template_name_t index by template_name_t;
5 |
6 | list_of_templates constant build_hash_t := build_hash_t(
7 | generate_variables => 'build.variables'
8 | ,generate_plsql_types => 'build.plsql-types'
9 | ,generate_procedures => 'build.procedures'
10 | ,generate_exceptions => 'build.exceptions'
11 | ,generate_select => 'build.select'
12 | ,generate_build => 'build.build'
13 | );
14 |
15 | function get_build_template_name( template_name in template_name_t )
16 | return template_name_t
17 | as
18 | begin
19 | if not list_of_templates.exists( template_name )
20 | then
21 | raise template_not_implemented;
22 | end if;
23 |
24 | return list_of_templates( template_name );
25 | end get_build_template_name;
26 |
27 | function make_code( template_name in template_name_t ) return clob
28 | as
29 | p_vars teplsql.t_assoc_array;
30 | v_returnvalue clob;
31 | begin
32 | p_vars( 'schema' ) := USER;
33 | p_vars( teplsql.g_set_indention_string ) := ' ';
34 |
35 | v_returnvalue := teplsql.process_build( p_vars
36 | ,get_build_template_name( template_name )
37 | ,$$PLSQL_UNIT
38 | ,'PACKAGE'
39 | );
40 |
41 | return v_returnvalue;
42 | end make_code;
43 |
44 | /*
45 | * Wrapper for `make_code()`.
46 | * Displays the results to DBMS_OUTPUT
47 | *
48 | * @param template_name in template_name_t
49 | */
50 | procedure output_code( template_name in template_name_t )
51 | as
52 | begin
53 | if template_name is null
54 | then
55 | raise no_data_found;
56 | end if;
57 |
58 | dbms_output.put_line( make_code( template_name) );
59 | exception
60 | when template_not_implemented then
61 | dbms_output.put_line( 'Template "' || template_name || '" not yet implemented.' );
62 | when no_data_found then
63 | dbms_output.put_line( 'Template name must be defined.' );
64 | end;
65 |
66 |
67 | $if false $then
68 | <%@ template( template_name=build.procedures, build=make ) %>
69 | <%@ extends( package, demo_procs_pkg ) %>
70 | <%@ extends( plsql-type, a_type ) %>
71 | <%@ block( data-type )%>varchar2(20 char)<%@ enblock %>
72 | <%@ enextends %>
73 | <%@ extends( procedure, 01_proc_1 ) %>
74 | <%@ block( name ) %>proc_1<%@ enblock %>
75 | <%@ enextends %>
76 | <%@ extends( procedure, 02_func_1) %>
77 | <%@ block( name ) %>func_1<%@ enblock %>
78 | <%@ block( return-variable-type ) %><%@ include( ${super.super}.plsql-type.a_type.name ) %><%@ enblock %>
79 | <%@ enextends %>
80 | <%@ enextends %>
81 | $end
82 |
83 | $if false $then
84 | <%@ template( template_name=build.plsql-types, build=make ) %>
85 | <%@ extends( package, demo_plsql_types_pkg ) %>
86 | <%@ extends( plsql-type, z99_last ) %>
87 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
88 | <%@ block( name ) %>this_is_last<%@ enblock %>
89 | <%@ enextends %>
90 | <%@ extends( plsql-type, 02_with_documentation ) %>
91 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
92 | <%@ block( name ) %>this_has_documentation<%@ enblock %>
93 | <%@ block( documentation ) %>-- This TYPE contains a Documentation section\\\\n<%@ enblock %>
94 | <%@ enextends %>
95 | <%@ extends( plsql-type, 03_nt_example ) %>
96 | <%@ block( name ) %>this_has_nt<%@ enblock %>
97 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
98 | <%@ block( nt-name) %>nt_name<%@ enblock %>
99 | <%@ enextends %>
100 | <%@ extends( plsql-type, 01_z_error ) %>
101 | <%@ block( name ) %>bad_build<%@ enblock %>
102 | <%@ enextends %>
103 | <%@ extends( plsql-type, 04_aa_example ) %>
104 | <%@ block( name ) %>this_has_aa<%@ enblock %>
105 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
106 | <%@ block( aa-name) %>aa_name<%@ enblock %>
107 | <%@ enextends %>
108 | <%@ extends( plsql-type, 05_aa_example2 ) %>
109 | <%@ block( name ) %>this_has_aa2<%@ enblock %>
110 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
111 | <%@ block( aa-name) %>aa_name2<%@ enblock %>
112 | <%@ block( aa-key-data-type ) %><%@ include( ${super}.01_first.name ) %><%@ enblock %>
113 | <%@ enextends %>
114 | <%@ extends( plsql-type, 06_rcd_example ) %>
115 | <%@ block( name ) %>record_example<%@ enblock %>
116 | <%@ block( record ) %>(<% teplsql.set_tab(1); %> m number(4,2)
117 | <% teplsql.goto_tab(1); %>,x number
118 | <% teplsql.goto_tab(1); %>,y number
119 | <% teplsql.goto_tab(1); %>,b number
120 | <% teplsql.goto_tab(1); %>,notes <%@ include( ${super}.01_first.name ) %>
121 | <% teplsql.goto_tab(1); %>)<%@ enblock %>
122 | <%@ enextends %>
123 | <%@ extends( plsql-type, 07_rcd_example2 ) %>
124 | <%@ block( name ) %>record_has_ref<%@ enblock %>
125 | <%@ block( record ) %>( m number(4,2) )<%@ enblock %>
126 | <%@ block( ref-name ) %>ref_name<%@ enblock %>
127 | <%@ enextends %>
128 | <%@ extends( plsql-type, no_name_given ) %>
129 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
130 | <%@ enextends %>
131 | <%@ extends( plsql-type, 01_first ) %>
132 | <%@ block( data-type ) %>varchar2(10)<%@ enblock %>
133 | <%@ block( name ) %>this_is_first<%@ enblock %>
134 | <%@ enextends %>
135 | <%@ enextends %>
136 | $end
137 |
138 | $if false $then
139 | <%@ template( template_name=build.variables, build=make ) %>
140 | <%@ extends( package, demo_variables_pkg ) %>
141 | <%@ extends( plsql-type, undefined ) %>
142 | <%@ block( data-type ) %>varchar2(42)<%@ enblock %>
143 | <%@ enextends %>
144 |
145 | <%@ extends( variable, 01_error ) %>
146 | <%@ block( name ) %>should_be_undefined<%@ enblock %>
147 | <%@ enextends %>
148 | <%@ extends( variable, 02_basic ) %>
149 | <%@ block( name ) %>test_2<%@ enblock %>
150 | <%@ block( data-type ) %>varchar2(42)<%@ enblock %>
151 | <%@ enextends %>
152 | <%@ extends( variable, 03_doc ) %>
153 | <%@ block( name ) %>test_3<%@ enblock %>
154 | <%@ block( data-type ) %>varchar2(42)<%@ enblock %>
155 | <%@ block( documentation ) %>/**
156 | * Test #3 has some comments
157 | */
158 | <%@ enblock %>
159 | <%@ enextends %>
160 | <%@ extends( variable, 04_value ) %>
161 | <%@ block( name ) %>test_4<%@ enblock %>
162 | <%@ block( data-type ) %>varchar2(42)<%@ enblock %>
163 | <%@ block( value ) %>'This is the initial value for Test #4'<%@ enblock %>
164 | <%@ enextends %>
165 | <%@ extends( variable, 05_constant ) %>
166 | <%@ block( name ) %>test_5<%@ enblock %>
167 | <%@ block( data-type ) %>varchar2(42)<%@ enblock %>
168 | <%@ block( constant-value ) %>'This is the constant value for Test #5'<%@ enblock %>
169 | <%@ enextends %>
170 | <%@ enextends %>
171 |
172 | $end
173 |
174 | $if false $then
175 | <%@ template( template_name=build.exceptions, build=make ) %>
176 | <%@ extends( package, demo_exceptions_pkg ) %>
177 | <%@ block( init ) %>-- testing exception call via Package Initialization clause
178 | null;
179 | <%@ enblock %>
180 | <%@ extends( exception, no_name ) %>
181 | <%@ enextends %>
182 | <%@ extends( exception, 01_doc ) %>
183 | <%@ block( name ) %>doc_changed<%@ enblock %>
184 | <%@ block( documentation ) %>/*
185 | * this exception is for some error
186 | */
187 | <%@ enblock %>
188 | <%@ enextends %>
189 | <%@ extends( exception, 02_number ) %>
190 | <%@ block( name ) %>exception_02<%@ enblock %>
191 | <%@ block( number ) %>-20101<%@ enblock %>
192 | <%@ enextends %>
193 | <%@ extends( exception, 03_text ) %>
194 | <%@ block( name ) %>exception_03<%@ enblock %>
195 | <%@ block( text ) %>'The Text has changed'<%@ enblock %>
196 | <%@ enextends %>
197 | <%@ extends( exception, 04_text ) %>
198 | <%@ block( name ) %>exception_04<%@ enblock %>
199 | <%@ block( text ) %>'The Text has changed'<%@ enblock %>
200 | <%@ enextends %>
201 | <%@ extends( exception, 05_const_num ) %>
202 | <%@ block( name ) %>exception_05<%@ enblock %>
203 | <%@ block( constant-number-name ) %>g_05_number<%@ enblock %>
204 | <%@ enextends %>
205 | <%@ extends( exception, 06_const_text ) %>
206 | <%@ block( name ) %>exception_06<%@ enblock %>
207 | <%@ block( constant-text-name ) %>g_06_text<%@ enblock %>
208 | <%@ enextends %>
209 |
210 | <%@ extends( procedure, test_exceptions ) %>
211 | <%@ extends( exceptions-block, 01_all ) %>
212 | <%@ block( body ) %><%@ include( ${super.super.super.super}.exception.*.when-clause ) %><%@ enblock %>
213 | <%@ enextends %>
214 | <%@ extends( exceptions-block, 99_others ) %>
215 | <%@ block( body ) %>-- custom error WHEN clause
216 | when others then
217 | raise;<%@ enblock %>
218 | <%@ enextends %>
219 | <%@ enextends %>
220 | -- exception for init clause
221 | <%@ extends( exceptions-block, 01_all ) %>
222 | <%@ block( body ) %>when no_data_found then null;<%@ enblock %>
223 | <%@ enextends %>
224 | <%@ enextends %>
225 | $end
226 |
227 | $if false $then
228 | <%@ template( template_name=build.select, build=main ) %>
229 | <%@ extends( build, foo ) %>
230 | <%@ extends( package, demo_exceptions_pkg ) %>
231 | <%@ block( init ) %>with <%@ include( ${this}.select.simple_cursor.cte ) %>\\\\n
232 | select a.dummy
233 | into <%@ include( ${this}.name ) %>.dummy
234 | from <%@ include( ${this}.select.simple_cursor.name ) %> a;
235 | <%@ enblock %>
236 | <%@ extends( variable, dummy ) %>
237 | <%@ block( data-type ) %>dual.dummy%type<%@ enblock %>
238 | <%@ enextends %> <%@ extends( select, simple_cursor ) %>
239 | <%@ block( SQL ) %>select 'X' dummy
240 | from emp
241 | where empno = 0<%@ enblock %>
242 | <%@ enextends %>
243 | <%@ extends( select, cursor_with_params ) %>
244 | <%@ block( parameters ) %><% teplsql.goto_tab(1); %> line_1 varchar2
245 | <% teplsql.goto_tab(1); %>,line_2 int
246 | <% teplsql.goto_tab(1); %>,line_3 date<%@ enblock %>
247 | <%@ enextends %>
248 | <%@ enextends %>
249 | <%@ extends( select, this_is_a_view ) %>
250 | <%@ enextends %>
251 | <%@ enextends %>
252 | $end
253 |
254 | $if false $then
255 | <%@ template( template_name=build.build, build=main ) %>
256 | <%@ extends( build, some_build ) %>
257 | <%@ enextends %>
258 | $end
259 |
260 | end;
261 | /
262 |
--------------------------------------------------------------------------------
/DefaultHelperTemplates.md:
--------------------------------------------------------------------------------
1 | Introduction
2 | ===
3 | When creating a Build Template, Helper Templates are the blue-prints for various sections of code.
4 |
5 | This version of *tePLSQL* includes a set of Default Helper Templates.
6 |
7 | The types of database objects that can be generated through a Build Template are:
8 |
9 | Type | Description
10 | -----|-------------
11 | build | supply cursors, etc to the Template code
12 | select | generate code for a View, Cursor, Select statement, CTE, or a Table Macro (future)
13 | package | generate code for a Package
14 | variable | generate code for a Variable or a Constant
15 | plsql-type | generate code for a Subtype, Record, AA, NT, or Ref Cursor
16 | exception | generate code for an Exception
17 | procedure | generate code for a Function or Procedure
18 | exception-block | generate code for the `EXCEPTION` clause of a Function,Procedur, or Package Initialization
19 |
20 |
21 | Installation
22 | ===
23 | These helper templates should be automatically loaded into the `TE_TEMPLATES` table upon a fresh install.
24 |
25 | You can manually install (or refresh) using the `te_default_helper_templates.install_templates` procedure.
26 | By doing this, all existing versions of the Helper Templates will be updated/overwritten.
27 | New ones will be added.
28 |
29 | build
30 | ==
31 | This provides cursors, etc. to be used by Templates. Use this as the head Extension.
32 |
33 | Cursor "Columns"
34 | ----
35 | **note** all parameters are `VARCHAR2`
36 |
37 | [h3]Parameters[/h3]
38 |
39 | pos | Parameter name | Parameter Desription
40 | ----|---------------|-----------
41 | 1 | schema | Schema owner of the Table to search.
42 | 2 | table_name | Name of the Table to search.
43 | 3 | search_txt | Search criteria (default `-HIDDEN -SYSTEM` )
44 |
45 | [h3]Returned Columns[/h3]
46 |
47 | Column Name | Column Description
48 | ------------|--------------------
49 | column_name | Name of the column
50 | column_name_rpad | Name of the column RPAD'd to largest returned column
51 | order_by | number representing the order of the columns
52 | order_by_desc | number representing the reverse order of the columns
53 | comma_first | gives a comma (`,`) for non-first row. Space (` `) otherwise.
54 | comma_last | gives a comma (`,`) for non-last row. Space (` `) otherwise.
55 | data_type | data type of the column
56 | data_desc | data description of the column ( eg `varchar2(10 char)`, `number(6,2)` )
57 | comment | Comment for the column
58 | data_default | ( `LONG` data type ! ) default value for the column
59 | is_pk | Is the column a part of the Primary Key? [YES/NO]
60 | is_id | Is the column an Identity Column(12c) or a single `NUMBER` column? [YES/NO]
61 | is_nullable | Is the column Nullable? [YES/NO]
62 | is_hidden | Is the column Hidden? [YES/NO]
63 | is_vc | Is the column a Virtual Column? [YES/NO]
64 | is_system | (12c+) Was the column System generated? [YES/NO] (opposited of `USER_GENERATED`)
65 |
66 | [h3]Search String[/h3]
67 |
68 | Search String is a space separated list of *key-words* with/without a prefix [+/-]
69 |
70 | - If the *key-word* has no prefix, All columns of that type are returned
71 | - If the *key-wird* has a `+` prefix, those column types are also returned
72 | - If the *key-word* has a `-` prefix, those column types are not returned.
73 |
74 | key-word | Column Type
75 | ---------|-------------
76 | PK | Column is a Primary Key
77 | ID | Column is the Identity Column
78 | VC | Column is a Virtual Column
79 | HIDDEN | Column is a Hidden Column
80 | SYSTEM | Column is a System Generated column.
81 | NULLABLE | Column can contain nulls
82 | NOTNULL | Column can not contain nulls
83 | DEFAULT | Column has a default value defined
84 |
85 | [h3]example[/h3]
86 |
87 | (Default) To get all Visible, user generated columns (including Virtual Columns)
88 | ```sql
89 | "Cursor"( '${schema}', '${table_name}' )
90 | ```
91 |
92 | To get NOT NULL columns with a DEFAULT value
93 | ```sql
94 | "Cursor"( '${schema}', '${table_name}', 'DEFAULT -NULLABLE' )
95 | ```
96 |
97 | To get all visible, user generate, non-PK, non-Virtual columns
98 | ```sql
99 | "Cursor"( '${schema}', '${table_name}', '-PK -VC' )
100 | ```
101 |
102 | sub-extenstions
103 | ----
104 |
105 | Supported sub-extenstions are:
106 | - packages
107 | - select (View or stand-alone Table Macro)
108 | - procedures (stand-alone Functions/Procedures)
109 |
110 | package
111 | ======
112 | Extend this to generate a Package (both Spec and Body will be generated).
113 |
114 | definable blocks
115 | ---
116 | Block | req? | Description
117 | ------|------|--------------
118 | name | D | name of the Package. (default is the object's name)
119 | Documentation | D | In-code documentation for the Exception.
120 | init | | If define, this is the body of the Package's initialization code.
121 |
122 | Legend
123 | - **D** - Required. But, a default value is given.
124 |
125 | sub-extensions
126 | ---
127 | Supported sub-extensions are
128 | - select (produces a cursor)
129 | - plsql-type
130 | - procedure
131 | - variables
132 | - exception
133 | - exception-block (needs an `init` block to generate)
134 |
135 | **note:** Object names of the form `private.*` will only be generated in the Body.
136 |
137 | plsql-types
138 | ===
139 | Extend this to generates code for Subtypes, Records, Nested Tables, Associative Array, and Ref Cursors.
140 |
141 | **note:** Current version of the default helper template requires a subtype/record for nt's, aa's, and ref cursors.
142 |
143 | definable blocks
144 | ---
145 | block | req? | ST/R | Description
146 | ------|------|-----|------------
147 | name | D | Both | name of the Record/Subtype pl/sql type. (default is the object's name)
148 | data-type | Y | ST | Data type for a Subtype pl/sql type. Set only one (`data-type`, `record`)
149 | record | Y | R | Defines the attributes for a Record pl/sql type. Set only one (`data-type`, `record`)
150 | Documentation| | Both | In-code documentation for pl/sql types
151 | nt-name | |Both | Name for a Nested Table pl/sql type. Set this to generate a Nested Table.
152 | aa-name | |Both | Name for an Associative Array pl/sql type. Set this to generate an Associative Array.
153 | ref-name | |Both | Name for an Ref Cursor pl/sql type. Set this to generate a Ref Cursor.
154 | aa-key-data-type | D | AA | Set this to define the `INDEX BY` clause. (default is `pls_integer')
155 |
156 | Legend
157 | - **D** - Required. But, a default value is given.
158 | - **Both** - used by Subtypes and Records
159 | - **ST** - only for Subtypes
160 | - **R** - only for Records
161 | - *AA** - only for Associative Arrays. (Requires `aa-name` to be defined)
162 |
163 | variables
164 | ===
165 | Extend this to generate code for a variable.
166 |
167 | definable blocks
168 | ---
169 | block | req? | Description
170 | ------|------|--------
171 | name | D | name of the variable. (default is the object's name)
172 | Documentation| | In-code documentation for the variable.
173 | data-type | Y | Data type of the variable.
174 | value | | Sets the value of the variable in the Declaration section.
175 | constant-value | | Defines the variable as a Constant. Also, sets its value.
176 |
177 | Legend
178 | - **D** - Required. But, a default value is given.
179 | - **Y** - Required.
180 |
181 | select
182 | ===
183 | Extend this to generate code for Select, View, Cursor, CTE, or Table Macro(future).
184 |
185 | **note:** Future version will generate SQL Table Macro code too
186 |
187 | definable blocks
188 | ---
189 | block | req? | For? | Description
190 | ------|------|--------
191 | name | D | VCM | name of the view,cursor. (default is the object's name)
192 | SQL | D | all | Select Statement. (default: `select * from dual`)
193 | parameters | | CM | Parameters for the Cursor/Table Macro. use `teplsql.goto_tab(1)` for multiline parameters.
194 | rcd-name* | | C | Name for a Record type. Set this to generate a Subtype for the cursor's `%ROWTYPE`.
195 | nt-name* | | C | Name for a Nested Table pl/sql type. Set this to generate a Nested Table.
196 | aa-name* | | C | Name for an Associative Array pl/sql type. Set this to generate an Associative Array.
197 | ref-name* | | C | Name for an Ref Cursor pl/sql type. Set this to generate a Ref Cursor.
198 | aa-key-data-type* | D | C | Set this to define the `INDEX BY` clause. (default is `pls_integer'). requires `aa-name` to be defined.
199 |
200 | Legend
201 | - **D** - Required. But, a default value is given.
202 | - **V** - Used for Views
203 | - **C** - Used for Cursors
204 | - **M** - Used for Table Macros
205 |
206 |
207 | executable blocks
208 | ---
209 | Block | Description
210 | ------|-------------
211 | specification | generate code for a cusor (automatically called for Package, Function, Procedure)
212 | make-view | generate code for `create view`
213 | cte | generate code for CTE. `WITH` keyword NOT included
214 | (tbd) | generate code for a stand-alone Table Macro
215 |
216 | procedure
217 | ====
218 | Generate code for a Procedure or Function.
219 |
220 | **note** This version of the Helper Template does not support pipeline functions or other function options ( eg `deterministic`, etc.)
221 |
222 | definable blocks
223 | ---
224 | Block | req? | For? | Description
225 | ------|------|------|------------
226 | name | D | both | name of the Procedure/Function. (default is the object's name)
227 | Documentation| D | In-code documentation for the Procedure/Function.
228 | return-variable-type | | F | Sets the return variable data type. If defined, Function code is generated.
229 | return-variable-name | D | F | Sets the return variable's name. (Default: `return_variable`)
230 | return-type | D | F | Sets the Function's return type. (Default: same as `return-variable-type` )
231 | decl | | both | Custom declaration code. (Funtions automatically declare the return variable)
232 | bdy | D | both | Custom body code. (Default `null;`) Functions always end with `return return_variable;`
233 | parameters | | Both | Parameters for the Function/Procedure. use `teplsql.goto_tab(1)` for multiline parameters.
234 |
235 | Legend
236 | - **D** - Required. But, a default value is given.
237 | - **F** - Only used for Functions
238 |
239 | Supported sub-extensions
240 | ---
241 | - select (produces a cursor)
242 | - plsql-type
243 | - procedure
244 | - variables
245 | - exception
246 | - exception-block
247 |
248 |
249 | exception
250 | ===
251 | Generate code for a custom exception.
252 |
253 | definable blocks
254 | ---
255 | Block | req? | Description
256 | ------|------|--------------
257 | name | D | name of the Exception. (default is the object's name)
258 | Documentation | | In-code documentation for the Exception.
259 | number | D | Exception number. (Default: `-20000`).
260 | text | D | The Text that is returned when this exception is raised
261 | constant-number-name | | If defined, generates a constant variable based on the value for `number`
262 | constant-text-name | | If defined, generates a constant based on the value for `text`.
263 | exception-code | D | The code that is ran when an exception is raised. (Default: `raise_application_exception()`)
264 |
265 | Legend
266 | ---
267 | - **D** - Required. But, a default value is given.
268 |
269 | executable blocks
270 | ----
271 | Block | Description
272 | ------|-------------
273 | when-clause | Generates code for the `WHEN` clause of the `EXCEPTION` clause.
274 |
275 |
276 | exceptions-block
277 | ====
278 | Generates code for the `exception` section of a procedure/function/package initialization.
279 |
280 | **note** the object's name is only used for ordering of the generated code
281 |
282 | definable blocks
283 | ---
284 | Block | req? |Description
285 | ------|------|-----------
286 | body | Y | Must generate the `WHEN` clause for an `EXCEPTION` clause
287 |
288 | Legend
289 | ---
290 | - **Y** - Required.
291 |
292 |
--------------------------------------------------------------------------------
/TE_TEMPLATES_API.pks:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE
2 | PACKAGE te_templates_api
3 | AUTHID current_user
4 | AS
5 | /**
6 | * Application Program Interface [API] against the TE_TEMPLATES table for the tePLSQL project.
7 | *
8 | * This package imports and exports a series of tePLSQL templates for the TE_TEMPLATES using XML.
9 | *
10 | * File Format
11 | * Example XML Format:
12 | *
13 | *
14 | *
15 | *
16 | * hello world
17 | * This is a "Hello World" template
18 | * SCOTT TIGER
19 | * 2016-11-19
20 | * SCOTT TIGHER
21 | * 2016-11-19
22 | * Hello World!
23 | *
24 | *
25 | *
26 | *
27 | *
28 | * File Extenstion should be .xml or .teplsql
29 | * DATE columns are those imported/exported via XML SQL. YYYY-MM-DD
30 | * The Node "/teplsql/templates/template/TEMPLATE" can be CDATA type data.
31 | * Multiple /teplsql/templates/template Nodes are expected.
32 | *
33 | * Security
34 | * This is an AUTHID CURRENT_USER package.
35 | *
36 | * The caller must have appropriate INSERT/UPDATE/SELECT permission on the TE_TEMPLATES table.
37 | *
38 | * For APEX:
39 | * The 'parsing schema' needs EXECUTE permission in order to run. (This is in addtion to INSERT/SELECT/UPDATE on TE_TEMPLATES
40 | *
41 | * For Oracle Directory:
42 | *
43 | * - The caller needs INSERT/SELECT/UPDATE permissions on the table TE_TEMPLATES
44 | * - The caller must also have appropriate READ/WRITE permission on the Oracle Directory if the "directory_*" interfaces are used.
45 | *
46 | *
47 | * Primative Functions
48 | * These functions are the main functions of the package.
49 | *
50 | * - xml_import - imports an XML LOB into the TE_TEMPLATES table
51 | * - xml_export - returns the XML in CLOB format (todo: this should return an XMLType
52 | * - assert - this verifies that the XML is valid for import()
53 | *
54 | *
55 | * PL/SQL Interfaces
56 | * These procedures allow you to import from/export to a file using an Oracle Directoyr
57 | *
58 | *
59 | * - file_import - imports templates from an XML file found in an Oracle Directory.
60 | * - file_export - exports templates into an XML file located in an Oracle Directory.
61 | *
62 | *
63 | * APEX Interfaces
64 | * These procedures are for use from within Oracle Application Express (APEX)
65 | *
66 | * - 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
67 | * - apex_export - a BEFORE HEADER process that allows the end-user to download the XML file. The Filename must end in xml or teplsql
68 | *
69 | *
70 | * List of Values
71 | * These are Pipelined Functions that allow you to create a List of Values for your application.
72 | *
73 | * - import_options_lov - returns a list of options for the import() series of procedures
74 | * - export_options_lov - returns a list of option for the export() series of procedures
75 | *
76 | *
77 | *
78 | * IMPORT Options
79 | * overwrite - if NAME matches, always OVERWRITE
80 | * ignore - if NAME matches, ignore
81 | * error - if NAME mathches, raise an error
82 | *
83 | *
84 | *
85 | * EXPORTS Options
86 | * exact - Match p_search_values against NAME using a case insentive exact mathch.
87 | * like - Match p_search_values against NAME using a case insentive LIKE match. You must provide "%" keys.
88 | * regexp - Match p_search_values against NAME using a case sensitive Regular Expression match.
89 | *
90 | * @headcom
91 | */
92 | SUBTYPE options_t IS INTEGER NOT NULL;
93 |
94 | g_option_uninitilized CONSTANT options_t :=-1;
95 |
96 | TYPE lov_t IS RECORD ( option_value options_t DEFAULT g_option_uninitilized
97 | , option_desc VARCHAR2( 50 )
98 | );
99 | TYPE lov_nt IS TABLE OF lov_t;
100 |
101 | g_import_overwrite CONSTANT options_t := 1;
102 | g_import_ignore CONSTANT options_t := 2;
103 | g_import_error CONSTANT options_t := 0;
104 | g_import_default CONSTANT options_t := g_import_overwrite;
105 |
106 | g_export_exact CONSTANT options_t := 1;
107 | g_export_like CONSTANT options_t := 2;
108 | g_export_regexp CONSTANT options_t := 3;
109 | g_export_dot CONSTANT options_t := 4;
110 | g_export_default CONSTANT options_t := g_export_exact;
111 |
112 | invalid_option EXCEPTION;
113 | invalid_tePLSQL_xml EXCEPTION;
114 |
115 | /**
116 | * Asserts that the XML conforms to the current XML Schema for tePLSQL TE_TEMPLATES
117 | *
118 | * TODO: this is currently a NOOP
119 | *
120 | * @param p_xml The XML to test
121 | * @raises invalid_tePLSQL_xml Raised when input XML is not an tePLSQL XML document.
122 | */
123 | PROCEDURE assert_xml (
124 | p_xml IN XMLTYPE
125 | );
126 |
127 | /*
128 | * Returns a List of Values for IMPORT Options
129 | *
130 | * The following languages are supported:
131 | *
132 | * - 'EN' - English
133 | *
134 | *
135 | * Default language is 'EN'
136 | *
137 | * usage
138 | *
139 | * select *
140 | * from table( te_templates_api.import_options_lov() )
141 | *
142 | *
143 | * All unsupported languages will raise the 'invalid_option' exception.
144 | *
145 | * At this time, only EN is supported.
146 | *
147 | * @param p_lang The language for Description.
148 | * @returns List of Values (LoV) suitable for User Interfaces
149 | * @raises invalid_option Raised if the language is not supported.
150 | */
151 | FUNCTION import_options_lov (
152 | p_lang IN VARCHAR2 DEFAULT 'EN'
153 | ) RETURN lov_nt
154 | PIPELINED;
155 |
156 | /**
157 | * Returns a List of Values for EXPORT Options
158 | *
159 | * The following languages are supported:
160 | *
161 | * - 'EN' - English
162 | *
163 | *
164 | * Default language is 'EN'
165 | *
166 | *
167 | * usage
168 | *
169 | * select *
170 | * from table( te_templates_api.export_options_lov() )
171 | *
172 | *
173 | * All unsupported languages will raise the 'invalid_option' exception.
174 | *
175 | * At this time, only EN is supported.
176 | *
177 | * @param p_lang The language for Description.
178 | * @returns List of Values (LoV) suitable for User Interfaces
179 | * @raises invalid_option Raised if the language is not supported.
180 | */
181 | FUNCTION export_options_lov (
182 | p_lang IN VARCHAR2 DEFAULT 'EN'
183 | ) RETURN lov_nt
184 | PIPELINED;
185 |
186 | /*
187 | * Imports a series of tePLSQL templates from a given XML document.
188 | *
189 | * The document must have already passed the "assert_xml()" function.
190 | *
191 | * @param p_xml The set of tePLSQL templates in XMLType format
192 | * @returns List of Values (LoV) suitable for User Interfaces
193 | * @param p_duplicates Defines how to handle duplicate. Default is "overwrite".
194 | * @raises invalid_option Raised when option is invalid.
195 | */
196 | PROCEDURE xml_import (
197 | p_xml IN XMLTYPE
198 | , p_duplicates IN options_t DEFAULT g_import_default
199 | );
200 |
201 | /**
202 | * Returns an XML Document for a series of templates based on the p_search_value
203 | *
204 | * @param p_search_value The search value to use
205 | * @param p_search_type Defines how to match. Match is either Exact (default), LIKE, or Regulare Expression
206 | * @returns XML Document of Templates suitable for import via xml_import()
207 | * @raises invalid_option Raised when option is invalid..
208 | */
209 | FUNCTION xml_export (
210 | p_search_value IN VARCHAR2 DEFAULT NULL
211 | , p_search_type IN options_t DEFAULT g_export_default
212 | ) RETURN XMLTYPE;
213 |
214 |
215 |
216 | /**
217 | * Imports a file from an Oracle DIRECTORY location.
218 | *
219 | * Filename must have either the ".xml" extension or the ".teplsql" extension.
220 | *
221 | * @param p_oradir The name of the Oracle DIRECTORY.
222 | * @param p_filename The name of the file to import (including extension)
223 | * @param p_duplicates The Import option to how to handle duplicate template NAMEs
224 | * @raises invalid_option Raised when option is invalid or filename is not correct.
225 | * @raises invalid_tePLSQL_xml Raised if filename is invalid or XML is not a tePLSQL XML document.
226 | */
227 | PROCEDURE file_import (
228 | p_oradir IN VARCHAR2
229 | , p_filename IN VARCHAR2
230 | , p_duplicates IN options_t DEFAULT g_import_default
231 | );
232 |
233 | /**
234 | * Exports a collection of templates to a file in an Oracle DIRECTORY location.
235 | *
236 | * Filename must have either the ".xml" extension or the ".teplsql" extension.
237 | *
238 | * @param p_oradir The name of the Oracle DIRECTORY.
239 | * @param p_filename The name of the file to export (including extension)
240 | * @param p_search_value The search value to use
241 | * @param p_search_type Defines how to match. Match is either Exact (default), LIKE, or Regulare Expression
242 | * @raises invalid_option Raised when option is invalid or filename is not correct.
243 | *
244 | */
245 | PROCEDURE file_export (
246 | p_oradir IN VARCHAR2
247 | , p_filename IN VARCHAR2
248 | , p_search_value IN VARCHAR2 DEFAULT NULL
249 | , p_search_type IN options_t DEFAULT g_export_default
250 | );
251 |
252 |
253 | /**
254 | * APEX utility to return a file, that was uploded via "File Browse..." Item Type, as a CLOB.
255 | *
256 | * @paream p_filename This is the value returned by the "File Browse..." Item. It is used to identify the correct file to process.
257 | */
258 | FUNCTION filebrowse_as_clob (
259 | p_filename IN VARCHAR2
260 | ) RETURN CLOB;
261 |
262 | /**
263 | * Interface for APEX Process.
264 | *
265 | * This is a single call interface for APEX Process.
266 | *
267 | * Thie "File Browse..." Item needs to save the file to APEX_APPLICATION_TEMP_FILES.
268 | *
269 | * Example Usage
270 | *
271 | * te_templates_api.apex_import( :P10_FILE_BROWSE, :P10_IMPORT_LOV );
272 | *
273 | *
274 | * @param p_filename This is the value returned by the "File Browse..." Item. It is used to identify the correct file to process.
275 | * @param p_duplicates Defines how to handle duplicate. Default is "overwrite".
276 | */
277 | PROCEDURE apex_import (
278 | p_filename IN VARCHAR2
279 | , p_duplicates IN options_t DEFAULT g_import_default
280 | );
281 |
282 | /**
283 | * Interface for APEX Process.
284 | *
285 | * This is a single call interface for APEX Process.
286 | *
287 | * This downloads a colletion of templates as an XML Document.
288 | * File extension shoul be '.xml' or '.teplsql'.
289 | *
290 | * Example Usage
291 | *
292 | * te_templates_api.apex_import( :P10_FILENAME_TEXT, :P10_SEARCH_TEXT, :P10_EXPORT_LOV );
293 | *
294 | *
295 | * @param p_filename This is the value returned by the "File Browse..." Item. It is used to identify the correct file to process.
296 | * @param p_search_value The search value to use
297 | * @param p_search_type Defines how to match. Match is either Exact (default), LIKE, or Regulare Expression
298 | * @raises invalid_option Raised when option is invalid or filename is not correct.
299 | */
300 | PROCEDURE apex_export (
301 | p_filename IN VARCHAR2
302 | , p_search_value IN VARCHAR2
303 | , p_search_type IN VARCHAR2
304 | );
305 |
306 | END;
307 | /
308 |
--------------------------------------------------------------------------------
/TE_TEMPLATES_API.pkb:
--------------------------------------------------------------------------------
1 | CREATE OR REPLACE
2 | PACKAGE BODY te_templates_api
3 | AS
4 |
5 | -- This cursor processes an XML Document into columns for the TE_TEMPLATES table.
6 | CURSOR extractTemplates( p_xml in XMLType )
7 | IS
8 | SELECT xt.*
9 | FROM XMLTABLE( '/teplsql/templates/template'
10 | PASSING p_xml
11 | COLUMNS
12 | "NAME" VARCHAR2( 500 ) PATH '/template/NAME'
13 | , "TEMPLATE" CLOB PATH '/template/TEMPLATE'
14 | , "DESCRIPTION" varchar2( 500 ) PATH '/template/DESCRIPTION'
15 | , CREATED_BY VARCHAR2( 500 ) PATH '/template/CREATED_BY'
16 | , CREATED_DATE DATE PATH '/template/CREATED_DATE'
17 | , MODIFIED_BY VARCHAR2( 500 ) PATH '/template/MODIFIED_BY'
18 | , MODIFIED_DATE DATE PATH '/template/MODIFIED_DATE'
19 | ) xt;
20 |
21 | TYPE extracttemplates_t IS TABLE OF extracttemplates%rowtype;
22 |
23 | PROCEDURE import_error (
24 | p_xml IN XMLTYPE
25 | )
26 | AS
27 | l_buffer extracttemplates_t;
28 | l_counter INT := 0;
29 | BEGIN
30 | OPEN extracttemplates( p_xml );
31 |
32 | WHILE ( l_counter < 10 )
33 | LOOP
34 | l_counter := l_counter + 1;
35 |
36 | FETCH extracttemplates BULK COLLECT INTO l_buffer LIMIT 500;
37 |
38 | FORALL i IN 1..l_buffer.count
39 | INSERT INTO te_templates (
40 | "NAME"
41 | , template
42 | , description
43 | , created_by
44 | , created_date
45 | , modified_by
46 | , modified_date
47 | ) VALUES (
48 | l_buffer( i )."NAME"
49 | , l_buffer( i ).template
50 | , l_buffer( i ).description
51 | , l_buffer( i ).created_by
52 | , l_buffer( i ).created_date
53 | , l_buffer( i ).modified_by
54 | , l_buffer( i ).modified_date
55 | );
56 |
57 | EXIT WHEN extracttemplates%notfound;
58 | END LOOP;
59 |
60 | IF extracttemplates%isopen
61 | THEN
62 | CLOSE extracttemplates;
63 | END IF;
64 | EXCEPTION
65 | WHEN OTHERS THEN
66 | IF extracttemplates%isopen
67 | THEN
68 | CLOSE extracttemplates;
69 | END IF;
70 | RAISE;
71 | END;
72 |
73 | PROCEDURE import_overwrite_ignore (
74 | p_xml IN XMLTYPE
75 | , p_duplicates IN options_t DEFAULT g_import_default
76 | )
77 | AS
78 | l_buffer extracttemplates_t;
79 | BEGIN
80 | OPEN extracttemplates( p_xml );
81 |
82 | WHILE ( 1 = 1 )
83 | LOOP
84 | FETCH extracttemplates BULK COLLECT INTO l_buffer LIMIT 500;
85 |
86 | FORALL i IN 1..l_buffer.count
87 | MERGE INTO te_templates old USING (
88 | SELECT l_buffer( i )."NAME" "NAME"
89 | , l_buffer( i ).template template
90 | , l_buffer( i ).description description
91 | , l_buffer( i ).created_by created_by
92 | , l_buffer( i ).created_date created_date
93 | , l_buffer( i ).modified_by modified_by
94 | , l_buffer( i ).modified_date modified_date
95 | FROM dual
96 | ) new
97 | ON ( old."NAME" = new."NAME" )
98 | WHEN MATCHED THEN UPDATE SET old.template = new.template
99 | , old.description = new.description
100 | , old.created_by = new.created_by
101 | , old.modified_by = new.modified_by
102 | , old.modified_date = new.modified_date
103 | WHERE p_duplicates = g_import_overwrite
104 | WHEN NOT MATCHED THEN INSERT (
105 | name
106 | , template
107 | , description
108 | , created_by
109 | , created_date
110 | , modified_by
111 | , modified_date
112 | ) VALUES (
113 | new.name
114 | , new.template
115 | , new.description
116 | , new.created_by
117 | , new.created_date
118 | , new.modified_by
119 | , new.modified_date )
120 | WHERE p_duplicates IN ( g_import_overwrite, g_import_ignore );
121 |
122 | EXIT WHEN extracttemplates%notfound;
123 | END LOOP;
124 |
125 | IF extracttemplates%isopen
126 | THEN
127 | CLOSE extracttemplates;
128 | END IF;
129 | EXCEPTION
130 | WHEN OTHERS THEN
131 | IF extracttemplates%isopen
132 | THEN
133 | CLOSE extracttemplates;
134 | END IF;
135 | RAISE;
136 | END;
137 |
138 | PROCEDURE xml_import( p_xml IN XMLType
139 | , p_duplicates IN options_t DEFAULT g_import_default
140 | )
141 | AS
142 | BEGIN
143 | CASE p_duplicates
144 | WHEN g_import_error THEN import_error( p_xml );
145 | WHEN g_import_ignore THEN import_overwrite_ignore( p_xml, p_duplicates );
146 | WHEN g_import_overwrite THEN import_overwrite_ignore( p_xml, p_duplicates );
147 | ELSE RAISE invalid_option;
148 | END CASE;
149 | END;
150 |
151 | FUNCTION xml_export (
152 | p_search_value IN VARCHAR2 DEFAULT NULL
153 | , p_search_type IN options_t DEFAULT g_export_default
154 | ) RETURN XMLTYPE
155 | IS
156 | l_buffer xmltype;
157 | l_search_name varchar2(4000);
158 | l_search_like varchar2(4000);
159 | l_search_regexp varchar2(4000);
160 | BEGIN
161 |
162 | CASE p_search_type
163 | WHEN g_export_exact THEN
164 | l_search_name := p_search_value;
165 | WHEN g_export_like THEN
166 | l_search_like := p_search_value;
167 | WHEN g_export_regexp THEN
168 | l_search_regexp := p_search_value;
169 | WHEN g_export_dot THEN
170 | l_search_regexp := p_search_value;
171 | ELSE
172 | RAISE invalid_option;
173 | END CASE;
174 |
175 | WITH data AS (
176 | SELECT
177 | XMLELEMENT( "teplsql"
178 | , XMLELEMENT( "templates"
179 | , XMLAGG(
180 | XMLELEMENT( "template"
181 | , XMLFOREST( t."NAME"
182 | , t."TEMPLATE"
183 | , t.description
184 | , t.created_by
185 | , t.created_date
186 | , t.modified_by
187 | , t.modified_date
188 | )
189 | )
190 | )
191 | )
192 | ) xmldoc
193 | FROM te_templates t
194 | WHERE
195 | upper( t.name ) = upper( l_search_name )
196 | OR upper( t.name ) LIKE upper( l_search_like )
197 | OR REGEXP_LIKE( t.name, l_search_regexp )
198 | )
199 | SELECT xmldoc
200 | INTO l_buffer
201 | FROM data;
202 |
203 | RETURN l_buffer;
204 | END;
205 |
206 | FUNCTION filebrowse_as_clob (
207 | p_filename IN VARCHAR2
208 | )
209 | RETURN CLOB AS
210 |
211 | l_blob BLOB;
212 | l_clob CLOB;
213 | l_dest_offsset INTEGER := 1;
214 | l_src_offsset INTEGER := 1;
215 | l_lang_context INTEGER := dbms_lob.default_lang_ctx;
216 | l_warning INTEGER;
217 | BEGIN
218 | SELECT blob_content
219 | INTO l_blob
220 | -- from wwv_flow_files -- APEX 4.2
221 | FROM apex_application_temp_files -- APEX 5.0+
222 | WHERE
223 | name = p_filename;
224 |
225 | dbms_lob.createtemporary(
226 | lob_loc => l_clob
227 | , cache => false
228 | );
229 |
230 | dbms_lob.converttoclob(
231 | dest_lob => l_clob
232 | , src_blob => l_blob
233 | , amount => dbms_lob.lobmaxsize
234 | , dest_offset => l_dest_offsset
235 | , src_offset => l_src_offsset
236 | , blob_csid => dbms_lob.default_csid
237 | , lang_context => l_lang_context
238 | , warning => l_warning
239 | );
240 |
241 | RETURN l_clob;
242 | END;
243 |
244 | PROCEDURE apex_import (
245 | p_filename IN VARCHAR2
246 | , p_duplicates IN options_t DEFAULT g_import_default
247 | )
248 | AS
249 | l_clob CLOB;
250 | l_xml XMLTYPE;
251 | BEGIN
252 | apex_debug.message( 'TE_TEMPLATES_API: Importing file "%s" with option "%s"', p_filename, p_duplicates );
253 |
254 | l_clob := filebrowse_as_clob( p_filename );
255 |
256 | l_xml := xmltype( l_clob );
257 |
258 | apex_debug.message( 'TE_TEMPLATES_API: Asserting XML "%s..."', substr( l_xml.getCLOBVal(), 1, 50 ) );
259 | assert_xml( l_xml );
260 |
261 | xml_import( l_xml, p_duplicates );
262 | apex_debug.message( 'TE_TEMPLATES_API: done' );
263 | END;
264 |
265 | PROCEDURE assert_xml (
266 | p_xml IN XMLTYPE
267 | )
268 | AS
269 | BEGIN
270 | IF p_xml IS NULL
271 | THEN
272 | RAISE invalid_teplsql_xml;
273 | END IF;
274 | END;
275 |
276 | FUNCTION import_options_lov( p_lang IN VARCHAR2 DEFAULT 'EN' ) RETURN lov_nt PIPELINED
277 | AS
278 | l_lang VARCHAR2(2);
279 | l_buffer lov_t;
280 | BEGIN
281 | l_lang := nvl( substr( p_lang,1,2) , 'EN' );
282 |
283 | CASE l_lang
284 | WHEN 'EN' then
285 | l_buffer.option_value := g_import_overwrite; l_buffer.option_desc := 'Overwrite Matches';
286 | pipe row ( l_buffer );
287 | l_buffer.option_value := g_import_ignore; l_buffer.option_desc := 'Skip Matches';
288 | pipe row ( l_buffer );
289 | l_buffer.option_value := g_import_error; l_buffer.option_desc := 'Throw Error on Match';
290 | pipe row ( l_buffer );
291 | ELSE
292 | RAISE invalid_option;
293 | END CASE;
294 |
295 | RETURN;
296 | END;
297 |
298 | FUNCTION export_options_lov( p_lang IN VARCHAR2 DEFAULT 'EN' ) RETURN lov_nt PIPELINED
299 | AS
300 | l_lang VARCHAR2(2);
301 | l_buffer lov_t;
302 | BEGIN
303 | l_lang := nvl( substr( p_lang,1,2) , 'EN' );
304 |
305 | CASE l_lang
306 | WHEN 'EN' THEN
307 | l_buffer.option_value := g_export_exact; l_buffer.option_desc := 'Case Insensitive Exact Match';
308 | pipe row ( l_buffer );
309 | l_buffer.option_value := g_export_like; l_buffer.option_desc := 'Case Insenstive Oracle LIKE';
310 | pipe row ( l_buffer );
311 | l_buffer.option_value := g_export_regexp; l_buffer.option_desc := 'Case Sensitive Regular Expression';
312 | pipe row ( l_buffer );
313 | ELSE
314 | RAISE invalid_option;
315 | END CASE;
316 |
317 | RETURN;
318 | END;
319 |
320 | PROCEDURE file_import (
321 | p_oradir IN VARCHAR2
322 | , p_filename IN VARCHAR2
323 | , p_duplicates IN options_t DEFAULT g_import_default
324 | )
325 | AS
326 |
327 | l_clob CLOB;
328 | l_dest_offset INT := 1;
329 | l_src_offset INT := 1;
330 | l_src_csid NUMBER := nls_charset_id( 'US7ASCII' );
331 | l_lang_context INTEGER := dbms_lob.default_lang_ctx;
332 | l_warning INTEGER;
333 | l_bfile BFILE;
334 | l_xml XMLTYPE;
335 | BEGIN
336 | l_bfile := bfilename( p_oradir, p_filename );
337 |
338 | dbms_lob.open( l_bfile, dbms_lob.lob_readonly );
339 |
340 | dbms_lob.createtemporary( l_clob, true );
341 |
342 | sys.dbms_lob.loadclobfromfile(
343 | l_clob
344 | , l_bfile
345 | , dbms_lob.lobmaxsize
346 | , l_dest_offset
347 | , l_src_offset
348 | , l_src_csid
349 | , l_lang_context
350 | , l_warning
351 | );
352 |
353 | dbms_lob.close( l_bfile );
354 |
355 | l_xml := xmltype( l_clob );
356 |
357 | assert_xml( l_xml );
358 |
359 | xml_import( l_xml, p_duplicates );
360 | EXCEPTION
361 | WHEN OTHERS THEN
362 | dbms_lob.close( l_bfile );
363 | RAISE;
364 | END;
365 |
366 | PROCEDURE file_export (
367 | p_oradir IN VARCHAR2
368 | , p_filename IN VARCHAR2
369 | , p_search_value IN VARCHAR2 DEFAULT NULL
370 | , p_search_type IN options_t DEFAULT g_export_default
371 | )
372 | AS
373 | l_xml XMLTYPE;
374 | l_file utl_file.file_type;
375 | l_clob CLOB;
376 | l_buffer VARCHAR2( 32767 );
377 | l_amount BINARY_INTEGER := 32767;
378 | l_pos INTEGER := 1;
379 | BEGIN
380 | --get XML
381 | l_xml := xml_export( p_search_value, p_search_type );
382 |
383 | -- format CLOB
384 | $IF false $THEN
385 | -- 10g does not support XMLSerialze( indent size = 2 )
386 | l_clob := l_xml.getCLOBVal();
387 | $ELSE
388 | -- all other versions of Oracle
389 | SELECT
390 | XMLSERIALIZE( DOCUMENT xml_export(
391 | p_search_value
392 | , p_search_type
393 | ) AS CLOB
394 | INDENT SIZE = 2 )
395 | INTO l_clob
396 | FROM dual;
397 | $END
398 |
399 | -- open file handle
400 |
401 | l_file := UTL_FILE.fopen(p_oradir, p_filename, 'w', 32767);
402 |
403 | LOOP
404 | DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer);
405 | UTL_FILE.put(l_file, l_buffer);
406 | l_pos := l_pos + l_amount;
407 | END LOOP;
408 | EXCEPTION
409 | WHEN NO_DATA_FOUND THEN
410 | -- Expected end.
411 | UTL_FILE.fclose(l_file);
412 | WHEN OTHERS THEN
413 | UTL_FILE.fclose(l_file);
414 | RAISE;
415 | END;
416 |
417 | PROCEDURE apex_export (
418 | p_filename IN VARCHAR2
419 | , p_search_value IN VARCHAR2
420 | , p_search_type IN VARCHAR2
421 | )
422 | AS
423 | l_xml XMLTYPE;
424 | l_clob CLOB;
425 | BEGIN
426 | --get CLOB
427 | $IF false $THEN
428 | apex_debug.message( 'TE_TEMPLATES_API: using 10g EXPORT method' );
429 | -- 10g does not support XMLSerialze( indent size = 2 )
430 | l_xml := xml_export( p_search_value, p_search_type );
431 | l_clob := l_xml.getclobval ();
432 | $ELSE
433 | apex_debug.message( 'TE_TEMPLATES_API: using 11g+ EXPORT method' );
434 | -- all other versions of Oracle
435 | SELECT XMLSerialize( document xml_export( p_search_value, p_search_type ) as CLOB indent size = 2)
436 | INTO l_clob
437 | FROM dual;
438 | $END
439 | IF dbms_lob.getlength( l_clob ) < 5 OR l_clob IS NULL
440 | THEN
441 | apex_debug.message( 'XML CLOB is too small (or NULL) to be real' );
442 | RAISE no_data_found;
443 | END IF;
444 |
445 | -- set up HTTP header
446 | owa_util.mime_header( 'text/xml', false
447 | );
448 |
449 | -- set the size so the browser knows how much to download
450 | htp.p( 'Content-length: ' || dbms_lob.getlength( l_clob ) );
451 |
452 | -- the filename will be used by the browser if the users does a save as
453 | htp.p( 'Content-Disposition: attachment; filename="' || replace( replace(
454 | substr( p_filename, instr( p_filename, '/' ) + 1 )
455 | , chr( 10 ), NULL ) , chr( 13 ) , NULL) || '"' );
456 | -- close the headers
457 | owa_util.http_header_close;
458 |
459 | -- download the BLOB
460 | wpg_docload.download_file( l_clob );
461 |
462 | -- stop APEX engine
463 | apex_application.stop_apex_engine;
464 | EXCEPTION
465 | WHEN no_data_found THEN
466 | apex_debug.message( 'NO_DATA_FOUND was raised.' );
467 | htp.p( 'No matching templates found' );
468 | apex_application.stop_apex_engine;
469 | END;
470 | END;
471 | /
--------------------------------------------------------------------------------
/TE_DEFAULT_HELPER_TEMPLATES.pkb:
--------------------------------------------------------------------------------
1 | create or replace
2 | package body te_default_helper_templates
3 | as
4 | procedure install_templates
5 | as
6 | t_clob clob;
7 | p_vars teplsql.t_assoc_array;
8 | imp xmltype;
9 | begin
10 | -- get XML file of Helper Templates
11 | p_vars( teplsql.g_set_render_mode ) := teplsql.g_render_mode_fetch_only;
12 | t_clob := teplsql.process( p_vars, 'DefaultHelperTemplates.xml', 'TE_DEFAULT_HELPER_TEMPLATES' );
13 |
14 | -- convert to XML
15 | imp := xmltype( t_clob );
16 |
17 | -- import
18 | te_templates_api.xml_import( imp, te_templates_api.g_import_overwrite );
19 | end install_templates;
20 |
21 | function base_name return te_templates.name%type
22 | as
23 | begin
24 | return g_base_name;
25 | end base_name;
26 |
27 | $if false $then
28 | <%@ template( template_name=DefaultHelperTemplates.xml ) %>
29 |
30 |
31 |
32 | teplsql.helper.default.package.name
33 | ${object_name}
34 | Name of the Function/Procedure
35 | TEPLSQL$SYS
36 | 2020-08-15
37 | TEPLSQL$SYS
38 | 2020-08-15
39 |
40 |
41 | teplsql.helper.default.package.body
42 | create or replace
43 | package body <%= lower( '${schema}' ) %>.<%@ include( ${this}.name ) %>\\n
44 | as
45 | <%@ include( ${this}.select.private.*.specification, , , ,1 ) %>\\n
46 | <%@ include( ${this}.plsql-type.private.*.specification, , , ,1 ) %>\\n
47 | <%@ include( ${this}.exception.private.*.specification, , , ,1 ) %>\\n
48 | <%@ include( ${this}.procedure.private.*.body, , , ,1 ) %>\\n
49 | <%@ include( ${this}.procedure.*.body, , , ,1 ) %>\\n
50 | <% if teplsql.template_exists( '${this}.init' )
51 | then %>
52 | begin
53 | <%@ include( ${this}.init, , , ,1 ) %>
54 | <% if teplsql.template_exists( '${this}.exceptions-block.*.body' ) then %>
55 | exception
56 | <%@ include( ${this}.exceptions-block.*.body, , , ,1 ) %>\\n
57 | <% end if; %>
58 | <% end if; %>
59 | end;
60 | <%= '/' %>\\n
61 |
62 | code to generate the BODY of the package
63 | TEPLSQL$SYS
64 | 2020-08-15
65 | TEPLSQL$SYS
66 | 2020-08-15
67 |
68 |
69 | teplsql.helper.default.package.specification
70 | create or replace
71 | package <%= lower('${schema}') %>.<%@ include( ${this}.name ) %>\\n
72 | <%@ include( ${this}.authid-spec, , , ,1 ) %>\\n
73 | <% if teplsql.template_exists( '${this}.accessibility' ) then %>
74 | <%@ include( ${this}.access-spec, , , ,1 ) %><% end if; %>
75 | as
76 | <%@ include( ${this}.documentation, , , ,1 ) %>
77 |
78 | <%@ include( ${this}.select.*.specification, , , ,1 ) %>\\n
79 |
80 | <%@ include( ${this}.plsql-type.*.specification, , , ,1 ) %>\\n
81 |
82 | <%@ include( ${this}.variable.*.specification, , , ,1 ) %>\\n
83 |
84 | <%@ include( ${this}.exception.*.specification, , , ,1 ) %>\\n
85 |
86 | <%@ include( ${this}.procedure.*.specification, , , ,1 ) %>\\n
87 |
88 | end;
89 | <%= '/' %>
90 |
91 | code to generate the specification
92 | TEPLSQL$SYS
93 | 2020-08-15
94 | TEPLSQL$SYS
95 | 2020-08-15
96 |
97 |
98 | teplsql.helper.default.select.SQL
99 | select * from dual
100 | The actual SQL statement
101 | TEPLSQL$SYS
102 | 2020-08-15
103 | TEPLSQL$SYS
104 | 2020-08-15
105 |
106 |
107 | teplsql.helper.default.select.name
108 | ${object_name}
109 | Name of SQL statement
110 | TEPLSQL$SYS
111 | 2020-08-15
112 | TEPLSQL$SYS
113 | 2020-08-15
114 |
115 |
116 | teplsql.helper.default.exception.number
117 | -20000
118 | Exception Number
119 | TEPLSQL$SYS
120 | 2020-08-15
121 | TEPLSQL$SYS
122 | 2020-08-15
123 |
124 |
125 | teplsql.helper.default.exception.text
126 | 'Something went wrong'
127 | Text displayed for a RAISE_APPLICATION_EXCEPTION.
128 | (in PL/SQL code format)
129 | TEPLSQL$SYS
130 | 2020-08-15
131 | TEPLSQL$SYS
132 | 2020-08-15
133 |
134 |
135 | teplsql.helper.default.exception.name
136 | ${object_name}
137 | name of the exception
138 | TEPLSQL$SYS
139 | 2020-08-15
140 | TEPLSQL$SYS
141 | 2020-08-15
142 |
143 |
144 | teplsql.helper.default.plsql-type.rcd-spec
145 | type <%@ include( ${this}.name ) %> is record <%@ include( ${this}.record ) %>;
146 | specification for RECORD TYPE.
147 | TEPLSQL$SYS
148 | 2020-08-15
149 | TEPLSQL$SYS
150 | 2020-08-15
151 |
152 |
153 | teplsql.helper.default.build.main
154 | <%!
155 | cursor "Columns"( schema in varchar2, table_name in varchar2, search_str in varchar2 ) is
156 | with PK_COLUMN_LIST as (
157 | select c.owner,c.table_name,cc.column_name
158 | ,decode(count(*) over (partition by c.owner,c.constraint_name),1,'YES')
159 | SINGLE_PK_COLUMN
160 | from sys.all_constraints c
161 | join sys.all_cons_columns cc
162 | on c.owner=cc.owner and c.constraint_name=cc.constraint_name
163 | where c.OWNER="Columns".schema
164 | and c.TABLE_NAME="Columns".TABLE_NAME
165 | and c.constraint_type='P'
166 | ), OWNER_TABLE_FILTERED_DATA as (
167 | select
168 | a.owner
169 | ,a.table_name
170 | ,a.column_name
171 | ,a.data_type
172 | ,a.data_type_mod
173 | ,a.data_type_owner
174 | ,a.data_length
175 | ,a.data_precision
176 | ,a.data_scale
177 | ,a.CHAR_USED
178 | ,decode(a.nullable,'Y','YES','NO') as NULLABLE
179 | ,a.column_id
180 | ,a.data_default -- warning this is a LONG
181 | ,case when a.data_default is not null then 'YES' else 'NO' end as HAS_DEFAULT
182 | ,a.hidden_column IS_HIDDEN
183 | ,a.VIRTUAL_COLUMN IS_VIRTUAL
184 | ,a.QUALIFIED_COL_NAME
185 | ,m.COMMENTS
186 | $IF SYS.DBMS_DB_VERSION.VERSION >= 12 $THEN
187 | ,a.USER_GENERATED
188 | $ELSE
189 | ,NULL AS USER_GENERATED
190 | $END
191 | ,case a.data_type
192 | when 'CHAR' then
193 | data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
194 | when 'VARCHAR' then
195 | data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
196 | when 'VARCHAR2' then
197 | data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
198 | when 'NCHAR' then
199 | data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
200 | when 'NUMBER' then
201 | case
202 | when a.data_precision is null and a.data_scale is null
203 | then
204 | 'NUMBER'
205 | when a.data_precision is null and a.data_scale is not null
206 | then
207 | 'NUMBER(38,'||a.data_scale||')'
208 | else
209 | a.data_type||'('||a.data_precision||','||a.data_SCALE||')'
210 | end
211 | when 'NVARCHAR' then
212 | a.data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
213 | when 'NVARCHAR2' then
214 | a.data_type||'('||a.char_length||decode(char_used,'B',' BYTE','C',' CHAR',null)||')'
215 | else
216 | a.data_type
217 | end DATA_TYPE_DESC
218 | ,nvl2(p.COLUMN_NAME,'YES','NO')
219 | as IS_PK
220 | ,coalesce(
221 | $IF SYS.DBMS_DB_VERSION.VERSION >= 12 $THEN
222 | a.IDENTITY_COLUMN -- 12c+
223 | $ELSE
224 | NULL -- pre-12c
225 | $END
226 | ,decode(a.DATA_TYPE,'NUMBER',p.SINGLE_PK_COLUMN)
227 | ,'NO'
228 | ) IS_ID
229 | from SYS.ALL_TAB_COLS a
230 | left outer join PK_COLUMN_LIST p
231 | on a.OWNER=p.OWNER
232 | and a.TABLE_NAME=p.TABLE_NAME
233 | and a.COLUMN_NAME=p.COLUMN_NAME
234 | left outer join SYS.ALL_COL_COMMENTS m
235 | on a.OWNER=m.OWNER
236 | and a.TABLE_NAME=m.TABLE_NAME
237 | and a.COLUMN_NAME=m.COLUMN_NAME
238 | where a.OWNER = "Columns".schema
239 | and a.TABLE_NAME = "Columns".TABLE_NAME
240 | and a.COLUMN_ID is not null -- VCs for FBIs
241 | ), OPTION_FILTERED_DATA as (
242 | select
243 | f.owner
244 | ,f.table_name
245 | ,f.column_name
246 | ,f.data_type
247 | ,f.data_type_mod
248 | ,f.data_type_owner
249 | ,f.data_length
250 | ,f.data_precision
251 | ,f.data_scale
252 | ,f.CHAR_USED
253 | ,f.nullable
254 | ,f.column_id
255 | ,f.has_default
256 | ,f.data_default
257 | ,f.is_hidden
258 | ,f.is_virtual
259 | ,f.QUALIFIED_COL_NAME
260 | ,f.DATA_TYPE_DESC
261 | ,f.IS_PK
262 | ,f.is_id
263 | ,f.COMMENTS
264 | ,f.USER_GENERATED
265 | from OWNER_TABLE_FILTERED_DATA f
266 | where
267 | ( -- include
268 | (("Columns".search_str is null or not regexp_like( "Columns".search_str, '(^| )[[:alpha:]]+' ))
269 | and f.is_hidden <> 'YES')
270 | or (regexp_like( "Columns".search_str, '(^| )[[:alpha:]]+' )
271 | and (1 = case
272 | when regexp_like( "Columns".search_str, '(^| )PK') and IS_PK='YES' then 1
273 | when regexp_like( "Columns".search_str, '(^| )VC') and IS_VIRTUAL='YES' then 1
274 | when regexp_like( "Columns".search_str, '(^| )HIDDEN') and IS_HIDDEN='YES' then 1
275 | when regexp_like( "Columns".search_str, '(^| )ID') and IS_ID='YES' then 1
276 | when regexp_like( "Columns".search_str, '(^| )NULLABLE') and NULLABLE='YES' then 1
277 | else 0
278 | end
279 | )
280 | or 1 = case
281 | when "Columns".search_str like '%+PK%' and is_pk='YES' then 1
282 | when "Columns".search_str like '%+VC%' and is_virtual='YES' then 1
283 | when "Columns".search_str like '%+HIDDEN%' and is_hidden='YES' then 1
284 | when "Columns".search_str like '%+ID%' and is_id='YES' then 1
285 | when "Columns".search_str like '%+NULLABLE%' and nullable='YES' then 1
286 | else 0
287 | end
288 | ) )
289 | -- exclude
290 | and not 1 = case
291 | when "Columns".search_str like '%-PK%' and is_pk='YES' then 1
292 | when "Columns".search_str like '%-VC%' and is_virtual='YES' then 1
293 | when "Columns".search_str like '%-HIDDEN%' and is_hidden='YES' then 1
294 | when "Columns".search_str like '%-ID%' and is_id='YES' then 1
295 | when "Columns".search_str like '%-NULLABLE%' and nullable='YES' then 1
296 | else 0
297 | end
298 | ), data as (
299 | select
300 | o.owner
301 | ,o.table_name
302 | ,o.column_name
303 | ,rpad(o.column_name
304 | ,max(length(o.column_name)) over () + 1 ) column_name_rpad
305 | ,o.data_type
306 | ,o.data_type_mod
307 | ,o.data_type_owner
308 | ,o.data_length
309 | ,o.data_precision
310 | ,o.data_scale
311 | ,o.CHAR_USED
312 | ,o.nullable
313 | ,o.column_id
314 | ,o.has_default
315 | ,o.data_default
316 | ,o.is_hidden
317 | ,o.is_virtual
318 | ,o.QUALIFIED_COL_NAME
319 | ,o.DATA_TYPE_DESC
320 | ,o.IS_PK
321 | ,o.is_ID
322 | ,o.COMMENTS
323 | ,row_number() over (partition by o.OWNER,o.TABLE_NAME order by o.COLUMN_ID)
324 | as ORDER_BY
325 | ,decode( row_number() over (partition by o.OWNER,o.TABLE_NAME order by o.COLUMN_ID)
326 | ,1, ' ', ',' ) as COMMA_FIRST
327 | ,row_number() over (partition by o.OWNER,o.TABLE_NAME order by o.COLUMN_ID desc)
328 | as ORDER_BY_DESC
329 | ,decode( row_number() over (partition by o.OWNER,o.TABLE_NAME order by o.COLUMN_ID desc)
330 | ,1, ' ', ',' ) as COMMA_LAST
331 | from OPTION_FILTERED_DATA o
332 | )
333 | select *
334 | from data d
335 | order by OWNER,TABLE_NAME,ORDER_BY;
336 |
337 | %>
338 |
339 | /*
340 | Building for ${this}
341 |
342 | Time : <%= systimestamp %>\\n
343 | Schema : ${schema}
344 | Table Name : ${table_name}
345 | */
346 |
347 | -- simple make all
348 | <%@ include( ${this}.*.*.make ) %>
349 | top-level Build
350 | TEPLSQL$SYS
351 | 2020-08-15
352 | TEPLSQL$SYS
353 | 2020-08-15
354 |
355 |
356 | teplsql.helper.default.select.documentation
357 | /**
358 | * SQL <%@ include( ${this}.name ) %>\\n
359 | */
360 |
361 | Documentation for the SQL in PL/doc format
362 | TEPLSQL$SYS
363 | 2020-08-15
364 | TEPLSQL$SYS
365 | 2020-08-15
366 |
367 |
368 | teplsql.helper.default.exception.documentation
369 | /**
370 | * Something didn't do what it was suppose to do.
371 | */
372 |
373 | Documentation of the exception in PL/Doc format
374 | TEPLSQL$SYS
375 | 2020-08-15
376 | TEPLSQL$SYS
377 | 2020-08-15
378 |
379 |
380 | teplsql.helper.default.package.documentation
381 | /**
382 | * Place Description of Package here
383 | *
384 | * @headcom
385 | */
386 |
387 | PL/Doc encoded documentation
388 | TEPLSQL$SYS
389 | 2020-08-15
390 | TEPLSQL$SYS
391 | 2020-08-15
392 |
393 |
394 | teplsql.helper.default.package.make
395 | <%@ include( ${this}.specification ) %>
396 |
397 | <%@ include( ${this}.body ) %>
398 | makes both specification followed by the body
399 | TEPLSQL$SYS
400 | 2020-08-15
401 | TEPLSQL$SYS
402 | 2020-08-15
403 |
404 |
405 | teplsql.helper.default.select.make
406 | create or replace
407 | view ${schema}.<%@ include( ${this}.name )%>\\n
408 | as
409 | <%@ include( ${this}.SQL )%>;
410 |
411 | creates the VIEW
412 | TEPLSQL$SYS
413 | 2020-08-15
414 | TEPLSQL$SYS
415 | 2020-08-15
416 |
417 |
418 | teplsql.helper.default.exception.specification
419 | <%@ include( ${this}.documentation ) %>
420 | <%@ include( ${this}.name ) %> exception;
421 | <% if teplsql.template_exists( '${this}.constant-number-name' ) then %>
422 | <%@ include( ${this}.constant-text-name ) %> constant varchar2(1024) := <%@ include( ${this}.text ) %>;
423 | <% end if; %>
424 | <% if teplsql.template_exists( '${this}.constant-number-name' ) then %>
425 | <%@ include( ${this}.constant-number-name ) %> constant int := <%@ include( ${this}.number ) %>;
426 | pragma exception_init( <%@ include( ${this}.name ) %>, <%@ include( ${this}.constant-number-name ) %> );
427 | <% else %>
428 | pragma exception_init( <%@ include( ${this}.name ) %>, <%@ include( ${this}.number ) %> );
429 | <% end if; %>
430 |
431 | specification for all parts of an exception.
432 | TEPLSQL$SYS
433 | 2020-08-15
434 | TEPLSQL$SYS
435 | 2020-08-15
436 |
437 |
438 | teplsql.helper.default.exception.when-clause
439 | when <%@ include( ${this}.name ) %> then
440 | <%@ include( ${this}.exception-code, , , ,1 ) %>
441 |
442 | Exception where clause for this exception.
443 | TEPLSQL$SYS
444 | 2020-08-15
445 | TEPLSQL$SYS
446 | 2020-08-15
447 |
448 |
449 | teplsql.helper.default.plsql-type.specification
450 | <% if teplsql.template_exists( '${this}.documentation' ) then %>
451 | <%@ include( ${this}.documentation ) %>
452 | <% end if; %>
453 | <% if teplsql.template_exists( '${this}.data-type' ) then %>
454 | <%@ include( ${this}.subtype-spec ) %>\\n
455 | <% elsif teplsql.template_exists( '${this}.record' ) then %>
456 | <%@ include( ${this}.rcd-spec ) %>\\n
457 | <% else %>
458 | -- missing <block> for '${object_name}' - need to define "data-type" or "record"
459 | <% end if; %>
460 | <% if teplsql.template_exists( '${this}.nt-name' ) then %>
461 | <%@ include( ${this}.nt-spec ) %>\\n
462 | <% end if; %>
463 | <% if teplsql.template_exists( '${this}.aa-name' ) then %>
464 | <%@ include( ${this}.aa-spec ) %>\\n
465 | <% end if; %>
466 | <% if teplsql.template_exists( '${this}.ref-name' ) then %>
467 | <%@ include( ${this}.ref-spec ) %>\\n
468 | <% end if; %>\\n
469 |
470 | Creates the specification for a record, nested tab
471 | TEPLSQL$SYS
472 | 2020-08-15
473 | TEPLSQL$SYS
474 | 2020-08-15
475 |
476 |
477 | teplsql.helper.default.plsql-type.aa-spec
478 | <% if teplsql.template_exists( '${this}.aa-key-data-type' ) then %>
479 | type <%@ include( ${this}.aa-name ) %> is table of <%@ include( ${this}.name ) %> index by <%@ include( ${this}.aa-key-data-type ) %>;<% else %>
480 | type <%@ include( ${this}.aa-name ) %> is table of <%@ include( ${this}.name ) %> index by pls_integer;<% end if; %>
481 | Creates the Associative Array TYPE
482 | TEPLSQL$SYS
483 | 2020-08-15
484 | TEPLSQL$SYS
485 | 2020-08-15
486 |
487 |
488 | teplsql.helper.default.plsql-type.nt-spec
489 | type <%@ include( ${this}.nt-name ) %> is table of <%@ include( ${this}.name ) %>;
490 | specification for the Nested Table TYPE
491 | TEPLSQL$SYS
492 | 2020-08-15
493 | TEPLSQL$SYS
494 | 2020-08-15
495 |
496 |
497 | teplsql.helper.default.function
498 | CREATE OR REPLACE
499 | <%= '<' %>%@ include( ${this}.spec ) %<%= '>' %><%= '\' || '\' || 'n' %>
500 | AS
501 | <%= '<' %>%@ include( ${this}.decl ) %<%= '>' %><%= '\' || '\' || 'n' %>
502 | BEGIN
503 | <%= '<' %>%@ include( ${this}.bdy ) %<%= '>' %><%= '\' || '\' || 'n' %>
504 | END;
505 | <%= '<' %>%= '/' %<%= '>' %><%= '\' || '\' || 'n' %>
506 | Template for a Standalone function
507 | TEPLSQL$SYS
508 | 2020-08-15
509 | TEPLSQL$SYS
510 | 2020-08-15
511 |
512 |
513 | teplsql.helper.default.exception.raise-error
514 | raise_application_error( <% if teplsql.template_exists( '${this}.constant-number-name' ) then %>
515 | <%@ include( ${this}.constant-number-name) %><% else %>
516 | <%@ include( ${this}.number) %><% end if; %>, <% if teplsql.template_exists( '${this}.constant-text-name' ) then %>
517 | <%@ include( ${this}.constant-text-name) %><% else %>
518 | <%@ include( ${this}.text ) %><% end if; %> );
519 |
520 | PL/Sql code that runs inside an EXCEPTION block
521 | TEPLSQL$SYS
522 | 2020-08-15
523 | TEPLSQL$SYS
524 | 2020-08-15
525 |
526 |
527 | teplsql.helper.default.package.initialization
528 | begin
529 | <%@ include( ${this}.init, , , ,1 ) %>
530 | end;
531 |
532 | Package initialization block.
533 | TEPLSQL$SYS
534 | 2020-10-05
535 | TEPLSQL$SYS
536 | 2020-10-05
537 |
538 |
539 | teplsql.helper.default.package.authid
540 | current_user
541 | Set package as Definer's Rights or Invoker's Rights (default)
542 | TEPLSQL$SYS
543 | 2020-08-29
544 | TEPLSQL$SYS
545 | 2020-08-29
546 |
547 |
548 | teplsql.helper.default.procedure.return-variable-name
549 | return_variable
550 | variable name for return value
551 | TEPLSQL$SYS
552 | 2020-10-06
553 | TEPLSQL$SYS
554 | 2020-10-06
555 |
556 |
557 | teplsql.helper.default.procedure.decl
558 | -- set variables here
559 |
560 | variable/type/function/cursor definitions go her
561 | TEPLSQL$SYS
562 | 2020-10-03
563 | TEPLSQL$SYS
564 | 2020-10-03
565 |
566 |
567 | teplsql.helper.default.procedure.documentation
568 | /**
569 | * Procedure <%@ include( ${this}.name ) %>\\n
570 | */
571 |
572 | PL/Doc encoded documentation
573 | TEPLSQL$SYS
574 | 2020-10-03
575 | TEPLSQL$SYS
576 | 2020-10-03
577 |
578 |
579 | teplsql.helper.default.procedure.name
580 | ${object_name}
581 | Name of the Function/Procedure
582 | TEPLSQL$SYS
583 | 2020-10-03
584 | TEPLSQL$SYS
585 | 2020-10-03
586 |
587 |
588 | teplsql.helper.default.procedure.spec
589 | <% if teplsql.template_exists( '${this}.return-variable-type' ) then %>
590 | function <%@ include( ${this}.name ) %> <% if teplsql.template_exists( '${this}.parameters' ) then
591 | teplsql.set_tab(1); %>(<%@ include( ${this}.parameters ) %>)
592 | <% teplsql.goto_tab(1); %>return <%@ include( ${this}.return-type ) %><% else %>
593 | return <%@ include( ${this}.return-type ) %><% end if; %>
594 | <% else %>
595 | procedure <%@ include( ${this}.name ) %><% if teplsql.template_exists( '${this}.parameters' ) then
596 | teplsql.set_tab(1); %>(<%@ include( ${this}.parameters ) %>)<% end if; %>
597 | <% end if; %>
598 |
599 | shortline specification for function/procedure
600 | TEPLSQL$SYS
601 | 2020-10-03
602 | TEPLSQL$SYS
603 | 2020-10-03
604 |
605 |
606 | teplsql.helper.default.procedure.specification
607 | <%@ include( ${this}.documentation ) %>
608 | <%@ include( ${this}.spec ) %>;
609 |
610 | Specification of the function for a Package
611 | TEPLSQL$SYS
612 | 2020-10-03
613 | TEPLSQL$SYS
614 | 2020-10-03
615 |
616 |
617 | teplsql.helper.default.procedure.bdy
618 | -- <block>=bdy for <procedure>=${object_name} not defined
619 | null;
620 | The body of the code
621 | TEPLSQL$SYS
622 | 2020-10-03
623 | TEPLSQL$SYS
624 | 2020-10-03
625 |
626 |
627 | teplsql.helper.default.procedure.body
628 | <%@ include( ${this}.spec ) %>\\n
629 | as
630 | <%@ include( ${this}.select.*.specification, , , ,1 ) %>
631 | <%@ include( ${this}.plsql-type.*.specification, , , ,1 ) %>
632 | <%@ include( ${this}.exception.*.specification, , , ,1 ) %>
633 | <% if teplsql.template_exists( '${this}.return-variable-type' ) then %>
634 | <%@ include( ${this}.return-decl, , , ,1 ) %>
635 | <% end if; %>
636 | <%@ include( ${this}.decl, , , ,1 ) %>
637 | <%@ include( ${this}.procedure.*.body, , , ,1 ) %>
638 | \\nbegin
639 | <%@ include( ${this}.bdy, , , ,1 ) %>\\n
640 | <% if teplsql.template_exists( '${this}.return-variable-type' ) then %>
641 | \\n
642 | <%@ include( ${this}.return-spec, , , ,1 ) %>
643 | <% end if; %>
644 | <% if teplsql.template_exists( '${this}.exceptions-block.*.body' ) then %>
645 | exception
646 | <%@ include( ${this}.exceptions-block.*.body, , , ,1 ) %>\\n
647 | <% end if; %>
648 | end <%@ include( ${this}.name ) %>;
649 |
650 | Body of the function for a Package
651 | TEPLSQL$SYS
652 | 2020-10-03
653 | TEPLSQL$SYS
654 | 2020-10-03
655 |
656 |
657 | teplsql.helper.default.procedure.return-type
658 | <%@ include( ${this}.return-variable-type ) %>
659 | return data type (if a function)
660 | TEPLSQL$SYS
661 | 2020-10-06
662 | TEPLSQL$SYS
663 | 2020-10-06
664 |
665 |
666 | teplsql.helper.default.plsql-type.name
667 | ${object_name}
668 | name of PL/SQL (sub)type
669 | TEPLSQL$SYS
670 | 2020-10-06
671 | TEPLSQL$SYS
672 | 2020-10-06
673 |
674 |
675 | teplsql.helper.default.plsql-type.ref-spec
676 | type <%@ include( ${this}.ref-name ) %> is ref cursor return <%@ include( ${this}.name ) %>;
677 | specification for REF type
678 | TEPLSQL$SYS
679 | 2020-10-06
680 | TEPLSQL$SYS
681 | 2020-10-06
682 |
683 |
684 | teplsql.helper.default.select.specification
685 | <%@ include( ${this}.documentation ) %>
686 | cursor <%@ include( ${this}.spec ) %> is
687 | <%@ include( ${this}.SQL, , , ,1 ) %>;
688 |
689 | Creates a CURSOR for PL/SQL
690 | TEPLSQL$SYS
691 | 2020-08-30
692 | TEPLSQL$SYS
693 | 2020-08-30
694 |
695 |
696 | teplsql.helper.default.select.spec
697 | <%@ include( ${this}.name ) %><% if teplsql.template_exists( '${this}.parameters' ) then %>(<% teplsql.set_tab(1); %>
698 | <%@ include( ${this}.parameters ) %> )<% end if; %>
699 | spec portion of a CURSOR
700 | TEPLSQL$SYS
701 | 2020-08-30
702 | TEPLSQL$SYS
703 | 2020-08-30
704 |
705 |
706 | teplsql.helper.default.plsql-type.subtype-spec
707 | subtype <%@ include( ${this}.name ) %> is <%@ include( ${this}.data-type ) %>;
708 | specification for RECORD TYPE.
709 | TEPLSQL$SYS
710 | 2020-10-06
711 | TEPLSQL$SYS
712 | 2020-10-06
713 |
714 |
715 | teplsql.helper.default.exception.exception-code
716 | -- default exception process
717 | <%@ include( ${this}.raise-error ) %>
718 |
719 | Actual code to run when the exception is encountered
720 | TEPLSQL$SYS
721 | 2020-10-05
722 | TEPLSQL$SYS
723 | 2020-10-05
724 |
725 |
726 | teplsql.helper.default.variable.name
727 | ${object_name}
728 | name of the variable
729 | TEPLSQL$SYS
730 | 2020-10-05
731 | TEPLSQL$SYS
732 | 2020-10-05
733 |
734 |
735 | teplsql.helper.default.variable.data-type
736 | undefined
737 | data type of the variable
738 | TEPLSQL$SYS
739 | 2020-10-05
740 | TEPLSQL$SYS
741 | 2020-10-05
742 |
743 |
744 | teplsql.helper.default.variable.specification
745 | <% if teplsql.template_exists( '${this}.documentation' )
746 | then %>
747 | <%@ include( ${this}.documentation ) %>
748 | <% end if; %>
749 | <%@ include( ${this}.name ) %> <% if teplsql.template_exists('${this}.constant-value' )
750 | then
751 | %>constant <%@ include( ${this}.data-type ) %> := <%@ include( ${this}.constant-value ) %>;
752 | <% elsif teplsql.template_exists('${this}.value' )
753 | then
754 | %> <%@ include( ${this}.data-type ) %> := <%@ include( ${this}.value ) %>;
755 | <% else %>
756 | <%@ include( ${this}.data-type ) %>;
757 | <% end if; %>
758 |
759 | specification line
760 | TEPLSQL$SYS
761 | 2020-10-05
762 | TEPLSQL$SYS
763 | 2020-10-05
764 |
765 |
766 | teplsql.helper.default.procedure.return-spec
767 | return <%@ include( ${this}.return-variable-name ) %>;
768 |
769 | return statement
770 | TEPLSQL$SYS
771 | 2020-10-06
772 | TEPLSQL$SYS
773 | 2020-10-06
774 |
775 |
776 | teplsql.helper.default.procedure.return-decl
777 | <%@ include( ${this}.return-variable-name ) %> <%@ include( ${this}.return-variable-type ) %>;
778 |
779 | return variable declaration
780 | TEPLSQL$SYS
781 | 2020-10-06
782 | TEPLSQL$SYS
783 | 2020-10-06
784 |
785 |
786 | teplsql.helper.default.procedure.make
787 | create or replace
788 | <%@ include( ${this}.body ) %>
789 | <%= '/' %>
790 |
791 | make a standalone procedure/function
792 | TEPLSQL$SYS
793 | 2020-10-07
794 | TEPLSQL$SYS
795 | 2020-10-07
796 |
797 |
798 | teplsql.helper.default.select.cte
799 | <%@ include( ${this}.name ) %> as (
800 | <%@ include( ${this}.SQL , , , ,1 ) %>\\n
801 | )
802 | Create a CTE (does not have WITH keyword)
803 | TEPLSQL$SYS
804 | 2020-10-07
805 | TEPLSQL$SYS
806 | 2020-10-07
807 |
808 |
809 | teplsql.helper.default.package.authid-spec
810 | authid <%@ include( ${this}.authid ) %>
811 |
812 | creates the AUTHID line
813 | TEPLSQL$SYS
814 | 2020-10-07
815 | TEPLSQL$SYS
816 | 2020-10-07
817 |
818 |
819 | teplsql.helper.default.package.access-spec
820 | accessible by (<% teplsql.set_tab(1); %><%@ include( ${this}.accessibility ) %> )
821 |
822 | creates the ACCESSIBLE BY line
823 | TEPLSQL$SYS
824 | 2020-10-07
825 | TEPLSQL$SYS
826 | 2020-10-07
827 |
828 |
829 |
830 | $end
831 |
832 | end te_default_helper_templates;
833 | /
834 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tePLSQL
2 | Template Engine for PLSQL.
3 |
4 | tePLSQL is a template engine written completly in PL/SQL, generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates. Templates are written with embebed Dynamic PL/SQL .
5 |
6 | With tePLSQL you should prepare the data to display in your PL/SQL packages and do business calculations, and then the template displays that already prepared data. In the template you are focusing on how to present the data, and outside the template you are focusing on what data to present.
7 |
8 | Now tePLSQL has the same syntax as the old fashion [Oracle PSP](http://docs.oracle.com/cd/E11882_01/appdev.112/e41502/adfns_psp.htm#ADFNS016) so you do not have to learn any new template language and your PSP will be supported by tePLSQL making some small modifications.
9 |
10 | Templates are processed and a single block of PL/SQL code being executed dynamically, as does the Oracle PSP loader do.
11 |
12 | For a quick look see [basic example](#basic-example). The best example of use tePLSQL is [tapiGen2](https://github.com/osalvador/tapiGen2)
13 |
14 | **topics**:
15 |
16 | - [Prerequisites for developing and deploying tePLSQL templates](#prerequisites)
17 | + [Install](#install)
18 | + [Compatibility](#compatibility)
19 | - [Developing tePLSQL templates](#developing)
20 | + [tePLSQL elements](#teElements)
21 | + [Specifying tePLSQL template characteristics](#characteristics)
22 | + [tePLSQL arguments](#arguments)
23 | + [Naming the tePLSQL templates](#naming)
24 | + [Including the contents of other template](#include)
25 | + [Declaring global variables in a tePLSQL template](#declare)
26 | + [Specifying executable statements in a tePLSQL template](#executable)
27 | + [Substituting expression values in a tePLSQL template](#expression)
28 | + [Escaping reserved words in a tePLSQL template](#escape)
29 | + [Print line break to the output](#lineBreak)
30 | + [Remove line break from the output](#noLineBreak)
31 | - [Loading and storing tePLSQL templates into the Database](#load)
32 | - [Examples of tePLSQL templates](#examples)
33 | - [Debugging tePLSQL templates](#debug)
34 | - [tePLSQL API reference](#apiReference)
35 | - [Advance Topics](#advance)
36 | + [Indention](#indention)
37 | + [tePLSQL Engine's Options](#engineOptions)
38 | + [Template Globbing](#templateGlobbing)
39 | + [Build Templates](#BuildTemplates)
40 | - [Contributing](#contributing)
41 | - [License](#license)
42 |
43 |
44 | ## Prerequisites for developing and deploying tePLSQL templates
45 | To develop and deploy tePLSQL templates, you must meet these prerequisites:
46 |
47 | - To write a tePLSQL templates you need a text editor. No other development tool is required.
48 | - To load a tePLSQL template you need an account on the database in which to load the templates.
49 | - To deploy tePLSQL template you must install tePLSQL package.
50 |
51 |
52 | ### Install
53 | Download and compile `TE_TEMPLATES.sql`,`TEPLSQL.pks` and `TEPLSQL.pkb`. No schema grants are necesary.
54 | Or just install by calling install.sql via sqlplus or sqlcl.
55 |
56 |
57 | ### Compatibility
58 | tePLSQL use regular expressions to process templates. Regular expressions were added in Oracle version 10 therefore teplsql works in Oracle Database 10g, 11g and 12c (all editions including XE).
59 |
60 |
61 | ## Developing tePLSQL templates
62 | The order and placement of the tePLSQL directives and declarations is usually not significant. It becomes significant only when another template is included. For ease of maintenance, we recommends that you put the directives and declarations near the beginning of the template.
63 |
64 | The next table lists the tePLSQL elements and directs you to the section that explains how to use them.
65 |
66 |
67 | ### tePLSQL elements
68 |
69 | |Element | Name | Description | Section
70 | |--------|------|------------- | ----
71 | |`<%@ template key=value,key=value %>` | Template Directive | Characteristics of the template | [Specifying tePLSQL template characteristics](#characteristics)
72 | |`${varName}` | Arguments | The arguments are defined in a key-value associative array that receives as parameter by the render | [tePLSQL arguments](#arguments)
73 | |`<%@ include(...) %>` | Include Directive | Includes and evaluates the specified template | [Including the contents of other template](#include)
74 | |`<%! ... %>` | Declaration block | The declaration for a set of PL/SQL variables that are visible throughout the template, not just within the next BEGIN/END block. | [Declaring global variables in a tePLSQL template](#declare)
75 | |`<% ... %>` | Code block |A set of PL/SQL statements to be executed when the template is run. | [Specifying executable statements in a tePLSQL template](#executable)
76 | |`<%= ... %>` | Expression block | A single PL/SQL expression | [Substituting expression values in a tePLSQL template](#expression)
77 | |`\\` | Escaped character | Escaping reserved words like `<% .. %>` and `q'[]'` | [Escaping reserved words strings in a tePLSQL template](#escape)
78 | | `\\n` | Line Break | Print line break to the output | [Print line break to the output](#lineBreak)
79 | | `!\n` | Remove line break | Remove line break from the output | [Remove line break from the output](#noLineBreak)
80 |
81 |
82 |
83 | ### Specifying tePLSQL template characteristics
84 | Use the `<%@ template ... %>` directive to specify characteristics of the template:
85 |
86 | - What is the name of the template, mandatory.
87 | - Any other user-defined feature like version, date, author...
88 |
89 | The characteristics are a pair of key-value separated by commas.
90 |
91 | Values defined in `<%@ template ... %>` directive can be accessed anywhere in the template as a variable argument, preceding the name of the key with the `template`.
92 |
93 | #### Syntax
94 |
95 | `<%@ template key=value, key2=value2 %>`
96 |
97 | The syntax is case-sensitive but space-insensitive. Values with blanks are not allowed.
98 |
99 | #### Example
100 | ```
101 | <%@ template name=example_template, version=0.1 %>
102 | Processing template ${template_name} with version ${template_version}
103 | ```
104 |
105 | Output:
106 | ```
107 | Processing template example_template with version 0.1
108 | ```
109 |
110 |
111 | ### tePLSQL arguments
112 | The arguments variable are defined in Oracle PL/SQL associative array that receives as parameter by the render. Within the templates reference to ahce variables via `${varName}`.
113 |
114 | #### Syntax
115 | ```plsql
116 | DECLARE
117 | p_vars teplsql.t_assoc_array;
118 | BEGIN
119 | p_vars ('FullName') := 'Oscar Salvador Magallanes';
120 | END;
121 | ```
122 |
123 | #### Example
124 | ```plsql
125 | DECLARE
126 | p_template VARCHAR2 (32000);
127 | p_vars teplsql.t_assoc_array;
128 | BEGIN
129 | p_template :='Hi ${FullName}!';
130 |
131 | p_vars ('FullName') := 'Oscar Salvador Magallanes';
132 | p_template := teplsql.render (p_vars, p_template);
133 | DBMS_OUTPUT.put_line (p_template);
134 | END;
135 | ```
136 |
137 | Output:
138 | ```
139 | Hi Oscar Salvador Magallanes
140 | ```
141 |
142 |
143 | ### Naming the tePLSQL templates
144 | In order to access and store templates correctly you must specify the template name in the `<%@ template ... %>` directive.
145 |
146 | To specify a template name, use this directive, where tmpl is the name for the template:
147 |
148 | <%@ template name=tmpl %>
149 |
150 | It is the name of the template, not the name of the object that you store the template.
151 |
152 |
153 | ### Including the contents of other template
154 | You can set up an include including other tePLSQL templates in the current template. Insert this directive at the point where the content of the other template is to appear, replacing template_name with the name of the template to be included.
155 |
156 | Any variables available in the current template are also available within the included template. However, all variables and functions defined in the included template have the local scope.
157 |
158 | Nested includes are allowed. tePLSQL search the template and include it in a new DECLARE BEGIN END; block, which assigned its own scope.
159 |
160 | ```
161 | <%@ include(template1) %>
162 | --template1 include template2
163 | <%@ include(template2) %>
164 | --template3 include template3
165 | <%@ include(template3) %>
166 | ```
167 |
168 | Will be interpreted as:
169 | ```plsql
170 | DECLARE
171 | BEGIN
172 | --template1
173 | DECLARE
174 | BEGIN
175 | --template2
176 | DECLARE
177 | BEGIN
178 | --template3
179 | END;
180 | END;
181 | END;
182 | ```
183 |
184 | #### Syntax
185 | ```
186 | <%@ include(template_name, object_name, object_type, schema, indent ) %>
187 | ```
188 |
189 | |Parameter | Description
190 | | ---------| ------------
191 | | `template_name` | The name of the template. Default NULL.
192 | | `object_name`| The name of the object (usually the name of the package). Default TE_TEMPLATES table.
193 | | `object_type`| The type of the object (PACKAGE, PROCEDURE, FUNCTION...). Default PACKAGE.
194 | | `schema`| The schema of the object. Default NULL.
195 | | `indent`| Indent the included template results? 1=yes, 0=no (default)
196 |
197 | You can use the include feature to pull in libraries of code into multiple templates. Alternatively, you can use this feature as a macro capability to include the same section of script code in multiple places in a template.
198 |
199 | #### Example
200 | This example includes a footer template
201 |
202 | <%@ include (footer) %>
203 |
204 | This template will be search into `TE_TEMPLATES` table.
205 |
206 | This is the same example, but the footer template is saved in package spec.
207 |
208 | <%@ include(footer , tmpl_tab_api) %>
209 |
210 |
211 | ### Declaring global variables in a tePLSQL template
212 |
213 | You can use the `<%! ... %>` directive to define a set of tePLSQL variables that are visible throughout the template, not just within the next BEGIN/END block. This element typically spans multiple lines, with individual PL/SQL variable declarations ended by semicolons.
214 |
215 | You can specify multiple declaration blocks; internally, they are all merged into a single block.
216 |
217 | You can also use explicit DECLARE blocks within the `<% ... %>` delimiters that are explained in "Specifying executable statements in a tePLSQL template". These declarations are only visible to the BEGIN/END block that follows them.
218 |
219 | To make things easier to maintain, keep all your directives and declarations near the beginning of a PL/SQL server template.
220 |
221 | #### Syntax
222 | ```plsql
223 | <%! PL/SQL declaration;
224 | [ PL/SQL declaration; ] ... %>
225 | ```
226 |
227 | The usual PL/SQL syntax is allowed within the block. The delimiters server as shorthand, enabling you to omit the DECLARE keyword. All declarations are available to the code later in the template.
228 |
229 | #### Example
230 | ```plsql
231 | <%!
232 | CURSOR emp_cursor IS
233 | SELECT last_name, first_name
234 | FROM hr.employees
235 | ORDER BY last_name;
236 | %>
237 | ```
238 |
239 |
240 | ### Specifying executable statements in a tePLSQL template
241 | You can use the `<% ... %>` code block directive to run a set of PL/SQL statements when the template is run.
242 |
243 | This element typically spans multiple lines, with individual PL/SQL statements ended by semicolons. The statements can include complete blocks.
244 |
245 | The statements can also be the bracketing parts of IF/THEN/ELSE or BEGIN/END blocks. When a code block is split into multiple directives, you can put output text or other directives in the middle, and the middle pieces are conditionally executed when the template is run. The example provides an illustration of this technique.
246 |
247 | All the usual PL/SQL syntax is allowed within the block.
248 |
249 | #### Syntax
250 | ```plsql
251 | <% PL/SQL statement;
252 | [ PL/SQL statement; ] ... %>
253 | ```
254 |
255 | #### Example
256 | ```plsql
257 | <%! v_color VARCHAR2(20); %>
258 | <% FOR ITEM IN (SELECT product_name, list_price, catalog_url
259 | FROM product_information
260 | WHERE list_price IS NOT NULL
261 | ORDER BY list_price DESC) LOOP
262 | IF item.list_price > p_minprice THEN
263 | v_color := '#CCCCFF';
264 | ELSE
265 | v_color := '#CCCCCC';
266 | END IF;
267 | %>
268 |
269 | | <%= item.product_name %> |
270 | <%= item.list_price %> |
271 |
272 | <% END LOOP; %>
273 | ```
274 |
275 |
276 | ### Substituting expression values in a tePLSQL template
277 | An expression directive outputs a single PL/SQL expression, such as a string, arithmetic expression, function call, or combination of these things. The result is substituted as a string at that spot in the output that is produced by the template. The expression result must be a string value or be able to be cast to a string. For any types that cannot be implicitly cast, such as DATE, pass the value to the PL/SQL `TO_CHAR` function.
278 |
279 | #### Syntax
280 | The syntax of an expression directive is as follows, where the expression placeholder is replaced by the desired expression:
281 |
282 | `<%= expression %>`
283 |
284 | You need not end the PL/SQL expression with a semicolon.
285 |
286 | #### Example
287 | This example includes a directive to print the value of a variable in a row of a cursor:
288 |
289 | `<%= emp_record.last_name %>`
290 |
291 | The content within the `<%= ... %>` delimiters is processed by the `tePLSQL.P` procedure, which trims leading or trailing white space and requires that you enclose literal strings in single quotation marks.
292 |
293 | You can use concatenation by using the twin pipe symbol (||) as in PL/SQL. This directive shows an example of concatenation:
294 |
295 | `<%= 'The employee last name is ' || emp_record.last_name %>`
296 |
297 |
298 |
299 | ### Escaping reserved words in a tePLSQL template
300 | tePLSQL has three reserved words:
301 |
302 | - `q'[]'`
303 | - `<%`
304 | - `%>`
305 | - `\\n`
306 |
307 | tePLSQLP use `q'[]'` alternative quoting mechanism to print template text into buffer, and `<% %>` to define directives.
308 |
309 | If you want to escape this reserved words you must use `\\`.
310 |
311 | #### Syntax
312 |
313 | `\\reserved_word`
314 |
315 | #### Example
316 | ```
317 | Scaping reserved words:
318 | - q\\'[]\\'
319 | - <\\%
320 | - %\\>
321 | - \\\\n
322 | ```
323 |
324 | Output:
325 | ```
326 | Scaping reserved words:
327 | - q'[]'
328 | - <%
329 | - %>
330 | - \\n
331 | ```
332 |
333 |
334 | ### Print line break to the output
335 | The control of the white-space in a template is a problem that to some extent haunts every template engine in the business.
336 |
337 | tePLSQL use white-space stripping. It automatically ignores (i.e. does not print to the output) superfluous white-spaces. The indentation white-space, and trailing white-space at the end of the line (includes the line break) will be ignored in lines that contains only tePLSQL tags (e.g. `<%if ... %>`, `<%! ... %>`), apart from the ignored white-space itself.
338 |
339 | If you want to force insert a line break you can use `\\n`
340 |
341 | #### Syntax
342 |
343 | `\\n`
344 |
345 | #### Example
346 | Without `\\n`
347 | ```
348 | <% for i in 1 .. 10 loop %>
349 | Value: <%=i%>
350 | <%end loop;%>
351 | ```
352 |
353 | ```
354 | Value: 1Value: 2Value: 3Value: 4Value: 5Value: 6Value: 7Value: 8Value: 9Value: 10
355 | ```
356 |
357 | With `\\n`
358 | ```
359 | <% for i in 1 .. 10 loop %>
360 | Value: <%=i%>\\n
361 | <%end loop;%>
362 | ```
363 |
364 | ```
365 | Value: 1
366 | Value: 2
367 | Value: 3
368 | Value: 4
369 | Value: 5
370 | Value: 6
371 | Value: 7
372 | Value: 8
373 | Value: 9
374 | Value: 10
375 | ```
376 |
377 |
378 | ### Remove line break from the output
379 | By the same way you can indicate in the template that a line break is not printed on the output.
380 |
381 | #### Syntax
382 |
383 | `!\n`
384 |
385 | #### Example
386 | Without `!\n`
387 | ```
388 | Values:
389 | <% for i in 1 .. 10 loop %>
390 | <%=i%>,
391 | <%end loop;%>
392 | ```
393 |
394 | ```
395 | Values:
396 | 1,
397 | 2,
398 | 3,
399 | 4,
400 | 5,
401 | 6,
402 | 7,
403 | 8,
404 | 9,
405 | 10,
406 | ```
407 |
408 | With `!\n`
409 | ```
410 | Values:!\n
411 | <% for i in 1 .. 10 loop %>
412 | <%=i%>,!\n
413 | <%end loop;%>
414 | ```
415 |
416 | ```
417 | Values:1,2,3,4,5,6,7,8,9,10,
418 | ```
419 |
420 |
421 | ## Loading and storing tePLSQL templates into the Database
422 | You can store tePLSQL templates in the database in two ways: In the relational table `TE_TEMPLATES` or in any Oracle Object.
423 |
424 | ### TE_TEMPLATES table
425 | `TE_TEMPLATES` table Is the default way of storing a tePLSQL templates. The table has a `TEMPLATE` column defined as CLOB where the template is loaded.
426 |
427 | #### Syntax
428 |
429 | ```
430 | TABLE TE_TEMPLATES
431 | Name Null? Type
432 | ----------------------------------------- -------- ----------------------------
433 | NAME NOT NULL VARCHAR2(300)
434 | TEMPLATE CLOB
435 | DESCRIPTION VARCHAR2(300)
436 | CREATED_BY NOT NULL VARCHAR2(100)
437 | CREATED_DATE NOT NULL DATE
438 | MODIFIED_BY NOT NULL VARCHAR2(100)
439 | MODIFIED_DATE NOT NULL DATE
440 | ```
441 |
442 | #### Example
443 | Insert template named *adding* into `TE_TEMPLATES` table
444 | ```plsql
445 | INSERT INTO te_templates (name
446 | , template)
447 | VALUES ('ADDING'
448 | , '<%@ template
449 | name=adding,
450 | version=0.1 %>
451 | <%! x pls_integer := 1 + 1; %>
452 | Processing template ${template_name} with version ${template_version}
453 | The variable x has the value: <%= x %>');
454 |
455 | COMMIT;
456 | ```
457 |
458 | Processing the template:
459 | ```plsql
460 | SET SERVEROUTPUT on;
461 | BEGIN
462 | DBMS_OUTPUT.put_line (teplsql.process (p_template_name => 'adding'));
463 | END;
464 | ```
465 |
466 | Output
467 | ```
468 | Processing template adding with version 0.1
469 | The variable x has the value: 2
470 | ```
471 |
472 | ### Oracle Objects
473 |
474 | tePLSQL templates can be stored inside PL/SQL program unit spec or bodies.
475 |
476 | In order to place a template into a program unit you have to create a non-compiled section in the latter with the aid of PL/SQL conditional compilation directives:
477 |
478 | #### Syntax
479 | ```
480 | $if false $then
481 | ... template ...
482 | $end
483 | ```
484 |
485 | The syntax is case-sensitive but space-insensitive. Line breaks are not allowed.
486 |
487 | #### Example
488 |
489 | ```plsql
490 | CREATE OR REPLACE PACKAGE test_tmpl
491 | AS
492 | $if false $then
493 | <%! x pls_integer := 1 + 1; %>
494 | The variable x has the value: <%= x %>
495 | $end
496 | END test_tmpl;
497 | ```
498 |
499 | Process the template:
500 |
501 | ```plsql
502 | SET SERVEROUTPUT on;
503 | BEGIN
504 | DBMS_OUTPUT.put_line (teplsql.process (p_object_name => 'test_tmpl'));
505 | END;
506 | ```
507 |
508 | Outout:
509 | ```
510 | The variable x has the value: 2
511 | ```
512 |
513 | #### Anonymous templates
514 | An anonymous template must be the only template in its host object. The template resides in a non-compiled section and occupies it entirely. An example of an anonymous template placed in the `test_tmpl` package specification:
515 |
516 | ```plsql
517 | CREATE OR REPLACE PACKAGE test_tmpl
518 | AS
519 | $if false $then
520 | <%! x pls_integer := 1 + 1; %>
521 | The variable x has the value: <%= x %>
522 | $end
523 | END test_tmpl;
524 | ```
525 |
526 | tePLSQL seeks anonymous templates in objects greedily, so the following template contains two anonymous templates that tePLSQL merge and execute together.
527 |
528 | ```plsql
529 | create or replace package test_tmpl2 as
530 | $if false $then
531 | <%! x pls_integer := 1 + 1;%>
532 | Value X: <%= x %>
533 | $end
534 |
535 | $if false $then
536 | <%! y pls_integer := 2 + 3; %>
537 | Value Y: <%= y %>
538 | $end
539 | end test_tmpl2;
540 | /
541 | ```
542 |
543 | tePLSQL interpret it as:
544 | ```plsql
545 | <%! x pls_integer := 1 + 1;%>
546 | Value X: <%= x %>
547 | <%! y pls_integer := 2 + 3; %>
548 | Value Y: <%= y %>
549 | ```
550 |
551 | Process the template:
552 | ```plsql
553 | SET SERVEROUTPUT on;
554 | BEGIN
555 | DBMS_OUTPUT.put_line (teplsql.process (p_object_name => 'test_tmpl2'));
556 | END;
557 | ```
558 |
559 | Output:
560 | ```
561 | Value X: 2Value Y: 5
562 | ```
563 |
564 | #### Named
565 | In order to store several templates in a single object correctly you must
566 | specify template characteristics, giving the name of the template.
567 |
568 | Defining the template name
569 |
570 | ```plsql
571 | CREATE OR REPLACE PACKAGE test_tmpl
572 | AS
573 |
574 | $if false $then
575 | <%@ template
576 | name=adding,
577 | version=0.1 %>
578 | <%! x pls_integer := 1 + 1; %>
579 | Processing template ${template_name} with version ${template_version}
580 | The variable x has the value: <%= x %>
581 | $end
582 |
583 | $if false $then
584 | <%@ template name=subtracting, version=0.1, revision=3 %>
585 | <%! y pls_integer := 1 - 1; %>
586 | Processing template ${template_name} with version ${template_version} and revision ${template_revision}
587 | The variable y has the value: <%= y %>
588 | $end
589 |
590 | END test_tmpl;
591 | ```
592 |
593 | Process the "subtracting" template:
594 |
595 | ```plsql
596 | SET SERVEROUTPUT on;
597 | BEGIN
598 | DBMS_OUTPUT.put_line (teplsql.process (p_template_name => 'subtracting', p_object_name => 'test_tmpl'));
599 | END;
600 | ```
601 |
602 | Output:
603 |
604 | Processing template subtracting with version 0.1 and revision 3
605 | The variable y has the value: 0
606 |
607 |
608 | ## Examples of tePLSQL templates
609 |
610 | ### Basic Example
611 |
612 | ```plsql
613 | DECLARE
614 | p_template VARCHAR2 (32000);
615 | p_vars teplsql.t_assoc_array;
616 | BEGIN
617 | p_template :=
618 | q'[<%/* Using variables */%>
619 | Hi ${FullName}!
620 |
621 | <%/* Using expressions */%>
622 | Today <%= TO_CHAR(SYSDATE, 'DD-MM-YYYY') %> is a great day!
623 |
624 | <% --Using external variable in the query loop
625 | for c1 in (select username, user_id from all_users where username = upper('${username}')) loop %>
626 | Username: <%= c1.username %>, ID:<%= c1.user_id %>.
627 | <% end loop; %>
628 |
629 | <%/* Escaping chars */%>
630 | This is the tePLSQL code block syntax <\\% ... %\\>
631 |
632 | <%/* Regards */%>
633 | Bye <%=UPPER('${username}')%>.]';
634 |
635 | --Key-value variables.
636 | p_vars ('FullName') := 'Oscar Salvador Magallanes';
637 | p_vars ('username') := 'test';
638 |
639 | p_template := teplsql.render (p_vars, p_template);
640 |
641 | DBMS_OUTPUT.put_line (p_template);
642 | END;
643 | ```
644 |
645 | Output:
646 | ```
647 | Hi Oscar Salvador Magallanes!
648 |
649 | Today 08-09-2015 is a great day!
650 |
651 | Username: SYS
652 |
653 | This is the tePLSQL code block syntax <% ... %>
654 |
655 | Bye SYS.
656 |
657 | PL/SQL procedure successfully completed.
658 | Elapsed: 00:00:00.02
659 | ```
660 |
661 | ### HTML Example
662 | ```plsql
663 | DECLARE
664 | p_template CLOB;
665 | p_vars teplsql.t_assoc_array;
666 | BEGIN
667 | p_template :=
668 | q'[
669 |
670 |
671 | ${title}
672 |
673 |
674 | Print Sequence numbers
675 |
676 | <%for i in ${initValue} .. ${lastValue} loop %>
677 | <%= i %>
678 | <% end loop;%>
679 | Print the Odd numbers of sequence
680 |
681 | <% /*You can insert PLSQL comments as always*/
682 | for i in ${initValue} .. ${lastValue}
683 | loop
684 | if mod(i,2) <> 0
685 | then %>
686 | <%= i %>
687 | <% end if;
688 | end loop; %>
689 |
690 | ]';
691 |
692 | --Key-value variables.
693 | p_vars ('title') := 'Number sequence';
694 | p_vars ('initValue') := 5;
695 | p_vars ('lastValue') := 20;
696 |
697 | p_template := teplsql.render (p_vars, p_template);
698 |
699 | DBMS_OUTPUT.put_line (p_template);
700 | END;
701 | ```
702 |
703 | Output:
704 | ```html
705 |
706 |
707 |
708 | Number sequence
709 |
710 |
711 | Print Sequence numbers
712 |
713 | 5
714 | 6
715 | 7
716 | 8
717 | 9
718 | 10
719 | 11
720 | 12
721 | 13
722 | 14
723 | 15
724 | 16
725 | 17
726 | 18
727 | 19
728 | 20
729 | Print the Odd numbers of sequence
730 |
731 | 5
732 | 7
733 | 9
734 | 11
735 | 13
736 | 15
737 | 17
738 | 19
739 |
740 |
741 | PL/SQL procedure successfully completed.
742 | Elapsed: 00:00:00.02
743 | ```
744 |
745 | ### Excel example
746 | Generating formatted Excel file. Save the result as .xml file and open it with MS Excel.
747 |
748 | ```plsql
749 | set timing on;
750 | set serveroutput on;
751 |
752 | DECLARE
753 | p_template CLOB;
754 | p_vars teplsql.t_assoc_array;
755 | BEGIN
756 | p_template :=
757 | q'[
758 |
759 |
762 |
763 | | <%=i%> |
764 | <%=CHR (i + 64)%> |
765 | <%=i%> |
766 | <%=i+10%> |
767 | <%=i+20%> |
768 |
769 | <% end loop; %>
770 | ...
771 | ]';
772 |
773 | p_template := teplsql.render (p_vars, p_template);
774 |
775 | DBMS_OUTPUT.put_line (p_template);
776 | END;
777 | ```
778 |
779 | Output:
780 |
781 | 
782 |
783 | #### Declaration and instructions
784 |
785 | ```plsql
786 | DECLARE
787 | p_template CLOB;
788 | p_vars teplsql.t_assoc_array;
789 | BEGIN
790 | p_template :=
791 | q'[<%! lang_name VARCHAR2(10) := 'PL/SQL';
792 | l_random_number pls_integer := ROUND(DBMS_RANDOM.VALUE (1, 9));
793 | %>
794 | The 'sequence' is used in scripting language: <%=lang_name %>.
795 | The result of the operation ${someInValue} * <%= l_random_number %> is <%= ${someInValue} * l_random_number %>
796 | ]';
797 |
798 | --Key-value variables.
799 | p_vars ('someInValue') := 5;
800 |
801 | p_template := teplsql.render (p_vars, p_template);
802 |
803 | DBMS_OUTPUT.put_line (p_template);
804 | END;
805 | ```
806 |
807 | Output:
808 |
809 | The 'sequence' is used in scripting language: PL/SQL.
810 | The result of the operation 5 * 7 is 35
811 |
812 |
813 | ## Debugging tePLSQL templates
814 | As you begin experimenting with tePLSQL templates, and as you adapt your first simple templates into more elaborate ones, keep these guidelines in mind when you encounter problems.
815 |
816 | ### Find where the template fails
817 | tePLSQL interprets the template and converts it into executable PL/SQL code. When error is occurred you will see the description in the `DBMS_OUTPUT`:
818 |
819 | Rendering this template:
820 | ```
821 | Testing Error.
822 | <%/* Raising error "divisor is equal to zero" */%>
823 | Raising an error <%= 10/0 %>.
824 | ```
825 |
826 | You will get this error:
827 | ```
828 | Testing Error.
829 | Raising an error ### tePLSQL Render Error ###
830 | ORA-01476: divisor is equal to zero ORA-06512: at line 2
831 | ORA-06512: at "USER.TEPLSQL", line 666
832 |
833 | ### Processed template ###
834 | DECLARE BEGIN tePLSQL.p(q'[Testing Error.
835 | ]'); /* Raising error "divisor is equal to zero" */ tePLSQL.p(q'[Raising an error ]');tePLSQL.p( 10/0 );tePLSQL.p(q'[. ]'); END;
836 | ```
837 |
838 | `### Processed template ###` is the template converted into executable PL/SQL.
839 |
840 | You can see `ORA-01476: divisor is equal to zero ORA-06512: at line 2` means that in the second line of the `### Processed template ###` code you have the error.
841 |
842 | The exception message will be append into the tePLSQL buffer. This helps you to find where the exception is occurred. tePLSQL trunc the buffer at maximum 500 characters to prevent the exception message is truncated in long templates.
843 |
844 | #### Syntax error
845 | Rendering this template:
846 | ```
847 | Testing syntax Error.
848 | <%/* Raising syntax error */%>
849 | Raising an error <%= 10/1; %>.
850 | ```
851 |
852 | You will get this error:
853 | ```
854 | ### tePLSQL Render Error ###
855 | ORA-06550: line 2, column 82:
856 | PLS-00103: Encountered the symbol ";" when expecting one of the following:
857 |
858 | ) , * & = - + < / > at in is mod remainder not rem =>
859 | <> or != or ~= >= <= <> and or like like2
860 | like4 likec as between from using || member submultiset
861 | The symbol ";" was ignored. ORA-06512: at "DBAX.TEPLSQL", line 666
862 |
863 | ### Processed template ###
864 | DECLARE BEGIN tePLSQL.p(q'[Testing syntax Error.
865 | ]'); /* Raising syntax error */ tePLSQL.p(q'[Raising an error ]');tePLSQL.p( 10/1; );tePLSQL.p(q'[. ]'); END;
866 | ```
867 |
868 | You will see at line 2 column 82, this instruction `tePLSQL.p( 10/1; )` that is not valid in PL/SQL.
869 |
870 |
871 | ## tePLSQL API reference
872 |
873 | ### RENDER
874 |
875 | Renders the template received as parameter.
876 |
877 | #### Syntax
878 |
879 | ```plsql
880 | FUNCTION render (p_vars IN t_assoc_array DEFAULT null_assoc_array,p_template IN CLOB)
881 | RETURN CLOB;
882 | ```
883 |
884 | #### Parameters
885 |
886 | |Parameter | Description
887 | |----------|------------
888 | |p_vars | The template's arguments.
889 | |p_template | The template's body.
890 | | return CLOB | The processed template.
891 |
892 | ### PROCESS
893 |
894 | Rceives the name of the object, usually a package, which contains an embedded template. The template is extracted and is rendered with `render` function
895 |
896 | #### Syntax
897 |
898 | ```plsql
899 | FUNCTION process (p_vars IN t_assoc_array DEFAULT null_assoc_array
900 | , p_template_name IN VARCHAR2 DEFAULT NULL
901 | , p_object_name IN VARCHAR2 DEFAULT 'TE_TEMPLATES'
902 | , p_object_type IN VARCHAR2 DEFAULT 'PACKAGE'
903 | , p_schema IN VARCHAR2 DEFAULT NULL )
904 | ```
905 |
906 | #### Parameters
907 |
908 | |Parameter | Description
909 | |----------|------------
910 | |p_vars | The template's arguments.
911 | |p_template_name | The name of the template.
912 | |p_object_name | The name of the object (usually the name of the package).
913 | |p_object_type | The type of the object (PACKAGE, PROCEDURE, FUNCTION...).
914 | |p_schema | The object's schema name.
915 | | return CLOB | The processed template.
916 |
917 | ### PRINT
918 |
919 | Prints received data into the buffer
920 |
921 | #### Syntax
922 |
923 | ```plsql
924 | PROCEDURE PRINT (p_data IN CLOB);
925 |
926 | PROCEDURE p (p_data IN CLOB);
927 |
928 | PROCEDURE PRINT (p_data IN VARCHAR2);
929 |
930 | PROCEDURE p (p_data IN VARCHAR2);
931 |
932 | PROCEDURE PRINT (p_data IN NUMBER);
933 |
934 | PROCEDURE p (p_data IN NUMBER);
935 | ```
936 |
937 | #### Parameters
938 |
939 | |Parameter | Description
940 | |----------|------------
941 | |p_data | The data to print into buffer
942 |
943 |
944 | ### OUTPUT_CLOB
945 |
946 | Output CLOB data to the DBMS_OUTPUT.PUT_LINE
947 |
948 | #### Syntax
949 |
950 | ```plsql
951 | PROCEDURE output_clob(p_clob in CLOB);
952 | ```
953 |
954 | #### Parameters
955 |
956 | |Parameter | Description
957 | |----------|------------
958 | |p_clob | The CLOB to print to the DBMS_OUTPUT
959 |
960 |
961 | ## Advance Topics
962 |
963 |
964 | ### Indention
965 | There are two methods to control indention of the rendered code.
966 |
967 | 1. Indent the whole sub-template
968 | 1. Set/Goto Tab stops
969 |
970 | Method 1 is done via 5th parameter of an `<% include() %>` directive.
971 |
972 | Method 2 uses public calls `teplsql.set_tab( *n* )` and `teplsql.goto_tab( *n* )`.
973 |
974 |
975 |
976 | ### tePLSQL Engine Options
977 | The way that the tePLSQL engine behaves can be modified by adding the options as additional [tePLSQL arguments](#arguments).
978 | The settings are reset to DEFAULT values, prior to parsing Template Variables, for each run.
979 |
980 | The argument names are defined as constants within the tePLSQL package specification.
981 |
982 | |Constant |Valid Values |Default Value |Description
983 | |---------|-------------|--------------|-------------
984 | |g_set_max_includes | integers >0 | 50 | [sets the maximum number of `include`](#maxInclude)
985 | |g_set_globbing_mode | constants `g_globbing_mode_*` | off | sets the search mode for [Template Globbing](#templateGlobbing).
986 | |g_set_globbing_separator | any valid string | `chr(10)` | The string used between globbed templates. More information is [here](#templateSeparator)
987 | |g_set_render_mode | constants `g_render_mode_*` | normal | Defines the type of rendering to be done. More information is [here](#RenderModes)
988 | |g_set_indention_string | any valid string | `' '` (4 spaces) | Sets the string used for indentions.
989 |
990 |
991 |
992 | #### g_set_max_includes
993 | In order to prevent potential infinite loops, tePLSQL will stop after processsing a set number of `include` commands.
994 |
995 | The default value is set to `50`. This value can be addjust with the `g_set_max_includes` argument.
996 |
997 | ```sql
998 | DECLARE
999 | l_vars teplsql.t_assoc_array := teplsql.null_assoc_array;
1000 | BEGIN
1001 | -- normal template variables
1002 | l_vars('schema') := USER;
1003 | l_vars('table_name') := 'MY_TABLE';
1004 |
1005 | -- setting maximum number includes to 100
1006 | l_vars(teplsql.g_set_max_includes) := 100;
1007 |
1008 | l_result := teplsql.process(l_vars,'My TAPI Template');
1009 | END;
1010 | /
1011 | ```
1012 |
1013 |
1014 | ### Template Globbing
1015 | Template Globbing allows a developer to include multiple templates with a single `include` call. By default, this feature is `off`.
1016 |
1017 | When used, the templates that match the search string are returned in case-sensitive order separated by a predetermined string.
1018 |
1019 | Example template for generating the Package Specification
1020 | ```sql
1021 | create or replace
1022 | package <%@ include( com.mycompany.templates.tapi.main_pkg.name ) %>
1023 | as
1024 | <%@ include( com.mycompany.templates.tapi.main_pkg.documentation ) %>
1025 |
1026 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.*.specification ) %>
1027 | end <%@ include( com.mycompany.templates.tapi.main_pkg.name ) %>;
1028 | <%= '/' %>
1029 | ```
1030 |
1031 | Template Globbing will expand as if the template was defined like this.
1032 | ```sql
1033 | create or replace
1034 | package <%@ include( com.mycompany.templates.tapi.main_pkg.name ) %>
1035 | as
1036 | <%@ include( com.mycompany.templates.tapi.main_pkg.documentation ) %>
1037 |
1038 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.01_ins.specification ) %>
1039 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.02_upd.specification ) %>
1040 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.03_del.specification ) %>
1041 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.04_sel.specification ) %>
1042 | <%@ include( com.mycompany.templates.tapi.main_pkg.functions.05_hash.specification ) %>
1043 | end <%@ include( com.mycompany.templates.tapi.main_pkg.name ) %>;
1044 | <%= '/' %>
1045 | ```
1046 |
1047 | If other similarly named templates are created, they will be automatically included the next time the Package Specification template is used.
1048 |
1049 | #### Engine Options
1050 | ##### Enabling Template Globbing
1051 | The constant `teplsql.g_set_globbing_mode` defines the name of the Template Variable the determines the Template Globbing mode.
1052 |
1053 | | constant | description |
1054 | |----------|-------------|
1055 | | `teplsql.g_globbing_mode_off` | Template Globbing mode is disabled (default) |
1056 | | `teplsql.g_globbing_mode_on` | Template Globbing mode is on. Search is case-sensitive. The star ( `*` ) is the only supported wildcard. Wildcard expansion will not expand across dots( `.` ). |
1057 | | `teplsql.g_globbing_mode_regexp` | Template Globbing mode is on. The template name within in the `include` clause is used as-is for a case-sensitive Regular Expression search. |
1058 | | `teplsql.g_globbing_mode_like` | Template Globbing mode is on. The template name within the `include` clause is used as-is for a case-insensitve LIKE search. |
1059 |
1060 | Before each call to `process` or `render`, you need to set the required Template Variable.
1061 | ```sql
1062 | -- Turn on Template Globbing
1063 | p_vars( teplsql.g_set_globbing_mode ) := teplsql.g_globbing_mode_on;
1064 | -- Default value for templates that use globbing can be too small
1065 | p_vars( teplsql.g_set_maximum_includes ) := 150;
1066 | ```
1067 |
1068 |
1069 | ##### Separation String
1070 | The concatination string used between included templates can be set with the Template Variable name defined by `teplsql.g_set_globing_separator`.
1071 |
1072 | By default, this string is `chr(10)`.
1073 |
1074 | Example
1075 | ```sql
1076 | -- all globbed templates are separated by a single 80 column block comment line.
1077 | p_vars( teplsql.g_set_globbing_separator ) := chr(10) || '/' || lpad('*',78,'*') || '/' || chr(10);
1078 | ```
1079 |
1080 |
1081 | ### Render Modes
1082 | This defines the various ways to render the extracted templates.
1083 |
1084 | | Render Mode | Description
1085 | |-------------|------------
1086 | | g_render_mode_normal | (default) Renders the template normally.
1087 | | g_render_mode_fetch_only | Retrieves the template and processes only the `<%@ template() %>` directives
1088 | | g_render_mode_hierarch_tags_only | Retrieves the template, processes only the `<%@ template() %>` directives and hierarchal tags `${this}`, `${super}`, `${super.super}`, etc.
1089 | | TBD | The template is a Build XML file. see BuildTemlates
1090 | | TBD | The template is a Build Template. see BuildTemplates
1091 |
1092 |
1093 |
1094 | ### Build Templates/XML
1095 | Similar to `jinja` for HTML documents, you can build a set of DB Objects by "extending" multiple Helper Templates.
1096 |
1097 | This can be done via Build Template or a Build XML file.
1098 |
1099 | Build XML is just the XML version of a Build Template.
1100 |
1101 | NOTE: the resulting templates (created from a Build) are stored in `TE_TEMPLATES` with a name format of `${base_name}.${object_type}.${object_name}.${block}`. As such, when you need to reference another object, you need to use `${super.super}` instead of just `${super}`.
1102 |
1103 |
1104 | #### Extending a Helper Template
1105 | To include/extend a Helper Template, use `<%@ extends( helper-type, object-name, base_name="xxxx" %>` and close with an `<%@ enextends %>`.
1106 |
1107 | To modify the code in a Helper Template, place the new template code between `<%@ block( *block-name* ) %>` and `<%@ enblock %>` with `*block_name*` representing the section of code you want to replace. The `<%@ block %> ... <%@ endblock %>` code should be within the `<%@ extends %> ... <%@ enextends %>` tags and before any sub-`<%@ extends %>`.
1108 |
1109 | You can "extend" other helper templates within a helper template. For exmple, you can add a function to a function of a package.
1110 |
1111 | example:
1112 | ```sql
1113 | <%@ template( template_name=HelloWorld ) %>
1114 | <%@ extends object_type="package" object_name="my_pkg" %>
1115 | <%@ extends object_type="function" object_name="outer_f" %>
1116 | <%@ block block_name="spec" %>procedure <%@ include( ${this}.name ) %><%@ enblock %>
1117 | <%@ block block_name="bdy" %><%@ include( ${this}.function.inner_f.name ) %>;
1118 | <%@ enblock %>
1119 | <%@ extends object_type="function" object_name="inner_f" %>
1120 | <%@ block block_name="spec" %>procedure <%@ include( ${this}.name ) %><%@ enblock %>
1121 | <%@ block block_name="bdy" %>dbms_output.put_line( 'Hello World' );<%@ enblock %>
1122 | <%@ enextends %>
1123 | <%@ enextends %>
1124 | <%@ enextends %>
1125 | ```
1126 |
1127 | results in
1128 | ```plsql
1129 | CREATE OR REPLACE
1130 | PACKAGE TEPLSQL$SYS.my_pkg
1131 | AS
1132 | /**
1133 | Place Description of Package here
1134 | @headcom
1135 | */
1136 |
1137 |
1138 |
1139 |
1140 |
1141 | /**
1142 | Function outer_f*/
1143 | procedure outer_f;
1144 | END;
1145 | /
1146 | CREATE OR REPLACE
1147 | PACKAGE BODY TEPLSQL$SYS.my_pkg
1148 | AS
1149 | procedure outer_f
1150 | AS
1151 |
1152 |
1153 | -- set variables here
1154 | procedure inner_f
1155 | AS
1156 |
1157 |
1158 | -- set variables here
1159 |
1160 | BEGIN
1161 | dbms_output.put_line( 'Hello World' );
1162 | END inner_f;
1163 |
1164 | BEGIN
1165 | inner_f;
1166 |
1167 | END outer_f;
1168 |
1169 | END;
1170 | /
1171 | ```
1172 |
1173 | See Also:
1174 | | file | Description
1175 | |------|-------------
1176 | `demo/BUILD_HELLO_WORLD.sql` | A slightly more comperhensive "Hello World" example.
1177 | `test/build_tests.pks/pkb` | Tests all options of each default Helper Templates via separate Build Template
1178 |
1179 |
1180 | #### Default Helper Templates
1181 | Helper Templates stored in the `TE_TEMPLATES` table have the format of `${base_name}.${object_type}.${block}`. The default value for `${base_name}` is `teplsql.helper.default`.
1182 |
1183 | The included default Helper Templates are:
1184 | | `${object_type}` | Description
1185 | |------------------|---------------
1186 | | build | Includes cursors, etc. in its definition. You should always start with one of these.
1187 | | package | Use this Helper Template to create a package.
1188 | | function | Use this Helper Template to create a function/procedure. Usually included in a `package` or `function`
1189 | | exception | Use this Helper Template to create an `exception`. Use this in a `package` or `function`.
1190 | | exceptions-block | Used to generate the `WHEN` clause(s) of the `EXCEPTION` block
1191 | | plsql-type | Use this Helper Template to create a series of PL/SQL Types. Used in a `package` or `function`.
1192 | | variable | Use this Helper Template to a variable/constant that is used in a `package` or `function`.
1193 | | selecd | Used tis Helper Template to build a View, Cursor, or CTE.
1194 |
1195 |
1196 |
1197 |
1198 | ## Contributing
1199 |
1200 | If you have ideas, get in touch directly.
1201 |
1202 | Please inser at the bottom of your commit message the following line using your name and e-mail address .
1203 |
1204 | Signed-off-by: Your Name
1205 |
1206 | This can be automatically added to pull requests by committing with:
1207 |
1208 | git commit --signoff
1209 |
1210 |
1211 | ## License
1212 | Copyright 2015 Oscar Salvador Magallanes
1213 |
1214 | tePLSQL is under MIT license.
1215 |
--------------------------------------------------------------------------------