The Lost Art
of
PLPGSQL
pgcon 2019
Robert Treat (@robtreat2) the lost art of plpgsql
NOTE: There Will Be Code!
Robert Treat (@robtreat2) the lost art of plpgsql
whoami?
occasional
dev | ops | dba
currently
lead u.s. operations
at credativ
open source services and support
we build and run world class applications and
infrastructure to empower our clients
Robert Treat (@robtreat2) the lost art of plpgsql
whoami?
@robtreat2
robert.treat@credativ.us
https://www.linkedin.com/company/credativ-llc
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of postgres functions
how many of you have used a postgres function?
Robert Treat (@robtreat2) the lost art of plpgsql
why plpgsql
server side / round trips
stable api
simplify portability*
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of postgres functions
four types of postgres functions:
• internal functions
• query language functions (functions written in SQL)
• procedural language functions (functions written in PL/pgSQL)
• C-language functions
they all work similarly and have overlapping bits,
today we only care about
procedural language functions
specifically plpgsql ones
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of postgres functions
https://www.postgresql.org/docs/current/sql-createfunction.html
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of plpgsql
Chapter 42
“PL/pgSQL - SQL Procedural Language”
note: you can write stored procedures
in pure SQL, but this is not that
Robert Treat (@robtreat2) the lost art of plpgsql
a very brief overview of plpgsql
originally added in 6.4
(pl/tcl added in 6.3)
installed by default in 9.0
minimal language for creating triggers and user defined functions
add basic control structures to SQL
“trusted” language for server side computation
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of plpgsql
get diagnostics
when doing dynamic query execution
“get diagnostics” can be used for finding
row count and call stack information
additionally, /FOUND/ variable can be used
to determine query outcomes
42.5.5 Obtaining the Result Status
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of plpgsql
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of plpgsql
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
a brief overview of plpgsql
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql function
CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer)
RETURNS boolean
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RETURN TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
postgres@pagila=# select inventory_in_stock(42);
inventory_in_stock
--------------------
t
(1 row)
Robert Treat (@robtreat2) the lost art of plpgsql
how to plpgsql
user defined functions
do scripts
stored procedures
postgres@pagila=#
DO $$
DECLARE
v_row record;
BEGIN
FOR v_row IN
SELECT film_id, title, rating FROM film WHERE film_id < 10
LOOP
IF v_row.rating ='G'::mpaa_rating THEN
RAISE NOTICE '% is safe for tv',v_row.title;
END IF;
END LOOP;
END$$
;
NOTICE: ACE GOLDFINGER is safe for tv
NOTICE: AFFAIR PREJUDICE is safe for tv
NOTICE: AFRICAN EGG is safe for tv
DO
Robert Treat (@robtreat2) the lost art of plpgsql
at least one slide on DO scripts
https://www.postgresql.org/docs/current/sql-do.html
postgres@pagila=#
DO$$
BEGIN
vacuum actor;
vacuum film;
END
$$;
ERROR: VACUUM cannot be executed from a function
CONTEXT: SQL statement "vacuum actor"
PL/pgSQL function inline_code_block line 1 at SQL statement
Robert Treat (@robtreat2) the lost art of plpgsql
at least one slide on DO scripts
Robert Treat (@robtreat2) the lost art of plpgsql
what even is a procedure?
enter stored procedures
Robert Treat (@robtreat2) the lost art of plpgsql
what even is a procedure?
but first a history
Robert Treat (@robtreat2) the lost art of plpgsql
what even is a procedure?
“other databases say”
functions: user defined code that executes some
set of commands and returns a result
stored procedures: user defined code that
executes some set of commands returning no
result
Robert Treat (@robtreat2) the lost art of plpgsql
what even is a procedure?
create function
smored_promedure()
returns void as $$
begin
return;
end
$$ language plpgsql;
postgres@pagila=#
select smored_promedure();
smored_promedure
------------------
(1 row)
Robert Treat (@robtreat2) the lost art of plpgsql
what even is a procedure?
“in postgres, functions are equivalent to stored
procedures, and can be used interchangeably”
Robert Treat (@robtreat2) the lost art of plpgsql
stored procedures, turned up to 11
sql standard based
allow transaction control
Robert Treat (@robtreat2) the lost art of plpgsql
stored procedures, turned up to 11
postgres@pagila=# h create procedure
Command: CREATE PROCEDURE
Description: define a new procedure
Syntax:
CREATE [ OR REPLACE ] PROCEDURE
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = }
default_expr ] [, ...] ] )
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| AS 'definition'
| AS 'obj_file', 'link_symbol'
} ...
Robert Treat (@robtreat2) the lost art of plpgsql
stored procedures, turned up to 11
postgres@pagila=# h call
Command: CALL
Description: invoke a procedure
Syntax:
CALL name ( [ argument ] [, ...] )
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
CREATE OR REPLACE PROCEDURE inventory_in_sproc(p_inventory_id integer)
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RAISE NOTICE ‘TRUE’;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RAISE NOTICE ‘FALSE’;
ELSE
RAISE NOTICE ‘TRUE’;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
CREATE OR REPLACE PROCEDURE inventory_in_sproc(p_inventory_id integer)
LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
RAISE NOTICE ‘TRUE’;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
RAISE NOTICE ‘FALSE’;
ELSE
RAISE NOTICE ‘TRUE’;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
postgres@pagila=# call inventory_in_sproc(42);
NOTICE: TRUE
CALL
postgres@pagila=# select inventory_in_stock(42);
inventory_in_stock
--------------------
t
(1 row)
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
CREATE OR REPLACE PROCEDURE inventory_in_shock(
IN p_inventory_id integer,
INOUT p_instock boolean DEFAULT false
) LANGUAGE plpgsql
AS $$
DECLARE
v_rentals INTEGER;
v_out INTEGER;
BEGIN
-- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
-- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED
SELECT count(*) INTO v_rentals
FROM rental
WHERE inventory_id = p_inventory_id;
IF v_rentals = 0 THEN
p_instock := TRUE;
END IF;
SELECT COUNT(rental_id) INTO v_out
FROM inventory LEFT JOIN rental USING(inventory_id)
WHERE inventory.inventory_id = p_inventory_id
AND rental.return_date IS NULL;
IF v_out > 0 THEN
p_instock := FALSE;
ELSE
p_instock := TRUE;
END IF;
END $$;
Robert Treat (@robtreat2) the lost art of plpgsql
an example plpgsql procedure
postgres@pagila=# call inventory_in_sproc(42);
NOTICE: TRUE
CALL
postgres@pagila=# select inventory_in_stock(42);
inventory_in_stock
--------------------
t
(1 row)
postgres@pagila=# call inventory_in_shock(42);
p_instock
-----------
t
(1 row)
Robert Treat (@robtreat2) the lost art of plpgsql
plpgsql procedure transaction control
postgres@pagila=# create table xx (xx int);
CREATE TABLE
postgres@pagila=#
create or replace procedure xx()
as $$
begin
insert into xx select 1; rollback;
insert into xx select 2; commit;
insert into xx select 3; rollback;
end $$
language plpgsql;
CREATE PROCEDURE
postgres@pagila=# call xx();
CALL
postgres@pagila=# select * from xx;
xx
----
2
(1 row)
Robert Treat (@robtreat2) the lost art of plpgsql
plpgsql procedure transaction control
postgres@pagila=# create or replace procedure merry_maids() as $$
begin vacuum actor; end $$ language plpgsql;
CREATE PROCEDURE
postgres@pagila=# call merry_maids();
ERROR: VACUUM cannot be executed from a function
CONTEXT: SQL statement "vacuum actor”
* fyi, you can do this with analyze
Robert Treat (@robtreat2) the lost art of plpgsql
more to do!
certain ddl - create index concurrently
vacuum support
multiple result-sets
#thankyou
Robert Treat (@robtreat2) the lost art of plpgsql

