[tmql-wg] A suggestion for TMQL

Rani Pinchuk Rani.Pinchuk@spaceapplications.com
Mon, 12 Jan 2004 15:08:07 +0100


--=-mNe/FXGZWB1BL8fZHI8G
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Dear all,

Please find attached a very early draft of a suggestion for TMQL. It is
presented as a "quasi-tutorial" because it is very far from being a
solid vision. 

The language is based very much on ideas from AsTMa* and Tolog, and also
from SQL and from the usual object oriented notation.

I will appreciate any feedback.

Thanks 

Rani
-- 
Rani Pinchuk
Software Engineer
Space Applications Services
Leuvensesteenweg, 325
B-1932 Zaventem
Belgium

Tel.: + 32 2 721 54 84
Fax.: + 32 2 721 54 44

http://www.spaceapplications.com 

--=-mNe/FXGZWB1BL8fZHI8G
Content-Disposition: attachment; filename=style.css
Content-Type: text/css; name=style.css; charset=UTF-8
Content-Transfer-Encoding: 7bit

BODY {
  background: white;
  color: black;
  font-family: arial,sans-serif;
  margin: 0;
  padding: 1ex;
}

TABLE {
  border-collapse: collapse;
  border-spacing: 0;
  border-width: 0;
  color: inherit;
}

IMG { border: 0; }
FORM { margin: 0; }
input { margin: 2px; }

A.fred {
  text-decoration: none;
}

A:link, A:visited {
  background: transparent;
  color: #006699;
}

A[href="#POD_ERRORS"] {
  background: transparent;
  color: #FF0000;
}

TD {
  margin: 0;
  padding: 0;
}

DIV {
  border-width: 0;
}

DT {
  margin-top: 1em;
}

.credits TD {
  padding: 0.5ex 2ex;
}

.huge {
  font-size: 32pt;
}

.s {
  background: #dddddd;
  color: inherit;
}

.s TD, .r TD {
  padding: 0.2ex 1ex;
  vertical-align: baseline;
}

TH {
  background: #bbbbbb;
  color: inherit;
  padding: 0.4ex 1ex;
  text-align: left;
}

TH A:link, TH A:visited {
  background: transparent;
  color: black;
}

.box {
  border: 1px solid #006699;
  margin: 1ex 0;
  padding: 0;
}

.distfiles TD {
  padding: 0 2ex 0 0;
  vertical-align: baseline;
}

.manifest TD {
  padding: 0 1ex;
  vertical-align: top;
}

.l1 {
  font-weight: bold;
}

.l2 {
  font-weight: normal;
}

.t1, .t2, .t3, .t4  {
  background: #006699;
  color: white;
}
.t4 {
  padding: 0.2ex 0.4ex;
}
.t1, .t2, .t3  {
  padding: 0.5ex 1ex;
}

/* IE does not support  .box>.t1  Grrr */
.box .t1, .box .t2, .box .t3 {
  margin: 0;
}

.t1 {
  font-size: 1.4em;
  font-weight: bold;
  text-align: center;
}

.t2 {
  font-size: 1.0em;
  font-weight: bold;
  text-align: left;
}

.t3 {
  font-size: 1.0em;
  font-weight: normal;
  text-align: left;
}

/* width: 100%; border: 0.1px solid #FFFFFF; */ /* NN4 hack */

.datecell {
  text-align: center;
  width: 17em;
}

.cell {
  padding: 0.2ex 1ex;
  text-align: left;
}

.label {
  background: #aaaaaa;
  color: black;
  font-weight: bold;
  padding: 0.2ex 1ex;
  text-align: right;
  white-space: nowrap;
  vertical-align: baseline;
}

.categories {
  border-bottom: 3px double #006699;
  margin-bottom: 1ex;
  padding-bottom: 1ex;
}

.categories TABLE {
  margin: auto;
}

.categories TD {
  padding: 0.5ex 1ex;
  vertical-align: baseline;
}

