--
-- $Id$
--
-- This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
-- project.
--
-- Copyright (C) 1998-2014 OpenLink Software
--
-- This project is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the
-- Free Software Foundation; only version 2 of the License, dated June 1991.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along
-- with this program; if not, write to the Free Software Foundation, Inc.,
-- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
-- Facet web service
create procedure
fct_dbg_msg (in str varchar, in lvl int := 666)
{
declare d_lvl int;
declare d_mode varchar;
d_lvl := connection_get ('fct_dbg_lvl');
d_mode := connection_get ('fct_dbg_mode');
if (lvl < d_lvl) return;
if (d_lvl)
{
if (d_mode = 'stderr')
{
dbg_printf ('%s', str);
return;
}
if (d_mode = 'page')
{
declare d_out_s any;
d_out_s := connection_get ('__fct_dbg_out');
if (d_out_s)
http (str || '\n', d_out_s);
}
}
}
;
create procedure
fct_render_dbg_out ()
{
declare d_lvl int;
declare d_out varchar;
d_lvl := connection_get ('fct_dbg_lvl');
d_out := connection_get ('fct_dbg_out');
if (not d_lvl) return;
if (not d_out) { dbg_printf ('fct_render_dbg_out: no d_out'); return; }
declare d_ses any;
d_ses := connection_get ('__fct_dbg_out');
if (d_ses)
{
http('
');
http_value (d_ses);
http('
');
}
else
dbg_printf ('fct_render_dbg_out: no string session to write to!');
}
;
create procedure
fct_uri_curie (in uri varchar)
{
declare delim integer;
declare uriSearch, nsPrefix varchar;
delim := -1;
if (uri is null)
return uri;
uriSearch := uri;
nsPrefix := null;
while (nsPrefix is null and delim <> 0) {
delim := coalesce (strrchr (uriSearch, '/'), 0);
delim := __max (delim, coalesce (strrchr (uriSearch, '#'), 0));
delim := __max (delim, coalesce (strrchr (uriSearch, ':'), 0));
nsPrefix := coalesce (__xml_get_ns_prefix (subseq (uriSearch, 0, delim + 1), 2),
__xml_get_ns_prefix (subseq (uriSearch, 0, delim), 2));
uriSearch := subseq (uriSearch, 0, delim);
-- dbg_obj_print(uriSearch);
}
if (nsPrefix is not null)
{
declare rhs varchar;
rhs := subseq (uri, length (uriSearch) + 1, null);
if (length (rhs) = 0)
{
return null;
}
else
{
return nsPrefix || ':' || rhs;
}
}
return null;
}
;
create procedure
fct_short_uri (in x any)
{
declare loc, pref, sh varchar;
if (not isstring (x))
return x;
pref := iri_split (x, loc);
if (pref is null)
return x;
sh := __xml_get_ns_prefix (pref, 2);
if (sh is not null)
return sh || ':' || loc;
return x;
}
;
create procedure
fct_trunc_uri (in s varchar, in maxlen int := 40)
{
declare _s varchar;
declare _h int;
_s := trim(s);
if (length(_s) <= maxlen) return _s;
_h := floor (maxlen / 2);
return sprintf ('%s...%s', "LEFT"(_s, _h), "RIGHT"(_s, _h-1));
}
;
create procedure
fct_short_form (in x any, in ltgt int := 0)
{
declare loc, pref, sh varchar;
if (not isstring (x))
return null;
sh := fct_uri_curie(x);
if (x like 'NodeID%')
return 'Blank' || x;
if (sh is not null)
return (fct_trunc_uri(sh));
else return (case when ltgt then '<' || fct_trunc_uri (x) || '>' else fct_trunc_uri (x) end);
}
;
create procedure
fct_long_uri (in x any)
{
declare loc, pref, sh varchar;
if (not isstring (x))
return x;
pref := iri_split (x, loc);
if ('' = pref or ':' <> subseq (pref, length (pref) - 1))
return x;
sh := __xml_get_ns_uri (subseq (pref, 0, length (pref) - 1), 2);
if (sh is not null)
return sh || loc;
return x;
}
;
cl_exec ('registry_set (''fct_label_iri'', ?)',
vector (cast (iri_id_num (__i2id ('http://www.openlinksw.com/schemas/virtrdf#label')) as varchar)));
cl_exec ('registry_set (''fct_timeout_min'',''8000'')');
cl_exec ('registry_set (''fct_timeout_max'',''40000'')');
create procedure
FCT_LABEL (in x any, in g_id iri_id_8, in ctx varchar)
{
declare best_str any;
declare best_l, l int;
declare label_iri iri_id_8;
if (not isiri_id (x))
return null;
if (__proc_exists ('rdf_resolve_labels_s') is not null)
{
declare ret any;
ret := rdf_resolve_labels_s (adler32 ('en'), vector (x));
ret := coalesce (ret[0], '');
return __ro2sq (ret);
}
rdf_check_init ();
label_iri := iri_id_from_num (atoi (registry_get ('fct_label_iri')));
best_str := null;
best_l := 0;
for select o, p
from rdf_quad table option (index primary key)
where s = x and p in (rdf_super_sub_list (ctx, label_iri, 3)) do
{
if (is_rdf_box (o) or isstring (o))
{
if (is_rdf_box (o) and not rdf_box_is_complete (o))
L := 20;
else
l := length (o);
if (l > best_l)
{
best_str := o;
best_l := l;
}
}
}
return __ro2sq(best_str);
}
;
create procedure
FCT_LABEL_DP (in x any, in g_id iri_id_8, in ctx varchar)
{
return FCT_LABEL_DP_L (x, g_id, ctx, null);
}
;
create procedure
FCT_LABEL_DP_L (in x any, in g_id iri_id_8, in ctx varchar, in lng varchar)
{
declare best_str any;
declare best_l, l int;
declare label_iri iri_id_8;
declare q, best_q, str_lang, lng_pref any;
if (not isiri_id (x))
return vector (null, 1);
rdf_check_init ();
label_iri := iri_id_from_num (atoi (registry_get ('fct_label_iri')));
best_str := null;
best_l := 0;
best_q := 0;
for select o, p
from rdf_quad table option (no cluster, index rdf_quad)
where s = x and p in (rdf_super_sub_list (ctx, label_iri, 3)) do
{
if (is_rdf_box (o))
{
lng_pref := rdf_box_lang (o);
str_lang := (select RL_ID from RDF_LANGUAGE where RL_TWOBYTE = lng_pref);
}
else
str_lang := 'en';
q := cmp_get_lang_by_q (lng, str_lang);
if (is_rdf_box (o) or isstring (o))
{
if (q > best_q)
{
best_str := o;
best_q := q;
}
}
if (0)
{
if (is_rdf_box (o) and not rdf_box_is_complete (o))
l := 20;
else
l := length (o);
if (l > best_l)
{
best_str := o;
best_l := l;
}
}
}
if (is_rdf_box (best_str) and not rdf_box_is_complete (best_str))
return vector (0, 0, vector ('LBL_O_VALUE', vector (rdf_box_ro_id (best_str))));
return vector (best_str, 1);
}
;
create procedure
FCT_LABEL_NP (in x any, in g_id iri_id_8, in ctx varchar, in lng varchar := 'en')
{
declare best_str any;
declare best_l, l int;
declare label_iri iri_id_8;
declare q, best_q, str_lang, lang_id any;
if (not isiri_id (x))
return null;
rdf_check_init ();
label_iri := iri_id_from_num (atoi (registry_get ('fct_label_iri')));
best_str := '';
best_l := 0;
best_q := 0;
for select o
from rdf_quad table option (index rdf_quad)
where s = x and p in (rdf_super_sub_list (ctx, label_iri, 3)) order by cast (b3s_lbl_order (P) as int) do
{
o := __ro2sq (o);
lang_id := rdf_box_lang (o);
if (lang_id > 257)
str_lang := (select RL_ID from RDF_LANGUAGE where RL_TWOBYTE = lang_id);
else
str_lang := 'en';
q := cmp_get_lang_by_q (lng, str_lang);
if (is_rdf_box (o) or isstring (o))
{
if (q > best_q)
{
best_str := o;
best_q := q;
}
}
}
return best_str;
}
;
create procedure
FCT_LABEL_S (in x any, in g_id iri_id_8, in ctx varchar, in lng varchar)
{
declare best_str any;
declare best_l, l int;
declare label_iri iri_id_8;
declare q, best_q, str_lang, lng_pref any;
if (not isiri_id (x))
return null;
if (__proc_exists ('rdf_resolve_labels_s') is not null)
{
declare ret any;
ret := rdf_resolve_labels_s (adler32 (coalesce (lng, '')), vector (x));
ret := coalesce (ret[0], '');
return __ro2sq (ret);
}
rdf_check_init ();
label_iri := iri_id_from_num (atoi (registry_get ('fct_label_iri')));
best_str := null;
best_l := 0;
best_q := 0;
for select o, p
from rdf_quad table option (no cluster, index rdf_quad)
where s = x and p in (rdf_super_sub_list (ctx, label_iri, 3)) do
{
if (is_rdf_box (o))
{
lng_pref := rdf_box_lang (o);
str_lang := (select RL_ID from RDF_LANGUAGE where RL_TWOBYTE = lng_pref);
}
else
str_lang := 'en';
q := cmp_get_lang_by_q (lng, str_lang);
if (is_rdf_box (o) or isstring (o))
{
if (q > best_q)
{
best_str := o;
best_q := q;
}
}
if (0)
{
if (is_rdf_box (o) and not rdf_box_is_complete (o))
l := 20;
else
l := length (o);
if (l > best_l)
{
best_str := o;
best_l := l;
}
}
}
if (is_rdf_box (best_str) and not rdf_box_is_complete (best_str))
{
set isolation = 'committed';
return (select case (isnull (RO_LONG)) when 0 then blob_to_string (RO_LONG) else RO_VAL end
from DB.DBA.RDF_OBJ table option (no cluster) where RO_ID = rdf_box_ro_id (best_str));
}
return best_str;
}
;
create procedure
LBL_O_VALUE (in id int)
{
set isolation = 'committed';
return vector ((select case (isnull (RO_LONG)) when 0 then blob_to_string (RO_LONG) else RO_VAL end
from DB.DBA.RDF_OBJ table option (no cluster) where RO_ID = id), 1);
}
;
create procedure decl_dpipe_define ()
{
if (sys_stat ('cl_run_local_only'))
return;
dpipe_define ('DB.DBA.FCT_LABEL', 'DB.DBA.RDF_QUAD', 'RDF_QUAD_SP', 'DB.DBA.FCT_LABEL_DP', 0);
dpipe_define ('FCT_LABEL_L', 'DB.DBA.RDF_QUAD', 'RDF_QUAD_SP', 'DB.DBA.FCT_LABEL_DP_L', 0);
dpipe_define ('FCT_LABEL', 'DB.DBA.RDF_QUAD', 'RDF_QUAD_SP', 'DB.DBA.FCT_LABEL_DP', 0); -- was OPGS
dpipe_define ('LBL_O_VALUE', 'DB.DBA.RDF_OBJ', 'RDF_OBJ', 'DB.DBA.LBL_O_VALUE', 0);
}
;
decl_dpipe_define ();
TTLP ('@prefix foaf: .
@prefix dc: .
@prefix rdfs: .
@prefix virtrdf: .
@prefix fbase: .
@prefix skos: .
@prefix bibo: .
@prefix gr: .
@prefix owl: .
@prefix geo: .
@prefix og: .
dc:title rdfs:subPropertyOf virtrdf:label .
rdfs:label rdfs:subPropertyOf virtrdf:label .
fbase:name rdfs:subPropertyOf virtrdf:label .
foaf:name rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
foaf:nick rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
skos:prefLabel rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
foaf:accountName rdfs:subPropertyOf virtrdf:label .
bibo:shortTitle rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf foaf:name .
rdfs:subClassOf gr:BusinessEntity .
gr:BusinessEntity rdfs:subClassOf foaf:Organization .
rdfs:subClassOf gr:BusinessEntity .
rdfs:subPropertyOf rdfs:label .
rdfs:subPropertyOf rdfs:label .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf rdfs:label .
rdfs:subPropertyOf geo:lat .
rdfs:subPropertyOf geo:long .
og:latitude rdfs:subPropertyOf geo:lat .
og:longitude rdfs:subPropertyOf geo:long .
rdfs:subPropertyOf geo:lat .
rdfs:subPropertyOf geo:long .
rdfs:subPropertyOf rdf:type .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
rdfs:subPropertyOf virtrdf:label .
', 'xx', 'facets');
rdfs_rule_set ('facets', 'facets');
create procedure
fct_inf_val (in tree any)
{
declare i varchar;
i := cast (xpath_eval ('/query/@inference', tree) as varchar);
if (i is null or '' = i)
return null;
return i;
}
;
create procedure
fct_inf_clause (in tree any)
{
declare i varchar;
i := fct_inf_val (tree);
if (i is not null)
return sprintf (' define input:inference "%s" ', i);
return '';
}
;
create procedure
fct_sas_val (in tree any)
{
declare i varchar;
i := cast (xpath_eval ('/query/@same-as', tree) as varchar);
if (i is null or '' = i)
return null;
return i;
}
;
create procedure
fct_sas_clause (in tree any)
{
declare i varchar;
i := fct_sas_val (tree);
if (i is not null)
return sprintf (' define input:same-as "%s" ', i);
return '';
}
;
create procedure
fct_graph_clause (in tree any)
{
declare i varchar;
i := cast (xpath_eval ('/query/@graph', tree) as varchar);
if (i is null or '' = i)
return '';
return sprintf (' define input:default-graph-uri <%s> ', cast (i as varchar));
}
;
create procedure
fct_named_graph_clause (in tree any)
{
declare xt, xp, inx, s any;
inx := 1;
s := string_output ();
while ((xp := xpath_eval (sprintf ('//query/@graph%d', inx), tree)) is not null)
{
inx := inx + 1;
http (sprintf (' define input:default-graph-uri <%s> ', cast (xp as varchar)), s);
}
return string_output_string (s);
}
;
create procedure
fct_post (in tree any, in post any, in lim int, in offs int)
{
if (lim is not null)
http (sprintf (' limit %d ', cast (lim as int)), post);
if (offs is not null)
http (sprintf (' offset %d ', cast (offs as int)), post);
}
;
create procedure
fct_dtp (in x any)
{
if (isiri_id (x) or __box_flags (x) = 1)
return 'uri';
declare dtp any;
dtp := rdf_datatype_of_long (x, UNAME'http://www.openlinksw.com/schemas/facets/dtp/plainstring');
return (id_to_iri (dtp));
}
;
--
-- Handle any DTs which need special serialization in FILTER, etc.
--
create procedure
fct_sparql_ser (in x any)
{
if (__TAG (x) = __TAG (getdate()))
return date_iso8601(__ro2sq (x));
return '';
}
;
create procedure
fct_lang (in x any)
{
if (not is_rdf_box (x))
return NULL;
if (rdf_box_lang (x) = 257)
return null;
return (select rl_id from rdf_language where rl_twobyte = rdf_box_lang (x));
}
;
create procedure
fct_get_mode (in tree any, in xp any)
{
declare view_type varchar;
view_type := cast (xpath_eval (xp, tree, 1) as varchar);
if (0 and sys_stat ('cl_run_local_only') and view_type = 'text-d')
view_type := 'text';
return view_type;
}
;
create procedure
fct_xml_wrap (in tree any, in txt any)
{
declare view_type varchar;
view_type := fct_get_mode (tree, '//view/@type');
declare ntxt any; -- , texp any;
ntxt := string_output ();
declare n_cols int;
n_cols := fct_n_cols(tree);
fct_dbg_msg (sprintf ('fct_xml_wrap: view_type: %s', view_type));
fct_dbg_msg (sprintf (' n_cols : %d', n_cols));
if (n_cols = 2)
{
if (view_type = 'text')
{
http (sprintf ('select xmlelement ("result", xmlattributes (''%s'' as "type"),
xmlagg (xmlelement ("row",
xmlelement ("column",
xmlattributes (''trank'' as "trank"),
"sc"),
xmlelement ("column",
xmlattributes (''erank'' as "erank"),
"rank"),
xmlelement ("column",
xmlattributes (''g'' as "graph"),
__ro2sq ("g")),
xmlelement ("column",
xmlattributes (fct_lang ("c1") as "xml:lang",
fct_dtp ("c1") as "datatype",
fct_short_form(__ro2sq("c1")) as "shortform"),
__ro2sq ("c1")),
xmlelement ("column",
fct_label ("c1", 0, ''facets'' )),
xmlelement ("column",
fct_bold_tags("c2")))))
from (sparql define output:valmode "LONG" ', view_type), ntxt);
}
else if (view_type = 'text-d')
{
-- texp := cast (xpath_eval ('string (//query/text)', tree, 1) as varchar);
http ('select xmlelement (\'result\',
xmlattributes (\'text-d\' as "type"),
"res")
from (sparql ', ntxt);
}
else if (view_type = 'entities-list' or view_type = 'list' or view_type = 'propval-list')
{
http (sprintf ('select xmlelement ("result", xmlattributes (''%s'' as "type"),
xmlagg (xmlelement ("row",
xmlelement ("column",
xmlattributes (fct_lang ("c1") as "xml:lang",
fct_dtp ("c1") as "datatype",
fct_short_form(__ro2sq("c1")) as "shortform"),
__ro2sq ("c1")),
xmlelement ("column",
fct_label ("c1", 0, ''facets'' )))))
from (sparql define output:valmode "LONG" ', view_type), ntxt);
}
else
{
http (sprintf ('select xmlelement ("result", xmlattributes (''%s'' as "type"),
xmlagg (xmlelement ("row",
xmlelement ("column",
xmlattributes (fct_lang ("c1") as "xml:lang",
fct_dtp ("c1") as "datatype",
fct_short_form(__ro2sq("c1")) as "shortform"),
__ro2sq ("c1")),
xmlelement ("column",
fct_label ("c1", 0, ''facets'' )),
xmlelement ("column",
fct_bold_tags("c2")))))
from (sparql define output:valmode "LONG" ', view_type), ntxt);
}
}
if (n_cols = 1)
http (sprintf ('select xmlelement ("result", xmlattributes (''%s'' as "type"),
xmlagg (xmlelement ("row",
xmlelement ("column",
xmlattributes (fct_lang ("c1") as "xml:lang",
fct_dtp ("c1") as "datatype",
fct_short_form(__ro2sq("c1")) as "shortform",
fct_sparql_ser ("c1") as "sparql_ser"),
__ro2sq ("c1")),
xmlelement ("column", fct_label ("c1", 0, ''facets'' )))))
from (sparql define output:valmode "LONG" ', view_type), ntxt);
if (n_cols = 3)
http (sprintf ('select xmlelement ("result", xmlattributes (''%s'' as "type"),
xmlagg (xmlelement ("row",
xmlelement ("column",
xmlattributes (fct_lang ("c1") as "xml:lang",
fct_dtp ("c1") as "datatype",
fct_short_form(__ro2sq("c1")) as "shortform"),
__ro2sq ("c1")),
xmlelement ("column",
fct_label ("c1", 0, ''facets'' )),
xmlelement ("column", __ro2sq ("c2")),
xmlelement ("column", __ro2sq ("c3"))
)))
from (sparql define output:valmode "LONG" ', view_type), ntxt);
http (txt, ntxt);
http (') xx option (quietcast)', ntxt);
return string_output_string (ntxt);
}
;
create procedure
fct_n_cols (in tree any)
{
declare tp varchar;
tp := cast (xpath_eval ('//view/@type', tree, 1) as varchar);
-- fct_dbg_msg (sprintf ('fct_n_cols: tp: %s', tp));
if ('list' = tp)
return 1;
else if ('geo' = tp or 'geo-list' = tp)
return 3;
return 2;
signal ('FCT00', 'Unknown facet view type');
}
;
create procedure
element_split (in val any)
{
declare srch_split, el varchar;
declare k integer;
declare sall any;
--srch_split := '';
--k := 0;
--sall := split_and_decode(val, 0, '\0\0 ');
--for(k:=0;k 0) srch_split := concat (srch_split, ', ', '''',el,'''');
--};
--srch_split := trim(srch_split,',');
--srch_split := trim(srch_split,' ');
--return srch_split;
declare words any;
srch_split := '';
val := trim (val, '"');
FTI_MAKE_SEARCH_STRING_INNER (val,words);
k := 0;
for(k:=0;k 0)
srch_split := concat (srch_split, ', ', '''',el,'''');
};
srch_split := trim (srch_split,',');
srch_split := trim (srch_split,' ');
return srch_split;
}
;
create procedure
fct_view (in tree any, in this_s int, in txt any, in pre any, in post any, in full_tree any, in plain integer := 0)
{
declare lim, offs int;
declare mode varchar;
offs := xpath_eval ('./@offset', tree, 1);
lim := xpath_eval ('./@limit', tree, 1);
http (sprintf (' %s %s %s %s ', fct_graph_clause (tree), fct_named_graph_clause (tree), fct_inf_clause (tree), fct_sas_clause (tree)), pre);
mode := fct_get_mode (tree, './@type');
-- geo-based conditionals force geo-list generation unless the old map mode is used
-- dbg_obj_print(full_tree);
declare geo_conds any;
geo_conds := xpath_eval ('//cond/@cond_t = ''near''', full_tree);
if (0 <> geo_conds and mode <> 'geo')
mode := 'geo-list';
fct_dbg_msg (sprintf('fct_view: view mode: %s', mode));
if ('list' = mode or 'propval-list' = mode)
{
http (sprintf ('select distinct ?s%d as ?c1 ?g', this_s), pre);
http (sprintf (' order by desc (?srank%d) ', this_s), post);
}
if ('list-count' = mode)
{
http (sprintf ('select ?s%d as ?c1 count (*) as ?c2 ', this_s), pre);
http (sprintf (' group by ?s%d order by desc 2', this_s), post);
}
if ('entities-list' = mode)
{
http (sprintf ('select distinct ?s%d as ?c1 ', this_s), pre);
http (sprintf (' order by desc (?srank%d) ', this_s), post);
}
if ('properties' = mode)
{
if (length (fct_inf_clause (tree)) > 0)
http (sprintf ('select ?s%dp as ?c1 count (distinct (?s%d)) as ?c2 ', this_s, this_s), pre);
else
http (sprintf ('select ?s%dp as ?c1 count (*) as ?c2 ', this_s), pre);
http (sprintf (' ?s%d ?s%dp ?s%do .', this_s, this_s, this_s), txt);
http (sprintf (' group by ?s%dp order by desc 2', this_s), post);
}
if ('properties-in' = mode)
{
http (sprintf ('select ?s%dip as ?c1 count (*) as ?c2 ', this_s), pre);
http (sprintf (' ?s%do ?s%dip ?s%d .', this_s, this_s, this_s), txt);
http (sprintf (' group by ?s%dip order by desc 2', this_s), post);
}
if ('text-properties' = mode)
{
http (sprintf ('select ?s%dtextp as ?c1 count (*) as ?c2 ', this_s), pre);
http (sprintf (' group by ?s%dtextp order by desc 2', this_s), post);
}
if ('classes' = mode)
{
if (length (fct_inf_clause (tree)) > 0)
http (sprintf ('select ?s%dc as ?c1 count (distinct (?s%d)) as ?c2 ', this_s, this_s), pre);
else
http (sprintf ('select ?s%dc as ?c1 count (*) as ?c2 ', this_s), pre);
http (sprintf (' ?s%d a ?s%dc .', this_s, this_s), txt);
http (sprintf (' group by ?s%dc order by desc 2', this_s), post);
}
if ('text' = mode or ('text-d' = mode and plain = 1))
{
declare exp any;
exp := cast (xpath_eval ('//text', tree) as varchar);
http (sprintf ('select ?s%d as ?c1, (bif:search_excerpt (bif:vector (%s), ?o%d)) as ?c2, ?sc, ?rank, ?g where {{{ select ?s%d, (?sc * 3e-1) as ?sc, ?o%d, (sql:rnk_scale (?srank%d)) as ?rank, ?g',
this_s,
element_split (exp),
this_s, this_s, this_s, this_s), pre);
http (sprintf (' order by desc (?sc * 3e-1 + sql:rnk_scale (?srank%d)) ', this_s), post);
fct_post (tree, post, lim, offs);
http ('}}}', post);
return;
}
if ('text-d' = mode)
{
declare exp any;
exp := charset_recode (xpath_eval ('string (//text)', tree), '_WIDE_', 'UTF-8');
-- dbg_obj_print (exp);
-- dbg_obj_print (element_split(exp));
http (sprintf ('select
( ( ( (?c1, ?sm, ?g1)), (%s))) as ?res where { {
select ((?s%d)) as ?c1, ( (?srank%d, (?s%dtextp), (?o%d), ?sc ) ) as ?sm, (?g) as ?g1', element_split (exp), this_s, this_s, this_s, this_s), pre);
http (sprintf ('group by ?s%d ?g order by desc ( (( (?srank%d, (?s%dtextp), (?o%d), ?sc ) ) ) )', this_s, this_s, this_s, this_s), post);
fct_post (tree, post, lim, offs);
http ('}}', post);
return;
}
if ('graphs' = mode)
{
http ('select ?g as ?c1, count(*) as ?c2 ', pre);
http (' order by desc (2) ' , post);
}
if ('geo' = mode or 'geo-list' = mode)
{
declare loc any;
loc := xpath_eval ('@location-prop', tree);
if (loc = 'any')
loc := '?anyloc';
if (length (loc) > 1)
{
http (sprintf ('select distinct ?location as ?c1 ?lat%d as ?c2 ?lng%d as ?c3 ',
this_s, this_s, this_s), pre);
}
else
http (sprintf ('select distinct ?s%d as ?c1 ?lat%d as ?c2 ?lng%d as ?c3 ',
this_s, this_s, this_s), pre);
if (length (loc) < 2)
http (sprintf (' ?s%d geo:lat ?lat%d ; geo:long ?lng%d .',
this_s, this_s, this_s), txt);
else
http (sprintf (' ?s%d %s ?location . ?location geo:lat ?lat%d ; geo:long ?lng%d .',
this_s, loc, this_s, this_s), txt);
}
fct_post (tree, post, lim, offs);
}
;
create procedure fct_esc_lit (in val any)
{
--no_c_escapes+
return replace (val, '"', '\"');
}
;
create procedure
fct_literal (in tree any)
{
declare val, dtp, lang varchar;
dtp := cast (xpath_eval ('./@datatype', tree) as varchar);
lang := cast (xpath_eval ('./@lang', tree) as varchar);
val := cast (xpath_eval ('./@val', tree) as varchar);
if (0 = val or val is null) val := cast (tree as varchar);
fct_dbg_msg (sprintf('fct_literal: val:%s, dtp:%s, lang:%s', val, dtp, lang));
if (lang is not null and lang <> '')
return sprintf ('"""%s"""@%s', fct_esc_lit (val), lang);
if (dtp = 'http://www.openlinksw.com/schemas/facets/dtp/plainstring')
return sprintf ('"""%s"""', fct_esc_lit (val));
if (val like '"%"^^')
{
declare arr any;
arr := sprintf_inverse (val, '"%s"^^', 0);
if (length (arr) > 0)
return sprintf ('<%s>', arr[0]);
}
if (dtp = '' or dtp is null or dtp like '%nteger' or dtp like '%ouble' or dtp like '%loat' or dtp like '%nt')
return val;
if ('uri' = dtp or 'url' = dtp or 'iri' = dtp) {
return sprintf ('<%s>', val);
}
return sprintf ('"%s"^^<%s>', val, dtp);
}
;
create procedure
fct_cond (in tree any, in this_s int, in txt any)
{
declare val, dtp, lang, neg, cond_t any;
val := fct_literal (tree);
cond_t := xpath_eval ('./@type', tree);
fct_dbg_msg (sprintf ('fct_cond: type: %s', cond_t));
if ('range' = cond_t or 'neg_range' = cond_t) {
return fct_cond_range (tree, this_s, txt); -- ranges are handled elsewhere
}
if ('in' = cond_t or 'not_in' = cond_t) {
return fct_cond_in (tree, this_s, txt); -- so is IN
}
if ('near' = cond_t) {
return fct_cond_near (tree, this_s, txt); -- and NEAR
}
if ('contains' = cond_t) {
return fct_cond_contains (tree, this_s, txt);
}
declare t_s varchar;
t_s := sprintf ('?s%d', this_s);
declare flt_inner varchar;
flt_inner := sprintf (fct_cond_fmt(cond_t), t_s, val);
-- dbg_printf ('fct_cond: inner: %s', flt_inner);
if (neg = 'on')
http (sprintf (' filter (! (%s)) . ', flt_inner), txt);
else
http (sprintf (' filter (%s) . ', flt_inner), txt);
return;
}
;
create procedure
fct_value (in tree any, in this_s int, in txt any)
{
declare val, dtp, op any;
val := fct_literal (tree);
op := xpath_eval ('./@op', tree);
if (0 = op or op is null)
op := '=';
declare t_s varchar;
t_s := sprintf ('?s%d', this_s);
http (sprintf (' filter (%s %s %s) .', t_s, op, val), txt);
return;
}
;
-- side effect warning: unrecognized conds become eq
create procedure
fct_cond_fmt (in cond_t varchar)
{
if (cond_t = 'eq') return '%s = %s';
if (cond_t = 'neq') return '%s != %s';
if (cond_t = 'lt') return '%s < %s';
if (cond_t = 'gt') return '%s > %s';
if (cond_t = 'gte') return '%s >= %s';
if (cond_t = 'lte') return '%s <= %s';
return '%s = %s';
}
;
create procedure
fct_cond_range (in tree any, in this_s int, in txt any)
{
declare cond_t, neg, lo, hi any;
cond_t := xpath_eval ('./@type', tree);
neg := xpath_eval ('./@neg', tree);
lo := xpath_eval ('./@lo', tree);
hi := xpath_eval ('./@hi', tree);
declare flt_inner, flt_cl varchar;
-- fct_dbg_msg (sprintf ('fct_cond_range: got lo: %s, hi: %s, neg: %s', lo, hi, cast (neg as varchar)));
if (lo <> '' and hi <> '') {
flt_inner := sprintf ('(?s%d >= %s && ?s%d <= %s)', this_s, lo, this_s, hi);
}
if (neg = 'on')
flt_cl := sprintf (' filter (! %s) .', flt_inner);
else
flt_cl := sprintf (' filter %s .', flt_inner);
http (flt_cl, txt);
return;
}
;
create procedure
fct_cond_contains (in tree any, in this_s int, in txt any)
{
declare val, neg, cond_t, txs_qr varchar;
declare wlimit int;
declare txs_arr any;
neg := xpath_eval ('./@neg', tree);
val := cast (xpath_eval ('.', tree) as varchar);
if (val <> '')
{
wlimit := registry_get ('fct_text_query_limit');
if (isstring (wlimit))
wlimit := atoi (wlimit);
if (0 = wlimit)
wlimit := 100;
txs_qr := fti_make_search_string_inner (charset_recode (xpath_eval ('string (.)', tree), '_WIDE_', 'UTF-8'), txs_arr);
if (length (txs_arr) > wlimit)
signal ('22023', 'The request is too large');
if ('no' <> neg)
{
http (sprintf (' ?s%d bif:contains ''%s'' .', this_s, txs_qr), txt);
}
else
{
http (sprintf (' filter (! bif:contains (?s%d, ''"%s"'')) .', this_s, val), txt);
}
}
}
;
create procedure
fct_cond_in (in tree any, in this_s int, in txt any) {
declare v any;
declare v_str varchar;
declare i int;
declare neg any;
neg := xpath_eval ('./@neg', tree);
v := xpath_eval ('./cond-parm', tree, 0);
if (0 = length(v)) return;
for (i := 0; i < length(v); i := i + 1) {
fct_dbg_msg (sprintf ('val: %s\n', cast (xpath_eval ('./text()', v[i]) as varchar)));
if (i = 0) {
v_str := fct_literal (v[i]);
}
else
v_str := v_str || ',' || fct_literal (v[i]);
};
fct_dbg_msg (sprintf ('fct_cond_in: v_str: %s', v_str));
http (sprintf (' filter (%s?s%d in (%s)).',
case when neg = '1' then '! ' else '' end,
this_s,
v_str), txt);
}
;
create procedure
fct_cond_near (in tree any, in this_s int, in txt any) {
declare v any;
declare v_str varchar;
declare i int;
declare lon, lat float;
declare d int;
declare prop varchar;
fct_dbg_msg (sprintf ('fct_cond_near.', lon, lat, d));
lon := xpath_eval ('./@lon', tree, 0);
lat := xpath_eval ('./@lat', tree, 0);
d := xpath_eval ('./@d', tree, 0);
prop := xpath_eval ('./@location-prop', tree, 0);
if (length(lon) = 0 or length(lat) = 0 or length (d) = 0) return;
lon := aref (lon, 0);
lat := aref (lat, 0);
d := cast (aref (d, 0) as int);
prop := aref (prop, 0);
if (lon = '' or lat = '') return;
fct_dbg_msg (sprintf ('fct_cond_near: lon:%s, lat:%s, dist: %d', lon, lat, d));
if (length (prop) < 2)
http (sprintf (' ?s%d geo:lat ?lat%d ; geo:long ?lng%d .', this_s, this_s, this_s), txt);
else
http (sprintf (' ?s%d %s ?location . ?location geo:lat ?lat%d ; geo:long ?lng%d .', this_s, prop, this_s, this_s), txt);
http (sprintf (' filter (bif:st_intersects (bif:st_point (xsd:float(?lng%d),xsd:float(?lat%d)), bif:st_point (%s,%s), %d)).',
this_s, this_s, lon, lat, d), txt);
}
;
create procedure
fct_curie_iri (in curie varchar)
{
declare pos int;
declare pref, ns, loc varchar;
pos := strchr (curie, ':');
if (pos is null)
return null;
pref := subseq (curie, 0, pos);
loc := subseq (curie, pos + 1);
ns := __xml_get_ns_uri (pref, 2);
if (ns is null)
return null;
return ns || loc;
}
;
create procedure
fct_curie (in curie varchar)
{
if (curie like '\\[%:%\\]')
{
declare tmp varchar;
tmp := trim (curie, '[]');
tmp := fct_curie_iri (tmp);
if (tmp is not null)
curie := tmp;
}
return curie;
}
;
create procedure
fct_text_1 (in tree any,
in this_s int,
inout max_s int,
in txt any,
in pre any,
in post any,
in full_tree any,
in plain integer := 0)
{
declare c any;
declare i, len int;
c := xpath_eval ('./node()', tree, 0);
for (i := 0; i < length (c); i := i + 1)
{
fct_text (c[i], this_s, max_s, txt, pre, post, full_tree, plain);
}
}
;
create procedure
fct_text (in tree any,
in this_s int,
inout max_s int,
in txt any,
in pre any,
in post any,
in full_tree any,
in plain integer := 0)
{
declare n varchar;
declare pos integer;
pos := fct_view_pos(tree) + 1;
n := cast (xpath_eval ('name ()', tree, 1) as varchar);
-- fct_dbg_msg (sprintf('fct_text pre: %s, post: %s', string_output_string(pre), string_output_string(post)));
-- fct_dbg_msg (sprintf(' n: %s', n));
-- dbg_obj_print (tree);
if ('class' = n)
{
declare ciri varchar;
ciri := fct_curie (cast (xpath_eval ('./@iri', tree) as varchar));
fct_dbg_msg (sprintf ('class: %s', cast (ciri as varchar)));
if (cast (xpath_eval ('./@exclude', tree) as varchar) = 'yes')
{
http (sprintf (' filter not exists { ?s%d a <%s> } .', this_s, ciri), txt);
}
else if (ciri is null)
{
http (sprintf ('?s%d a ?s%d . ', this_s, this_s + 1), txt);
}
else
{
http (sprintf ('?s%d a <%s> . ', this_s, ciri), txt);
}
return;
}
if ('query' = n)
{
max_s := 1;
fct_text_1 (tree, 1, max_s, txt, pre, post, full_tree, plain);
return;
}
if (n = 'text')
{
declare prop, sc_opt, v, txs_qr varchar;
declare txs_arr any;
declare wlimit int;
v := cast (xpath_eval ('//view/@type', tree) as varchar);
prop := cast (xpath_eval ('./@property', tree, 1) as varchar);
-- fct_dbg_msg (printf ('prop: %s', coalesce(prop, 'NULL')));
if ('text' = v or 'text-d' = v)
sc_opt := ' option (score ?sc) ';
else
sc_opt := '';
if (prop is not null)
prop := '<' || prop || '>';
else
prop := sprintf ('?s%dtextp', this_s);
wlimit := registry_get ('fct_text_query_limit');
if (isstring (wlimit))
wlimit := atoi (wlimit);
if (0 = wlimit)
wlimit := 100;
txs_qr := fti_make_search_string_inner (charset_recode (xpath_eval ('string (.)', tree), '_WIDE_', 'UTF-8'), txs_arr);
if (length (txs_arr) > wlimit)
signal ('22023', 'The request is too large');
http (sprintf (' quad map virtrdf:DefaultQuadMap { graph ?g { ?s%d %s ?o%d . ?o%d bif:contains ''%s'' %s . }} ', this_s, prop, this_s, this_s, txs_qr, sc_opt), txt);
--dbg_obj_print_vars (pos, this_s);
if (pos = this_s and ('text' = v or 'text-d' = v))
http (sprintf (' optional { graph virtrdf:IRI_Rank_c { ?s%d virtrdf:IRI_Rank_rnk_c_int ?srank%d . } } ', this_s, this_s), txt);
}
if ('property' = n)
{
declare new_s int;
declare piri varchar;
declare flt_expr, v varchar;
max_s := max_s + 1;
new_s := max_s;
piri := fct_curie (cast (xpath_eval ('./@iri', tree, 1) as varchar));
v := cast (xpath_eval ('//view/@type', tree) as varchar);
-- fct_dbg_msg (sprintf ('property: <%s>', piri));
if (cast (xpath_eval ('./@exclude', tree) as varchar) = 'yes')
{
http (sprintf (' filter not exists { ?s%d <%s> ?v%d } .', this_s, piri, new_s), txt);
max_s := max_s - 1;
new_s := max_s;
fct_text_1 (tree, new_s, max_s, txt, pre, post, full_tree, plain);
return;
}
else
{
http (sprintf (' quad map virtrdf:DefaultQuadMap { ?s%d <%s> ?s%d . }', this_s, piri, new_s), txt);
if (xpath_eval ('./following-sibling::view[@type="list"]', tree) is not null)
http (sprintf (' optional { graph virtrdf:IRI_Rank_c { ?s%d virtrdf:IRI_Rank_rnk_c_int ?srank%d . } } ', this_s, this_s), txt);
--else if (xpath_eval ('./view[@type="list"]', tree) is not null)
else if (xpath_eval ('./*[1][local-name()="view" and @type="list"]', tree) is not null)
http (sprintf (' optional { graph virtrdf:IRI_Rank_c { ?s%d virtrdf:IRI_Rank_rnk_c_int ?srank%d . filter isIRI (?s%d) } } ', new_s, new_s, new_s), txt);
fct_text_1 (tree, new_s, max_s, txt, pre, post, full_tree, plain);
}
}
if ('property-of' = n)
{
declare new_s int;
max_s := max_s + 1;
new_s := max_s;
http (sprintf (' quad map virtrdf:DefaultQuadMap { ?s%d <%s> ?s%d . }', new_s, fct_curie (cast (xpath_eval ('./@iri', tree, 1) as varchar)), this_s), txt);
if (xpath_eval ('./following-sibling::view[@type="list"]', tree) is not null)
http (sprintf (' optional { graph virtrdf:IRI_Rank_c { ?s%d virtrdf:IRI_Rank_rnk_c_int ?srank%d . filter isIRI (?s%d) } } ', this_s, this_s, this_s), txt);
else if (xpath_eval ('./*[1][local-name()="view" and @type="list"]', tree) is not null)
http (sprintf (' optional { graph virtrdf:IRI_Rank_c { ?s%d virtrdf:IRI_Rank_rnk_c_int ?srank%d . } } ', new_s, new_s), txt);
fct_text_1 (tree, new_s, max_s, txt, pre, post, full_tree, plain);
}
if ('value' = n)
{
fct_value (tree, this_s, txt);
}
if ('cond' = n)
{
fct_chk_any_prop (tree, this_s, max_s, txt);
fct_cond (tree, this_s, txt);
}
if ('cond-range' = n)
{
fct_chk_any_prop (tree, this_s, max_s, txt);
fct_cond_range (tree, this_s, txt);
}
if ('view' = n)
{
fct_view (tree, this_s, txt, pre, post, full_tree, plain);
}
}
;
create procedure
fct_chk_any_prop (in tree any, inout this_s int, inout max_s int, in txt any)
{
if (0 = xpath_eval ('count (./ancestor::*[name()=''property''])+ count(./ancestor::*[name()=''property-of'']) + count(./preceding::*[name()=''class'']) ', tree, 1))
{
declare dtp varchar;
dtp := xpath_eval ('./@dtp', tree, 1);
declare new_s int;
max_s := max_s + 1;
new_s := max_s;
http (sprintf ('?s%d ?s%dcondp ?s%d .', this_s, this_s, new_s), txt);
this_s := max_s;
}
}
;
create procedure
fct_query (in tree any, in plain integer := 0)
{
declare s, add_graph int;
declare txt, pre, post any;
if (isstring (tree))
tree := xtree_doc (tree);
txt := string_output ();
pre := string_output ();
post := string_output ();
s := 0;
add_graph := 0;
if (xpath_eval ('//view[@type="graphs"]', tree) is not null or
xpath_eval ('//view[@type="text"]', tree) is not null or
xpath_eval ('//view[@type="text-d"]', tree) is not null
or xpath_eval ('//property[view[@type="list"]]', tree) is not null
or xpath_eval ('//property-of[view[@type="list"]]', tree) is not null
)
{
add_graph := 1;
http (' define input:storage virtrdf:IRI_Rank_Storage ', pre);
}
fct_text (xpath_eval ('//query', tree), 0, s, txt, pre, post, tree, plain);
http (' where {', pre);
--if (add_graph) http (' quad map virtrdf:DefaultQuadMap { graph ?g { ', pre);
http (txt, pre);
http (' }', pre);
--if (add_graph) http (' } } ', pre);
http (post, pre);
return string_output_string (pre);
}
;
create procedure
fct_test (in str varchar, in timeout int := 0)
{
declare sqls, msg varchar;
declare start_time int;
declare reply, tree, md, res, qr, qr2 any;
declare cplete varchar;
tree := xtree_doc (str);
qr := fct_query (xpath_eval ('//query', tree, 1));
qr2 := fct_xml_wrap (tree, qr);
set result_timeout = timeout;
sqls := '00000';
start_time := msec_time ();
exec (qr2, sqls, msg, vector (), 0, md, res);
if (sqls <> '00000' and sqls <> 'S1TAT')
signal (sqls, msg);
if (sqls = 'S1TAT') {
cplete := 'yes';
}
reply := xmlelement ("facets", xmlelement ("sparql", qr), xmlelement ("time", msec_time () - start_time),
xmlelement ("complete", cplete),
xmlelement ("db-activity", db_activity ()), res[0][0]);
-- dbg_obj_print (reply);
return xslt (registry_get ('_fct_xslt_') || 'facet_text.xsl', reply);
}
;
registry_set ('fct_dbg_lvl', '0');
create procedure
fct_view_pos (in tree any)
{
declare c any;
declare i int;
c := xpath_eval ('//*[name() = "query" or
name () = "property" or
name () = "property-of"]', tree, 0);
for (i := 0; i < length (c); i := i + 1)
{
if (xpath_eval ('./view', c[i]) is not null)
return i;
}
return 0;
}
;
create procedure
fct_exec (in tree any,
in timeout int)
{
declare start_time, view3, inx, n_rows int;
declare sqls, msg, qr, qr2, act, query varchar;
declare md, res, results, more any;
declare tmp any;
declare offs, lim int;
set result_timeout = __min (timeout, atoi (registry_get ('fct_timeout_max')));
declare d_lvl integer;
d_lvl := atoi (registry_get ('fct_dbg_lvl'));
offs := xpath_eval ('//view/@offset', tree);
lim := xpath_eval ('//view/@limit', tree);
results := vector (null, null, null);
more := vector ();
if (xpath_eval ('//query[@view3="yes"]//view[@type="text"]', tree) is not null)
{
more := vector ('classes', 'properties');
}
sqls := '00000';
qr := fct_query (xpath_eval ('//query', tree, 1));
if (VAD_CHECK_VERSION ('VAL') is not null)
qr := fct_inject_val_graph_security_callback (qr);
query := qr;
qr2 := fct_xml_wrap (tree, qr);
start_time := msec_time ();
connection_set ('sparql_query', qr2);
if (d_lvl)
string_to_file ('q.log', sprintf('%s\n', query),-1);
set isolation = 'uncommitted';
exec (qr2, sqls, msg, vector (), vector ('use_cache', 1, 'max_rows', 0), md, res);
n_rows := row_count ();
act := db_activity ();
set result_timeout = 0;
if (sqls <> '00000' and sqls <> 'S1TAT')
signal (sqls, msg);
if (not isarray (res) or 0 = length (res) or not isarray (res[0]) or 0 = length (res[0]))
results[0] := xtree_doc ('');
else
results[0] := res[0][0];
inx := 1;
foreach (varchar tp in more) do
{
tree := XMLUpdate (tree, '/query/view/@type', tp, '/query/view/@limit', '40', '/query/view/@offset', '0');
qr := fct_query (xpath_eval ('//query', tree, 1));
qr2 := fct_xml_wrap (tree, qr);
sqls := '00000';
set result_timeout = __min (timeout, atoi (registry_get ('fct_timeout_max')));
-- dbg_printf ('qr2: %s', qr2);
exec (qr2, sqls, msg, vector (), 0, md, res);
n_rows := row_count ();
act := db_activity ();
set result_timeout = 0;
if (sqls <> '00000' and sqls <> 'S1TAT')
signal (sqls, msg);
if (isarray (res) and length (res) and isarray (res[0]) and length (res[0]))
{
tmp := res[0][0];
tmp := XMLUpdate (tmp, '/result/@type', tp);
results[inx] := tmp;
}
inx := inx + 1;
}
declare v_pos integer;
v_pos := fct_view_pos(tree);
if (sqls <> 'S1TAT' and n_rows = 0)
connection_set ('noresult', 1);
res := xmlelement ("facets", xmlelement ("sparql", query),
xmlelement ("time", msec_time () - start_time),
xmlelement ("complete", case when sqls = 'S1TAT' then 'no' else 'yes' end),
xmlelement ("timeout", __min (timeout * 2, atoi (registry_get ('fct_timeout_max')))),
xmlelement ("db-activity", act),
xmlelement ("processed", n_rows),
xmlelement ("view", xmlattributes (offs as "offset", lim as "limit", v_pos as "position")),
results[0], results[1], results[2]);
if (d_lvl)
string_to_file ('ret.xml', serialize_to_UTF8_xml (res), -1);
-- dbg_obj_print (results[0]);
return res;
}
;
create procedure
fct_inject_val_graph_security_callback (in qr varchar)
{
declare val_serviceId, val_sid, val_realm, val_uname, val_webidGraph varchar;
declare val_isRealUser integer;
declare val_cert any;
if (VAL.DBA.acls_enabled_for_scope (VAL.DBA.get_query_scope ()) = 0)
return qr;
val_realm := null;
val_webidGraph := uuid();
VAL.DBA.get_authentication_details_for_connection (
sid => val_sid,
serviceId => val_serviceId,
uname => val_uname,
isRealUser => val_isRealUser,
realm => val_realm,
cert => val_cert,
webidGraph => val_webidGraph );
connection_set ('val_sparql_rule_realm', val_realm);
if (not val_uname is null)
connection_set ('val_sparql_uname', val_uname);
connection_set ('val_sparql_webid_graph', val_webidGraph);
if (atod (sys_stat ('db_ver_string')) >= 7.5 and sys_stat ('enable_g_in_sec') = 1)
{
connection_set ('SPARQLUserId', 'VAL_SPARQL_ADMIN_G_CTX');
VAL.DBA.set_graph_context_query ( serviceId=>val_serviceId, realm=>val_sid, certificate=>val_cert, webidGraph=>val_webidGraph);
}
else
{
qr := sprintf ('define sql:gs-app-callback "VAL_SPARQL_PERMS" define sql:gs-app-uid "%s" ', coalesce (val_serviceId, 'nobody')) || qr;
}
return qr;
}
;