+ All Categories
Home > Technology > Data Processing Inside PostgreSQL

Data Processing Inside PostgreSQL

Date post: 06-May-2015
Category:
Upload: enterprisedb
View: 9,788 times
Download: 6 times
Share this document with a friend
Description:
This presentation is for those who are familiar with databases and SQL, but want to learn how to move processing from their applications into the database to improve consistency, administration, and performance. Topics covered include advanced SQL features like referential integrity constraints, ANSI joins, views, rules, and triggers. The presentation also explains how to create server-side functions, operators, and custom data types in PostgreSQL.
93
Processing Data Inside PostgreSQL BRUCE MOMJIAN, ENTERPRISEDB February, 2009 Abstract There are indisputable advantages of doing data processing in the database rather than in each application. This presentation explores the ability to push data processing into the database using SQL, functions, triggers, and the object-relational features of POSTGRESQL. Creative Commons Attribution License http://momjian.us/presentations
Transcript
Page 1: Data Processing Inside PostgreSQL

Processing Data Inside PostgreSQL

BRUCE MOMJIAN,ENTERPRISEDB

February, 2009

AbstractThere are indisputable advantages of doing data processing in the databaserather than in each application. This presentation explores the ability to pushdata processing into the database using SQL, functions, triggers, and theobject-relational features of POSTGRESQL.

Creative Commons Attribution License http://momjian.us/presentations

Page 2: Data Processing Inside PostgreSQL

Pre-SQL Data Access

No one wants to return to this era:

� Complex cross-table access

� Single index

� No optimizer

� Simple WHERE processing

� No aggregation

Processing Data Inside PostgreSQL 1

Page 3: Data Processing Inside PostgreSQL

SQL Data Access

You probably take these for granted:

� Easy cross-table access, with optimizer assistance

� Complex WHERE processing

� Transaction Control

� Concurrency

� Portable language (SQL)

Processing Data Inside PostgreSQL 2

Page 4: Data Processing Inside PostgreSQL

Post-Ingres

Welcome to thenext generation

of data storage.

Processing Data Inside PostgreSQL 3

Page 5: Data Processing Inside PostgreSQL

Contents

1. SQL

2. Functions and Triggers

3. Customizing Database Features

Processing Data Inside PostgreSQL 4

Page 6: Data Processing Inside PostgreSQL

1. SQL

Make full use of the

SQL tools available.

Processing Data Inside PostgreSQL 5

Page 7: Data Processing Inside PostgreSQL

2. Functions and Triggers

Put your programs

in the database.

Processing Data Inside PostgreSQL 6

Page 8: Data Processing Inside PostgreSQL

3. Customizing Database Features

Change the

database features.

Processing Data Inside PostgreSQL 7

Page 9: Data Processing Inside PostgreSQL

1. SQL

Processing Data Inside PostgreSQL 8

Page 10: Data Processing Inside PostgreSQL

Table ConstraintsTable creation requires concentration.

Processing Data Inside PostgreSQL 9

Page 11: Data Processing Inside PostgreSQL

Unique Test in an Application

BEGIN;

LOCK tab;

SELECT ... WHERE col = key;

if not found

INSERT (or UPDATE)

COMMIT;

Processing Data Inside PostgreSQL 10

Page 12: Data Processing Inside PostgreSQL

UNIQUE Constraint

CREATE TABLE tab

(

col ... UNIQUE

);

CREATE TABLE customer (id INTEGER UNIQUE);

Processing Data Inside PostgreSQL 11

Page 13: Data Processing Inside PostgreSQL

Preventing NULLs

if (col != NULL)

INSERT/UPDATE;

Processing Data Inside PostgreSQL 12

Page 14: Data Processing Inside PostgreSQL

NOT NULL Constraint

CREATE TABLE tab

(

col ... NOT NULL

);

CREATE TABLE customer (name TEXT NOT NULL);

Processing Data Inside PostgreSQL 13

Page 15: Data Processing Inside PostgreSQL

Primary Key Constraint� UNIQUE

� NOT NULL

CREATE TABLE customer (id INTEGER PRIMARY KEY);

Processing Data Inside PostgreSQL 14

Page 16: Data Processing Inside PostgreSQL

Ensuring Table LinkageForeign —> Primary

BEGIN;

SELECT *

FROM primary

WHERE key = col

FOR UPDATE;

if found

INSERT (or UPDATE) INTO foreign;

COMMIT;

