Polymorphic Functions

Starting with PostgreSQL version 8.0, you can write polymorphic functions in PL/pgSQL. A polymorphic function is a function with at least one parameter of type ANYELEMENT or ANYARRAY. The types ANYELEMENT and ANYARRAY are called polymorphic types because they can assume different "shapes" at run-time.

Here's a simple polymorphic function that will return the greater of two arguments:

-- ch07.sql
CREATE OR REPLACE FUNCTION max( arg1 ANYELEMENT, arg2 ANYELEMENT ) 
 RETURNS ANYELEMENT AS $$
 BEGIN

 IF( arg1 > arg2 ) THEN
 RETURN( arg1 );
 ELSE
 RETURN( arg2 );
 END IF;

 END;
$$ LANGUAGE 'plpgsql';

When you call this function with two INTEGER values, PL/pgSQL treats the function as if you had defined it as

CREATE OR REPLACE FUNCTION max( arg1 INTEGER, arg2 INTEGER ) 
 RETURNS INTEGER AS $$

The polymorphic arguments arg1 and arg2 are assumed to be of type INTEGER.

If you call this function with two TEXT values, arg1 and arg2 are considered to be of type TEXT and the return value is also assumed to be of type TEXT. In fact, you can call this function with two arguments of almost any type. The only restriction is that the function must compile properly for a given type. In the case of the max() function, that means that there must be a > operator that compares two values of that type (since the function compares arg1 and arg2 using the > operator).

When you call a polymorphic function, the actual values that you provide for polymorphic parameters must all be of the same type. You can't call the max() function with an INTEGER and a TEXT argument because arg1 and arg2 are both defined as ANYELEMENT parameters. You can mix polymorphic arguments with other data types, you just have to ensure that all polymorphic arguments are of the same type. If you define ANYARRAY arguments, the elements within those arrays must match the type of other polymorphic parameters.

You can also write functions that return a value of type ANYELEMENT or ANYARRAY. When you call such a function, PostgreSQL infers the date type of the return value from the data type of the polymorphic arguments. You can't write a function that returns a polymorphic value unless the function expects at least one ANYELEMENT (or ANYARRAY) argument.

Here's a function that returns a polymorphic value. firstSmaller() finds the first element in arg2 that's smaller than arg1. arg2 must be a one-dimensional array:

-- ch07.sql
CREATE OR REPLACE FUNCTION firstSmaller( arg1 ANYELEMENT, arg2 ANYARRAY )
 RETURNS ANYELEMENT AS $$
 BEGIN

 FOR i IN array_lower( arg2, 1 ) .. array_upper( arg2, 1 ) LOOP

 IF arg2[i] < arg1 THEN
 RETURN( arg2[i] );
 END IF;

 END LOOP;

 RETURN NULL;

 END;
$$ LANGUAGE 'plpgsql';

You can call this function with an INTEGER value and array of INTEGERS, or a TEXT value and array of TEXT values, or a NUMERIC value and an array of NUMERIC values, and so on. If the polymorphic arguments (arg1 and arg2) are of type INTEGER, the return value will be of type INTEGER. If you call firstSmaller() with NUMERIC values, the return value will be of type NUMERIC.

A function that returns a polymorphic value automatically inherits an extra variable named $0. You can ALIAS $0 to a more descriptive name, such as result, to make it easier to read your code. The type of $0 is the same as the type of the return value; in other words, the data type of $0 matches the data type of the polymorphic arguments.

The sum() function, shown here, returns a polymorphic value.

-- ch07.sql
CREATE OR REPLACE FUNCTION sum( arg1 ANYARRAY ) RETURNS ANYELEMENT AS $$
 DECLARE
 result ALIAS FOR $0;
 BEGIN

 result := 0;

 FOR i IN array_lower( arg1, 1 ) .. array_upper( arg1, 1 ) LOOP

 IF arg1[i] IS NOT NULL THEN
 result := result + arg1[i];
 END IF;

 END LOOP;

 RETURN( result );

 END;

$$ LANGUAGE 'plpgsql';

The data type for $0 is inferred from the type of arg1. PL/pgSQL always initializes the return value to NULLbecause this function accumulates result as it progresses through the arg1 array, you must re-initialize result to 0 before you can add to it (remember, NULL + 5 is not the same as 0 + 5NULL+ 5 = NULL).

Note that you can't call the sum() function with an array of TEXT values because PostgreSQL doesn't define a TEXT + TEXT operator. You can call sum() with an array of any numeric type (INTEGER, REAL, NUMERIC, and so on).

Part I: General PostgreSQL Use

Introduction to PostgreSQL and SQL

Working with Data in PostgreSQL

PostgreSQL SQL Syntax and Use

Performance

Part II: Programming with PostgreSQL

Introduction to PostgreSQL Programming

Extending PostgreSQL

PL/pgSQL

The PostgreSQL C APIlibpq

A Simpler C APIlibpgeasy

The New PostgreSQL C++ APIlibpqxx

Embedding SQL Commands in C Programsecpg

Using PostgreSQL from an ODBC Client Application

Using PostgreSQL from a Java Client Application

Using PostgreSQL with Perl

Using PostgreSQL with PHP

Using PostgreSQL with Tcl and Tcl/Tk

Using PostgreSQL with Python

Npgsql: The .NET Data Provider

Other Useful Programming Tools

Part III: PostgreSQL Administration

Introduction to PostgreSQL Administration

PostgreSQL Administration

Internationalization and Localization

Security

Replicating PostgreSQL Data with Slony

Contributed Modules

Index



PostgreSQL(c) The comprehensive guide to building, programming, and administering PostgreSQL databases
PostgreSQL(c) The comprehensive guide to building, programming, and administering PostgreSQL databases
ISBN: 735712573
EAN: N/A
Year: 2004
Pages: 261

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net