SlideShare a Scribd company logo
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

What's hot

ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
Little Tukta Lita
 
Function overloading(C++)
Function overloading(C++)Function overloading(C++)
Function overloading(C++)
Ritika Sharma
 
Lambda Expressions in C++
Lambda Expressions in C++Lambda Expressions in C++
Lambda Expressions in C++
Patrick Viafore
 
Function
FunctionFunction
Function
jayesh30sikchi
 
Oop in java script
Oop in java scriptOop in java script
Oop in java script
Pierre Spring
 
GC in C++0x [eng]
GC in C++0x [eng]GC in C++0x [eng]
GC in C++0x [eng]
yak1ex
 
TypeScriptのすゝめ
TypeScriptのすゝめTypeScriptのすゝめ
TypeScriptのすゝめ
CASAREAL, Inc.
 
Debugging Your PHP Cake Application
Debugging Your PHP Cake ApplicationDebugging Your PHP Cake Application
Debugging Your PHP Cake Application
Jose Diaz-Gonzalez
 
Function in c
Function in cFunction in c
Function in c
savitamhaske
 
Functions in C++ (OOP)
Functions in C++ (OOP)Functions in C++ (OOP)
Functions in C++ (OOP)
Faizan Janjua
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabs
Stephane Gleizes
 
Javascript Secrets - Front in Floripa 2015
Javascript Secrets - Front in Floripa 2015Javascript Secrets - Front in Floripa 2015
Javascript Secrets - Front in Floripa 2015
Fernando Daciuk
 
Function in c
Function in cFunction in c
46630497 fun-pointer-1
46630497 fun-pointer-146630497 fun-pointer-1
46630497 fun-pointer-1
AmIt Prasad
 
C++ functions
C++ functionsC++ functions
C++ functions
Dawood Jutt
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime
 
C++ functions
C++ functionsC++ functions
C++ functions
Mayank Jain
 
Function lecture
Function lectureFunction lecture
Function lecture
DIT University, Dehradun
 

What's hot (18)

ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
 
Function overloading(C++)
Function overloading(C++)Function overloading(C++)
Function overloading(C++)
 
Lambda Expressions in C++
Lambda Expressions in C++Lambda Expressions in C++
Lambda Expressions in C++
 
Function
FunctionFunction
Function
 
Oop in java script
Oop in java scriptOop in java script
Oop in java script
 
GC in C++0x [eng]
GC in C++0x [eng]GC in C++0x [eng]
GC in C++0x [eng]
 
TypeScriptのすゝめ
TypeScriptのすゝめTypeScriptのすゝめ
TypeScriptのすゝめ
 
Debugging Your PHP Cake Application
Debugging Your PHP Cake ApplicationDebugging Your PHP Cake Application
Debugging Your PHP Cake Application
 
Function in c
Function in cFunction in c
Function in c
 
Functions in C++ (OOP)
Functions in C++ (OOP)Functions in C++ (OOP)
Functions in C++ (OOP)
 
C++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabs
 
Javascript Secrets - Front in Floripa 2015
Javascript Secrets - Front in Floripa 2015Javascript Secrets - Front in Floripa 2015
Javascript Secrets - Front in Floripa 2015
 
Function in c
Function in cFunction in c
Function in c
 
46630497 fun-pointer-1
46630497 fun-pointer-146630497 fun-pointer-1
46630497 fun-pointer-1
 
C++ functions
C++ functionsC++ functions
C++ functions
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
 
C++ functions
C++ functionsC++ functions
C++ functions
 
Function lecture
Function lectureFunction lecture
Function lecture
 

Similar to the-lost-art-of-plpgsql

stack.pptx
stack.pptxstack.pptx
stack.pptx
KalimuthuVelappan
 
The Ring programming language version 1.2 book - Part 58 of 84
The Ring programming language version 1.2 book - Part 58 of 84The Ring programming language version 1.2 book - Part 58 of 84
The Ring programming language version 1.2 book - Part 58 of 84
Mahmoud Samir Fayed
 
C++ Advanced
C++ AdvancedC++ Advanced
C++ Advanced
Vivek Das
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
Kirill Chebunin
 
The STL
The STLThe STL
The STL
adil raja
 
Writing Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel SchulhofWriting Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel Schulhof
WithTheBest
 
The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185
Mahmoud Samir Fayed
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in Javascript
Knoldus Inc.
 
The Ring programming language version 1.10 book - Part 96 of 212
The Ring programming language version 1.10 book - Part 96 of 212The Ring programming language version 1.10 book - Part 96 of 212
The Ring programming language version 1.10 book - Part 96 of 212
Mahmoud Samir Fayed
 
The secret of PHP7's Performance
The secret of PHP7's Performance The secret of PHP7's Performance
The secret of PHP7's Performance
Xinchen Hui
 
The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210
Mahmoud Samir Fayed
 
02 Php Vars Op Control Etc
02 Php Vars Op Control Etc02 Php Vars Op Control Etc
02 Php Vars Op Control Etc
Geshan Manandhar
 

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

stack.pptx
stack.pptxstack.pptx
stack.pptx
 
The Ring programming language version 1.2 book - Part 58 of 84
The Ring programming language version 1.2 book - Part 58 of 84The Ring programming language version 1.2 book - Part 58 of 84
The Ring programming language version 1.2 book - Part 58 of 84
 
C++ Advanced
C++ AdvancedC++ Advanced
C++ Advanced
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
The STL
The STLThe STL
The STL
 
Writing Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel SchulhofWriting Node.js Bindings - General Principles - Gabriel Schulhof
Writing Node.js Bindings - General Principles - Gabriel Schulhof
 
The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185The Ring programming language version 1.5.4 book - Part 81 of 185
The Ring programming language version 1.5.4 book - Part 81 of 185
 