Processing Data Inside PostgreSQL 15

Page 17: Data Processing Inside PostgreSQL

Ensuring Table LinkagePrimary —> Foreign

BEGIN;

SELECT *

FROM foreign

WHERE col = key

FOR UPDATE;

if found

?

UPDATE/DELETE primary;

COMMIT;

Processing Data Inside PostgreSQL 16

Page 18: Data Processing Inside PostgreSQL

Ensuring Table LinkageExample

CREATE TABLE statename (

code CHAR(2) PRIMARY KEY,

name VARCHAR(30)

);

CREATE TABLE customer

(

customer_id INTEGER,

name VARCHAR(30),

telephone VARCHAR(20),

street VARCHAR(40),

city VARCHAR(25),

state CHAR(2) REFERENCES statename,

zipcode CHAR(10),

country VARCHAR(20)

);Processing Data Inside PostgreSQL 17

Page 19: Data Processing Inside PostgreSQL

Ensuring Table LinkageLarger Example

CREATE TABLE customer

(

customer_id INTEGER PRIMARY KEY,

name VARCHAR(30),

telephone VARCHAR(20),

street VARCHAR(40),

city VARCHAR(25),

state CHAR(2),

zipcode CHAR(10),

country VARCHAR(20)

);

CREATE TABLE employee

(

employee_id INTEGER PRIMARY KEY,

name VARCHAR(30),

hire_date DATE

);

CREATE TABLE part (Processing Data Inside PostgreSQL 18

Page 20: Data Processing Inside PostgreSQL

part_id INTEGER PRIMARY KEY,

name VARCHAR(30),

cost NUMERIC(8,2),

weight FLOAT

);

CREATE TABLE salesorder (

order_id INTEGER,

customer_id INTEGER REFERENCES customer,

employee_id INTEGER REFERENCES employee,

part_id INTEGER REFERENCES part,

order_date DATE,

ship_date DATE,

payment NUMERIC(8,2)

);

Processing Data Inside PostgreSQL 19

Page 21: Data Processing Inside PostgreSQL

Ensuring Table LinkagePrevent Change to Primary

BEGIN;

SELECT ...

FROM foreign

WHERE col = key

FOR UPDATE;

IF found

ABORT;

UPDATE/DELETE primary;

COMMIT;

Processing Data Inside PostgreSQL 20

Page 22: Data Processing Inside PostgreSQL

Ensuring Table LinkageREFERENCES Constraint

NO ACTION/RESTRICT (default)

CREATE TABLE foreign

(

col ... REFERENCES primary (col)

ON UPDATE NO ACTION -- not required

ON DELETE NO ACTION -- not required

);

Processing Data Inside PostgreSQL 21

Page 23: Data Processing Inside PostgreSQL

Ensuring Table LinkageCascade Change to Primary

BEGIN;

SELECT ...

FROM foreign

WHERE col = key

FOR UPDATE;

IF found

UPDATE/DELETE foreign;

UPDATE/DELETE primary;

COMMIT;

Processing Data Inside PostgreSQL 22

Page 24: Data Processing Inside PostgreSQL

Ensuring Table LinkageREFERENCES Constraint

CASCADE

CREATE TABLE foreign

(

col ... REFERENCES primary (col)

ON UPDATE CASCADE

ON DELETE CASCADE

);

Processing Data Inside PostgreSQL 23

Page 25: Data Processing Inside PostgreSQL

Ensuring Table LinkageSet Foreign to NULL on Change to Primary

BEGIN;

SELECT ...

FROM foreign

WHERE col = key

FOR UPDATE;

IF found

UPDATE foreign SET col = NULL;

UPDATE/DELETE primary;

COMMIT;

Processing Data Inside PostgreSQL 24

Page 26: Data Processing Inside PostgreSQL

Ensuring Table LinkageREFERENCES Constraint

SET NULL

CREATE TABLE foreign

(

col ... REFERENCES primary (col)

ON UPDATE SET NULL

ON DELETE SET NULL

);

Processing Data Inside PostgreSQL 25

Page 27: Data Processing Inside PostgreSQL

Ensuring Table LinkageSet Foreign to DEFAULT on Change to Primary

BEGIN;

SELECT ...

FROM foreign

WHERE col = key

FOR UPDATE;

IF found

UPDATE foreign SET col = DEFAULT;

UPDATE/DELETE primary;

COMMIT;

Processing Data Inside PostgreSQL 26