.path A {
  background: transparent;
  color: #006699;
  font-weight: bold;
}

.pages {
  background: #dddddd;
  color: #006699;
  padding: 0.2ex 0.4ex;
}

.path {
  background: #dddddd;
  border-bottom: 1px solid #006699;
  color: #006699;
 /*  font-size: 1.4em;*/
  margin: 1ex 0;
  padding: 0.5ex 1ex;
}

.menubar TD {
  background: #006699;
  color: white;
}

.menubar {
  background: #006699;
  color: white;
  margin: 1ex 0;
  padding: 1px;
}

.menubar .links     {
  background: transparent;
  color: white;
  padding: 0.2ex;
  text-align: left;
}

.menubar .searchbar {
  background: black;
  color: black;
  margin: 0px;
  padding: 2px;
  text-align: right;
}

A.m:link, A.m:visited {
  background: #006699;
  color: white;
  font: bold 10pt Arial,Helvetica,sans-serif;
text-decoration: none;
}

A.o:link, A.o:visited {
  background: #006699;
  color: #ccffcc;
  font: bold 10pt Arial,Helvetica,sans-serif;
text-decoration: none;
}

A.o:hover {
  background: transparent;
  color: #ff6600;
  text-decoration: underline;
}

A.m:hover {
  background: transparent;
  color: #ff6600;
  text-decoration: underline;
}

table.dlsip     {
  background: #dddddd;
  border: 0.4ex solid #dddddd;
}

PRE     {
  background: #eeeeee;
  border: 1px solid #888888;
  color: black;
  padding: 1em;
  white-space: pre;
}

H1      {
  background: transparent;
  color: #006699;
  font-size: +3;
}

H2      {
  background: transparent;
  color: #006699;
  font-size: +2;
}

H3      {
  background: transparent;
  color: #006699;
  font-size: +1;
}

IMG     {
  vertical-align: top;
}

.toc A  {
  text-decoration: none;
}

.toc LI {
  line-height: 1.2em;
  list-style-type: none;
}

.faq DT {
  font-size: 1.4em;
  font-weight: bold;
}

.chmenu {
  background: black;
  color: red;
  font: bold 1.1em Arial,Helvetica,sans-serif;
  margin: 1ex auto;
  padding: 0.5ex;
}

.chmenu TD {
  padding: 0.2ex 1ex;
}

.chmenu A:link, .chmenu A:visited  {
  background: transparent;
  color: white;
  text-decoration: none;
}

.chmenu A:hover {
  background: transparent;
  color: #ff6600;
  text-decoration: underline;
}

.column {
  padding: 0.5ex 1ex;
  vertical-align: top;
}

.datebar {
  margin: auto;
  width: 14em;
}

.date {
  background: transparent;
  color: #008000;
}


--=-mNe/FXGZWB1BL8fZHI8G
Content-Disposition: attachment; filename=toma.html
Content-Type: text/html; name=toma.html; charset=UTF-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Quasi-Tutorial for a Suggested TMQL</title>
<link rel="stylesheet" href="style.css" type="text/css" />
<link rev="made" href="mailto:rani@cpan.org" />
</head>

<body>

<p><a name="__index__"></a></p>
<!-- INDEX BEGIN -->

<ul>

	<li><a href="#quasitutorial_for_a_suggested_tmql">Quasi-Tutorial for a Suggested TMQL</a></li>
	<ul>

		<li><a href="#introduction">Introduction</a></li>
		<li><a href="#selection_by_topics">Selection by Topics</a></li>
		<ul>

			<li><a href="#topic_accessors">Topic Accessors</a></li>
			<li><a href="#simple_topic_selects">Simple Topic Selects</a></li>
			<li><a href="#the_returned_values">The Returned Values</a></li>
		</ul>

		<li><a href="#selection_by_associations">Selection by Associations</a></li>
		<li><a href="#learning_the_structure_of_the_topic_map">Learning the Structure of the Topic Map</a></li>
		<li><a href="#sorting_the_results">Sorting the Results</a></li>
		<li><a href="#author_&_copyright">Author &amp; Copyright</a></li>
	</ul>

