SlideShare a Scribd company logo
Why You Should Use TAPIs
Jeffrey Kemp
AUSOUG Connect Perth, November 2016
All artifacts including code are presented for illustration
purposes only. Use at your own risk. Test thoroughly in
a non-critical environment before use.
Main Menu
1. Why a data API?
2. Why choose PL/SQL?
3. How to structure your API?
4. Data API for Apex
5. Table APIs (TAPIs)
6. Open Source TAPI project
Background
“Building Maintainable Apex Apps”, 2014
https://jeffkemponoracle.com/2014/11/14/sample-tapi-apex-application/
https://jeffkemponoracle.com/2016/02/11/tapi-generator-mkii/
https://jeffkemponoracle.com/2016/02/12/apex-api-call-a-package-for-all-your-dml/
https://jeffkemponoracle.com/2016/02/16/apex-api-for-tabular-forms/
https://jeffkemponoracle.com/2016/06/30/interactive-grid-apex-5-1-ea/
Why a data API?
Why a data API?
“I’m building a simple Apex app.
I’ll just use the built-in processes
to handle all the DML.”
Your requirements get more
complex.
– More single-row and/or tabular
forms
– More pages, more load routines,
more validations, more
insert/update processes
– Complex conditions
– Edge cases, special cases, weird
cases
Why You Should Use TAPIs
Another system must create the same data –
outside of Apex
– Re-use validations and processing
– Rewrite the validations
– Re-engineer all processing (insert/update) logic
– Same edge cases
– Different edge cases
Define all validations and processes in one place
– Integrated error messages
– Works with Apex single-row and tabular forms
Simple wrapper to allow code re-use
– Same validations and processes included
– Reduced risk of regression
– Reduced risk of missing bits
• They get exactly the same logical outcome as we get
• No hidden surprises from Apex features
TAPIs
Business Rule Validations
Default Values
Reusability
Encapsulation
Maintainability
Maintainability is in the eye of the
beholder maintainer.
Techniques
• DRY
• Consistency
• Naming
• Single-purpose
• Assertions
Why use PL/SQL for your API?
Why use PL/SQL for your API?
• Data is forever
• UIs come and go
• Business logic
– tighter coupling with Data than UI
Business Logic
• your schema
• your data constraints
• your validation rules
• your insert/update/delete logic
• keep business logic close to your data
• on Oracle, PL/SQL is the best
Performance
#ThickDB
#ThickDB
How should you structure your API?
How should you structure your API?
Use packages
Focus each Package
For example:
– “Employees” API
– “Departments” API
– “Workflow” API
– Security (user roles and privileges) API
– Apex Utilities
Package names as context
GENERIC_PKG.get_event (event_id => nv('P1_EVENT_ID'));
GENERIC_PKG.get_member (member_id => nv('P1_MEMBER_ID'));
EVENT_PKG.get (event_id => nv('P1_EVENT_ID'));
MEMBER_PKG.get (member_id => nv('P1_MEMBER_ID'));
Apex processes, simplified
MVC Architecture
entity$APEX
table$TAPI
Process: load
load
1. Get PK value
2. Call TAPI to query record
3. Set session state for each column
Validation
validate
1. Get values from session state into record
2. Pass record to TAPI
3. Call APEX_ERROR for each validation error
process page request
process
1. Get v('REQUEST')
2. Get values from session state into record
3. Pass record to TAPI
Process a page requestprocedure process is
rv EVENTS$TAPI.rvtype;
r EVENTS$TAPI.rowtype;
begin
UTIL.check_authorization(SECURITY.Operator);
case
when APEX_APPLICATION.g_request = 'CREATE'
then
rv := apex_get;
r := EVENTS$TAPI.ins (rv => rv);
apex_set (r => r);
UTIL.success('Event created.');
when APEX_APPLICATION.g_request like 'SAVE%'
then
rv := apex_get;
r := EVENTS$TAPI.upd (rv => rv);
apex_set (r => r);
UTIL.success('Event updated.');
when APEX_APPLICATION.g_request = 'DELETE'
then
rv := apex_get_pk;
EVENTS$TAPI.del (rv => rv);
UTIL.clear_page_cache;
UTIL.success('Event deleted.');
else
null;
end case;
end process;
get_rowfunction apex_get return VOLUNTEERS$TAPI.rvtype is
rv VOLUNTEERS$TAPI.rvtype;
begin
rv.vol_id := nv('P9_VOL_ID');
rv.given_name := v('P9_GIVEN_NAME');
rv.surname := v('P9_SURNAME');
rv.date_of_birth := v('P9_DATE_OF_BIRTH');
rv.address_line := v('P9_ADDRESS_LINE');
rv.suburb := v('P9_SUBURB');
rv.postcode := v('P9_POSTCODE');
rv.state := v('P9_STATE');
rv.home_phone := v('P9_HOME_PHONE');
rv.mobile_phone := v('P9_MOBILE_PHONE');
rv.email_address := v('P9_EMAIL_ADDRESS');
rv.version_id := nv('P9_VERSION_ID');
return rv;
end apex_get;
set row
procedure apex_set (r in VOLUNTEERS$TAPI.rowtype) is
begin
sv('P9_VOL_ID', r.vol_id);
sv('P9_GIVEN_NAME', r.given_name);
sv('P9_SURNAME', r.surname);
sd('P9_DATE_OF_BIRTH', r.date_of_birth);
sv('P9_ADDRESS_LINE', r.address_line);
sv('P9_STATE', r.state);
sv('P9_SUBURB', r.suburb);
sv('P9_POSTCODE', r.postcode);
sv('P9_HOME_PHONE', r.home_phone);
sv('P9_MOBILE_PHONE', r.mobile_phone);
sv('P9_EMAIL_ADDRESS', r.email_address);
sv('P9_VERSION_ID', r.version_id);
end apex_set;
PL/SQL in Apex
PKG.proc;
SQL in Apex
select t.col_a
,t.col_b
,t.col_c
from my_table t;
• Move joins, select expressions, etc. to a
view
– except Apex-specific stuff like generated APEX_ITEMs
Pros
• Fast development
• Smaller apex app
• Dependency analysis
• Refactoring
• Modularity
• Code re-use
• Customisation
• Version control
Cons
• Misspelled/missing item names
– Mitigation: isolate all apex code in one set of
packages
– Enforce naming conventions – e.g. P1_COLUMN_NAME
• Apex Advisor doesn’t check database package
code
Apex API Coding Standards
• All v() calls at start of proc, once per item
• All sv() calls at end of proc
• Constants instead of 'P1_COL'
• Dynamic Actions calling PL/SQL – use parameters
• Replace PL/SQL with Javascript (where possible)
Error Handling
• Validate - only record-level validation
• Cross-record validation – db constraints + XAPI
• Capture DUP_KEY_ON_VALUE and ORA-02292 for unique and
referential constraints
• APEX_ERROR.add_error
TAPIs
• Encapsulate all DML for a table
• Row-level validation
• Detect lost updates
• Generated
TAPI contents
• Record types
– rowtype, arraytype, validation record type
• Functions/Procedures
– ins / upd / del / merge / get
– bulk_ins / bulk_upd / bulk_merge
• Constants for enumerations
Why not a simple rowtype?
procedure ins
(emp_name in varchar2
,dob in date
,salary in number
) is
begin
if is_invalid_date (dob) then
raise_error('Date of birth bad');
elsif is_invalid_number (salary) then
raise_error('Salary bad');
end if;
insert into emp (emp_name, dob, salary) values (emp_name, dob, salary);
end ins;
ins (emp_name => :P1_EMP_NAME, dob => :P1_DOB, salary => :P1_SALARY);
ORA-01858: a non-numeric character was found where a numeric was expected
It’s too late to validate
data types here!
Validation record type
type rv is record
( emp_name varchar2(4000)
, dob varchar2(4000)
, salary varchar2(4000));
procedure ins (rv in rvtype) is
begin
if is_invalid_date (dob) then
raise_error('Date of birth bad');
elsif is_invalid_number (salary) then
raise_error('Salary bad');
end if;
insert into emp (emp_name, dob, salary) values (emp_name, dob, salary);
end ins;
ins (emp_name => :P1_EMP_NAME, dob => :P1_DOB, salary => :P1_SALARY);
I’m sorry Dave, I can’t do that - Date of birth bad
Example Table
create table venues
( venue_id integer default on null venue_id_seq.nextval
, name varchar2(200 char)
, map_position varchar2(200 char)
, created_dt date default on null sysdate
, created_by varchar2(100 char)
default on null sys_context('APEX$SESSION','APP_USER')
, last_updated_dt date default on null sysdate
, last_updated_by varchar2(100 char)
default on null sys_context('APEX$SESSION','APP_USER')
, version_id integer default on null 1
);
TAPI example
package VENUES$TAPI as
cursor cur is select x.* from venues;
subtype rowtype is cur%rowtype;
type arraytype is table of rowtype
index by binary_integer;
type rvtype is record
(venue_id venues.venue_id%type
,name varchar2(4000)
,map_position varchar2(4000)
,version_id venues.version_id%type
);
type rvarraytype is table of rvtype
index by binary_integer;
-- validate the row
function val (rv IN rvtype) return varchar2;
-- insert a row
function ins (rv IN rvtype) return rowtype;
-- update a row
function upd (rv IN rvtype) return rowtype;
-- delete a row
procedure del (rv IN rvtype);
end VENUES$TAPI;
TAPI ins
function ins (rv in rvtype)
return rowtype is
r rowtype;
error_msg varchar2(32767);
begin
error_msg := val (rv => rv);
if error_msg is not null then
UTIL.raise_error(error_msg);
end if;
insert into venues
(name
,map_position)
values(rv.name
,rv.map_position)
returning
venue_id
,...
into r;
return r;
exception
when dup_val_on_index then
UTIL.raise_dup_val_on_index;
end ins;
TAPI val
function val (rv in rvtype) return varchar2 is
begin
UTIL.val_not_null (val => rv.host_id, column_name => HOST_ID);
UTIL.val_not_null (val => rv.event_type, column_name => EVENT_TYPE);
UTIL.val_not_null (val => rv.title, column_name => TITLE);
UTIL.val_not_null (val => rv.start_dt, column_name => START_DT);
UTIL.val_max_len (val => rv.event_type, len => 100, column_name => EVENT_TYPE);
UTIL.val_max_len (val => rv.title, len => 100, column_name => TITLE);
UTIL.val_max_len (val => rv.description, len => 4000, column_name => DESCRIPTION);
UTIL.val_datetime (val => rv.start_dt, column_name => START_DT);
UTIL.val_datetime (val => rv.end_dt, column_name => END_DT);
UTIL.val_domain
(val => rv.repeat
,valid_values => t_str_array(DAILY, WEEKLY, MONTHLY, ANNUALLY)
,column_name => REPEAT);
UTIL.val_integer (val => rv.repeat_interval, range_low => 1, column_name => REPEAT_INTERVAL);
UTIL.val_date (val => rv.repeat_until, column_name => REPEAT_UNTIL);
UTIL.val_ind (val => rv.repeat_ind, column_name => REPEAT_IND);
return UTIL.first_error;
end val;
TAPI upd
function upd (rv in rvtype) return rowtype is
r rowtype;
error_msg varchar2(32767);
begin
error_msg := val (rv => rv);
if error_msg is not null then
UTIL.raise_error(error_msg);
end if;
update venues x
set x.name = rv.name
,x.map_position = rv.map_position
where x.venue_id = rv.venue_id
and x.version_id = rv.version_id
returning
venue_id
,...
into r;
if sql%notfound then
raise UTIL.lost_update;
end if;
return r;
exception
when dup_val_on_index then
UTIL.raise_dup_val_on_index;
when UTIL.ref_constraint_violation then
UTIL.raise_ref_con_violation;
when UTIL.lost_update then
lost_upd (rv => rv);
end upd;
Lost update handler
procedure lost_upd (rv in rvtype) is
db_last_updated_by venues.last_updated_by%type;
db_last_updated_dt venues.last_updated_dt%type;
begin
select x.last_updated_by
,x.last_updated_dt
into db_last_updated_by
,db_last_updated_dt
from venues x
where x.venue_id = rv.venue_id;
UTIL.raise_lost_update
(updated_by => db_last_updated_by
,updated_dt => db_last_updated_dt);
exception
when no_data_found then
UTIL.raise_error('LOST_UPDATE_DEL');
end lost_upd;
“This record was changed by
JOE BLOGGS at 4:31pm.
Please refresh the page to see
changes.”
“This record was deleted by
another user.”
TAPI bulk_ins
function bulk_ins (arr in rvarraytype) return number is
begin
bulk_val(arr);
forall i in indices of arr
insert into venues
(name
,map_position)
values (arr(i).name
,arr(i).map_position);
return sql%rowcount;
exception
when dup_val_on_index then
UTIL.raise_dup_val_on_index;
end bulk_ins;
What about queries?
Tuning a complex, general-purpose query
is more difficult than
tuning a complex, single-purpose query.
Generating Code
• Only PL/SQL
• Templates compiled in the schema
• Simple syntax
• Sub-templates (“includes”) for extensibility
OraOpenSource TAPI
• Runs on NodeJS
• Uses Handlebars for template processing
• https://github.com/OraOpenSource/oos-tapi/
• Early stages, needs contributors
OOS-TAPI Example
create or replace package body {{toLowerCase table_name}} as
gc_scope_prefix constant varchar2(31) := lower($$plsql_unit) || '.';
procedure ins_rec(
{{#each columns}}
p_{{toLowerCase column_name}} in {{toLowerCase data_type}}
{{#unless @last}},{{lineBreak}}{{/unless}}
{{~/each}}
);
end {{toLowerCase table_name}};
oddgen
• SQL*Developer plugin
• Code generator, including TAPIs
• Support now added in jk64 Apex TAPI generator
https://www.oddgen.org
Why You Should Use TAPIs
Takeaways
Be Consistent
Consider Your Successors
Thank you
jeffkemponoracle.com
Ad

More Related Content

What's hot (20)

Java cheat sheet
Java cheat sheetJava cheat sheet
Java cheat sheet
Piyush Mittal
 
Oracle Forms: Messages
Oracle Forms: MessagesOracle Forms: Messages
Oracle Forms: Messages
Sekhar Byna
 
Web 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style SheetsWeb 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style Sheets
Mohammad Imam Hossain
 
python Function
python Function python Function
python Function
Ronak Rathi
 
Oracle APEX Cheat Sheet
Oracle APEX Cheat SheetOracle APEX Cheat Sheet
Oracle APEX Cheat Sheet
Dimitri Gielis
 
Reading the .explain() Output
Reading the .explain() OutputReading the .explain() Output
Reading the .explain() Output
MongoDB
 
Find Anything In Your APEX App - Fuzzy Search with Oracle Text
Find Anything In Your APEX App - Fuzzy Search with Oracle TextFind Anything In Your APEX App - Fuzzy Search with Oracle Text
Find Anything In Your APEX App - Fuzzy Search with Oracle Text
Carsten Czarski
 
Php.ppt
Php.pptPhp.ppt
Php.ppt
Nidhi mishra
 
Packages - PL/SQL
Packages - PL/SQLPackages - PL/SQL
Packages - PL/SQL
Esmita Gupta
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
Soluto
 
jQuery
jQueryjQuery
jQuery
Jay Poojara
 
Operators In Java Part - 8
Operators In Java Part - 8Operators In Java Part - 8
Operators In Java Part - 8
MuhammadAtif231
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
HalaiHansaika
 
Oracle SQL Advanced
Oracle SQL AdvancedOracle SQL Advanced
Oracle SQL Advanced
Dhananjay Goel
 
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Edureka!
 
Django Models
Django ModelsDjango Models
Django Models
Mindfire Solutions
 
Clean code slide
Clean code slideClean code slide
Clean code slide
Anh Huan Miu
 
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Karen Cannell
 
User defined Function in SQL
User defined Function in SQLUser defined Function in SQL
User defined Function in SQL
baabtra.com - No. 1 supplier of quality freshers
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An Introduction
Manvendra Singh
 
Oracle Forms: Messages
Oracle Forms: MessagesOracle Forms: Messages
Oracle Forms: Messages
Sekhar Byna
 
Web 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style SheetsWeb 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style Sheets
Mohammad Imam Hossain
 
python Function
python Function python Function
python Function
Ronak Rathi
 
Oracle APEX Cheat Sheet
Oracle APEX Cheat SheetOracle APEX Cheat Sheet
Oracle APEX Cheat Sheet
Dimitri Gielis
 
Reading the .explain() Output
Reading the .explain() OutputReading the .explain() Output
Reading the .explain() Output
MongoDB
 
Find Anything In Your APEX App - Fuzzy Search with Oracle Text
Find Anything In Your APEX App - Fuzzy Search with Oracle TextFind Anything In Your APEX App - Fuzzy Search with Oracle Text
Find Anything In Your APEX App - Fuzzy Search with Oracle Text
Carsten Czarski
 
React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
Soluto
 
Operators In Java Part - 8
Operators In Java Part - 8Operators In Java Part - 8
Operators In Java Part - 8
MuhammadAtif231
 
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Edureka!
 
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Going to the Grid: Tabular Form Edition (Oracle APEX Editable Interactive Grids)
Karen Cannell
 
JavaScript - An Introduction
JavaScript - An IntroductionJavaScript - An Introduction
JavaScript - An Introduction
Manvendra Singh
 

Viewers also liked (13)

Building Maintainable Applications in Apex
Building Maintainable Applications in ApexBuilding Maintainable Applications in Apex
Building Maintainable Applications in Apex
Jeffrey Kemp
 
Why You Should Use Oracle SQL Developer
Why You Should Use Oracle SQL DeveloperWhy You Should Use Oracle SQL Developer
Why You Should Use Oracle SQL Developer
Jeffrey Kemp
 
Apex and Virtual Private Database
Apex and Virtual Private DatabaseApex and Virtual Private Database
Apex and Virtual Private Database
Jeffrey Kemp
 
Automate Amazon S3 Storage with Alexandria
Automate Amazon S3 Storage with AlexandriaAutomate Amazon S3 Storage with Alexandria
Automate Amazon S3 Storage with Alexandria
Jeffrey Kemp
 
11g Function Result Cache
11g Function Result Cache11g Function Result Cache
11g Function Result Cache
Jeffrey Kemp
 
Aws konferenz vortrag gk
Aws konferenz vortrag gkAws konferenz vortrag gk
Aws konferenz vortrag gk
execupery
 
Učinkovitejše iskanje v Google
Učinkovitejše iskanje v GoogleUčinkovitejše iskanje v Google
Učinkovitejše iskanje v Google
Tomaž Bešter
 
Migrate BI to APEX 5: Are We There Yet?
Migrate BI to APEX 5: Are We There Yet?Migrate BI to APEX 5: Are We There Yet?
Migrate BI to APEX 5: Are We There Yet?
Karen Cannell
 
Open Canary - novahackers
Open Canary - novahackersOpen Canary - novahackers
Open Canary - novahackers
Chris Gates
 
Single page App
Single page AppSingle page App
Single page App
Gaurav Gawande
 
Presantecion 1
Presantecion 1Presantecion 1
Presantecion 1
huvabayona
 
Nature Walk
Nature Walk Nature Walk
Nature Walk
peterpanpeyton
 
Taking Human Error out of K12 Attendance Equation
Taking Human Error out of K12 Attendance EquationTaking Human Error out of K12 Attendance Equation
Taking Human Error out of K12 Attendance Equation
ScholarChip ☁ Tools for Smarter Schools
 
Building Maintainable Applications in Apex
Building Maintainable Applications in ApexBuilding Maintainable Applications in Apex
Building Maintainable Applications in Apex
Jeffrey Kemp
 
Why You Should Use Oracle SQL Developer
Why You Should Use Oracle SQL DeveloperWhy You Should Use Oracle SQL Developer
Why You Should Use Oracle SQL Developer
Jeffrey Kemp
 
Apex and Virtual Private Database
Apex and Virtual Private DatabaseApex and Virtual Private Database
Apex and Virtual Private Database
Jeffrey Kemp
 
Automate Amazon S3 Storage with Alexandria
Automate Amazon S3 Storage with AlexandriaAutomate Amazon S3 Storage with Alexandria
Automate Amazon S3 Storage with Alexandria
Jeffrey Kemp
 
11g Function Result Cache
11g Function Result Cache11g Function Result Cache
11g Function Result Cache
Jeffrey Kemp
 
Aws konferenz vortrag gk
Aws konferenz vortrag gkAws konferenz vortrag gk
Aws konferenz vortrag gk
execupery
 
Učinkovitejše iskanje v Google
Učinkovitejše iskanje v GoogleUčinkovitejše iskanje v Google
Učinkovitejše iskanje v Google
Tomaž Bešter
 
Migrate BI to APEX 5: Are We There Yet?
Migrate BI to APEX 5: Are We There Yet?Migrate BI to APEX 5: Are We There Yet?
Migrate BI to APEX 5: Are We There Yet?
Karen Cannell
 
Open Canary - novahackers
Open Canary - novahackersOpen Canary - novahackers
Open Canary - novahackers
Chris Gates
 
Presantecion 1
Presantecion 1Presantecion 1
Presantecion 1
huvabayona
 
Ad

Similar to Why You Should Use TAPIs (20)

Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa
 
Mock Servers - Fake All the Things!
Mock Servers - Fake All the Things!Mock Servers - Fake All the Things!
Mock Servers - Fake All the Things!
Atlassian
 
PHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & PinbaPHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & Pinba
Patrick Allaert
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
vvaswani
 
Passenger 6 generic language support presentation
Passenger 6 generic language support presentationPassenger 6 generic language support presentation
Passenger 6 generic language support presentation
Hongli Lai
 
api-platform: the ultimate API platform
api-platform: the ultimate API platformapi-platform: the ultimate API platform
api-platform: the ultimate API platform
Stefan Adolf
 
Rack
RackRack
Rack
shen liu
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
High-level Programming Languages: Apache Pig and Pig Latin
High-level Programming Languages: Apache Pig and Pig LatinHigh-level Programming Languages: Apache Pig and Pig Latin
High-level Programming Languages: Apache Pig and Pig Latin
Pietro Michiardi
 
Ice mini guide
Ice mini guideIce mini guide
Ice mini guide
Ady Liu
 
Integration of APEX and Oracle Forms
Integration of APEX and Oracle FormsIntegration of APEX and Oracle Forms
Integration of APEX and Oracle Forms
Roel Hartman
 
PBDL.pdf
PBDL.pdfPBDL.pdf
PBDL.pdf
souzatg
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
ManageIQ
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
Ben Lin
 
Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
Rubyc Slides
 
From CakePHP to Laravel
From CakePHP to LaravelFrom CakePHP to Laravel
From CakePHP to Laravel
Jason McCreary
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
NAVER D2
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
Tatsuhiko Miyagawa
 
Aura for PHP at Fossmeet 2014
Aura for PHP at Fossmeet 2014Aura for PHP at Fossmeet 2014
Aura for PHP at Fossmeet 2014
Hari K T
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
Michelangelo van Dam
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa
 
Mock Servers - Fake All the Things!
Mock Servers - Fake All the Things!Mock Servers - Fake All the Things!
Mock Servers - Fake All the Things!
Atlassian
 
PHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & PinbaPHP applications/environments monitoring: APM & Pinba
PHP applications/environments monitoring: APM & Pinba
Patrick Allaert
 
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram VaswaniCreating REST Applications with the Slim Micro-Framework by Vikram Vaswani
Creating REST Applications with the Slim Micro-Framework by Vikram Vaswani
vvaswani
 
Passenger 6 generic language support presentation
Passenger 6 generic language support presentationPassenger 6 generic language support presentation
Passenger 6 generic language support presentation
Hongli Lai
 
api-platform: the ultimate API platform
api-platform: the ultimate API platformapi-platform: the ultimate API platform
api-platform: the ultimate API platform
Stefan Adolf
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
High-level Programming Languages: Apache Pig and Pig Latin
High-level Programming Languages: Apache Pig and Pig LatinHigh-level Programming Languages: Apache Pig and Pig Latin
High-level Programming Languages: Apache Pig and Pig Latin
Pietro Michiardi
 
Ice mini guide
Ice mini guideIce mini guide
Ice mini guide
Ady Liu
 
Integration of APEX and Oracle Forms
Integration of APEX and Oracle FormsIntegration of APEX and Oracle Forms
Integration of APEX and Oracle Forms
Roel Hartman
 
PBDL.pdf
PBDL.pdfPBDL.pdf
PBDL.pdf
souzatg
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
ManageIQ
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
Ben Lin
 
From CakePHP to Laravel
From CakePHP to LaravelFrom CakePHP to Laravel
From CakePHP to Laravel
Jason McCreary
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
NAVER D2
 
Aura for PHP at Fossmeet 2014
Aura for PHP at Fossmeet 2014Aura for PHP at Fossmeet 2014
Aura for PHP at Fossmeet 2014
Hari K T
 
Ad

Recently uploaded (20)

SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Mobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi ArabiaMobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi Arabia
Steve Jonas
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Mobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi ArabiaMobile App Development Company in Saudi Arabia
Mobile App Development Company in Saudi Arabia
Steve Jonas
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 

Why You Should Use TAPIs

  • 1. Why You Should Use TAPIs Jeffrey Kemp AUSOUG Connect Perth, November 2016
  • 2. All artifacts including code are presented for illustration purposes only. Use at your own risk. Test thoroughly in a non-critical environment before use.
  • 3. Main Menu 1. Why a data API? 2. Why choose PL/SQL? 3. How to structure your API? 4. Data API for Apex 5. Table APIs (TAPIs) 6. Open Source TAPI project
  • 4. Background “Building Maintainable Apex Apps”, 2014 https://jeffkemponoracle.com/2014/11/14/sample-tapi-apex-application/ https://jeffkemponoracle.com/2016/02/11/tapi-generator-mkii/ https://jeffkemponoracle.com/2016/02/12/apex-api-call-a-package-for-all-your-dml/ https://jeffkemponoracle.com/2016/02/16/apex-api-for-tabular-forms/ https://jeffkemponoracle.com/2016/06/30/interactive-grid-apex-5-1-ea/
  • 5. Why a data API?
  • 6. Why a data API? “I’m building a simple Apex app. I’ll just use the built-in processes to handle all the DML.”
  • 7. Your requirements get more complex. – More single-row and/or tabular forms – More pages, more load routines, more validations, more insert/update processes – Complex conditions – Edge cases, special cases, weird cases
  • 9. Another system must create the same data – outside of Apex – Re-use validations and processing – Rewrite the validations – Re-engineer all processing (insert/update) logic – Same edge cases – Different edge cases
  • 10. Define all validations and processes in one place – Integrated error messages – Works with Apex single-row and tabular forms
  • 11. Simple wrapper to allow code re-use – Same validations and processes included – Reduced risk of regression – Reduced risk of missing bits
  • 12. • They get exactly the same logical outcome as we get • No hidden surprises from Apex features
  • 13. TAPIs Business Rule Validations Default Values Reusability Encapsulation Maintainability
  • 14. Maintainability is in the eye of the beholder maintainer.
  • 15. Techniques • DRY • Consistency • Naming • Single-purpose • Assertions
  • 16. Why use PL/SQL for your API?
  • 17. Why use PL/SQL for your API? • Data is forever • UIs come and go • Business logic – tighter coupling with Data than UI
  • 18. Business Logic • your schema • your data constraints • your validation rules • your insert/update/delete logic
  • 19. • keep business logic close to your data • on Oracle, PL/SQL is the best
  • 23. How should you structure your API?
  • 24. How should you structure your API? Use packages
  • 25. Focus each Package For example: – “Employees” API – “Departments” API – “Workflow” API – Security (user roles and privileges) API – Apex Utilities
  • 26. Package names as context GENERIC_PKG.get_event (event_id => nv('P1_EVENT_ID')); GENERIC_PKG.get_member (member_id => nv('P1_MEMBER_ID')); EVENT_PKG.get (event_id => nv('P1_EVENT_ID')); MEMBER_PKG.get (member_id => nv('P1_MEMBER_ID'));
  • 30. load 1. Get PK value 2. Call TAPI to query record 3. Set session state for each column
  • 32. validate 1. Get values from session state into record 2. Pass record to TAPI 3. Call APEX_ERROR for each validation error
  • 34. process 1. Get v('REQUEST') 2. Get values from session state into record 3. Pass record to TAPI
  • 35. Process a page requestprocedure process is rv EVENTS$TAPI.rvtype; r EVENTS$TAPI.rowtype; begin UTIL.check_authorization(SECURITY.Operator); case when APEX_APPLICATION.g_request = 'CREATE' then rv := apex_get; r := EVENTS$TAPI.ins (rv => rv); apex_set (r => r); UTIL.success('Event created.'); when APEX_APPLICATION.g_request like 'SAVE%' then rv := apex_get; r := EVENTS$TAPI.upd (rv => rv); apex_set (r => r); UTIL.success('Event updated.'); when APEX_APPLICATION.g_request = 'DELETE' then rv := apex_get_pk; EVENTS$TAPI.del (rv => rv); UTIL.clear_page_cache; UTIL.success('Event deleted.'); else null; end case; end process;
  • 36. get_rowfunction apex_get return VOLUNTEERS$TAPI.rvtype is rv VOLUNTEERS$TAPI.rvtype; begin rv.vol_id := nv('P9_VOL_ID'); rv.given_name := v('P9_GIVEN_NAME'); rv.surname := v('P9_SURNAME'); rv.date_of_birth := v('P9_DATE_OF_BIRTH'); rv.address_line := v('P9_ADDRESS_LINE'); rv.suburb := v('P9_SUBURB'); rv.postcode := v('P9_POSTCODE'); rv.state := v('P9_STATE'); rv.home_phone := v('P9_HOME_PHONE'); rv.mobile_phone := v('P9_MOBILE_PHONE'); rv.email_address := v('P9_EMAIL_ADDRESS'); rv.version_id := nv('P9_VERSION_ID'); return rv; end apex_get;
  • 37. set row procedure apex_set (r in VOLUNTEERS$TAPI.rowtype) is begin sv('P9_VOL_ID', r.vol_id); sv('P9_GIVEN_NAME', r.given_name); sv('P9_SURNAME', r.surname); sd('P9_DATE_OF_BIRTH', r.date_of_birth); sv('P9_ADDRESS_LINE', r.address_line); sv('P9_STATE', r.state); sv('P9_SUBURB', r.suburb); sv('P9_POSTCODE', r.postcode); sv('P9_HOME_PHONE', r.home_phone); sv('P9_MOBILE_PHONE', r.mobile_phone); sv('P9_EMAIL_ADDRESS', r.email_address); sv('P9_VERSION_ID', r.version_id); end apex_set;
  • 39. SQL in Apex select t.col_a ,t.col_b ,t.col_c from my_table t; • Move joins, select expressions, etc. to a view – except Apex-specific stuff like generated APEX_ITEMs
  • 40. Pros • Fast development • Smaller apex app • Dependency analysis • Refactoring • Modularity • Code re-use • Customisation • Version control
  • 41. Cons • Misspelled/missing item names – Mitigation: isolate all apex code in one set of packages – Enforce naming conventions – e.g. P1_COLUMN_NAME • Apex Advisor doesn’t check database package code
  • 42. Apex API Coding Standards • All v() calls at start of proc, once per item • All sv() calls at end of proc • Constants instead of 'P1_COL' • Dynamic Actions calling PL/SQL – use parameters • Replace PL/SQL with Javascript (where possible)
  • 43. Error Handling • Validate - only record-level validation • Cross-record validation – db constraints + XAPI • Capture DUP_KEY_ON_VALUE and ORA-02292 for unique and referential constraints • APEX_ERROR.add_error
  • 44. TAPIs • Encapsulate all DML for a table • Row-level validation • Detect lost updates • Generated
  • 45. TAPI contents • Record types – rowtype, arraytype, validation record type • Functions/Procedures – ins / upd / del / merge / get – bulk_ins / bulk_upd / bulk_merge • Constants for enumerations
  • 46. Why not a simple rowtype? procedure ins (emp_name in varchar2 ,dob in date ,salary in number ) is begin if is_invalid_date (dob) then raise_error('Date of birth bad'); elsif is_invalid_number (salary) then raise_error('Salary bad'); end if; insert into emp (emp_name, dob, salary) values (emp_name, dob, salary); end ins; ins (emp_name => :P1_EMP_NAME, dob => :P1_DOB, salary => :P1_SALARY); ORA-01858: a non-numeric character was found where a numeric was expected It’s too late to validate data types here!
  • 47. Validation record type type rv is record ( emp_name varchar2(4000) , dob varchar2(4000) , salary varchar2(4000)); procedure ins (rv in rvtype) is begin if is_invalid_date (dob) then raise_error('Date of birth bad'); elsif is_invalid_number (salary) then raise_error('Salary bad'); end if; insert into emp (emp_name, dob, salary) values (emp_name, dob, salary); end ins; ins (emp_name => :P1_EMP_NAME, dob => :P1_DOB, salary => :P1_SALARY); I’m sorry Dave, I can’t do that - Date of birth bad
  • 48. Example Table create table venues ( venue_id integer default on null venue_id_seq.nextval , name varchar2(200 char) , map_position varchar2(200 char) , created_dt date default on null sysdate , created_by varchar2(100 char) default on null sys_context('APEX$SESSION','APP_USER') , last_updated_dt date default on null sysdate , last_updated_by varchar2(100 char) default on null sys_context('APEX$SESSION','APP_USER') , version_id integer default on null 1 );
  • 49. TAPI example package VENUES$TAPI as cursor cur is select x.* from venues; subtype rowtype is cur%rowtype; type arraytype is table of rowtype index by binary_integer; type rvtype is record (venue_id venues.venue_id%type ,name varchar2(4000) ,map_position varchar2(4000) ,version_id venues.version_id%type ); type rvarraytype is table of rvtype index by binary_integer; -- validate the row function val (rv IN rvtype) return varchar2; -- insert a row function ins (rv IN rvtype) return rowtype; -- update a row function upd (rv IN rvtype) return rowtype; -- delete a row procedure del (rv IN rvtype); end VENUES$TAPI;
  • 50. TAPI ins function ins (rv in rvtype) return rowtype is r rowtype; error_msg varchar2(32767); begin error_msg := val (rv => rv); if error_msg is not null then UTIL.raise_error(error_msg); end if; insert into venues (name ,map_position) values(rv.name ,rv.map_position) returning venue_id ,... into r; return r; exception when dup_val_on_index then UTIL.raise_dup_val_on_index; end ins;
  • 51. TAPI val function val (rv in rvtype) return varchar2 is begin UTIL.val_not_null (val => rv.host_id, column_name => HOST_ID); UTIL.val_not_null (val => rv.event_type, column_name => EVENT_TYPE); UTIL.val_not_null (val => rv.title, column_name => TITLE); UTIL.val_not_null (val => rv.start_dt, column_name => START_DT); UTIL.val_max_len (val => rv.event_type, len => 100, column_name => EVENT_TYPE); UTIL.val_max_len (val => rv.title, len => 100, column_name => TITLE); UTIL.val_max_len (val => rv.description, len => 4000, column_name => DESCRIPTION); UTIL.val_datetime (val => rv.start_dt, column_name => START_DT); UTIL.val_datetime (val => rv.end_dt, column_name => END_DT); UTIL.val_domain (val => rv.repeat ,valid_values => t_str_array(DAILY, WEEKLY, MONTHLY, ANNUALLY) ,column_name => REPEAT); UTIL.val_integer (val => rv.repeat_interval, range_low => 1, column_name => REPEAT_INTERVAL); UTIL.val_date (val => rv.repeat_until, column_name => REPEAT_UNTIL); UTIL.val_ind (val => rv.repeat_ind, column_name => REPEAT_IND); return UTIL.first_error; end val;
  • 52. TAPI upd function upd (rv in rvtype) return rowtype is r rowtype; error_msg varchar2(32767); begin error_msg := val (rv => rv); if error_msg is not null then UTIL.raise_error(error_msg); end if; update venues x set x.name = rv.name ,x.map_position = rv.map_position where x.venue_id = rv.venue_id and x.version_id = rv.version_id returning venue_id ,... into r; if sql%notfound then raise UTIL.lost_update; end if; return r; exception when dup_val_on_index then UTIL.raise_dup_val_on_index; when UTIL.ref_constraint_violation then UTIL.raise_ref_con_violation; when UTIL.lost_update then lost_upd (rv => rv); end upd;
  • 53. Lost update handler procedure lost_upd (rv in rvtype) is db_last_updated_by venues.last_updated_by%type; db_last_updated_dt venues.last_updated_dt%type; begin select x.last_updated_by ,x.last_updated_dt into db_last_updated_by ,db_last_updated_dt from venues x where x.venue_id = rv.venue_id; UTIL.raise_lost_update (updated_by => db_last_updated_by ,updated_dt => db_last_updated_dt); exception when no_data_found then UTIL.raise_error('LOST_UPDATE_DEL'); end lost_upd; “This record was changed by JOE BLOGGS at 4:31pm. Please refresh the page to see changes.” “This record was deleted by another user.”
  • 54. TAPI bulk_ins function bulk_ins (arr in rvarraytype) return number is begin bulk_val(arr); forall i in indices of arr insert into venues (name ,map_position) values (arr(i).name ,arr(i).map_position); return sql%rowcount; exception when dup_val_on_index then UTIL.raise_dup_val_on_index; end bulk_ins;
  • 55. What about queries? Tuning a complex, general-purpose query is more difficult than tuning a complex, single-purpose query.
  • 56. Generating Code • Only PL/SQL • Templates compiled in the schema • Simple syntax • Sub-templates (“includes”) for extensibility
  • 57. OraOpenSource TAPI • Runs on NodeJS • Uses Handlebars for template processing • https://github.com/OraOpenSource/oos-tapi/ • Early stages, needs contributors
  • 58. OOS-TAPI Example create or replace package body {{toLowerCase table_name}} as gc_scope_prefix constant varchar2(31) := lower($$plsql_unit) || '.'; procedure ins_rec( {{#each columns}} p_{{toLowerCase column_name}} in {{toLowerCase data_type}} {{#unless @last}},{{lineBreak}}{{/unless}} {{~/each}} ); end {{toLowerCase table_name}};
  • 59. oddgen • SQL*Developer plugin • Code generator, including TAPIs • Support now added in jk64 Apex TAPI generator https://www.oddgen.org

Editor's Notes

  • #7: It’s declarative – no code required to load, validate, insert, update and delete data.” Apex handles so much for us, making the app more reliable and us more productive – such as automatic lost update detection, basic data type validations including maximum field lengths, date formats, mandatory fields and more.” (Why would a sane developer want to rebuild any of this?)
  • #12: (and you have a hard time remembering the details of what you built last week)
  • #13: No need to reverse-engineer the logic, no need to replicate things with added risk of hidden surprises
  • #14: Code that is easy to maintain is code that is easy to read, and easy to test.
  • #15: Remember, maintainability is NOT a problem for you while you are writing the code. It is a problem you need to solve for the person 3 months later who needs to maintain your code.
  • #16: How do we make code easier to read and test?
  • #27: Organise and name your packages according to how they will be used elsewhere. This means your function and procedure names can be very short, because you no longer have to say “get_event”
  • #29: Table APIs will form the “Model” part of the MVC equation. Apex provides the “View” part. The Controller is what we’ll implement almost completely in PL/SQL in database packages.
  • #37: NV is only used for hidden items that should always have numerical values. The TAPI will handle all other data type conversions (such as numbers and dates).
  • #39: For Dynamic Actions, since performance is the top priority, I’d always use parameters for any data required.
  • #41: IF/ELSE and CASE statements instead of Apex conditions. The code is more re-usable: both across pages within the application, as well as by other apex applications or even other UIs and system interfaces. Easier to read, debug, diagnose and version control. Code merge has been solved for database PL/SQL source files, but not for Apex components.
  • #45: Especially good for external interfaces, e.g. for inserting into an eBus interface table
  • #46: Where multiple rows might need to be processed, always use bulk binding and bulk DML. Never ever call single-row routines from within a loop!
  • #52: The val routine in a TAPI should rarely if ever query other tables – it usually only validates the row in isolation within its own context. Generally cross-record and cross-table validation should be done at the XAPI level, or rely on table constraints.