More Related Content

PDF
The Ring programming language version 1.5.3 book - Part 90 of 184
PDF
The Ring programming language version 1.7 book - Part 86 of 196
PDF
C++ for Java Developers (SwedenCpp Meetup 2017)
PDF
C++ for Java Developers (JavaZone 2017)
PPTX
Journey of a C# developer into Javascript
PPT
CPP Language Basics - Reference
PDF
IBM Cloud University: Java, Node.js and Swift
PPT
Functions in C++
The Ring programming language version 1.5.3 book - Part 90 of 184
The Ring programming language version 1.7 book - Part 86 of 196
C++ for Java Developers (SwedenCpp Meetup 2017)
C++ for Java Developers (JavaZone 2017)
Journey of a C# developer into Javascript
CPP Language Basics - Reference
IBM Cloud University: Java, Node.js and Swift
Functions in C++

What's hot (17)

PPTX
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
PPT
Function overloading(C++)
PPTX
Lambda Expressions in C++
ODP
Function
PDF
Oop in java script
PDF
GC in C++0x [eng]
PDF
TypeScriptのすゝめ
KEY
Debugging Your PHP Cake Application
PPSX
Function in c
PPTX
Functions in C++ (OOP)
PDF
C++17 introduction - Meetup @EtixLabs
PDF
Javascript Secrets - Front in Floripa 2015
PPTX
PDF
46630497 fun-pointer-1
PPT
C++ functions
PPT
C++ functions
PDF
Function lecture
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
Function overloading(C++)
Lambda Expressions in C++
Function
Oop in java script
GC in C++0x [eng]
TypeScriptのすゝめ
Debugging Your PHP Cake Application
Function in c
Functions in C++ (OOP)
C++17 introduction - Meetup @EtixLabs
Javascript Secrets - Front in Floripa 2015
46630497 fun-pointer-1
C++ functions
C++ functions
Function lecture
Ad

