Thread: Inheritance of functions shows unexpected behaviour

Inheritance of functions shows unexpected behaviour

From
pgsql-bugs@postgresql.org
Date:
Ganesh Prasad (ganesh.prasad@reply2.com) reports a bug with a severity of 2
The lower the number the more severe it is.

Short Description
Inheritance of functions shows unexpected behaviour

Long Description
This is an example to demonstrate a possible bug in the inheritance behaviour of the PostgreSQL object model.
You can run the test yourself to see if the behaviour is as expected.

The installation should be PostgreSQL 7.1 with PL/pgSQL installed.

If a class (table) has a method (function) defined, then we should be able to invoke it on all instances of that class
(eventhose of any inherited class), because they are all instances of the parent class as well. 

Take a class "employee" with key "id" and attributes "name" and "salary".  Define a function "getTax()" that calculates
taxas 20% of salary. 

Invocation of "getTax()" on instances of the "employee" class should yield correct results.

Now define a subclass of "employee" called "manager" with one extra attribute "dept", and insert a record into it.

The "getTax()" method *should* continue to work for all instances of "employee", because managers are employees too.
Theextra attribute "dept" should be ignored, because the query is on the "employee" class, not the "manager" class.
Regularselects seem to ignore the extra attribute. 

However, invocation of "getTax()" fails on the "employee" class for records corresponding to "manager".

STEPS:

1. Run the script "setup.sql". This creates the two tables, populates them with a record each, and creates the function
"getTax()".

2. Run the script "test1.sql". This invokes the "getTax()" method on the "employee" table for the record corresponding
tothe parent class itself (employee). The following output should occur: 

     gettax
    --------
      20000
    (1 row)

3. Run the script "test2.sql". This invokes the "getTax()" method on the "employee" table for the record corresponding
tothe child class (manager). The following (unexpected) output occurs: 

    ERROR:  query didn't return correct # of attributes for $1

Apparently, the extra attribute "dept" defined for manager is somehow affecting the result. But why? When the query is
onthe parent class, all instances should behave like instances of the parent class. 

Is this a bug?

COROLLARY:

If we now define a "getTax()" function on the "manager" class that calculates tax differently (say 25% of salary), then
polymorphismsays that any invocation of "getTax()", even on the parent class (employee), should yield different results
fordifferent employees (having the same salary) depending on whether the particular employee is a manager or not. The
appropriatemethod should be transparently used. 

Is this considered desirable behaviour? What would the function definition be like? If the function is defined for
"manager",then how can it override the corresponding function defined for "employee"? 

Resolution of this "bug" is vey important as it has implications for implementing object persistence directly in
PostgreSQLwithout the need for Object-Relational mapping (say) in a Container-Managed Entity Bean (EJB). 


Sample Code
setup.sql:

drop table t_manager;
drop table t_employee;

/*
Employees have an id (key), a name and a salary.
*/
create table t_employee
(
id    int4 primary key,
name    varchar(50) not null,
salary    float8
);

/*
Managers are employees who manage a department.
*/
create table t_manager
(
dept    char(2)
)
inherits (t_employee);

/*
An ordinary employee.
*/
insert into t_employee
values
(
1,
'Joe Bloggs',
100000.0
);

/*
A manager.
*/
insert into t_manager
values
(
2,
'John Doe',
150000.0,
'HR'
);

/*
A "method" defined for the "employee" class,
which should be inherited by the "manager" class.
*/
drop function getTax( t_employee );
create function getTax( t_employee ) returns float8 as '
declare
    emp alias for $1;
begin
    return emp.salary * 0.2 ;
end;
' language 'plpgsql';


test1.sql:

/*
The "method" is correctly invoked for an ordinary employee.
*/
select getTax( t_employee ) from t_employee where id = 1;

test2.sql:

/*
The "method" fails for managers, who should have inherited it
from employees.
*/
select getTax( t_employee ) from t_employee where id = 2;



No file was uploaded with this report

Re: Inheritance of functions shows unexpected behaviour

From
Tom Lane
Date:
pgsql-bugs@postgresql.org writes:
> Inheritance of functions shows unexpected behaviour

I agree, plpgsql is doing the wrong thing here.  Fix committed for
7.1.1.

            regards, tom lane

RE: Inheritance of functions shows unexpected behaviour

From
Ganesh Prasad
Date:
Thank you.

I hope the fix will implement polymorphism also, i.e., if a superclass and
subclass define an identically-named function, then calling the function on
all records of the superclass should transparently call the subclass's
function for the records corresponding to the subclass.

Regards,

Ganesh

-----Original Message-----
From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Sent: Tuesday, 1 May 2001 6:09 AM
To: ganesh.prasad@reply2.com; pgsql-bugs@postgresql.org
Subject: Re: [BUGS] Inheritance of functions shows unexpected behaviour


pgsql-bugs@postgresql.org writes:
> Inheritance of functions shows unexpected behaviour

I agree, plpgsql is doing the wrong thing here.  Fix committed for
7.1.1.

            regards, tom lane