ADQL polymorphic functions

Markus Demleitner msdemlei at ari.uni-heidelberg.de
Thu Apr 22 13:28:19 CEST 2021


Dear DAL, dear Apps,

In the run-up to VODataService's RegTAP mapping (which will,
according to my plan, feature spectral coverage in J), and also to
make obscore more easily usable across the spectrum, I've implemented
a user-defined function for converting between the various spectral
units (cf. http://dc.g-vo.org/tap/capabilities, look for
gavo_specconv).  

For instance, you can say

  SELECT access_url, gavo_specconv(em_min, 'keV') as en_min
  FROM ivoa.obscore
  WHERE 1=CONTAINS(s_region, CIRCLE(30, 20, 5))
    AND gavo_specconv(1, 'keV', 'm') BETWEEN em_min and em_max

(this will run on http://dc.g-vo.org/tap). 

I'll make a sales pitch for this some other day, as I think this is
an excellent candidate for the UDF catalogue.

This time, however, my problem is of a different nature: As you can
see in the example, the UDF has two forms: a two-parameter one for
when the machinery can figure out the unit of the argument itself,
and a three-argument one when the user has to (or wants to) provide a
unit literal.

Current TAPRegExt doesn't really deal with this.

Of course, one could just define two UDFs, like this

  <feature>
    <form>gavo_specconv(expr DOUBLE PRECISION, dest_unit TEXT) 
        -&gt; DOUBLE PRECISION</form>
      <description>returns the spectral value expr converted to dest_unit.
        The unit of expr is derived from expr's components...
      </description>
  </feature>

  <feature>
    <form>gavo_specconv(expr DOUBLE PRECISION, expr_unit TEXT, dest_unit TEXT) 
        -&gt; DOUBLE PRECISION</form>
      <description>returns the spectral value expr converted to dest_unit.
        expr is assumed to be given in expr_unit...
      </description>
  </feature>

This has the advantage that it doesn't require any standards work.
It has the disadvantage that it increases the number of UDFs users
have to scan (in TOPCAT's service tab, say), and this might become
really ugly when functions are highly polymorphous (think: three
optional parameters each accepting three types would explode into
nine feature elements with, presumably, almost identical content.

Given that, I've thought about alternatives.  For instance, we could
expand the syntax of UDF signatures (parsing these is always
best-effort, so we wouldn't really break anything seriously).  In
this particular case,

  <form>gavo_specconv(expr DOUBLE PRECISION[, expr_unit TEXT],
    dest_unit TEXT)</form>
  <description>
    In the two parameter form, this...; the third parameter...
  </description>

-- in the spirit of EBNF -- would do the trick.  But this syntax is a
bit of a burden on clients that actually want to look at the
signatures, and it'll become ugly when we want to express type
polymorphism.  So, I can't say I like it much.

An interesting compromise would be to allow multiple form elements;
this would retain the ease of parsing with not having to repeat
possibly verbose descriptions, like this:

  <feature>
    <form>gavo_specconv(expr DOUBLE PRECISION, dest_unit TEXT) 
        -&gt; DOUBLE PRECISION</form>
    <form>gavo_specconv(expr DOUBLE PRECISION, expr_unit TEXT, dest_unit TEXT) 
        -&gt; DOUBLE PRECISION</form>
      <description>returns the spectral value expr converted to dest_unit.
        expr is assumed to be given in expr_unit...
      </description>
  </feature>

-- this would be my favourite, except it needs schema changes in
TAPRegExt, and I'd not bet on how well existing capabilities parsers
would cope with this.  Conversely, I think some of the other features
could profit from allowing multiple form-s, too.  Hm.

Sooo, TAP implementors, client authors: do you have additional ideas
for how to deal with polymorphous UDFs?  Or opinions on my options?

Thanks,

           Markus


More information about the apps mailing list