Similar to the-lost-art-of-plpgsql (20)

PDF
Function Procedure Trigger Partition.pdf
PPT
plsql les02
PPTX
Five more things about Oracle SQL and PLSQL
PDF
Find it. Fix it. Real-World SQL Tuning Cases with Karen Morton
PDF
kscope2013vst-130627142814-phpapp02.pdf
PPTX
Useful PL/SQL Supplied Packages
PDF
Standard SQL features where PostgreSQL beats its competitors
ODP
Pro PostgreSQL
PDF
Deep dive into PostgreSQL statistics.
PDF
Oracle 11G PL SQL Programming 2nd Edition Casteel Solutions Manual
PDF
Oracle 11G PL SQL Programming 2nd Edition Casteel Solutions Manual
PDF
Peeking into the Black Hole Called PL/PGSQL - the New PL Profiler / Jan Wieck...
PPT
zen and the art of SQL optimization
PPTX
How to tune a query - ODTUG 2012
PDF
Chris Bull's Bi Portfolio
PDF
Enhancements in Oracle 23c Introducing the NewOld Returning Clause
PPTX
SQL Tuning Methodology, Kscope 2013
PDF
Percona live-2012-optimizer-tuning
PDF
2013 Collaborate - OAUG - Presentation
TXT
Fx oracle - AS400
Function Procedure Trigger Partition.pdf
plsql les02
Five more things about Oracle SQL and PLSQL
Find it. Fix it. Real-World SQL Tuning Cases with Karen Morton
kscope2013vst-130627142814-phpapp02.pdf
Useful PL/SQL Supplied Packages
Standard SQL features where PostgreSQL beats its competitors
Pro PostgreSQL
Deep dive into PostgreSQL statistics.
Oracle 11G PL SQL Programming 2nd Edition Casteel Solutions Manual
Oracle 11G PL SQL Programming 2nd Edition Casteel Solutions Manual
Peeking into the Black Hole Called PL/PGSQL - the New PL Profiler / Jan Wieck...
zen and the art of SQL optimization
How to tune a query - ODTUG 2012
Chris Bull's Bi Portfolio
Enhancements in Oracle 23c Introducing the NewOld Returning Clause
SQL Tuning Methodology, Kscope 2013
Percona live-2012-optimizer-tuning
2013 Collaborate - OAUG - Presentation
Fx oracle - AS400
Ad