Functional programming in Javascript
Functional programming in JavascriptFunctional programming in Javascript
Functional programming in Javascript
 
The Ring programming language version 1.10 book - Part 96 of 212
The Ring programming language version 1.10 book - Part 96 of 212The Ring programming language version 1.10 book - Part 96 of 212
The Ring programming language version 1.10 book - Part 96 of 212
 
The secret of PHP7's Performance
The secret of PHP7's Performance The secret of PHP7's Performance
The secret of PHP7's Performance
 
The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210The Ring programming language version 1.9 book - Part 94 of 210
The Ring programming language version 1.9 book - Part 94 of 210
 
02 Php Vars Op Control Etc
02 Php Vars Op Control Etc02 Php Vars Op Control Etc
02 Php Vars Op Control Etc
 

More from Robert Treat

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

More from Robert Treat (20)

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

Recently uploaded

Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
OnBoard
 
Vulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive OverviewVulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive Overview
Steven Carlson
 
Improving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning ContentImproving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning Content
Enterprise Knowledge
 
kk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdfkk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdf
KIRAN KV
 
Semantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software DevelopmentSemantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software Development
Baishakhi Ray
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
Zilliz
 
Keynote : Presentation on SASE Technology
Keynote : Presentation on SASE TechnologyKeynote : Presentation on SASE Technology
Keynote : Presentation on SASE Technology
Priyanka Aash
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
SAI KAILASH R
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Zilliz
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
FIDO Alliance
 
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
AimanAthambawa1
 
Demystifying Neural Networks And Building Cybersecurity Applications
Demystifying Neural Networks And Building Cybersecurity ApplicationsDemystifying Neural Networks And Building Cybersecurity Applications
Demystifying Neural Networks And Building Cybersecurity Applications
Priyanka Aash
 
NVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space ExplorationNVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space Exploration
Alison B. Lowndes
 
Required Documents for ISO 17021 Certification.PPT
Required Documents for ISO 17021 Certification.PPTRequired Documents for ISO 17021 Certification.PPT
Required Documents for ISO 17021 Certification.PPT
mithun772
 
Connector Corner: Leveraging Snowflake Integration for Smarter Decision Making
Connector Corner: Leveraging Snowflake Integration for Smarter Decision MakingConnector Corner: Leveraging Snowflake Integration for Smarter Decision Making
Connector Corner: Leveraging Snowflake Integration for Smarter Decision Making
DianaGray10
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
ankush9927
 
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
FIDO Alliance
 
Retrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with RagasRetrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with Ragas
Zilliz
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
Priyanka Aash
 
Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
AmandaCheung15
 

Recently uploaded (20)

Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
Mastering Board Best Practices: Essential Skills for Effective Non-profit Lea...
 
Vulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive OverviewVulnerability Management: A Comprehensive Overview
Vulnerability Management: A Comprehensive Overview
 
Improving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning ContentImproving Learning Content Efficiency with Reusable Learning Content
Improving Learning Content Efficiency with Reusable Learning Content
 
kk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdfkk vathada _digital transformation frameworks_2024.pdf
kk vathada _digital transformation frameworks_2024.pdf
 
Semantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software DevelopmentSemantic-Aware Code Model: Elevating the Future of Software Development
Semantic-Aware Code Model: Elevating the Future of Software Development
 
It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...It's your unstructured data: How to get your GenAI app to production (and spe...
It's your unstructured data: How to get your GenAI app to production (and spe...
 
Keynote : Presentation on SASE Technology
Keynote : Presentation on SASE TechnologyKeynote : Presentation on SASE Technology
Keynote : Presentation on SASE Technology
 
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and DisadvantagesBLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
BLOCKCHAIN TECHNOLOGY - Advantages and Disadvantages
 
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
Garbage In, Garbage Out: Why poor data curation is killing your AI models (an...
 
UX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business GoalsUX Webinar Series: Aligning Authentication Experiences with Business Goals
UX Webinar Series: Aligning Authentication Experiences with Business Goals
 
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
COVID-19 and the Level of Cloud Computing Adoption: A Study of Sri Lankan Inf...
 
Demystifying Neural Networks And Building Cybersecurity Applications
Demystifying Neural Networks And Building Cybersecurity ApplicationsDemystifying Neural Networks And Building Cybersecurity Applications
Demystifying Neural Networks And Building Cybersecurity Applications
 
NVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space ExplorationNVIDIA at Breakthrough Discuss for Space Exploration
NVIDIA at Breakthrough Discuss for Space Exploration
 
Required Documents for ISO 17021 Certification.PPT
Required Documents for ISO 17021 Certification.PPTRequired Documents for ISO 17021 Certification.PPT
Required Documents for ISO 17021 Certification.PPT
 
Connector Corner: Leveraging Snowflake Integration for Smarter Decision Making
Connector Corner: Leveraging Snowflake Integration for Smarter Decision MakingConnector Corner: Leveraging Snowflake Integration for Smarter Decision Making
Connector Corner: Leveraging Snowflake Integration for Smarter Decision Making
 
Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10Computer HARDWARE presenattion by CWD students class 10
Computer HARDWARE presenattion by CWD students class 10
 
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
UX Webinar Series: Drive Revenue and Decrease Costs with Passkeys for Consume...
 
Retrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with RagasRetrieval Augmented Generation Evaluation with Ragas
Retrieval Augmented Generation Evaluation with Ragas
 
Keynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive SecurityKeynote : AI & Future Of Offensive Security
Keynote : AI & Future Of Offensive Security
 
Zaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdfZaitechno Handheld Raman Spectrometer.pdf
Zaitechno Handheld Raman Spectrometer.pdf
 

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