Also, question for the OP (Chris):
It’s not completely clear what exactly you want to hide from whom.
That is, if you only want to hide the implementation details from API clients, then RESTXQ and some conditional code is probably sufficient, however your comparison with local stored procedures in SQL make me think you mean that database clients my provide their own implementations of lower level functions, and you want higher level procedures to be able to call those functions without being concerned with the implementations. ( Which is what made me think of comparison with Object Oriented programming. )
— Steve M.
On Feb 25, 2020, at 11:17 AM, Majewski, Steven Dennis (sdm7g) sdm7g@virginia.edu wrote:
I was thinking that there would be a simpler way to bind function namespaces and databases, but that runs into the asymmetry that string in import and namespace declarations in the prolog must be literal strings and can’t be variables. ( I still tend to think from XSLT mental models instead of XQuery sometimes. ) And it seems that even the extended Q{} syntax requires a literal, so it’s not simple to make the function namespace variable.
I can do something like this ( with modules for English, French, Italian added to my repo ):
declare variable $it := 'http://example.org/modules/Italian http://example.org/modules/Italian' ; declare variable $fr := 'http://example.org/modules/French http://example.org/modules/French' ; declare variable $head := 'import module namespace lang = "' ; declare variable $tail := '"; ' ;
for $lang in ( $it, $fr ) let $prolog := $head || $lang || $tail return xquery:eval( $prolog || 'lang:hello("Everybody!")' )
Returns =>
Ciao Everybody! Bonjour Everybody!
In the XSLT 1 days, we used to get around the lack of dynamic eval by the functional programming technique of having one stylesheet produce another with the variables resolved. So another way of packaging this might be to create a RESTXQ endpoint that generates an XQuery module from a template and use that endpoint URL in an “import module … at” expression. But that location must also be a literal, so it’s just another variation of the above.
I can also think of some tricks using higher level functions, but so far, nothing that makes it all simple.
— Steve M.
On Feb 25, 2020, at 5:50 AM, Christian Grün <christian.gruen@gmail.com mailto:christian.gruen@gmail.com> wrote:
Hi Luke,
It isn't clear to me how RESTXQ helps with this.
Here is a (very minimal) example how an XQuery endpoint could look like:
declare %rest:path('{$db}/{$query}') function rest:execute( $db as xs:string, $query as xs:string ) { xquery:eval( xs:anyURI($db || '/' || $query), map { '': db:open($db) } ) };
One endpoint for all databases would suffice indeed.
Extending the semantics of our REST API would be another option, but we may need to clarify various questions (will there be an extra server directory for each database? What happens if people want to access both global and database-specific queries? etc).
Hope this helps, Christian