More from Robert Treat (20)

PDF
Advanced Int->Bigint Conversions
PDF
Explaining Explain
PDF
Managing Chaos In Production: Testing vs Monitoring
PDF
Managing Databases In A DevOps Environment 2016
PDF
Less Alarming Alerts - SRECon 2016
PDF
What Ops Can Learn From Design
PDF
Postgres 9.4 First Look
PDF
Less Alarming Alerts!
PDF
Past, Present, and Pachyderm - All Things Open - 2013
PDF
Big Bad "Upgraded" Postgres
PDF
Managing Databases In A DevOps Environment
PDF
The Essential PostgreSQL.conf
PDF
Pro Postgres 9
PDF
Advanced WAL File Management With OmniPITR
PDF
Scaling with Postgres (Highload++ 2010)
PDF
Intro to Postgres 9 Tutorial
PDF
Check Please!
PDF
Database Scalability Patterns
PDF
A Guide To PostgreSQL 9.0
PPT
Scaling With Postgres
Advanced Int->Bigint Conversions
Explaining Explain
Managing Chaos In Production: Testing vs Monitoring
Managing Databases In A DevOps Environment 2016
Less Alarming Alerts - SRECon 2016
What Ops Can Learn From Design
Postgres 9.4 First Look
Less Alarming Alerts!
Past, Present, and Pachyderm - All Things Open - 2013
Big Bad "Upgraded" Postgres
Managing Databases In A DevOps Environment
The Essential PostgreSQL.conf
Pro Postgres 9
Advanced WAL File Management With OmniPITR
Scaling with Postgres (Highload++ 2010)
Intro to Postgres 9 Tutorial
Check Please!
Database Scalability Patterns
A Guide To PostgreSQL 9.0
Scaling With Postgres

Recently uploaded (20)

PDF
sustainability-14-14877-v2.pddhzftheheeeee
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PPTX
O2C Customer Invoices to Receipt V15A.pptx
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PPT
Module 1.ppt Iot fundamentals and Architecture
PPTX
The various Industrial Revolutions .pptx
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PDF
Developing a website for English-speaking practice to English as a foreign la...
PDF
DP Operators-handbook-extract for the Mautical Institute
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PPT
Geologic Time for studying geology for geologist
PPTX
Benefits of Physical activity for teenagers.pptx
PPTX
observCloud-Native Containerability and monitoring.pptx
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
DOCX
search engine optimization ppt fir known well about this
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
Five Habits of High-Impact Board Members
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
sustainability-14-14877-v2.pddhzftheheeeee
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
Final SEM Unit 1 for mit wpu at pune .pptx
O2C Customer Invoices to Receipt V15A.pptx
Assigned Numbers - 2025 - Bluetooth® Document
Module 1.ppt Iot fundamentals and Architecture
The various Industrial Revolutions .pptx
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
Developing a website for English-speaking practice to English as a foreign la...
DP Operators-handbook-extract for the Mautical Institute
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Geologic Time for studying geology for geologist
Benefits of Physical activity for teenagers.pptx
observCloud-Native Containerability and monitoring.pptx
A contest of sentiment analysis: k-nearest neighbor versus neural network
search engine optimization ppt fir known well about this
Zenith AI: Advanced Artificial Intelligence
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
Five Habits of High-Impact Board Members
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...