</ul>
<!-- INDEX END -->

<hr />
<p>
</p>
<h1><a name="quasitutorial_for_a_suggested_tmql">Quasi-Tutorial for a Suggested TMQL</a></h1>
<p>
</p>
<h2><a name="introduction">Introduction</a></h2>
<p>Because the language that is shown below is very young, I
chose to present it as a quasi-tutorial. It contains many examples
but also some definition parts. However it is very far from being a
language specification.</p>
<p>I was hoping to uncover some difficulties in the language itself,
but also to generate a somewhat readable document that exposes
what I believe to be the strengths of the language.</p>
<p>It is my hope that this document will bring much feedback (hopefully
constructive :-), so the language can be developed to a more
consistent and powerful language.</p>
<p>The language below is strongly based on two other languages for
dealing with topic maps, <strong>tolog</strong> (of Ontopia) and <strong>AsTMa*</strong> (of
Robert Barta), and on SQL. 
I even used some examples from the presentation of <strong>tolog</strong> and the
tutorials of <strong>AsTMa*</strong>. 
Actually I see this effort as an integration effort among the ideas I
took from those languages.</p>
<p>When doing this pre-designing of the language (if it might be called
that way) I had in mind two targets:</p>
<dl>
<dt><strong><a name="item_power">Power</a></strong><br />
</dt>
<dd>
The language suppose to let the user to query most if not all the
queries he/she might have in mind.
</dd>
<p></p>
<dt><strong><a name="item_simplicity">Simplicity</a></strong><br />
</dt>
<dd>
In order for a new language to become popular, it must be easy to
learn and use.
</dd>
<p></p></dl>
<p>Usually, the above two targets contradict each other. However, they
guided me in making the following decisions:</p>
<ol>
<li></li>
Basing the syntax as much as possible on the well known SQL. This
simplified the learning process of the language at least for those who
know already SQL. SQL also deals with quite similar problems, so I
found good match between its structure and the needs.
<p></p>
<li></li>
No support for generating a presentation of the results in different
formats. Like SQL, it seems that this language will be embedded within
other more generic languages (Perl, Java, C etc). On the other hand
the number of formats and presentations that might be needed is
uncountable. Usually the host languages are already capable of
providing with formating/presentation means. Therefore I thought that
the loss of moving the formatting/presentation part out of the
language to the host language makes sense.
<p>In this context see also the Skin design pattern.</p>
<p>In the context of embedding the language in other language, see the 
Phrasebook design pattern.</p>
<p></p>
<li></li>
Treating topics as objects. As was said before, ``everything in a topic
map is a topic''. And a topic is a structure that holds various data
and references to data. Therefore it made sense to treat it as an
object. This implied the usage of accessors - in order to access the
elements of the object. I found that AsTMa= provides very clear
symbols that actually play as accessors (such as the scope character
@). The accessors found to be (in my humble opinion) a good thing, as
they let us ``navigate'' within the topic object and also to other topic
objects. Although the accessors might seem confusing at first, they
provide huge power in reasonable complexity.
<p></p></ol>
<p>Finally, I am well aware that the description below does not include
all the facilities that the language suppose to include. In many
places I assume knowledge of SQL by the reader. For example, I did
not include any built-in functions like the functions provided by
SQL. I also did not include macros or function definitions. I guess
that if the development of this language goes on, there should be a
careful process of choosing what of those functions and other
facilities should be adopted in the language.</p>
<p>
</p>
<h2><a name="selection_by_topics">Selection by Topics</a></h2>
<p>We start with the most simple case - selecting a certain topic from a
certain topic map:</p>
<pre>
  select $person from tm://my/topic/map where $person.id = 'Jonathan';</pre>
<p>We can see that we select from a certain topic map that is defined by
the <em>from</em> clause. Instead of doing that, we could choose to work
from now on with that topic map:</p>
<pre>
  use tm://my/topic/map;
  select $person where $person.id = 'Jonathan';</pre>
