9.2.8.Finding Methods - Method Signatures Generation & Comparison

A method of a user defined type is identified uniquely by the combination of the following:

the method name
number of the method's parameters
the method's parameter types
the method's return type

This combination of a method attributes is called the method's signature.

The Virtuoso Server must know the method's types of the parameter values and the return type at compile time to calculate the method signature and find exactly the method to call in the types method table. This is different from the current practice in calling stored procedures, because the compile types are not used to find the procedure.

The majority of the system functions are known at compile time to return values of a certain SQL type (e.g.: LEFT is known to return VARCHAR, ATOI returns INTEGER etc). But there are some (e.g.: AREF) that may return values of more than one type. The Virtuoso server does type arithmetic for scalar expressions at compile time already (to be able to supply columns types of a result set to ODBC clients for example), but so far the calculated type has only informative value and was not used anywhere during the compilation. All of the type checks are done at runtime. The method/constructor invocation breaks that practice by using the calculated compile time types for the scalar expressions.

Example9.7.Method Signatures

Consider a method m1 of type t1 taking an INTEGER parameter and returning an integer value:

CREATE METHOD m1 (in x integer)
  for t1 returns integer
{ return x + 10; };

Now consider calling the method as follows (in a Virtuoso/PL procedure):

...
declare p float;
declare ret integer;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(p);
....

This will yield a compilation error explaining that there is no method m1 of user defined type t1 . It will do that because p has a compile time type of FLOAT.

The following will also fail to compile:

...
declare p integer;
declare ret float;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(p);
....

This time the ret has a declared type of FLOAT and there is no method in t1 taking 1 INTEGER parameter and returning FLOAT.

The most consistent way of specifying the compile time type of a scalar expression is to enclose it in a CAST statement, as follows:

...
declare p float;
declare ret integer;
declare t1i t1;

t1i := new t1();
p := 1;

ret := t1i.m1(CAST (p as integer));
....

This will compile and execute correctly.