the-lost-art-of-plpgsql

  • 1. The Lost Art of PLPGSQL pgcon 2019 Robert Treat (@robtreat2) the lost art of plpgsql NOTE: There Will Be Code!
  • 2. Robert Treat (@robtreat2) the lost art of plpgsql whoami? occasional dev | ops | dba currently lead u.s. operations at credativ open source services and support we build and run world class applications and infrastructure to empower our clients
  • 3. Robert Treat (@robtreat2) the lost art of plpgsql whoami? @robtreat2 robert.treat@credativ.us https://www.linkedin.com/company/credativ-llc
  • 4. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of postgres functions how many of you have used a postgres function?
  • 5. Robert Treat (@robtreat2) the lost art of plpgsql why plpgsql server side / round trips stable api simplify portability*
  • 6. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of postgres functions four types of postgres functions: • internal functions • query language functions (functions written in SQL) • procedural language functions (functions written in PL/pgSQL) • C-language functions they all work similarly and have overlapping bits, today we only care about procedural language functions specifically plpgsql ones
  • 7. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of postgres functions https://www.postgresql.org/docs/current/sql-createfunction.html
  • 8. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of plpgsql Chapter 42 “PL/pgSQL - SQL Procedural Language” note: you can write stored procedures in pure SQL, but this is not that
  • 9. Robert Treat (@robtreat2) the lost art of plpgsql a very brief overview of plpgsql originally added in 6.4 (pl/tcl added in 6.3) installed by default in 9.0 minimal language for creating triggers and user defined functions add basic control structures to SQL “trusted” language for server side computation
  • 10. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of plpgsql get diagnostics when doing dynamic query execution “get diagnostics” can be used for finding row count and call stack information additionally, /FOUND/ variable can be used to determine query outcomes 42.5.5 Obtaining the Result Status
  • 11. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 12. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of plpgsql CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 13. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of plpgsql CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 14. Robert Treat (@robtreat2) the lost art of plpgsql a brief overview of plpgsql CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 15. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 16. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 17. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 18. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 19. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 20. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 21. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 22. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 23. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql function CREATE OR REPLACE FUNCTION inventory_in_stock(p_inventory_id integer) RETURNS boolean LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RETURN TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RETURN FALSE; ELSE RETURN TRUE; END IF; END $$;
  • 24. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure postgres@pagila=# select inventory_in_stock(42); inventory_in_stock -------------------- t (1 row)
  • 25. Robert Treat (@robtreat2) the lost art of plpgsql how to plpgsql user defined functions do scripts stored procedures
  • 26. postgres@pagila=# DO $$ DECLARE v_row record; BEGIN FOR v_row IN SELECT film_id, title, rating FROM film WHERE film_id < 10 LOOP IF v_row.rating ='G'::mpaa_rating THEN RAISE NOTICE '% is safe for tv',v_row.title; END IF; END LOOP; END$$ ; NOTICE: ACE GOLDFINGER is safe for tv NOTICE: AFFAIR PREJUDICE is safe for tv NOTICE: AFRICAN EGG is safe for tv DO Robert Treat (@robtreat2) the lost art of plpgsql at least one slide on DO scripts https://www.postgresql.org/docs/current/sql-do.html
  • 27. postgres@pagila=# DO$$ BEGIN vacuum actor; vacuum film; END $$; ERROR: VACUUM cannot be executed from a function CONTEXT: SQL statement "vacuum actor" PL/pgSQL function inline_code_block line 1 at SQL statement Robert Treat (@robtreat2) the lost art of plpgsql at least one slide on DO scripts
  • 28. Robert Treat (@robtreat2) the lost art of plpgsql what even is a procedure? enter stored procedures
  • 29. Robert Treat (@robtreat2) the lost art of plpgsql what even is a procedure? but first a history
  • 30. Robert Treat (@robtreat2) the lost art of plpgsql what even is a procedure? “other databases say” functions: user defined code that executes some set of commands and returns a result stored procedures: user defined code that executes some set of commands returning no result
  • 31. Robert Treat (@robtreat2) the lost art of plpgsql what even is a procedure? create function smored_promedure() returns void as $$ begin return; end $$ language plpgsql; postgres@pagila=# select smored_promedure(); smored_promedure ------------------ (1 row)
  • 32. Robert Treat (@robtreat2) the lost art of plpgsql what even is a procedure? “in postgres, functions are equivalent to stored procedures, and can be used interchangeably”
  • 33. Robert Treat (@robtreat2) the lost art of plpgsql stored procedures, turned up to 11 sql standard based allow transaction control
  • 34. Robert Treat (@robtreat2) the lost art of plpgsql stored procedures, turned up to 11 postgres@pagila=# h create procedure Command: CREATE PROCEDURE Description: define a new procedure Syntax: CREATE [ OR REPLACE ] PROCEDURE name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] ) { LANGUAGE lang_name | TRANSFORM { FOR TYPE type_name } [, ... ] | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | SET configuration_parameter { TO value | = value | FROM CURRENT } | AS 'definition' | AS 'obj_file', 'link_symbol' } ...
  • 35. Robert Treat (@robtreat2) the lost art of plpgsql stored procedures, turned up to 11 postgres@pagila=# h call Command: CALL Description: invoke a procedure Syntax: CALL name ( [ argument ] [, ...] )
  • 36. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure CREATE OR REPLACE PROCEDURE inventory_in_sproc(p_inventory_id integer) LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RAISE NOTICE ‘TRUE’; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RAISE NOTICE ‘FALSE’; ELSE RAISE NOTICE ‘TRUE’; END IF; END $$;
  • 37. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure CREATE OR REPLACE PROCEDURE inventory_in_sproc(p_inventory_id integer) LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN RAISE NOTICE ‘TRUE’; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN RAISE NOTICE ‘FALSE’; ELSE RAISE NOTICE ‘TRUE’; END IF; END $$;
  • 38. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure postgres@pagila=# call inventory_in_sproc(42); NOTICE: TRUE CALL postgres@pagila=# select inventory_in_stock(42); inventory_in_stock -------------------- t (1 row)
  • 39. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure CREATE OR REPLACE PROCEDURE inventory_in_shock( IN p_inventory_id integer, INOUT p_instock boolean DEFAULT false ) LANGUAGE plpgsql AS $$ DECLARE v_rentals INTEGER; v_out INTEGER; BEGIN -- AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE -- FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED SELECT count(*) INTO v_rentals FROM rental WHERE inventory_id = p_inventory_id; IF v_rentals = 0 THEN p_instock := TRUE; END IF; SELECT COUNT(rental_id) INTO v_out FROM inventory LEFT JOIN rental USING(inventory_id) WHERE inventory.inventory_id = p_inventory_id AND rental.return_date IS NULL; IF v_out > 0 THEN p_instock := FALSE; ELSE p_instock := TRUE; END IF; END $$;
  • 40. Robert Treat (@robtreat2) the lost art of plpgsql an example plpgsql procedure postgres@pagila=# call inventory_in_sproc(42); NOTICE: TRUE CALL postgres@pagila=# select inventory_in_stock(42); inventory_in_stock -------------------- t (1 row) postgres@pagila=# call inventory_in_shock(42); p_instock ----------- t (1 row)
  • 41. Robert Treat (@robtreat2) the lost art of plpgsql plpgsql procedure transaction control postgres@pagila=# create table xx (xx int); CREATE TABLE postgres@pagila=# create or replace procedure xx() as $$ begin insert into xx select 1; rollback; insert into xx select 2; commit; insert into xx select 3; rollback; end $$ language plpgsql; CREATE PROCEDURE postgres@pagila=# call xx(); CALL postgres@pagila=# select * from xx; xx ---- 2 (1 row)
  • 42. Robert Treat (@robtreat2) the lost art of plpgsql plpgsql procedure transaction control postgres@pagila=# create or replace procedure merry_maids() as $$ begin vacuum actor; end $$ language plpgsql; CREATE PROCEDURE postgres@pagila=# call merry_maids(); ERROR: VACUUM cannot be executed from a function CONTEXT: SQL statement "vacuum actor” * fyi, you can do this with analyze
  • 43. Robert Treat (@robtreat2) the lost art of plpgsql more to do! certain ddl - create index concurrently vacuum support multiple result-sets
  • 44. #thankyou Robert Treat (@robtreat2) the lost art of plpgsql