<p>We treat topics as objects that have id, base name etc. Dollar
followed by any alphanumeric character, underscore or hyphen is a 
variable that can hold a topic object.</p>
<p>
</p>
<h3><a name="topic_accessors">Topic Accessors</a></h3>
<p>We can access the topic elements as follows:</p>
<dl>
<dt><strong><a name="item_id">id</a></strong><br />
</dt>
<dd>
<em>.id</em> will give us the topic id:
</dd>
<dd>
<pre>
  $person.id</pre>
</dd>
<p></p>
<dt><strong><a name="item_base_name">base name</a></strong><br />
</dt>
<dd>
<em>.bn</em> will give us the topic base name:
</dd>
<dd>
<pre>
  $person.bn</pre>
</dd>
<dd>
<p>The @ character will let us alter the scope. So for example</p>
</dd>
<dd>
<pre>
  $city.bn@en</pre>
</dd>
<dd>
<p>will give us the base name of the city in the English scope.</p>
</dd>
<p></p>
<dt><strong><a name="item_type">type</a></strong><br />
</dt>
<dd>
A topic type (is-a relationship) is a topic by itself. We use the
<em>.type()</em> where inside the brackets we can place a number, or an
asterisk.
</dd>
<dd>
<p>The following refers to the type of $person topic:</p>
</dd>
<dd>
<pre>
  $person.type(0)</pre>
</dd>
<dd>
<p>We can refer to the type of the superclass of $person topic like this:</p>
</dd>
<dd>
<pre>
  $person.type(1)</pre>
</dd>
<dd>
<p>If we want to refer to the type of $person or the type of any
superclass of it, we can write:</p>
</dd>
<dd>
<pre>
  $person.type(*)</pre>
</dd>
<dd>
<p>We can also use the .. operator as follows:</p>
</dd>
<dd>
<pre>
  $person.type(0..1)</pre>
</dd>
<dd>
<p>The above refers to the type of $person and to the type of its type.</p>
</dd>
<dd>
<p>Note that because <em>.type()</em> returns a topic, we can use o it any of
the other accessors. For example, the following is the base name of
the type of $person:
</p>
</dd>
<dd>
<pre>

  $person.type(0).bn</pre>
</dd>
<p></p>
<dt><strong><a name="item_occurrence">occurrence</a></strong><br />
</dt>
<dd>
Occurrence can be a reference or in-line. We can refer to occurrence by
three accessors: <em>.oc</em>, <em>.ref</em> or <em>.in</em>. <em>.oc</em> refers to any
occurrence no matter if it is a reference or in-line. <em>.ref</em> refers
only to references and <em>.in</em> refers only to in-lines.
</dd>
<dd>
<p>Each occurrence might have a scope and a type. We refer to the scope by
using again the character @. We refer to the type by placing it inside
brackets just after the accessor. If we want to refer both to the
scope and to the type, we place always the brackets in the end.</p>
</dd>
<dd>
<p>Example:</p>
</dd>
<dd>
<pre>
  $person.in</pre>
</dd>
<dd>
<pre>
  $person.ref@en(cv)</pre>
</dd>
<dd>
<pre>
  $person.oc@en(birthdate)</pre>
</dd>
<dd>
<p>Note that the occurrence accessors return the data itself (so the
reference or the in-line). However, if another accessor is placed after
those accessors it will refer to the topic of the type of the
occurrence. So the following:</p>
</dd>
<dd>
<pre>
  $person.in(cv).bn</pre>
</dd>
<dd>
<p>might give us ``Curriculum Vitae'' which is the base name of the topic
with id 'cv'.</p>
</dd>
<p></p>
<dt><strong><a name="item_role">role</a></strong><br />
</dt>
<dd>
The accessors <em>.role()</em> implies that the element before them is an
association.
</dd>
<dd>
<pre>
   $a.role('location')</pre>
