Subject Re: [Firebird-Architect] Design of new built-in functions
Author Jim Starkey
Dmitry Yemanov wrote:

>Let's have a discussion on how we map new engine functions to BLR codes. The
>current approach (one BLR verb per function) requires many code
>modifications and wastes the limited BLR space. Now we have more than 50
>available positions, but that's not too many, actually. I know we're going
>to deprecate BLR a some point in the future, but it's not going to happen
>very soon, so we need some short-term solution.
>I see two alternative approaches to design system-defined functions (SDFs):
>1) as per Borland's conference paper "Extending SQL Functionality in
>2) as per Yaffil's implementation
Neither of these is very good; you need to consider more alternatives.
I note that you design from the implementation backwards. This is a
poor way to do design. Good design starts with a statement of
requirements both so you know what you are looking for and to evaluate a
potential design.

As you are probably aware, the original design had no configuration
file, so UDFs had to be defined by system tables. Firebird, or at
least Vulcan, now has an extensible set of configuration files that
would allow definition of system UDFs in a distributed configuration
file and "local" UDFs in site specific files, including per data control
of UDFs. This also have the desirable characteristic of giving the
system administrator, not random users, the control over what UDFs are
available (and safe to call). The Vulcan configuration file would also
give a great deal more flexibility defining the linkage between the UDF
and the engine.

No UDF should ever be given carte blanc to call back into the engine. A
proper callback object should be defined as part of a new linkage to
provide necessary engine functionality to a UDF. Defining the callback
object as an abstract C++ class would make extensibility simple and
straightforward while still given reasonable control over callbacks.

UDFs should *not* use internal descriptors. If you stay with
descriptors for future extensions, freeze the type space and descriptor
format as UDF specific. Internal types and descriptors need to change
from time to time; the UDF interface should be immutable.

Returning to my original point, take the time to list and debate the
requirements for UDFs. Deciding whether or not local UDFs should
override system UDFs by which implementation you prefer is ass
backwards. Figure out which behavior you want first, then design an
implementation that meets the requirements.

When putting together a requirements document, consider C, C++, other
"hard" compiled languages, and the "sandbox" languages. Think about
whether descriptors are actually needed, or whether a mechanism to pass
arbitrary length strings is all that is needed. If abstract strings do
the trick, maybe descriptors aren't needed -- and nobody would mourn
their disappearance. Keep in mind that abominations like VARCHAR are a
throwback to punch cards and that almost all modern languages support
"string" types without fixed limits.

So do requirements first, then architecture, then implementation.
Starting with implementation gives you two stupid alternatives.
Thinking about what you want to do will give you more freedom and,
hopefully, a better design.


Jim Starkey
Netfrastructure, Inc.
978 526-1376