Ganesh Prasad ([EMAIL PROTECTED]) 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 (even those 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 tax as 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. The extra attribute "dept" should be ignored, 
because the query is on the "employee" class, not the "manager" class. Regular selects 
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 to the 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 to the 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 on the 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 polymorphism says that any invocation of 
"getTax()", even on the parent class (employee), should yield different results for 
different employees (having the same salary) depending on whether the particular 
employee is a manager or not. The appropriate method 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 PostgreSQL without 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


---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to