</dd>
<dd>
<p>implies that $a is an association that has a role which its id is
'location'. By writing the above we refer to the topic that plays that
role (so the topic that plays the role 'location').</p>
</dd>
<dd>
<p>Thus,</p>
</dd>
<dd>
<pre>
   $a.role('location').bn</pre>
</dd>
<dd>
<p>refers to the base name of the topic which plays the 'location' role.</p>
</dd>
<dd>
<p>In the same way,</p>
</dd>
<dd>
<pre>
   $a.role(*)</pre>
</dd>
<dd>
<p>implies that $a is an association that has whatever role and we
refer to the topic that plays that whatever role.</p>
</dd>
<dd>
<p>If we put a variable inside the brackets, we get the actual topic
that describe the role. So</p>
</dd>
<dd>
<pre>
   $a.role($b)</pre>
</dd>
<dd>
<p>is very similar to last example, but $b will be populated with the
topic object that describes that role. Later we will see how we use
this structure in order to restrict the roles of an yet unknown
association, or to find what are the roles of certain association.</p>
</dd>
<p></p></dl>
<p>
</p>
<h3><a name="simple_topic_selects">Simple Topic Selects</a></h3>
<ul>
<li></li>
Select a topic by its base name:
<pre>
    select $city where $city.bn@fr = 'Anvers'</pre>
<p></p>
<li></li>
Select a topic by its type base name
<pre>
    select $language where $lanaguge.type(0).bn = 'Object Oriented Language';</pre>
<pre>
    select $language where $language.type(0..1).bn = 'Computer Language';</pre>
<pre>
    select $language where $language.type(*).bn = 'Computer Language';</pre>
<p></p>
<li></li>
Select a topic by its occurrence
<pre>
    select $language where $language.ref = '<a href="http://www.perl.com">http://www.perl.com</a>'</pre>
<p></p>
<li></li>
Select a topic that has occurrence in English and that the French base
name of the type of that occurrence is 'ville'.
<p>Note that the moment we add an accessor after the <em>.oc</em>, <em>.ref</em> or
or <em>.in</em>, we refer to the topic map of the type of the occurrence and
not to the reference or the in-line data.</p>
<pre>
    select $city where $city.ref@en.bn@fr = 'ville'</pre>
<p></p>
<li></li>
Select a topic by the base name of its occurrence type
<pre>
    select $c where $c.oc.bn = 'City'</pre>
<p></p>
<li></li>
Select a topic by its in-line occurrence.
<pre>
    select $a where $a.in@en(city) =~ 'Antwerp';</pre>
<p>Here we select the in-line data that match the simple string 'Antwerp'. 
In general, the language supports regular expressions style Perl5. It
is done by using the operators =~ or !~ followed by the regular
expression. The first non white character after the operator will be
the delimiter of the regular expression. So the above could be written
also like:</p>
<pre>
    select $a where $a.in@en(city) =~ /Antwerp/;</pre>
<p>or:</p>
<pre>
    select $a where $a.in@en(city) =~ sAntwerps;</pre>
<p></p></ul>
<p>
</p>
<h3><a name="the_returned_values">The Returned Values</a></h3>
<p>In the examples above, we list only the actual topic objects as the
returned values. We can deal with those objects with whatever
programming interface we use.</p>
<p>However, we can also request only certain data out of the returned
value, again using the accessors. Examples:</p>
<ul>
<li></li>
Select the id of the topic:
<pre>
  select $bla.id ...</pre>
<p></p>
<li></li>
Select the base name of the topic:
<pre>
  select $bla.bn ...</pre>
<p></p>
<li></li>
Select the type of the topic (so select the superclass topic):
<pre>
  select $bla.type(0) ...</pre>
<p></p>
<li></li>
Select the base name of the type of the topic:
<pre>
  select $bla.type(0).bn ...</pre>
<p></p>
<li></li>
Select certain occurrence of the topic:
<pre>
  select $person.ref@en(homepage) ...</pre>
