FUNCTION definitions

A FUNCTION definition defines a named procedure with a set of statements.

Syntax 1 (legacy function syntax):

[PUBLIC|PRIVATE] FUNCTION function-name ( [ parameter-name [,...] ] )
    [ DEFINE parameter-name type-specification [,...] ]
    [ local-declaration [...] ]
    [ instruction 
    | [ RETURN expression [,...] ]
        [...] 
    ]
END FUNCTION
  1. function-name is the function identifier.
  2. parameter-name is the name of a formal argument of the function.
  3. type-specification can be one of:
  4. local-declaration is a DEFINE, CONSTANT or TYPE instruction.
  5. instruction is a language statement to be executed when the function is invoked.
  6. expression is a value to be returned by the function.

Syntax 2 (fully typed function):

[PUBLIC|PRIVATE] FUNCTION function-name (
     { parameter-name type-specification [ attributes-list ]
     | record-name record-type INOUT
     }
     [,...]
  )
 [ attributes-list ]
 [ RETURNS returns-specification ]
    [ local-declaration [...] ]
    [ instruction 
    | [ RETURN expression [,...] ]
        [...] 
    ]
END FUNCTION
where returns-specification is:
{ type-specification [ attributes-list ]
| ( type-specification [ attributes-list ] [,...] )
| ( )
} 
  1. function-name is the identifier of the function, that must follow the convention for identifiers.
  2. parameter-name is the name of a formal argument of the function.
  3. type-specification can be one of:
  4. record-name is the name of a parameter defined as record-type.
  5. record-type is a the name of a user-defined TYPE declared as a RECORD structure.
  6. attributes-list is a comma-separated list of name = value pairs or name attributes, and defines attributes for the function.
  7. local-declaration is a DEFINE, CONSTANT or TYPE instruction.
  8. instruction is a language statement to be executed when the function is invoked.
  9. expression is a value to be returned by the function.

Syntax 3 (methods):

[PUBLIC|PRIVATE] FUNCTION ( receiver-name receiver-type ) method-name (
     { parameter-name type-specification
     | record-name record-type INOUT
     }
     [,...]
  )
 [ RETURNS returns-specification ]
    [ local-declaration [...] ]
    [ instruction 
    | [ RETURN expression [,...] ]
        [...] 
    ]
END FUNCTION
where returns-specification is:
{ type-specification
| ( type-specification [,...] )
| ( )
}
  1. A (receiver-name receiver-type) clause defines a function as a method for a user-defined type.
  2. receiver-name is the identifier of the receiver referenced in the method body.
  3. receiver-type is the user-defined type to be the target of this method.
  4. method-name is the identifier of the method.
  5. parameter-name is the name of a formal argument of the method.
  6. type-specification can be one of:
  7. record-name is the name of a parameter defined with a record TYPE.
  8. record-type is a the name of a user-defined TYPE declared as a RECORD structure.
  9. local-declaration is a DEFINE, CONSTANT or TYPE instruction.
  10. instruction is a language statement to be executed when the method is invoked.
  11. expression is a value to be returned by the method.

Function names

Like other identifiers, function names are case-insensitive. However, always consider using the same naming convention when defining and invoking functions.

If the function name is also the name of a built-in function, an error occurs at link time, even if the program does not reference the built-in function.

Function definition using legacy syntax

The following example shows a function definition using the legacy syntax, with parameter definition in the function body:
FUNCTION split(str, len)
    DEFINE str STRING, len INT
    RETURN str.subString(1, len),
           str.subString(len+1, str.getLength())
END FUNCTION

This syntax does not define a function with a complete signature.

Function definition with complete function type

By specifying data types in the parameter list, you define a function with a complete function type.

This syntax allows better compilation checking:
FUNCTION split(str STRING, len INT) RETURNS (STRING, STRING)
    RETURN str.subString(1, len),
           str.subString(len+1, str.getLength())
END FUNCTION
Braces after the RETURNS clause are not required, when the function returns a single value:
FUNCTION count_items(sid INT) RETURNS INT
    DEFINE cnt INT
    SELECT COUNT(*) INTO cnt FROM stock WHERE stock_id = sid
    RETURN cnt
END FUNCTION

When the function returns a single value/type, it is also possible to enclose the type in parentheses:

FUNCTION count_items(sid INT) RETURNS (INT)
    ...
In the next example, the function has no parameters and does not return values:
FUNCTION clean_debug_log() RETURNS ()
    DELETE FROM debug_log
END FUNCTION

Methods

A FUNCTION definition using a receiver identifier and type defines a method for this type. Specify the receiver identifier and type before the method name:
TYPE Rectangle RECORD
    height, width DOUBLE PRECISION
END RECORD

FUNCTION (r Rectangle) area() RETURNS DOUBLE PRECISION
    RETURN r.height * r.width
END FUNCTION

For more details see Methods.

Function with record passed as reference

The INOUT keyword can be used to pass records by reference:

SCHEMA custdemo
TYPE CustRec RECORD LIKE customer.*
FUNCTION init_cust(r CustRec INOUT)
    INITIALIZE r.* TO NULL
    LET r.cust_num = 0
    LET r.cust_name = "<undefined>"
END FUNCTION

For more details see Function parameters.

Function with attributes

Function attributes can be used to complete the definition of the function itself, for its parameters and return values:

FUNCTION add(
    p1 INTEGER ATTRIBUTES(json_name = "parameter 1"),
    p2 INTEGER ATTRIBUTES(json_name = "parameter 2")
    )
    ATTRIBUTES(json_name = "function add")
    RETURNS INTEGER ATTRIBUTES(json_name = "return value 1")
        DEFINE var1 INTEGER
        LET var1 = (p1 + p2)
        RETURN var1
END FUNCTION

Function attributes are especially useful to implement RESTful Web Services functions.

For more details see Function attributes.