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