<p>It is not yet decided what happens if there is more then one occurrence 
that can be returned (in the example above - two or more homepages in
English). One possibility is to return one of them. Other possibility
is to return always an array, when occurrences is requested. Yet another
possibility is to forbid to request an occurrence all together - and to
demand that the occurrences will be retrieved via the topic object.</p>
<p></p></ul>
<p>
</p>
<h2><a name="selection_by_associations">Selection by Associations</a></h2>
<p>When we select by an association, we know the actual association, and
can refer to it by its id.</p>
<p>Let us examine an example. Select a person that was born in a city
that is called in Dutch 'Antwerpen':</p>
<pre>
    select $person where born_in.person = $person 
                     and born_in.location.bn@nl = 'Antwerpen'</pre>
<p>We can see that we use kind of accessors (role names) for an element
that is not a variable. 'born_in' in the example above, is the id of
an association. Any id of association followed by a dot and a role
name refers to the topic that plays that role in that association.</p>
<p>Because the structure &lt;association_id&gt;.&lt;role_name&gt; refers to a topic, 
we can use the usual accessors on that topic.</p>
<p>We can also see that we use <em>and</em> between two parts of the <em>where</em>
clause. We can use <em>and</em> and <em>or</em> and group them using brackets as
it is done in SQL.</p>
<p>Sometimes though we will need to refer to the same association more
then once in the same <em>where</em> clause. We can do that by using the
aliases clause. For example, the following query selects a part that 
is contained in other part that is contained in a spaceship.</p>
<pre>
    select $part
       aliases contains contains1, contains contains2
        where contains1.part = $part 
          and contains1.whole = contains2.part
          and contains2.whole.id = 'spaceship';</pre>
<p>We can also use the negation operator <em>not</em> or use the <em>!=</em>
operator. In the following example we get all the employees that are
not managers of the same company where they are employed:</p>
<pre>
  select $person, $company
     where (managed_by.manager != $person 
            and managed_by.company = $company)
       or  (employed_by.company = $company 
            and employed_by.employee = $person);</pre>
<p>This can be written also as:</p>
<pre>
  select $person, $company
     where not (managed_by.manager != $person
                and managed_by.company = $company)
           or  (employed_by.company = $company 
                and employed_by.employee = $person);</pre>
<p>Note that not always we need to mention all the association roles in a
query. Consider the following example which query who manages whatever
company:</p>
<pre>
  select $person where managed_by.manager = $person;</pre>
<p>Sometimes we might want to know how two or more topics might be
associated. We can do that by using the <em>.role()</em> accessor.</p>
<p>The following query selects an association that connects two topics -
one with base name 'Antwerpen' and the other with base name 'Jonathan'
(will return the association topic 'born_in').</p>
<p>Note that the usage of the accessor <em>.role()</em> implies that the element 
before it is an association. And remember also that when using
<em>.role()</em> we look at the topic that <strong>plays</strong> that role.</p>
<pre>
    select $a where $a.role(*).bn@nl = 'Antwerpen'
                and $a.role(*).bn = 'Jonathan';</pre>
<p>As we saw above, we can check what are the roles we found by placing 
a variable in the brackets of <em>.role()</em>:</p>
<pre>
    select $a, $r1, $r2 where $a.role($r1).bn@nl = 'Antwerpen'
                          and $a.role($r2).bn = 'Jonathan';</pre>
<p>In a similar way, we can restrict the roles we found:</p>
<pre>
    select $a where $a.role($r).bn@nl = 'New York'
                and $a.role(*).bn = 'Roni'
                and $r != 'state';</pre>
<p>We can also use scope over an association. We do that by using the
<em>@...</em> accessor over the object that represents the association. 
For example, if Jonathan is now in Antwerpen, he might have the
association located_in. Yet, that association will not be active under
the 'history' scope, and only born_in association will be returned:</p>
<pre>
    select $a where $a@history.role(*).bn@nl = 'Antwerpen'
                and $a@history.role(*).bn = 'Jonathan'</pre>