Page 28: Data Processing Inside PostgreSQL

Ensuring Table LinkageREFERENCES Constraint

SET DEFAULT

CREATE TABLE foreign

(

col ... REFERENCES primary (col)

ON UPDATE SET DEFAULT

ON DELETE SET DEFAULT

);

CREATE TABLE order (cust_id INTEGER REFERENCES customer (id));

Processing Data Inside PostgreSQL 27

Page 29: Data Processing Inside PostgreSQL

Controlling Data

if col > 0 ...

(col = 2 OR col = 7) ...

length(col) < 10 ...

INSERT/UPDATE tab;

Processing Data Inside PostgreSQL 28

Page 30: Data Processing Inside PostgreSQL

CHECK Constraint

CREATE TABLE tab

(

col ... CHECK (col > 0 ...

);

CREATE TABLE customer (age INTEGER CHECK (age >= 0));

Processing Data Inside PostgreSQL 29

Page 31: Data Processing Inside PostgreSQL

Check Constraint Example

CREATE TABLE friend2 (

firstname VARCHAR(15),

lastname VARCHAR(20),

city VARCHAR(15),

state CHAR(2) CHECK (length(trim(state)) = 2),

age INTEGER CHECK (age >= 0),

gender CHAR(1) CHECK (gender IN (’M’,’F’)),

last_met DATE CHECK (last_met BETWEEN ’1950-01-01’

AND CURRENT_DATE),

CHECK (upper(trim(firstname)) != ’ED’ OR

upper(trim(lastname)) != ’RIVERS’)

);

INSERT INTO friend2

VALUES (’Ed’, ’Rivers’, ’Wibbleville’, ’J’, -35, ’S’, ’1931-09-23’);

ERROR: ExecAppend: rejected due to CHECK constraint friend2_last_metProcessing Data Inside PostgreSQL 30

Page 32: Data Processing Inside PostgreSQL

Default Column Values

if col not specified

col = DEFAULT;

INSERT/UPDATE tab;

Processing Data Inside PostgreSQL 31

Page 33: Data Processing Inside PostgreSQL

DEFAULT Constraint

CREATE TABLE tab

(

quantity ... DEFAULT 1

);

CREATE TABLE customer (created timestamp DEFAULT CURRENT_TIMESTAMP);

Processing Data Inside PostgreSQL 32

Page 34: Data Processing Inside PostgreSQL

Auto-numbering Column

CREATE TABLE counter (curr INTEGER);

INSERT INTO counter VALUES (1);

...

BEGIN;

val = SELECT curr FROM counter FOR UPDATE;

UPDATE counter SET curr = curr + 1;

COMMIT;

INSERT INTO tab VALUES (... val ...);

Processing Data Inside PostgreSQL 33

Page 35: Data Processing Inside PostgreSQL

SERIAL/Sequence

CREATE TABLE tab

(

col SERIAL

);

CREATE TABLE tab

(

col INTEGER DEFAULT nextval(’tab_col_seq’)

);

CREATE TABLE customer (id SERIAL);

CREATE SEQUENCE customer_id_seq;

CREATE TABLE customer (id INTEGER DEFAULT nextval(’customer_id_seq’));

Processing Data Inside PostgreSQL 34

Page 36: Data Processing Inside PostgreSQL

Constraint MacrosDOMAIN

CREATE DOMAIN phone AS

CHAR(12) CHECK (VALUE ~ ’^[0-9]{3}-[0-9]{3}-[0-9]{4}$’);

CREATE TABLE company ( ... phnum phone, ...);

Processing Data Inside PostgreSQL 35

Page 37: Data Processing Inside PostgreSQL

UsingSELECT’sFeatures

Processing Data Inside PostgreSQL 36

Page 38: Data Processing Inside PostgreSQL

ANSI Outer Joins - LEFT OUTER

SELECT *

FROM tab1, tab2

WHERE tab1.col = tab2.col

UNION

SELECT *

FROM tab1

WHERE col NOT IN

(

SELECT tab2.col

FROM tab2

);

SELECT *

FROM tab1 LEFT JOIN tab2 ON tab1.col = tab2.col;

Processing Data Inside PostgreSQL 37

Page 39: Data Processing Inside PostgreSQL

ANSI Outer Joins - RIGHT OUTER

SELECT *

FROM tab1, tab2

WHERE tab1.col = tab2.col

UNION

SELECT *

FROM tab2

WHERE col NOT IN

(

SELECT tab1.col

FROM tab1

);

SELECT *

FROM tab1 RIGHT JOIN tab2 ON tab1.col = tab2.col;

Processing Data Inside PostgreSQL 38

Page 40: Data Processing Inside PostgreSQL

ANSI Outer Joins - FULL OUTER

SELECT *

FROM tab1, tab2

WHERE tab1.col = tab2.col

UNION

SELECT *

FROM tab1

WHERE col NOT IN

(

SELECT tab2.col

FROM tab2

)

UNION

SELECT *

FROM tab2

WHERE col NOT IN

(

SELECT tab1.col

FROM tab1

);

SELECT *

FROM tab1 FULL JOIN tab2 ON tab1.col = tab2.col;Processing Data Inside PostgreSQL 39

Page 41: Data Processing Inside PostgreSQL

ANSI Outer Join Example

SELECT *

FROM customer LEFT JOIN order ON customer.id = order.cust_id;

Processing Data Inside PostgreSQL 40

Page 42: Data Processing Inside PostgreSQL

AggregatesSUM()

total = 0

FOREACH val IN set

total = total + val;

END FOREACH

SELECT SUM(val) FROM tab;

Processing Data Inside PostgreSQL 41

Page 43: Data Processing Inside PostgreSQL

AggregatesMAX()

max = MIN_VAL;

FOREACH val IN set

if (val > max)

max = val;

END FOREACH

SELECT MAX(val) FROM tab;

SELECT MAX(cost) FROM part;

Processing Data Inside PostgreSQL 42

Page 44: Data Processing Inside PostgreSQL

AggregatesGROUP BY SUM()

qsort(set)

save = ’’;

total = 0;

FOREACH val IN set

if val != save and save != ’’

{

print save, total;

save = val;

total = 0;

}

total = total + amt;

END FOREACH

if save != ’’

print save, total;

SELECT val, SUM(amt) FROM tab GROUP BY val;

Processing Data Inside PostgreSQL 43

Page 45: Data Processing Inside PostgreSQL

AggregatesGROUP BY MAX()

save = ’’;

max = MIN_VAL;

FOREACH val IN set

if val != save and save != ’’

{

print save, max;

save = val;

max = MIN_VAL;

}

if (amt > max)

max = amt;

END FOREACH

if save != ’’

print save, max;

SELECT val, MAX(amt) FROM tab GROUP BY val;

Processing Data Inside PostgreSQL 44

Page 46: Data Processing Inside PostgreSQL

AggregatesGROUP BY Examples

SELECT part, COUNT(*)

FROM order

ORDER BY part;

SELECT cust_id, SUM(due)

FROM order

GROUP BY cust_id

ORDER BY 2 DESC;

Processing Data Inside PostgreSQL 45

Page 47: Data Processing Inside PostgreSQL

Merging SELECTsUNION

SELECT * INTO TEMP out FROM ...

INSERT INTO TEMP out SELECT ...

INSERT INTO TEMP out SELECT ...

SELECT DISTINCT ...

SELECT *

UNION

SELECT *

UNION

SELECT *;

Processing Data Inside PostgreSQL 46

Page 48: Data Processing Inside PostgreSQL

Joining SELECTsINTERSECT

SELECT * INTO TEMP out;

DELETE FROM out WHERE out.* NOT IN (SELECT ...);

DELETE FROM out WHERE out.* NOT IN (SELECT ...);

SELECT *

INTERSECT

SELECT *

INTERSECT

SELECT *;

Processing Data Inside PostgreSQL 47

Page 49: Data Processing Inside PostgreSQL

Subtracting SELECTsEXCEPT

SELECT * INTO TEMP out;

DELETE FROM out WHERE out.* IN (SELECT ...);

DELETE FROM out WHERE out.* IN (SELECT ...);

SELECT *

EXCEPT

SELECT *

EXCEPT

SELECT *;

Processing Data Inside PostgreSQL 48

Page 50: Data Processing Inside PostgreSQL

Controlling Rows ReturnedLIMIT/OFFSET

DECLARE limdemo CURSOR FOR SELECT ...

FOR i = 1 to 5

FETCH IN limdemo

END FOR

SELECT *

LIMIT 5;

DECLARE limdemo CURSOR FOR SELECT ...

MOVE 20 IN limdemo

FOR i = 1 to 5

FETCH IN limdemo;

END FOR

SELECT *

OFFSET 20 LIMIT 5;

Processing Data Inside PostgreSQL 49

Page 51: Data Processing Inside PostgreSQL

Controlling Rows ReturnedLIMIT/OFFSET Example

SELECT order_id, balance

FROM order

ORDER BY balance DESC

LIMIT 10;

Processing Data Inside PostgreSQL 50

Page 52: Data Processing Inside PostgreSQL

Locking SELECT RowsFOR UPDATE

BEGIN;

LOCK tab;

SELECT * FROM CUSTOMER WHERE id = 4452;

UPDATE customer SET balance = 0 WHERE id = 4452;

COMMIT;

BEGIN;

SELECT *

FROM customer

WHERE id = 4452

FOR UPDATE;

...

UPDATE customer

SET balance = 0Processing Data Inside PostgreSQL 51

Page 53: Data Processing Inside PostgreSQL

WHERE id = 4452;

COMMIT;

Processing Data Inside PostgreSQL 52

Page 54: Data Processing Inside PostgreSQL

Temporary Tables

CREATE TABLE tab (...);

...

DROP TABLE tab;

CREATE TEMP TABLE tab (...);

SELECT *

INTO TEMPORARY hold

FROM tab1, tab2, tab3

WHERE ...

Processing Data Inside PostgreSQL 53

Page 55: Data Processing Inside PostgreSQL

Automatically Modify SELECTVIEW - One Column

SELECT col4

FROM tab;

CREATE VIEW view1 AS

SELECT col4

FROM tab;

SELECT * FROM view1;

Processing Data Inside PostgreSQL 54

Page 56: Data Processing Inside PostgreSQL

Automatically Modify SELECTVIEW - One Row

SELECT *

FROM tab

WHERE col = ’ISDN’;

CREATE VIEW view2 AS

SELECT *

FROM tab

WHERE col = ’ISDN’;

SELECT * FROM view2;

Processing Data Inside PostgreSQL 55

Page 57: Data Processing Inside PostgreSQL

Automatically Modify SELECTVIEW - One Field

SELECT col4

FROM tab

WHERE col = ’ISDN’;

CREATE VIEW view3 AS

SELECT col4

FROM tab

WHERE col = ’ISDN’;

SELECT * FROM view3;

Processing Data Inside PostgreSQL 56

Page 58: Data Processing Inside PostgreSQL

Automatically ModifyINSERT/UPDATE/DELETE

Rules

INSERT INTO tab1 VALUES (...);

INSERT INTO tab2 VALUES (...);

CREATE RULE insert_tab1 AS ON INSERT TO tab1 DO

INSERT INTO tab2 VALUES (...);

INSERT INTO tab1 VALUES (...);

Processing Data Inside PostgreSQL 57

Page 59: Data Processing Inside PostgreSQL

Automatically ModifyINSERT/UPDATE/DELETE

Rules Example

CREATE TABLE service_request

(

customer_id INTEGER,

description text,

cre_user text DEFAULT CURRENT_USER,

cre_timestamp timestamp DEFAULT CURRENT_TIMESTAMP

);

CREATE TABLE service_request_log

(

customer_id INTEGER,

description text,

mod_type char(1),

mod_user text DEFAULT CURRENT_USER,

mod_timestamp timestamp DEFAULT CURRENT_TIMESTAMP

);

Processing Data Inside PostgreSQL 58

Page 60: Data Processing Inside PostgreSQL

Rules Example - Rule Definition

CREATE RULE service_request_update AS -- UPDATE rule

ON UPDATE TO service_request

DO

INSERT INTO service_request_log (customer_id, description, mod_type)

VALUES (old.customer_id, old.description, ’U’);

CREATE RULE service_request_delete AS -- DELETE rule

ON DELETE TO service_request

DO

INSERT INTO service_request_log (customer_id, description, mod_type)

VALUES (old.customer_id, old.description, ’D’);

Processing Data Inside PostgreSQL 59

Page 61: Data Processing Inside PostgreSQL

Multi-User Consistency� Atomic Changes

� Atomic Visibility

� Atomic Consistency

� Reliability

User 1 User 2 Description

BEGIN WORK User 1 starts a transaction

UPDATE acct SET balance = balance - 100 WHERE acctno = 53224 remove 100 from an account

UPDATE acct SET balance = balance + 100 WHERE acctno = 94913 add 100 to an account

SELECT * FROM acct sees both changes

SELECT * FROM acct sees no changes

COMMIT WORK

SELECT * FROM acct sees both changesProcessing Data Inside PostgreSQL 60

Page 62: Data Processing Inside PostgreSQL

NotificationLISTEN/NOTIFY

signal()/kill()

LISTEN myevent;

NOTIFY myevent;

Processing Data Inside PostgreSQL 61

Page 63: Data Processing Inside PostgreSQL

Application Walk-through

Gborg, http://gborg.postgresql.org/

Processing Data Inside PostgreSQL 62

Page 64: Data Processing Inside PostgreSQL

2. Functions and Triggers

Placing Code

Into the Database:

Server-side Functions

Processing Data Inside PostgreSQL 63

Page 65: Data Processing Inside PostgreSQL

Single-Parameter Built-In Functions/Operator

SELECT factorial(10);

factorial

-----------

3628800

(1 row)

SELECT 10!;

?column?

----------

3628800

(1 row)

Processing Data Inside PostgreSQL 64

Page 66: Data Processing Inside PostgreSQL

Two-Parameter Built-in Function/Operator

SELECT date_mi(’2003-05-20’::date, ’2001-10-13’::date);

date_mi

---------

584

(1 row)

SELECT ’2003-05-20’::date - ’2001-10-13’::date;

?column?

----------

584

(1 row)

psql \df

psql \do

Processing Data Inside PostgreSQL 65

Page 67: Data Processing Inside PostgreSQL

Custom Server-Side Functions� Create function

� Call function, manually or automatically

Processing Data Inside PostgreSQL 66

Page 68: Data Processing Inside PostgreSQL

Compute Sales Tax

total = cost * 1.06;

INSERT ... VALUES ( ... total ... );

INSERT ... VALUES ( ... cost * 1.06, ... );

CREATE FUNCTION total(float)

RETURNS float

AS ’SELECT $1 * 1.06;’

LANGUAGE ’sql’;

INSERT ... VALUES ( ... total(cost) ... )

Processing Data Inside PostgreSQL 67

Page 69: Data Processing Inside PostgreSQL

Convert Fahrenheit to Centigrade

cent = (faren - 32.0) * 5.0 / 9.0

INSERT ... VALUES ( ... cent ... )

INSERT ... VALUES ( ... (faren - 32.0) * 5.0 / 9.0, ... )

CREATE FUNCTION ftoc(float)

RETURNS float

AS ’SELECT ($1 - 32.0) * 5.0 / 9.0;’

LANGUAGE ’sql’;

INSERT ... VALUES ( ... ftoc(faren) ... )

Processing Data Inside PostgreSQL 68

Page 70: Data Processing Inside PostgreSQL

Compute Shipping Cost

if cost < 2

shipping = 3.00

else if cost < 4

shipping = 5.00

else shipping = 6.00

INSERT ... VALUES ( ... cost + shipping ... );

Processing Data Inside PostgreSQL 69

Page 71: Data Processing Inside PostgreSQL

Shipping Cost Function

CREATE FUNCTION shipping(numeric)

RETURNS numeric

AS ’SELECT CASE

WHEN $1 < 2 THEN CAST(3.00 AS numeric(8,2))

WHEN $1 >= 2 AND $1 < 4 THEN CAST(5.00 AS numeric(8,2))

WHEN $1 >= 4 THEN CAST(6.00 AS numeric(8,2))

END;’

LANGUAGE ’sql’;

INSERT ... VALUES ( ... cost + shipping(cost) ... );

Processing Data Inside PostgreSQL 70

Page 72: Data Processing Inside PostgreSQL

String Processing — PL/pgSQL

CREATE FUNCTION spread(text)

RETURNS text

AS $$

DECLARE

str text;

ret text;

i integer;

len integer;

BEGIN

str := upper($1);

ret := ’’; -- start with zero length

i := 1;

len := length(str);

WHILE i <= len LOOP

ret := ret || substr(str, i, 1) || ’ ’;

i := i + 1;

END LOOP;

RETURN ret;Processing Data Inside PostgreSQL 71

Page 73: Data Processing Inside PostgreSQL

END;

$$

LANGUAGE ’plpgsql’;

SELECT spread(’Major Financial Report’);

spread

----------------------------------------------

M A J O R F I N A N C I A L R E P O R T

(1 row)

Processing Data Inside PostgreSQL 72

Page 74: Data Processing Inside PostgreSQL

State Name LookupSQL Language Function

SELECT name

FROM statename

WHERE code = ’AL’;

CREATE FUNCTION getstatename(text)

RETURNS text

AS ’SELECT name

FROM statename

WHERE code = $1;’

LANGUAGE ’sql’;

SELECT getstatename(’AL’);

Processing Data Inside PostgreSQL 73

Page 75: Data Processing Inside PostgreSQL

State Name Lookup From StringPL/pgSQL Language Function

CREATE FUNCTION getstatecode(text)

RETURNS text

AS $$

DECLARE

state_str statename.name%TYPE;

statename_rec record;

i integer;

len integer;

matches record;

search_str text;

BEGIN

state_str := initcap($1); -- capitalization match column

len := length(trim($1));

i := 2;

SELECT INTO statename_rec * -- first try for an exact match

FROM statename

WHERE name = state_str;

IF FOUND

THEN RETURN statename_rec.code;

END IF;Processing Data Inside PostgreSQL 74

Page 76: Data Processing Inside PostgreSQL

WHILE i <= len LOOP -- test 2,4,6,... chars for match

search_str = trim(substr(state_str, 1, i)) || ’%’;

SELECT INTO matches COUNT(*)

FROM statename

WHERE name LIKE search_str;

IF matches.count = 0 -- no matches, failure

THEN RETURN NULL;

END IF;

IF matches.count = 1 -- exactly one match, return it

THEN

SELECT INTO statename_rec *

FROM statename

WHERE name LIKE search_str;

IF FOUND

THEN RETURN statename_rec.code;

END IF;

END IF;

i := i + 2; -- >1 match, try 2 more chars

END LOOP;

RETURN ’’;

END;

$$

LANGUAGE ’plpgsql’;

SELECT getstatecode(’Alabama’);

SELECT getstatecode(’ALAB’);

Processing Data Inside PostgreSQL 75

Page 77: Data Processing Inside PostgreSQL

SELECT getstatecode(’Al’);

SELECT getstatecode(’Ail’);

Processing Data Inside PostgreSQL 76

Page 78: Data Processing Inside PostgreSQL

State Name Maintenance

CREATE FUNCTION change_statename(char(2), char(30))

RETURNS boolean

AS $$

DECLARE

state_code ALIAS FOR $1;

state_name ALIAS FOR $2;

statename_rec RECORD;

BEGIN

IF length(state_code) = 0 -- no state code, failure

THEN RETURN ’f’;

ELSE

IF length(state_name) != 0 -- is INSERT or UPDATE?

THEN

SELECT INTO statename_rec *

FROM statename

WHERE code = state_code;

IF NOT FOUND -- is state not in table?

THEN INSERT INTO statename

VALUES (state_code, state_name);

ELSE UPDATE statename

SET name = state_nameProcessing Data Inside PostgreSQL 77

Page 79: Data Processing Inside PostgreSQL

WHERE code = state_code;

END IF;

RETURN ’t’;

ELSE -- is DELETE

SELECT INTO statename_rec *

FROM statename

WHERE code = state_code;

IF FOUND

THEN DELETE FROM statename

WHERE code = state_code;

RETURN ’t’;

ELSE RETURN ’f’;

END IF;

END IF;

END IF;

END;

$$

LANGUAGE ’plpgsql’;

SELECT change_statename(’AL’,’Alabama’);

SELECT change_statename(’AL’,’Bermuda’);

SELECT change_statename(’AL’,’’);

SELECT change_statename(’AL’,’’); -- row was already deleted

Processing Data Inside PostgreSQL 78

Page 80: Data Processing Inside PostgreSQL

SELECT Inside FROM

SELECT *

FROM (SELECT * FROM tab) AS tab;

SELECT *

FROM ( SELECT 1,2,3,4,5 UNION

SELECT 6,7,8,9,10 UNION

SELECT 11,12,13,14,15) AS tab15;

col| col| col| col| col

---+----+----+----+----

1 | 2 | 3 | 4 | 5

6 | 7 | 8 | 9 | 10

11 | 12 | 13 | 14 | 15

(3 rows)

Processing Data Inside PostgreSQL 79

Page 81: Data Processing Inside PostgreSQL

Function ReturningMultiple Values

CREATE TABLE int5(x1 INTEGER, x2 INTEGER, x3 INTEGER, x4 INTE-

GER, x5 INTEGER);

CREATE FUNCTION func5() RETURNS SETOF int5 AS

’SELECT 1,2,3,4,5;’

LANGUAGE SQL;

SELECT * FROM func5();

x1 | x2 | x3 | x4 | x5

----+----+----+----+----

1 | 2 | 3 | 4 | 5

(1 row)

Processing Data Inside PostgreSQL 80

Page 82: Data Processing Inside PostgreSQL

Function Returninga Table Result

CREATE OR REPLACE FUNCTION func15() RETURNS SETOF int5 AS

’ SELECT 1,2,3,4,5 UNION

SELECT 6,7,8,9,10 UNION

SELECT 11,12,13,14,15;’

LANGUAGE SQL;

SELECT * FROM func15();

x1 | x2 | x3 | x4 | x5

----+----+----+----+----

1 | 2 | 3 | 4 | 5

6 | 7 | 8 | 9 | 10

11 | 12 | 13 | 14 | 15

(3 rows)

Processing Data Inside PostgreSQL 81

Page 83: Data Processing Inside PostgreSQL

Automatic Function CallsTrigger

� BEFORE/AFTER ROW

� INSERT/UPDATE/DELETE

� OLD/NEW

Processing Data Inside PostgreSQL 82

Page 84: Data Processing Inside PostgreSQL

Trigger on Statename

CREATE FUNCTION trigger_insert_update_statename()

RETURNS trigger

AS $$

BEGIN

IF new.code !~ ’^[A-Za-z][A-Za-z]$’

THEN RAISE EXCEPTION ’State code must be two alphabetic characters.’;

END IF;

IF new.name !~ ’^[A-Za-z ]*$’

THEN RAISE EXCEPTION ’State name must be only alphabetic characters.’;

END IF;

IF length(trim(new.name)) < 3

THEN RAISE EXCEPTION ’State name must longer than two characters.’;

END IF;

new.code = upper(new.code); -- uppercase statename.code

new.name = initcap(new.name); -- capitalize statename.name

RETURN new;

END;

$$Processing Data Inside PostgreSQL 83

Page 85: Data Processing Inside PostgreSQL

LANGUAGE ’plpgsql’;

Processing Data Inside PostgreSQL 84

Page 86: Data Processing Inside PostgreSQL

Install TriggerOn Statename

CREATE TRIGGER trigger_statename

BEFORE INSERT OR UPDATE

ON statename

FOR EACH ROW

EXECUTE PROCEDURE trigger_insert_update_statename();

INSERT INTO statename VALUES (’a’, ’alabama’);

INSERT INTO statename VALUES (’al’, ’alabama2’);

INSERT INTO statename VALUES (’al’, ’al’);

INSERT INTO statename VALUES (’al’, ’alabama’);

Processing Data Inside PostgreSQL 85

Page 87: Data Processing Inside PostgreSQL

Function Languages� SQL

� PL/pgSQL

� PL/TCL

� PL/Python

� PL/Perl

� PL/sh

� C

Processing Data Inside PostgreSQL 86

Page 88: Data Processing Inside PostgreSQL

Function Examples� /contrib/earthdistance

� /contrib/fuzzystringmatch

� /contrib/pgcrypto

Processing Data Inside PostgreSQL 87

Page 89: Data Processing Inside PostgreSQL

3. Customizing Database Features

Adding New

Data and Indexing

Features

Processing Data Inside PostgreSQL 88

Page 90: Data Processing Inside PostgreSQL

Creation� CREATE FUNCTIONS in C

� CREATE TYPE

� CREATE OPERATOR

� CREATE OPERATOR CLASS (index type)

Processing Data Inside PostgreSQL 89

Page 91: Data Processing Inside PostgreSQL

Create New Data TypeWith Operator and Index Support

� Write input/output functions

� Register input/output functions with CREATE FUNCTION

� Register type with CREATE TYPE

� Write comparison functions

� Register comparison functions with CREATE FUNCTION

� Register comparison functions with CREATE OPERATOR

� Register operator class for indexes with CREATE OPERATOR CLASS

Processing Data Inside PostgreSQL 90

Page 92: Data Processing Inside PostgreSQL

Create New Data TypeExamples

� /contrib/chkpass

� /contrib/isn

� /contrib/cube

� /contrib/ltree

� /src/backend/utils/adt

Processing Data Inside PostgreSQL 91

Page 93: Data Processing Inside PostgreSQL

Conclusion

Processing Data Inside PostgreSQL 92


Recommended