--
--  $Id$
--
--  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
--  project.
--
--  Copyright (C) 1998-2018 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
--
--

create table DB.DBA.RDF_QUAD (
  G IRI_ID_8,
  S IRI_ID_8,
  P IRI_ID_8,
  O any,
  primary key (P, S, O, G) column
  )
alter index RDF_QUAD on DB.DBA.RDF_QUAD partition (S int (0hexffff00))

create distinct no primary key ref column index RDF_QUAD_SP on DB.DBA.RDF_QUAD (S, P) partition (S int (0hexffff00))
create column index RDF_QUAD_POGS on DB.DBA.RDF_QUAD (P, O, S, G) partition (O varchar (-1, 0hexffff))
create distinct no primary key ref column index RDF_QUAD_GS on DB.DBA.RDF_QUAD (G, S) partition (S int (0hexffff00))
create distinct no primary key ref column index RDF_QUAD_OP on DB.DBA.RDF_QUAD (O, P) partition (O varchar (-1, 0hexffff))
;

create table DB.DBA.RDF_QUAD_RECOV_TMP (
  G1 IRI_ID_8,  S1 IRI_ID_8,  P1 IRI_ID_8,  O1 any,  primary key (P1, S1, O1, G1) column)
alter index RDF_QUAD_RECOV_TMP on DB.DBA.RDF_QUAD_RECOV_TMP partition (S1 int (0hexffff00))
create column index RDF_QUAD_RECOV_TMP_POGS on DB.DBA.RDF_QUAD_RECOV_TMP (P1, O1, G1, S1) partition (O1 varchar (-1, 0hexffff))
create distinct no primary key ref column index RDF_QUAD_RECOV_TMP_OP on DB.DBA.RDF_QUAD_RECOV_TMP (O1, P1) partition (O1 varchar (-1, 0hexffff))
;

create function DB.DBA.RDF_MAKE_IID_OF_QNAME_SAFE (in qname any) returns IRI_ID
{
  return iri_to_id_nosignal (qname);
}
;

create function DB.DBA.RDF_MAKE_IID_OF_QNAME_COMP (in qname any) returns IRI_ID
{
  return iri_to_id_nosignal (qname, 0);
}
;

create function DB.DBA.RDF_QNAME_OF_IID (in iid IRI_ID) returns varchar -- DEPRECATED
{
  return id_to_iri_nosignal (iid);
}
;

DB.DBA.RDF_MAKE_IID_OF_QNAME_SAFE (null)
;

DB.DBA.RDF_MAKE_IID_OF_QNAME_COMP (null)
;

DB.DBA.RDF_QNAME_OF_IID (null)
;

--create trigger DB.DBA.RDF_QUAD_O_AUDIT before insert on DB.DBA.RDF_QUAD
--{
--  if (not rdf_box_is_storeable (O))
--    signal ('RDFXX', 'non-storeable O');
--}
--;

create table DB.DBA.RDF_OBJ (
  RO_ID bigint primary key,
  RO_VAL varchar not null,
  RO_LONG long varchar,
  RO_FLAGS smallint not null default 0,
  RO_DT_AND_LANG integer not null default 16843009 compress any
)
alter index RDF_OBJ on RDF_OBJ partition (RO_ID int (0hexffff00))

create index RO_VAL on DB.DBA.RDF_OBJ (RO_VAL, RO_DT_AND_LANG)
 partition (RO_VAL varchar (-4, 0hexffff))
;


create table DB.DBA.RO_START (RS_START varchar, RS_DT_AND_LANG int, RS_RO_ID any,
  primary key (RS_START, RS_DT_AND_LANG, RS_RO_ID))
alter index RO_START on DB.DBA.RO_START partition (RS_RO_ID varchar (-1, 0hexffff))
;


--create table DB.DBA.RDF_FT (
--  RF_ID bigint primary key,
--  RF_O any)
--alter index RDF_FT on RDF_FT partition (RF_ID int (0hexffff00))
--create index RF_O on RDF_FT (RF_O) partition (RF_O varchar  (-1, 0hexffff))
--;

create table DB.DBA.RDF_DATATYPE (
  RDT_IID IRI_ID_8 not null primary key,
  RDT_TWOBYTE integer not null unique,
  RDT_QNAME varchar not null unique )
alter index RDF_DATATYPE on RDF_DATATYPE partition cluster replicated
alter index DB_DBA_RDF_DATATYPE_UNQC_RDT_TWOBYTE   on RDF_DATATYPE partition cluster replicated
alter index DB_DBA_RDF_DATATYPE_UNQC_RDT_QNAME on RDF_DATATYPE partition cluster replicated
;

select count (rdf_cache_id ('t', RDT_QNAME, RDT_TWOBYTE)) from DB.DBA.RDF_DATATYPE
;

create table DB.DBA.RDF_LANGUAGE (
  RL_ID varchar not null primary key,
  RL_TWOBYTE integer not null unique )
alter index RDF_LANGUAGE on RDF_LANGUAGE  partition cluster replicated
alter index DB_DBA_RDF_LANGUAGE_UNQC_RL_TWOBYTE on RDF_LANGUAGE  partition cluster replicated
;

select count (rdf_cache_id ('l', RL_ID, RL_TWOBYTE)) from DB.DBA.RDF_LANGUAGE
;

create table DB.DBA.SYS_SPARQL_HOST (
  SH_HOST	varchar not null primary key,
  SH_GRAPH_URI	varchar,
  SH_USER_URI	varchar,
  SH_BASE_URI	varchar,
  SH_DEFINES	long varchar
)
;

alter table DB.DBA.SYS_SPARQL_HOST add SH_BASE_URI varchar
;

create table DB.DBA.RDF_OBJ_FT_RULES (
  ROFR_G varchar not null,
  ROFR_P varchar not null,
  ROFR_REASON varchar not null,
  primary key (ROFR_G, ROFR_P, ROFR_REASON) )
alter index RDF_OBJ_FT_RULES on RDF_OBJ_FT_RULES partition cluster replicated
;

create table DB.DBA.SYS_SPARQL_SW_LOG (
    PL_SERVER varchar,
    PL_URI    varchar,
    PL_TS     timestamp,
    PL_RC     varchar,
    PL_MSG    long varchar,
    primary key (PL_SERVER, PL_URI, PL_TS))
;

create table DB.DBA.SYS_XML_PERSISTENT_NS_DECL
(
  NS_PREFIX varchar not null primary key,
  NS_URL varchar not null
)
alter index SYS_XML_PERSISTENT_NS_DECL on SYS_XML_PERSISTENT_NS_DECL partition cluster replicated
;

create table DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH
(
  REC_GRAPH_IID IRI_ID not null primary key
)
alter index RDF_EXPLICITLY_CREATED_GRAPH on RDF_EXPLICITLY_CREATED_GRAPH partition cluster replicated
;

create table RDF_GEO (X real no compress, Y real no compress,X2 real no compress, Y2 real no compress, ID bigint no compress, primary key (X, Y, X2, Y2, ID))
alter index RDF_GEO on RDF_GEO partition (ID int (0hexffff00))
;

create table DB.DBA.RDF_LABEL (RL_O any primary key, RL_RO_ID bigint, RL_TEXT varchar, RL_LANG int)
alter index RDF_LABEL on RDF_LABEL partition (RL_O varchar (-1, 0hexffff))
create index RDF_LABEL_TEXT on RDF_LABEL (RL_TEXT, RL_O) partition (RL_TEXT varchar (6, 0hexffff))
;

create table DB.DBA.RDF_QUAD_DELETE_QUEUE (
  EVENT_ID bigint not null,
  RULE_ID bigint not null,
  QG IRI_ID not null,
  QS IRI_ID not null,
  QP IRI_ID not null,
  QO any not null,
  primary key (EVENT_ID, RULE_ID,  QG, QS, QP, QO)
)
;

create table DB.DBA.SYS_IDONLY_EMPTY
(
  ID integer not null primary key
)
;

create table DB.DBA.SYS_IDONLY_ONE
(
  ID integer not null primary key
)
;

insert soft DB.DBA.SYS_IDONLY_ONE (ID) values (0)
;

sequence_set ('RDF_URL_IID_NAMED', 1000000, 1)
;

sequence_set ('RDF_PREF_SEQ', 1, 1)
;

sequence_set ('RDF_URL_IID_BLANK', iri_id_num (min_bnode_iri_id ()), 1)
;

sequence_set ('RDF_URL_IID_NAMED_BLANK', iri_id_num (min_named_bnode_iri_id ()), 1)
;

sequence_set ('RDF_RO_ID', 1, 1)
;

sequence_set ('RDF_DATATYPE_TWOBYTE', 258, 1)
;

sequence_set ('RDF_LANGUAGE_TWOBYTE', 258, 1)
;

create procedure RDF_QUAD_FT_INIT ()
{
  if (not exists (select 1 from SYS_VT_INDEX where VI_COL = 'o'))
    {
      insert soft SYS_VT_INDEX (VI_TABLE, VI_INDEX, VI_COL, VI_ID_COL, VI_INDEX_TABLE, VI_ID_IS_PK, VI_OPTIONS)
	values ('DB.DBA.RDF_QUAD', 'RDF_QUAD_OP', 'O', 'O', 'DB.DBA.RDF_GEO', 1, 'GR');
      insert soft SYS_VT_INDEX (VI_TABLE, VI_INDEX, VI_COL, VI_ID_COL, VI_INDEX_TABLE, VI_ID_IS_PK, VI_OPTIONS)
	values ('DB.DBA.RDF_QUAD', 'RDF_QUAD_OP', 'o', 'O', 'DB.DBA.RDF_OBJ_RO_FLAGS_WORDS', 1, null);
      __ddl_changed ('DB.DBA.RDF_QUAD');
    }
}
;

create procedure DB.DBA.RDF_OBJ_RO_FLAGS_INDEX_HOOK (inout vtb any, inout d_id any)
{
  if (cl_current_slice () = 0hexffff)
{
  for (select RO_LONG, RO_VAL, RO_FLAGS
	 from DB.DBA.RDF_OBJ  where RO_ID=d_id and bit_and (RO_FLAGS, 1)) do
    {
      if (bit_and (RO_FLAGS, 2))
        vt_batch_feed (vtb, xml_tree_doc (__xml_deserialize_packed (RO_LONG)), 0);
      else
        vt_batch_feed (vtb, coalesce (RO_LONG, RO_VAL), 0);
    }
 }
  else
    {
  for (select RO_LONG, RO_VAL, RO_FLAGS
	 from DB.DBA.RDF_OBJ table option (no cluster) where RO_ID=d_id and bit_and (RO_FLAGS, 1)) do
    {
      if (bit_and (RO_FLAGS, 2))
        vt_batch_feed (vtb, xml_tree_doc (__xml_deserialize_packed (RO_LONG)), 0);
      else
        vt_batch_feed (vtb, coalesce (RO_LONG, RO_VAL), 0);
    }
    }
  return 1;
}
;

create procedure DB.DBA.RDF_OBJ_RO_FLAGS_UNINDEX_HOOK (inout vtb any, inout d_id any)
{
  if (cl_current_slice () = 0hexffff)
    {
  for (select RO_LONG, RO_VAL, RO_FLAGS
	 from DB.DBA.RDF_OBJ  where RO_ID=d_id and bit_and (RO_FLAGS, 1)) do
    {
      if (bit_and (RO_FLAGS, 2))
        vt_batch_feed (vtb, xml_tree_doc (__xml_deserialize_packed (RO_LONG)), 1);
      else
        vt_batch_feed (vtb, coalesce (RO_LONG, RO_VAL), 1);
    }
    }
  else
    {
  for (select RO_LONG, RO_VAL, RO_FLAGS
	 from DB.DBA.RDF_OBJ table option (no cluster) where RO_ID=d_id and bit_and (RO_FLAGS, 1)) do
    {
      if (bit_and (RO_FLAGS, 2))
        vt_batch_feed (vtb, xml_tree_doc (__xml_deserialize_packed (RO_LONG)), 1);
      else
        vt_batch_feed (vtb, coalesce (RO_LONG, RO_VAL), 1);
    }
    }
  return 1;
}
;

create procedure sparql_exec_quiet (in expn varchar)
{
  declare sta, msg varchar;
  exec (expn, sta, msg);
}
;

sparql_exec_quiet ('DB.DBA.vt_create_text_index (
      fix_identifier_case (''DB.DBA.RDF_OBJ''),
      fix_identifier_case (''RO_FLAGS''),
      fix_identifier_case (''RO_ID''),
      0, 0, vector (), 1, ''*ini*'', ''UTF-8-QR'')')
;

sparql_exec_quiet ('DB.DBA.vt_batch_update (fix_identifier_case (''DB.DBA.RDF_OBJ''), ''ON'', 1)')
;

--sparql_exec_quiet ('alter index VTLOG_DB_DBA_RDF_OBJ on VTLOG_DB_DBA_RDF_OBJ partition (VTLOG_RO_ID int (0hexffff00))')
--;

--!AWK PUBLIC
create function DB.DBA.XML_SET_NS_DECL (in prefix varchar, in url varchar, in persist integer := 1) returns integer
{
  declare res integer;
  res := __xml_set_ns_decl (prefix, url, persist);
  if (bit_and (res, 2))
    {
      declare exit handler for sqlstate '*' { __xml_remove_ns_by_prefix (prefix, persist); resignal; };
      if (exists (select 1 from DB.DBA.SYS_XML_PERSISTENT_NS_DECL where NS_PREFIX = prefix and NS_URL = url))
	return;
      delete from DB.DBA.SYS_XML_PERSISTENT_NS_DECL where NS_PREFIX = prefix;
      insert into DB.DBA.SYS_XML_PERSISTENT_NS_DECL (NS_PREFIX, NS_URL) values (prefix, url);
      commit work;
    }
  return res;
}
;

--!AWK PUBLIC
create procedure DB.DBA.XML_REMOVE_NS_BY_PREFIX (in prefix varchar, in persist integer := 1)
{
  declare res integer;
  __xml_remove_ns_by_prefix (prefix, persist);
  if (bit_and (persist, 2))
    {
      whenever sqlstate '*' goto again;
again:
      delete from DB.DBA.SYS_XML_PERSISTENT_NS_DECL where NS_PREFIX=prefix;
      commit work;
    }
}
;

--!AWK PUBLIC
create procedure DB.DBA.XML_CLEAR_ALL_NS_DECLS (in persist integer := 1)
{
  declare res integer;
  __xml_clear_all_ns_decls (persist);
  if (bit_and (persist, 2))
    {
      whenever sqlstate '*' goto again;
again:
      delete from DB.DBA.SYS_XML_PERSISTENT_NS_DECL;
      commit work;
    }
}
;

--!AWK PUBLIC
create procedure DB.DBA.XML_SELECT_ALL_NS_DECLS (in persist integer := 3)
{
  declare decls any;
  declare ctr, len integer;
  declare PREFIX, URI varchar;
  decls := __xml_get_all_ns_decls (persist);
  result_names (PREFIX, URI);
  len := length (decls);
  for (ctr := 0; ctr < len; ctr := ctr + 2)
    result (decls[ctr], decls[ctr+1]);
}
;

create procedure DB.DBA.XML_LOAD_ALL_NS_DECLS ()
{
  for (select NS_PREFIX, NS_URL from DB.DBA.SYS_XML_PERSISTENT_NS_DECL) do
    {
      __xml_set_ns_decl (NS_PREFIX, NS_URL, 2);
    }
  DB.DBA.XML_SET_NS_DECL (	'bif'		, 'bif:'	, 2);
  DB.DBA.XML_SET_NS_DECL (	'dawgt'		, 'http://www.w3.org/2001/sw/DataAccess/tests/test-dawg#'	, 2);
  DB.DBA.XML_SET_NS_DECL (	'dbpedia'	, 'http://dbpedia.org/resource/'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'dbpprop'	, 'http://dbpedia.org/property/'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'dc'		, 'http://purl.org/dc/elements/1.1/'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'go'		, 'http://purl.org/obo/owl/GO#'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'geo'		, 'http://www.w3.org/2003/01/geo/wgs84_pos#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'fn'		, 'http://www.w3.org/2005/xpath-functions/#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'foaf'		, 'http://xmlns.com/foaf/0.1/'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'obo'		, 'http://www.geneontology.org/formats/oboInOwl#'		, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogc'		, 'http://www.opengis.net/'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogcgml'	, 'http://www.opengis.net/ont/gml#'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogcgs'		, 'http://www.opengis.net/ont/geosparql#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogcgsf'	, 'http://www.opengis.net/def/function/geosparql/'		, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogcgsr'	, 'http://www.opengis.net/def/rule/geosparql/'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'ogcsf'		, 'http://www.opengis.net/ont/sf#'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'owl'		, 'http://www.w3.org/2002/07/owl#'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'mesh'		, 'http://purl.org/commons/record/mesh/'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'math'		, 'http://www.w3.org/2000/10/swap/math#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'mf'		, 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#'	, 2);
  DB.DBA.XML_SET_NS_DECL (	'nci'		, 'http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#'		, 2);
  DB.DBA.XML_SET_NS_DECL (	'product'	, 'http://www.buy.com/rss/module/productV2/'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'protseq'	, 'http://purl.org/science/protein/bysequence/'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'rdf'		, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'rdfa'		, 'http://www.w3.org/ns/rdfa#'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'rdfdf'		, 'http://www.openlinksw.com/virtrdf-data-formats#'		, 2);
  DB.DBA.XML_SET_NS_DECL (	'rdfs'		, 'http://www.w3.org/2000/01/rdf-schema#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'sc'		, 'http://purl.org/science/owl/sciencecommons/'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'sd'		, 'http://www.w3.org/ns/sparql-service-description#'		, 2);
  DB.DBA.XML_SET_NS_DECL (	'sioc'		, 'http://rdfs.org/sioc/ns#'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'skos'		, 'http://www.w3.org/2004/02/skos/core#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'sql'		, 'sql:'							, 2);
  DB.DBA.XML_SET_NS_DECL (	'vcard'		, 'http://www.w3.org/2001/vcard-rdf/3.0#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'vcard2006'	, 'http://www.w3.org/2006/vcard/ns#'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'virtrdf'	, 'http://www.openlinksw.com/schemas/virtrdf#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'virtcxml'	, 'http://www.openlinksw.com/schemas/virtcxml#'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'void'		, 'http://rdfs.org/ns/void#'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'xf'		, 'http://www.w3.org/2004/07/xpath-functions'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'xml'		, 'http://www.w3.org/XML/1998/namespace'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'xsd'		, 'http://www.w3.org/2001/XMLSchema#'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'xsl10'		, 'http://www.w3.org/XSL/Transform/1.0'				, 2);
  DB.DBA.XML_SET_NS_DECL (	'xsl1999'	, 'http://www.w3.org/1999/XSL/Transform'			, 2);
  DB.DBA.XML_SET_NS_DECL (	'xslwd'		, 'http://www.w3.org/TR/WD-xsl'					, 2);
  DB.DBA.XML_SET_NS_DECL (	'yago'		, 'http://dbpedia.org/class/yago/'				, 2);
}
;

DB.DBA.XML_LOAD_ALL_NS_DECLS ()
;

rdf_inf_const_init ()
;

create procedure DB.DBA.RDF_LOAD_ALL_FT_RULES ()
{
  whenever sqlstate '*' goto again;
again:
  for (select ROFR_G as rule_g, ROFR_P as rule_p, ROFR_REASON as reason from DB.DBA.RDF_OBJ_FT_RULES) do
    {
      declare rule_g_iid, rule_p_iid IRI_ID;
      rule_g_iid := case (rule_g) when '' then null else iri_to_id (rule_g) end;
      rule_p_iid := case (rule_p) when '' then null else iri_to_id (rule_p) end;
      -- dbg_obj_princ ('__rdf_obj_ft_rule_add (', rule_g_iid, rule_p_iid, reason, ')');
      __rdf_obj_ft_rule_add (rule_g_iid, rule_p_iid, reason);
    }
}
;

DB.DBA.RDF_LOAD_ALL_FT_RULES ()
;

create procedure DB.DBA.RDF_REPL_START (in quiet integer := 0)
{
  if (repl_this_server () is null)
    return;
  if (isstring (registry_get ('DB.DBA.RDF_REPL')))
    {
      if (quiet)
        return;
      signal ('RDF99', 'RDF replication is already enabled');
    }
  for (select RGGM_MEMBER_IID from DB.DBA.RDF_GRAPH_GROUP_MEMBER
  where RGGM_GROUP_IID = iri_to_id (UNAME'http://www.openlinksw.com/schemas/virtrdf#rdf_repl_graph_group')
    and not __rgs_ack_cbk (RGGM_MEMBER_IID, __rdf_repl_uid(), 1) ) do
    {
      signal ('RDF99', 'RDF replication can not be enabled because it will violate security rules for read access to graph <' || id_to_iri(RGGM_MEMBER_IID) || '> by __rdf_repl account');
    }
  repl_publish ('__rdf_repl', '__rdf_repl.log');
  repl_text ('__rdf_repl', '__rdf_repl_flush_queue()');
  DB.DBA.RDF_GRAPH_GROUP_CREATE (UNAME'http://www.openlinksw.com/schemas/virtrdf#rdf_repl_graph_group', 1);
  DB.DBA.CL_EXEC ('registry_set (?,?)', vector ('DB.DBA.RDF_REPL', cast (now() as varchar)));
  exec ('checkpoint');
}
;

create procedure DB.DBA.RDF_REPL_STOP (in quiet integer := 0)
{
  if (not isstring (registry_get ('DB.DBA.RDF_REPL')))
    {
      if (quiet)
        return;
      signal ('RDF99', 'RDF replication is not enabled');
    }
  repl_unpublish ('__rdf_repl');
  DB.DBA.CL_EXEC ('registry_remove (?)', vector ('DB.DBA.RDF_REPL'));
}
;

create procedure DB.DBA.RDF_REPL_GRAPH_INS (in memb_iri varchar)
{
  declare memb_iid IRI_ID;
  memb_iid := iri_to_id (memb_iri);
  memb_iri := id_to_iri (memb_iid);
  DB.DBA.RDF_GRAPH_GROUP_INS (UNAME'http://www.openlinksw.com/schemas/virtrdf#rdf_repl_graph_group', memb_iri);
}
;

create procedure DB.DBA.RDF_REPL_GRAPH_DEL (in memb_iri varchar)
{
  declare memb_iid IRI_ID;
  DB.DBA.RDF_GRAPH_GROUP_DEL (UNAME'http://www.openlinksw.com/schemas/virtrdf#rdf_repl_graph_group', memb_iri);
}
;

create procedure DB.DBA.RDF_REPL_SYNC (in publisher varchar, in u varchar, in pwd varchar)
{
  declare lvl, stat integer;
  if (repl_this_server () is null)
    return;
  commit work;
retr:

  repl_sync (publisher, '__rdf_repl', u, pwd);
again:
  repl_status (publisher, '__rdf_repl', lvl, stat);
  if (0 = stat)
    {
      __rdf_repl_flush_queue();
      return;
    }
  if (1 = stat)
    {
      delay (0.1);
      goto again;
    }
  if (2 = stat)
    {
      __rdf_repl_flush_queue();
      return;
    }
  goto retr;
}
;


create procedure DB.DBA.RDF_REPL_INSERT_TRIPLES (in graph_iri varchar, inout triples any)
{
  declare ctr integer;
  for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
    {
      declare s_iri, p_iri, o_val, o_type, o_lang any;
      s_iri := iri_canonicalize (triples[ctr][0]);
      p_iri := iri_canonicalize (triples[ctr][1]);
      o_val := triples[ctr][2];
      if (isiri_id (o_val))
        __rdf_repl_quad (84, graph_iri, s_iri, p_iri, iri_canonicalize (o_val));
      else if (__tag of rdf_box <> __tag (o_val))
        __rdf_repl_quad (80, graph_iri, s_iri, p_iri, o_val);
      else
        {
          declare dt_twobyte, lang_twobyte integer;
          dt_twobyte := rdf_box_type (o_val);
          lang_twobyte := rdf_box_lang (o_val);
          if (257 <> dt_twobyte)
            __rdf_repl_quad (81, graph_iri, s_iri, p_iri, rdf_box_data (o_val), (select RDT_QNAME from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = dt_twobyte), NULL);
          else if (257 <> lang_twobyte)
            __rdf_repl_quad (82, graph_iri, s_iri, p_iri, rdf_box_data (o_val), NULL, (select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = lang_twobyte));
          else
            __rdf_repl_quad (80, graph_iri, s_iri, p_iri, rdf_box_data (o_val));
        }
    }
}
;

create procedure DB.DBA.RDF_REPL_DELETE_TRIPLES (in graph_iri varchar, inout triples any)
{
  declare ctr integer;
  for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
    {
      declare s_iri, p_iri, o_val, o_type, o_lang any;
      s_iri := iri_canonicalize (triples[ctr][0]);
      p_iri := iri_canonicalize (triples[ctr][1]);
      o_val := triples[ctr][2];
      if (isiri_id (o_val))
        __rdf_repl_quad (164, graph_iri, s_iri, p_iri, iri_canonicalize (o_val));
      else if (__tag of rdf_box <> __tag (o_val))
        __rdf_repl_quad (160, graph_iri, s_iri, p_iri, o_val);
      else
        {
          declare dt_twobyte, lang_twobyte integer;
          dt_twobyte := rdf_box_type (o_val);
          lang_twobyte := rdf_box_lang (o_val);
          if (257 <> dt_twobyte)
            __rdf_repl_quad (161, graph_iri, s_iri, p_iri, rdf_box_data (o_val), (select RDT_QNAME from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = dt_twobyte), NULL);
          else if (257 <> lang_twobyte)
            __rdf_repl_quad (162, graph_iri, s_iri, p_iri, rdf_box_data (o_val), NULL, (select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = lang_twobyte));
          else
            __rdf_repl_quad (160, graph_iri, s_iri, p_iri, rdf_box_data (o_val));
        }
    }
}
;

--!AFTER
create procedure DB.DBA.RDF_GLOBAL_RESET (in hard integer := 0)
{
  if (isstring (registry_get ('DB.DBA.RDF_REPL')))
    {
      signal ('42RDF', 'Can not make DB.DBA.RDF_GLOBAL_RESET while an RDF replication is enabled');
    }
--  checkpoint;
  __atomic (1);
  iri_id_cache_flush ();
  __rdf_obj_ft_rule_zap_all ();
  dict_zap (__rdf_graph_group_dict(), 2);
  dict_zap (__rdf_graph_group_of_privates_dict(), 2);
  dict_zap (__rdf_graph_default_perms_of_user_dict(0), 2);
  dict_zap (__rdf_graph_default_perms_of_user_dict(1), 2);
  dict_zap (__rdf_graph_public_perms_dict(), 2);
  for select RS_NAME from DB.DBA.SYS_RDF_SCHEMA do
    rdf_inf_clear (RS_NAME);
  delete from sys_rdf_schema;
  delete from DB.DBA.RDF_QUAD;
  delete from DB.DBA.RDF_OBJ_FT_RULES;
  delete from DB.DBA.RDF_GRAPH_GROUP;
  for (select __id2i(t.RGU_GRAPH_IID) as graph_iri from (select distinct RGU_GRAPH_IID from DB.DBA.RDF_GRAPH_USER) as t) do
    {
      if (graph_iri is not null)
        {
          jso_mark_affected (graph_iri);
          log_text ('jso_mark_affected (?)', graph_iri);
          jso_mark_affected (iri_canonicalize (graph_iri));
          log_text ('jso_mark_affected (?)', iri_canonicalize (graph_iri));
          log_text ('jso_mark_affected (iri_canonicalize (?))', graph_iri);
        }
    }
  for (select __id2i(t.RGGM_GROUP_IID) as group_iri from (select distinct RGGM_GROUP_IID from DB.DBA.RDF_GRAPH_GROUP_MEMBER) as t) do
    {
      if (group_iri is not null)
	{
	  jso_mark_affected (group_iri);
	  log_text ('jso_mark_affected (?)', group_iri);
	}
    }
  for (select __id2i(RGGM_MEMBER_IID) as memb_iri from DB.DBA.RDF_GRAPH_GROUP_MEMBER where RGGM_GROUP_IID = __i2id ('http://www.openlinksw.com/schemas/virtrdf#PrivateGraphs')) do
    {
      if (memb_iri is not null)
	{
	  jso_mark_affected (memb_iri);
	  log_text ('jso_mark_affected (?)', memb_iri);
	}
    }
  for (sparql define input:storage "" select distinct str (?qms) as ?qms_iri from virtrdf: where { ?qms a virtrdf:QuadStorage } ) do
    {
      if ("qms_iri" is not null)
	{
	  jso_mark_affected ("qms_iri");
	  log_text ('jso_mark_affected (?)', "qms_iri");
	}
    }
  jso_mark_affected ('http://www.openlinksw.com/schemas/virtrdf#PrivateGraphs');
  log_text ('jso_mark_affected (?)', 'http://www.openlinksw.com/schemas/virtrdf#PrivateGraphs');
  jso_mark_affected ('http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage');
  log_text ('jso_mark_affected (?)', 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage');
  jso_mark_affected ('http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap');
  log_text ('jso_mark_affected (?)', 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap');
  delete from DB.DBA.RDF_GRAPH_GROUP_MEMBER;
  delete from DB.DBA.RDF_GRAPH_USER;
  delete from DB.DBA.RDF_LABEL;
  delete from DB.DBA.RDF_GEO;
  commit work;
  if (hard)
    {
      --delete from DB.DBA.RDF_URL;
      delete from DB.DBA.RDF_IRI;
      delete from DB.DBA.RDF_PREFIX;
      delete from DB.DBA.RDF_OBJ;
      delete from DB.DBA.RO_START;
      delete from DB.DBA.RDF_DATATYPE;
      delete from DB.DBA.RDF_LANGUAGE;
      --__rdf_twobyte_cache_zap();
      --log_text ('__rdf_twobyte_cache_zap()');
      delete from DB.DBA.VTLOG_DB_DBA_RDF_OBJ;
      delete from DB.DBA.RDF_OBJ_RO_FLAGS_WORDS;
      sequence_set ('RDF_URL_IID_NAMED', 1000000, 0);
      sequence_set ('RDF_URL_IID_BLANK', iri_id_num (min_bnode_iri_id ()), 0);
      sequence_set ('RDF_URL_IID_NAMED_BLANK', iri_id_num (min_named_bnode_iri_id ()), 0);
      sequence_set ('RDF_PREF_SEQ', 1, 0);
      sequence_set ('RDF_RO_ID', 1, 0);
      sequence_set ('RDF_DATATYPE_TWOBYTE', 258, 0);
      sequence_set ('RDF_LANGUAGE_TWOBYTE', 258, 0);
      __atomic (0);
      exec ('checkpoint');
      raw_exit ();
    }
  sequence_set ('RDF_URL_IID_NAMED', 1000000, 1);
  sequence_set ('RDF_URL_IID_BLANK', iri_id_num (min_bnode_iri_id ()), 1);
  sequence_set ('RDF_URL_IID_NAMED_BLANK', iri_id_num (min_named_bnode_iri_id ()), 1);
  sequence_set ('RDF_PREF_SEQ', 1, 1);
  sequence_set ('RDF_RO_ID', 1, 1);
  sequence_set ('RDF_DATATYPE_TWOBYTE', 258, 1);
  sequence_set ('RDF_LANGUAGE_TWOBYTE', 258, 1);
  DB.DBA.RDF_LOAD_ALL_FT_RULES ();
  DB.DBA.TTLP (
    cast ( DB.DBA.XML_URI_GET (
        'http://www.openlinksw.com/sparql/virtrdf-data-formats.ttl', '' ) as varchar ),
    '', 'http://www.openlinksw.com/schemas/virtrdf#' );
  DB.DBA.TTLP (
    cast ( DB.DBA.XML_URI_GET (
        'http://www.openlinksw.com/sparql/virtrdf-quad-storages.ttl', '' ) as varchar ),
    '', 'http://www.openlinksw.com/schemas/virtrdf#' );
  delete from SYS_HTTP_SPONGE where HS_PARSER = 'DB.DBA.RDF_LOAD_HTTP_RESPONSE';
  commit work;
  sequence_set ('RDF_URL_IID_NAMED', 1010000, 1);
  sequence_set ('RDF_URL_IID_BLANK', iri_id_num (min_bnode_iri_id ()) + 10000, 1);
  sequence_set ('RDF_URL_IID_NAMED_BLANK', iri_id_num (min_named_bnode_iri_id ()) + 10000, 1);
  sequence_set ('RDF_PREF_SEQ', 101, 1);
  sequence_set ('RDF_RO_ID', 1001, 1);
  iri_id_cache_flush ();
  DB.DBA.SPARQL_RELOAD_QM_GRAPH ();
  __atomic (0);
  exec ('checkpoint');
}
;


-----
-- Handling of IRI IDs

create function DB.DBA.RDF_MAKE_IID_OF_QNAME (in qname varchar) returns IRI_ID
{
  return iri_to_id (qname);
}
;


create function DB.DBA.RDF_MAKE_IID_OF_LONG (in qname any) returns IRI_ID -- DEPRECATED
{
  if (isiri_id (qname))
    return qname;
  if (not isstring (qname))
    {
      if (__tag of rdf_box = __tag (qname) and rdf_box_is_complete (qname))
        qname := rdf_box_data (qname, 1);
      else
        qname := __rdf_strsqlval (qname);
    }
  return iri_to_id_nosignal (qname);
}
;

create function DB.DBA.RDF_MAKE_GRAPH_IIDS_OF_QNAMES (in qnames any) returns any
{
  if (__tag of vector <> __tag (qnames))
    return vector ();
  declare res_acc any;
  vectorbld_init (res_acc);
  foreach (any qname in qnames) do
    {
      declare iid IRI_ID;
      whenever sqlstate '*' goto skip_acc;
      iid := iri_to_id (qname, 0, 0);
      if (not isinteger (iid))
        vectorbld_acc (res_acc, iid);
skip_acc: ;
    }
  vectorbld_final (res_acc);
  return res_acc;
}
;

-----
-- Datatypes and languages

create function DB.DBA.RDF_TWOBYTE_OF_DATATYPE (in iid any) returns integer
{
  declare res integer;
  declare qname varchar;
  if (iid is null)
    return 257;
  if (not isiri_id (iid))
    {
      declare new_iid IRI_ID;
      new_iid := iri_to_id (iid);
      if (new_iid is NULL or new_iid >= min_bnode_iri_id ())
        signal ('RDFXX', 'Invalid datatype IRI_ID passes as an argument to DB.DBA.RDF_TWOBYTE_OF_DATATYPE()');
      iid := new_iid;
    }
  qname := id_to_iri (iid);
  res := rdf_cache_id ('t', qname);
  if (res)
    return res;
  whenever not found goto mknew;
  set isolation='committed';
  select RDT_TWOBYTE into res from DB.DBA.RDF_DATATYPE where RDT_IID = iid;
  return res;

mknew:
  set isolation='serializable';
  declare tb_cr cursor for select RDT_TWOBYTE from DB.DBA.RDF_DATATYPE where RDT_IID = iid;
  open tb_cr (exclusive);
  whenever not found goto mknew_ser;
  fetch tb_cr into res;
  return res;

mknew_ser:
  res := sequence_next ('RDF_DATATYPE_TWOBYTE');
  if (0 = bit_and (res, 255))
    {
      if (res = 0hex7F00)
        {
          sequence_set ('RDF_DATATYPE_TWOBYTE', 0hex7F00, 0);
          res := 0hex7F01;
          qname := 'http://www.openlinksw.com/schemas/virtrdf#Unsaved';
          iid := iri_to_id (qname);
          insert soft DB.DBA.RDF_DATATYPE
            (RDT_IID, RDT_TWOBYTE, RDT_QNAME)
          values (iid, res, qname);
          goto cache_and_log;
        }
      res := sequence_next ('RDF_DATATYPE_TWOBYTE');
    }
  insert into DB.DBA.RDF_DATATYPE
    (RDT_IID, RDT_TWOBYTE, RDT_QNAME)
  values (iid, res, qname);
cache_and_log:
  rdf_cache_id ('t', qname, res);
  log_text ('rdf_cache_id (\'t\', ?, ?)', qname, res);  --'
  return res;
}
;

create function DB.DBA.RDF_PRESET_TWOBYTES_OF_DATATYPES ()
{
  declare xsd_lnames any;
  xsd_lnames := vector (
    'ENTITY',
    'ENTITIES',
    'ID',
    'IDREF',
    'IDREFS',
    'NCName',
    'Name',
    'NMTOKEN',
    'NMTOKENS',
    'NOTATION',
    'QName',
    'any',
    'anyAtomicType',
    'anySimpleType',
    'anyType',
    'anyURI',
    'base64Binary',
    'boolean',
    'byte',
    'date',
    'dateTime',
    'dateTimeStamp',
    'dayTimeDuration',
    'decimal',
    'double',
    'duration',
    'float',
    'gDay',
    'gMonth',
    'gMonthDay',
    'gYear',
    'gYearMonth',
    'hexBinary',
    'int',
    'integer',
    'language',
    'long',
    'negativeInteger',
    'nonNegativeInteger',
    'nonPositiveInteger',
    'normalizedString',
    'positiveInteger',
    'short',
    'string',
    'time',
    'token',
    'unsignedByte',
    'unsignedInt',
    'unsignedLong',
    'unsignedShort',
    'yearMonthDuration' );
  foreach (varchar n in xsd_lnames) do
    {
      __dbf_set ('rb_type__xsd:' || n, DB.DBA.RDF_TWOBYTE_OF_DATATYPE (iri_to_id ('http://www.w3.org/2001/XMLSchema#' || n)));
    }
  commit work;
}
;

--!AFTER
DB.DBA.RDF_PRESET_TWOBYTES_OF_DATATYPES ()
;

create function DB.DBA.RDF_TWOBYTE_OF_LANGUAGE (in id varchar) returns integer
{
  declare res integer;
  if (id is null)
    return 257;
  id := lower (id);
  res := rdf_cache_id ('l', id);
  if (res)
    return res;
  whenever not found goto mknew;
  set isolation='committed';
  select RL_TWOBYTE into res from DB.DBA.RDF_LANGUAGE where RL_ID = id;
  return res;

mknew:
  set isolation='serializable';
  declare tb_cr cursor for select RL_TWOBYTE from DB.DBA.RDF_LANGUAGE where RL_ID = id;
  open tb_cr (exclusive);
  whenever not found goto mknew_ser;
  fetch tb_cr into res;
  return res;

mknew_ser:
  res := sequence_next ('RDF_LANGUAGE_TWOBYTE');
  if (0 = bit_and (res, 255))
    {
      if (res = 0hex7F00)
        {
          sequence_set ('RDF_LANGUAGE_TWOBYTE', 0hex7F00, 0);
          res := 0hex7F01;
          id := 'x-unsaved';
          insert soft DB.DBA.RDF_LANGUAGE (RL_ID, RL_TWOBYTE) values (id, res);
          goto cache_and_log;
        }
      res := sequence_next ('RDF_LANGUAGE_TWOBYTE');
    }
  insert into DB.DBA.RDF_LANGUAGE (RL_ID, RL_TWOBYTE) values (id, res);
cache_and_log:
  rdf_cache_id ('l', id, res);
  log_text ('rdf_cache_id (\'l\', ?, ?)', id, res); --'
  return res;
}
;

-----
-- Conversions from and to _table fields_ in short representation

create function DB.DBA.RQ_LONG_OF_O (in o_col any) returns any -- DEPRECATED
{
  return __rdf_long_of_obj (o_col);
}
;

create procedure DB.DBA.RDF_BOX_COMPLETE (inout o_col any) -- DEPRECATED
{
  __rdf_box_make_complete (o_col);
}
;

create function DB.DBA.RQ_SQLVAL_OF_O (in o_col any) returns any -- DEPRECATED
{
  return __rdf_sqlval_of_obj (o_col);
}
;

create function DB.DBA.RQ_BOOL_OF_O (in o_col any array) returns any -- DEPRECATED
{
  vectored;
  return sparql_ebv_int_of_sqlval (__ro2sq(o_col));
}
;

create function DB.DBA.RQ_SPARQL_EBV_OF_O (in o_col any array) returns any -- DEPRECATED
{
  vectored;
  return sparql_ebv_of_sqlval (__ro2sq(o_col));
}
;

create function DB.DBA.RQ_IID_OF_O (in shortobj any) returns IRI_ID -- DEPRECATED
{
  return id_to_iri_nosignal (shortobj);
}
;

create function DB.DBA.RQ_O_IS_LIT (in shortobj any) returns integer -- DEPRECATED
{
  if (isiri_id (shortobj))
    return 0;
  return 1;
}
;

-----
-- Conversions from and to values in short representation that may be not field values (may perform more validation checks)



create procedure RDF_G_INS (in id int, in g any)
{
  geo_insert ('DB.DBA.RDF_GEO', g, id);
}
;

create procedure cl_rdf_geo_insert (in id int, inout g any)
{
  declare daq any;
  daq := daq (1);
  daq_call (daq, 'DB.DBA.RDF_OBJ', 'RDF_OBJ', 'DB.DBA.RDF_G_INS', vector (id, g), 1);
  daq_results (daq);
}
;

create function rdf_geo_add (in v any)
{
  declare id, h, ser, g any;
  if (rdf_box_ro_id (v))
    return v;
 g := rdf_box_data (v);
  if (not isgeometry (g))
    signal ('22023', 'RDFXX', 'Must be geometry box if to be stored as geo object');
  ser := serialize (g);
  if (length (ser) > 50)
    h := mdigest5 (ser);
  else
    {
      h := ser;
      ser := null;
    }
  set isolation = 'committed';
  id := (select ro_id, ro_val, ro_long from rdf_obj where ro_val = h and ro_dt_and_lang = 0hex1000101 and case when ro_long is not null then equ (blob_to_string (ro_long),  ser) else 1 end );
  if (id is not null)
    {
      rdf_box_set_ro_id (v, id);
      return v;
    }
  set isolation = 'serializable';
  id := (select ro_id, ro_val, ro_long from rdf_obj where ro_val = h and ro_dt_and_lang = 0hex1000101 and case when ro_long is not null then equ (blob_to_string (ro_long),  ser) else 1 end for update);
  if (id is not null)
    {
      rdf_box_set_ro_id (v, id);
      return v;
    }
 id := sequence_next ('RDF_RO_ID');
  set triggers off;
  -- dbg_obj_princ ('zero RO_FLAGS in sparql.sql:997 ', ro_val, ro_long);
  insert into rdf_obj (ro_id, ro_val, ro_long, ro_dt_and_lang)
    values (id, h, ser, 0hex1000101);
  if (1 = sys_stat ('cl_run_local_only'))
    geo_insert ('DB.DBA.RDF_GEO', g, id);
  else
    cl_rdf_geo_insert (id, g);
  rdf_box_set_ro_id (v, id);
  return v;
}
;

create function rdf_geo_set_id (inout v any)
{
  declare id, h, ser, g any;
  if (rdf_box_ro_id (v))
    return v;
  g := rdf_box_data (v);
  if (not isgeometry (g))
    signal ('22023', 'RDFXX', 'Must be geometry box if to be stored as geo object');
  ser := serialize (g);
  if (length (ser) > 50)
    h := mdigest5 (ser);
  else
    {
      h := ser;
      ser := null;
    }
  set isolation = 'committed';
  id := (select RO_ID from RDF_OBJ where RO_VAL = h and RO_DT_AND_LANG = 0hex1000101
  	and case when RO_LONG is not null then equ (blob_to_string (RO_LONG),  ser) else 1 end );
  if (id is not null)
    {
      rdf_box_set_ro_id (v, id);
      return v;
    }
  return null;
}
;

create function DB.DBA.RDF_OBJ_ADD (in dt_twobyte integeR, in v varchar, in lang_twobyte integeR, in ro_id_dict any := 0) returns varchar
{
  declare llong, id, need_digest integer;
  declare digest any;
  declare old_flags, dt_and_lang integer;
  -- dbg_obj_princ ('DB.DBA.RDF_OBJ_ADD (', dt_twobyte, v, lang_twobyte, case (isnull (ro_id_dict)) when 1 then '/*no_ft*/' else '/*want_ft*/' end,')');
  if (isinteger (ro_id_dict))
    {
      if (__rdf_obj_ft_rule_check (null, null))
        ro_id_dict := dict_new ();
      else
        ro_id_dict := null;
    }
  if (126 = __tag (v))
    v := blob_to_string (v);
  if (isstring (rdf_box_data (v)))
    need_digest := rdf_box_needs_digest (v, ro_id_dict);
  else if (__tag of XML = __tag (v))
    need_digest := 1;
  if (__tag of rdf_box = __tag (v))
    {
      if (256 = rdf_box_type (v))
	return rdf_geo_add (v);
      if (0 = need_digest)
        return v;
      if (1 = need_digest)
        {
          if (0 <> rdf_box_ro_id (v))
            return v;
        }
      dt_twobyte := rdf_box_type (v);
      lang_twobyte := rdf_box_lang (v);
      v := __rdf_sqlval_of_obj (v, 1);
    }
  else
    {
      if (dt_twobyte <> 257 or lang_twobyte <> 257)
        need_digest := 3;
      else if (0 = need_digest)
        return v;
      if (dt_twobyte < 257)
        signal ('RDFXX', sprintf ('Bad datatype code: DB.DBA.RDF_OBJ_ADD (%d, %s, %d)',
          dt_twobyte, "LEFT" (cast (v as varchar), 100), lang_twobyte) );
      if (lang_twobyte < 257)
        signal ('RDFXX', sprintf ('Bad lang code: DB.DBA.RDF_OBJ_ADD (%d, %s, %d)',
          dt_twobyte, "LEFT" (cast (v as varchar), 100), lang_twobyte) );
    }
  dt_and_lang := bit_or (bit_shift (dt_twobyte, 16), lang_twobyte);
  if (not isstring (v))
    {
      declare sum64 varchar;
      if (__tag of XML <> __tag (v))
        signal ('RDFXX', sprintf ('Bad call: DB.DBA.RDF_OBJ_ADD (%d, %s, %d)',
          dt_twobyte, "LEFT" (cast (v as varchar), 100), lang_twobyte) );
      sum64 := xtree_sum64 (v);
      whenever not found goto serializable_xtree;
      set isolation='committed';
      select RO_ID, RO_FLAGS into id, old_flags
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = sum64
      and RO_DT_AND_LANG = dt_and_lang
      and bit_and (RO_FLAGS, 2);
      --!TBD ... and paranoid check

      goto found_xtree;
serializable_xtree:
      whenever not found goto new_xtree;
      set isolation='serializable';
      declare id_cr cursor for
        select RO_ID, RO_FLAGS from DB.DBA.RDF_OBJ table option (index RO_VAL) where RO_VAL = sum64
        and RO_DT_AND_LANG = dt_and_lang
        and bit_and (RO_FLAGS, 2);
      --!TBD ... and paranoid check
      open id_cr (exclusive);
      fetch id_cr into id, old_flags;
found_xtree:
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      if (ro_id_dict is not null)
        {
          if (not (bit_and (old_flags, 1)))
	    {
	      update DB.DBA.RDF_OBJ set RO_FLAGS = bit_or (RO_FLAGS, 1) where RO_ID = id;
	      --insert soft rdf_ft (rf_id, rf_o) values (id, digest);
	    }
          dict_put (ro_id_dict, id, 1);
        }
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX2', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
      -- goto recheck;
new_xtree:
      id := sequence_next ('RDF_RO_ID');
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      -- if (ro_id_dict is null)
      --   {
      --     -- dbg_obj_princ ('zero RO_FLAGS in sparql.sql:1124');
      --     ;
      --   }
      insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_LONG, RO_FLAGS, RO_DT_AND_LANG) values
        (id, sum64, __xml_serialize_packed (v), case (isnull (ro_id_dict)) when 0 then 3 else 2 end, dt_and_lang);
      --if (ro_id_dict is not null)
	--insert soft rdf_ft (rf_id, rf_o) values (id, digest);
      if (ro_id_dict is not null)
        dict_put (ro_id_dict, id, 1);
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX3', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
      -- old_digest := null;
      -- goto recheck;
    }
  if ((dt_twobyte = 257) and (lang_twobyte = 257) and (length (v) <= -1))
    {
      if (1 >= need_digest)
        return v;
      whenever not found goto serializable_veryshort;
      set isolation='committed';
      select RO_ID into id
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = v and RO_DT_AND_LANG = dt_and_lang and not (bit_and (RO_FLAGS, 2));
      goto found_veryshort;
serializable_veryshort:
      whenever not found goto new_veryshort;
      set isolation='serializable';
      declare id_cr cursor for select RO_ID
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = v and RO_DT_AND_LANG = dt_and_lang and not (bit_and (RO_FLAGS, 2));
      open id_cr (exclusive);
      fetch id_cr into id;
found_veryshort:
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	  --insert soft rdf_ft (rf_id, rf_o) values (id, v);
	}
      if (not (rdf_box_is_storeable (v)))
        signal ('RDFX4', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return v;
new_veryshort:
      id := sequence_next ('RDF_RO_ID');
      insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_FLAGS, RO_DT_AND_LANG) values (id, v, 1, dt_and_lang);
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	}
      insert into DB.DBA.RO_START (RS_START, RS_DT_AND_LANG, RS_RO_ID)
        values (subseq (v, 0, case when length (v) > 10 then 10 else length (v) end), dt_and_lang, rdf_box (0, 257, 257, id, 0));
      if (not (rdf_box_is_storeable (v)))
        signal ('RDFX5', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return v;
    }
  llong := 50;
  if (length (v) > llong)
    {
      declare chksm varchar;
      chksm := mdigest5 (v, 1);
      whenever not found goto serializable_long;
      set isolation='committed';
      select RO_ID, RO_FLAGS into id, old_flags
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = chksm
      and RO_DT_AND_LANG = dt_and_lang
      and not (bit_and (RO_FLAGS, 2))
      and blob_to_string (RO_LONG) = v;
      goto found_long;
serializable_long:
      whenever not found goto new_long;
      set isolation='serializable';
      declare id_cr cursor for
        select RO_ID, RO_FLAGS from DB.DBA.RDF_OBJ
      table option (index RO_VAL) where RO_VAL = chksm
      and RO_DT_AND_LANG = dt_and_lang
      and not (bit_and (RO_FLAGS, 2))
      and blob_to_string (RO_LONG) = v;
      open id_cr (exclusive);
      fetch id_cr into id, old_flags;
found_long:
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      if ((not (bit_and (old_flags, 1))) and (1 < need_digest))
        update DB.DBA.RDF_OBJ set RO_FLAGS = bit_or (RO_FLAGS, 1) where RO_ID = id;
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	}
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX6', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
new_long:
      id := sequence_next ('RDF_RO_ID');
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      if (1 < need_digest)
        insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_LONG, RO_FLAGS, RO_DT_AND_LANG)
        values (id, chksm, v, 1, dt_and_lang);
      else
        {
          set triggers off;
          -- dbg_obj_princ ('zero RO_FLAGS in sparql.sql:1225 ', chksm, v);
          insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_LONG, RO_DT_AND_LANG)
          values (id, chksm, v, dt_and_lang);
          set triggers on;
        }
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	}
      insert into DB.DBA.RO_START (RS_START, RS_DT_AND_LANG, RS_RO_ID)
        -- no need in values (subseq (v, 0, case when length (v) > 10 then 10 else length (v), RO_DT_AND_LANG, rdf_box (0, 257, 257, id, 0));
        values (subseq (v, 0, 10), dt_and_lang, rdf_box (0, 257, 257, id, 0));
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX7', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
    }
  else
    {
      whenever not found goto serializable_short;
      set isolation='committed';
      select RO_ID, RO_FLAGS into id, old_flags
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = v
      and RO_DT_AND_LANG = dt_and_lang;
      goto found_short;
serializable_short:
      whenever not found goto new_short;
      set isolation='serializable';
      declare id_cr cursor for select RO_ID, RO_FLAGS
      from DB.DBA.RDF_OBJ table option (index RO_VAL)
      where RO_VAL = v
      and RO_DT_AND_LANG = dt_and_lang;
      open id_cr (exclusive);
      fetch id_cr into id, old_flags;
found_short:
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      if ((not (bit_and (old_flags, 1))) and (1 < need_digest))
        update DB.DBA.RDF_OBJ set RO_FLAGS = bit_or (RO_FLAGS, 1) where RO_ID = id;
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	}
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX8', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
new_short:
      id := sequence_next ('RDF_RO_ID');
      digest := rdf_box (v, dt_twobyte, lang_twobyte, id, 1);
      if (1 < need_digest)
        insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_FLAGS, RO_DT_AND_LANG)
        values (id, v, 1, dt_and_lang);
      else
        {
          -- dbg_obj_princ ('zero RO_FLAGS in sparql.sql:1271 ', v);
          set triggers off;
          insert into DB.DBA.RDF_OBJ (RO_ID, RO_VAL, RO_FLAGS, RO_DT_AND_LANG)
          values (id, v, 0, dt_and_lang);
          set triggers on;
        }
      insert into DB.DBA.RO_START (RS_START, RS_DT_AND_LANG, RS_RO_ID)
        values (subseq (v, 0, case when length (v) > 10 then 10 else length (v) end), dt_and_lang, rdf_box (0, 257, 257, id, 0));
      if (ro_id_dict is not null)
	{
	  dict_put (ro_id_dict, id, 1);
	}
      if (not (rdf_box_is_storeable (digest)))
        signal ('RDFX9', 'DB.DBA.RDF_OBJ_ADD() tries to return bad digest');
      return digest;
    }
recheck:
  -- dbg_obj_princ ('recheck: id=', id, ', old_digest=', old_digest, ', need_digest=', need_digest, ', digest=', digest);
  signal ('FUNNY', 'Debug code of DB.DBA.RDF_OBJ_ADD() is reached. This can not happen (I believe). Please report this error.');
}
;

create function DB.DBA.RDF_FIND_RO_DIGEST (in dt_twobyte integeR, in v varchar, in lang_twobyte integeR) returns varchar
{
  declare llong, dt_and_lang int;
  declare dt_s, lang_s, chksm, sum64 varchar;
  declare digest, old_digest any;
  if (126 = __tag (v))
    v := blob_to_string (v);
  dt_and_lang := bit_or (bit_shift (dt_twobyte, 16), lang_twobyte);
  if (not (isstring (v)))
    {
      if (__tag of XML <> __tag (v))
        return v;
      sum64 := xtree_sum64 (v);
      return (select rdf_box (v, dt_twobyte, lang_twobyte, RO_ID, 1)
        from DB.DBA.RDF_OBJ table option (index RO_VAL)
        where RO_VAL = sum64
        and RO_DT_AND_LANG = dt_and_lang
        and bit_and (RO_FLAGS, 2)
        --!TBD ... and paranoid check
        );
    }
  if ((dt_twobyte = 257) and (lang_twobyte = 257) and (length (v) <= 20))
    return v;
  llong := 50;
  if (length (v) > llong)
    {
      chksm := mdigest5 (v, 1);
      return (select rdf_box (v, dt_twobyte, lang_twobyte, RO_ID, 1)
        from DB.DBA.RDF_OBJ table option (index RO_VAL)
        where RO_VAL = chksm
        and RO_DT_AND_LANG = dt_and_lang
        and not (bit_and (RO_FLAGS, 2))
        and blob_to_string (RO_LONG) = v );
    }
  else
    {
      return (select rdf_box (v, dt_twobyte, lang_twobyte, RO_ID, 1)
        from DB.DBA.RDF_OBJ table option (index RO_VAL)
        where RO_VAL = v
        and RO_DT_AND_LANG = dt_and_lang
        and not (bit_and (RO_FLAGS, 2)) );
    }
}
;

create function DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL (in v any) returns any array
{
  declare t int;
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML, __tag of rdf_box)))
    return v;
  if (__tag of UNAME = t)
    return __i2id (v);
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return __i2id (v);
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  return DB.DBA.RDF_OBJ_ADD (257, v, 257);
}
;

create function DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (in v any, in g_iid IRI_ID, in p_iid IRI_ID, in ro_id_dict any := null) returns any
{
  declare t int;
  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (', v, g_iid, p_iid, ro_id_dict, ')');
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML, __tag of rdf_box)))
    return v;
  if (__tag of UNAME = t)
    return __i2id (v);
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return __i2id (v);
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (t = 126)
    v := cast (v as varchar);
  if (not __rdf_obj_ft_rule_check (g_iid, p_iid))
    ro_id_dict := null;
  else
    {
      if (ro_id_dict is null)
        {
          declare res any;
          ro_id_dict := dict_new ();
          res := DB.DBA.RDF_OBJ_ADD (257, v, 257, ro_id_dict);
          DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (g_iid, ro_id_dict);
          return res;
        }
    }
  return DB.DBA.RDF_OBJ_ADD (257, v, 257, ro_id_dict);
}
;

create function DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (in v any, in dt_iid IRI_ID, in lang varchar) returns any array
{
  declare t, dt_twobyte, lang_twobyte int;
  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (', v, dt_iid, lang, ')');
retry_unrdf:
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML)))
    {
      if (__tag of rdf_box = t)
        {
          v := rdf_box_data (v);
          goto retry_unrdf;
        }
      -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL() should accept only string representations of typed values, real arguments are ', v, dt_iid, lang);
      return v;
    }
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (126 = t)
    v := cast (v as varchar);
  if (dt_iid is not null)
    dt_twobyte := DB.DBA.RDF_TWOBYTE_OF_DATATYPE (dt_iid);
  else
    dt_twobyte := 257;
  if (lang is not null)
    lang_twobyte := DB.DBA.RDF_TWOBYTE_OF_LANGUAGE (lang);
  else
    lang_twobyte := 257;
  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (', v, dt_iid, lang, ') calls DB.DBA.RDF_OBJ_ADD (', dt_twobyte, v, lang_twobyte, ')');
  return DB.DBA.RDF_OBJ_ADD (dt_twobyte, v, lang_twobyte);
}
;

create function DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT (in v any, in dt_iid IRI_ID, in lang varchar, in g_iid IRI_ID, in p_iid IRI_ID, in ro_id_dict any := null) returns any array
{
  declare t, dt_twobyte, lang_twobyte int;
  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT (', v, dt_iid, lang, g_iid, p_iid, ro_id_dict, ')');
retry_unrdf:
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML)))
    {
      if (__tag of rdf_box = t)
        {
          v := rdf_box_data (v);
          goto retry_unrdf;
        }
      -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT() should accept only string representations of typed values, real arguments are ', v, dt_iid, lang, g_iid, p_iid);
      return v;
    }
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (__tag of UNAME = t or 126 = t)
    v := cast (v as varchar);
  if (dt_iid is not null)
    dt_twobyte := DB.DBA.RDF_TWOBYTE_OF_DATATYPE (dt_iid);
  else
    dt_twobyte := 257;
  if (lang is not null)
    lang_twobyte := DB.DBA.RDF_TWOBYTE_OF_LANGUAGE (lang);
  else
    lang_twobyte := 257;
  if (not __rdf_obj_ft_rule_check (g_iid, p_iid))
    ro_id_dict := null;
  else
    {
      if (ro_id_dict is null)
        {
          declare res any;
          ro_id_dict := dict_new ();
          res := DB.DBA.RDF_OBJ_ADD (dt_twobyte, v, lang_twobyte, ro_id_dict);
          DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (g_iid, ro_id_dict);
          return res;
        }
    }
  return DB.DBA.RDF_OBJ_ADD (dt_twobyte, v, lang_twobyte, ro_id_dict);
}
;

create function DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_STRINGS (
  in o_val any, in o_type varchar, in o_lang varchar ) returns any array
{
  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_STRINGS (', o_val, o_type, o_lang, ')');
  if (__tag (o_type) in (__tag of varchar, __tag of UNAME))
    {
      declare parsed any;
      parsed := __xqf_str_parse_to_rdf_box (o_val, o_type, isstring (o_val));
      if (parsed is not null)
        {
          if (__tag of XML = __tag (parsed))
            {
              return DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (
                parsed, iri_to_id (o_type), null );
            }
          if (__tag of rdf_box = __tag (parsed))
            {
              if (256 = rdf_box_type (parsed))
                db..rdf_geo_add (parsed);
              else
                rdf_box_set_type (parsed,
                  DB.DBA.RDF_TWOBYTE_OF_DATATYPE (iri_to_id (o_type)));
              parsed := DB.DBA.RDF_OBJ_ADD (257, parsed, 257, null);
            }
          return parsed;
        }
      return DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (
        o_val,
        iri_to_id (o_type),
        o_lang );
    }
  if (isstring (o_lang))
    {
      return DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (
        o_val, NULL, o_lang );
    }
  return DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL (o_val);
}
;

create function DB.DBA.RDF_LONG_OF_OBJ (in shortobj any) returns any -- DEPRECATED
{
  return __rdf_long_of_obj (shortobj);
}
;

create function DB.DBA.RDF_DATATYPE_OF_OBJ (in shortobj any, in dflt varchar := UNAME'http://www.w3.org/2001/XMLSchema#string') returns any
{
  declare twobyte integer;
  declare res any;
  if (__tag of rdf_box <> __tag (shortobj))
    {
      if (isiri_id (shortobj))
        return null;
      if (isstring (shortobj) and bit_and (__box_flags (shortobj), 1))
        return null;
      if (__tag of UNAME = __tag (shortobj))
        return null;
      -- dbg_obj_princ ('DB.DBA.RDF_DATATYPE_OF_OBJ (', shortobj, ') will return ', __xsd_type (shortobj, dflt), ' for non-rdfbox');
      return __xsd_type (shortobj, dflt);
    }
  twobyte := rdf_box_type (shortobj);
  -- dbg_obj_princ ('DB.DBA.RDF_DATATYPE_OF_OBJ (', shortobj, ') found twobyte ', twobyte);
  if (257 = twobyte)
    return case (rdf_box_lang (shortobj)) when 257 then __uname (dflt) else null end;
  whenever not found goto badtype;
  select __uname (RDT_QNAME) into res from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = twobyte;
  return res;

badtype:
  signal ('RDFXX', sprintf ('Unknown datatype in DB.DBA.RQ_DATATYPE_OF_OBJ, bad type id %d, string value "%s"',
    twobyte, cast (rdf_box_data (shortobj) as varchar) ) );
}
;

create function DB.DBA.RDF_LANGUAGE_OF_OBJ (in shortobj any array, in dflt varchar := '') returns any
{
  vectored;
  declare twobyte integer;
  declare res varchar;
  if (__tag of rdf_box <> __tag (shortobj))
    {
      if (isiri_id (shortobj))
        return null;
      if (isstring (shortobj) and bit_and (__box_flags (shortobj), 1))
        return null;
      if (__tag of UNAME = __tag (shortobj))
        return null;
      -- dbg_obj_princ ('DB.DBA.RDF_LANGUAGE_OF_OBJ (', shortobj, ') got a non-rdfbox');
      return dflt;
    }
  twobyte := rdf_box_lang (shortobj);
  -- dbg_obj_princ ('DB.DBA.RDF_LANGUAGE_OF_OBJ (', shortobj, ') found twobyte ', twobyte);
  if (257 = twobyte)
    return dflt;
  return coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte), 
     signal ('RDFXX', sprintf ('Unknown language in DB.DBA.RDF_LANGUAGE_OF_OBJ, bad string "%s"', cast (shortobj as varchar))));
}
;

create function DB.DBA.RDF_SQLVAL_OF_OBJ (in shortobj any) returns any -- DEPRECATED
{
  return __rdf_sqlval_of_obj (shortobj);
}
;

create function DB.DBA.RDF_BOOL_OF_OBJ (in shortobj any array) returns any
{
  vectored;
  return sparql_ebv (__ro2sq(shortobj));
}
;

create function DB.DBA.RDF_SPARQL_EBV_OF_OBJ (in shortobj any array) returns any
{
  vectored;
  return sparql_ebv (__ro2sq(shortobj));
}
;

create function DB.DBA.RDF_QNAME_OF_OBJ (in shortobj any) returns varchar -- DEPRECATED
{
  return id_to_iri_nosignal (shortobj);
}
;

create function DB.DBA.RDF_STRSQLVAL_OF_OBJ (in shortobj any) -- DEPRECATED
{
  return __rdf_strsqlval (shortobj, 0);
}
;

create function DB.DBA.RDF_OBJ_OF_LONG (in longobj any) returns any
{
  declare t int;
  t := __tag (longobj);
  if (__tag of rdf_box <> t)
    {
      if (not (t in (__tag of varchar, 126, __tag of UNAME, __tag of nvarchar, 133, 226)))
        return longobj;
      if (t = 133)
	{
	  longobj := cast (longobj as nvarchar);
	  t := __tag (longobj);
	}
      if (__tag of nvarchar = t or t = 226)
        longobj := charset_recode (longobj, '_WIDE_', 'UTF-8');
      else if (t = 126)
        longobj := cast (longobj as varchar);
      else if (__tag of UNAME = t)
        return __i2id (longobj);
      else if (bit_and (1, __box_flags (longobj)))
        return __i2id (longobj);
      return DB.DBA.RDF_OBJ_ADD (257, longobj, 257);
    }
  if (0 = rdf_box_needs_digest (longobj))
    return longobj;
  return DB.DBA.RDF_OBJ_ADD (257, longobj, 257);
}
;

create function DB.DBA.RDF_OBJ_OF_SQLVAL (in v any) returns any array
{
  declare t int;
  t := __tag (v);
  if (not (t in (__tag of varchar, 126, __tag of UNAME, __tag of nvarchar)))
    {
      if (__tag of rdf_box = __tag(v) and 0 = rdf_box_ro_id (v))
        return DB.DBA.RDF_OBJ_ADD (257, v, 257);
      return v;
    }
  if (__tag of UNAME = t)
    return __i2id (v);
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return __i2id (v);
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (t = 126)
    v := cast (v as varchar);
  return DB.DBA.RDF_OBJ_ADD (257, v, 257);
}
;

-----
-- Functions for long object representation.

create function DB.DBA.RDF_MAKE_LONG_OF_SQLVAL (in v any) returns any
{
  declare t int;
  declare res any;
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML)))
    return v;
  if (__tag of UNAME = t)
    return __i2id (v);
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return __i2id (v);
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (126 = t)
    v := cast (v as varchar);
  res := rdf_box (v, 257, 257, 0, 1);
  return res;
}
;


create function DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (in v any, in dt_iid IRI_ID, in lang varchar) returns any
{
  declare t, dt_twobyte, lang_twobyte int;
  declare res any;
  t := __tag (v);
--  if (not (t in (__tag of varchar, __tag of UNAME, __tag of nvarchar, __tag of XML)))
--    signal ('RDFXX', 'DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL() accepts only string representations of typed values');
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (__tag of UNAME = t)
    v := cast (v as varchar);
  else if (__tag of varchar = t and 1 = __box_flags (v) and dt_iid is null and lang is null)
    return iri_to_id (v);
  if (__tag of varchar <> __tag (v))
    {
      declare xsdt IRI_ID;
      if (lang is not null)
        {
          if (is_rdf_box (v) and rdf_box_type (v) = 257)
            {
              v := rdf_box_data (v, 1);
              if (__tag of varchar <> __tag (v))
                {
                  -- dbg_obj_princ ('DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (', v, dt_iid, lang, ')');
                  signal ('RDFXX', 'Language is set and the argument is invalid RDF box in DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL()');
                }
            }
          else
            {
              -- dbg_obj_princ ('DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (', v, dt_iid, lang, ')');
              signal ('RDFXX', 'Language is specified for typed literal in DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL()');
            }
          if (dt_iid is not null)
            signal ('RDFXX', 'Both language and type are specified in call of DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL()');
        }
      else
        {
          if (is_rdf_box (v))
            v := rdf_box_data (v, 1);
          xsdt := cast (__xsd_type (v, UNAME'http://www.w3.org/2001/XMLSchema#string', NULL) as varchar);
          if (dt_iid = case (isiri_id (dt_iid)) when 1 then iri_to_id (xsdt) else xsdt end)
            return v;
          -- dbg_obj_princ ('no opt -- ', dt_iid, case (isiri_id (dt_iid)) when 1 then iri_to_id (xsdt) else xsdt end);
        }
    }
  if (dt_iid is not null)
    dt_twobyte := DB.DBA.RDF_TWOBYTE_OF_DATATYPE (dt_iid);
  else
    dt_twobyte := 257;
  if (lang is not null)
    lang_twobyte := DB.DBA.RDF_TWOBYTE_OF_LANGUAGE (lang);
  else
    lang_twobyte := 257;
  res := rdf_box (v, dt_twobyte, lang_twobyte, 0, 1);
  return res;
}
;

create function DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (
  in o_val any, in o_type varchar, in o_lang varchar ) returns any
{
  if (__tag (o_type) in (__tag of varchar, __tag of UNAME))
    {
      declare parsed any;
      parsed := __xqf_str_parse_to_rdf_box (o_val, o_type, isstring (o_val));
      if (parsed is not null)
        {
          if (__tag of XML = __tag (parsed))
	    parsed := rdf_box (parsed, 300, 257, 0, 1);
          if (__tag of rdf_box = __tag (parsed))
            rdf_box_set_type (parsed,
              DB.DBA.RDF_TWOBYTE_OF_DATATYPE (iri_to_id (o_type)));
          return parsed;
        }
      return DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (
        o_val,
        iri_to_id (o_type),
        null );
    }
  if (__tag (o_lang) in (__tag of varchar, __tag of UNAME))
    return DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (o_val, NULL, o_lang);
  return DB.DBA.RDF_MAKE_LONG_OF_SQLVAL (o_val);
}
;

create function DB.DBA.RDF_QNAME_OF_LONG_SAFE (in longobj any) returns varchar -- DEPRECATED
{
  return id_to_iri_nosignal (longobj);
}
;

create function DB.DBA.RDF_SQLVAL_OF_LONG (in longobj any) returns any -- DEPRECATED
{
  return __rdf_sqlval_of_obj (longobj);
}
;

create function DB.DBA.RDF_BOOL_OF_LONG (in longobj any) returns any
{
  if (isiri_id (longobj))
    return NULL;
  if (isinteger (longobj))
    {
      if (longobj)
        return 1;
      return 0;
    }
  if (__tag of rdf_box <> __tag (longobj))
    {
      if (longobj is null)
        return null;
      if (equ (longobj, 0.0) or equ (longobj, '')) return 0; else return 1;
    }
  declare dtqname any;
  if (257 = rdf_box_type (longobj))
    goto type_ok;
  whenever not found goto badtype;
  select RDT_QNAME into dtqname from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (longobj);
  if (dtqname <> UNAME'http://www.w3.org/2001/XMLSchema#string')
    return null;

type_ok:
  return case (length (rdf_box_data (longobj))) when 0 then 0 else 1 end;

badtype:
  signal ('RDFXX', sprintf ('Unknown datatype in DB.DBA.RDF_BOOL_OF_LONG (code %d)', rdf_box_type (longobj)));
}
;

create function DB.DBA.RDF_DATATYPE_OF_LONG (in longobj any, in dflt any := UNAME'http://www.w3.org/2001/XMLSchema#string') returns any
{
  if (__tag of rdf_box = __tag (longobj))
    {
      declare twobyte integer;
      declare res IRI_ID;
      twobyte := rdf_box_type (longobj);
      if (257 = twobyte)
        return case (rdf_box_lang (longobj)) when 257 then __uname (dflt) else null end;
      whenever not found goto badtype;
      select __uname (RDT_QNAME) into res from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = twobyte;
      return res;

badtype:
  signal ('RDFXX', sprintf ('Unknown datatype in DB.DBA.RDF_DATATYPE_OF_LONG, bad id %d', twobyte));
    }
  if (isiri_id (longobj))
    return NULL;
  return __xsd_type (longobj, dflt);
}
;

create function DB.DBA.RDF_DATATYPE_IRI_OF_LONG (in longobj any, in dflt any := UNAME'http://www.w3.org/2001/XMLSchema#string') returns any
{
  if (__tag of rdf_box = __tag (longobj))
    {
      declare twobyte integer;
      declare res varchar;
      twobyte := rdf_box_type (longobj);
      if (257 = twobyte)
        return case (rdf_box_lang (longobj)) when 257 then dflt else null end;
      whenever not found goto badtype;
      select RDT_QNAME into res from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = twobyte;
      return res;

badtype:
  signal ('RDFXX', sprintf ('Unknown datatype in DB.DBA.RDF_DATATYPE_IRI_OF_LONG, bad id %d', twobyte));
    }
  if (isiri_id (longobj))
    return NULL;
  return __xsd_type (longobj, dflt);
}
;

create function DB.DBA.RDF_LANGUAGE_OF_LONG (in longobj any, in dflt varchar := '') returns any
{
  if (__tag of rdf_box = __tag (longobj))
    {
      declare twobyte integer;
      declare res varchar;
      twobyte := rdf_box_lang (longobj);
      if (257 = twobyte)
        return dflt;
      whenever not found goto badlang;
      select RL_ID into res from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte;
      return res;

badlang:
  signal ('RDFXX', sprintf ('Unknown language in DB.DBA.RDF_LANGUAGE_OF_LONG, bad id %d', twobyte));
    }
  return case (isiri_id (longobj)) when 0 then dflt else null end;
}
;

create function DB.DBA.RDF_STRSQLVAL_OF_LONG (in longobj any) -- DEPRECATED
{
  return __rdf_strsqlval (longobj, 0);
}
;

create function DB.DBA.RDF_WIDESTRSQLVAL_OF_LONG (in longobj any)
{
  declare t, len integer;
  if (__tag of rdf_box = __tag (longobj))
    {
      if (rdf_box_is_complete (longobj))
        {
          if (__tag of varchar = rdf_box_data_tag (longobj))
            return charset_recode (rdf_box_data (longobj), 'UTF-8', '_WIDE_');
          if (__tag of datetime = rdf_box_data_tag (longobj))
            {
              declare vc varchar;
              vc := cast (rdf_box_data (longobj) as varchar); --!!!TBD: replace with proper serialization
              return cast (replace (vc, ' ', 'T') as nvarchar);
            }
          if (__tag of XML = rdf_box_data_tag (longobj))
            {
              return charset_recode (serialize_to_UTF8_xml (rdf_box_data (longobj)), 'UTF-8', '_WIDE_');
            }
          return cast (rdf_box_data (longobj) as nvarchar);
        }
      declare id integer;
      declare v2 any;
      id := rdf_box_ro_id (longobj);
      if (__tag of XML = rdf_box_data_tag (longobj))
        {
          v2 := (select xml_tree_doc (__xml_deserialize_packed (RO_LONG)) from DB.DBA.RDF_OBJ where RO_ID = id);
          rdf_box_set_data (longobj, v2, 1);
          return charset_recode (serialize_to_UTF8_xml (v2), 'UTF-8', '_WIDE_');
        }
      else
        v2 := (select case (isnull (RO_LONG)) when 0 then blob_to_string (RO_LONG) else RO_VAL end from DB.DBA.RDF_OBJ where RO_ID = id);
      if (v2 is null)
        signal ('RDFXX', sprintf ('Integrity violation in DB.DBA.RDF_WIDESTRSQLVAL_OF_LONG, bad id %d', id));
      rdf_box_set_data (longobj, v2, 1);
      return charset_recode (v2, 'UTF-8', '_WIDE_');
    }
  if (isiri_id (longobj))
    {
      declare res varchar;
      res := id_to_iri (longobj);
--      res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = longobj));
      if (res is null)
        signal ('RDFXX', 'Wrong iid in DB.DBA.RDF_WIDESTRSQLVAL_OF_LONG()');
      return charset_recode (res, 'UTF-8', '_WIDE_');
    }
  if (__tag of datetime = __tag (longobj))
    {
      declare vc varchar;
      vc := cast (longobj as varchar); --!!!TBD: replace with proper serialization
      return cast (replace (vc, ' ', 'T') as nvarchar);
    }
  if (__tag of nvarchar = __tag (longobj))
    return longobj;
  if (__tag of XML = __tag (longobj))
    {
      return charset_recode (serialize_to_UTF8_xml (longobj), 'UTF-8', '_WIDE_');
    }
  return cast (longobj as nvarchar);
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_DATATYPE_OF_SQLVAL (in v any,
  in strg_datatype any := UNAME'http://www.w3.org/2001/XMLSchema#string',
  in default_res any := NULL) returns any
{
  if (__tag of rdf_box = __tag (v))
    {
      declare twobyte integer;
      declare res IRI_ID;
      twobyte := rdf_box_type (v);
      if (257 = twobyte)
        return case (rdf_box_lang (v)) when 257 then __uname (strg_datatype) else null end;
      whenever not found goto badtype;
      select __uname (RDT_QNAME) into res from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = twobyte;
      return res;

badtype:
  signal ('RDFXX', sprintf ('Unknown datatype in DB.DBA.RDF_DATATYPE_OF_SQLVAL, bad id %d', twobyte));
    }
  return __uname (__xsd_type (v, strg_datatype, default_res));
}
;

-- /* keep the input parameter as varchar in order to make jdbc happy and receive 182 instead of 242 on which it breaks the utf8 support */
create function DB.DBA.RDF_LONG_OF_SQLVAL (in v varchar) returns any
{
  declare t int;
  t := __tag (v);
  if (not (t in (126, __tag of varchar, __tag of UNAME, __tag of nvarchar)))
    return v;
  if (__tag of UNAME = t)
    return __i2id (v);
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return __i2id (v);
  if (__tag of nvarchar = t)
    v := charset_recode (v, '_WIDE_', 'UTF-8');
  else if (t = 126)
    v := cast (v as varchar);
--  if ((t = __tag of varchar) and (v like 'http://%'))
--    {
--     -- dbg_obj_princ ('DB.DBA.RDF_LONG_OF_SQLVAL (', v, '): no box flag, suspicious value');
--      ;
--    }
  return rdf_box (v, 257, 257, 0, 1);
}
;

-----
-- Conversions for SQL values

--!AWK PUBLIC
create function DB.DBA.RDF_STRSQLVAL_OF_SQLVAL (in sqlval any) -- DEPRECATED
{
  declare t, len integer;
  if (__tag of rdf_box = __tag (sqlval))
    sqlval := __ro2sq (sqlval, 1);
  if (isiri_id (sqlval))
    {
      declare res varchar;
      res := id_to_iri (sqlval);
--      res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = sqlval));
      if (res is null)
        signal ('RDFXX', 'Wrong iid in DB.DBA.RDF_STRSQLVAL_OF_SQLVAL()');
      __box_flags_set (res, 2);
      return res;
    }
  if (__tag of datetime = __tag (sqlval))
    {
      declare vc varchar;
      vc := cast (sqlval as varchar); --!!!TBD: replace with proper serialization
      return replace (vc, ' ', 'T');
    }
  if (__tag of nvarchar = __tag (sqlval))
    return charset_recode (sqlval, '_WIDE_', 'UTF-8');
  return cast (sqlval as varchar);
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_LANGUAGE_OF_SQLVAL (in v any, in dflt varchar := '') returns any
{
  declare t int;
  if (__tag of rdf_box = __tag (v))
    {
      declare twobyte integer;
      declare res varchar;
      twobyte := rdf_box_lang (v);
      whenever not found goto badtype;
      select RL_ID into res from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte;
      return res;

badtype:
  signal ('RDFXX', sprintf ('Unknown language in DB.DBA.RDF_LANGUAGE_OF_SQLVAL, bad id %d', twobyte));
    }
  if (__tag of UNAME = t)
    return null;
  if (isstring (v) and bit_and (__box_flags (v), 1))
    return null;
  if (isiri_id (v))
    return null;
  return dflt;
--  t := __tag (v);
--  if (not (t in (__tag of varchar, __tag of UNAME, __tag of nvarchar)))
--    return NULL;
--  return NULL; -- !!!TBD: uncomment this and make a support for UTF8 'language name' codepoint plane
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_IS_BLANK_REF (in v any) returns any
{
  if ((__tag (v) = __tag of UNAME) or ((__tag (v) = __tag of varchar) and bit_and (1, __box_flags (v))))
    {
      if ("LEFT" (v, 9) <> 'nodeID://')
        return 0;
      return 1;
    }
  if (__tag (v) = 243)
    {
      if (v < min_bnode_iri_id ())
        return 0;
      return 1;
    }
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_IS_URI_REF (in v any) returns any
{
  if ((__tag (v) = __tag of UNAME) or ((__tag (v) = __tag of varchar) and bit_and (1, __box_flags (v))))
    {
      if ("LEFT" (v, 9) <> 'nodeID://')
        return 1;
      return 0;
    }
  if (__tag (v) = 243)
    {
      if (v < min_bnode_iri_id ())
        return 1;
      return 0;
    }
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_IS_REF (in v any) returns any
{
  if (__tag (v) in (__tag of UNAME, 243))
    return 1;
  if ((__tag of varchar = __tag (v)) and bit_and (1, __box_flags (v)))
    return 1;
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_IS_LITERAL (in v any) returns any
{
  if (__tag (v) in (__tag of UNAME, 243))
    return 0;
  if ((__tag of varchar = __tag (v)) and bit_and (1, __box_flags (v)))
    return 0;
  if (v is null)
    return 0;
  return 1;
}
;

-----
-- Partial emulation of XQuery Core Function Library (temporary, to be deleted soon)

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#boolean" (in strg any) returns any
{
  declare res integer;
  if (isstring (strg))
    {
      if (('true' = strg) or ('1' = strg))
        res := 1;
      else if (('false' = strg) or ('0' = strg))
        res := 0;
      else
        return NULL;
      return sparql_ebv_of_sqlval (res);
    }
  return sparql_ebv_of_sqlval (strg);
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#date" (in strg any) returns date
{
  if (__tag of datetime = __tag (strg))
    return strg;
  whenever sqlstate '*' goto ret_null;
  if (isstring (strg))
    return __xqf_str_parse ('date', strg);
  return cast (strg as date);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#dateTime" (in strg any) returns datetime
{
  if (__tag of datetime = __tag (strg))
    return strg;
  whenever sqlstate '*' goto ret_null;
  if (isstring (strg))
    return __xqf_str_parse ('dateTime', strg);
  return cast (strg as datetime);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#double" (in strg varchar) returns double precision
{
  whenever sqlstate '*' goto ret_null;
  return cast (strg as double precision);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#float" (in strg varchar) returns float
{
  whenever sqlstate '*' goto ret_null;
  return cast (strg as float);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#integer" (in strg varchar) returns integer
{
  whenever sqlstate '*' goto ret_null;
  return cast (strg as integer);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#int" (in strg varchar) returns integer
{
  whenever sqlstate '*' goto ret_null;
  return cast (strg as integer);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#time" (in strg any) returns time
{
  if (__tag of datetime = __tag (strg))
    return strg;
  whenever sqlstate '*' goto ret_null;
  if (isstring (strg))
    return __xqf_str_parse ('time', strg);
  return cast (strg as time);
ret_null:
  return NULL;
}
;

--!AWK PUBLIC
create function DB.DBA."http://www.w3.org/2001/XMLSchema#string" (in strg any) returns any
{
  whenever sqlstate '*' goto ret_null;
  declare t, dt_twobyte, lang_twobyte int;
  t := __tag (strg);
  if (__tag of nvarchar = t)
    strg := charset_recode (strg, '_WIDE_', 'UTF-8');
  else if (__tag of varchar <> t)
    strg := cast (strg as varchar);
  return DB.DBA.RDF_OBJ_ADD (
    DB.DBA.RDF_TWOBYTE_OF_DATATYPE ('http://www.w3.org/2001/XMLSchema#string'),
    strg, 257 );

ret_null:
  return NULL;
}
;

-----
-- Boolean operators as functions (temporary, will be replaced with 'LET' SQL extension soon)

--!AWK PUBLIC
create function DB.DBA.__and (in e1 any, in e2 any) returns integer
{
  if (e1 and e2)
    return 1;
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.__or (in e1 any, in e2 any) returns integer
{
  if (e1 or e2)
    return 1;
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.__not (in e1 any) returns integer
{
  if (e1)
    return 0;
  return 1;
}
;

-----
-- SPARQL 1.1 built-in functions, implemented as stored procedures

create function DB.DBA.rdf_strdt_impl (in str varchar, in dt_iri any)
{
  declare dt_iid IRI_ID;
  declare parsed any;
  dt_iid := __i2id (dt_iri);
  if (dt_iid is null)
    signal ('22007', 'Function rdf_strdt_impl needs a valid datatype IRI as its second argument');
  if (__tag of IRI_ID = __tag (dt_iri))
    dt_iri := __id2i (dt_iri);
  parsed := __xqf_str_parse_to_rdf_box (str, dt_iri, isstring (str));
  if (parsed is not null)
    {
      if (__tag of rdf_box = __tag (parsed))
        rdf_box_set_type (parsed,
          DB.DBA.RDF_TWOBYTE_OF_DATATYPE (dt_iid));
      return parsed;
    }
  return DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (str, dt_iid, null);
}
;

create function DB.DBA.rdf_strlang_impl (in str varchar, in lang any)
{
  declare t integer;
  lang := cast (lang as varchar);
  if ((lang is null) or (regexp_match ('^(([a-z][a-z](-[A-Z][A-Z])?)|(x-[A-Za-z0-9]+))\044', lang) is null))
    signal ('22007', 'Function rdf_strlang_impl needs a valid language ID as its second argument');
  if (is_rdf_box (str))
    str := rdf_box_data (str, 1);
  t := __tag (str);
  if (__tag of nvarchar = t)
    str := charset_recode (str, '_WIDE_', 'UTF-8');
  else if (__tag of varchar <> t)
    {
      if (str is null)
        signal ('22007', 'Function rdf_strlang_impl needs a bound value as its first argument, not a NULL');
      str := cast (str as varchar);
    }
  return rdf_box (str, 257, DB.DBA.RDF_TWOBYTE_OF_LANGUAGE (lang), 0, 1);
}
;

--!AWK PUBLIC
create function DB.DBA.rdf_replace_impl (in src varchar, in needle varchar, in rpl varchar, in opts varchar := '')
{
  declare src_tag, needle_tag, rpl_tag integer;
  declare res varchar;
  src_tag := __tag (src);
  needle_tag := __tag (needle);
  rpl_tag := __tag (rpl);
  if (__tag of rdf_box = src_tag)
    {
      src := rdf_box_data (src);
      src_tag := __tag (src);
    }
  if (__tag of rdf_box = needle_tag)
    {
      needle := rdf_box_data (needle);
      needle_tag := __tag (needle);
    }
  if (__tag of rdf_box = rpl_tag)
    {
      rpl := rdf_box_data (rpl);
      rpl_tag := __tag (rpl);
    }
  if (__tag of nvarchar = src_tag)
    src := charset_recode (src, '_WIDE_', 'UTF-8');
  else if (__tag of varchar <> src_tag)
    src := cast (src as varchar);
  if (__tag of nvarchar = needle_tag)
    needle := charset_recode (needle, '_WIDE_', 'UTF-8');
  else if (__tag of varchar <> needle_tag)
    needle := cast (needle as varchar);
  if (__tag of nvarchar = rpl_tag)
    rpl := charset_recode (rpl, '_WIDE_', 'UTF-8');
  else if (__tag of varchar <> rpl_tag)
    rpl := cast (rpl as varchar);
  if (__tag of varchar <> __tag (opts))
    opts := cast (opts as varchar);
  if (opts is null)
    opts := '';
  if (src is null or needle is null or rpl is null)
    return null;
  if ('' = needle)
    return src;
  if (regexp_match ('^[^()|+?.:^\044\\\\\\[\\]-]+\044', needle, 0, 'u') is not null and strchr (rpl, '\044') is null and strchr (rpl, 92) is null)
    {
      if ('' = opts)
        {
          res := replace (src, needle, rpl);
          __box_flags_set (res, 2);
          return res;
        }
      if (opts in ('i', 'I'))
        {
          declare src_lc varchar;
          declare hit, needle_len integer;
          declare ses any;
          src_lc := lcase (src);
          needle := lcase (needle);
          hit := strstr (src_lc, needle);
          if (hit is null)
            {
              res := src;
              __box_flags_set (res, 2);
              return res;
            }
          ses := string_output();
          needle_len := length (needle);
          while (hit is not null)
            {
              http (subseq (src, 0, hit), ses);
              http (rpl, ses);
              src := subseq (src, hit + needle_len);
              src_lc := subseq (src_lc, hit + needle_len);
              hit := strstr (src_lc, needle);
            }
          http (src, ses);
          res := string_output_string (ses);
          __box_flags_set (res, 2);
          return res;
        }
    }
  if (strchr (opts, 'u') is null and strchr (opts, 'U') is null)
    opts := opts || 'u';
  res := regexp_xfn_replace (src, needle, rpl, 0, null, opts);
  __box_flags_set (res, 2);
  return res;
}
;

--!AWK PUBLIC
create function DB.DBA.regexp_xfn_replace (in src varchar, in needle varchar, in tmpl varchar, in search_begin_pos integer, in hit_max_count integer, in opts varchar)
{
  declare hit_list any;
  if (0 = length (src))
    return '';
  if (regexp_parse (needle, '', 0, opts) is not null)
    signal ('22023', 'The regex-based XPATH/XQuery/SPARQL replace() function can not search for a pattern that can be found even in an empty string');
  hit_list := regexp_parse_list (needle, src, search_begin_pos, opts, coalesce (hit_max_count, 2097152));
  return regexp_replace_hits_with_template (src, tmpl, hit_list, 1);
}
;

create function DB.DBA.rdf_uuid_impl ()
{
  return iri_to_id ('urn:uuid:' || uuid());
}
;

--!AWK PUBLIC
create function DB.DBA.rdf_timezone_impl (in dt datetime)
{
  declare minutes integer;
  declare sign, str varchar;
  minutes := timezone (dt);
  if (minutes is null)
    signal ('22007', 'Function rdf_timezone_impl needs a datetime with some timezone set as its argument');
  if (minutes < 0)
    {
      sign := '-';
      minutes := -minutes;
    }
  else
    sign := '';
  if (mod (minutes, 60))
    str := sprintf ('%sPT%dH%dM', sign, minutes / 60, mod (minutes, 60));
  else if (minutes = 0)
    str := 'PT0S';
  else
    str := sprintf ('%sPT%dH', sign, minutes / 60);
  return DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL (str, __i2id (UNAME'http://www.w3.org/2001/XMLSchema#dayTimeDuration'), null);
}
;

--!AWK PUBLIC
create function DB.DBA.rdf_tz_impl (in dt datetime)
{
  declare minutes integer;
  declare sign varchar;
  minutes := timezone (dt);
  if (minutes is null)
    return '';
  if (minutes = 0)
    return 'Z';
  if (minutes < 0)
    {
      sign := '-';
      minutes := -minutes;
    }
  else
    sign := '';
  return sprintf ('%s%02d:%02d', sign, minutes / 60, mod (minutes, 60));
}
;


-----
-- Data loading

create procedure DB.DBA.RDF_QUAD_URI (in g_uri varchar, in s_uri varchar, in p_uri varchar, in o_uri varchar)
{
  declare g_iid IRI_ID;
  g_iid := iri_to_id (g_uri);
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    __rdf_repl_quad (84, iri_canonicalize (g_uri), iri_canonicalize (s_uri), iri_canonicalize (p_uri), iri_canonicalize (o_uri));
  insert soft DB.DBA.RDF_QUAD (G,S,P,O)
  values (
    g_iid,
    iri_to_id (s_uri),
    iri_to_id (p_uri),
    iri_to_id (o_uri) );
}
;

create procedure DB.DBA.RDF_QUAD_URI_L (in g_uri varchar, in s_uri varchar, in p_uri varchar, in o_lit any, in ro_id_dict any := null)
{
  declare g_iid, s_iid, p_iid IRI_ID;
  declare o_obj any;
  g_iid := iri_to_id (g_uri);
  s_iid := iri_to_id (s_uri);
  p_iid := iri_to_id (p_uri);
  o_obj := DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (o_lit, g_iid, p_iid, ro_id_dict);
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    {
      declare triples any;
      triples := vector (vector (s_iid, p_iid, o_obj));
      DB.DBA.RDF_REPL_INSERT_TRIPLES (id_to_iri (g_iid), triples);
    }
  insert soft DB.DBA.RDF_QUAD (G,S,P,O) values (g_iid, s_iid, p_iid, o_obj);
}
;

create procedure DB.DBA.RDF_QUAD_URI_L_TYPED (in g_uri varchar, in s_uri varchar, in p_uri varchar, in o_lit any, in dt any, in lang varchar, in ro_id_dict any := null)
{
  declare g_iid, s_iid, p_iid IRI_ID;
  declare o_obj any;
  g_iid := iri_to_id (g_uri);
  s_iid := iri_to_id (s_uri);
  p_iid := iri_to_id (p_uri);
  if (dt is null and lang is null)
    o_obj := DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (o_lit, g_iid, p_iid, ro_id_dict);
  else
    o_obj := DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT (o_lit, iri_to_id (dt), lang, g_iid, p_iid, ro_id_dict);
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    {
      declare triples any;
      triples := vector (vector (s_iid, p_iid, o_obj));
      DB.DBA.RDF_REPL_INSERT_TRIPLES (id_to_iri (g_iid), triples);
    }
  insert soft DB.DBA.RDF_QUAD (G,S,P,O) values (g_iid, s_iid, p_iid, o_obj);
}
;

create procedure DB.DBA.RDF_QUAD_L_RDB2RDF (in g_iid varchar, in s_iid varchar, in p_iid varchar, inout o_val any, inout old_g_iid any, inout ro_id_dict any)
{
  declare t int;
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    {
      declare triples any;
      triples := vector (vector (s_iid, p_iid, o_val));
      DB.DBA.RDF_REPL_INSERT_TRIPLES (id_to_iri (g_iid), triples);
    }
  t := __tag (o_val);
  if (__tag of rdf_box <> t)
    {
      if (not (t in (__tag of varchar, 126, 133, __tag of UNAME, __tag of nvarchar, 226)))
        {
          goto o_val_done;
        }
      if (t = 133)
	{
	  o_val := cast (o_val as nvarchar);
	  t := __tag (o_val);
	}
      if (__tag of nvarchar = t or t = 226)
        o_val := charset_recode (o_val, '_WIDE_', 'UTF-8');
      else if (t = 126)
        o_val := cast (o_val as varchar);
      else if (t = __tag of UNAME)
        {
          o_val := iri_to_id (o_val);
          goto o_val_done;
        }
      else if (bit_and (1, __box_flags (o_val)))
        {
          o_val := iri_to_id (o_val);
          goto o_val_done;
        }
    }
  if (__rdf_obj_ft_rule_check (g_iid, p_iid))
    {
      if (old_g_iid <> g_iid)
        {
          if (dict_size (ro_id_dict))
            DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (old_g_iid, ro_id_dict);
          old_g_iid := g_iid;
        }
      if (ro_id_dict is null)
        ro_id_dict := dict_new ();
      o_val := DB.DBA.RDF_OBJ_ADD (257, o_val, 257, ro_id_dict);
    }
  else
    o_val := DB.DBA.RDF_OBJ_ADD (257, o_val, 257);

o_val_done:
  if (o_val is null or s_iid is null) 
    {
      -- cannot have null values
      return;
    }
  insert soft DB.DBA.RDF_QUAD (G,S,P,O) values (g_iid, s_iid, p_iid, o_val);
}
;

create procedure DB.DBA.TTLP_EV_NEW_GRAPH (inout g varchar, inout g_iid IRI_ID, inout app_env any) {
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_NEW_GRAPH(', g, g_iid, app_env, ')');
  if (__rdf_obj_ft_rule_count_in_graph (g_iid))
    app_env[1] := dict_new (app_env[2]);
  else
    app_env[1] := null;
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    app_env[3] := g;
  else
    app_env[3] := null;
}
;

create procedure DB.DBA.TTLP_EV_NEW_BLANK (inout g_iid IRI_ID, inout app_env any, inout res IRI_ID) {
  res := iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK'));
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_NEW_BLANK (', g_iid, app_env, ') returns ', res);
}
;

create procedure DB.DBA.TTLP_EV_GET_IID (inout uri varchar, inout g_iid IRI_ID, inout app_env any, inout res IRI_ID) {
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_GET_IID (', uri, g_iid, app_env, ')');
  res := iri_to_id (uri);
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_GET_IID (', uri, g_iid, app_env, ') returns ', res);
}
;

create procedure DB.DBA.TTLP_EV_TRIPLE (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_TRIPLE (', g_iid, s_uri, p_uri, o_uri, ');');
  if (app_env[3] is not null)
    __rdf_repl_quad (84, app_env[3], iri_canonicalize (s_uri), iri_canonicalize (p_uri), iri_canonicalize (o_uri));
  insert soft DB.DBA.RDF_QUAD (G,S,P,O) values (g_iid, iri_to_id (s_uri), iri_to_id (p_uri), iri_to_id (o_uri));
}
;

create procedure DB.DBA.TTLP_EV_TRIPLE_L (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_TRIPLE_L (', g_iid, s_uri, p_uri, o_val, o_type, o_lang, app_env, ');');
  declare log_mode integer;
  declare p_iid IRI_ID;
  declare ro_id_dict any;
  if (app_env[3] is not null)
    {
      if (isstring (o_type))
        __rdf_repl_quad (81, app_env[3], iri_canonicalize (s_uri), iri_canonicalize (p_uri), o_val, iri_canonicalize (o_type), NULL);
      else if (isstring (o_lang))
        __rdf_repl_quad (82, app_env[3], iri_canonicalize (s_uri), iri_canonicalize (p_uri), o_val, null, o_lang);
      else
        __rdf_repl_quad (80, app_env[3], iri_canonicalize (s_uri), iri_canonicalize (p_uri), o_val);
    }
  log_mode := app_env[0];
  ro_id_dict := app_env[1];
  p_iid := iri_to_id (p_uri);
  if (isstring (o_type))
    {
      declare parsed any;
      parsed := __xqf_str_parse_to_rdf_box (o_val, o_type, isstring (o_val));
      if (parsed is not null)
        {
          if (__tag of XML = __tag (parsed))
            {
              insert soft DB.DBA.RDF_QUAD (G,S,P,O)
              values (g_iid, iri_to_id (s_uri), p_iid,
                DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (
                  parsed, g_iid, p_iid, ro_id_dict ) );
              return;
            }
          if (__tag of rdf_box = __tag (parsed))
	    {
	      if (256 = rdf_box_type (parsed))
		db..rdf_geo_add (parsed);
	      else
		rdf_box_set_type (parsed,
				  DB.DBA.RDF_TWOBYTE_OF_DATATYPE (iri_to_id (o_type)));
	      parsed := DB.DBA.RDF_OBJ_ADD (257, parsed, 257, ro_id_dict);
	    }
          insert soft DB.DBA.RDF_QUAD (G,S,P,O)
          values (g_iid, iri_to_id (s_uri), p_iid, parsed);
          return;
        }
      insert soft DB.DBA.RDF_QUAD (G,S,P,O)
      values (g_iid, iri_to_id (s_uri), p_iid,
        DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT (
          o_val,
          iri_to_id (o_type),
          case (isstring (o_lang)) when 0 then null else o_lang end,
          g_iid, p_iid, ro_id_dict ) );
      return;
    }
  if (isstring (o_lang))
    {
      insert soft DB.DBA.RDF_QUAD (G,S,P,O)
      values (g_iid, iri_to_id (s_uri), p_iid,
        DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL_FT (o_val, NULL, o_lang, g_iid, p_iid, ro_id_dict) );
      return;
    }
  if (isstring (o_val) or (__tag of XML = __tag (o_val)))
    {
      insert soft DB.DBA.RDF_QUAD (G,S,P,O)
      values (g_iid, iri_to_id (s_uri), p_iid,
        DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (o_val, g_iid, p_iid, ro_id_dict) );
    }
  else
    {
      insert soft DB.DBA.RDF_QUAD (G,S,P,O)
      values (g_iid, iri_to_id (s_uri), p_iid,
        o_val );
    }
}
;

create procedure DB.DBA.TTLP_EV_COMMIT (inout g varchar, inout app_env any) {
  -- dbg_obj_princ ('DB.DBA.TTLP_COMMIT(', g, app_env, ')');
  declare log_mode integer;
  declare ro_id_dict any;
  log_mode := app_env[0];
  ro_id_dict := app_env[1];
  if (ro_id_dict is not null)
    DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (iri_to_id (g), ro_id_dict);
}
;

create procedure DB.DBA.TTLP_EV_REPORT_DEFAULT (
  inout msg_no integer, inout msg_type varchar,
  inout src varchar, inout base varchar, inout graph varchar,
  inout line_no integer, inout triple_no integer,
  inout sstate varchar, inout smore varchar, inout descr varchar,
  inout env any )
{
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_REPORT_DEFAULT (', msg_no, msg_type, src, base, graph, line_no, triple_no, sstate, smore, descr, env, ')');
  ;
}
;

create procedure DB.DBA.TTLP_EV_TRIPLE_XLAT (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{
  declare xlat_cbk, s_xlat, o_xlat varchar;
  declare xlat_env any;
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_TRIPLE_XLAT (', g_iid, s_uri, p_uri, o_uri, ');');
  xlat_cbk := app_env[4];
  xlat_env := app_env[5];
  s_xlat := call(xlat_cbk)(s_uri, xlat_env);
  o_xlat := call(xlat_cbk)(o_uri, xlat_env);
  DB.DBA.TTLP_EV_TRIPLE (g_iid, s_xlat, p_uri, o_xlat, app_env);
}
;

create procedure DB.DBA.TTLP_EV_TRIPLE_L_XLAT (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  declare xlat_cbk, s_xlat varchar;
  declare xlat_env any;
  -- dbg_obj_princ ('DB.DBA.TTLP_EV_TRIPLE_L_XLAT (', g_iid, s_uri, p_uri, o_val, o_type, o_lang, app_env, ');');
  xlat_cbk := app_env[4];
  xlat_env := app_env[5];
  s_xlat := call(xlat_cbk)(s_uri, xlat_env);
  DB.DBA.TTLP_EV_TRIPLE_L (g_iid, s_xlat, p_uri, o_val, o_type, o_lang, app_env);
}
;

--!AWK PUBLIC
create procedure DB.DBA.TTLP_XLAT_CONCAT (
  inout iri varchar, inout env any )
{
  if (__tag (iri) <> __tag of varchar)
    return iri;
  if (iri like 'http://%')
    return concat (env, subseq (iri, 7));
  return iri;
}
;

create procedure DB.DBA.TTLP (in strg varchar, in base varchar, in graph varchar := null, in flags integer := 0,
	in log_enable int := null, in transactional int := 0)
{
  declare app_env any;
  declare old_log_mode int;
  declare ret any;
  if (graph = '')
    signal ('22023', 'Empty string is not a valid graph IRI in DB.DBA.TTLP()');
  else if (graph is null)
    {
      graph := base;
      if ((graph is null) or (graph = ''))
        signal ('22023', 'DB.DBA.TTLP() requires a valid IRI as a base argument if graph is not specified');
    }
  if (1 = sys_stat ('enable_vec') and not is_atomic ())
    {
      DB.DBA.TTLP_V (strg, base, graph, flags, 3, log_enable => log_enable, transactional => transactional);
      return;
    }
  old_log_mode := null;
  if (transactional = 0)
    {
      if (log_enable = 0 or log_enable = 1)
        log_enable := log_enable + 2;
    }
  if (log_enable is not null)
    {
      old_log_mode := log_enable (log_enable, 1);
    }
  if (1 <> sys_stat ('cl_run_local_only'))
    {
      DB.DBA.TTLP_CL (strg, 0, base, graph, flags);
      return;
    }
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  app_env := vector (flags, null, __max (length (strg) / 100, 100000), null);
  ret := rdf_load_turtle (strg, base, graph, flags,
    vector (
      'DB.DBA.TTLP_EV_NEW_GRAPH',
      'DB.DBA.TTLP_EV_NEW_BLANK',
      'DB.DBA.TTLP_EV_GET_IID',
      'DB.DBA.TTLP_EV_TRIPLE',
      'DB.DBA.TTLP_EV_TRIPLE_L',
      'DB.DBA.TTLP_EV_COMMIT',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    app_env);
  if (__rdf_graph_is_in_enabled_repl (iri_to_id (graph)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  return ret;
}
;

create procedure DB.DBA.TTLP_WITH_IRI_TRANSLATION (in strg varchar, in base varchar, in graph varchar, in flags integer,
	in log_enable integer, in transactional integer,
        in iri_xlate_cbk varchar, in iri_xlate_env any )
{
  declare app_env any;
  declare old_log_mode int;
  if (graph = '')
    signal ('22023', 'Empty string is not a valid graph IRI in DB.DBA.TTLP()');
  else if (graph is null)
    {
      graph := base;
      if ((graph is null) or (graph = ''))
        signal ('22023', 'DB.DBA.TTLP() requires a valid IRI as a base argument if graph is not specified');
    }
  old_log_mode := null;
  if (transactional = 0)
    {
      if (log_enable = 0 or log_enable = 1)
        log_enable := log_enable + 2;
    }
  if (log_enable is not null)
    {
      old_log_mode := log_enable (log_enable, 1);
    }
  if (1 <> sys_stat ('cl_run_local_only'))
    {
      DB.DBA.TTLP_CL (strg, 0, base, graph, flags);
      return;
    }
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  app_env := vector (flags, null, __max (length (strg) / 100, 100000), null, iri_xlate_cbk, iri_xlate_env);
  return rdf_load_turtle (strg, base, graph, flags,
    vector (
      'DB.DBA.TTLP_EV_NEW_GRAPH',
      'DB.DBA.TTLP_EV_NEW_BLANK',
      'DB.DBA.TTLP_EV_GET_IID',
      'DB.DBA.TTLP_EV_TRIPLE_XLAT',
      'DB.DBA.TTLP_EV_TRIPLE_L_XLAT',
      'DB.DBA.TTLP_EV_COMMIT',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    app_env);
}
;

create procedure DB.DBA.TTLP_VALIDATE (in strg varchar, in base varchar, in graph varchar := null, in flags integer := 0, in report_cbk varchar := '')
{
  declare app_env any;
  declare old_log_mode int;
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  return rdf_load_turtle (strg, base, graph, flags,
    vector ('', '', '', '', '', '', report_cbk),
    app_env);
}
;

create procedure DB.DBA.TTLP_VALIDATE_LOCAL_FILE (in strg varchar, in base varchar, in graph varchar := null, in flags integer := 0, in report_cbk varchar := '')
{
  declare app_env any;
  declare old_log_mode int;
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  return rdf_load_turtle_local_file (strg, base, graph, flags,
    vector ('', '', '', '', '', '', report_cbk),
    app_env);
}
;

create procedure DB.DBA.RDF_VALIDATE_RDFXML (in strg varchar, in base varchar, in graph varchar)
{
  declare app_env any;
  declare old_log_mode int;
  if (graph = '')
    signal ('22023', 'Empty string is not a valid graph IRI in DB.DBA.RDF_VALIDATE_RDFXML()');
  else if (graph is null)
    {
      graph := base;
      if ((graph is null) or (graph = ''))
        signal ('22023', 'DB.DBA.RDF_VALIDATE_RDFXML() requires a valid IRI as a base argument if graph is not specified');
    }
  rdf_load_rdfxml (strg, 0, graph, vector ( '', '', '', '', '', '', '' ), app_env, base );
  return graph;
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH (inout g varchar, inout g_iid IRI_ID, inout app_env any) {
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH(', g, g_iid, app_env, ')');
  ;
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK (inout g_iid IRI_ID, inout app_env any, inout res IRI_ID) {
  res := iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK'));
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK (', g_iid, app_env, ') returns ', res);
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_GET_IID (inout uri varchar, inout g_iid IRI_ID, inout app_env any, inout res IRI_ID) {
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2HASH_EXEC_GET_IID (', uri, g_iid, app_env, ')');
  res := iri_to_id (uri);
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2HASH_EXEC_GET_IID (', uri, g_iid, app_env, ') returns ', res);
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{
  dict_put (app_env,
    vector (iri_to_id (s_uri), iri_to_id (p_uri), iri_to_id (o_uri)),
    0 );
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  dict_put (app_env,
    vector (
      iri_to_id (s_uri),
      iri_to_id (p_uri),
      DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (o_val,
        case when (isstring (o_type) or isuname (o_type)) then o_type else null end,
        case when (isstring (o_lang) or isuname (o_lang)) then o_lang else null end) ),
    0 );
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_XLAT (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{

  declare xlat_cbk, s_xlat, o_xlat varchar;
  declare xlat_env, dict any;
  -- dbg_obj_princ (current_proc_name (), ' (', g_iid, s_uri, p_uri, o_uri, ');');
  dict := app_env[0];
  xlat_cbk := app_env[1];
  xlat_env := app_env[2];
  if (__proc_params_num (xlat_cbk) = 2)
    {
      s_xlat := call(xlat_cbk)(s_uri, xlat_env);
      o_xlat := call(xlat_cbk)(o_uri, xlat_env);
    }
  else
    {
      s_xlat := call(xlat_cbk)(s_uri, p_uri, 's', xlat_env);
      o_xlat := call(xlat_cbk)(o_uri, p_uri, 'o', xlat_env);
    }

  dict_put (dict, vector (iri_to_id (s_xlat), iri_to_id (p_uri), iri_to_id (o_xlat)), 0);
}
;

create procedure DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L_XLAT (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  declare xlat_cbk, s_xlat, o_xlat varchar;
  declare xlat_env, dict any;
  -- dbg_obj_princ (current_proc_name (),' (', g_iid, s_uri, p_uri, o_uri, ');');
  dict := app_env[0];
  xlat_cbk := app_env[1];
  xlat_env := app_env[2];
  if (__proc_params_num (xlat_cbk) = 2)
    s_xlat := call(xlat_cbk)(s_uri, xlat_env);
  else
    s_xlat := call(xlat_cbk)(s_uri, p_uri, 's', xlat_env);
  dict_put (dict,
    vector (
      iri_to_id (s_xlat),
      iri_to_id (p_uri),
      DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (o_val,
        case when (isstring (o_type) or __tag (o_type) = __tag of UNAME) then o_type else null end,
        case when (isstring (o_lang) or __tag (o_lang) = __tag of UNAME) then o_lang else null end) ),
    0);
}
;

create function DB.DBA.RDF_TTL2HASH (in strg varchar, in base varchar, in graph varchar := null, in flags integer := 0) returns any
{
  declare res any;
  res := dict_new ();
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  res := dict_new (length (strg) / 100);
  rdf_load_turtle (strg, base, graph, flags,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    res);
  return res;
}
;

create function DB.DBA.RDF_TTL_LOAD_DICT (in strg varchar, in base varchar, in graph varchar, in dict any, in flags integer := 0) returns any
{
  if (__tag (dict) <> 214)
    signal ('22023', 'RDFXX', 'The dict argument must be of type dictionary');
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  rdf_load_turtle (strg, base, graph, flags,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    dict);
  return;
}
;

create procedure DB.DBA.RDF_TTL2SQLHASH_EXEC_GET_IID (inout uri varchar, inout g_iid IRI_ID, inout app_env any, inout res IRI_ID) {
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2SQLHASH_EXEC_GET_IID (', uri, g_iid, app_env, ')');
  res := __bft (uri, 1);
  -- dbg_obj_princ ('DB.DBA.RDF_TTL2SQLHASH_EXEC_GET_IID (', uri, g_iid, app_env, ') returns ', res);
}
;

create procedure DB.DBA.RDF_TTL2SQLHASH_EXEC_TRIPLE (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{
  dict_put (app_env,
    vector (
      __bft (s_uri, 1),
      __bft (p_uri, 1),
      __bft (o_uri, 1) ),
    0 );
}
;

create procedure DB.DBA.RDF_TTL2SQLHASH_EXEC_TRIPLE_L (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  dict_put (app_env,
    vector (
      __bft (s_uri, 1),
      __bft (p_uri, 1),
      DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (o_val,
        case when (isstring (o_type) or isuname (o_type)) then o_type else null end,
        case when (isstring (o_lang) or isuname (o_lang)) then o_lang else null end) ),
    0 );
}
;

create function DB.DBA.RDF_TTL2SQLHASH (in strg varchar, in base varchar, in graph varchar := null, in flags integer := 0) returns any
{
  declare res any;
  res := dict_new ();
  if (126 = __tag (strg))
    strg := cast (strg as varchar);
  res := dict_new (length (strg) / 100);
  rdf_load_turtle (strg, base, graph, flags,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2SQLHASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2SQLHASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2SQLHASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    res);
  return res;
}
;

create procedure DB.DBA.RDF_LOAD_RDFXML_IMPL (inout strg varchar, in base varchar, in graph varchar,
  in parse_mode integer, in log_enable int := null, in transactional int := 0)
{
  declare app_env any;
  declare old_log_mode int;
  if (graph = '')
    signal ('22023', 'Empty string is not a valid graph IRI in DB.DBA.RDF_LOAD_RDFXML() and the like');
  else if (graph is null)
    {
      graph := base;
      if ((graph is null) or (graph = ''))
        signal ('22023', 'DB.DBA.RDF_LOAD_RDFXML() and similar functions require a valid IRI as a base argument if graph is not specified');
    }
  old_log_mode := null;
  if (transactional = 0)
    {
      if (log_enable = 0 or log_enable = 1)
        log_enable := log_enable + 2;
    }
  if (log_enable is not null)
    {
      old_log_mode := log_enable (log_enable, 1);
    }
  if (1 <> sys_stat ('cl_run_local_only'))
    return DB.DBA.RDF_LOAD_RDFXML_CL (strg, base, graph, parse_mode);
  if (not is_atomic ())
    return db.dba.rdf_load_rdfxml_v (strg, base, graph, transactional => transactional, log_mode => log_enable, parse_mode => parse_mode);
  app_env := vector (
    null,
    null,
    __max (length (strg) / 100, 100000),
    null );
  rdf_load_rdfxml (strg, parse_mode,
    graph,
    vector (
      'DB.DBA.TTLP_EV_NEW_GRAPH',
      'DB.DBA.TTLP_EV_NEW_BLANK',
      'DB.DBA.TTLP_EV_GET_IID',
      'DB.DBA.TTLP_EV_TRIPLE',
      'DB.DBA.TTLP_EV_TRIPLE_L',
      'DB.DBA.TTLP_EV_COMMIT',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    app_env,
    base );
  if (__rdf_graph_is_in_enabled_repl (iri_to_id (graph)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  return graph;
}
;

create procedure DB.DBA.RDF_LOAD_RDFXML (in strg varchar, in base varchar, in graph varchar := null,
  in xml_parse_mode integer := 0, in log_enable int := null, in transactional int := 0 )
{
  return DB.DBA.RDF_LOAD_RDFXML_IMPL (strg, base, graph, bit_shift (xml_parse_mode, 8), log_enable, transactional);
}
;


create procedure DB.DBA.RDF_RDFXML_TO_DICT (in strg varchar, in base varchar, in graph varchar := null)
{
  declare res any;
  res := dict_new (length (strg) / 100);
  rdf_load_rdfxml (strg, 0,
    graph,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    res,
    base );
  return res;
}
;

create procedure DB.DBA.RDF_RDFXML_LOAD_DICT (in strg varchar, in base varchar, in graph varchar, inout dict any, in flag int := 0, in xml_parse_mode int := 0)
{
  if (__tag (dict) <> 214)
    signal ('22023', 'RDFXX', 'The dict argument must be of type dictionary');
  if (flag = 0)
    xml_parse_mode := 0;
  rdf_load_rdfxml (strg, bit_or (flag, bit_shift (xml_parse_mode, 8)), -- 0 rdfxml, 2 rdfa
    graph,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    dict,
    base );
}
;

create procedure DB.DBA.RDFA_LOAD_DICT (in strg varchar, in base varchar, in graph varchar, inout dict any, in xml_parse_mode int := 0)
{
  declare app_env any;
  if (__tag (dict) <> 214)
    signal ('22023', 'RDFXX', 'The dict argument must be of type dictionary');
  rdf_load_rdfxml (strg, bit_or (2, bit_shift (xml_parse_mode, 8)), -- 0 rdfxml, 2 rdfa
    graph,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT'),
    dict,
    base );
}
;


create procedure DB.DBA.RDFA_LOAD_DICT_XLAT (in strg varchar, in base varchar, in graph varchar, inout dict any, in xml_parse_mode int := 0, in iri_xlate_cbk varchar, in iri_xlate_env any)
{
  declare app_env any;
  if (__tag (dict) <> 214)
    signal ('22023', 'RDFXX', 'The dict argument must be of type dictionary');
  rdf_load_rdfxml (strg, bit_or (2, bit_shift (xml_parse_mode, 8)), -- 0 rdfxml, 2 rdfa
    graph,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_XLAT',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L_XLAT',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    vector (dict, iri_xlate_cbk, iri_xlate_env),
    base );
}
;



create procedure DB.DBA.RDF_RDFA11_FETCH_PROFILES (in profile_iris any, inout prefixes any, inout terms any, inout vocab any)
{
  declare agg any;
  -- dbg_obj_princ ('DB.DBA.RDF_RDFA11_FETCH_PROFILES (', profile_iris, ')');
  foreach (varchar profile_iri in profile_iris) do
    {
      if (not exists (sparql define input:storage "" ask where { graph `iri(?:profile_iri)` { ?s ?p ?o }}))
        DB.DBA.SPARUL_LOAD (profile_iri, profile_iri, 0, NULL, 0);
    }
  vectorbld_init (agg);
  foreach (varchar profile_iri in profile_iris) do
    {
      for (sparql define input:storage "" prefix rdfa: <http://www.w3.org/ns/rdfa#>
        select ?p, ?u
        where {
            graph `iri(?:profile_iri)` {
                ?s rdfa:prefix ?p ; rdfa:uri ?u .
                optional { ?s rdfa:uri ?u2 . filter (?u != ?u2). }
                filter (isliteral (?p))
                filter (isliteral (?u))
                filter (?u != '')
                filter (!bound (?u2)) } }
        ) do { vectorbld_acc (agg, "p", "u"); }
    }
  vectorbld_final (agg);
  prefixes := agg;
  vectorbld_init (agg);
  foreach (varchar profile_iri in profile_iris) do
    {
      for (sparql define input:storage "" prefix rdfa: <http://www.w3.org/ns/rdfa#>
        select ?t, ?u
        where {
            graph `iri(?:profile_iri)` {
                ?s rdfa:term ?t ; rdfa:uri ?u .
                optional { ?s rdfa:uri ?u2 . filter (?u != ?u2). }
                optional { ?s rdfa:term ?t2 . filter (?t != ?t2). }
                filter (isliteral (?t))
                filter (isliteral (?u))
                filter (?t != '')
                filter (?u != '')
                filter (!bound (?t2))
                filter (!bound (?u2)) } }
        order by ?t
        ) do { vectorbld_acc (agg, "t", "u"); }
    }
  vectorbld_final (agg);
  if (1 < length (profile_iris))
    gvector_sort (agg, 2, 0, 1);
  terms := agg;
  vocab := null;
  foreach (varchar profile_iri in profile_iris) do
    {
      vocab := (sparql define input:storage "" prefix rdfa: <http://www.w3.org/ns/rdfa#>
        select (max(str(?v)))
        where {
            graph `iri(?:profile_iri)` {
                ?s rdfa:vocabulary ?v } } );
      if (isstring (vocab))
        goto vocab_is_set;
    }
vocab_is_set: ;
  -- dbg_obj_princ ('DB.DBA.RDF_RDFA11_FETCH_PROFILES (', profile_iris, ' returned ', prefixes, terms, vocab);
}
;


create procedure DB.DBA.RDF_LOAD_RDFA (in strg varchar, in base varchar, in graph varchar := null,
  in xml_parse_mode integer := 0, in log_enable int := null, in transactional int := 0 )
{
  return DB.DBA.RDF_LOAD_RDFXML_IMPL (strg, base, graph, bit_or (2, bit_shift (xml_parse_mode, 8)), log_enable, transactional);
}
;

create procedure DB.DBA.RDF_LOAD_RDFA_WITH_IRI_TRANSLATION (in strg varchar, in base varchar, in graph varchar, in xml_parse_mode integer,
  in iri_xlate_cbk varchar, in iri_xlate_env any)
{
  declare app_env any;
  if (graph = '')
    signal ('22023', 'Empty string is not a valid graph IRI in DB.DBA.RDF_LOAD_RDFA_WITH_IRI_TRANSLATION ()');
  else if (graph is null)
    {
      graph := base;
      if ((graph is null) or (graph = ''))
        signal ('22023', 'DB.DBA.RDF_LOAD_RDFA_WITH_IRI_TRANSLATION () requires a valid IRI as a base argument if graph is not specified');
    }
  if (1 <> sys_stat ('cl_run_local_only'))
    return DB.DBA.RDF_LOAD_RDFA_WITH_IRI_TRANSLATION_CL (strg, base, graph, xml_parse_mode, iri_xlate_cbk, iri_xlate_env);
  app_env := vector (
    null,
    null,
    __max (length (strg) / 100, 100000),
    null,
    iri_xlate_cbk,
    iri_xlate_env );
  rdf_load_rdfxml (strg, bit_or (2, bit_shift (xml_parse_mode, 8)),
    graph,
    vector (
      'DB.DBA.TTLP_EV_NEW_GRAPH',
      'DB.DBA.TTLP_EV_NEW_BLANK',
      'DB.DBA.TTLP_EV_GET_IID',
      'DB.DBA.TTLP_EV_TRIPLE_XLAT',
      'DB.DBA.TTLP_EV_TRIPLE_L_XLAT',
      'DB.DBA.TTLP_EV_COMMIT',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    app_env,
    base );
  if (__rdf_graph_is_in_enabled_repl (iri_to_id (graph)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  return graph;
}
;

create procedure DB.DBA.RDF_RDFA_TO_DICT (in strg varchar, in base varchar, in graph varchar := null)
{
  declare res any;
  res := dict_new (length (strg) / 100);
  rdf_load_rdfxml (strg, 2,
    graph,
    vector (
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_GRAPH',
      'DB.DBA.RDF_TTL2HASH_EXEC_NEW_BLANK',
      'DB.DBA.RDF_TTL2HASH_EXEC_GET_IID',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE',
      'DB.DBA.RDF_TTL2HASH_EXEC_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    res,
    base );
  return res;
}
;

create procedure DB.DBA.RDF_LOAD_XHTML_MICRODATA (in strg varchar, in base varchar, in graph varchar := null,
  in xml_parse_mode integer := 1, in log_enable int := null, in transactional int := 0 )
{
  return DB.DBA.RDF_LOAD_RDFXML_IMPL (strg, base, graph, bit_or (4, bit_shift (xml_parse_mode, 8)), log_enable, transactional);
}
;

-----
-- Fast rewriting from serialization to serialization without storing

--!AWK PUBLIC
create procedure DB.DBA.RDF_XML_IRI_TO_TTL (inout obj any, inout ses any)
{
  declare res varchar;
  if (isiri_id (obj))
    {
      if (obj >= min_bnode_iri_id ())
        {
          if (obj >= #ib0)
            http (sprintf ('_:bb%d ', iri_id_num (obj) - iri_id_num (#ib0)), ses);
          else
            http (sprintf ('_:b%d ', iri_id_num (obj)), ses);
        }
      else
        {
          res := coalesce (id_to_iri (obj), sprintf ('_:bad_iid_%d', iri_id_num (obj)));
--          res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = obj), sprintf ('_:bad_iid_%d', iri_id_num (obj)));
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
    }
  else if (__tag of varchar = __tag (obj))
    {
      if ("LEFT" (obj, 9) = 'nodeID://')
        {
          http ('_:', ses);
          http (subseq (obj, 9), ses);
          http (' ', ses);
        }
      else
        {
          http ('<', ses);
          http_escape (obj, 12, ses, 1, 1);
          http ('> ', ses);
        }
    }
  else
    {
      http ('<', ses);
      http_escape (cast (obj as varchar), 12, ses, 1, 1);
      http ('> ', ses);
    }
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_XML_OBJ_TO_TTL (
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout ses any)
{
  declare res varchar;
  if (isiri_id (o_val))
    {
      if (o_val >= min_bnode_iri_id ())
        {
          if (o_val >= #ib0)
            http (sprintf ('_:bb%d ', iri_id_num (o_val) - iri_id_num (#ib0)), ses);
          else
            http (sprintf ('_:b%d ', iri_id_num (o_val)), ses);
        }
      else
        {
          res := coalesce (id_to_iri (o_val), sprintf ('_:bad_iid_%d', iri_id_num (o_val)));
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
      return;
    }
  http ('"', ses);
  if (__tag of XML = o_val)
    http_escape (serialize_to_UTF8_xml (o_val), 11, ses, 1, 1);
  else
    http_escape (o_val, 11, ses, 1, 1);
  if (isstring (o_type))
    {
      http ('"^^<', ses);
      http_escape (o_type, 12, ses, 1, 1);
      http ('> ', ses);
    }
  else if (isstring (o_lang))
    {
      http ('"@', ses);
      http (o_lang, ses);
      http (' ', ses);
    }
  else
    http ('" ', ses);
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_NEW_BLANK (inout g_iid IRI_ID, inout app_env any, inout res IRI_ID)
{
  ; -- empty procedure
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_TRIPLE (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_uri varchar,
  inout app_env any )
{
  DB.DBA.RDF_XML_IRI_TO_TTL (s_uri, app_env);
  DB.DBA.RDF_XML_IRI_TO_TTL (p_uri, app_env);
  DB.DBA.RDF_XML_IRI_TO_TTL (o_uri, app_env);
  http ('.\n', app_env);
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_TRIPLE_L (
  inout g_iid IRI_ID, inout s_uri varchar, inout p_uri varchar,
  inout o_val any, inout o_type varchar, inout o_lang varchar,
  inout app_env any )
{
  DB.DBA.RDF_XML_IRI_TO_TTL (s_uri, app_env);
  DB.DBA.RDF_XML_IRI_TO_TTL (p_uri, app_env);
  DB.DBA.RDF_XML_OBJ_TO_TTL (o_val, o_type, o_lang, app_env);
  http ('.\n', app_env);
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_CONVERT_RDFXML_TO_TTL (in strg varchar, in base varchar, inout ttl_ses any)
{
  rdf_load_rdfxml (strg, 0,
    'http://example.com',
    vector (
      '',
      'DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_NEW_BLANK',
      'DB.DBA.TTLP_EV_GET_IID',
      'DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_TRIPLE',
      'DB.DBA.RDF_CONVERT_RDFXML_TO_TTL_EV_TRIPLE_L',
      '',
      'DB.DBA.TTLP_EV_REPORT_DEFAULT' ),
    ttl_ses,
    base );
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_CONVERT_RDFXML_FILE_TO_TTL_FILE (in rdfxml_source_filename varchar, in base varchar, in ttl_target_filename varchar)
{
  declare in_ses, out_ses any;
  in_ses := file_to_string_output (rdfxml_source_filename);
  out_ses := string_output ();
  DB.DBA.RDF_CONVERT_RDFXML_TO_TTL (in_ses, base, out_ses);
  string_to_file (ttl_target_filename, out_ses, -2);
}
;

-----
-- Export into external serializations

create procedure DB.DBA.RDF_LONG_TO_TTL (inout obj any, inout ses any)
{
  declare res varchar;
  if (obj is null)
    signal ('RDFXX', 'DB.DBA.RDF_LONG_TO_TTL(): object is NULL');
  if (isiri_id (obj))
    {
      if (obj >= min_bnode_iri_id ())
        {
          if (obj >= #ib0)
            http (sprintf ('_:bb%d ', iri_id_num (obj) - iri_id_num (#ib0)), ses);
          else
            http (sprintf ('_:b%d ', iri_id_num (obj)), ses);
        }
      else
        {
          res := coalesce (id_to_iri (obj), sprintf ('_:bad_iid_%d', iri_id_num (obj)));
--          res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = obj), sprintf ('_:bad_iid_%d', iri_id_num (obj)));
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
    }
  else if (__tag of rdf_box = __tag (obj))
    {
      declare dt_iri varchar;
      if (257 <> rdf_box_type (obj))
        {
          dt_iri := coalesce ((select RDT_QNAME from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
          if (dt_iri is null)
            signal ('RDFXX', sprintf ('Bad rdf box type (%d), box "%s"', rdf_box_type (obj), cast (rdf_box_data (obj) as varchar)));
          if (dt_iri = 'http://www.w3.org/2001/XMLSchema#boolean' and rdf_box_data_tag (obj) = __tag of integer)
            {
              http (case sparql_ebv_of_obj (obj) when 0 then '"false"^^<' else '"true"^^<' end, ses);
              http ('http://www.w3.org/2001/XMLSchema#boolean> ', ses);
              return;
            }
        }
      else
        dt_iri := null;
      http ('"', ses);
      if (rdf_box_data_tag (obj) in (__tag of varchar, __tag of long varchar, __tag of nvarchar, __tag of long nvarchar, 185))
        http_escape (__rdf_sqlval_of_obj (obj, 1), 11, ses, 1, 1);
      else if (__tag of datetime = rdf_box_data_tag (obj))
        __rdf_long_to_ttl (obj, ses);
      else if (__tag of XML = rdf_box_data_tag (obj))
        http_escape (serialize_to_UTF8_xml (__rdf_sqlval_of_obj (obj, 1)), 11, ses, 1, 1);
      else if (__tag of varbinary = rdf_box_data_tag (obj))
        {
          http ('"', ses);
          http_escape (__rdf_sqlval_of_obj (obj, 1), 11, ses, 0, 0);
          http ('" ', ses);
        }
      else
        http_escape (cast (__rdf_sqlval_of_obj (obj, 1) as varchar), 11, ses, 1, 1);
      if (dt_iri is not null)
        {
          http ('"^^<', ses);
          http_escape (dt_iri, 12, ses, 1, 1);
          http ('> ', ses);
        }
      else if (257 <> rdf_box_lang (obj))
        {
          res := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
          http ('"@', ses); http (res, ses); http (' ', ses);
        }
      else
        http ('" ', ses);
    }
  else if (__tag of varchar = __tag (obj))
    {
      if (1 = __box_flags (obj))
        {
          http ('<', ses);
          http_escape (obj, 12, ses, 1, 1);
          http ('> ', ses);
        }
      else
        {
          http ('"', ses);
          http_escape (obj, 11, ses, 1, 1);
          http ('" ', ses);
        }
    }
  else if (__tag (obj) in (__tag of long varchar, __tag of nvarchar, __tag of long nvarchar, 185))
    {
      http ('"', ses);
      http_escape (obj, 11, ses, 1, 1);
      http ('" ', ses);
    }
  else if (__tag of datetime = rdf_box_data_tag (obj))
    {
      http ('"', ses);
     __rdf_long_to_ttl (obj, ses);
      http ('"^^<', ses);
      http_escape (cast (__xsd_type (obj) as varchar), 12, ses, 1, 1);
      http ('> ', ses);
    }
  else if (__tag of varbinary =  __tag (obj))
    {
      http ('"', ses);
      http_escape (obj, 11, ses, 0, 0);
      http ('" ', ses);
    }
  else
    {
      http ('"', ses);
      http_escape (__rdf_strsqlval (obj), 11, ses, 1, 1);
      http ('"^^<', ses);
      http_escape (cast (__xsd_type (obj) as varchar), 12, ses, 1, 1);
      http ('> ', ses);
    }
}
;


create procedure DB.DBA.RDF_TRIPLES_TO_VERBOSE_TTL (inout triples any, inout ses any)
{
  declare tcount, tctr integer;
  declare prev_s, prev_p IRI_ID;
  declare res varchar;
  declare string_subjs_found, string_preds_found integer;
  string_subjs_found := 0;
  string_preds_found := 0;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_VERBOSE_TTL:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('# Empty TURTLE\n', ses);
      return;
    }
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj,pred any;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      if (not (isiri_id (subj)))
        {
          if (isstring (subj) and (1 = __box_flags (subj)))
            string_subjs_found := 1;
          else
            {
              if (subj is null)
                signal ('RDFXX', 'DB.DBA.TRIPLES_TO_TTL(): subject is NULL');
              signal ('RDFXX', 'DB.DBA.TRIPLES_TO_TTL(): subject is literal');
            }
        }
      if (not isiri_id (pred))
        {
          if (isstring (pred) and (1 = __box_flags (pred)))
            string_preds_found := 1;
          else
            {
              if (pred is null)
                signal ('RDFXX', 'DB.DBA.TRIPLES_TO_TTL(): predicate is NULL');
              signal ('RDFXX', 'DB.DBA.TRIPLES_TO_TTL(): predicate is literal');
            }
        }
      if (pred >= min_bnode_iri_id ())
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_TTL(): blank node as predicate');
    }
  if (not string_preds_found)
    rowvector_digit_sort (triples, 1, 1);
  if (not string_subjs_found)
    rowvector_digit_sort (triples, 0, 1);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  prev_s := null;
  prev_p := null;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj,pred,obj any;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      if (prev_s = subj)
        {
          if (prev_p = pred)
            {
              http (',\n\t\t', ses);
              goto print_o;
            }
          http (';\n\t', ses);
          goto print_p;
        }
      if (prev_s is not null)
        http ('.\n', ses);
      if (isstring (subj))
        {
          if (subj like 'nodeID://%')
            {
              http ('_:', ses);
              http_escape (subseq (subj, 9), 12, ses, 1, 1);
	      http (' ', ses);
            }
          else
            {
              http ('<', ses);
              http_escape (subj, 12, ses, 1, 1);
              http ('> ', ses);
            }
        }
      else if (subj >= min_bnode_iri_id ())
        {
          if (subj >= #ib0)
            http (sprintf ('_:bb%d ', iri_id_num (subj) - iri_id_num (#ib0)), ses);
          else
            http (sprintf ('_:b%d ', iri_id_num (subj)), ses);
        }
      else
        {
          res := id_to_iri (subj);
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
	  http ('> ', ses);
        }
      prev_s := subj;
      prev_p := null;
print_p:
      if (isstring (pred))
        {
          if (pred like 'nodeID://%')
            {
              http ('_:', ses);
              http_escape (subseq (pred, 9), 12, ses, 1, 1);
	      http (' ', ses);
            }
          else
            {
              http ('<', ses);
              http_escape (pred, 12, ses, 1, 1);
              http ('> ', ses);
            }
        }
      else
        {
          res := id_to_iri (pred);
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
      prev_p := pred;
print_o:
      DB.DBA.RDF_LONG_TO_TTL (obj, ses);
    }
  http ('.\n', ses);
}
;

create function DB.DBA.RDF_TRIPLES_TO_TTL_ENV (in tcount integer, in env_flags integer, in col_metas any, inout ses any)
{
  return vector (dict_new (__min (tcount, 16000)), 0, '', '', '', 0, 0, env_flags, col_metas, ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_TTL (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_TTL:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('# Empty TURTLE\n', ses);
      return;
    }
  env := DB.DBA.RDF_TRIPLES_TO_TTL_ENV (tcount, 0, 0, ses);
  { whenever sqlstate '*' goto end_pred_sort;
    rowvector_subj_sort (triples, 1, 1);
end_pred_sort: ;
  }
  { whenever sqlstate '*' goto end_subj_sort;
    rowvector_subj_sort (triples, 0, 1);
end_subj_sort: ;
  }
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      http_ttl_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
    }
  http (' .', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_TRIG (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr, first_dflt_g_idx integer;
  declare prev_g_iri varchar;
  declare first_g_idx integer;
  tcount := length (triples);
  if (0 = tcount)
    {
      http ('# Empty TriG\n', ses);
      return;
    }
  env := DB.DBA.RDF_TRIPLES_TO_TTL_ENV (tcount, 0, 0, ses);
  { whenever sqlstate '*' goto end_pred_sort;
    rowvector_subj_sort (triples, 1, 1);
end_pred_sort: ;
  }
  { whenever sqlstate '*' goto end_subj_sort;
    rowvector_subj_sort (triples, 0, 1);
end_subj_sort: ;
  }
  rowvector_graph_sort (triples, 3, 1);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_TRIG after sort:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; (tctr < tcount) and aref_or_default (triples, tctr, 3, null) is null; tctr := tctr + 1)
    {
      http_ttl_prefixes (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
    }
  first_g_idx := tctr;
  for (tctr := first_g_idx; tctr < tcount; tctr := tctr + 1)
    {
      http_ttl_prefixes (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
    }
  if (0 < first_g_idx)
    {
      http ('{\n', ses);
      for (tctr := 0; tctr < first_g_idx; tctr := tctr + 1)
        {
          http_ttl_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
        }
      http (' .\n}\n', ses);
    }
  prev_g_iri := '';
  for (tctr := first_g_idx; tctr < tcount; tctr := tctr + 1)
    {
      declare g_iri varchar;
      g_iri := id_to_iri_nosignal (triples[tctr][3]);
      if (g_iri is not null)
        {
          if (g_iri <> prev_g_iri)
            {
              if (prev_g_iri <> '')
                http (' .\n}\n', ses);
              env[1] := 0;
              http ('<', ses);
              http_escape (g_iri, 12, ses, 1, 1);
              http ('> = {\n', ses);
              prev_g_iri := g_iri;
            }
          http_ttl_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
        }
    }
  if (prev_g_iri <> '')
    http (' .\n}\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_NT (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_TTL:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('# Empty NT\n', ses);
      return;
    }
  env := vector (0, 0, 0);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      http_nt_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
    }
}
;

create procedure DB.DBA.RDF_GRAPH_TO_TTL (in graph_iri varchar, inout ses any)
{
  declare tcount integer;
  declare res varchar;
  declare prev_s, prev_p IRI_ID;
  -- dbg_obj_princ ('DB.DBA.RDF_GRAPH_TO_TTL (', graph_iri, ', ...)');
  tcount := 0;
  prev_s := null;
  prev_p := null;
  for (select S as subj, P as pred, O as obj from DB.DBA.RDF_QUAD where G = iri_to_id (graph_iri)) do
    {
      if (prev_s = subj)
        {
          if (prev_p = pred)
            {
              http (',\n\t\t', ses);
              goto print_o;
            }
          http (';\n\t', ses);
          goto print_p;
        }
      if (prev_s is not null)
        http ('.\n', ses);
      if (subj >= min_bnode_iri_id ())
        {
          if (subj >= #ib0)
            http (sprintf ('_:bb%d ', iri_id_num (subj) - iri_id_num (#ib0)), ses);
          else
            http (sprintf ('_:b%d ', iri_id_num (subj)), ses);
        }
      else
        {
          res := id_to_iri (subj);
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
      prev_s := subj;
      prev_p := null;
print_p:
      if (pred >= min_bnode_iri_id ())
        signal ('RDFXX', 'DB.DBA.RDF_GRAPH_TO_TTL(): blank node as predicate');
      else
        {
          res := id_to_iri (pred);
          http ('<', ses);
          http_escape (res, 12, ses, 1, 1);
          http ('> ', ses);
        }
      prev_p := pred;
print_o:
       DB.DBA.RDF_LONG_TO_TTL (obj, ses);
       tcount := tcount + 1;
    }
  if (0 = tcount)
    http ('# Empty TURTLE\n', ses);
  else
    http ('.\n', ses);
}
;

--create procedure DB.DBA.TEST_SPARQL_TTL (in query varchar, in dflt_graph varchar)
--{
--  declare ses, rset, triples any;
--  declare txt varchar;
--  ses := string_output ();
--  rset := DB.DBA.SPARQL_EVAL_TO_ARRAY (query, dflt_graph, 1);
--  triples := dict_list_keys (rset[0][0], 1);
--  DB.DBA.RDF_TRIPLES_TO_TTL (triples, ses);
--  txt := string_output_string (ses);
--  dump_large_text (txt);
--}
--;

create procedure DB.DBA.RDF_TRIPLES_TO_RDF_XML_TEXT (inout triples any, in print_top_level integer, inout ses any)
{
  declare ns_dict, env any;
  declare tcount, tctr integer;
  tcount := length (triples);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  { whenever sqlstate '*' goto end_pred_sort;
    rowvector_subj_sort (triples, 1, 1);
end_pred_sort: ;
  }
  ns_dict := dict_new (case (print_top_level) when 0 then 10 else __min (tcount, 16000) end);
  dict_put (ns_dict, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf');
  dict_put (ns_dict, 'http://www.w3.org/2000/01/rdf-schema#', 'rdfs');
  env := vector (ns_dict, 0, 0, '', '', 0, 0, 0, 0, 0);
  if (print_top_level)
    {
       http ('<?xml version="1.0" encoding="utf-8" ?>\n<rdf:RDF\n\txmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n\txmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"', ses);
       for (tctr := 0; tctr < tcount; tctr := tctr + 1)
         {
           http_rdfxml_p_ns (env, triples[tctr][1], ses);
         }
       http (' >', ses);
    }
  { whenever sqlstate '*' goto end_subj_sort;
    rowvector_subj_sort (triples, 0, 1);
end_subj_sort: ;
  }
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      http_rdfxml_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
    }
  if (isstring (env[2]))
    http ('\n  </rdf:Description>', ses);
  if (print_top_level)
    {
      http ('\n</rdf:RDF>', ses);
    }
}
;

--create procedure DB.DBA.TEST_SPARQL_RDF_XML_TEXT (in query varchar, in dflt_graph varchar)
--{
--  declare ses, rset, triples any;
--  declare txt varchar;
--  ses := string_output ();
--  rset := DB.DBA.SPARQL_EVAL_TO_ARRAY (query, dflt_graph, 1);
--  triples := dict_list_keys (rset[0][0], 1);
--  DB.DBA.RDF_TRIPLES_TO_RDF_XML_TEXT (triples, 1, ses);
--  txt := string_output_string (ses);
--  dump_large_text (txt);
--}
--;

create procedure DB.DBA.RDF_TRIPLES_TO_TALIS_JSON (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr, status integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_TALIS_JSON:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('{ }\n', ses);
      return;
    }
  env := vector (0, 0, 0, null);
-- No error handlers here because failed sorting by predicate or subject would result in poorly structured output.
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  http ('{\n  ', ses);
  status := 0;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      if (http_talis_json_triple (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses))
        status := 1;
    }
  if (status)
    http (' ] }\n', ses);
  http ('}\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_JSON_LD (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr, nesting integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_LD:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('{ }\n', ses);
      return;
    }
  env := vector (0, 0, 0, null);
-- No error handlers here because failed sorting by predicate or subject would result in poorly structured output.
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  http ('{ "@graph": [\n    ', ses);
  nesting := http_ld_json_triple_batch (env, triples, ses);
  if (nesting > 1)
    http (' ]', ses);
  if (nesting)
    http (' }\n', ses);
  http ('] }\n', ses);
}
;

-- The function calculates data needed for writing triples in nested form, resulting in dominance subgraphs.
-- If \c trees4all is nonzero then both named and blank nodes may form hierarchies and uses of one node as an object for multiple subjects does not prevent from making trees.
-- If \c trees4all is zero then only blank nodes may form hierarchies and hierarchy is built only if a bnode is used as an object for a single triple.
create procedure DB.DBA.RDF_TRIPLES_DOMINANCE_DATA (inout triples any, in trees4all integer, out bnode_usage_dict_ret any, out tail_to_head_dict_ret any, out printed_triples_mask_ret varchar)
{
  declare bnode_usage_dict any;
-- Keys of bnode_usage_dict are IRI_IDs of all blank nodes of the \c triples,
-- values are vectors of six items
-- [0]:
--     If \c trees4all is nonzero then
--       NULL if key node is not used as object OR IRI_ID of some subject such that the key node is object.
--     If \c trees4all is zero then
--       NULL if key bnode is not used as object OR IRI_ID of subject of a single triple such that the key bnode is object OR an empty string UNAME if the key bnode is used as object many times or makes a loop made of anonymous bnodes.
-- [1]: Index of first triple where the bnode appears as a subject, NULL if there are no such.
-- [2]: temporary integer to check for loops
-- [3]: NULL if key bnode does not have rdf:first property OR an integer index of that rdf:first triple in \c triples OR an empty string UNAME if the key bnode has many values of rdf:first or non-list predicates.
-- [4]: NULL if key bnode does not have rdf:rest property OR an integer index of that rdf:rest triple in \c triples OR an empty string UNAME if the key bnode has many values of rdf:rest or non-list predicates.
-- [5]: NULL if not in the list or not yet checked OR an integer that indicates the length of proper tail of the list OR an empty string UNAME if the list is ended up with cycle or something weird.
  declare tail_to_head_dict any;
-- Keys of tail_to_head_dict are last bnodes of lists, values are first bnodes of (valid parts of) lists OR empty string UNAME for last bnodes that were later proven to be inappropriate.
  declare printed_triples_mask varchar;
  declare rdf_first_iid, rdf_rest_iid, rdf_nil_iid IRI_ID;
  declare all_bnodes any;
  declare tcount, tctr, bnode_ctr integer;
  declare tail_bnode, head_bnode IRI_ID;
  tcount := length (triples);
  printed_triples_mask := space (tcount);
  rowvector_obj_sort (triples, 2, 1);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  rdf_first_iid	:= iri_to_id ('http://www.w3.org/1999/02/22-rdf-syntax-ns#first');
  rdf_rest_iid	:= iri_to_id ('http://www.w3.org/1999/02/22-rdf-syntax-ns#rest');
  rdf_nil_iid	:= iri_to_id ('http://www.w3.org/1999/02/22-rdf-syntax-ns#nil');
-- First of all we gather info into bnode_usage_dict, except items #2 and #5 of values
  bnode_usage_dict := dict_new (13 + (tcount / 100));
  tail_to_head_dict := dict_new (13 + (tcount / 1000));
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare s_iid, o_iid IRI_ID;
      -- dbg_obj_princ ('Gathering ', tctr, '/', tcount, triples[tctr][0], triples[tctr][1], triples[tctr][2]);
      if (triples[tctr][0] is null or triples[tctr][1] is null or triples[tctr][2] is null)
        {
          printed_triples_mask[tctr] := ascii ('N');
          goto triple_skipped;
        }
      s_iid := iri_to_id_nosignal (triples[tctr][0]);
      o_iid := iri_to_id_nosignal (triples[tctr][2]);
      if (trees4all or is_bnode_iri_id (s_iid))
        {
          declare p_iid IRI_ID;
          declare u any;
          p_iid := iri_to_id_nosignal (triples[tctr][1]);
          u := dict_get (bnode_usage_dict, s_iid, null);
          if (u is null)
            u := vector (null, tctr, null, null, null, null);
          else if (u[1] is null)
            u[1] := tctr;
          if (trees4all)
            goto s_iid_done;
          if (rdf_first_iid = p_iid)
            {
              if (u[3] is null)
                {
                  u[3] := tctr;
                  goto s_iid_done;
                }
              else
                goto bad_for_list;
            }
          else if (rdf_rest_iid = p_iid)
            {
              if (u[4] is not null)
                goto bad_for_list;
              else if (rdf_nil_iid = o_iid)
                {
                  dict_put (tail_to_head_dict, s_iid, s_iid);
                  u[4] := tctr;
                  goto s_iid_done;
                }
              else if (is_bnode_iri_id (o_iid))
                {
                  u[4] := tctr;
                  goto s_iid_done;
                }
              else
                goto bad_for_list;
            }
bad_for_list:
          u[3] := UNAME'';
          u[4] := UNAME'';
          if (dict_get (tail_to_head_dict, s_iid, null) is not null)
            dict_put (tail_to_head_dict, s_iid, UNAME'');
s_iid_done:
          dict_put (bnode_usage_dict, s_iid, u);
        }
      if (trees4all or is_bnode_iri_id (o_iid))
        {
          declare u any;
          u := dict_get (bnode_usage_dict, o_iid, null);
          if (u is null)
            dict_put (bnode_usage_dict, o_iid, vector (s_iid, null, null, null, null, null));
          else
            {
              if (u[0] is null)
                u[0] := s_iid;
              else
                u[0] := UNAME'';
              dict_put (bnode_usage_dict, o_iid, u);
            }
        }
triple_skipped: ;
    }
-- Now it's possible to check for loops
  all_bnodes := dict_list_keys (bnode_usage_dict, 0);
  gvector_sort (all_bnodes, 1, 0, 1);
  for (bnode_ctr := length (all_bnodes) - 1; bnode_ctr >= 0; bnode_ctr := bnode_ctr - 1)
    {
      declare top_bn_iid, next_bn_iid IRI_ID;
      declare u, top_u, next_u any;
      top_bn_iid := all_bnodes[bnode_ctr];
      u := dict_get (bnode_usage_dict, top_bn_iid, null);
next_loop_check:
      if (u[5] is not null)
        goto bn_iid_done;
      if (u[2] = bnode_ctr)
        {
          while (u[5] is not null)
            {
              -- dbg_obj_princ ('Marking as part of a loop: ', top_bn_iid, u);
              next_bn_iid := u[0];
              u[5] := UNAME'';
              dict_put (bnode_usage_dict, top_bn_iid, u);
              top_bn_iid := next_bn_iid;
              u := dict_get (bnode_usage_dict, top_bn_iid, null);
            }
          goto bn_iid_done;
        }
      next_bn_iid := u[0];
      u[2] := bnode_ctr;
      dict_put (bnode_usage_dict, top_bn_iid, u);
      if (not case trees4all when 0 then is_bnode_iri_id (next_bn_iid) else isiri_id (next_bn_iid) end)
        goto bn_iid_done;
      next_u := dict_get (bnode_usage_dict, next_bn_iid, null);
      top_bn_iid := next_bn_iid;
      u := next_u;
      goto next_loop_check;
bn_iid_done: ;
    }
-- Now it is possible to check list nodes
  if (not trees4all)
    {
      dict_iter_rewind (tail_to_head_dict);
      while (dict_iter_next (tail_to_head_dict, tail_bnode, head_bnode))
        {
          declare u, next_u any;
          declare last_good_head_bnode, next_bn_iid IRI_ID;
          declare len_ctr integer;
          len_ctr := 0;
          last_good_head_bnode := head_bnode;
          -- dbg_obj_princ ('Loop from ', tail_bnode, ' to ', head_bnode);
          while (is_bnode_iri_id (head_bnode))
            {
              u := dict_get (bnode_usage_dict, head_bnode, null);
              if (isinteger (u[3]) and isinteger (u[4]) and u[5] is null)
                {
                  -- dbg_obj_princ ('Reached ', head_bnode, u, ' from ', last_good_head_bnode);
                  last_good_head_bnode := head_bnode;
                  u[5] := len_ctr;
                  len_ctr := len_ctr + 1;
                  dict_put (bnode_usage_dict, head_bnode, u);
                  next_bn_iid := u[0];
                  next_u := dict_get (bnode_usage_dict, next_bn_iid, null);
                  if (next_u is not null and isinteger (next_u[4]) and (triples[next_u[4]][2] = head_bnode))
                    {
                      head_bnode := next_bn_iid;
                      u := next_u;
                    }
                  else
                    {
                      -- dbg_obj_princ ('Rejected ', head_bnode, u, ' from last goood ', last_good_head_bnode);
                      head_bnode := null;
                    }
                }
              else
                {
                  -- dbg_obj_princ ('Rejected ', head_bnode, u, ' from ', last_good_head_bnode);
                  u[5] := UNAME'';
                  dict_put (bnode_usage_dict, head_bnode, u);
                  head_bnode := null;
                }
            }
        }
    }
  bnode_usage_dict_ret := bnode_usage_dict;
  tail_to_head_dict_ret := tail_to_head_dict;
  printed_triples_mask_ret := printed_triples_mask;
}
;

create function DB.DBA.JSON_LD_CTX_USED_NAMES (in ctx_dict any)
{
  declare used_names any;
  declare k,v any;
  used_names := dict_new (dict_size (ctx_dict));
  dict_iter_rewind (ctx_dict);
  while (dict_iter_next (ctx_dict, k, v))
    if (k[3] is not null)
      {
        declare prev_use any;
        prev_use := dict_get (used_names, v[0], null);
        if (k[3] is not null and prev_use is not null)
          signal ('22023', 'JSON-LD context dictionary is invalid, it uses shortcut "' || dict_get (used_names, v[0], null)
            || '" for both <' || k[0] || '> with ' || k[3] || ' and <' || prev_use[0] || '> with ' || prev_use[3] );
        dict_put (used_names, v[0], k);
      }
  return used_names;
}
;

create function DB.DBA.JSON_LD_CTX_MAKE_NEW_SHORTCUT (in p varchar, in otype varchar, in used_names any)
{
  declare old_k any;
  declare p_tail, otype_tail integer;
  declare orig_p, shortcut, short2, o_suffix varchar;
  orig_p := p;
  otype_tail := strrchr (otype, '#');
  if (otype_tail is null)
    o_suffix := otype;
  else
    {
      o_suffix := subseq (otype, otype_tail+1);
      if (o_suffix = '')
        o_suffix := otype;
    }
again:
  p_tail := strrchr (p, '#');
  if (p_tail is null)
    p_tail := strrchr (p, '/');
  if (p_tail is not null)
    {
      shortcut := subseq (p, p_tail+1);
      if (o_suffix = '')
        {
          p := subseq (p, 0, p_tail);
          goto again;
        }
      old_k := dict_get (used_names, shortcut, null);
      if (old_k is null or (orig_p = old_k[0] and otype = old_k[1]))
        return shortcut;
      short2 := shortcut || o_suffix;
      old_k := dict_get (used_names, short2, null);
      if (old_k is null or (orig_p = old_k[0] and otype = old_k[1]))
        return short2;
      p [p_tail] := ascii ('_');
      goto again;
    }
  return 'x' || tree_md5 (vector (orig_p, otype), 1);
}
;

-- ctx_dict is a dictionary of JSON_LD shortcut names and at the same time the dictionary of preset types for some predicates.
-- The keys of the dictionary are either vector (predicate, type) or vector (predicate, NULL); first variant is for shortcuts and second one is for checking types.
-- The values are vector (shortcut, reserved-for-future) for first variant and vector (first-type, can-add-more-types) for second one.
-- ctx_mode tells what to do with the context dictionary:
-- bit 1 = create dictionary if not exists.
-- bit 2 = if needed, extend the existing or newly created dictionary by new properties (but not create the dictionary if bit 1 is not set).
-- bit 4 = if needed, extend the existing or newly created dictionary by new object types for known properties (otherwise only new properties can be edited, or none at all if bit 2 is not set).
-- bit 8 = signal an error if type of object does not match the type in dictionary (if not set then plain notation is used).
-- bit 256 = 100% accuracy in types, different numeric types get different entries in dictionary (or results in an error).
-- bit 512 = signal an error if the property in triples is not listed in the dictionary (if not set then plain notation is used).
-- Note then now bits 1 2 4 are more or less ok, but not higher.

create procedure DB.DBA.RDF_TRIPLES_TO_JSON_LD_CTX (inout triples any, inout ses any, in ctx_dict any := null, in ctx_mode integer := 255)
{
  declare bnode_usage_dict any;
  declare tail_to_head_dict any;
  declare env any;
  declare printed_triples_mask varchar;
  declare tcount, tctr, nesting integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_LD_CTX with mode ', ctx_mode, ':'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  if (0 = tcount)
    {
      http ('{ }\n', ses);
      return;
    }
  env := vector (0, 0, 0, null);
  if (214 <> __tag (ctx_dict))
    {
      if (bit_and (ctx_mode, 1))
        ctx_dict := dict_new (31);
      else if (bit_and (ctx_mode, 2+4))
        signal ('22023', 'JSON-LD context dictionary is required but neither provided nor allowed to be created (bit 1 of context mode is not set)');
    }
  DB.DBA.RDF_TRIPLES_DOMINANCE_DATA (triples, 0, bnode_usage_dict, tail_to_head_dict, printed_triples_mask);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  if (bit_and (ctx_mode, 2+4))
    {
      declare used_names any;
      declare prev_p, prev_otype any;
      declare fixed_otype_of_p any;
      used_names := DB.DBA.JSON_LD_CTX_USED_NAMES (ctx_dict);
      prev_p := '';
      prev_otype := '@:)';
      fixed_otype_of_p := null;
      for (tctr := 0; tctr < tcount; tctr := tctr + 1)
        {
          declare p, obj, raw_otype, otype any;
          if (ascii(' ') <> printed_triples_mask[tctr])
            {
              -- dbg_obj_princ ('skipping ', triples[tctr], ' due to mask ', printed_triples_mask[tctr]);
              goto skip_shortcut_calc; -- see below;
            }
          p := id_to_iri (triples[tctr][1]);
          obj := triples[tctr][2];
          otype := raw_otype := case __tag(obj)
            when __tag of rdf_box then UNAME'@@lit'
            when __tag of integer then UNAME'@num'
            when __tag of real then UNAME'@num'
            when __tag of double precision then UNAME'@num'
            when __tag of decimal then UNAME'@num'
            when __tag of IRI_ID then UNAME'@id'
            when __tag of UNAME then UNAME'@id'
            when __tag of varchar then case when (bit_and (__box_flags (obj), 1)) then UNAME'@id' else UNAME'http://www.w3.org/2001/XMLSchema#string' end
            when __tag of nvarchar then UNAME'http://www.w3.org/2001/XMLSchema#string'
            else uname(__xsd_type (obj)) end;
          -- dbg_obj_princ ('was ', prev_p, prev_otype, '; now ', p, obj, otype);
          if (otype = UNAME'@@lit')
            {
              otype := coalesce ((select RDT_QNAME from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)), UNAME'http://www.w3.org/2001/XMLSchema#string');
              if (otype in ('http://www.w3.org/2001/XMLSchema#integer', 'http://www.w3.org/2001/XMLSchema#float', 'http://www.w3.org/2001/XMLSchema#double', 'http://www.w3.org/2001/XMLSchema#decimal'))
                otype := UNAME'@num';
              else
                otype := uname(otype);
            }
          if (((p <> prev_p) or (otype <> prev_otype)) and (p <> UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'))
            {
              declare shortcut_etc any;
              declare shortcut varchar;
              shortcut_etc := dict_get (ctx_dict, vector (p, otype), null);
              -- dbg_obj_princ ('dict_get (ctx_dict, ', vector (p, otype), ') returned ', shortcut_etc);
              if (p <> prev_p)
                {
                  fixed_otype_of_p := dict_get (ctx_dict, vector (p, null), null);
                  -- dbg_obj_princ ('dict_get (ctx_dict, ', vector (p, null), ') returned ', fixed_otype_of_p);
                  if (fixed_otype_of_p is null)
                    {
                      if (fixed_otype_of_p is not null and (fixed_otype_of_p <> otype))
                        signal ('22023', 'JSON-LD context is not suitable for data: property <' || p || '> is supposed to have values of type " || fixed_otype_of_p || " but the data contain value of type "' || otype || '".');
                    }
                }
              if (shortcut_etc is null)
                {
                  if (bit_and (ctx_mode, 4) or fixed_otype_of_p is null)
                    {
                      shortcut := DB.DBA.JSON_LD_CTX_MAKE_NEW_SHORTCUT (p, otype, used_names);
                      -- dbg_obj_princ ('dict_put (ctx_dict, ', vector (p, otype), vector (shortcut));
                      dict_put (ctx_dict, vector (p, otype), vector (shortcut));
                      dict_put (used_names, shortcut, vector (p, otype));
                    }
                }
            }
          prev_p := p;
          prev_otype := otype;
skip_shortcut_calc: ;
        }
    }
  if (214 <> __tag (ctx_dict))
    http ('{ "@graph": [\n    ', ses);
  else
    {
      declare need_comma integer;
      declare k,v any;
      http ('{ "@context": {', ses);
      dict_iter_rewind (ctx_dict);
      need_comma := 0;
      while (dict_iter_next (ctx_dict, k, v))
        {
          if (k[1] is not null)
            {
              if (need_comma)
                http (',', ses);
              else
                need_comma := 1;
              http ('\n    "', ses);
              http (v[0], ses);
              http ('": { "@id": "', ses);
              http (id_to_iri (k[0]), ses);
              if (k[1] not in (UNAME'@num', UNAME'http://www.w3.org/2001/XMLSchema#string'))
                {
                  http ('", "@type": "', ses);
                  http (k[1], ses);
                  http ('" }', ses);
                }
              else
                {
            -- Uncomment either
                  --http ('" /*, "@type": "', ses);
                  --http (k[1], ses);
                  --http ('"*/ }', ses);
            -- or
                  http ('" }', ses);
            -- but not both
                }
            }
        }
      http (' },\n  "@graph": [\n    ', ses);
    }
  nesting := http_ld_json_triple_batch (env, triples, ses, ctx_dict, ctx_mode, bnode_usage_dict, printed_triples_mask);
  if (nesting > 1)
    http (' ]', ses);
  if (nesting)
    http (' }\n', ses);
  http ('] }\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_JSON (inout triples any, inout ses any)
{
  declare tcount, tctr, env integer;
  tcount := length (triples);
  http ('\n{ "head": { "link": [], "vars": [ "s", "p", "o" ] },\n  "results": { "distinct": false, "ordered": true, "bindings": [', ses);
  tcount := length (triples);
  env := vector (0, 0, vector ('s', 'p', 'o'), null);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare triple any;
      if (tctr > 0)
        http(',', ses);
      triple := aref_set_0 (triples, tctr);
      sparql_rset_json_write_row (ses, env, triple);
      aset_zap_arg (triples, tctr, triple);
    }
  http (' ] } }', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_CSV (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr, status integer;
  http ('"subject","predicate","object"\n', ses);
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_CSV:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  { whenever sqlstate '*' goto p_done; rowvector_subj_sort (triples, 1, 1); p_done: ; }
  { whenever sqlstate '*' goto s_done; rowvector_subj_sort (triples, 0, 1); s_done: ; }
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][0]);
      http (',', ses);
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][1]);
      http (',', ses);
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][2]);
      http ('\n', ses);
    }
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_TSV (inout triples any, inout ses any)
{
  declare env any;
  declare tcount, tctr, status integer;
  http ('"subject","predicate","object"\n', ses);
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_TSV:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  { whenever sqlstate '*' goto p_done; rowvector_subj_sort (triples, 1, 1); p_done: ; }
  { whenever sqlstate '*' goto s_done; rowvector_subj_sort (triples, 0, 1); s_done: ; }
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][0]);
      http ('\t', ses);
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][1]);
      http ('\t', ses);
      DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (ses, triples[tctr][2]);
      http ('\n', ses);
    }
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML (inout triples any, inout ses any)
{
  declare env, prev_subj, subj_text, pred_text, nsdict, nslist any;
  declare ctr, len, tcount, tctr, status integer;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  http ('<?xml version="1.0" encoding="UTF-8"?>\n
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">\n', ses);
  if (0 = tcount)
    {
      http ('<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Empty RDFa+XHTML document</title></head><body>
<p>This document is empty and basically useless. It is generated by a web service that can make some statements in XHTML+RDFa format.
This time the service made zero such statements, sorry.</p></body></html>', ses);
      return;
    }
  nsdict := dict_new (10 + cast (sqrt(tcount) as integer));
  dict_put (nsdict, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf');
  dict_put (nsdict, 'http://www.w3.org/2001/XMLSchema#', 'xsdh');
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; (tctr < tcount) and (1000 > dict_size (nsdict)); tctr := tctr + 1)
    {
      sparql_iri_split_rdfa_qname (triples[tctr][0], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][1], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][2], nsdict, 1);
    }
  http ('<html xmlns="http://www.w3.org/1999/xhtml"', ses);
  nslist := dict_to_vector (nsdict, 0);
  len := length (nslist);
  for (ctr := len - 2; ctr >= 0; ctr := ctr-2)
    {
      http (sprintf ('\n  xmlns:%s="', nslist[ctr+1]), ses);
      http_escape (nslist[ctr], 3, ses, 1, 1);
      http ('"', ses);
    }
  http ('>\n<head><title>RDFa+XHTML document</title></head><body>\n', ses);
  http (sprintf ('<p>This HTML document contains %d embedded RDF statements represented using (X)HTML+RDFa notation.</p>',
    tcount), ses);
  http ('<p>The embedded RDF content will be recognized by any processor of (X)HTML+RDFa.</p>', ses);
  http ('\n<table border="1">\n<thead><tr><th>Namespace Prefix</th><th>Namespace URI</th></tr></thead><tbody>', ses);
  for (ctr := len - 2; ctr >= 0; ctr := ctr-2)
    {
      http (sprintf ('\n<tr><td>xmlns:%s</td><td>', nslist[ctr+1]), ses);
      http_escape (nslist[ctr], 3, ses, 1, 1);
      http ('</td></tr>', ses);
    }
  http ('\n</tbody></table>', ses);
  http ('\n<table border="1">\n<thead><tr><th>Subject</th><th>Predicate</th><th>Object</th></tr></thead>', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  prev_subj := null;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, obj_iri_split any;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          if (prev_subj is not null)
            http ('\n</tbody>', ses);
          http ('\n<tbody about="[', ses);
          split := sparql_iri_split_rdfa_qname (subj, nsdict, 2);
          -- dbg_obj_princ ('Split of ', subj, ' is ', split);
          if ('' = split[1])
            {
              subj_text := split[2];
              http_escape (subj_text, 3, ses, 1, 1);
              http (']">', ses);
            }
          else if (isstring (split[0]))
            {
              subj_text := concat (split[0], ':', split[2]);
              http_escape (subj_text, 3, ses, 1, 1);
              http (']">', ses);
            }
          else
            {
              subj_text := id_to_iri (subj);
              http_escape (concat ('s:', split[2]), 3, ses, 1, 1);
              http (']" xmlns:s="', ses);
              http_escape (split[1], 3, ses, 1, 1);
              http ('">', ses);
            }
          subj_text := sprintf ('\n<tr><td>%V</td><td>', subj_text);
          prev_subj := subj;
        }
      http (subj_text, ses);
      split := sparql_iri_split_rdfa_qname (pred, nsdict, 2);
      if ('' = split[1])
        {
          http_value (split[2], 0, ses);
        }
      else if (isstring (split[0]))
        {
          http_value (concat (split[0], ':', split[2]), 0, ses);
        }
      else
        {
          http_value (id_to_iri (pred), 0, ses);
        }
      obj_iri_split := sparql_iri_split_rdfa_qname (obj, nsdict, 2);
      http (case (isvector (obj_iri_split)) when 0 then '</td><td property="' else '</td><td rel="' end, ses);
      if ('' = split[1])
        {
          pred_text := split[2];
          http_escape (pred_text, 3, ses, 1, 1);
          http ('"', ses);
        }
      else if (isstring (split[0]))
        {
          pred_text := concat (split[0], ':', split[2]);
          http_escape (pred_text, 3, ses, 1, 1);
          http ('"', ses);
        }
      else
        {
          pred_text := id_to_iri (pred);
          http_escape (concat ('p:', split[2]), 3, ses, 1, 1);
          http ('" xmlns:p="', ses);
          http_escape (split[1], 3, ses, 1, 1);
          http ('"', ses);
        }
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_RDFA_XHTML: object is NULL');
      if (isvector (obj_iri_split))
        {
          http (' resource="', ses);
          if (isstring (obj_iri_split[0]))
            {
              http ('[', ses);
              http_escape (concat (obj_iri_split[0], ':', obj_iri_split[2]), 3, ses, 1, 1);
              http (']" >', ses);
              http_value (concat (obj_iri_split[0], ':', obj_iri_split[2]), 0, ses);
              http ('</td></tr>', ses);
            }
          else
            {
              http_escape (concat (obj_iri_split[1], ':', obj_iri_split[2]), 3, ses, 1, 1);
              http ('" >', ses);
              http_value (concat (obj_iri_split[1], ':', obj_iri_split[2]), 0, ses);
              http ('</td></tr>', ses);
            }
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_type (obj))
                dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              else if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
              if (__tag of datetime = __tag (sqlval))
                {
                  if (257 = rdf_box_type (obj))
                    dt := __xsd_type (sqlval);
                }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
              dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
          if (not (isinteger (dt)))
            {
              http (' datatype="', ses);
              split := sparql_iri_split_rdfa_qname (dt, nsdict, 2);
              if ('' = split[1])
                {
                  http_escape (split[2], 3, ses, 1, 1);
                  http ('"', ses);
                }
              else if (isstring (split[0]))
                {
                  http_escape (concat (split[0], ':', split[2]), 3, ses, 1, 1);
                  http ('"', ses);
                }
              else
                {
                  http_escape (concat ('dt:', split[2]), 3, ses, 1, 1);
                  http ('" xmlns:dt="', ses);
                  http_escape (split[1], 3, ses, 1, 1);
                  http ('"', ses);
                }
            }
          if (isstring (lang))
            {
              http (' xml:lang="', ses);
              http_escape (lang, 3, ses, 1, 1);
              http ('"', ses);
            }
          http ('>', ses);
          if (__tag of datetime = __tag(sqlval))
            __rdf_long_to_ttl (sqlval, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            http_value (sqlval, 0, ses);
          else if (__tag of varchar = __tag (sqlval))
            http_value (charset_recode (sqlval, 'UTF-8', '_WIDE_'), 0, ses);
          else
            {
              sqlval := __rdf_strsqlval (obj);
              if (__tag of varchar = __tag (sqlval))
                sqlval := charset_recode (sqlval, 'UTF-8', '_WIDE_');
              http_value (sqlval, 0, ses);
            }
          http ('</td></tr>', ses);
        }
    }
  if (prev_subj is not null)
    http ('\n</tbody>', ses);
  http ('\n</table></body></html>\n', ses);
}
;

create function DB.DBA.RDF_ENDPOINT_DESCRIBE_LINK_FMT (in ul_or_tr varchar)
{
  declare lpath varchar;
  lpath := virtuoso_ini_item_value ('URIQA','DefaultHost');
  if (lpath is null)
    lpath := '/sparql';
  else
    lpath := 'http://' || lpath || '/sparql';
  whenever sqlstate 'HT013' goto no_http_context;
  lpath := http_path ();
no_http_context:
  return ' <a href=" ' || lpath || '?query=describe+%%3C%U%%3E&amp;format=text%%2Fx-html%%2B' || ul_or_tr || '">describe</a> ';
}
;

create function DB.DBA.RDF_PIVOT_DESCRIBE_LINK (in iri varchar)
{
  return sprintf ('; <a href="/describe/?url=%U&sid=1&amp;urilookup=1">facets</a> ', iri);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_HTML_UL (inout triples any, inout ses any)
{
  declare env, prev_subj, prev_pred any array;
  declare can_pivot, ctr, len, tcount, tctr, status, obj_needs_br integer;
  declare endpoint_fmt, subj_iri, pred_iri varchar;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_UL:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  http ('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">\n', ses);
  if (0 = tcount)
    {
      http ('<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Empty HTML RDFa and Microdata document</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head><body>
<p>This document is empty and basically useless. It is generated by a web service that can make some statements in HTML Microdata format.
This time the service made zero such statements, sorry.</p></body></html>', ses);
      return;
    }
  endpoint_fmt := DB.DBA.RDF_ENDPOINT_DESCRIBE_LINK_FMT ('ul');
  can_pivot := case (isnull (DB.DBA.VAD_CHECK_VERSION ('PivotViewer'))) when 0 then 1 else 0 end;
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  http ('<html xmlns="http://www.w3.org/1999/xhtml"', ses);
  http ('>\n<head><title>HTML RDFa and Microdata document</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>\n<body>\n<ul>\n', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  prev_subj := prev_pred := null;
  obj_needs_br := 0;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, obj_iri_split any array;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_UL: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_UL: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_UL: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          if (prev_subj is not null)
            http ('\n          </ul></li>\n      </ul></li>', ses);
          subj_iri := id_to_iri (subj);
          http ('\n  <li about="', ses);
          http_escape (subj_iri, 3, ses, 1, 1);
          http ('" itemscope="" itemid="', ses);
          http_escape (subj_iri, 3, ses, 1, 1);
          http ('"><a href="', ses);
          http_escape (subj_iri, 3, ses, 1, 1);
          http ('">', ses);
          http_escape (subj_iri, 1, ses, 1, 1);
          http ('</a> (', ses);
          http (sprintf (endpoint_fmt, subj_iri), ses);
          if (can_pivot)
            http (DB.DBA.RDF_PIVOT_DESCRIBE_LINK (subj_iri), ses);
          http (')\n    <ul>', ses);
          prev_subj := subj;
          prev_pred := null;
        }
      if (prev_pred is null or (pred <> prev_pred))
        {
          if (prev_pred is not null)
            http ('\n        </ul></li>', ses);
          pred_iri := id_to_iri (pred);
          http ('\n      <li><a href="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('">', ses);
          http_escape (pred_iri, 1, ses, 1, 1);
          http ('</a> (', ses);
          http (sprintf (endpoint_fmt, pred_iri), ses);
          if (can_pivot)
            http (DB.DBA.RDF_PIVOT_DESCRIBE_LINK (pred_iri), ses);
          http (')\n        <ul>', ses);
          prev_pred := pred;
          obj_needs_br := 0;
        }
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_HTML_UL: object is NULL');
      if (obj_needs_br)
        http ('\n', ses);
      else
        obj_needs_br := 1;
      if (isiri_id (obj))
        {
          declare obj_iri varchar;
          obj_iri := id_to_iri (obj);
          http ('\n          <li><a rel="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" resource="', ses);
          http_escape (obj_iri, 3, ses, 1, 1);
          http ('" itemprop="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" href="', ses);
          http_escape (obj_iri, 3, ses, 1, 1);
          http ('">', ses);
          http_escape (obj_iri, 1, ses, 1, 1);
          http ('</a> (', ses);
          http (sprintf (endpoint_fmt, obj_iri), ses);
          if (can_pivot)
            http (DB.DBA.RDF_PIVOT_DESCRIBE_LINK (obj_iri), ses);
          http (')</li>', ses);
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          http ('\n          <li property="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" itemprop="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
              else if (257 <> rdf_box_type (obj))
                dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
              if (__tag of datetime = __tag (sqlval))
                {
                  if (257 = rdf_box_type (obj))
                    dt := __xsd_type (sqlval);
                }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
              dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
          if (not (isinteger (dt)))
            {
              http ('" datatype="', ses);
              http_escape (dt, 3, ses, 1, 1);
            }
          if (isstring (lang))
            {
              http ('" xml:lang="', ses);
              http_escape (lang, 3, ses, 1, 1);
            }
          http ('">', ses);
          if (__tag of datetime = __tag(sqlval))
            __rdf_long_to_ttl (sqlval, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            http_value (sqlval, 0, ses);
          else if (__tag of varchar = __tag (sqlval))
            http_value (charset_recode (sqlval, 'UTF-8', '_WIDE_'), 0, ses);
          else
            {
              sqlval := __rdf_strsqlval (obj);
              if (__tag of varchar = __tag (sqlval))
                sqlval := charset_recode (sqlval, 'UTF-8', '_WIDE_');
              http_value (sqlval, 0, ses);
            }
          http ('</li>', ses);
        }
    }
  if (prev_subj is not null)
    http ('\n        </ul></li></ul></li></ul>', ses);
  http ('\n</body></html>\n', ses);
}
;


create procedure DB.DBA.RDF_TRIPLES_TO_HTML_TR (inout triples any, inout ses any)
{
  declare env, prev_subj, prev_pred any;
  declare can_pivot, ctr, len, tcount, tctr, status integer;
  declare endpoint_fmt, subj_iri, pred_iri, subj_recod, pred_recod, subj_trtd, pred_tdtd varchar;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_TR:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  -- http ('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE html>\n', ses);
  if (0 = tcount)
    {
      http ('<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Empty HTML RDFa and Microdata document</title></head><body>
<p>This document is empty and basically useless. It is generated by a web service that can make some statements in HTML Microdata format.
This time the service made zero such statements, sorry.</p></body></html>', ses);
      return;
    }
  endpoint_fmt := DB.DBA.RDF_ENDPOINT_DESCRIBE_LINK_FMT ('tr');
  can_pivot := case (isnull (DB.DBA.VAD_CHECK_VERSION ('PivotViewer'))) when 0 then 1 else 0 end;
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  http ('<html xmlns="http://www.w3.org/1999/xhtml"', ses);
  http ('>\n<head><title>HTML RDFa and Microdata document</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>\n<body>\n<table>\n', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  prev_subj := prev_pred := null;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, obj_iri_split any;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_TR: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_TR: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_TR: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          declare trtd_ses any;
          subj_iri := id_to_iri (subj);
          --subj_recod := replace (subj_iri, '"', '%22');
          --subj_trtd := sprintf ('\n<tr itemscope="itemscope" about="%s" itemid="%s">\n  <td><a href="%s">%V</a> (' || endpoint_fmt || '%s)</td>',
          --  subj_recod, subj_recod, subj_recod, subj_iri, subj_iri,
          --  case when (can_pivot) then DB.DBA.RDF_PIVOT_DESCRIBE_LINK (id_to_iri (subj)) else '' end );
          trtd_ses := string_output ();
          http ('\n<tr itemscope="itemscope" about="', trtd_ses);
          http_escape (subj_iri, 3, trtd_ses, 1, 1);
          http ('" itemid="', trtd_ses);
          http_escape (subj_iri, 3, trtd_ses, 1, 1);
          http ('">\n  <td><a href="', trtd_ses);
          http_escape (subj_iri, 3, trtd_ses, 1, 1);
          http (sprintf ('">%V</a> (' || endpoint_fmt || '%s)</td>', subj_iri, subj_iri,
              case when (can_pivot) then DB.DBA.RDF_PIVOT_DESCRIBE_LINK (id_to_iri (subj)) else '' end ),
            trtd_ses );
          subj_trtd := string_output_string (trtd_ses);
          prev_subj := subj;
        }
      if (prev_pred is null or (pred <> prev_pred))
        {
          declare tdtd_ses any;
          pred_iri := id_to_iri (pred);
          --pred_recod := replace (pred_iri, '"', '%22');
          --pred_tdtd := sprintf ('\n  <td><a href="%s">%s</a> (' || endpoint_fmt || '%s)\n  </td><td',
          --  pred_recod, pred_recod, pred_iri,
          --  case when (can_pivot) then DB.DBA.RDF_PIVOT_DESCRIBE_LINK (id_to_iri (pred)) else '' end );
          tdtd_ses := string_output ();
          http ('\n  <td><a href="', tdtd_ses);
          http_escape (pred_iri, 3, tdtd_ses, 1, 1);
          http ('">', tdtd_ses);
          http_escape (pred_iri, 1, tdtd_ses, 1, 1);
          http (sprintf ('</a> (' || endpoint_fmt || '%s)\n  </td><td', pred_iri,
              case when (can_pivot) then DB.DBA.RDF_PIVOT_DESCRIBE_LINK (id_to_iri (pred)) else '' end ),
            tdtd_ses );
          pred_tdtd := string_output_string (tdtd_ses);
          prev_pred := pred;
        }
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_HTML_TR: object is NULL');
      http (subj_trtd, ses);
      http (pred_tdtd, ses);
      if (isiri_id (obj))
        {
          declare obj_iri varchar;
          obj_iri := id_to_iri (obj);
          http ('><a rel="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" resource="', ses);
          http_escape (obj_iri, 3, ses, 1, 1);
          http ('" itemprop="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" href="', ses);
          http_escape (obj_iri, 3, ses, 1, 1);
          http (sprintf ('">%V</a> (' || endpoint_fmt, obj_iri, obj_iri), ses);
          if (can_pivot)
            http (DB.DBA.RDF_PIVOT_DESCRIBE_LINK (obj_iri), ses);
          http (')</td></tr>', ses);
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          http (' property="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          http ('" itemprop="', ses);
          http_escape (pred_iri, 3, ses, 1, 1);
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
              else if (257 <> rdf_box_type (obj))
                dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
              if (__tag of datetime = __tag (sqlval))
                {
                  if (257 = rdf_box_type (obj))
                    dt := __xsd_type (sqlval);
                }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
              dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
          if (not (isinteger (dt)))
            {
              http ('" datatype="', ses);
              http_escape (dt, 3, ses, 1, 1);
            }
          if (isstring (lang))
            {
              http ('" xml:lang="', ses);
              http_escape (lang, 3, ses, 1, 1);
            }
          http ('">', ses);
          if (__tag of datetime = __tag(sqlval))
            __rdf_long_to_ttl (sqlval, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            http_value (sqlval, 0, ses);
          else if (__tag of varchar = __tag (sqlval))
            http_value (charset_recode (sqlval, 'UTF-8', '_WIDE_'), 0, ses);
          else
            {
              sqlval := __rdf_strsqlval (obj);
              if (__tag of varchar = __tag (sqlval))
                sqlval := charset_recode (sqlval, 'UTF-8', '_WIDE_');
              http_value (sqlval, 0, ses);
            }
          http ('</td></tr>', ses);
        }
    }
  http ('\n</table></body></html>\n', ses);
}
;


create procedure DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA (inout triples any, inout ses any)
{
  declare env, prev_subj, prev_pred, nsdict, nslist any;
  declare ctr, len, tcount, tctr, status, obj_needs_br integer;
  declare objs_of_sp any;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  -- http ('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE html>\n', ses);
  if (0 = tcount)
    {
      http ('<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Empty HTML Microdata document</title></head><body>
<p>This document is empty and basically useless. It is generated by a web service that can make some statements in HTML Microdata format.
This time the service made zero such statements, sorry.</p></body></html>', ses);
      return;
    }
  nsdict := dict_new (10 + cast (sqrt(tcount) as integer));
  dict_put (nsdict, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf');
  dict_put (nsdict, 'http://www.w3.org/2001/XMLSchema#', 'xsdh');
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; (tctr < tcount) and (1000 > dict_size (nsdict)); tctr := tctr + 1)
    {
      sparql_iri_split_rdfa_qname (triples[tctr][0], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][1], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][2], nsdict, 1);
    }
  http ('<html xmlns="http://www.w3.org/1999/xhtml"', ses);
  http ('>\n<head><title>HTML Microdata document</title></head><body>\n', ses);
  http (sprintf ('<p>This HTML5 document contains %d embedded RDF statements represented using HTML+Microdata notation.</p>',
    tcount), ses);
  http ('<p>The embedded RDF content will be recognized by any processor of HTML5 Microdata.</p>', ses);
  http ('\n<table><tr><th>Prefix</th><th>Namespace IRI</th></tr>', ses);
  nslist := dict_to_vector (nsdict, 0);
  len := length (nslist);
  for (ctr := len - 2; ctr >= 0; ctr := ctr-2)
    {
      http (sprintf ('\n<tr><td>%V</td><td>%V</td></tr>', nslist[ctr+1], nslist[ctr]), ses);
    }
  http ('</table>', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  prev_subj := prev_pred := null;
  obj_needs_br := 0;
  objs_of_sp := dict_new (20);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, obj_iri_split any;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      if (isstring (subj))
	subj := iri_to_id (subj);
      if (isstring (pred))
	pred := iri_to_id (pred);
      if (isstring (obj) and __box_flags (obj) = 1)
	obj := iri_to_id (obj);
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          if (prev_subj is not null)
            http ('\n</dd></dl>', ses);
          http (sprintf ('\n<dl itemscope itemid="%s">', replace (id_to_iri (subj), '"', '%22')), ses);
          split := sparql_iri_split_rdfa_qname (subj, nsdict, 2);
          -- dbg_obj_princ ('Split of ', subj, ' is ', split);
          if ('' = split[1])
            http (sprintf ('\n<dt>Subject Item</dt><dd>%V</dd>', split[2]), ses);
          else if (isstring (split[0]))
            http (sprintf ('\n<dt>Subject Item</dt><dd>%V:%V</dd>', split[0], split[2]), ses);
          else
            http (sprintf ('\n<dt>Subject Item</dt><dd>%V%V</dd>', split[1], split[2]), ses);
          prev_subj := subj;
          prev_pred := null;
        }
      if (prev_pred is null or (pred <> prev_pred))
        {
          dict_zap (objs_of_sp, 2);
          if (prev_pred is not null)
            http ('\n</dd>', ses);
          split := sparql_iri_split_rdfa_qname (pred, nsdict, 2);
          -- dbg_obj_princ ('Split of ', pred, ' is ', split);
          if ('' = split[1])
            http (sprintf ('\n<dt>%V</dt><dd>', split[2]), ses);
          else if (isstring (split[0]))
            http (sprintf ('\n<dt>%V:%V</dt><dd>', split[0], split[2]), ses);
          else
            http (sprintf ('\n<dt>%V%V</dt><dd>', split[1], split[2]), ses);
          prev_pred := pred;
          obj_needs_br := 0;
        }
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_HTML_MICRODATA: object is NULL');
      if (dict_get (objs_of_sp, obj, 0))
        goto skip_obj;
      dict_put (objs_of_sp, obj, 1);
      if (obj_needs_br)
        http ('\n', ses);
      else
        obj_needs_br := 1;
      obj_iri_split := sparql_iri_split_rdfa_qname (obj, nsdict, 2);
      if (isvector (obj_iri_split))
        {
          http (sprintf ('\n<a itemprop="%s" href="%s">', replace (id_to_iri (pred), '"', '%22'), replace (id_to_iri (obj), '"', '%22')), ses);
          if ('' = obj_iri_split[1])
            http (sprintf ('%V</a>', obj_iri_split[2]), ses);
          else if (isstring (obj_iri_split[0]))
            http (sprintf ('%V:%V</a>', obj_iri_split[0], obj_iri_split[2]), ses);
          else
            http (sprintf ('%V%V</a>', obj_iri_split[1], obj_iri_split[2]), ses);
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          http (sprintf ('\n<span itemprop="%s"', replace (id_to_iri (pred), '"', '%22')), ses);
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
--DT          else if (257 <> rdf_box_type (obj))
--DT            dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
--DT          if (__tag of datetime = __tag (sqlval))
--DT            {
--DT              if (257 = rdf_box_type (obj))
--DT                dt := __xsd_type (sqlval);
--DT            }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
--DT          dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
--DT      if (not (isinteger (dt)))
--DT        {
--DT          http (' datatype="', ses);
--DT          split := sparql_iri_split_rdfa_qname (dt, nsdict, 2);
--DT          if ('' = split[1])
--DT            {
--DT              http_escape (split[2], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else if (isstring (split[0]))
--DT            {
--DT              http_escape (concat (split[0], ':', split[2]), 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else
--DT            {
--DT              http_escape (concat ('dt:', split[2]), 3, ses, 1, 1);
--DT              http ('" xmlns:dt="', ses);
--DT              http_escape (split[1], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT        }
          if (isstring (lang))
            {
              http (' xml:lang="', ses);
              http_escape (lang, 3, ses, 1, 1);
              http ('"', ses);
            }
          http ('>', ses);
          if (__tag of datetime = __tag(sqlval))
            __rdf_long_to_ttl (sqlval, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            http_value (sqlval, 0, ses);
          else if (__tag of varchar = __tag (sqlval))
            http_value (charset_recode (sqlval, 'UTF-8', '_WIDE_'), 0, ses);
          else
            {
              sqlval := __rdf_strsqlval (obj);
              if (__tag of varchar = __tag (sqlval))
                sqlval := charset_recode (sqlval, 'UTF-8', '_WIDE_');
              http_value (sqlval, 0, ses);
            }
          http ('</span>', ses);
        }
skip_obj: ;
    }
  if (prev_subj is not null)
    http ('\n</dd></dl>', ses);
  http ('\n</body></html>\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA (inout triples any, inout ses any)
{
  declare env, prev_subj, prev_pred, nsdict, nslist any;
  declare val, p_itemprop, nice_host, describe_path, about_path varchar;
  declare ctr, len, tcount, tctr, status, obj_needs_br integer;
  declare objs_of_sp any;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  -- http ('<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE html>\n', ses);
  if (0 = tcount)
    {
      http ('<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Empty HTML Microdata document</title></head><body>
<p>This document is empty and basically useless. It is generated by a web service that can make some statements in HTML Microdata format.
This time the service made zero such statements, sorry.</p></body></html>', ses);
      return;
    }
  objs_of_sp := dict_new (20);
  nice_host := registry_get ('URIQADefaultHost');
  describe_path := about_path := null;
  if (isstring (nice_host))
    {
      if (exists (select 1 from VAD.DBA.VAD_REGISTRY where R_KEY like '/VAD/fct/%/resources/dav/%'))
        describe_path := 'http://' || nice_host || '/describe/?url=';
      if (exists (select 1 from VAD.DBA.VAD_REGISTRY where R_KEY like '/VAD/cartridges/%/resources/dav/%'))
        about_path := 'http://' || nice_host || '/about/html/';
    }
  nsdict := dict_new (10 + cast (sqrt(tcount) as integer));
  dict_put (nsdict, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdf');
  dict_put (nsdict, 'http://www.w3.org/2001/XMLSchema#', 'xsdh');
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  for (tctr := 0; (tctr < tcount) and (1000 > dict_size (nsdict)); tctr := tctr + 1)
    {
      sparql_iri_split_rdfa_qname (triples[tctr][0], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][1], nsdict, 1);
      sparql_iri_split_rdfa_qname (triples[tctr][2], nsdict, 1);
    }
  http ('<html xmlns="http://www.w3.org/1999/xhtml"', ses);
  http ('>\n<head><title>HTML Based Entity Description (with embedded Microdata)</title></head><body>\n', ses);
  http (sprintf ('<p>This HTML5 document contains %d embedded RDF statements represented using HTML+Microdata notation.</p>',
    tcount), ses);
  http ('<p>The embedded RDF content will be recognized by any processor of HTML5 Microdata.</p>', ses);

  -- http ('\n<table><tr><th>Prefix</th><th>Namespace IRI</th></tr>', ses);
  -- nslist := dict_to_vector (nsdict, 0);
  -- len := length (nslist);
  -- for (ctr := len - 2; ctr >= 0; ctr := ctr-2)
  --   {
  --     http (sprintf ('\n<tr><td>%V</td><td>%V</td></tr>', nslist[ctr+1], nslist[ctr]), ses);
  --   }
  -- http ('</table>', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  prev_subj := prev_pred := null;
  obj_needs_br := 0;
  http ('\n<table border="1"><tr><th>Subject</th><th>Predicate</th><th>Object</th></tr><tr><td>', ses);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, o_split any;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      if (isstring (subj))
        subj := iri_to_id (subj);
      if (isstring (pred))
        pred := iri_to_id (pred);
      if (isstring (obj) and __box_flags (obj) = 1)
        obj := iri_to_id (obj);
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          if (prev_subj is not null)
            http ('\n</td></tr><tr><td>', ses);
          split := sparql_iri_split_rdfa_qname (subj, nsdict, 2);
          val := id_to_iri (subj);
          -- dbg_obj_princ ('Split of ', subj, ' is ', split);
          if (about_path is not null)
            {
              if ('' = split[1])		http (sprintf ('\n<a href="%U">%V</a>&nbsp;(<a href="%s%U">/about</a>)</td>'		, val, split[2]			, about_path, val)	, ses);
              else if (isstring (split[0]))	http (sprintf ('\n<a href="%U">%V:%V</a>&nbsp;(<a href="%s%U">/about</a>)</td>'		, val, split[0], split[2]	, about_path, val)	, ses);
              else				http (sprintf ('\n<a href="%U">%V%V</a>&nbsp;(<a href="%s%U">/about</a>)</td>'		, val, split[1], split[2]	, about_path, val)	, ses);
            }
          else if (describe_path is not null)
            {
              if ('' = split[1])		http (sprintf ('\n<a href="%U">%V</a>&nbsp;(<a href="%s%U">/describe</a>)</td>'		, val, split[2]			, describe_path, val)	, ses);
              else if (isstring (split[0]))	http (sprintf ('\n<a href="%U">%V:%V</a>&nbsp;(<a href="%s%U">/describe</a>)</td>'	, val, split[0], split[2]	, describe_path, val)	, ses);
              else				http (sprintf ('\n<a href="%U">%V%V</a>&nbsp;(<a href="%s%U">/describe</a>)</td>'	, val, split[1], split[2]	, describe_path, val)	, ses);
            }
          else
            {
              if ('' = split[1])		http (sprintf ('\n<a href="%U">%V</a></td>'	, val, split[2])		, ses);
              else if (isstring (split[0]))	http (sprintf ('\n<a href="%U">%V:%V</a></td>'	, val, split[0], split[2])	, ses);
              else				http (sprintf ('\n<a href="%U">%V%V</a></td>'	, val, split[1], split[2])	, ses);
            }
          prev_subj := subj;
          prev_pred := null;
        }
      if (prev_pred is null or (pred <> prev_pred))
        {
          dict_zap (objs_of_sp, 2);
--          if (prev_pred is not null)
--            http ('\n</td></tr>', ses);
--          http ('\n<tr>', ses);
          split := sparql_iri_split_rdfa_qname (pred, nsdict, 2);
          p_itemprop := replace (id_to_iri (pred), '"', '%22');
          -- dbg_obj_princ ('Split of ', pred, ' is ', split);
          if ('' = split[1])		http (sprintf ('\n<td><a href="%s">%V</a>'	, p_itemprop, split[2])			, ses);
          else if (isstring (split[0]))	http (sprintf ('\n<td><a href="%s">%V:%V</a>'	, p_itemprop, split[0], split[2])	, ses);
          else				http (sprintf ('\n<td><a href="%s">%V%V</a>'	, p_itemprop, split[1], split[2])	, ses);
          if (describe_path is not null)
            http (sprintf (' (<a href="%s%U">/describe</a>)'	, describe_path, id_to_iri (pred)), ses);
          http (sprintf ('</td>\n<td itemscope itemid="%U">', val), ses);
          prev_pred := pred;
          obj_needs_br := 0;
        }
      if (dict_get (objs_of_sp, obj, 0))
        goto skip_obj;
      dict_put (objs_of_sp, obj, 1);
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_HTML_NICE_MICRODATA: object is NULL');
      if (obj_needs_br)
        http (' ,', ses);
      else
        obj_needs_br := 1;
      o_split := sparql_iri_split_rdfa_qname (obj, nsdict, 2);
      if (isvector (o_split))
        {
          declare o_href varchar;
          o_href := replace (id_to_iri (obj), '"', '%22');
          if ('' = o_split[1])			http (sprintf ('\n<a itemprop="%V" href="%s">%V</a>'	, p_itemprop, o_href, o_split[2])		, ses);
          else if (isstring (o_split[0]))	http (sprintf ('\n<a itemprop="%V" href="%s">%V:%V</a>'	, p_itemprop, o_href, o_split[0], o_split[2])	, ses);
          else					http (sprintf ('\n<a itemprop="%V" href="%s">%V%V</a>'	, p_itemprop, o_href, o_split[1], o_split[2])	, ses);
          if (about_path is not null)
            http (sprintf ('\n(<a href="%s%s">/about</a>)', about_path, o_href), ses);
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          http (sprintf ('\n<span itemprop="%s"', replace (id_to_iri (pred), '"', '%22')), ses);
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
--DT          else if (257 <> rdf_box_type (obj))
--DT            dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
--DT          if (__tag of datetime = __tag (sqlval))
--DT            {
--DT              if (257 = rdf_box_type (obj))
--DT                dt := __xsd_type (sqlval);
--DT            }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
--DT          dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
--DT      if (not (isinteger (dt)))
--DT        {
--DT          http (' datatype="', ses);
--DT          split := sparql_iri_split_rdfa_qname (dt, nsdict, 2);
--DT          if ('' = split[1])
--DT            {
--DT              http_escape (split[2], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else if (isstring (split[0]))
--DT            {
--DT              http_escape (concat (split[0], ':', split[2]), 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else
--DT            {
--DT              http_escape (concat ('dt:', split[2]), 3, ses, 1, 1);
--DT              http ('" xmlns:dt="', ses);
--DT              http_escape (split[1], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT        }
          if (isstring (lang))
            {
              http (' xml:lang="', ses);
              http_escape (lang, 3, ses, 1, 1);
              http ('"', ses);
            }
          http ('>', ses);
          if (__tag of datetime = __tag(sqlval))
            __rdf_long_to_ttl (sqlval, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            http_value (sqlval, 0, ses);
          else if (__tag of varchar = __tag (sqlval))
            http_value (charset_recode (sqlval, 'UTF-8', '_WIDE_'), 0, ses);
          else
            {
              sqlval := __rdf_strsqlval (obj);
              if (__tag of varchar = __tag (sqlval))
                sqlval := charset_recode (sqlval, 'UTF-8', '_WIDE_');
              http_value (sqlval, 0, ses);
            }
          http ('</span>', ses);
        }
skip_obj: ;
    }
  if (prev_subj is not null)
    http ('\n</td></tr></table>', ses);
  http ('\n</body></html>\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA (inout triples any, inout ses any)
{
  declare env, prev_subj, prev_pred any;
  declare ctr, len, tcount, tctr, status, obj_needs_comma integer;
  declare objs_of_sp any;
  tcount := length (triples);
  -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA:'); for (tctr := 0; tctr < tcount; tctr := tctr + 1) -- dbg_obj_princ (triples[tctr]);
  http ('{ "items" : [', ses);
  env := vector (0, 0, 0, null);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  prev_subj := prev_pred := null;
  obj_needs_comma := 0;
  objs_of_sp := dict_new (20);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare subj, pred, obj, split, obj_iri_split any;
      declare pred_tagname varchar;
      declare res varchar;
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA: subj:', subj, __tag(subj), __box_flags (subj));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA: pred:', pred, __tag(pred), __box_flags (pred));
      -- dbg_obj_princ ('DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA: obj:', obj, __tag(obj), __box_flags (obj));
      if (prev_subj is null or (subj <> prev_subj))
        {
          declare subj_iri varchar;
          if (prev_subj is not null)
            http (' ] } },\n', ses);
	  if (isstring (subj))
	    subj_iri := subj;
	  else
          subj_iri := id_to_iri (subj);
          if (starts_with (subj_iri, 'nodeID://'))
            subj_iri := '_:' || subseq (subj_iri, 9);
          http ('\n    { "id" : "', ses); http_escape (subj_iri, 14, ses, 1, 1); http ('"\n      "properties" : {', ses);
          prev_subj := subj;
          prev_pred := null;
        }
      if (prev_pred is null or (pred <> prev_pred))
        {
          dict_zap (objs_of_sp, 2);
          if (prev_pred is not null)
            http (' ] ,', ses);
          http ('\n        "', ses); http_escape (case when isstring (pred) then pred else id_to_iri (pred) end, 14, ses, 1, 1); http ('" : [ ', ses);
          prev_pred := pred;
          obj_needs_comma := 0;
        }
      if (obj is null)
        signal ('RDFXX', 'DB.DBA.TRIPLES_TO_JSON_MICRODATA: object is NULL');
      if (dict_get (objs_of_sp, obj, 0))
        goto skip_obj;
      dict_put (objs_of_sp, obj, 1);
      if (obj_needs_comma)
        http (',\n          ', ses);
      else
        obj_needs_comma := 1;
      if (isiri_id (obj))
        {
          declare obj_iri varchar;
          obj_iri := id_to_iri (obj);
          if (starts_with (obj_iri, 'nodeID://'))
            obj_iri := '_:' || subseq (obj_iri, 9);
          http ('{ "id" : "', ses); http_escape (obj_iri, 14, ses, 1, 1); http ('" }', ses);
        }
      else
        {
          declare sqlval any;
          declare dt, lang, strval any;
          dt := 0; lang := 0;
          if (__tag of rdf_box = __tag (obj))
            {
              if (257 <> rdf_box_lang (obj))
                lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = rdf_box_lang (obj)));
--DT          else if (257 <> rdf_box_type (obj))
--DT            dt := coalesce ((select __bft (RDT_QNAME, 1) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = rdf_box_type (obj)));
              sqlval := __rdf_sqlval_of_obj (obj, 1);
--DT          if (__tag of datetime = __tag (sqlval))
--DT            {
--DT              if (257 = rdf_box_type (obj))
--DT                dt := __xsd_type (sqlval);
--DT            }
            }
          else if (__tag (obj) not in (__tag of varchar, __tag of varbinary))
            {
              sqlval := obj;
--DT          dt := __xsd_type (sqlval);
            }
          else
            sqlval := obj;
--DT      if (not (isinteger (dt)))
--DT        {
--DT          http (' datatype="', ses);
--DT          split := sparql_iri_split_rdfa_qname (dt, nsdict, 2);
--DT          if ('' = split[1])
--DT            {
--DT              http_escape (split[2], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else if (isstring (split[0]))
--DT            {
--DT              http_escape (concat (split[0], ':', split[2]), 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT          else
--DT            {
--DT              http_escape (concat ('dt:', split[2]), 3, ses, 1, 1);
--DT              http ('" xmlns:dt="', ses);
--DT              http_escape (split[1], 3, ses, 1, 1);
--DT              http ('"', ses);
--DT            }
--DT        }
--DT      if (isstring (lang))
--DT        {
--DT          http (' xml:lang="', ses);
--DT          http_escape (lang, 3, ses, 1, 1);
--DT          http ('"', ses);
--DT        }
--DT      http ('>', ses);
          if (__tag (sqlval) in (__tag of integer, __tag of real, __tag of double precision, __tag of decimal))
            http_value (sqlval, 0, ses);
          else if (__tag (sqlval) in (__tag of varbinary, __tag of XML))
            {
              declare tmpses any;
              tmpses := string_output();
              http_value (sqlval, 0, tmpses);
              http ('"', ses); http_escape (string_output_string (tmpses), 14, ses, 1, 1); http ('"', ses);
            }
          else if (__tag of varchar = __tag (sqlval))
            {
              http ('"', ses); http_escape (sqlval, 14, ses, 1, 1); http ('"', ses);
            }
          else
            {
              sqlval := __rdf_strsqlval (obj);
              http ('"', ses); http_escape (sqlval, 14, ses, 1, 1); http ('"', ses);
            }
        }
skip_obj: ;
    }
  if (prev_subj is not null)
    http ('] } }', ses);
  http (' }\n', ses);
}
;

-- /* OData ATOM format */
create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_ATOM_XML (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_ATOM_XML_TEXT (triples, 1, ses);
  return ses;
}
;

create procedure DB.DBA.ODATA_EDM_TYPE (in obj any)
{
  if (__tag of int = __tag (obj))
    return 'Int32';
  else if (__tag of smallint  = __tag (obj))
    return 'Int16';
  else if (__tag of bigint = __tag (obj))
    return 'Int64';
  else if (__tag of numeric = __tag (obj))
    return 'Decimal';
  else if (__tag of double precision = __tag (obj))
    return 'Double';
  else if (__tag of real = __tag (obj))
    return 'Double';
  else if (__tag of datetime = __tag (obj))
    return 'DateTime';
  else if (__tag of date = __tag (obj))
    return 'Date';
  else if (__tag of time = __tag (obj))
    return 'Time';
  else if (__tag of varbinary = __tag (obj))
    return 'Binary';
  return null;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_ODATA_JSON (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_ODATA_JSON (triples, ses);
  return ses;
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_ODATA_JSON (inout triples any, inout ses any)
{
  declare tcount, tctr, ns_ctr integer;
  declare dict, entries any;
  declare subj, pred, obj any;
  declare entry_dict, ns_dict, ns_arr any;
  declare pred_tagname varchar;
  declare p_ns_uri, p_ns_pref varchar;
  dict := dict_new ();
  ns_dict := dict_new ();
  ns_ctr := 0;
  tcount := length (triples);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  http ('{ "d" : { \n  "results": [ \n', ses);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      entry_dict := dict_get (dict, subj);
      if (entry_dict is null)
	{
	  entry_dict := dict_new ();
	  dict_put (dict, subj, entry_dict);
	}
      dict_put (entry_dict, vector (pred, obj), 1);
    }
  entries := dict_list_keys (dict, 0);
  tcount := length (entries);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare meta any;
      declare has_meta, mcount int;
      declare title, content varchar;

      has_meta := 0; title := null; content := null;
      subj := entries[tctr];
      entry_dict := dict_get (dict, subj);
      meta := dict_list_keys (entry_dict, 1);

      if (isiri_id (subj)) subj := id_to_iri (subj);
      http ('    { ', ses);
      http (sprintf ('"__metadata": { "uri": "%s" }, \n', subj), ses);
      for (declare i, l int, i := 0, l := length (meta); i < l; i := i + 1)
        {
	  pred := meta[i][0];
	  obj := meta[i][1];
	  if (isiri_id (pred)) pred := id_to_iri (pred);
	  if (isiri_id (obj) or (isstring (obj) and __box_flags (obj) = 1))
	    {
	      -- links
	      if (isiri_id (obj)) obj := id_to_iri (obj);
	      http (sprintf ('      "%s": { "__deferred": { "uri": "%s" } }', pred, obj), ses);
	    }
	  else
	    {
	      -- data
	      declare tmp any;
	      http (sprintf ('      "%s": ', pred), ses);
	      if (__tag of rdf_box = __tag (obj))
		{
		  tmp := __rdf_strsqlval (obj);
		  if (__tag of varchar = __tag (tmp))
		    tmp := charset_recode (tmp, 'UTF-8', '_WIDE_');
		}
	      else
		{
		  tmp := obj;
		}
	      http ('"', ses);
	      http_value (tmp, 0, ses);
	      http ('"', ses);
	    }
	  if (i < l - 1)
  	    http (', \n', ses);
	}
      http ('\n     } ', ses);
      if (tctr < tcount - 1)
	http (', ', ses);
    }
  http (sprintf ('\n ], "__count": "%d"\n } }', tcount), ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_ATOM_XML_TEXT (inout triples any, in print_top_level integer, inout ses any)
{
  declare tcount, tctr, ns_ctr integer;
  declare dict, entries any;
  declare subj, pred, obj any;
  declare entry_dict, ns_dict, ns_arr any;
  declare pred_tagname varchar;
  declare p_ns_uri, p_ns_pref, lang, range varchar;
  declare pct integer;
  declare twobyte integer;

  dict := dict_new ();
  ns_dict := dict_new ();
  ns_ctr := 0; pct := 0;
  tcount := length (triples);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  if (print_top_level)
    {
       http ('<?xml version="1.0" encoding="utf-8" ?>\n<feed \n\t xmlns="http://www.w3.org/2005/Atom" \n'||
      			'\t xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" \n'||
			'\t xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" \n', ses);
    }
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      subj := triples[tctr][0];
      pred := triples[tctr][1];
      obj := triples[tctr][2];
      entry_dict := dict_get (dict, subj);
      if (entry_dict is null)
	{
	  entry_dict := dict_new ();
	  dict_put (dict, subj, entry_dict);
	}
      dict_put (entry_dict, vector (pred, obj), 1);

      if (isiri_id (obj) or (isstring (obj) and __box_flags (obj) = 1))
	goto next;
      if (isiri_id (pred)) pred := id_to_iri (pred);

      p_ns_uri := iri_split (pred, pred_tagname);
      if (length (p_ns_uri) > 0 and dict_get (ns_dict, p_ns_uri) is null)
	{
	  p_ns_pref := __xml_get_ns_prefix (p_ns_uri, 3);
	  if (p_ns_pref is null)
	    {
	      p_ns_pref := sprintf ('ns%dpred', ns_ctr);
	      ns_ctr := ns_ctr + 1;
	    }
	  dict_put (ns_dict, p_ns_uri, p_ns_pref);
	}
      next:;
    }
  ns_arr := dict_to_vector (ns_dict, 0);
  for (declare i int, i := 0; i < length (ns_arr); i := i + 2)
    {
      http (sprintf ('\t xmlns:%s="%s"\n', ns_arr[i+1], ns_arr[i]), ses);
    }
  http ('>\n', ses);
  if (is_http_ctx ())
    {
      declare q, u, h, id varchar;
      declare lines any;
      q := http_request_get ('QUERY_STRING');
      if (length (q))
	q := '?' || q;
      else
        q := '';
      u := http_request_get ('REQUEST_URI');
      h := WS.WS.PARSE_URI (http_requested_url () || q);
      h [2] := u; h [4] := '';
      id := WS.WS.VFS_URI_COMPOSE (h);
      http (sprintf ('\t<id>%V</id>\n', id), ses);
      lines := http_request_header ();
      range := http_request_header_full (lines, 'Accept-Language', 'en');
    }
  else
    {
      http ('\t<id/>\n', ses);
      range := 'en, */*;0.1';
    }
  http (sprintf ('\t<updated>%s</updated>\n', date_iso8601 (dt_set_tz (now (), 0))), ses);
  http ('\t<author><name /></author>\n', ses);
  http (sprintf ('\t<title type="text">OData Service and Descriptor Document</title>\n'), ses);
  entries := dict_list_keys (dict, 0);
  tcount := length (entries);
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare meta any;
      declare has_meta int;
      declare title, content varchar;

      pct := 0;
      has_meta := 0; title := null; content := null;
      subj := entries[tctr];
      entry_dict := dict_get (dict, subj);
      meta := dict_list_keys (entry_dict, 1);
      http ('\t<entry>\n', ses);
      if (isiri_id (subj)) subj := id_to_iri (subj);
      http (sprintf ('\t\t<id>%s</id>\n', subj), ses);
      --http (sprintf ('\t\t<link rel="self" href="%s"/>\n', subj), ses);
      for (declare i, l int, i := 0, l := length (meta); i < l; i := i + 1)
        {
	  pred := meta[i][0];
	  obj := meta[i][1];
	  if (isiri_id (obj) or (isstring (obj) and __box_flags (obj) = 1))
	    {
	      if (isiri_id (obj)) obj := id_to_iri (obj);
	      if (isiri_id (pred)) pred := id_to_iri (pred);
              --p_ns_uri := iri_split (pred, pred_tagname);
	      --if (length (p_ns_uri) > 0)
	      --{
              --  p_ns_pref := dict_get (ns_dict, p_ns_uri);
	      --  pred_tagname := p_ns_pref || ':' || pred_tagname;
              --}
	      http (sprintf ('\t\t<link rel="%s" href="%s"/>\n', pred, obj), ses);
	    }
	  else
	    {
	      if (title is null and
		(
		 pred = iri_to_id ('http://purl.org/dc/terms/title') or
	      	 pred = iri_to_id ('http://www.w3.org/2000/01/rdf-schema#label'))
		)
		{
		   declare rc int;
		   lang := 'en';
		   if (__tag of rdf_box = __tag (obj))
		     {
		       twobyte := rdf_box_lang (obj);
		       if (twobyte <> 257)
		         {
			   lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte), lang);
			 }
		     }
		   rc := langmatches_pct_http (lang, range);
		   if (pct < rc)
		     {
		       title := __rdf_strsqlval (obj);
		       pct := rc;
		     }
		}
	      has_meta := 1;
	    }
	}
      if (title is not null)
	http (sprintf ('\t\t<title>%s</title>\n', title), ses);
      http (sprintf ('\t\t<updated>%s</updated>\n', date_iso8601 (dt_set_tz (now (), 0))), ses);
      http ('\t\t<author><name /></author>\n', ses);
      if (has_meta)
	http ('\t\t<content type="application/xml">\n\t\t\t<m:properties>\n', ses);
      for (declare i, l int, i := 0, l := length (meta); i < l; i := i + 1)
        {
	  pred := meta[i][0];
	  obj := meta[i][1];
	  if (isiri_id (pred)) pred := id_to_iri (pred);
	  if (not (isiri_id (obj) or (isstring (obj) and __box_flags (obj) = 1)))
	    {

              p_ns_uri := iri_split (pred, pred_tagname);
	      if (length (p_ns_uri) = 0)
		{
		  http ('<', ses); http (pred_tagname, ses);
		}
	      else
		{
		  p_ns_pref := dict_get (ns_dict, p_ns_uri);
		  pred_tagname := p_ns_pref || ':' || pred_tagname;
		  http ('\t\t\t\t<', ses); http (pred_tagname, ses);
		  if (__tag of rdf_box = __tag (obj))
		    {
		      declare tmp any;
		      tmp := __rdf_strsqlval (obj);
		       twobyte := rdf_box_lang (obj);
		       if (twobyte <> 257)
			 {
			   lang := coalesce ((select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte), lang);
			   http (sprintf (' xml:lang="%s"', lang), ses);
			 }
		      http ('>', ses);
		      if (__tag of varchar = __tag (tmp))
			tmp := charset_recode (tmp, 'UTF-8', '_WIDE_');
		      http_value (tmp, 0, ses);
		    }
		  else
		    {
		      declare tp varchar;
		      tp := ODATA_EDM_TYPE (obj);
		      if (tp is not null)
                        http (sprintf (' m:type="Edm.%s"', tp), ses);
		      http ('>', ses);
		      if (__tag of varbinary = __tag (obj))
			obj := encode_base64 (cast (obj as varchar));
		      http_value (obj, 0, ses);
		    }
		  http ('</', ses); http (pred_tagname, ses); http ('>\n', ses);
		}
	    }
	}
      if (has_meta)
	http ('\t\t\t</m:properties>\n\t\t</content>\n', ses);
      http ('\t</entry>\n', ses);
    }
  if (print_top_level)
    {
      http ('</feed>', ses);
    }
}
;



-----
-- Export into external serializations for 'define output:format "..."'

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_INIT (inout _env any)
{
  _env := string_output();
  http ('@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rs: <http://www.w3.org/2005/sparql-results#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
[ rdf:type rs:results ;', _env);
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare col_ctr, col_count integer;
  declare blank_ids any;
  if (185 <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_INIT (_env);
  http ('\n  rs:result [', _env);
  col_count := length (colnames);
  for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
    {
      declare _name varchar;
      declare _val any;
      _name := colnames[col_ctr];
      _val := colvalues[col_ctr];
      if (_val is null)
        goto end_of_binding;
      http ('\n      rs:binding [ rs:name "', _env);
      http_value (colnames[col_ctr], 0, _env);
      http ('" ; rs:value ', _env);
      if (isiri_id (_val))
        {
          if (_val >= min_bnode_iri_id ())
	    {
	      http (sprintf ('_:nodeID%d ] ;', iri_id_num (_val)), _env);
	    }
	  else
	    {
              declare res varchar;
              res := id_to_iri (_val);
--              res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = _val));
              if (res is null)
                res := sprintf ('<bad://%d>', iri_id_num (_val));
	      http (sprintf ('<%V> ] ;', res), _env);
	    }
	}
      else
        {
          DB.DBA.RDF_LONG_TO_TTL (_val, _env);
          http (sprintf (' ] ;'), _env);
        }
end_of_binding: ;

    }
  http ('\n      ] ;', _env);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_FIN (inout _env any) returns long varchar
{
  if (185 <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_INIT (_env);

  http ('\n    ] .', _env);
  return string_output_string (_env);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_TTL_FIN
order
;


create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_INIT (inout _env any)
{
  _env := vector (0, 0, string_output());
  http ('@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rs: <http://www.w3.org/2005/sparql-results#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
_:_ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2005/sparql-results#results> .\n', _env[2]);
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare col_ctr, col_count integer;
  declare rowid varchar;
  declare blank_ids any;
  if (__tag of vector <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_INIT (_env);
  if (isinteger (_env[1]))
    {
      declare col_buf any;
      col_count := length (colnames);
      if (185 <> __tag(_env))
        DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_INIT (_env);
      col_buf := make_array (col_count * 7, 'any');
      for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
        col_buf [col_ctr * 7] := colnames[col_ctr];
      _env[1] := col_buf;
    }
  sparql_rset_nt_write_row (0, _env, colvalues);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_FIN (inout _env any) returns long varchar
{
  if (__tag of vector <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_INIT (_env);
  return string_output_string (_env[2]);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_NT_FIN
order
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_INIT (inout _env any)
{
  _env := string_output();
  http ('<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:rs="http://www.w3.org/2005/sparql-results#"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema#" >
  <rs:results rdf:nodeID="rset">', _env);
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  -- dbg_obj_princ ('DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_ACC (..., ', colvalues, colnames, ')');
  declare sol_id varchar;
  declare col_ctr, col_count integer;
  declare blank_ids any;
  if (185 <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_INIT (_env);
  sol_id := cast (length (_env) as varchar);
  http ('\n  <rs:result rdf:nodeID="sol' || sol_id || '">', _env);
  col_count := length (colnames);
  for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
    {
      declare _name varchar;
      declare _val any;
      _name := colnames[col_ctr];
      _val := colvalues[col_ctr];
      if (_val is null)
        goto end_of_binding;
      http ('\n   <rs:binding rdf:nodeID="sol' || sol_id || '-' || cast (col_ctr as varchar) || '" rs:name="', _env);
      http_value (colnames[col_ctr], 0, _env);
      http ('"><rs:value', _env);
      if (isiri_id (_val))
        {
          if (_val >= min_bnode_iri_id ())
	    {
	      http (sprintf (' rdf:nodeID="b%d"/></rs:binding>', iri_id_num (_val)), _env);
	    }
	  else
	    {
              declare res varchar;
              res := id_to_iri (_val);
--              res := coalesce ((select RU_QNAME from DB.DBA.RDF_URL where RU_IID = _val));
              if (res is null)
                res := sprintf ('bad://%d', iri_id_num (_val));
	      http (sprintf (' rdf:resource="%V"/></rs:binding>', res), _env);
	    }
	}
      else
        {
	  declare lang, dt varchar;
	  lang := DB.DBA.RDF_LANGUAGE_OF_LONG (_val, null);
	  dt := DB.DBA.RDF_DATATYPE_IRI_OF_LONG (_val, null);
	  if (lang is not null)
	    {
	      if (dt is not null)
                http (sprintf (' xml:lang="%V" rdf:datatype="%V">',
		    cast (lang as varchar), cast (dt as varchar)), _env);
	      else
                http (sprintf (' xml:lang="%V">',
		    cast (lang as varchar)), _env);
	    }
	  else
	    {
	      if (dt is not null)
                http (sprintf (' rdf:datatype="%V">',
		    cast (dt as varchar)), _env);
	      else
                http (sprintf ('>'), _env);
	    }
	  http_value (__rdf_strsqlval (_val), 0, _env);
          http ('</rs:value></rs:binding>', _env);
        }
end_of_binding: ;

    }
  http ('\n  </rs:result>', _env);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_FIN (inout _env any) returns long varchar
{
  if (185 <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_INIT (_env);

  http ('\n </rs:results>\n</rdf:RDF>', _env);
  return string_output_string (_env);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_RDF_XML_FIN
order
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_INIT (inout _env any)
{
  _env := 0;
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare sol_id varchar;
  declare col_ctr, col_count, need_comma integer;
  declare blank_ids any;
  col_count := length (colnames);
  if (185 <> __tag(_env))
    {
      _env := string_output ();
      http ('\n{ "head": { "link": [], "vars": [', _env);
      for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
        {
          if (col_ctr > 0)
            http(', "', _env);
          else
            http('"', _env);
          http_escape (colnames[col_ctr], 11, _env, 0, 1);
          http('"', _env);
        }
      http ('] },\n  "results": { "distinct": false, "ordered": true, "bindings": [\n    {', _env);
    }
  else
    http(',\n    {', _env);
  need_comma := 0;
  for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
    {
      declare val any;
      val := colvalues[col_ctr];
      if (val is null)
        goto end_of_val_print; -- see below
      if (need_comma)
        http('\t,', _env);
      else
        need_comma := 1;
      DB.DBA.SPARQL_RESULTS_JSON_WRITE_BINDING (_env, colnames[col_ctr], val);
end_of_val_print: ;
    }
  http('}', _env);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_FIN (inout _env any) returns long varchar
{
  if (185 <> __tag(_env))
    {
      _env := string_output ();
      http ('\n{ "head": { "link": [], "vars": [] },\n  "results": { "distinct": false, "ordered": true, "bindings": [', _env);
    }
  http (' ] } }', _env);
  return string_output_string (_env);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_JSON_FIN
order
;



create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_INIT (inout _env any)
{
  _env := 0;
}
;

create procedure DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (inout _env any, in val any)
{
  declare t integer;
  t := __tag (val);
  if (t = __tag of rdf_box)
    {
      if (__tag of datetime = rdf_box_data_tag (val))
	{
	  http ('"', _env);
	  __rdf_long_to_ttl (val, _env);
	  http ('"', _env);
	  return;
	}
      val := rdf_box_data (val);
      t := __tag (val);
    }
  if (t in (__tag of integer, __tag of numeric, __tag of double precision, __tag of float, __tag of date, __tag of time, __tag of datetime, __tag of real))
    {
      http_value (__rdf_strsqlval (val), 0, _env);
      return;
    }
  if (t = __tag of IRI_ID)
    val := id_to_iri (val);
  http ('"', _env);
  http (replace (cast (val as varchar), '"', '""'), _env);
  http ('"', _env);
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare sol_id varchar;
  declare col_ctr, col_count integer;
  declare blank_ids any;
  col_count := length (colnames);
  if (185 <> __tag(_env))
    {
      _env := string_output ();
      for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
        {
          if (col_ctr > 0)
            http(',', _env);
          DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (_env, colnames[col_ctr]);
        }
      http ('\n', _env);
    }
  for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
    {
      declare val any;
      val := colvalues[col_ctr];
      if (col_ctr > 0)
        http(',', _env);
      if (val is not null)
        DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (_env, val);
    }
  http('\n', _env);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_FIN (inout _env any) returns long varchar
{
  if (185 <> __tag(_env))
    return '';
  return string_output_string (_env);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_FIN
order
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_TSV_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare sol_id varchar;
  declare col_ctr, col_count integer;
  declare blank_ids any;
  col_count := length (colnames);
  if (185 <> __tag(_env))
    {
      _env := string_output ();
      for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
        {
          if (col_ctr > 0)
            http('\t', _env);
          DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (_env, colnames[col_ctr]);
        }
      http ('\n', _env);
    }
  for (col_ctr := 0; col_ctr < col_count; col_ctr := col_ctr + 1)
    {
      declare val any;
      val := colvalues[col_ctr];
      if (col_ctr > 0)
        http('\t', _env);
      if (val is not null)
        DB.DBA.SPARQL_RESULTS_CSV_WRITE_VALUE (_env, val);
    }
  http('\n', _env);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_TSV (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_TSV_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_CSV_FIN
order
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_INIT (inout _env any)
{
  _env := 0;
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare agg, colvalues_copy any;
  colvalues_copy := colvalues;
  if (isinteger (_env))
    {
      vectorbld_init (agg);
      _env := vector (0, colnames);
    }
  else
    {
      agg := aref_set_0 (_env, 0);
    }
  vectorbld_acc (agg, colvalues_copy);
  aset_zap_arg (_env, 0, agg);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_FIN (inout _env any) returns long varchar
{
  declare ses, metas, rset any;
  declare accept varchar;
  declare add_http_headers integer;
  ses := string_output ();
  if (isinteger (_env))
    {
      metas := vector (vector (vector ('s')), 1);
      rset := vector ();
      DB.DBA.SPARQL_RESULTS_CXML_WRITE (ses, metas, rset, accept, add_http_headers);
    }
  else
    {
      declare cols any;
      declare colctr, colcount integer;
      rset := aref_set_0 (_env, 0);
      vectorbld_final (rset);
      cols := aref_set_0 (_env, 1);
      colcount := length (cols);
      for (colctr := 0; colctr < colcount; colctr := colctr + 1) cols[colctr] := vector (cols[colctr]);
      metas := vector (cols, vector ());
      DB.DBA.SPARQL_RESULTS_CXML_WRITE (ses, metas, rset, accept, add_http_headers);
    }
  return string_output_string (ses);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_CXML_FIN
order
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_INIT (inout _env any)
{
  _env := vector (0, 0, string_output());
}
;

create procedure DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_ACC (inout _env any, inout colvalues any, inout colnames any)
{
  declare col_ctr, col_count integer;
  declare ses any;
  declare rowid varchar;
  declare blank_ids any;
  if (__tag of vector <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_INIT (_env);
  if (isinteger (_env[1]))
    {
      if (185 <> __tag(_env))
        DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_INIT (_env);
      _env[1] := colnames;
      ses := aref_set_0 (_env, 2);
      http ('BINDINGS', ses);
      foreach (varchar colname in colnames) do { http (' ?' || colname, ses); }
      http (' {', ses);
    }
  else
    ses := aref_set_0 (_env, 2);
  http ('\n  (', ses);
  foreach (any val in colvalues) do
    {
      if (val is null)
        http ('\tUNDEF', ses);
      else
        {
          http ('\t', ses);
          http_nt_object (val, ses);
        }
    }
  http ('\t)', ses);
  aset_zap_arg (_env, 2, ses);
}
;

create function DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_FIN (inout _env any) returns long varchar
{
  declare ses any;
  if (__tag of vector <> __tag(_env))
    DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_INIT (_env);
  if (isinteger (_env[1]))
    return 'BINDINGS ?EmptyResultSetStub { }';
  ses := aref_set_0 (_env, 2);
  if (not isinteger (_env[1]))
    http ('\n}', ses);
  return string_output_string (ses);
}
;

create aggregate DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS (in colvalues any, in colnames any) returns long varchar
from DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_INIT, DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_ACC, DB.DBA.RDF_FORMAT_RESULT_SET_AS_BINDINGS_FIN
order
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_TTL (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_TTL (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_NICE_TTL (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  if (2666 < dict_size (triples_dict)) -- The "nice" algorithm is too slow to be applied to large outputs. There's also a limit for 8000 namespace prefixes.
    return DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_TTL (triples_dict);
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    triples := vector ();
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_NICE_TTL (triples, ses);
  return ses;
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_NICE_TTL (inout triples any, inout ses any)
{
  declare tcount integer;
  tcount := length (triples);
  if (0 = tcount)
    {
      http ('# Empty Turtle\n', ses);
      return;
    }
  if (2666 < tcount) -- The "nice" algorithm is too slow to be applied to large outputs. There's also a limit for 8000 namespace prefixes.
    {
      DB.DBA.RDF_TRIPLES_TO_TTL (triples, ses);
      return;
    }
  DB.DBA.RDF_TRIPLES_TO_NICE_TTL_IMPL (triples, 0, ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_NICE_TTL_IMPL (inout triples any, in env_flags integer, inout ses any)
{
  declare bnode_usage_dict any;
  declare tail_to_head_dict any;
  declare env, printed_triples_mask any;
  declare tcount, tctr, bnode_ctr integer;
  declare prefixes_are_printed integer;
  declare prev_s, prev_p varchar;
  DB.DBA.RDF_TRIPLES_DOMINANCE_DATA (triples, 0, bnode_usage_dict, tail_to_head_dict, printed_triples_mask);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
-- Start the actual serialization
  env := DB.DBA.RDF_TRIPLES_TO_TTL_ENV (tcount, env_flags, 0, ses);
  tcount := length (triples);
  prefixes_are_printed := 0;
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    prefixes_are_printed := prefixes_are_printed + http_ttl_prefixes (env, triples[tctr][0], triples[tctr][1], triples[tctr][2], ses);
  if (prefixes_are_printed)
    http ('\n', ses);
  prev_s := '';
  prev_p := '';
  -- dbg_obj_princ ('printed_triples_mask="', printed_triples_mask, '"');
  for (tctr := 0; tctr < tcount; tctr := tctr + 1)
    {
      declare s_iid, o_iid IRI_ID;
      declare s, p, o any;
      if (ascii (' ') <> printed_triples_mask[tctr])
        goto done_triple;
      s := triples[tctr][0];
      p := triples[tctr][1];
      o := triples[tctr][2];
      s_iid := iri_to_id_nosignal (s);
      o_iid := iri_to_id_nosignal (o);
      if (is_bnode_iri_id (s_iid))
        {
          declare u any;
          u := dict_get (bnode_usage_dict, s_iid, null);
          if (isiri_id (u[0]))
            {
              -- dbg_obj_princ ('Skipping ', tctr, '/', tcount, triples[tctr][0], triples[tctr][1], triples[tctr][2], ': subj has ', u);
              goto done_triple;
            }
        }
      -- dbg_obj_princ ('Printing ', tctr, '/', tcount, triples[tctr][0], triples[tctr][1], triples[tctr][2]);
      if (s <> prev_s)
        {
          if (prev_s <> '')
            http (' .\n', ses);
          http_ttl_value (env, s, 0, ses);
          http ('\n\t', ses);
          prev_s := s;
          prev_p := '';
        }
      if (p <> prev_p)
        {
          if (prev_p <> '')
            http (' ;\n\t', ses);
          http_ttl_value (env, p, 1, ses);
          http ('\t', ses);
          prev_p := p;
        }
      else
        http (' , ', ses);
      printed_triples_mask[tctr] := ascii ('p');
      if (is_bnode_iri_id (o_iid))
        DB.DBA.RDF_TRIPLE_OBJ_BNODE_TO_NICE_TTL (triples, printed_triples_mask, o_iid, env, bnode_usage_dict, 2, ses);
      else
        http_ttl_value (env, o, 2, ses);
      -- dbg_obj_princ ('printed_triples_mask="', printed_triples_mask, '"');
done_triple: ;
    }
done_data:
  if (prev_s is not null)
    http (' .\n', ses);
  else
    http ('# Empty Turtle (no valid data to print)\n', ses);
}
;

create procedure DB.DBA.RDF_TRIPLE_OBJ_BNODE_TO_NICE_TTL (inout triples any, inout printed_triples_mask any, in s_bnode_iid IRI_ID, inout env any, inout bnode_usage_dict any, in depth integer, inout ses any)
{
  declare u, subj, prev_p any;
  declare tctr, tcount integer;
  u := dict_get (bnode_usage_dict, s_bnode_iid, null);
  if (u[0] is not null and not isiri_id (u[0]))
    {
      -- dbg_obj_princ ('Printing plain bnode ', s_bnode_iid, ' u=', u);
      http_ttl_value (env, s_bnode_iid, 2, ses);
      return;
    }
  if (isinteger (u[5]))
    {
      -- dbg_obj_princ ('Printing list from ', s_bnode_iid, ' u=', u);
      http ('(', ses);
      while (is_bnode_iri_id (s_bnode_iid))
        {
          declare itm any;
          declare itm_iid IRI_ID;
          itm := triples[u[3]][2];
          itm_iid := iri_to_id_nosignal (itm);
          if (ascii (' ') <> printed_triples_mask[u[3]]) signal ('OBLOM', 'Corrupted CAR in list');
          if (ascii (' ') <> printed_triples_mask[u[4]]) signal ('OBLOM', 'Corrupted CDR in list');
          printed_triples_mask[u[3]] := ascii ('A');
          http (' ', ses);
          if (is_bnode_iri_id (itm_iid))
            DB.DBA.RDF_TRIPLE_OBJ_BNODE_TO_NICE_TTL (triples, printed_triples_mask, itm_iid, env, bnode_usage_dict, depth + 1, ses);
          else
            http_ttl_value (env, itm, 2, ses);
          printed_triples_mask[u[4]] := ascii ('D');
          s_bnode_iid := iri_to_id_nosignal (triples[u[4]][2]);
          u := dict_get (bnode_usage_dict, s_bnode_iid, null);
          -- dbg_obj_princ ('next node ', s_bnode_iid, ' u=', u);
        }
      http (' )', ses);
      return;
    }
  tctr := u[1];
  if (tctr is null)
    {
      -- dbg_obj_princ ('Printing empty bnode ', s_bnode_iid, ' u=', u);
      http ('[ ]', ses);
      return;
    }
  tcount := length (triples);
  subj := triples[tctr][0];
  prev_p := '';
  http ('[\t', ses);
  -- dbg_obj_princ ('Printing bnode triples for ', s_bnode_iid, ' starting from ', tctr, '/', tcount, ' u=', u);
  while (1=1)
    {
      declare o_iid IRI_ID;
      declare p, o any;
      if (ascii (' ') <> printed_triples_mask[tctr])
        goto done_triple;
      p := triples[tctr][1];
      o := triples[tctr][2];
      o_iid := iri_to_id_nosignal (o);
      if (p <> prev_p)
        {
          if (prev_p <> '')
            http (' ;\n' || repeat ('\t', depth+2), ses);
          http_ttl_value (env, p, 2, ses);
          http ('\t', ses);
          prev_p := p;
        }
      else
        http (' , ', ses);
      printed_triples_mask[tctr] := ascii ('[');
      if (is_bnode_iri_id (o_iid))
        DB.DBA.RDF_TRIPLE_OBJ_BNODE_TO_NICE_TTL (triples, printed_triples_mask, o_iid, env, bnode_usage_dict, depth + 2, ses);
      else
        http_ttl_value (env, o, 2, ses);
done_triple:
      tctr := tctr + 1;
      if (not ((tctr < tcount) and (triples[tctr][0] = subj)))
        {
          http (' ]', ses);
          return;
        }
    }
}
;



create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_TRIG (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_TRIG (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_NT (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_NT (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_RDF_XML (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_RDF_XML_TEXT (triples, 1, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_TALIS_JSON (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_TALIS_JSON (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_JSON_LD (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_JSON_LD (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_JSON_LD_CTX (inout triples_dict any, in ctx_dict any := null) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_JSON_LD_CTX (triples, ses, ctx_dict);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_UL (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_UL (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_TR (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_TR (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_MICRODATA (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_MICRODATA (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_NICE_MICRODATA (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_NICE_MICRODATA (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_NICE_TTL (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    triples := vector ();
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_NICE_TTL (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_SCRIPT_LD_JSON (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    triples := vector ();
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_SCRIPT_LD_JSON (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_HTML_SCRIPT_TTL (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    triples := vector ();
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_HTML_SCRIPT_TTL (triples, ses);
  return ses;
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_HTML_NICE_TTL (inout triples any, inout ses any)
{
  declare tcount integer;
  tcount := length (triples);
  if (0 = tcount)
    {
      http ('# Empty Turtle\n', ses);
      return;
    }
  rowvector_obj_sort (triples, 2, 1);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
  if (2666 < tcount) -- The "nice" algorithm is too slow to be applied to large outputs. There's also a limit for 8000 namespace prefixes.
    {
      http (sprintf ('# The result consists of %d triples so it is too long to be pretty-printed. The dump below contains that triples without any decoration', tcount), ses);
      http ('<xmp>', ses);
      DB.DBA.RDF_TRIPLES_TO_TTL (triples, ses);
      http ('</xmp>', ses);
      return;
    }
  http ('<pre>', ses);
  DB.DBA.RDF_TRIPLES_TO_NICE_TTL_IMPL (triples, 257, ses);
  http ('</pre>', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_HTML_SCRIPT_TTL (inout triples any, inout ses any)
{
  declare tcount integer;
  tcount := length (triples);
  if (0 = tcount)
    {
      http ('<html><head><title>Empty RDF Graph</title></head><body><para>This document contains an empty RDF graph.</para><script type="text/turtle"></script></body></html>\n', ses);
      return;
    }
  http ('<html><head><title>RDF Graph</title></head><body><para>This document contains ' || tcount || ' RDF triples in machine-readable format.</para><script type="text/turtle">', ses);
  rowvector_obj_sort (triples, 2, 1);
  rowvector_subj_sort (triples, 1, 1);
  rowvector_subj_sort (triples, 0, 1);
--  if (2666 < tcount) -- The "nice" algorithm is too slow to be applied to large outputs. There's also a limit for 8000 namespace prefixes.
    DB.DBA.RDF_TRIPLES_TO_TTL (triples, ses);
--  else
--    DB.DBA.RDF_TRIPLES_TO_NICE_TTL_IMPL (triples, 257, ses);
  http ('</script></body></html>', ses);
}
;

create procedure DB.DBA.RDF_TRIPLES_TO_HTML_SCRIPT_LD_JSON (inout triples any, inout ses any)
{
  declare tcount integer;
  tcount := length (triples);
  if (0 = tcount)
    {
      http ('<html><head><title>Empty RDF Graph</title></head><body><para>This document contains an empty RDF graph.</para><script type="application/ld+json"></script></body></html>\n', ses);
      return;
    }
  http ('<html><head><title>RDF Graph</title></head><body><para>This document contains ' || tcount || ' RDF triples in machine-readable format.</para><script type="application/ld+json">', ses);
  DB.DBA.RDF_TRIPLES_TO_JSON_LD (triples, ses);
  http ('</script></body></html>', ses);
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_JSON_MICRODATA (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_JSON_MICRODATA (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_CSV (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_CSV (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_TSV (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_TSV (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_RDFA_XHTML (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_RDFA_XHTML (triples, ses);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_CXML (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  declare accept varchar;
  declare add_http_headers integer;
  add_http_headers := 0;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_CXML (triples, ses, accept, add_http_headers, 0);
  return ses;
}
;

create function DB.DBA.RDF_FORMAT_TRIPLE_DICT_AS_CXML_QRCODE (inout triples_dict any) returns long varchar
{
  declare triples, ses any;
  declare accept varchar;
  declare add_http_headers integer;
  add_http_headers := 0;
  ses := string_output ();
  if (214 <> __tag (triples_dict))
    {
      triples := vector ();
    }
  else
    triples := dict_list_keys (triples_dict, 1);
  DB.DBA.RDF_TRIPLES_TO_CXML (triples, ses, accept, add_http_headers, 1);
  return ses;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_INIT (inout _env any)
{
  _env := 0;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_ACC (inout _env any, in one any array)
{
  _env := 1;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_FIN (inout _env any) returns long varchar
{
  declare ses any;
  declare ans varchar;
  ses := string_output ();
  if (isinteger (_env) and _env)
    ans := 'true';
  else
    ans := 'false';
  http ('<sparql xmlns="http://www.w3.org/2005/sparql-results#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/sw/DataAccess/rf1/result2.xsd">
 <head></head>
 <boolean>' || ans || '</boolean>
</sparql>', ses);
  return ses;
}
;

create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_INIT, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_ACC, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_XML_FIN
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_INIT (inout _env any)
{
  _env := 0;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_ACC (inout _env any, in one any array)
{
  _env := 1;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_FIN (inout _env any) returns long varchar
{
  declare ses any;
  declare ans varchar;
  ses := string_output ();
  if (isinteger (_env) and _env)
    ans := '1';
  else
    ans := '0';
  http ('<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:rs="http://www.w3.org/2005/sparql-results#"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema#" >
  <rs:results rdf:nodeID="rset">
   <rs:boolean rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean">' || ans || '</rs:boolean></rs:results></rdf:RDF>', ses);
  return ses;
}
;

create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_INIT, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_ACC, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_RDF_XML_FIN
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_INIT (inout _env any)
{
  _env := 0;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_ACC (inout _env any, in one any array)
{
  _env := 1;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_FIN (inout _env any) returns long varchar
{
  declare ses any;
  declare ans varchar;
  ses := string_output ();
  if (isinteger (_env) and _env)
    ans := 'TRUE';
  else
    ans := 'FALSE';
  http ('@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rs: <http://www.w3.org/2005/sparql-results#> .\n', ses);
  http (sprintf ('[] rdf:type rs:results ; rs:boolean %s .', ans), ses);
  return ses;
}
;

create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_INIT, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_ACC, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_FIN
;

--!AWK PUBLIC
create function DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_NT_FIN (inout _env any) returns long varchar
{
  declare ses any;
  declare ans varchar;
  ses := string_output ();
  if (isinteger (_env) and _env)
    ans := 'true';
  else
    ans := 'false';
  http (sprintf ('_:_ <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2005/sparql-results#results> .\n_:_ <http://www.w3.org/2005/sparql-results#boolean> "%s"^^<http://www.w3.org/2001/XMLSchema#boolean> .\n', ans), ses);
  return ses;
}
;

create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_NT (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_INIT,	-- Not DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_NT_INIT
 DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_ACC,	-- Not DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_NT_ACC
 DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_NT_FIN
;


create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_INIT, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_ACC, DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_FIN
;

--!AWK PUBLIC
create function DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_CSV_FIN (inout _env any) returns long varchar
{
  declare ans varchar;
  if (isinteger (_env) and _env)
    return '"bool"\n1\n';
  else
    return '"bool"\n0\n';
}
;

create aggregate DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_CSV (in one any array) returns long varchar
from DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_INIT,	-- Not DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_CSV_INIT
 DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_TTL_ACC,	-- Not DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_CSV_ACC
 DB.DBA.RDF_FORMAT_BOOL_RESULT_AS_CSV_FIN
;

-----
-- Insert, delete, modify operations for lists of triples

-- By default, SPARQL 1.0 codegen makes calls of SPARQL_INSERT_DICT_CONTENT() / SPARQL_DELETE_DICT_CONTENT() / SPARQL_MODIFY_BY_DICT_CONTENTS()
-- with SPARQL_CONSTRUCT as an aggregate that makes dictionary of triples
-- SPARQL 1.1 codegen can also make calls of SPARQL_INSERT_QUAD_DICT_CONTENT() / SPARQL_DELETE_QUAD_DICT_CONTENT() / SPARQL_MODIFY_BY_QUAD_DICT_CONTENTS()
-- with SPARQL_CONSTRUCT as an aggregate that makes dictionary of triples or quads.
-- The optimizer can tweak these calls for optimization: instead of plain constant for default graph IRI,
-- a call of SPARQL_INSERT_CTOR / SPARQL_DELETE_CTOR / SPARQL_MODIFY_CTOR can be placed.
-- Thus some triples will be inserted/deleted witout being accumulated in dictionary for the whole time of the selection process.
-- Accomulators SPARQL_INSERT_CTOR_ACC / SPARQL_DELETE_CTOR_ACC / SPARQL_MODIFY_CTOR_ACC are based on a common
-- SPARQL_INS_OR_DEL_CTOR_IMPL that calls either RDF_INSERT_TRIPLES / RDF_INSERT_QUADS or RDF_DELETE_TRIPLES_AGG / RDF_DELETE_QUADS, depending on the requested operation code.
-- A common finalizer SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_FIN calls RDF_INSERT_TRIPLES / RDF_INSERT_QUADS or RDF_DELETE_TRIPLES /* without _AGG suffix*/  / RDF_DELETE_QUADS.


create procedure DB.DBA.RDF_INSERT_TRIPLES_CL (inout graph_iri any, inout triples any, in log_mode integer := null)
{
  declare is_text, ctr, old_log_enable, l integer;
  declare ro_id_dict, dp any;
  if ('1' = registry_get ('cl_rdf_text_index'))
    is_text := 1;
  if (not isiri_id (graph_iri))
    graph_iri := iri_to_id (graph_iri);
  if (__rdf_graph_is_in_enabled_repl (graph_iri))
    DB.DBA.RDF_REPL_INSERT_TRIPLES (id_to_iri (graph_iri), triples);
  connection_set ('g_iid', graph_iri);
  ro_id_dict := null;
  --ro_id_dict := dict_new ();
  --connection_set ('g_dict', ro_id_dict);
  dp := dpipe (0, 'IRI_TO_ID_1', 'IRI_TO_ID_1', 'IRI_TO_ID_1', 'MAKE_RO_1', 'IRI_TO_ID_1');
  dpipe_set_rdf_load (dp);
  l := length (triples);
  for (ctr := 0; ctr < l; ctr := ctr + 1)
    {
      declare r, o_val any;
      r := triples[ctr];
      o_val := r[2];
      if (__tag (o_val) in (__tag of varchar, __tag of XML))
        {
          if (is_text)
            {
              -- make first first non default type because if all is default it will make no box
              declare o_val_2 any;
              o_val_2 := rdf_box (o_val, 300, 257, 0, 1);
              rdf_box_set_is_text (o_val_2, 1);
              rdf_box_set_type (o_val_2, 257);
              -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES_CL inserts text1 ', r[0], r[1], null, o_val_2, null);
              dpipe_input (dp, r[0], r[1], null, o_val_2, null);
            }
          else
            {
              -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES_CL inserts text0 ', r[0], r[1], null, o_val, null);
              -- dbg_obj_princ ('zero is_text in sparql.sql:6618 ', o_val);
              dpipe_input (dp, r[0], r[1], null, o_val, null);
            }
        }
      else
        {
          -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES_CL inserts ', r[0], r[1], null, o_val);
          -- dbg_obj_princ ('unknown is_text in sparql.sql:6626 ', o_val);
          dpipe_input (dp, r[0], r[1], null, o_val, null);
        }
      if (mod (ctr + 1, 40000) = 0 and l > 60000)
	{
	  dpipe_next (dp, 0);
	  dpipe_next (dp, 1);
	  dpipe_reuse (dp);
	}
    }
  dpipe_next (dp, 0);
  dpipe_next (dp, 1);
  if (ro_id_dict is not null)
    DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (graph_iri, ro_id_dict);
}
;

/* insert */
create procedure DB.DBA.RDF_INSERT_TRIPLES (in graph_iid any, inout triples any, in log_mode integer := null)
{
  declare ctr, old_log_enable integer;
  declare ro_id_dict any;
  if (0 = sys_stat ('cl_run_local_only'))
    return RDF_INSERT_TRIPLES_CL (graph_iid, triples, log_mode);
  if (not isiri_id (graph_iid))
    graph_iid := iri_to_id (graph_iid);
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  if (0 = bit_and (old_log_enable, 2))
    {
      declare dp any;
      dp := rl_local_dpipe ();
      connection_set ('g_iid', graph_iid);
      for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
	{
	  declare s_iid, p_iid, obj, o_type, o_lang any;
	s_iid := triples[ctr][0];
	p_iid := triples[ctr][1];
	obj :=   triples[ctr][2];
	  if (isiri_id (obj))
	    dpipe_input (dp, s_iid, p_iid, obj, null);
	  else
            {
              __rdf_obj_set_is_text_if_ft_rule_check (obj, graph_iid, p_iid, null);
	    dpipe_input (dp, s_iid, p_iid, null, obj);
	}
        }
      rl_flush (dp, graph_iid);
      return;
    }
  if (not is_atomic ())
    {
      declare app_env any;
      -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES, not atomic');
      app_env := vector (async_queue (0, 1), rl_local_dpipe (), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
      connection_set ('g_iid', graph_iid);
      for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
         {
	   declare s_iid, p_iid, obj, o_type, o_lang any;
	   s_iid := triples[ctr][0];
	   p_iid := triples[ctr][1];
	   obj :=   triples[ctr][2];
	   if (isiri_id (obj))
	     dpipe_input (app_env[1], s_iid, p_iid, obj, null);
	   else
             {
               __rdf_obj_set_is_text_if_ft_rule_check (obj, graph_iid, p_iid, null);
	     dpipe_input (app_env[1], s_iid, p_iid, null, obj);
             }
	   if (dpipe_count (app_env[1]) > dc_batch_sz ())
             rl_send (app_env, graph_iid);
         }
      rl_send (app_env, graph_iid);
      commit work;
      aq_wait_all (app_env[0]);
      connection_set ('g_dict', null);
      log_enable (old_log_enable, 1);
      return;
    }
  if (__rdf_graph_is_in_enabled_repl (graph_iid))
    DB.DBA.RDF_REPL_INSERT_TRIPLES (id_to_iri (graph_iid), triples);
  ro_id_dict := null;
  for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
    {
      declare p_iid, o_orig, o_final any;
      declare need_digest integer;
      p_iid := triples[ctr][1];
      o_final := o_orig := triples[ctr][2];
      if (isiri_id (o_final))
        goto do_insert;
      if (ro_id_dict is null and __rdf_obj_ft_rule_check (graph_iid, p_iid))
        ro_id_dict := dict_new ();
      -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES got ', graph_iid, triples[ctr][0], p_iid, o_final);
      need_digest := rdf_box_needs_digest (o_final, ro_id_dict);
      if (1 < need_digest)
        {
          o_final := DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL_FT (o_final, graph_iid, p_iid, ro_id_dict);
          --if (not rdf_box_is_storeable (o_final))
          --  {
          --    -- dbg_obj_princ ('OBLOM', 'Bad O after DB.DBA.MAKE_OBJ_OF_SQLVAL_FT', o_orig, '=>', o_final);
          --    signal ('OBLOM', 'Bad O after MAKE_OBJ_OF_SQLVAL_FT');
          --  }
        }
      else
        {
          o_final := DB.DBA.RDF_OBJ_ADD (257, o_final, 257);
          --if (not rdf_box_is_storeable (o_final))
          --  {
          --    -- dbg_obj_princ ('OBLOM', 'Bad O after DB.DBA.RDF_OBJ_ADD', o_orig, '=>', o_final);
          --    signal ('OBLOM', 'Bad O after DB.DBA.RDF_OBJ_ADD');
          --  }
        }
do_insert:
      -- dbg_obj_princ ('DB.DBA.RDF_INSERT_TRIPLES inserts ', graph_iid, triples[ctr][0], p_iid, o_final);
      insert soft DB.DBA.RDF_QUAD (G,S,P,O)
      values (graph_iid, triples[ctr][0], p_iid, o_final);
    }
  if (ro_id_dict is not null)
    DB.DBA.RDF_OBJ_ADD_KEYWORD_FOR_GRAPH (graph_iid, ro_id_dict);
  log_enable (old_log_enable, 1);
}
;

create procedure DB.DBA.RDF_DELETE_TRIPLES (in graph_iri any, in triples any, in log_mode integer := null)
{
  declare ctr, old_log_enable, l integer;
  if (not isiri_id (graph_iri))
    graph_iri := iri_to_id (graph_iri);
  if (__rdf_graph_is_in_enabled_repl (graph_iri))
    DB.DBA.RDF_REPL_DELETE_TRIPLES (id_to_iri (graph_iri), triples);
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  if (1 = sys_stat ('enable_vec'))
    {
      declare gv, sv, pv, ov any;
      l := length (triples);
      gv := make_array (l, 'any');
      sv := make_array (l, 'any');
      pv := make_array (l, 'any');
      ov := make_array (l, 'any');
      for (ctr := 0; ctr < l; ctr := ctr + 1)
        {
          declare r any;
          r := triples[ctr];
	  gv[ctr] := graph_iri;
	  sv[ctr] := r[0];
	  pv[ctr] := r[1];
	  ov[ctr] := DB.DBA.RDF_OBJ_OF_LONG (r[2]);
	}
      for vectored (in gi any := gv, in si any := sv, in pi any := pv, in oi any array := ov)
         {
	   delete from DB.DBA.RDF_QUAD where G = gi and S = si and P = pi and O = oi;
	 }
      log_enable (old_log_enable, 1);
      return;
    }
  for (ctr := length (triples) - 1; ctr >= 0; ctr := ctr - 1)
    {
      declare o_short any;
      o_short := DB.DBA.RDF_OBJ_OF_LONG (triples[ctr][2]);
--      {
--        whenever sqlstate '*' goto strange_fail;
          delete from DB.DBA.RDF_QUAD
          where G = graph_iri and S = triples[ctr][0] and P = triples[ctr][1] and O = o_short;
--        goto complete;
--      }
--strange_fail:
--      if (not exists (select top 1 1 from DB.DBA.RDF_QUAD
--      where G = graph_iri and S = triples[ctr][0] and P = triples[ctr][1] and O = o_short ) )
--        goto complete;
--      delete from DB.DBA.RDF_QUAD
--      where G = graph_iri and S = triples[ctr][0] and P = triples[ctr][1] and O = o_short;
-- complete: ;
    }
  log_enable (old_log_enable, 1);
}
;

-- /* delete */
create procedure DB.DBA.RDF_DELETE_TRIPLES_AGG (in graph_iid any, inout triples any, in log_mode integer := null)
{
  declare ctr, old_log_enable, l integer;
  declare is_local int;
  declare dp any array;
  is_local := sys_stat ('cl_run_local_only');
  if (not isiri_id (graph_iid))
    graph_iid := iri_to_id (graph_iid);
  if (__rdf_graph_is_in_enabled_repl (graph_iid))
    DB.DBA.RDF_REPL_DELETE_TRIPLES (id_to_iri (graph_iid), triples);
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  if (is_local)
    dp := dpipe (5, 'L_IRI_TO_ID', 'L_IRI_TO_ID', 'L_IRI_TO_ID', 'L_MAKE_RO');
  else
    dp := dpipe (5, 'IRI_TO_ID_1', 'IRI_TO_ID_1', 'IRI_TO_ID_1', 'MAKE_RO_1');
  dpipe_set_rdf_load (dp, 8);
  for vectored (in a_triple any array := triples)
            {
      declare a_s, a_p, a_o any array;
      a_s := a_triple[0];
      a_p := a_triple[1];
      a_o := a_triple[2];
      dpipe_input (dp, graph_iid, a_s, a_p, a_o);
    }
  if (is_local)
    rl_dp_ids (dp, 0);
  else
    {
      dpipe_next (dp, 0);
      dpipe_next (dp, 1);
        }
      log_enable (old_log_enable, 1);
    }
;

create procedure DB.DBA.RDF_MODIFY_TRIPLES (in graph_iri any, in del_triples any, in ins_triples any, in log_mode integer := null)
{
  DB.DBA.RDF_DELETE_TRIPLES (graph_iri, del_triples, log_mode);
  DB.DBA.RDF_INSERT_TRIPLES (graph_iri, ins_triples, log_mode);
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_INIT (inout _env any)
{
  _env := 0;
}
;

create procedure DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (inout _env any, in graph_iri any, in opcodes any, in vars any, in log_mode integer, in ctor_op integer)
{
  declare triple_ctr, quads_found integer;
  declare blank_ids any;
  declare dict any;
  declare action_ctr integer;
  declare old_log_enable integer;
  old_log_enable := log_enable (log_mode, 1);
  -- dbg_obj_princ ('DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (', _env, graph_iri, opcodes, vars, log_mode, ctor_op, ')');
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  blank_ids := 0;
  action_ctr := 0;
  quads_found := _env[5 + ctor_op];
  for (triple_ctr := length (opcodes) - 1; triple_ctr >= 0; triple_ctr := triple_ctr-1)
    {
      declare fld_ctr, fld_count integer;
      declare triple_vec any;
      declare g_opcode integer;
      g_opcode := aref_or_default (opcodes, triple_ctr, 6, null);
      if (g_opcode is null)
        {
          fld_count := 3;
          triple_vec := vector (0,0,0);
        }
      else
        {
          fld_count := 4;
          triple_vec := vector (0,0,0,0);
        }
      for (fld_ctr := fld_count - 1; fld_ctr >= 0; fld_ctr := fld_ctr - 1)
        {
          declare op integer;
          declare arg any;
          op := opcodes[triple_ctr][fld_ctr * 2];
          arg := opcodes[triple_ctr][fld_ctr * 2 + 1];
          if (1 = op)
            {
              declare i any;
              i := vars[arg];
              if (i is null)
                goto end_of_adding_triple;
              if (isiri_id (i))
                {
                  if (fld_ctr in (1,3) and is_bnode_iri_id (i))
                    signal ('RDF01', 'Bad variable value in INSERT: blank node can not be used as predicate or graph');
                }
              else if ((isstring (i) and (1 = __box_flags (i))) or (__tag of UNAME = __tag(i)))
                {
                  if (fld_ctr in (1,3) and (i like 'bnode://%'))
                    signal ('RDF01', 'Bad variable value in INSERT: blank node can not be used as predicate or graph');
                  i := iri_to_id (i);
                }
              else if (2 <> fld_ctr)
                signal ('RDF01',
                  sprintf ('Bad variable value in INSERT: "%.100s" (tag %d box flags %d) is not a valid %s, only object of a triple can be a literal',
                    __rdf_strsqlval (i), __tag (i), __box_flags (i),
                    case (fld_ctr) when 1 then 'predicate' else 'subject' end ) );
              triple_vec[fld_ctr] := i;
            }
          else if (2 = op)
            {
              if (isinteger (blank_ids))
                blank_ids := vector (iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK')));
              while (arg >= length (blank_ids))
                blank_ids := vector_concat (blank_ids, vector (iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK'))));
              if (fld_ctr in (1,3))
                signal ('RDF01', 'Bad triple for INSERT: blank node can not be used as predicate');
              triple_vec[fld_ctr] := blank_ids[arg];
            }
          else if (3 = op)
            {
              if (arg is null)
                goto end_of_adding_triple;
              if (isiri_id (arg))
                {
                  if (fld_ctr in (1,3) and is_bnode_iri_id (arg))
                    signal ('RDF01', 'Bad const value in INSERT: blank node can not be used as predicate or graph');
                }
              else if ((isstring (arg) and (1 = __box_flags (arg))) or (__tag of UNAME = __tag(arg)))
                {
                  if (fld_ctr in (1,3) and (arg like 'bnode://%'))
                    signal ('RDF01', 'Bad const value in INSERT: blank node can not be used as predicate or graph');
                  arg := iri_to_id (arg);
                }
              else if (2 <> fld_ctr)
                signal ('RDF01',
                  sprintf ('Bad const value in INSERT: "%.100s" (tag %d box flags %d) is not a valid %s, only object of a triple can be a literal',
                    __rdf_strsqlval (arg), __tag (arg), __box_flags (arg),
                    case (fld_ctr) when 1 then 'predicate' else 'subject' end ) );
              else if (__tag of vector = __tag (arg))
                arg := DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (arg[0], arg[1], arg[2]);
              triple_vec[fld_ctr] := arg;
            }
          else signal ('RDFXX', 'Bad opcode in DB.DBA.SPARQL_INSERT_CTOR()');
        }
      -- dbg_obj_princ ('generated triple:', triple_vec);
      if (4 = fld_count)
        quads_found := 1;
      dict := _env [2 + ctor_op];
      dict_put (dict, triple_vec, 1);
      if (1 = ctor_op)
        {
--          delete from DB.DBA.RDF_QUAD
--          where G = _env[0] and S = triple_vec[0] and P = triple_vec[1] and O = DB.DBA.RDF_OBJ_OF_LONG(triple_vec[2]);
          if (80000 <= dict_size (dict))
            {
              if (quads_found)
                {
                  DB.DBA.RDF_DELETE_QUADS (_env[0], dict_list_keys (dict, 2), _env[8], _env[5]);
                  quads_found := 0;
                }
              else
                DB.DBA.RDF_DELETE_TRIPLES_AGG (_env[0], dict_list_keys (dict, 2), _env[5]);
            }
        }
      else
        {
--          insert soft DB.DBA.RDF_QUAD (G,S,P,O)
--          values (_env[0], triple_vec[0], triple_vec[1], DB.DBA.RDF_OBJ_OF_LONG(triple_vec[2]));
          if (80000 <= dict_size (dict))
            {
              if (quads_found)
                {
                  DB.DBA.RDF_INSERT_QUADS (_env[0], dict_list_keys (dict, 2), _env[8], _env[5]);
                  quads_found := 0;
                }
              else
                DB.DBA.RDF_INSERT_TRIPLES (_env[0], dict_list_keys (dict, 2), _env[5]);
            }
        }
      action_ctr := action_ctr + 1;
end_of_adding_triple: ;
    }
  _env[ctor_op] := _env[ctor_op] + action_ctr;
  _env[5 + ctor_op] := quads_found;
  log_enable (old_log_enable, 1);
}
;

create function DB.DBA.SPARQL_DELETE_CTOR_ACC (inout _env any, in graph_iri any, in opcodes any, in vars any, in uid integer, in log_mode integer)
{
  if (not (isarray (_env)))
--                  0                      1  2  3                 4     5         6  7  8
    _env := vector (iri_to_id (graph_iri), 0, 0, dict_new (80000), null, log_mode, 0, 0, uid);
  if (not _env[1])
    __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL DELETE');
  DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (_env, graph_iri, opcodes, vars, log_mode, 1);
}
;

create procedure DB.DBA.SPARQL_INSERT_CTOR_ACC (inout _env any, in graph_iri any, in opcodes any, in vars any, in uid integer, in log_mode integer)
{
  -- dbg_obj_princ ('DB.DBA.SPARQL_INSERT_CTOR_ACC (', _env, graph_iri, opcodes, vars, uid, log_mode);
  if (not (isarray (_env)))
--                  0                      1  2  3     4                 5         6  7  8
    _env := vector (iri_to_id (graph_iri), 0, 0, null, dict_new (80000), log_mode, 0, 0, uid);
  if (not _env[2])
    __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL INSERT');
  DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (_env, graph_iri, opcodes, vars, log_mode, 2);
}
;

create procedure DB.DBA.SPARQL_MODIFY_CTOR_ACC (inout _env any, in graph_iri any, in del_opcodes any, in ins_opcodes any, in vars any, in uid integer, in log_mode integer)
{
  if (not (isarray (_env)))
--                  0                      1  2  3                 4                 5         6  7  8
    _env := vector (iri_to_id (graph_iri), 0, 0, dict_new (80000), dict_new (80000), log_mode, 0, 0, uid);
  if (not _env[1] and not _env[2])
    __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL MODIFY');
  DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (_env, graph_iri, del_opcodes, vars, log_mode, 1);
  DB.DBA.SPARQL_INS_OR_DEL_CTOR_IMPL (_env, graph_iri, ins_opcodes, vars, log_mode, 2);
}
;

create procedure DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_FIN (inout _env any)
{
  if (isarray (_env))
    {
      declare dict any;
      dict := _env[3];
      if (dict is not null and (0 < dict_size (dict)))
        {
          _env[3] := null;
          if (_env[6])
            DB.DBA.RDF_DELETE_QUADS (_env[0], dict_list_keys (dict, 2), _env[8], _env[5]);
          else
            DB.DBA.RDF_DELETE_TRIPLES (_env[0], dict_list_keys (dict, 2), _env[5]);
        }
      dict := _env[4];
      if (dict is not null and (0 < dict_size (dict)))
        {
          _env[4] := null;
          if (_env[7])
            DB.DBA.RDF_INSERT_QUADS (_env[0], dict_list_keys (dict, 2), _env[8], _env[5]);
          else
            DB.DBA.RDF_INSERT_TRIPLES (_env[0], dict_list_keys (dict, 2), _env[5]);
        }
    }
  return _env;
}
;

create aggregate DB.DBA.SPARQL_DELETE_CTOR (in graph_iri any, in opcodes any, in vars any, in uid integer, in log_mode integer) returns any
from DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_INIT, DB.DBA.SPARQL_DELETE_CTOR_ACC, DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_FIN
;

create aggregate DB.DBA.SPARQL_INSERT_CTOR (in graph_iri any, in opcodes any, in vars any, in uid integer, in log_mode integer) returns any
from DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_INIT, DB.DBA.SPARQL_INSERT_CTOR_ACC, DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_FIN
;

create aggregate DB.DBA.SPARQL_MODIFY_CTOR (in graph_iri any, in del_opcodes any, in ins_opcodes any, in vars any, in uid integer, in log_mode integer) returns any
from DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_INIT, DB.DBA.SPARQL_MODIFY_CTOR_ACC, DB.DBA.SPARQL_INS_OR_DEL_OR_MODIFY_CTOR_FIN
;

create function DB.DBA.SPARQL_INSERT_DICT_CONTENT (in graph_iri any, in triples_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare triples any;
  declare ins_count integer;
  ins_count := 0;
  if (__tag of vector = __tag (graph_iri))
    {
      ins_count := graph_iri[2]; -- 2, not 1
      graph_iri := graph_iri[0]; -- the last op.
    }
  __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL INSERT');
  while (dict_size (triples_dict) > 0)
    {
      triples := dict_destructive_list_rnd_keys (triples_dict, 80000);
      DB.DBA.RDF_INSERT_TRIPLES (graph_iri, triples, log_mode);
      ins_count := ins_count + length (triples);
    }
  if (isiri_id (graph_iri))
    graph_iri := id_to_iri (graph_iri);
  if (graph_iri is not null and __rdf_graph_is_in_enabled_repl (iri_to_id (graph_iri)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  if (compose_report)
    {
      if (ins_count)
        return sprintf ('Insert into <%s>, %d (or less) triples -- done', graph_iri, ins_count);
      else
        return sprintf ('Insert into <%s>, 0 triples -- nothing to do', graph_iri);
    }
  else
    return ins_count;
}
;

create function DB.DBA.SPARQL_DELETE_DICT_CONTENT (in graph_iri any, in triples_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare triples any;
  declare del_count integer;
  del_count := 0;
  if (__tag of vector = __tag (graph_iri))
    {
      del_count := graph_iri[1];
      graph_iri := graph_iri[0]; -- the last op.
    }
  __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL DELETE');
  while (dict_size (triples_dict) > 0)
    {
      triples := dict_destructive_list_rnd_keys (triples_dict, 2000000);
      DB.DBA.RDF_DELETE_TRIPLES_AGG (graph_iri, triples, log_mode);
      del_count := del_count + length (triples);
    }
  if (isiri_id (graph_iri))
    graph_iri := id_to_iri (graph_iri);
  if (graph_iri is not null and __rdf_graph_is_in_enabled_repl (iri_to_id (graph_iri)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  if (compose_report)
    {
      if (del_count)
        return sprintf ('Delete from <%s>, %d (or less) triples -- done', graph_iri, del_count);
      else
        return sprintf ('Delete from <%s>, 0 triples -- nothing to do', graph_iri);
    }
  else
    return del_count;
}
;

create function DB.DBA.SPARQL_MODIFY_BY_DICT_CONTENTS (in graph_iri any, in del_triples_dict any, in ins_triples_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare del_count, ins_count integer;
  del_count := 0;
  ins_count := 0;
  if (__tag of vector = __tag (graph_iri))
    {
      del_count := graph_iri[1];
      ins_count := graph_iri[2];
      graph_iri := graph_iri[0]; -- the last op.
    }
  __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL MODIFY');
  if (del_triples_dict is not null)
    {
      del_count := del_count + dict_size (del_triples_dict);
      DB.DBA.SPARQL_DELETE_DICT_CONTENT (graph_iri, del_triples_dict, uid, log_mode);
    }
  if (ins_triples_dict is not null)
    {
      ins_count := ins_count + dict_size (ins_triples_dict);
      DB.DBA.SPARQL_INSERT_DICT_CONTENT (graph_iri, ins_triples_dict, uid, log_mode);
    }
  if (isiri_id (graph_iri))
    graph_iri := id_to_iri (graph_iri);
  if (graph_iri is not null and __rdf_graph_is_in_enabled_repl (iri_to_id (graph_iri)))
    repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
  if (compose_report)
    return sprintf ('Modify <%s>, delete %d (or less) and insert %d (or less) triples -- done', graph_iri, del_count, ins_count);
  else
    return del_count + ins_count;
}
;

-- /* delete quads */
create procedure DB.DBA.RDF_REPL_DEL (inout rquads any)
{
  declare rquads_ctr, rquads_count, opcode integer;
  declare g_iri, prev_g_iri varchar;
  declare g_iid varchar;
  declare ro_id_dict, app_env any;
  rquads_count := length (rquads);
  prev_g_iri := '';
  for (rquads_ctr := 0; rquads_ctr < rquads_count; rquads_ctr := rquads_ctr + 1)
    {
      -- dbg_obj_princ ('DB.DBA.RDF_REPL_DEL(), rquad ', rquads_ctr, ' / ', rquads_count, ': ', rquads[rquads_ctr]);
      g_iri := rquads[rquads_ctr][1];
      if (g_iri <> prev_g_iri)
        {
          g_iid := iri_to_id (g_iri);
          --DB.DBA.TTLP_EV_CL_GS_NEW_GRAPH (g_iri, g_iid, app_env);
          prev_g_iri := g_iri;
        }
      opcode := rquads[rquads_ctr][0];
      if (0 = opcode)
	{
          delete from DB.DBA.RDF_QUAD
	      where G = g_iid and S = iri_to_id_repl (rquads[rquads_ctr][2]) and P = iri_to_id_repl (rquads[rquads_ctr][3])
	      and O = DB.DBA.RDF_MAKE_OBJ_OF_SQLVAL (rquads[rquads_ctr][4]);
	  if (__rdf_graph_is_in_enabled_repl (g_iid))
	    __rdf_repl_quad (160 + opcode, g_iri, rquads[rquads_ctr][2], rquads[rquads_ctr][3], rquads[rquads_ctr][4]);
	}
      else if (1 = opcode)
	{
	  declare obj any;
	  if (isgeometry (rquads[rquads_ctr][4]))
	    {
	      obj := rdf_box (rquads[rquads_ctr][4], 256, 257, 0, 1);
	      rdf_geo_set_id (obj);
	    }
	  else
	    obj := DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (rquads[rquads_ctr][4], iri_to_id_repl (rquads[rquads_ctr][5]), null);
	  delete from DB.DBA.RDF_QUAD
	      where G = g_iid and S = iri_to_id_repl (rquads[rquads_ctr][2]) and P = iri_to_id_repl (rquads[rquads_ctr][3]) and O = obj;
	  if (__rdf_graph_is_in_enabled_repl (g_iid))
	    __rdf_repl_quad (160 + opcode, g_iri, rquads[rquads_ctr][2], rquads[rquads_ctr][3], rquads[rquads_ctr][4], rquads[rquads_ctr][5], null);
	}
      else if (2 = opcode)
	{
	  delete from DB.DBA.RDF_QUAD
	      where G = g_iid and S = iri_to_id_repl (rquads[rquads_ctr][2]) and P = iri_to_id_repl (rquads[rquads_ctr][3])
	      and O = DB.DBA.RDF_MAKE_OBJ_OF_TYPEDSQLVAL (rquads[rquads_ctr][4], null, rquads[rquads_ctr][5]);
	  if (__rdf_graph_is_in_enabled_repl (g_iid))
	    __rdf_repl_quad (160 + opcode, g_iri, rquads[rquads_ctr][2], rquads[rquads_ctr][3], rquads[rquads_ctr][4], null, rquads[rquads_ctr][5]);
	}
      else if (4 = opcode)
	{
	  delete from DB.DBA.RDF_QUAD
	      where G = g_iid and S = iri_to_id_repl (rquads[rquads_ctr][2]) and P = iri_to_id_repl (rquads[rquads_ctr][3])
	      and O = iri_to_id_repl (rquads[rquads_ctr][4]);
	  if (__rdf_graph_is_in_enabled_repl (g_iid))
	    __rdf_repl_quad (160 + opcode, g_iri, rquads[rquads_ctr][2], rquads[rquads_ctr][3], rquads[rquads_ctr][4]);
	}


    }
  app_env := vector (1, null);
  DB.DBA.TTLP_EV_COMMIT (g_iri, app_env);
  --if (1 <> sys_stat ('cl_run_local_only'))
  --  rdf_dpipe_flush_gs (app_env, 1);
  connection_set ('g_dict', null);
  commit work;
}
;

--#IF VER=5
--!AFTER
--#ENDIF
create function DB.DBA.SPARUL_CLEAR (in graph_iris any, in inside_sponge integer, in uid integer := 0, in log_mode integer := null, in compose_report integer := 0, in options any := null, in silent integer := 0) returns any
{
  declare g_iid IRI_ID;
  declare old_log_enable integer;
  declare txtreport varchar;
  txtreport := '';
  if (__tag of vector <> __tag (graph_iris))
    graph_iris := vector (graph_iris);
  foreach (any g_iri in graph_iris) do
    {
      if (isiri_id (g_iri))
        g_iri := id_to_iri (g_iri);
      g_iid := iri_to_id (g_iri);
      __rgs_assert_cbk (g_iri, uid, 2, 'SPARUL CLEAR GRAPH');
    }
  foreach (any g_iri in graph_iris) do
    {
      if (isiri_id (g_iri))
        g_iri := id_to_iri (g_iri);
      g_iid := iri_to_id (g_iri);
      old_log_enable := log_enable (log_mode, 1);
      if (__rdf_graph_is_in_enabled_repl (g_iid))
        {
	  declare lm int;
	  lm := log_enable (null);
          repl_text ('__rdf_repl', '__rdf_repl_flush_queue()');
          repl_text ('__rdf_repl', sprintf ('sparql define input:storage "" define sql:log-enable %d clear graph iri ( ?? )', lm), g_iri);
        }
      declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
      exec (sprintf ('
      delete from DB.DBA.RDF_QUAD
      where G = __i2id (''%S'') ', g_iri));
      delete from DB.DBA.RDF_QUAD table option (index RDF_QUAD_GS, index_only) where G = iri_to_id (g_iri, 0)  option (index_only, index RDF_QUAD_GS);
      delete from DB.DBA.RDF_OBJ_RO_FLAGS_WORDS where VT_WORD = rdf_graph_keyword (g_iid);
      if (not inside_sponge)
        {
          delete from DB.DBA.SYS_HTTP_SPONGE where HS_LOCAL_IRI = g_iri;
          delete from DB.DBA.SYS_HTTP_SPONGE where HS_LOCAL_IRI like concat ('destMD5=', md5 (g_iri), '&graphMD5=%');
        }
      if (compose_report)
        {
          if (txtreport <> '')
            txtreport := txtreport || '\n';
          txtreport := txtreport || sprintf ('Clear graph <%s> -- done', g_iri);
        }
    }
  /*091202 commit work; */
  log_enable (old_log_enable, 1);
  if (compose_report)
    return txtreport;
  return 1;
}
;

create function DB.DBA.SPARUL_LOAD (in graph_iri any, in resource varchar, in uid integer, in log_mode integer, in compose_report integer, in options any := null, in silent integer := 0) returns any
{
  declare old_log_enable integer;
  declare grab_params any;
  declare grabbed any;
  declare res integer;
  __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL LOAD');
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); if (silent) goto fail; resignal; };
  grabbed := dict_new();
  if (isiri_id (graph_iri))
    graph_iri := id_to_iri (graph_iri);
  grab_params := vector_concat (vector (
      'base_iri', resource,
      'get:destination', graph_iri,
      'get:soft', get_keyword ('get:soft', options, 'replacing'),
      'get:refresh', get_keyword ('get:refresh', options, -1),
      'get:error-recovery', get_keyword ('get:error-recovery', options, 'signal'),
      -- 'flags', flags,
      'get:strategy', get_keyword ('get:strategy', options, 'rdfa-only'),
      'get:private', get_keyword ('get:private', options, null),
      'grabbed', grabbed ),
    options );
  commit work;
  res := DB.DBA.RDF_GRAB_SINGLE (resource, grabbed, grab_params);
  commit work;
  log_enable (old_log_enable, 1);
  if (res)
    {
      if (compose_report)
        return sprintf ('Load <%s> into graph <%s> -- done', resource, graph_iri);
      else
        return 1;
    }
  else
    {
      if (compose_report)
        return sprintf ('Load <%s> into graph <%s> -- failed', resource, graph_iri);
      else
        return 0;
    }
fail:
  if (compose_report)
    return sprintf ('Load silent <%s> into graph <%s> -- failed: %s: %s', resource, graph_iri, __SQL_STATE, __SQL_MESSAGE);
  else
    return 0;
}
;

create function DB.DBA.SPARUL_LOAD_SERVICE_DATA (in service_iri any, in proxy_iri varchar, in uid integer, in log_mode integer, in compose_report integer, in options any := null, in silent integer := 0) returns any
{
  declare old_log_enable integer;
  declare mdta, rows any;
  declare stat, msg varchar;
  __rgs_assert_cbk (service_iri, uid, 2, 'SPARUL LOAD SERVICE DATA');
  -- dbg_obj_princ ('DB.DBA.SPARUL_LOAD_SERVICE_DATA (', service_iri, proxy_iri, uid, log_mode, compose_report, options, silent, ')');
  old_log_enable := log_enable (log_mode, 1);
  stat := '00000';
  exec ('DB.DBA.SPARQL_SD_PROBE (?, ?, 0, 0)', stat, msg, vector (service_iri, proxy_iri), 10000, mdta, rows);
  log_enable (old_log_enable, 1);
  if (stat <> '00000')
    {
      if (not silent) signal (stat, msg);
      if (compose_report)
        return sprintf ('Load service <%s> data failed: %s: %s', service_iri, stat, msg);
      else
        return 0;
    }
  if (compose_report)
    {
      if (length (rows))
        return sprintf ('Load service <%s> data -- done. %s', service_iri, rows[length(rows)-1][1]);
      else
        return sprintf ('Load service <%s> data -- nothing done', service_iri);
    }
  else
    return 1;
}
;

create function DB.DBA.SPARUL_CREATE (in graph_iri any, in silent1 integer, in uid integer, in log_mode integer, in compose_report integer, in options any := null, in silent integer := 0) returns any
{
  declare g_iid IRI_ID;
  declare old_log_enable integer;
  __rgs_assert_cbk (graph_iri, uid, 2, 'SPARUL CREATE GRAPH');
  g_iid := iri_to_id (graph_iri);
  if (__rdf_graph_is_in_enabled_repl (g_iid))
    repl_text ('__rdf_repl', 'sparql define input:storage "" create graph iri ( ?? )', graph_iri);
  if ((silent1 is not null) and silent1)
    silent := 1;
  if (exists (select top 1 1 from DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH where REC_GRAPH_IID = g_iid))
    {
      if (silent)
        {
          if (compose_report)
            return sprintf ('Create silent graph <%s> -- already exists', graph_iri);
          else
            return 0;
        }
      else
        signal ('22023', 'SPARUL_CREATE() failed: graph <' || graph_iri || '> has been explicitly created before');
    }
  if (silent)
    {
      old_log_enable := log_enable (log_mode, 1);
      declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
      insert soft DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH (REC_GRAPH_IID) values (iri_to_id (graph_iri));
      /*091202 commit work; */
      log_enable (old_log_enable, 1);
      if (compose_report)
        return sprintf ('Create silent graph <%s> -- done', graph_iri);
      else
        return 1;
    }
  if (exists (select top 1 1 from DB.DBA.RDF_QUAD where G = iri_to_id (graph_iri)))
    signal ('22023', 'SPARUL_CREATE() failed: graph <' || graph_iri || '> contains triples already');
  if (exists (sparql define input:storage ""
    ask from <http://www.openlinksw.com/schemas/virtrdf#>
    where { ?qmv virtrdf:qmGraphRange-rvrFixedValue `iri(?:graph_iri)` } ) )
    signal ('22023', 'SPARUL_CREATE() failed: graph <' || graph_iri || '> is used for mapping relational data to RDF');
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  insert soft DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH (REC_GRAPH_IID) values (iri_to_id (graph_iri));
  /*091202 commit work; */
  log_enable (old_log_enable, 1);
  if (compose_report)
    return sprintf ('Create graph <%s> -- done', graph_iri);
  else
    return 1;
}
;

create function DB.DBA.SPARUL_DROP (in graph_iris any, in silent1 integer, in uid integer, in log_mode integer, in compose_report integer, in options any := null, in silent integer := 0) returns any
{
  declare g_iid IRI_ID;
  declare old_log_enable integer;
  declare txtreport varchar;
  txtreport := '';
  if ((silent1 is not null) and silent1)
    silent := 1;
  if (__tag of vector <> __tag (graph_iris))
    graph_iris := vector (graph_iris);
  foreach (any g_iri in graph_iris) do
    {
      if (isiri_id (g_iri))
        g_iri := id_to_iri (g_iri);
      g_iid := iri_to_id (g_iri);
      __rgs_assert_cbk (g_iri, uid, 2, 'SPARUL DROP GRAPH');
    }
  foreach (any g_iri in graph_iris) do
    {
      if (isiri_id (g_iri))
        g_iri := id_to_iri (g_iri);
      g_iid := iri_to_id (g_iri);
      if (__rdf_graph_is_in_enabled_repl (g_iid))
        {
          repl_text ('__rdf_repl', '__rdf_repl_flush_queue()');
          repl_text ('__rdf_repl', 'sparql define input:storage "" drop graph iri ( ?? )', g_iri);
        }
      old_log_enable := log_enable (log_mode, 1);
      declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
      if (not exists (select top 1 1 from DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH where REC_GRAPH_IID = g_iid))
        {
          if (silent)
            {
              if (exists (select top 1 1 from DB.DBA.RDF_QUAD where G = g_iid))
                {
                  DB.DBA.SPARUL_CLEAR (g_iri, 0, uid);
                  log_enable (old_log_enable, 1);
                  if (compose_report)
                    return sprintf ('Drop silent graph <%s> -- graph has not been explicitly created before, triples were removed', g_iri);
                  else
                    return 2;
                }
              if (compose_report)
                return sprintf ('Drop silent graph <%s> -- nothing to do', g_iri);
              else
                return 0;
            }
          else
            signal ('22023', 'SPARUL_DROP() failed: graph <' || g_iri || '> has not been explicitly created before');
        }
      if (silent)
        {
          DB.DBA.SPARUL_CLEAR (g_iri, 0, uid);
          delete from DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH where REC_GRAPH_IID = g_iid;
          /*091202 commit work; */
          log_enable (old_log_enable, 1);
          if (compose_report)
            return sprintf ('Drop silent graph <%s> -- done', g_iri);
          else
            return 1;
        }
      if (exists (sparql define input:storage ""
        ask from <http://www.openlinksw.com/schemas/virtrdf#>
        where { ?qmv virtrdf:qmGraphRange-rvrFixedValue `iri(?:g_iri)` } ) )
        signal ('22023', 'SPARUL_DROP() failed: graph <' || g_iri || '> is used for mapping relational data to RDF');
      DB.DBA.SPARUL_CLEAR (g_iri, 0, uid);
      delete from DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH where REC_GRAPH_IID = g_iid;
      if (compose_report)
        {
          if (txtreport <> '')
            txtreport := txtreport || '\n';
          txtreport := txtreport || sprintf ('Drop graph <%s> -- done', g_iri);
        }
    }
  log_enable (old_log_enable, 1);
  /*091202 commit work; */
  if (compose_report)
    return txtreport;
  return 1;
}
;

create function DB.DBA.SPARUL_RUN (in results any, in compose_report integer := 0) returns any
{
  --commit work;
  if (compose_report)
    {
      declare ses any;
      ses := string_output ();
      foreach (varchar r in results) do
        {
          http (cast (r as varchar) || '\n', ses);
        }
      http ('Commit -- done\n', ses);
      return string_output_string (ses);
    }
  else
    {
      declare res integer;
      res := 0;
      foreach (integer c in results) do
        {
          res := res + c;
        }
      return res;
   }
}
;

-- SPARQL 1.1 BINDINGS

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_BINDINGS_VIEW_IMP (in dta any)
{
  declare rcount, rctr integer;
  declare BND any;
  result_names (BND);
  rcount := length (dta);
  for (rctr := 0; rctr < rcount; rctr := rctr+1)
    result (dta[rctr]);
}
;

create procedure view DB.DBA.SPARQL_BINDINGS_VIEW as DB.DBA.SPARQL_BINDINGS_VIEW_IMP (dta) (BND any)
;

grant select on DB.DBA.SPARQL_BINDINGS_VIEW to public
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_BINDINGS_VIEW_C_1_IMP (in dta any)
{
  declare rcount, rctr integer;
  declare BND0 any;
  result_names (BND0);
  rcount := length (dta);
  for (rctr := 0; rctr < rcount; rctr := rctr+1)
    result (dta[rctr][0]);
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_BINDINGS_VIEW_C_2_IMP (in dta any)
{
  declare rcount, rctr integer;
  declare BND0, BND1 any;
  result_names (BND0, BND1);
  rcount := length (dta);
  for (rctr := 0; rctr < rcount; rctr := rctr+1)
    result (dta[rctr][0], dta[rctr][1]);
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_BINDINGS_VIEW_C_3_IMP (in dta any)
{
  declare rcount, rctr integer;
  declare BND0, BND1, BND2 any;
  result_names (BND0, BND1, BND2);
  rcount := length (dta);
  for (rctr := 0; rctr < rcount; rctr := rctr+1)
    result (dta[rctr][0], dta[rctr][1], dta[rctr][2]);
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_BINDINGS_VIEW_C_4_IMP (in dta any)
{
  declare rcount, rctr integer;
  declare BND0, BND1, BND2, BND3 any;
  result_names (BND0, BND1, BND2, BND3);
  rcount := length (dta);
  for (rctr := 0; rctr < rcount; rctr := rctr+1)
    result (dta[rctr][0], dta[rctr][1], dta[rctr][2], dta[rctr][3]);
}
;

create procedure view DB.DBA.SPARQL_BINDINGS_VIEW_C_1 as DB.DBA.SPARQL_BINDINGS_VIEW_C_1_IMP (dta) (BND0 any)
;

create procedure view DB.DBA.SPARQL_BINDINGS_VIEW_C_2 as DB.DBA.SPARQL_BINDINGS_VIEW_C_2_IMP (dta) (BND0 any, BND1 any)
;

create procedure view DB.DBA.SPARQL_BINDINGS_VIEW_C_3 as DB.DBA.SPARQL_BINDINGS_VIEW_C_3_IMP (dta) (BND0 any, BND1 any, BND2 any)
;

create procedure view DB.DBA.SPARQL_BINDINGS_VIEW_C_4 as DB.DBA.SPARQL_BINDINGS_VIEW_C_4_IMP (dta) (BND0 any, BND1 any, BND2 any, BND3 any)
;

grant select on DB.DBA.SPARQL_BINDINGS_VIEW_C_1 to public
;

grant select on DB.DBA.SPARQL_BINDINGS_VIEW_C_2 to public
;

grant select on DB.DBA.SPARQL_BINDINGS_VIEW_C_3 to public
;

grant select on DB.DBA.SPARQL_BINDINGS_VIEW_C_4 to public
;


-- SPARQL 1.1 UPDATE functions
create procedure DB.DBA.RDF_INSERT_QUADS (in dflt_graph_iri any, inout quads any, in uid integer, in log_mode integer := null) returns any
{
  declare groups any;
  declare group_ctr, group_count integer;
  declare qtst, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv any;
  qtst := quads;
  __rgs_prepare_del_or_ins (qtst, uid, dflt_graph_iri, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv);
  rowvector_graph_sort (quads, 3, 1);
  groups := rowvector_graph_partition (quads, 3);
  group_count := length (groups);
  for (group_ctr := 0; group_ctr < group_count; group_ctr := group_ctr+1)
    {
      declare g_group, g any;
      g_group := aref_set_0 (groups, group_ctr);
      g := aref_or_default (g_group, 0, 3, dflt_graph_iri);
      __rgs_assert_cbk (g, uid, 2, 'SPARQL 1.1 INSERT');
      DB.DBA.RDF_INSERT_TRIPLES (g, g_group, log_mode);
      if (isiri_id (g))
        g := id_to_iri (g);
      if (g is not null and __rdf_graph_is_in_enabled_repl (iri_to_id (g)))
        repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
    }
}
;

create function DB.DBA.RDF_DELETE_QUADS (in dflt_graph_iri any, inout quads any, in uid integer, in log_mode integer := null) returns any
{
  declare groups any;
  declare group_ctr, group_count integer;
  declare old_log_enable integer;
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  declare repl_quads any array;
  declare all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv any;
  -- dbg_obj_princ ('__rgs_prepare_del_or_ins (', quads, uid, dflt_graph_iri, ') formed the following:');
  __rgs_prepare_del_or_ins (quads, uid, dflt_graph_iri, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv);
  for vectored (in a_s any array := all_sv, in a_p any array := all_pv, in a_o any array := all_ov, in a_g any array := all_gv)
    {
      declare o_val any array;
      declare o_dt_and_lang_twobyte integer;
      if (not isinteger (a_g))
        {
          if (not isiri_id (a_s))
            a_s := __i2idn (a_s);
          if (not isiri_id (a_p))
            a_p := __i2idn (a_p);
          if (isiri_id (a_s) and isiri_id (a_p))
            {
              if (isiri_id (a_o))
                delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
              else
                {
                  if (__tag of rdf_box = __tag (a_o) and rdf_box_ro_id (a_o)) -- was if (__tag of rdf_box = __tag (a_o) and rdf_box_is_complete (a_o))
                    {
                      -- dbg_obj_princ ('delete by O=a_o because the box has ro_id');
                      delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                    }
                  else
                    {
                      declare o_val any array;
                      declare o_dt_and_lang_twobyte integer;
                      declare search_fields_are_ok integer;
                      search_fields_are_ok := __rdf_box_to_ro_id_search_fields (a_o, o_val, o_dt_and_lang_twobyte);
                      -- dbg_obj_princ ('__rdf_box_to_ro_id_search_fields (', a_o, ') returned ', search_fields_are_ok, o_val, o_dt_and_lang_twobyte);
                      if (search_fields_are_ok)
                        {
                          declare rb_of_ro_id any;
                          rb_of_ro_id := (select rdf_box_from_ro_id(RO_ID) from DB.DBA.RDF_OBJ where RO_VAL = o_val and RO_DT_AND_LANG = o_dt_and_lang_twobyte);
                          if (rb_of_ro_id is not null)
                            {
                              -- dbg_obj_princ ('delete by search fields, ro_id will be ', rb_of_ro_id);
                              delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = rb_of_ro_id and rdf_box_dt_and_lang(O) = o_dt_and_lang_twobyte;
                            }
                          else
                            {
                              -- dbg_obj_princ ('delete by O=a_o as a fallback for missing search fields');
                              delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                            }
                        }
                      else if (isstring (a_o)) /* it should be string IRI otherwise it's in RDF_OBJ */
                        {
                          -- dbg_obj_princ ('delete of string iri, iri_id will be ', iri_to_id (a_o));
                          delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = iri_to_id (a_o);
                        }
                      else
                        {
                          -- dbg_obj_princ ('delete by O=a_o as a fallback');
                          delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                        }
                    }
                }
            }
        }
    }
  if (0 < length (repl_sv))
    {
      for vectored (in r_s any array := repl_sv, in r_p any array := repl_pv, in r_o any array := repl_ov, in r_g any array := repl_gv, out repl_quads := r_q)
        {
	  declare r_q any array;
          declare r_g_iri, r_s_iri, r_p_iri varchar;
          r_g_iri := iri_canonicalize (__id2in (r_g));
          r_s_iri := iri_canonicalize (__id2in (r_s));
          r_p_iri := iri_canonicalize (__id2in (r_p));
          if (isiri_id (r_o) or (__tag (r_o) = __tag of UNAME) or ((__tag (r_o) = __tag of varchar) and bit_and (1, __box_flags (r_o))))
            r_q := vector (r_g_iri, r_s_iri, r_p_iri, iri_canonicalize (__id2in (r_o)));
          else
            r_q := vector (r_g_iri, r_s_iri, r_p_iri, __ro2sq (r_o));
        }
      repl_text ('__rdf_repl', 'DB.DBA.RDF_REPL_DELETE_QUADS (?)', repl_quads);
    }
  log_enable (old_log_enable, 1);
}
;


create function DB.DBA.SPARQL_INSERT_QUAD_DICT_CONTENT (in dflt_graph_iri any, in quads_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare ins_count, ins_grp_count integer;
  declare res_ses any;
  ins_count := 0;
  ins_grp_count := 0;
  if (__tag of vector = __tag (dflt_graph_iri))
    {
      ins_count := dflt_graph_iri[2]; -- 2, not 1
      dflt_graph_iri := dflt_graph_iri[0]; -- the last op.
    }
  while (dict_size (quads_dict) > 0)
    {
      declare quads, groups any;
      declare group_ctr, group_count, g_ins_count integer;
      quads := dict_destructive_list_rnd_keys (quads_dict, 80000);

      declare qtst, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv any;
      qtst := quads;
      -- dbg_obj_princ ('__rgs_prepare_del_or_ins (', qtst, uid, dflt_graph_iri, ') formed the following:');
      __rgs_prepare_del_or_ins (qtst, uid, dflt_graph_iri, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv);
      -- dbg_obj_princ ('All items:');
      --for vectored (in a_s any array := all_sv, in a_p any array := all_pv, in a_o any array := all_ov, in a_g any array := all_gv) {
        -- dbg_obj_princ (a_s, a_p, a_o, a_g);
        --}
      -- dbg_obj_princ ('Replication items:');
      --for vectored (in r_s any array := repl_sv, in r_p any array := repl_pv, in r_o any array := repl_ov, in r_g any array := repl_gv) {
        -- dbg_obj_princ (r_s, r_p, r_o, r_g);
      --}

      rowvector_graph_sort (quads, 3, 1);
      groups := rowvector_graph_partition (quads, 3);
      group_count := length (groups);
      for (group_ctr := 0; group_ctr < group_count; group_ctr := group_ctr+1)
        {
          declare g_group, g any;
          g_group := aref_set_0 (groups, group_ctr);
          g := aref_or_default (g_group, 0, 3, dflt_graph_iri);
          __rgs_assert_cbk (g, uid, 2, 'SPARQL 1.1 INSERT');
          DB.DBA.RDF_INSERT_TRIPLES (g, g_group, log_mode);
          g_ins_count := length (g_group);
          ins_count := ins_count + g_ins_count;
          ins_grp_count := ins_grp_count + 1;
          if (isiri_id (g))
            g := id_to_iri (g);
          if (g is not null and __rdf_graph_is_in_enabled_repl (iri_to_id (g)))
            repl_text ('__rdf_repl', '__rdf_repl_flush_queue ()');
          if (compose_report and ins_grp_count < 1000)
            {
              if (group_ctr)
                http ('\n', res_ses);
              else
                res_ses := string_output();
              http (sprintf ('Insert into <%s>, %d (or less) quads -- done', g, g_ins_count), res_ses);
            }
        }
    }
  if (compose_report)
    {
      if (ins_grp_count >= 1000)
        return sprintf ('Insert into %d (or more) graphs, total %d (or less) quads -- done', ins_grp_count, ins_count);
      if (ins_count)
        return string_output_string (res_ses);
      else if (dflt_graph_iri is null)
        return sprintf ('Insert of 0 quads -- nothing to do');
      else
        return sprintf ('Insert into <%s>, 0 quads -- nothing to do', dflt_graph_iri);
    }
  else
    return ins_count;
}
;

create function DB.DBA.SPARQL_DELETE_QUAD_DICT_CONTENT (in dflt_graph_iri any, in quads_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare del_count, del_grp_count integer;
  declare res_ses any;
  del_count := 0;
  declare old_log_enable integer;
  old_log_enable := log_enable (log_mode, 1);
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  if (__tag of vector = __tag (dflt_graph_iri))
    {
      del_count := dflt_graph_iri[1]; -- 1 for del count
      dflt_graph_iri := dflt_graph_iri[0]; -- the last op.
    }
  while (dict_size (quads_dict) > 0)
    {
      declare quads, groups any;
      declare group_ctr, group_count, g_del_count integer;
      declare repl_quads any array;
      quads := dict_destructive_list_rnd_keys (quads_dict, 80000);
      declare all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv any;
      -- dbg_obj_princ ('__rgs_prepare_del_or_ins (', quads, uid, dflt_graph_iri, ') formed the following:');
      __rgs_prepare_del_or_ins (quads, uid, dflt_graph_iri, all_sv, all_pv, all_ov, all_gv, repl_sv, repl_pv, repl_ov, repl_gv);
      for vectored (in a_s any array := all_sv, in a_p any array := all_pv, in a_o any array := all_ov, in a_g any array := all_gv)
        {
          if (not isinteger (a_g))
            {
              if (not isiri_id (a_s))
                a_s := __i2idn (a_s);
              if (not isiri_id (a_p))
                a_p := __i2idn (a_p);
              if (isiri_id (a_s) and isiri_id (a_p))
                {
                  if (isiri_id (a_o))
                    {
                      -- dbg_obj_princ ('delete of plain iri_id ', a_o);
                      delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                    }
                  else if (__tag of rdf_box = __tag (a_o) and rdf_box_ro_id (a_o))
                    {
                      -- dbg_obj_princ ('delete by O=a_o because the box has ro_id');
                      delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                    }
              else
                    {
                      declare o_val any array;
                      declare o_dt_and_lang_twobyte integer;
                      declare search_fields_are_ok integer;
                      search_fields_are_ok := __rdf_box_to_ro_id_search_fields (a_o, o_val, o_dt_and_lang_twobyte);
                      -- dbg_obj_princ ('__rdf_box_to_ro_id_search_fields (', a_o, ') returned ', search_fields_are_ok, o_val, o_dt_and_lang_twobyte);
                      if (search_fields_are_ok)
                        {
                          declare rb_of_ro_id any;
                          rb_of_ro_id := (select rdf_box_from_ro_id(RO_ID) from DB.DBA.RDF_OBJ where RO_VAL = o_val and RO_DT_AND_LANG = o_dt_and_lang_twobyte);
                          if (rb_of_ro_id is not null)
                            {
                              -- dbg_obj_princ ('delete by search fields, ro_id will be ', rb_of_ro_id);
                              delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = rb_of_ro_id and rdf_box_dt_and_lang(O) = o_dt_and_lang_twobyte;
                            }
                          else
                            {
                              -- dbg_obj_princ ('delete by O=a_o as a fallback for missing search fields');
                              delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                            }
                        }
                      else if (isstring (a_o)) /* it should be string IRI otherwise it's in RDF_OBJ */
                        {
                          -- dbg_obj_princ ('delete of string iri, iri_id will be ', iri_to_id (a_o));
                          delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = iri_to_id (a_o);
                        }
                      else
                        {
                          -- dbg_obj_princ ('delete by O=a_o as a fallback');
                          delete from DB.DBA.RDF_QUAD where G = a_g and S = a_s and P = a_p and O = a_o;
                        }
            }
        }
    }
        }
      if (0 < length (repl_sv))
        {
          for vectored (in r_s any array := repl_sv, in r_p any array := repl_pv, in r_o any array := repl_ov, in r_g any array := repl_gv, out repl_quads := r_q)
            {
	      declare r_q any array;
              declare r_g_iri, r_s_iri, r_p_iri varchar;
              r_g_iri := iri_canonicalize (__id2in (r_g));
              r_s_iri := iri_canonicalize (__id2in (r_s));
              r_p_iri := iri_canonicalize (__id2in (r_p));
              if (isiri_id (r_o) or (__tag (r_o) = __tag of UNAME) or ((__tag (r_o) = __tag of varchar) and bit_and (1, __box_flags (r_o))))
                r_q := vector (r_g_iri, r_s_iri, r_p_iri, iri_canonicalize (__id2in (r_o)));
              else
                r_q := vector (r_g_iri, r_s_iri, r_p_iri, __ro2sq (r_o));
            }
          repl_text ('__rdf_repl', 'DB.DBA.RDF_REPL_DELETE_QUADS (?)', repl_quads);
        }
      del_count := del_count + length (quads);
    }
  log_enable (old_log_enable, 1);
  if (compose_report)
    {
      if (del_count)
        return sprintf ('Delete %d (or less) quads -- done', del_count);
      else if (dflt_graph_iri is null)
        return sprintf ('Delete 0 quads -- nothing to do');
      else
        return sprintf ('Delete from <%s>, 0 quads -- nothing to do', dflt_graph_iri);
    }
  else
    return del_count;
}
;


create function DB.DBA.SPARQL_MODIFY_BY_QUAD_DICT_CONTENTS (in dflt_graph_iri any, in del_quads_dict any, in ins_quads_dict any, in uid integer, in log_mode integer := null, in compose_report integer := 0) returns any
{
  declare del_count, ins_count integer;
  declare del_rep, ins_rep any;
  del_count := 0;
  ins_count := 0;
  if (__tag of vector = __tag (dflt_graph_iri))
    {
      del_count := dflt_graph_iri[1];
      ins_count := dflt_graph_iri[2];
      dflt_graph_iri := dflt_graph_iri[0]; -- the last op.
    }
  if (del_quads_dict is not null)
    {
      del_count := del_count + dict_size (del_quads_dict);
      del_rep := DB.DBA.SPARQL_DELETE_QUAD_DICT_CONTENT (dflt_graph_iri, del_quads_dict, uid, log_mode, compose_report);
    }
  else if (compose_report)
    del_rep := '';
  else
    del_rep := 0;
  if (ins_quads_dict is not null)
    {
      ins_count := ins_count + dict_size (ins_quads_dict);
      ins_rep := DB.DBA.SPARQL_INSERT_QUAD_DICT_CONTENT (dflt_graph_iri, ins_quads_dict, uid, log_mode, compose_report);
    }
  else if (compose_report)
    ins_rep := '';
  else
    ins_rep := 0;
  if (compose_report)
    return concat (del_rep, case when ins_rep <> '' and del_rep <> '' then '\n' else '' end, ins_rep);
  else
    return del_count + ins_count;
}
;

create function DB.DBA.SPARUL_COPYMOVEADD_IMPL (in opname varchar, in src_g_iri any, in tgt_g_iri any, in uid integer := 0, in log_mode integer := null, in compose_report integer := 0, in options any := null, in silent integer := 0) returns any
{
  declare src_g_iid IRI_ID;
  declare tgt_g_iid IRI_ID;
  declare old_log_enable, src_repl, tgt_repl integer;
  declare qry, stat, msg varchar;
  if (isiri_id (src_g_iri))
    src_g_iri := id_to_iri (src_g_iri);
  src_g_iid := iri_to_id (src_g_iri);
  if (isiri_id (tgt_g_iri))
    tgt_g_iri := id_to_iri (tgt_g_iri);
  tgt_g_iid := iri_to_id (tgt_g_iri);
  __rgs_assert_cbk (tgt_g_iri, uid, 2, 'SPARQL 1.1 ' || opname);
  __rgs_assert_cbk (src_g_iri, uid, case (opname) when 'MOVE' then 2 else 1 end, 'SPARQL 1.1 ' || opname);
  if (src_g_iid = tgt_g_iid)
    {
      if (compose_report)
        return sprintf ('%s <%s> to itself -- nothing to do', opname, src_g_iri);
      return 1;
    }
  src_repl := __rdf_graph_is_in_enabled_repl (src_g_iid);
  tgt_repl := __rdf_graph_is_in_enabled_repl (tgt_g_iid);
  if (src_repl and not tgt_repl)
    signal ('22023', sprintf ('SPARQL 1.1 can not %s replicated graph <%s> to non-replicated graph <%s>, both should be in same replication status', src_g_iri, tgt_g_iri));
  if (tgt_repl and not src_repl)
    signal ('22023', sprintf ('SPARQL 1.1 can not %s non-replicated graph <%s> to replicated graph <%s>, both should be in same replication status', src_g_iri, tgt_g_iri));
  if ('ADD' <> opname)
    DB.DBA.SPARUL_CLEAR (tgt_g_iri, 0, uid, log_mode, 0, options, silent);
  old_log_enable := log_enable (log_mode, 1);
  if (src_repl and tgt_repl)
    {
      declare lm int;
      lm := log_enable (null);
      repl_text ('__rdf_repl', '__rdf_repl_flush_queue()');
      repl_text ('__rdf_repl', sprintf ('sparql define input:storage "" define sql:log-enable %d add iri( ?? ) to iri( ?? )', lm), src_g_iri, tgt_g_iri);
    }
  declare exit handler for sqlstate '*' { log_enable (old_log_enable, 1); resignal; };
  stat := '00000';
  qry := sprintf ('insert soft DB.DBA.RDF_QUAD (G,S,P,O) select __i2id (''%S''), t.S, t.P, t.O from DB.DBA.RDF_QUAD t where t.G = __i2id (''%S'') ',
     tgt_g_iri, src_g_iri );
  exec (qry, stat, msg);
  if (stat <> '00000')
    signal (stat, msg);
  if ('MOVE' = opname)
    DB.DBA.SPARUL_CLEAR (src_g_iri, 0, uid, log_mode, 0, options, silent);
  /*091202 commit work; */
  log_enable (old_log_enable, 1);
  if (compose_report)
    return sprintf ('%s <%s> to <%s> -- done', opname, src_g_iri, tgt_g_iri);
  return 1;
}
;

create function DB.DBA.SPARUL_COPY (in src_g_iri any, in tgt_g_iri any, in uid integer := 0, in log_mode integer := null, in compose_report integer := 0, in options any := null, in silent integer := 0) returns any
{
  return DB.DBA.SPARUL_COPYMOVEADD_IMPL ('COPY', src_g_iri, tgt_g_iri, uid, log_mode, compose_report, options, silent);
}
;

create function DB.DBA.SPARUL_MOVE (in src_g_iri any, in tgt_g_iri any, in uid integer := 0, in log_mode integer := null, in compose_report integer := 0, in options any := null, in silent integer := 0) returns any
{
  return DB.DBA.SPARUL_COPYMOVEADD_IMPL ('MOVE', src_g_iri, tgt_g_iri, uid, log_mode, compose_report, options, silent);
}
;

create function DB.DBA.SPARUL_ADD (in src_g_iri any, in tgt_g_iri any, in uid integer := 0, in log_mode integer := null, in compose_report integer := 0, in options any := null, in silent integer := 0) returns any
{
  return DB.DBA.SPARUL_COPYMOVEADD_IMPL ('ADD', src_g_iri, tgt_g_iri, uid, log_mode, compose_report, options, silent);
}
;

create procedure DB.DBA.SPARQL_SELECT_KNOWN_GRAPHS (in return_iris integer := 1, in lim integer := 2000000000)
{
  declare specials, specials_vec any;
  declare last_iri_id, cur_iri_id IRI_ID;
  declare cr cursor for select G from DB.DBA.RDF_QUAD table option (index G, index order) where G > last_iri_id and not (dict_get (specials, G, 0));
  declare cr_cl cursor for select G from DB.DBA.RDF_QUAD table option (index G, index order)  where G > last_iri_id and 0 >= position (G, specials_vec);
  declare GRAPH_IRI varchar;
  declare GRAPH_IID IRI_ID;
  declare ctr, len integer;
  if (lim is null)
    lim := 2000000000;
  if (return_iris)
    result_names (GRAPH_IRI);
  else
    result_names (GRAPH_IID);
  specials := dict_new (50);
  set isolation = 'repeatable';
  for (sparql define input:storage ""
    select distinct ?graph_rvr_fixed
    from <http://www.openlinksw.com/schemas/virtrdf#>
    where { ?qmv virtrdf:qmGraphRange-rvrFixedValue ?graph_rvr_fixed } ) do
    {
      dict_put (specials, iri_to_id ("graph_rvr_fixed"), 1);
    }
  if (dict_size (specials) >= lim)
    goto done_all;
  for (select REC_GRAPH_IID from DB.DBA.RDF_EXPLICITLY_CREATED_GRAPH) do
    {
      dict_put (specials, REC_GRAPH_IID, 2);
    }
  len := dict_size (specials);
  if (len >= lim)
    goto done_all;
  last_iri_id := #i0;

--  if (1 <> sys_stat ('cl_run_local_only'))
--    {
      specials_vec := dict_list_keys (specials, 0);
      whenever not found goto done_rdf_quad_cl;
      open cr_cl (prefetch 1);

next_fetch_cr_cl:
      fetch cr_cl into cur_iri_id;
      if (return_iris)
        result (id_to_iri (cur_iri_id));
      else
        result (cur_iri_id);
      lim := lim - 1;
      if (len >= lim)
        goto done_rdf_quad_cl;
      last_iri_id := cur_iri_id;
      close cr_cl;
      open cr_cl (prefetch 1);
      goto next_fetch_cr_cl;

done_rdf_quad_cl:
      close cr_cl;
--    }
--  else
--    {
--      whenever not found goto done_rdf_quad;
--      open cr (prefetch 1);

--next_fetch_cr:
--      fetch cr into cur_iri_id;
--      if (return_iris)
--        result (id_to_iri (cur_iri_id));
--      else
--        result (cur_iri_id);
--      lim := lim - 1;
--      if (len >= lim)
--        goto done_rdf_quad;
--      last_iri_id := cur_iri_id;
--      goto next_fetch_cr;

--done_rdf_quad:
--      close cr;
--    }

done_all:
  specials := dict_list_keys (specials, 1);
  len := length (specials);
  for (ctr := 0; ctr < len; ctr := ctr + 1)
    if (return_iris)
      result (id_to_iri (specials[ctr]));
    else
      result (specials[ctr]);
}
;

-----
-- Built-in operations of SPARQL as SQL functions

--!AWK PUBLIC
create function DB.DBA.RDF_REGEX (in s varchar, in p varchar, in coll varchar := null)
{
  if (not iswidestring (s) and not isstring (s))
    return 0;
  if (regexp_match (p, s, 0, coalesce (coll, ''), 1) is not null)
    return 1;
  return 0;
}
;

--!AWK PUBLIC
create function DB.DBA.RDF_LANGMATCHES (in r varchar, in t varchar)
{
  if ((t is null) or (r is null))
    return null;
  if ('*' = t)
    {
      if (r <> '')
        return 1;
      return 0;
    }
  t := upper (t);
  r := upper (r);
  if (r = t)
    return 1;
  if (r like t || '-%')
    return 1;
  return 0;
}
;

--!AWK PUBLIC
create procedure DB.DBA.BEST_LANGMATCH_INIT (inout env any)
{
  env := vector (0, -2);
}
;

--!AWK PUBLIC
create procedure DB.DBA.BEST_LANGMATCH_ACC (inout env any, in obj any array, in range varchar, in dflt_lang varchar)
{
  declare lang varchar;
  declare pct integer;
  if (obj is null)
    return;
  if (__tag (env) <> __tag of vector)
    env := vector (0, -2);
  if (__tag of rdf_box = __tag (obj))
    {
      declare twobyte integer;
      twobyte := rdf_box_lang (obj);
      if (257 = twobyte)
        lang := dflt_lang;
      else
        {
          whenever not found goto badlang;
          select RL_ID into lang from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = twobyte;
          goto lang_ready;
badlang:
          signal ('RDFXX', sprintf ('Unknown language in DB.DBA.BEST_LANGMATCH_ACC, bad lang id %d', twobyte));
        }
    }
  else if (__tag of varchar = __tag (obj))
      lang := dflt_lang;
  else
    {
      if (env[1] = -2)
        env := vector (obj, -1);
      return;
    }
lang_ready:
  pct := langmatches_pct_http (lang, range);
  if (env[1] < pct)
    env := vector (obj, pct);
}
;

--!AWK PUBLIC
create function DB.DBA.BEST_LANGMATCH_FINAL (inout env any) returns any
{
  if (__tag (env) <> __tag of vector)
    return null;
  return env[0];
}
;

--!AWK PUBLIC
create aggregate DB.DBA.BEST_LANGMATCH (inout obj any, in range varchar, in dflt_lang varchar) from
  DB.DBA.BEST_LANGMATCH_INIT,
  DB.DBA.BEST_LANGMATCH_ACC,
  DB.DBA.BEST_LANGMATCH_FINAL
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_CONSTRUCT_INIT (inout _env any)
{
  _env := 0; -- No actual initialization
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_CONSTRUCT_ACC (inout _env any, in opcodes any, in vars any, in stats any, in use_dict_limit integer)
{
  declare triple_ctr integer;
  declare blank_ids any;
  if (214 <> __tag(_env))
    {
      if (use_dict_limit)
        _env := dict_new (31, sys_stat ('sparql_result_set_max_rows'), sys_stat ('sparql_max_mem_in_use'));
      else
        _env := dict_new (31);
      if (0 < length (stats))
        DB.DBA.SPARQL_CONSTRUCT_ACC (_env, stats, vars, vector(), use_dict_limit);
    }
  blank_ids := 0;
  for (triple_ctr := length (opcodes) - 1; triple_ctr >= 0; triple_ctr := triple_ctr-1)
    {
      declare fld_ctr, fld_count integer;
      declare triple_vec any;
      declare g_opcode integer;
      g_opcode := aref_or_default (opcodes, triple_ctr, 6, null);
      if (g_opcode is null)
        {
          fld_count := 3;
          triple_vec := vector (0,0,0);
        }
      else
        {
          fld_count := 4;
          triple_vec := vector (0,0,0,0);
        }
      -- dbg_obj_princ ('opcodes[triple_ctr]=', opcodes[triple_ctr]);
      for (fld_ctr := fld_count - 1; fld_ctr >= 0; fld_ctr := fld_ctr - 1)
        {
          declare op integer;
          declare arg any;
          op := opcodes[triple_ctr][fld_ctr * 2];
          arg := opcodes[triple_ctr][fld_ctr * 2 + 1];
          if (1 = op)
            {
              declare i any;
              i := vars[arg];
              if (i is null)
                goto end_of_adding_triple;
              if (isiri_id (i))
                {
                  if (fld_ctr in (1,3) and is_bnode_iri_id (i))
                    signal ('RDF01', 'Bad variable value in CONSTRUCT: blank node can not be used as predicate or graph');
                }
              else if ((isstring (i) and (1 = __box_flags (i))) or (__tag of UNAME = __tag(i)))
                {
                  if (fld_ctr in (1,3) and (i like 'bnode://%'))
                    signal ('RDF01', 'Bad variable value in CONSTRUCT: blank node can not be used as predicate or graph');
                  i := iri_to_id (i);
                }
              else if (2 <> fld_ctr)
                signal ('RDF01',
                  sprintf ('Bad variable value in CONSTRUCT: "%.100s" (tag %d box flags %d) is not a valid %s, only object of a triple can be a literal',
                    __rdf_strsqlval (i), __tag (i), __box_flags (i),
                    case (fld_ctr) when 1 then 'predicate' else 'subject' end ) );
              triple_vec[fld_ctr] := i;
            }
          else if (2 = op)
            {
              if (isinteger (blank_ids))
                blank_ids := vector (iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK')));
              while (arg >= length (blank_ids))
                blank_ids := vector_concat (blank_ids, vector (iri_id_from_num (sequence_next ('RDF_URL_IID_BLANK'))));
              if (fld_ctr in (1,3))
                signal ('RDF01', 'Bad triple for CONSTRUCT: blank node can not be used as predicate or graph');
              triple_vec[fld_ctr] := blank_ids[arg];
            }
          else if (3 = op)
            {
              if (arg is null)
                goto end_of_adding_triple;
              if (isiri_id (arg))
                {
                  if (fld_ctr in (1,3) and is_bnode_iri_id (arg))
                    signal ('RDF01', 'Bad const value in CONSTRUCT: blank node can not be used as predicate or graph');
                }
              else if ((isstring (arg) and (1 = __box_flags (arg))) or (__tag of UNAME = __tag(arg)))
                {
                  if (fld_ctr in (1,3) and (arg like 'bnode://%'))
                    signal ('RDF01', 'Bad const value in CONSTRUCT: blank node can not be used as predicate or graph');
                  arg := iri_to_id (arg);
                }
              else if (2 <> fld_ctr)
                signal ('RDF01',
                  sprintf ('Bad const value in CONSTRUCT: "%.100s" (tag %d box flags %d) is not a valid %s, only object of a triple can be a literal',
                    __rdf_strsqlval (arg), __tag (arg), __box_flags (arg),
                    case (fld_ctr) when 1 then 'predicate' else 'subject' end ) );
              else if (__tag of vector = __tag (arg))
                arg := DB.DBA.RDF_MAKE_LONG_OF_TYPEDSQLVAL_STRINGS (arg[0], arg[1], arg[2]);
              triple_vec[fld_ctr] := arg;
            }
          else signal ('RDFXX', 'Bad opcode in DB.DBA.SPARQL_CONSTRUCT()');
        }
      -- dbg_obj_princ ('generated triple:', triple_vec);
      dict_put (_env, triple_vec, 0);
end_of_adding_triple: ;
    }
}
;

--!AWK PUBLIC
create procedure DB.DBA.SPARQL_CONSTRUCT_FIN (inout _env any)
{
  if (214 <> __tag(_env))
    _env := dict_new ();
  return _env;
}
;

--!AWK PUBLIC
create aggregate DB.DBA.SPARQL_CONSTRUCT (in opcodes any, in vars any, in stats any, in use_dict_limit integer) returns any
from DB.DBA.SPARQL_CONSTRUCT_INIT, DB.DBA.SPARQL_CONSTRUCT_ACC, DB.DBA.SPARQL_CONSTRUCT_FIN
;

create procedure DB.DBA.SPARQL_DESC_AGG_INIT (inout _env any)
{
  _env := 0; -- No actual initialization
}
;

-- create procedure DB.DBA.SPARQL_INSERT_DATA (in graph_iri any, in triple_ops any)
-- is no longer available. Use DB.DBA.RDF_INSERT_TRIPLES (graph_iri, triples, log_mode) instead.

create procedure DB.DBA.SPARQL_DESC_AGG_ACC (inout _env any, in vars any)
{
  declare var_ctr integer;
  declare blank_ids any;
  if (214 <> __tag(_env))
    {
      _env := dict_new (31, sys_stat ('sparql_result_set_max_rows'), sys_stat ('sparql_max_mem_in_use'));
    }
  for (var_ctr := length (vars) - 1; var_ctr >= 0; var_ctr := var_ctr - 1)
    {
      declare i any;
      i := vars[var_ctr];
      if (isiri_id (i))
        dict_put (_env, i, 0);
    }
}
;

create procedure DB.DBA.SPARQL_DESC_AGG_FIN (inout _env any)
{
  declare subjects, options, res any;
  declare subj_ctr integer;
  if (214 <> __tag(_env))
    return dict_new ();
  return _env;
}
;

create aggregate DB.DBA.SPARQL_DESC_AGG (in vars any) returns any
from DB.DBA.SPARQL_DESC_AGG_INIT, DB.DBA.SPARQL_DESC_AGG_ACC, DB.DBA.SPARQL_DESC_AGG_FIN
;

create procedure DB.DBA.SPARQL_DESC_DICT (in subj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_subj_descs, phys_subjects, sorted_good_graphs, sorted_bad_graphs, g_dict, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, s_ctr, all_s_count, phys_s_count integer;
  declare gs_app_callback, gs_app_uid, inf_ruleset, sameas varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  inf_ruleset := get_keyword ('inference', options);
  sameas := get_keyword ('same-as', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (isiri_id (c))
        dict_put (subj_dict, c, 0);
    }
  all_subj_descs := dict_list_keys (subj_dict, 1);
  all_s_count := length (all_subj_descs);
  if (0 = all_s_count)
    return res;
  gvector_sort (all_subj_descs, 1, 0, 0);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (isiri_id (g) and g < min_bnode_iri_id () and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isiri_id (g) and g < min_bnode_iri_id ())
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  vectorbld_init (phys_subjects);
  if (storage_name is null)
    storage_name := 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage';
  else if (('' = storage_name) and (inf_ruleset is null) and (sameas is null))
    {
      for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
        {
          declare s, phys_s any;
          s := all_subj_descs [s_ctr];
          if (isiri_id (s))
            vectorbld_acc (phys_subjects, s);
          else
            {
              phys_s := iri_to_id (s, 0, 0);
              if (not isinteger (phys_s))
                vectorbld_acc (phys_subjects, phys_s);
            }
        }
      vectorbld_final (phys_subjects);
      goto describe_physical_subjects;
    }
  -- dbg_obj_princ ('storage_name=',storage_name, ' sorted_good_graphs=', sorted_good_graphs, ' sorted_bad_graphs=', sorted_bad_graphs);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s, phys_s, maps_s, maps_o any;
      declare maps_s_len, maps_o_len integer;
      s := all_subj_descs [s_ctr];
      maps_s := sparql_quad_maps_for_quad (NULL, s, NULL, NULL, storage_name, case (graphs_listed) when 0 then vector() else sorted_good_graphs end, sorted_bad_graphs);
      maps_o := sparql_quad_maps_for_quad (NULL, NULL, NULL, s, storage_name, case (graphs_listed) when 0 then vector() else sorted_good_graphs end, sorted_bad_graphs);
      -- dbg_obj_princ ('s = ', s, ' maps_s = ', maps_s, ' maps_o = ', maps_o);
      maps_s_len := length (maps_s);
      maps_o_len := length (maps_o);
      if ((inf_ruleset is null) and (sameas is null))
        {
          declare phys_as_s, phys_as_o integer;
          phys_as_s := case when ((maps_s_len > 0) and (maps_s[maps_s_len-1][0] = UNAME'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap')) then 1 else 0 end;
          phys_as_o := case when ((maps_o_len > 0) and (maps_o[maps_o_len-1][0] = UNAME'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap')) then 1 else 0 end;
          if (phys_as_s or phys_as_o)
            {
              if (isiri_id (s))
                {
                  phys_s := s;
                  vectorbld_acc (phys_subjects, phys_s);
                }
              else
                {
                  phys_s := iri_to_id (s, 0, 0);
                  if (not isinteger (phys_s))
                    vectorbld_acc (phys_subjects, phys_s);
                }
              if (phys_as_s)
                {
                  maps_s := subseq (maps_s, 0, maps_s_len-1);
                  maps_s_len := maps_s_len - 1;
                }
              if (phys_as_o)
                {
                  maps_o := subseq (maps_o, 0, maps_o_len-1);
                  maps_o_len := maps_o_len - 1;
                }
            }
        }
      if ((maps_s_len > 0) or (maps_o_len > 0))
        all_subj_descs [s_ctr] := vector (s, maps_s, maps_o);
      else
        all_subj_descs [s_ctr] := 0;
      -- dbg_obj_princ ('s = ', s, ' maps = ', maps);
      -- dbg_obj_princ ('all_subj_descs [', s_ctr, '] = ', all_subj_descs [s_ctr]);
    }
  vectorbld_final (phys_subjects);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s_desc, s, maps_s, maps_o any;
      declare map_ctr, maps_s_len, maps_o_len integer;
      declare fname varchar;
      s_desc := all_subj_descs [s_ctr];
      if (isinteger (s_desc))
        goto end_of_s;
      s := s_desc[0];
      maps_s := s_desc[1];
      maps_o := s_desc[2];
      maps_s_len := length (maps_s);
      maps_o_len := length (maps_o);
      fname := sprintf ('SPARQL_DESC_DICT_QMV1_%U', md5 (storage_name || ' ' || inf_ruleset || ' ' || sameas || ' ' || cast (graphs_listed as varchar) || md5_box (maps_s) || md5_box (maps_o) || md5_box (sorted_bad_graphs)));
      if (not exists (select top 1 1 from Db.DBA.SYS_PROCEDURES where P_NAME = 'DB.DBA.' || fname))
        {
          declare ses, txt, saved_user any;
          ses := string_output ();
          http ('create procedure DB.DBA."' || fname || '" (in subj any, in res any', ses);
          if (graphs_listed)
            http (', inout sorted_good_graphs any', ses);
          http (')\n', ses);
          http ('{\n', ses);
          http ('  declare subj_iri varchar;\n', ses);
          http ('  subj_iri := id_to_iri_nosignal (subj);\n', ses);
          if (maps_s_len > 0)
            {
              http ('  for (sparql define output:valmode "LONG" define input:storage <' || storage_name || '> ', ses);
              foreach (any g in sorted_bad_graphs) do
                {
                  http ('  define input:named-graph-exclude <' || id_to_iri_nosignal (g) || '>\n', ses);
                }
              if (inf_ruleset is not null)
                  http ('  define input:inference <' || inf_ruleset || '>\n', ses);
              if (sameas is not null)
                  http ('  define input:same-as <' || sameas || '>\n', ses);
              http ('select ?g1 ?p1 ?o1\n', ses);
              http ('      where { graph ?g1 {\n', ses);
              for (map_ctr := 0; map_ctr < maps_s_len; map_ctr := map_ctr + 1)
                {
                  if (map_ctr > 0) http ('              union\n', ses);
                  http ('              { quad map <' || maps_s[map_ctr][0] || '> { ?:subj_iri ?p1 ?o1 } }\n', ses);
                }
              http ('            } } ) do {\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g1"), sorted_good_graphs))\n', ses);
              http ('      dict_bitor_or_put (res, vector (subj, "p1", "o1"), 1);\n    }\n', ses);
            }
          if (maps_o_len > 0)
            {
              http ('  for (sparql define output:valmode "LONG" define input:storage <' || storage_name || '> ', ses);
              foreach (any g in sorted_bad_graphs) do
                {
                  http ('  define input:named-graph-exclude <' || id_to_iri_nosignal (g) || '>\n', ses);
                }
              if (inf_ruleset is not null)
                  http ('  define input:inference <' || inf_ruleset || '>\n', ses);
              if (sameas is not null)
                  http ('  define input:same-as <' || sameas || '>\n', ses);
              http ('select ?g1 ?s1 ?p1\n', ses);
              http ('      where { graph ?g1 {\n', ses);
              for (map_ctr := 0; map_ctr < maps_o_len; map_ctr := map_ctr + 1)
                {
                  if (map_ctr > 0) http ('              union\n', ses);
                  http ('              { quad map <' || maps_o[map_ctr][0] || '> { ?s1 ?p1 ?o1 . FILTER (?p1 != rdf:type) . FILTER(isREF (?o1)) . FILTER (?o1 = iri(?:subj_iri)) } }\n', ses);
                }
              http ('            } } ) do {\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g1"), sorted_good_graphs))\n', ses);
              http ('      dict_bitor_or_put (res, vector ("s1", "p1", subj), 4);\n    }\n', ses);
            }
          http ('}\n', ses);
          txt := string_output_string (ses);
          -- dbg_obj_princ ('Procedure text: ', txt); string_to_file (fname || '.sql', txt || '\n;', -2);
          saved_user := user;
          set_user_id ('dba', 1);
          exec (txt);
          set_user_id (saved_user);
        }
      if (graphs_listed)
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, res, sorted_good_graphs, ')');
          call ('DB.DBA.' || fname)(s, res, sorted_good_graphs);
        }
      else
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, res, ')');
          call ('DB.DBA.' || fname)(s, res);
        }
end_of_s: ;
    }

describe_physical_subjects:
  gvector_sort (phys_subjects, 1, 0, 0);
  phys_s_count := length (phys_subjects);
  -- dbg_obj_princ ('phys_subjects = ', phys_subjects);
  if (0 = phys_s_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
            {
              declare subj any;
              subj := phys_subjects [s_ctr];
              for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
                {
                  -- dbg_obj_princ ('found5 ', subj, p1, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
                }
              for (select S as s1, P as p1 from DB.DBA.RDF_QUAD
                  where G = graph and O = subj and P <> rdf_type_iid
                  option (QUIETCAST)) do
                {
                  -- dbg_obj_princ ('found2 ', s1, p1, subj, ' in ', graph);
                  dict_bitor_or_put (res, vector (s1, p1, subj), 4);
                }
            }
        }
      return res;
    }
  g_dict := dict_new ();
  for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
    {
      declare subj any;
      subj := phys_subjects [s_ctr];
      for (select G as graph from DB.DBA.RDF_QUAD where O = subj and
        0 = position (G, sorted_bad_graphs) and
        __rgs_ack_cbk (G, uid, 1) and
        (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
	{
	  if (graph is not null)
	    dict_put (g_dict, graph, 0);
	}
    }
  sorted_good_graphs := dict_list_keys (g_dict, 1);
  if (0 = length (sorted_good_graphs))
    {
      g_dict := dict_new ();
      for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj any;
          subj := phys_subjects [s_ctr];
          for (select G as graph from DB.DBA.RDF_QUAD where S = subj and P = rdf_type_iid and
            0 = position (G, sorted_bad_graphs) and
            __rgs_ack_cbk (G, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
	    {
	      if (graph is not null)
		dict_put (g_dict, graph, 0);
	    }
        }
      sorted_good_graphs := dict_list_keys (g_dict, 1);
    }
  -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
  gvector_sort (sorted_good_graphs, 1, 0, 0);
  good_g_count := length (sorted_good_graphs);
  -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
  for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
    {
      declare graph any;
      graph := sorted_good_graphs [g_ctr];
      for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj any;
          subj := phys_subjects [s_ctr];
          for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
            {
              -- dbg_obj_princ ('found1 ', subj, p1, ' in ', graph);
              dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
--              if (isiri_id (obj1))
--                {
--                  for (select P as p2, O as obj2
--                    from DB.DBA.RDF_QUAD
--                    where G = graph and S = obj1 and not (isiri_id (O)) ) do
--                    {
--                      dict_bitor_or_put (dict, vector (obj1, p2, __rdf_long_of_obj (obj2)), 17);
--                    }
--                }
            }
          for (select S as s1, P as p1 from DB.DBA.RDF_QUAD
            where G = graph and O = subj and P <> rdf_type_iid
            option (QUIETCAST)) do
            {
              -- dbg_obj_princ ('found2 ', s1, p1, subj, ' in ', graph);
              dict_bitor_or_put (res, vector (s1, p1, subj), 4);
            }
        }
    }
  -- dbg_obj_princ ('final result is ', res);
  return res;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_SPO (in subj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_subj_descs, phys_subjects, sorted_good_graphs, sorted_bad_graphs, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, s_ctr, all_s_count, phys_s_count integer;
  declare gs_app_callback, gs_app_uid, inf_ruleset, sameas varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  inf_ruleset := get_keyword ('inference', options);
  sameas := get_keyword ('same-as', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (isiri_id (c))
        dict_put (subj_dict, c, 0);
    }
  all_subj_descs := dict_list_keys (subj_dict, 1);
  all_s_count := length (all_subj_descs);
  if (0 = all_s_count)
    return res;
  gvector_sort (all_subj_descs, 1, 0, 0);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (isiri_id (g) and g < min_bnode_iri_id () and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isiri_id (g) and g < min_bnode_iri_id ())
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  vectorbld_init (phys_subjects);
  if (storage_name is null)
    storage_name := 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage';
  else if (('' = storage_name) and (inf_ruleset is null) and (sameas is null))
    {
      for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
        {
          declare s, phys_s any;
          s := all_subj_descs [s_ctr];
          if (isiri_id (s))
            vectorbld_acc (phys_subjects, s);
          else
            {
              phys_s := iri_to_id (s, 0, 0);
              if (not isinteger (phys_s))
                vectorbld_acc (phys_subjects, phys_s);
            }
        }
      vectorbld_final (phys_subjects);
      goto describe_physical_subjects;
    }
  -- dbg_obj_princ ('storage_name=',storage_name, ' sorted_good_graphs=', sorted_good_graphs, ' sorted_bad_graphs=', sorted_bad_graphs);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s, phys_s, maps any;
      declare maps_len integer;
      s := all_subj_descs [s_ctr];
      maps := sparql_quad_maps_for_quad (NULL, s, NULL, NULL, storage_name, case (graphs_listed) when 0 then vector() else sorted_good_graphs end, sorted_bad_graphs);
      -- dbg_obj_princ ('s = ', s, ' maps = ', maps);
      maps_len := length (maps);
      if ((maps_len > 0) and (inf_ruleset is null) and (sameas is null) and (maps[maps_len-1][0] = UNAME'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap'))
        {
          if (isiri_id (s))
            {
              phys_s := s;
              vectorbld_acc (phys_subjects, phys_s);
            }
          else
            {
              phys_s := iri_to_id (s, 0, 0);
              if (not isinteger (phys_s))
                vectorbld_acc (phys_subjects, phys_s);
            }
          maps := subseq (maps, 0, maps_len-1);
          maps_len := maps_len - 1;
        }
      if (maps_len > 0)
        all_subj_descs [s_ctr] := vector (s, maps);
      else
        all_subj_descs [s_ctr] := 0;
      -- dbg_obj_princ ('s = ', s, ' maps = ', maps);
      -- dbg_obj_princ ('all_subj_descs [', s_ctr, '] = ', all_subj_descs [s_ctr]);
    }
  vectorbld_final (phys_subjects);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s_desc, s, maps any;
      declare map_ctr, maps_len integer;
      declare fname varchar;
      s_desc := all_subj_descs [s_ctr];
      if (isinteger (s_desc))
        goto end_of_s;
      s := s_desc[0];
      maps := s_desc[1];
      maps_len := length (maps);
      fname := sprintf ('SPARQL_DESC_DICT_QMV1_%U', md5 (storage_name || ' ' || inf_ruleset || ' ' || sameas || ' ' || cast (graphs_listed as varchar) || md5_box (maps) || md5_box (sorted_bad_graphs)));
      if (not exists (select top 1 1 from Db.DBA.SYS_PROCEDURES where P_NAME = 'DB.DBA.' || fname))
        {
          declare ses, txt, saved_user any;
          ses := string_output ();
          http ('create procedure DB.DBA."' || fname || '" (in subj any, in res any', ses);
          if (graphs_listed)
            http (', inout sorted_good_graphs any', ses);
          http (')\n', ses);
          http ('{\n', ses);
          http ('  declare subj_iri varchar;\n', ses);
          http ('  subj_iri := id_to_iri_nosignal (subj);\n', ses);
          if (maps_len > 0)
            {
              http ('  for (sparql define output:valmode "LONG" define input:storage <' || storage_name || '> ', ses);
              foreach (any g in sorted_bad_graphs) do
                {
                  http ('  define input:named-graph-exclude <' || id_to_iri_nosignal (g) || '>\n', ses);
                }
              if (inf_ruleset is not null)
                  http ('  define input:inference <' || inf_ruleset || '>\n', ses);
              if (sameas is not null)
                  http ('  define input:same-as <' || sameas || '>\n', ses);
              http ('select ?g1 ?p1 ?o1\n', ses);
              http ('      where { graph ?g1 {\n', ses);
              for (map_ctr := 0; map_ctr < maps_len; map_ctr := map_ctr + 1)
                {
                  if (map_ctr > 0) http ('              union\n', ses);
                  http ('              { quad map <' || maps[map_ctr][0] || '> { ?:subj_iri ?p1 ?o1 } }\n', ses);
                }
              http ('            } } ) do {\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g1"), sorted_good_graphs))\n', ses);
              http ('      dict_bitor_or_put (res, vector (subj, "p1", "o1"), 1);\n    }\n', ses);
            }
          http ('}\n', ses);
          txt := string_output_string (ses);
          -- dbg_obj_princ ('Procedure text: ', txt);
          saved_user := user;
          set_user_id ('dba', 1);
          exec (txt);
          set_user_id (saved_user);
        }
      if (graphs_listed)
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, res, sorted_good_graphs, ')');
          call ('DB.DBA.' || fname)(s, res, sorted_good_graphs);
        }
      else
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, res, ')');
          call ('DB.DBA.' || fname)(s, res);
        }
end_of_s: ;
    }

describe_physical_subjects:
  gvector_sort (phys_subjects, 1, 0, 0);
  phys_s_count := length (phys_subjects);
  -- dbg_obj_princ ('phys_subjects = ', phys_subjects);
  if (0 = phys_s_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
            {
              declare subj any;
              subj := phys_subjects [s_ctr];
              for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
                {
                  -- dbg_obj_princ ('found3 ', subj, p1, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
                }
            }
        }
      return res;
    }
  for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
    {
      declare subj any;
      subj := phys_subjects [s_ctr];
      for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where
        0 = position (G, sorted_bad_graphs) and
        S = subj and
        __rgs_ack_cbk (G, uid, 1) and
        (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
        {
          -- dbg_obj_princ ('found4 ', subj, p1);
          dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
        }
    }
  return res;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_SPO_PHYSICAL (in subj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_subj_descs, phys_subjects, sorted_good_graphs, sorted_bad_graphs, g_dict, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, s_ctr, all_s_count, phys_s_count integer;
  declare gs_app_callback, gs_app_uid varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (isiri_id (c))
        dict_put (subj_dict, c, 0);
    }
  all_subj_descs := dict_list_keys (subj_dict, 1);
  all_s_count := length (all_subj_descs);
  if (0 = all_s_count)
    return res;
  gvector_sort (all_subj_descs, 1, 0, 0);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (isiri_id (g) and g < min_bnode_iri_id () and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isiri_id (g) and g < min_bnode_iri_id ())
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  vectorbld_init (phys_subjects);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s, phys_s any;
      s := all_subj_descs [s_ctr];
      if (isiri_id (s))
        vectorbld_acc (phys_subjects, s);
      else
        {
          phys_s := iri_to_id (s, 0, 0);
          if (not isinteger (phys_s))
            vectorbld_acc (phys_subjects, phys_s);
        }
    }
  vectorbld_final (phys_subjects);
  gvector_sort (phys_subjects, 1, 0, 0);
  phys_s_count := length (phys_subjects);
  -- dbg_obj_princ ('phys_subjects = ', phys_subjects);
  if (0 = phys_s_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
            {
              declare subj any;
              subj := phys_subjects [s_ctr];
              for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
                {
                  -- dbg_obj_princ ('found5 ', subj, p1, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
                }
            }
        }
      return res;
    }
  g_dict := dict_new ();
  for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
    {
      declare subj, graph any;
      subj := phys_subjects [s_ctr];
      graph := coalesce ((select top 1 G as g1 from DB.DBA.RDF_QUAD where O = subj and
          0 = position (G, sorted_bad_graphs) and
          __rgs_ack_cbk (G, uid, 1) and
          (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) );
      if (graph is not null)
        dict_put (g_dict, graph, 0);
    }
  sorted_good_graphs := dict_list_keys (g_dict, 1);
  if (0 = length (sorted_good_graphs))
    {
      g_dict := dict_new ();
      for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj, graph any;
          subj := phys_subjects [s_ctr];
          graph := coalesce ((select top 1 G as g1 from DB.DBA.RDF_QUAD where S = subj and P = rdf_type_iid and
              0 = position (G, sorted_bad_graphs) and
              __rgs_ack_cbk (G, uid, 1) and
              (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) );
          if (graph is not null)
            dict_put (g_dict, graph, 0);
        }
      sorted_good_graphs := dict_list_keys (g_dict, 1);
    }
  -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
  gvector_sort (sorted_good_graphs, 1, 0, 0);
  good_g_count := length (sorted_good_graphs);
  -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
  for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
    {
      declare graph any;
      graph := sorted_good_graphs [g_ctr];
      for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj any;
          subj := phys_subjects [s_ctr];
          for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
            {
              -- dbg_obj_princ ('found6 ', subj, p1, ' in ', graph);
              dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
--              if (isiri_id (obj1))
--                {
--                  for (select P as p2, O as obj2
--                    from DB.DBA.RDF_QUAD
--                    where G = graph and S = obj1 and not (isiri_id (O)) ) do
--                    {
--                      dict_bitor_or_put (dict, vector (obj1, p2, __rdf_long_of_obj (obj2)), 17);
--                    }
--                }
            }
--          for (select S as s1, P as p1 from DB.DBA.RDF_QUAD
--            where G = graph and O = subj and P <> rdf_type_iid
--            option (QUIETCAST)) do
--            {
              -- dbg_obj_princ ('found7 ', s1, p1, subj, ' in ', graph);
--              dict_bitor_or_put (res, vector (s1, p1, subj), 4);
--            }
        }
    }
  -- dbg_obj_princ ('final result is ', res);
  return res;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_CBD (in subj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_subjs, phys_subjects, sorted_good_graphs, sorted_bad_graphs, next_iter_subjs, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, s_ctr, all_s_count, phys_s_count integer;
  declare gs_app_callback, gs_app_uid, inf_ruleset varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  inf_ruleset := get_keyword ('inference', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (isiri_id (c))
        dict_put (subj_dict, c, 0);
    }
  all_subjs := dict_list_keys (subj_dict, 0);
  next_iter_subjs := dict_new ();
  all_s_count := length (all_subjs);
  if (0 = all_s_count)
    return res;

next_iteration:
  all_s_count := length (all_subjs);
  gvector_sort (all_subjs, 1, 0, 0);
  -- dbg_obj_princ ('new iteration: all_subjs = ', all_subjs);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (isiri_id (g) and g < min_bnode_iri_id () and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isiri_id (g) and g < min_bnode_iri_id ())
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  vectorbld_init (phys_subjects);
  if (storage_name is null)
    storage_name := 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage';
  else if (('' = storage_name) and (inf_ruleset is null))
    {
      for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
        {
          declare s, phys_s any;
          s := all_subjs [s_ctr];
          if (isiri_id (s))
            vectorbld_acc (phys_subjects, s);
          else
            {
              phys_s := iri_to_id (s, 0, 0);
              if (not isinteger (phys_s))
                vectorbld_acc (phys_subjects, phys_s);
            }
        }
      vectorbld_final (phys_subjects);
      goto describe_physical_subjects;
    }
  -- dbg_obj_princ ('storage_name=',storage_name, ' sorted_good_graphs=', sorted_good_graphs, ' sorted_bad_graphs=', sorted_bad_graphs);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s, phys_s, maps any;
      declare maps_len integer;
      s := all_subjs [s_ctr];
      maps := sparql_quad_maps_for_quad (NULL, s, NULL, NULL, storage_name, case (graphs_listed) when 0 then vector() else sorted_good_graphs end, sorted_bad_graphs);
      -- dbg_obj_princ ('s = ', s, id_to_iri (s), ' maps = ', maps);
      maps_len := length (maps);
      if ((maps_len > 0) and (inf_ruleset is null) and (maps[maps_len-1][0] = UNAME'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap'))
        {
          if (isiri_id (s))
            {
              phys_s := s;
              vectorbld_acc (phys_subjects, phys_s);
            }
          else
            {
              phys_s := iri_to_id (s, 0, 0);
              if (not isinteger (phys_s))
                vectorbld_acc (phys_subjects, phys_s);
            }
          maps := subseq (maps, 0, maps_len-1);
          maps_len := maps_len - 1;
        }
      if (maps_len > 0)
        all_subjs [s_ctr] := vector (s, maps);
      else
        all_subjs [s_ctr] := 0;
      -- dbg_obj_princ ('s = ', s, ' maps = ', maps);
      -- dbg_obj_princ ('all_subjs [', s_ctr, '] = ', all_subjs [s_ctr]);
    }
  vectorbld_final (phys_subjects);
  for (s_ctr := 0; s_ctr < all_s_count; s_ctr := s_ctr + 1)
    {
      declare s_desc, s, maps any;
      declare map_ctr, maps_len integer;
      declare fname varchar;
      s_desc := all_subjs [s_ctr];
      if (isinteger (s_desc))
        goto end_of_s;
      s := s_desc[0];
      maps := s_desc[1];
      maps_len := length (maps);
      fname := sprintf ('SPARQL_DESC_DICT_CBD_QMV1_%U', md5 (storage_name || inf_ruleset || cast (graphs_listed as varchar) || md5_box (maps) || md5_box (sorted_bad_graphs)));
      if (not exists (select top 1 1 from Db.DBA.SYS_PROCEDURES where P_NAME = 'DB.DBA.' || fname))
        {
          declare ses, txt, saved_user any;
          ses := string_output ();
          http ('create procedure DB.DBA."' || fname || '" (in subj any, in subj_dict any, in next_iter_subjs any, in res any', ses);
          if (graphs_listed)
            http (', inout sorted_good_graphs any', ses);
          http (')\n', ses);
          http ('{\n', ses);
          http ('  declare subj_iri varchar;\n', ses);
          http ('  subj_iri := id_to_iri_nosignal (subj);\n', ses);
          if (maps_len > 0)
            {
              http ('  for (sparql define output:valmode "LONG" define input:storage <' || storage_name || '> ', ses);
              foreach (any g in sorted_bad_graphs) do
                {
                  http ('  define input:named-graph-exclude <' || id_to_iri_nosignal (g) || '>\n', ses);
                }
              if (inf_ruleset is not null)
                  http ('  define input:inference <' || inf_ruleset || '>\n', ses);
              http ('select ?g1 ?p1 ?o1 ?g2 ?st2\n', ses);
              http ('      where { graph ?g1 {\n', ses);
              for (map_ctr := 0; map_ctr < maps_len; map_ctr := map_ctr + 1)
                {
                  if (map_ctr > 0) http ('              union\n', ses);
                  http ('              { quad map <' || maps[map_ctr][0] || '> { ?:subj_iri ?p1 ?o1 } }\n', ses);
                }
              http ('            }\n', ses);
              http ('          optional { graph ?g2 {\n', ses);
              http ('                  ?st2 a rdf:Statement ; rdf:subject ?:subj_iri ; rdf:predicate ?p1 ; rdf:object ?o1 } }\n', ses);
              http ('            } ) do {\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g1"), sorted_good_graphs)) {\n', ses);
              http ('      dict_bitor_or_put (res, vector (subj, "p1", "o1"), 1);\n', ses);
              http ('      if (isiri_id ("o1") and "o1" > min_bnode_iri_id() and dict_get (subj_dict, "o1") is null)\n', ses);
              http ('        dict_put (next_iter_subjs, "o1", 1);\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g2"), sorted_good_graphs)) {\n', ses);
              http ('      if ("st2" is not null and dict_get (subj_dict, "st2") is null)\n', ses);
              http ('        dict_put (next_iter_subjs, "o1", 1);\n', ses);
              if (graphs_listed)
                http ('        } }\n', ses);
              http ('    }\n', ses);
            }
          http ('}\n', ses);
          txt := string_output_string (ses);
          -- dbg_obj_princ ('Procedure text: ', txt);
          saved_user := user;
          set_user_id ('dba', 1);
          exec (txt);
          set_user_id (saved_user);
        }
      if (graphs_listed)
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, subj_dict, next_iter_subjs, res, sorted_good_graphs, ')');
          call ('DB.DBA.' || fname)(s, subj_dict, next_iter_subjs, res, sorted_good_graphs);
        }
      else
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', s, subj_dict, next_iter_subjs, res, ')');
          call ('DB.DBA.' || fname)(s, subj_dict, next_iter_subjs, res);
        }
end_of_s: ;
    }

describe_physical_subjects:
  gvector_sort (phys_subjects, 1, 0, 0);
  phys_s_count := length (phys_subjects);
  -- dbg_obj_princ ('phys_subjects = ', phys_subjects);
  if (0 = phys_s_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
            {
              declare subj any;
              subj := phys_subjects [s_ctr];
              for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
                {
                  -- dbg_obj_princ ('found3 ', subj, p1, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
                  if (isiri_id (obj1) and obj1 > min_bnode_iri_id() and dict_get (subj_dict, obj1) is null)
                    dict_put (next_iter_subjs, obj1, 1);
                  for (sparql define output:valmode "LONG"
                    select ?g2 ?st2 where {
                        graph ?g2 {
                            ?st2 a rdf:Statement ; rdf:subject ?:subj ; rdf:predicate ?:p1 ; rdf:object ?:obj1 } } ) do
                    {
                      if (position ("g2", sorted_good_graphs) and dict_get (subj_dict, "st2") is null)
                        dict_put (next_iter_subjs, "st2", 1);
                    }
                }
            }
        }
    }
  else
    {
      for (s_ctr := phys_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj any;
          subj := phys_subjects [s_ctr];
          for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where
            0 = position (G, sorted_bad_graphs) and
            S = subj and
            __rgs_ack_cbk (G, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
            {
              -- dbg_obj_princ ('found4 ', subj, p1);
              dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
              if (isiri_id (obj1) and obj1 > min_bnode_iri_id() and dict_get (subj_dict, obj1) is null)
                dict_put (next_iter_subjs, obj1, 1);
              for (sparql define output:valmode "LONG"
                select ?g2 ?st2 where {
                    graph ?g2 {
                        ?st2 a rdf:Statement ; rdf:subject ?:subj ; rdf:predicate ?:p1 ; rdf:object ?:obj1 } } ) do
                {
                  if (0 = position ("g2", sorted_bad_graphs) and
                    dict_get (subj_dict, "st2") is null and
                    __rgs_ack_cbk ("g2", uid, 1) and
                    (gs_app_callback is null or bit_and (1, call (gs_app_callback) ("g2", gs_app_uid))) )
                    dict_put (next_iter_subjs, "st2", 1);
                }
            }
        }
    }
ret_or_next_iter:
  if (0 = dict_size (next_iter_subjs))
    {
      -- dbg_obj_princ ('no new subjs, res = ', dict_list_keys (res, 0));
      return res;
    }
  all_subjs := dict_list_keys (next_iter_subjs, 1);
  foreach (IRI_ID s in all_subjs) do dict_put (subj_dict, s, 1);
  goto next_iteration;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_CBD_PHYSICAL (in subj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_subjs, sorted_good_graphs, sorted_bad_graphs, next_iter_subjs, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, s_ctr, all_s_count integer;
  declare gs_app_callback, gs_app_uid varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (isiri_id (c))
        dict_put (subj_dict, c, 0);
    }
  all_subjs := dict_list_keys (subj_dict, 0);
  next_iter_subjs := dict_new ();
  all_s_count := length (all_subjs);
  if (0 = all_s_count)
    return res;

next_iteration:
  all_s_count := length (all_subjs);
  gvector_sort (all_subjs, 1, 0, 0);
  -- dbg_obj_princ ('new iteration: all_subjs = ', all_subjs);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (isiri_id (g) and g < min_bnode_iri_id () and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isiri_id (g) and g < min_bnode_iri_id ())
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  -- dbg_obj_princ ('all_subjs = ', all_subjs);
  if (0 = all_s_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (s_ctr := all_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
            {
              declare subj any;
              subj := all_subjs [s_ctr];
              for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where G = graph and S = subj) do
                {
                  -- dbg_obj_princ ('found3 ', subj, p1, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
                  if (isiri_id (obj1) and obj1 > min_bnode_iri_id() and dict_get (subj_dict, obj1) is null)
                    dict_put (next_iter_subjs, obj1, 1);
                  for (sparql define output:valmode "LONG"
                    select ?g2 ?st2 where {
                        graph ?g2 {
                            ?st2 a rdf:Statement ; rdf:subject ?:subj ; rdf:predicate ?:p1 ; rdf:object ?:obj1 } } ) do
                    {
                      if (position ("g2", sorted_good_graphs) and dict_get (subj_dict, "st2") is null)
                        dict_put (next_iter_subjs, "st2", 1);
                    }
                }
            }
        }
    }
  else
    {
      for (s_ctr := all_s_count - 1; s_ctr >= 0; s_ctr := s_ctr - 1)
        {
          declare subj any;
          subj := all_subjs [s_ctr];
          for (select P as p1, O as obj1 from DB.DBA.RDF_QUAD where
            0 = position (G, sorted_bad_graphs) and
            S = subj and
            __rgs_ack_cbk (G, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
            {
              -- dbg_obj_princ ('found4 ', subj, p1);
              dict_bitor_or_put (res, vector (subj, p1, __rdf_long_of_obj (obj1)), 1);
              if (isiri_id (obj1) and obj1 > min_bnode_iri_id() and dict_get (subj_dict, obj1) is null)
                dict_put (next_iter_subjs, obj1, 1);
              for (sparql define output:valmode "LONG"
                select ?g2 ?st2 where {
                    graph ?g2 {
                        ?st2 a rdf:Statement ; rdf:subject ?:subj ; rdf:predicate ?:p1 ; rdf:object ?:obj1 } } ) do
                {
                  if (0 = position ("g2", sorted_bad_graphs) and
                    dict_get (subj_dict, "st2") is null and
                    __rgs_ack_cbk ("g2", uid, 1) and
                    (gs_app_callback is null or bit_and (1, call (gs_app_callback) ("g2", gs_app_uid))) )
                    dict_put (next_iter_subjs, "st2", 1);
                }
            }
        }
    }

ret_or_next_iter:
  if (0 = dict_size (next_iter_subjs))
    {
      -- dbg_obj_princ ('no new subjs, res = ', dict_list_keys (res, 0));
      return res;
    }
  all_subjs := dict_list_keys (next_iter_subjs, 1);
  foreach (IRI_ID s in all_subjs) do dict_put (subj_dict, s, 1);
  goto next_iteration;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_OBJCBD (in obj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_objs, phys_objects, sorted_good_graphs, sorted_bad_graphs, next_iter_objs, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, obj_ctr, all_obj_count, phys_obj_count integer;
  declare gs_app_callback, gs_app_uid, inf_ruleset varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  inf_ruleset := get_keyword ('inference', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (not isnumeric (c))
        dict_put (obj_dict, c, 0);
    }
  all_objs := dict_list_keys (obj_dict, 0);
  next_iter_objs := dict_new ();
  all_obj_count := length (all_objs);
  if (0 = all_obj_count)
    return res;

next_iteration:
  all_obj_count := length (all_objs);
  gvector_sort (all_objs, 1, 0, 0);
  -- dbg_obj_princ ('new iteration: all_objs = ', all_objs);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (is_named_iri_id (g) and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (is_named_iri_id (g))
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  vectorbld_init (phys_objects);
  if (storage_name is null)
    storage_name := 'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadStorage';
  else if (('' = storage_name) and (inf_ruleset is null))
    {
      for (obj_ctr := 0; obj_ctr < all_obj_count; obj_ctr := obj_ctr + 1)
        {
          declare obj, phys_obj any;
          obj := all_objs [obj_ctr];
          if (not isnumeric (obj))
            {
              if (isiri_id (obj))
                vectorbld_acc (phys_objects, obj);
              else
                {
                  phys_obj := iri_to_id (obj, 0, 0);
                  if (not isinteger (phys_obj))
                    vectorbld_acc (phys_objects, phys_obj);
                }
            }
        }
      vectorbld_final (phys_objects);
      goto describe_physical_objects;
    }
  -- dbg_obj_princ ('storage_name=',storage_name, ' sorted_good_graphs=', sorted_good_graphs, ' sorted_bad_graphs=', sorted_bad_graphs);
  for (obj_ctr := 0; obj_ctr < all_obj_count; obj_ctr := obj_ctr + 1)
    {
      declare obj, phys_obj, maps any;
      declare maps_len integer;
      obj := all_objs [obj_ctr];
      maps := sparql_quad_maps_for_quad (NULL, NULL, NULL, obj, storage_name, case (graphs_listed) when 0 then vector() else sorted_good_graphs end, sorted_bad_graphs);
      -- dbg_obj_princ ('obj = ', obj, id_to_iri (obj), ' maps = ', maps);
      maps_len := length (maps);
      if ((maps_len > 0) and (inf_ruleset is null) and (maps[maps_len-1][0] = UNAME'http://www.openlinksw.com/schemas/virtrdf#DefaultQuadMap'))
        {
          if (not isnumeric (obj))
            {
              if (isiri_id (obj))
                {
                  phys_obj := obj;
                  vectorbld_acc (phys_objects, phys_obj);
                }
              else
                {
                  phys_obj := iri_to_id (obj, 0, 0);
                  if (not isinteger (phys_obj))
                    vectorbld_acc (phys_objects, phys_obj);
                }
            }
          maps := subseq (maps, 0, maps_len-1);
          maps_len := maps_len - 1;
        }
      if (maps_len > 0)
        all_objs [obj_ctr] := vector (obj, maps);
      else
        all_objs [obj_ctr] := 0;
      -- dbg_obj_princ ('obj = ', obj, ' maps = ', maps);
      -- dbg_obj_princ ('all_objs [', obj_ctr, '] = ', all_objs [obj_ctr]);
    }
  vectorbld_final (phys_objects);
  for (obj_ctr := 0; obj_ctr < all_obj_count; obj_ctr := obj_ctr + 1)
    {
      declare s_desc, obj, maps any;
      declare map_ctr, maps_len integer;
      declare fname varchar;
      s_desc := all_objs [obj_ctr];
      if (isinteger (s_desc))
        goto end_of_s;
      obj := s_desc[0];
      maps := s_desc[1];
      maps_len := length (maps);
      fname := sprintf ('SPARQL_DESC_DICT_OBJCBD_QMV1_%U', md5 (storage_name || inf_ruleset || cast (graphs_listed as varchar) || md5_box (maps) || md5_box (sorted_bad_graphs)));
      if (not exists (select top 1 1 from Db.DBA.SYS_PROCEDURES where P_NAME = 'DB.DBA.' || fname))
        {
          declare ses, txt, saved_user any;
          ses := string_output ();
          http ('create procedure DB.DBA."' || fname || '" (in obj any, in obj_dict any, in next_iter_objs any, in res any', ses);
          if (graphs_listed)
            http (', inout sorted_good_graphs any', ses);
          http (')\n', ses);
          http ('{\n', ses);
          http ('  declare obj_iri varchar;\n', ses);
          http ('  obj_iri := id_to_iri_nosignal (obj);\n', ses);
          if (maps_len > 0)
            {
              http ('  for (sparql define output:valmode "LONG" define input:storage <' || storage_name || '> ', ses);
              foreach (any g in sorted_bad_graphs) do
                {
                  http ('  define input:named-graph-exclude <' || id_to_iri_nosignal (g) || '>\n', ses);
                }
              if (inf_ruleset is not null)
                  http ('  define input:inference <' || inf_ruleset || '>\n', ses);
              http ('select ?g1 ?p1 ?s1 ?g2 ?st2\n', ses);
              http ('      where { graph ?g1 {\n', ses);
              for (map_ctr := 0; map_ctr < maps_len; map_ctr := map_ctr + 1)
                {
                  if (map_ctr > 0) http ('              union\n', ses);
                  http ('              { quad map <' || maps[map_ctr][0] || '> { ?s1 ?p1 ?:obj_iri } }\n', ses);
                }
              http ('            }\n', ses);
              http ('          optional { graph ?g2 {\n', ses);
              http ('                  ?st2 a rdf:Statement ; rdf:object ?:obj_iri ; rdf:predicate ?p1 ; rdf:subject ?s1 } }\n', ses);
              http ('            } ) do {\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g1"), sorted_good_graphs)) {\n', ses);
              http ('      dict_bitor_or_put (res, vector ("s1", "p1", obj), 1);\n', ses);
              http ('      if (is_bnode_iri_id ("s1") and dict_get (obj_dict, "s1") is null)\n', ses);
              http ('        dict_put (next_iter_objs, "s1", 1);\n', ses);
              if (graphs_listed)
                http ('      if (position (__i2idn ("g2"), sorted_good_graphs)) {\n', ses);
              http ('      if ("st2" is not null and dict_get (obj_dict, "st2") is null)\n', ses);
              http ('        dict_put (next_iter_objs, "s1", 1);\n', ses);
              if (graphs_listed)
                http ('        } }\n', ses);
              http ('      }\n', ses);
            }
          http ('}\n', ses);
          txt := string_output_string (ses);
          -- dbg_obj_princ ('Procedure text: ', txt);
          saved_user := user;
          set_user_id ('dba', 1);
          exec (txt);
          set_user_id (saved_user);
        }
      if (graphs_listed)
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', obj, obj_dict, next_iter_objs, res, sorted_good_graphs, ')');
          call ('DB.DBA.' || fname)(obj, obj_dict, next_iter_objs, res, sorted_good_graphs);
        }
      else
        {
          -- dbg_obj_princ ('call (''DB.DBA.', fname, ''')(', obj, obj_dict, next_iter_objs, res, ')');
          call ('DB.DBA.' || fname)(obj, obj_dict, next_iter_objs, res);
        }
end_of_s: ;
    }

describe_physical_objects:
  gvector_sort (phys_objects, 1, 0, 0);
  phys_obj_count := length (phys_objects);
  -- dbg_obj_princ ('phys_objects = ', phys_objects);
  if (0 = phys_obj_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (obj_ctr := phys_obj_count - 1; obj_ctr >= 0; obj_ctr := obj_ctr - 1)
            {
              declare obj any;
              obj := phys_objects [obj_ctr];
              for (select P as p1, S as subj1 from DB.DBA.RDF_QUAD where G = graph and O = obj) do
                {
                  -- dbg_obj_princ ('found3 ', subj1, p1, obj, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj1, p1, __rdf_long_of_obj (obj)), 1);
                  if (is_bnode_iri_id (subj1) and dict_get (obj_dict, subj1) is null)
                    dict_put (next_iter_objs, subj1, 1);
                  for (sparql define output:valmode "LONG"
                    select ?g2 ?st2 where {
                        graph ?g2 {
                            ?st2 a rdf:Statement ; rdf:object ?:obj ; rdf:predicate ?:p1 ; rdf:subject ?:subj1 } } ) do
                    {
                      if (position ("g2", sorted_good_graphs) and dict_get (obj_dict, "st2") is null)
                        dict_put (next_iter_objs, "st2", 1);
                    }
                }
            }
        }
    }
  else
    {
      for (obj_ctr := phys_obj_count - 1; obj_ctr >= 0; obj_ctr := obj_ctr - 1)
        {
          declare obj any;
          obj := phys_objects [obj_ctr];
          for (select P as p1, S as subj1 from DB.DBA.RDF_QUAD where
            0 = position (G, sorted_bad_graphs) and
            O = obj and
            __rgs_ack_cbk (G, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
            {
              -- dbg_obj_princ ('found4 ', obj, p1);
              dict_bitor_or_put (res, vector (subj1, p1, __rdf_long_of_obj (obj)), 1);
              if (is_bnode_iri_id (subj1) and dict_get (obj_dict, subj1) is null)
                dict_put (next_iter_objs, subj1, 1);
              for (sparql define output:valmode "LONG"
                select ?g2 ?st2 where {
                    graph ?g2 {
                        ?st2 a rdf:Statement ; rdf:object ?:obj ; rdf:predicate ?:p1 ; rdf:subject ?:subj1 } } ) do
                {
                  if (0 = position ("g2", sorted_bad_graphs) and
                    dict_get (obj_dict, "st2") is null and
                    __rgs_ack_cbk ("g2", uid, 1) and
                    (gs_app_callback is null or bit_and (1, call (gs_app_callback) ("g2", gs_app_uid))) )
                    dict_put (next_iter_objs, "st2", 1);
                }
            }
        }
    }
ret_or_next_iter:
  if (0 = dict_size (next_iter_objs))
    {
      -- dbg_obj_princ ('no new objs, res = ', dict_list_keys (res, 0));
      return res;
    }
  all_objs := dict_list_keys (next_iter_objs, 1);
  foreach (IRI_ID obj in all_objs) do dict_put (obj_dict, obj, 1);
  goto next_iteration;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_OBJCBD_PHYSICAL (in obj_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare all_objs, sorted_good_graphs, sorted_bad_graphs, next_iter_objs, res any;
  declare uid, graphs_listed, g_ctr, good_g_count, bad_g_count, obj_ctr, all_obj_count integer;
  declare gs_app_callback, gs_app_uid varchar;
  declare rdf_type_iid IRI_ID;
  uid := get_keyword ('uid', options, http_nobody_uid());
  gs_app_callback := get_keyword ('gs-app-callback', options);
  if (gs_app_callback is not null)
    gs_app_uid := get_keyword ('gs-app-uid', options);
  rdf_type_iid := iri_to_id (UNAME'http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
  res := dict_new ();
  if (isinteger (consts))
    return res;
  foreach (any c in consts) do
    {
      if (not isnumeric (c))
        dict_put (obj_dict, c, 0);
    }
  all_objs := dict_list_keys (obj_dict, 0);
  next_iter_objs := dict_new ();
  all_obj_count := length (all_objs);
  if (0 = all_obj_count)
    return res;

next_iteration:
  all_obj_count := length (all_objs);
  gvector_sort (all_objs, 1, 0, 0);
  -- dbg_obj_princ ('new iteration: all_objs = ', all_objs);
  if (__tag of integer = __tag (good_graphs))
    graphs_listed := 0;
  else
    {
      vectorbld_init (sorted_good_graphs);
      foreach (any g in good_graphs) do
        {
          if (is_named_iri_id (g) and
            __rgs_ack_cbk (g, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (g, gs_app_uid))) )
            vectorbld_acc (sorted_good_graphs, g);
        }
      vectorbld_final (sorted_good_graphs);
      good_g_count := length (sorted_good_graphs);
      if (0 = good_g_count)
        return res;
      graphs_listed := 1;
    }
  vectorbld_init (sorted_bad_graphs);
  foreach (any g in bad_graphs) do
    {
      if (isnamed_iri_id (g))
        vectorbld_acc (sorted_bad_graphs, g);
    }
  vectorbld_final (sorted_bad_graphs);
  bad_g_count := length (sorted_bad_graphs);
  -- dbg_obj_princ ('all_objs = ', all_objs);
  if (0 = all_obj_count)
    return res;
  -- dbg_obj_princ ('sorted_bad_graphs = ', sorted_bad_graphs);
  if (graphs_listed)
    {
      gvector_sort (sorted_good_graphs, 1, 0, 0);
      -- dbg_obj_princ ('sorted_good_graphs = ', sorted_good_graphs);
      for (g_ctr := good_g_count - 1; g_ctr >= 0; g_ctr := g_ctr - 1)
        {
          declare graph any;
          graph := sorted_good_graphs [g_ctr];
          for (obj_ctr := all_obj_count - 1; obj_ctr >= 0; obj_ctr := obj_ctr - 1)
            {
              declare obj any;
              obj := all_objs [obj_ctr];
              for (select P as p1, S as subj1 from DB.DBA.RDF_QUAD where G = graph and O = obj) do
                {
                  -- dbg_obj_princ ('found3 ', subj1, p1, obj, ' in ', graph);
                  dict_bitor_or_put (res, vector (subj1, p1, __rdf_long_of_obj (obj)), 1);
                  if (is_bnode_iri_id (subj1) and dict_get (obj_dict, subj1) is null)
                    dict_put (next_iter_objs, subj1, 1);
                  for (sparql define output:valmode "LONG"
                    select ?g2 ?st2 where {
                        graph ?g2 {
                            ?st2 a rdf:Statement ; rdf:object ?:obj ; rdf:predicate ?:p1 ; rdf:subject ?:subj1 } } ) do
                    {
                      if (position ("g2", sorted_good_graphs) and dict_get (obj_dict, "st2") is null)
                        dict_put (next_iter_objs, "st2", 1);
                    }
                }
            }
        }
    }
  else
    {
      for (obj_ctr := all_obj_count - 1; obj_ctr >= 0; obj_ctr := obj_ctr - 1)
        {
          declare obj any;
          obj := all_objs [obj_ctr];
          for (select P as p1, S as subj1 from DB.DBA.RDF_QUAD where
            0 = position (G, sorted_bad_graphs) and
            O = obj and
            __rgs_ack_cbk (G, uid, 1) and
            (gs_app_callback is null or bit_and (1, call (gs_app_callback) (G, gs_app_uid))) ) do
            {
              -- dbg_obj_princ ('found4 ', subj1, p1, obj);
              dict_bitor_or_put (res, vector (subj1, p1, __rdf_long_of_obj (obj)), 1);
              if (is_bnode_iri_id (subj1) and dict_get (obj_dict, subj1) is null)
                dict_put (next_iter_objs, subj1, 1);
              for (sparql define output:valmode "LONG"
                select ?g2 ?st2 where {
                    graph ?g2 {
                        ?st2 a rdf:Statement ; rdf:object ?:obj ; rdf:predicate ?:p1 ; rdf:subject ?:subj1 } } ) do
                {
                  if (0 = position ("g2", sorted_bad_graphs) and
                    dict_get (obj_dict, "st2") is null and
                    __rgs_ack_cbk ("g2", uid, 1) and
                    (gs_app_callback is null or bit_and (1, call (gs_app_callback) ("g2", gs_app_uid))) )
                    dict_put (next_iter_objs, "st2", 1);
                }
            }
        }
    }

ret_or_next_iter:
  if (0 = dict_size (next_iter_objs))
    {
      -- dbg_obj_princ ('no new objs, res = ', dict_list_keys (res, 0));
      return res;
    }
  all_objs := dict_list_keys (next_iter_objs, 1);
  foreach (IRI_ID obj in all_objs) do dict_put (obj_dict, obj, 1);
  goto next_iteration;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_SCBD (in node_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare cbd_res, objcbd_res, triples any;
  cbd_res := DB.DBA.SPARQL_DESC_DICT_CBD (node_dict, consts, good_graphs, bad_graphs, storage_name, options);
  objcbd_res := DB.DBA.SPARQL_DESC_DICT_OBJCBD (node_dict, consts, good_graphs, bad_graphs, storage_name, options);
again:
  triples := dict_destructive_list_rnd_keys (objcbd_res, 80000);
  if (0 = length (triples))
    return cbd_res;
  foreach (any triple in triples) do { dict_put (cbd_res, triple, 1); }
  goto again;
}
;

create procedure DB.DBA.SPARQL_DESC_DICT_SCBD_PHYSICAL (in node_dict any, in consts any, in good_graphs any, in bad_graphs any, in storage_name any, in options any)
{
  declare cbd_res, objcbd_res, triples any;
  cbd_res := DB.DBA.SPARQL_DESC_DICT_CBD_PHYSICAL (node_dict, consts, good_graphs, bad_graphs, storage_name, options);
  objcbd_res := DB.DBA.SPARQL_DESC_DICT_OBJCBD_PHYSICAL (node_dict, consts, good_graphs, bad_graphs, storage_name, options);
again:
  triples := dict_destructive_list_rnd_keys (objcbd_res, 80000);
  if (0 = length (triples))
    return cbd_res;
  foreach (any triple in triples) do { dict_put (cbd_res, triple, 1); }
  goto again;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_DICT_OF_TRIPLES_TO_THREE_COLS (in dict any, in destructive integer := 0)
{
  declare ctr, len, max_batch_sz integer;
  declare editable_dict, triples, O any;
  declare S, P, O_DT, O_LANG varchar;
  declare O_IS_IRI, dt_twobyte, lang_twobyte integer;
  result_names (S, P, O);
  max_batch_sz := __min (sys_stat ('dc_max_batch_sz'), 1000000);
  editable_dict := null;
  if (not destructive and dict_size (dict) > max_batch_sz)
    editable_dict := dict_duplicate (dict);
next_batch:
  if (editable_dict is not null)
    {
      if (dict_size (editable_dict))
        triples := dict_destructive_list_rnd_keys (editable_dict, max_batch_sz);
      else
        return;
    }
  else
    {
      if (dict_size (dict))
        {
          if (dict_size (dict) > max_batch_sz)
            triples := dict_destructive_list_rnd_keys (dict, max_batch_sz);
          else
            {
              triples := dict_list_keys (dict, destructive);
              dict := null;
            }
        }
      else
        return;
    }
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
--  exec_result_names (vector (vector ('S', 182, 0, 4072, 1, 0, 1, 0, 0, 0, 0, 0), vector ('P', 182, 0, 4072, 1, 0, 1, 0, 0, 0, 0, 0), vector ('O', 125, 0, 2147483647, 1, 0, 0, 0, 0, 0, 0, 0)));
  len := length (triples);
  for (ctr := 0; ctr < len; ctr := ctr+1)
    {
      if (isiri_id (triples[ctr][0]))
        S := id_to_iri (triples[ctr][0]);
      else
        S := triples[ctr][0];

      if (isiri_id (triples[ctr][1]))
        P := id_to_iri (triples[ctr][1]);
      else
        P := triples[ctr][1];
      O := triples[ctr][2];
      if (isiri_id (O))
        {
          result (S, P, id_to_iri (O) --, 1, NULL, NULL
          );
        }
--      else if (is_rdf_box (O))
--        {
--          dt_twobyte := rdf_box_type (O);
--          O_DT := case (dt_twobyte) when 257 then NULL else coalesce (
--            (select id_to_iri (RDT_IID) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = dt_twobyte) ) end;
--          lang_twobyte := rdf_box_lang (O);
--          O_LANG := case (lang_twobyte) when 257 then NULL else coalesce (
--            (select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = lang_twobyte) ) end;
--          result (S, P, O, 0, O_DT, O_LANG);
--        }
      else if (S is not null and P is not null and O is not null)
        result (S, P, O --, 0, __xsd_type (O, NULL), NULL
        );
    }
  goto next_batch;
}
;

--!AWK PUBLIC
create procedure DB.DBA.RDF_DICT_OF_TRIPLES_TO_FOUR_COLS (in dict any, in destructive integer := 0)
{
  declare ctr, len integer;
  declare triples, O any;
  declare S, P, O_DT, O_LANG varchar;
  declare O_IS_IRI, dt_twobyte, lang_twobyte integer;
  triples := dict_list_keys (dict, destructive);
  DB.DBA.RDF_TRIPLES_BATCH_COMPLETE (triples);
  exec_result_names (vector (vector ('S', 182, 0, 4072, 1, 0, 1, 0, 0, 0, 0, 0), vector ('P', 182, 0, 4072, 1, 0, 1, 0, 0, 0, 0, 0), vector ('O', 182, 0, 2147483647, 1, 0, 0, 0, 0, 0, 0, 0), vector ('O_TYPE', 182, 0, 4072, 1, 0, 1, 0, 0, 0, 0, 0)));
  len := length (triples);
  for (ctr := 0; ctr < len; ctr := ctr+1)
    {
      if (isiri_id (triples[ctr][0]))
        S := id_to_iri (triples[ctr][0]);
      else
        S := triples[ctr][0];

      if (isiri_id (triples[ctr][1]))
        P := id_to_iri (triples[ctr][1]);
      else
        P := triples[ctr][1];
      O := triples[ctr][2];
      if (isiri_id (O))
        {
          result (S, P, id_to_iri (O), NULL);
        }
      else if (is_rdf_box (O))
        {
          dt_twobyte := rdf_box_type (O);
          O_DT := case (dt_twobyte) when 257 then NULL else coalesce (
            (select id_to_iri (RDT_IID) from DB.DBA.RDF_DATATYPE where RDT_TWOBYTE = dt_twobyte) ) end;
          lang_twobyte := rdf_box_lang (O);
          --O_LANG := case (lang_twobyte) when 257 then NULL else coalesce (
          --  (select RL_ID from DB.DBA.RDF_LANGUAGE where RL_TWOBYTE = lang_twobyte) ) end;
          result (S, P, O, coalesce (O_DT, ''));
        }
      else if (S is not null and P is not null and O is not null)
        result (S, P, O, coalesce (__xsd_type (O, NULL), ''));
    }
}
;

-----
-- Internal functions used in SQL generated by SPARQL compiler.
-- They will change frequently, do not try to use them in applications!

create function DB.DBA.RDF_TYPEMIN_OF_OBJ (in obj any) returns any
{
  declare tag integer;
  if (obj is null)
    return NULL;
  tag := __tag (obj);
  if (tag in (__tag of integer, __tag of double precision, __tag of numeric))
    return -3.40282347e+38;
  if (tag = __tag of datetime)
    return cast ('0101-01-01' as datetime);
  if (tag = __tag of rdf_box)
    return rdf_box ('', rdf_box_type (obj), 257, 0, 1);
  if (tag = (__tag of varchar))
    return '';
  return NULL; -- Nothing else can be compared hence no min.
}
;

create function DB.DBA.RDF_TYPEMAX_OF_OBJ (in obj any) returns any
{
  declare tag integer;
  if (obj is null)
    return NULL;
  tag := __tag (obj);
  if (tag in (__tag of integer, __tag of double precision, __tag of numeric))
    return 3.40282347e+38;
  if (tag = __tag of datetime)
    return cast ('9999-12-30' as datetime);
  if (tag = __tag of rdf_box)
    return rdf_box ('\377\377\377\377\377\377', rdf_box_type (obj), 257, 0, 1);
  if (tag = (__tag of varchar))
    return '\377\377\377\377\377\377';
  return NULL; -- Nothing else can be compared hence no max.
}
;

create function DB.DBA.RDF_IID_CMP (in obj1 any, in obj2 any) returns integer
{
  return NULL;
}
;

create function DB.DBA.RDF_OBJ_CMP (in obj1 any, in obj2 any) returns integer
{
  declare tag1, tag2 integer;
  if (obj1 is null or obj2 is null)
    return NULL;
  tag1 := __tag (obj1);
  tag2 := __tag (obj2);
  if (tag1 = __tag of rdf_box)
    {
      if (tag2 = __tag of rdf_box)
        {
          if (obj1 = obj2)
            return 0;
          if (rdf_box_type (obj1) <> rdf_box_type (obj2))
            return null;
          if (not rdf_box_is_complete (obj1))
            {
              declare id1 integer;
              declare full1 varchar;
              id1 := rdf_box_ro_id (obj1);
              if (__tag of XML = rdf_box_data_tag (obj1))
                return null;
              full1 := (select case (isnull (RO_LONG)) when 0 then blob_to_string (RO_LONG) else RO_VAL end from DB.DBA.RDF_OBJ where RO_ID = id1);
              if (full1 is null)
                signal ('RDFXX', sprintf ('Integrity violation in DB.DBA.RDF_OBJ_CMP, bad id %d', id1));
              rdf_box_set_data (obj1, full1, 1);
            }
          if (not rdf_box_is_complete (obj2))
            {
              declare id2 integer;
              declare full2 varchar;
              id2 := rdf_box_ro_id (obj2);
              if (__tag of XML = rdf_box_data_tag (obj2))
                return null;
              full2 := (select case (isnull (RO_LONG)) when 0 then blob_to_string (RO_LONG) else RO_VAL end from DB.DBA.RDF_OBJ where RO_ID = id2);
              if (full2 is null)
                signal ('RDFXX', sprintf ('Integrity violation in DB.DBA.RDF_OBJ_CMP, bad id %d', id2));
              rdf_box_set_data (obj2, full2, 1);
            }
          return rdf_box_strcmp (obj1, obj2);
        }
       return null;
     }
  if (tag1 in (__tag of integer, __tag of double precision, __tag of numeric))
    {
      if (tag2 in (__tag of integer, __tag of double precision, __tag of numeric))
        {
          if (obj1 <> obj2)
            {
              if (obj1 < obj2)
                return -1;
              return 1;
            }
          return 0;
        }
      return null;
    }
  if (tag1 = __tag of datetime)
    {
      if (tag2 = __tag of datetime)
        {
          if (obj1 <> obj2)
            {
              if (obj1 < obj2)
                return -1;
              return 1;
            }
          return 0;
        }
      return null;
    }
  return NULL;
}
;