<p>Note that we could write the above also like this:</p>
<pre>
    select $a where $a@history.role(*).bn@nl = 'Antwerpen'
                and $a.role(*).bn = 'Jonathan'</pre>
<p>The moment a topic object got a scope, it will be kept. The following
on the other hand is an error:</p>
<pre>
    select $a where $a@history.role(*).bn@nl = 'Antwerpen'
                and $a@current.role(*).bn = 'Jonathan'    # an error !!</pre>
<p>The last examples bring us to the domain of introspective queries that
will be discussed next.</p>
<p>
</p>
<h2><a name="learning_the_structure_of_the_topic_map">Learning the Structure of the Topic Map</a></h2>
<p>Get all the topics:</p>
<pre>
    select $a where exists $a;</pre>
<p>We use the <em>exists</em> keyword that returns <em>true</em> if the expression
that follows it exists in the topic map.</p>
<p>Get all the associations:</p>
<pre>
    select $a where exists $a.role(*);</pre>
<p>Select all association types in this topic map:</p>
<pre>
    select distinct $a.type(0) where exists $a.role(*);</pre>
<p>Note that we use the <em>distinct</em> keyword. This keyword make sure that
each row of the result set is unique.</p>
<p>Select an association that has a role named 'location' or 'placed':</p>
<pre>
    select $a where exists $a.role('location') 
                 or exists $a.role('placed')</pre>
<p>Select all role types used in more than one association type:</p>
<pre>
    select distinct $a where exists $a.role($r)
                         and exists $b.role($r)
                         and $a != $b;</pre>
<p>Select all occurrence types:
</p>
<pre>

    select distinct $a where $b.oc.type(0) = $a;</pre>
<p>In order to query about scopes we first examine the scope character @.
Because a scope can be seen also as a topic, the string we place after 
the @ character is the id of the topic that represents the
scope. However, we can also place a variable after the scope
character. for example:</p>
<pre>
  $city.bn@$language</pre>
<p>However, we should be careful with precedence issues. For example, in</p>
<pre>
  $a@$scope.role(*).bn@nl</pre>
<p>it is not clear if</p>
<pre>
  .role(*).bn@nl</pre>
<p>is referring to $scope or to</p>
<pre>
  $a@$scope</pre>
<p>Actually, all the accessors refer to the immediate element from their
left. So probably we want to write the above as:</p>
<pre>
  ($a@$scope).role(*).bn@nl</pre>
<p>Using a variable after the scope character, we can select all scopes:</p>
<pre>
    select distinct $s where exists $t@$s
                          or exists $t.oc@$s
                          or exists $t.bn@$s;</pre>
<p>We can also select the scope of certain occurrence. For example
checking in which languages (so scopes, in that case) the CV of
certain person is available.</p>
<pre>
    select $s where $person.id = 'michael' 
                and exists $person.oc@$s('cv');</pre>
<p>
</p>
<h2><a name="sorting_the_results">Sorting the Results</a></h2>
<p>The results from the query are returned as rows of topic objects or
strings. We can sort the results by using the <em>order by</em> keyword. 
When we order by a topic object, its id will be taken for determining
the order. So:</p>
<pre>
   ... order by $t</pre>
<p>and</p>
<pre>
   ... order by $t.id</pre>
<p>is actually the same.</p>
<p>We can order by several variables, and we can reverse the order with
the keyword 'desc':</p>
<pre>
   ... order by $a, $b.bn@en decs, $c.type(0).bn;</pre>
<p>
</p>
<h2><a name="author_&_copyright">Author &amp; Copyright</a></h2>
<p>Rani Pinchuk, &lt;<a href="mailto:rp@spaceapplications.com">rp@spaceapplications.com</a>&gt;

</p>
<p>Copyright (c) 2003 Space Applications Services

</p>

</body>

</html>

--=-mNe/FXGZWB1BL8fZHI8G--