Skip to main content

Hello World

First steps with MonetDB/XQuery and mclient

Of course, each language needs an 'Hello World' example. So does XQuery. But first, let's make sure our MonetDB/XQuery server is running, and we can query it.

Starting Mserver

The first task is to start the MonetDB Server. On Windows platforms this is done by clicking:

Start -> Programs -> MonetDB -> MonetDB XQuery Server 

If you are a Linux user, you should type something like:

  Mserver --dbinit="module(pathfinder);"

More information in the Reference Manual.

Using mclient

The mclient utility is used to send queries to MonetDB/XQuery. On Windows, double-clicking a .xq XQuery file will send it to MonetDB/XQuery, which is supposed to be running on the local machine then.

You can also start an interactive session:

MonetDB XQuery Client

On Linux, to execute an XQuery query example.xq you must type:

  mclient -lx

You can type XQuery queries that span multiple lines; finish them by typing

<>

(or CTRL-D on Linux resp. CTRL-Z on Windows) on a new (empty) line at the

more>

prompt. The mclient utility has command-line history (use the arrow-up to re-use past commands). The manual page can be found in theReference Manual.

 

On a different machine: the default security settings prohibit access to MonetDB/XQuery from another machine. You can lift that restriction by starting Mserver with the following command:

  Mserver --dbinit="module(pathfinder);" --set mapi_open=yes

Be aware that this opens up access to the database from anywhere in the world! Note that MonetDB version 4 does not yet have a user/password mechanism, so you should at least make sure that the TCP/IP mapi_port (50000) is blocked by your firewall. It should be, normally. You can change the default values of MonetDB options such as mapi_open and mapi_port in the MonetDB.conf file.

Hello World

Below you can find a list of queries which will each return the line: <example>Hello World</example>

example1: Any piece of XML is also a valid XQuery query! So this is the simplest HelloWorld query:

  <example>Hello World</example>

Using XML in an XQuery is called element construction because each constructed XML node gets a new unique identity.

example2: Here we construct an <example> element node with a text node child "Hello World". The string value is created by concatenating "Hello", " " and "World":

  <example> { fn:concat("Hello"," ","World") } </example>

This demonstrates the use of parentheses { } inside element construction to embed XQuery expressions. The built-in function fn:concat()

used here is one of the few XQuery functions that accept any number of arguments (the fn: namespace is default and can be omitted).

example3: All XQuery expression return value sequences. In element construction, a (comma-separated) sequence of values is automatically separated with a single space:

  <example>{ "Hello",'World' }</example>

Notice that XQuery allows both "" and '' string quotes.

example4: Here we also use element construction, but enclose the text in an additional <doc> element. The text value of that node can be retrieved using /text() XPath child step:

  <example> { 
    <doc>Hello World</doc>/text() 
  } </example>

When adding an additional <msg> element, we need to extend the XPath expression by a /msg child step:

  <example> { 
    <doc><msg>Hello World</msg></doc>/msg/text()    
  } </example>

An alternative syntax for /msg/text() is /child::msg/child::text()

example5: or alternatively using a single // descendant step with text() test:

  <example> { 
    <doc>Hello World</doc>//text()
  } </example>
  <example> { 
    <doc><msg>Hello World</msg></doc>//text()
  } </example>

An alternative syntax for //text() is /descendant::text()

example6: This demonstrates getting an attribute value with an attribute step:

  <example> { 
     text { <doc test="Hello World"/>/@test }
  } </example>

An alternative syntax for /@test() is /attribute::test

Querying XML documents with FLWR ("Flower") Statements

The above statements are expressions in the XPath language, which is a subset of the XQuery language. The XQuery language adds the use of 'for', 'let', 'where', 'return'-statements (FLWR, pronounce as 'Flower').

example7: Here we iterate over ('Hello','my','World') but exclude 'my' such that this query becomes equivalent to example 3:

  <example> { 
    for $t in ('Hello','my','World')
    where $t != 'my'
    return   $t 
  } </example>

example8: A quite complicated example that shows the use of let variable bindings and XPath expressions with [] predicates:

  for $t in ( <doc>
    <greet kind="informal">Hi </greet>
    <greet kind="casual">Hello </greet>
    <location kind="global">World</location>
    <location kind="local">Amsterdam</location>
  </doc> )
  let $x := $t/greet[@kind="casual"]/text()
  let $y := $t/location[@kind="global"]/text()
  return <example> { $x, $y } </example>

Output Formats

The -f <mode> command-line option in mclient allows to adapt the output formatting of XQuery results. It can also be changed using the \f <mode> interactive command in mclient . The <mode> is explained in detail in the  manual .

dm

In the default dm mode, the answer to all our hello world queries was:

<example>Hello World</example>

xml

The xml mode (i.e. type \f xml in mclient ) guarantees that all XQuery queries produce in a valid XML result. It does so by placing a <?xml version='1.0' encoding='UTF-8'?> header and an enclosing <XQueryResult> root node on top of the result:

<?xml version='1.0' encoding='UTF-8'?>
<XQueryResult>
<example>Hello World</example>
</XQueryResult>

xml-root-XYZ

The element name <XQueryResult> is arbitrarily chosen, and an application may want a to use a different one, e.g. <XXX/> by using the submode -root-XXX (i.e. type \f xml-root-XXX in mclient ):

<?xml version='1.0' encoding='UTF-8'?>
<XXX>
<example>Hello World</example>
</XXX>

xml-noheader-noroot

Both header and root-node can be omitted by the sub-modes -noheader and -noroot respectively (or combined, as here):

<example>Hello World</example>

xml-typed

The xml-typed mode ensures that all type information is preserved in the result XML, enclosing all atomic values in <result:atomic-value> and all sequences (including the overall query result) in a <result:sequence> element:

<?xml version='1.0' encoding='UTF-8'?>
<result:sequence
 xmlns:result="http://monetdb.cwi.nl/XQuery/results"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <result:element><example>Hello World</example></result:element>
</result:sequence>

none

Finally, the none mode suppresses any output. This mode is mostly useful for performance measurements, if one wants to exclude the result serialization time.

Timing

You can investigate the performance of mclient queries in some detail by switching on timing using the mclient -lx -t

command-line switch. Also, while in an interactive mclient session, timing can be toggled on or off with the \t command. The results produced can look like this:

<example>Hello World</example>

Trans      18.000 msec
Shred       0.000 msec
Query       5.000 msec
Print       0.000 msec
Timer      24.436 msec

Here, Trans is the time the Pathfinder compiler takes to translate and optimize the XQuery query into a MonetDB query plan. Note that translation time can be eliminated by using Prepared Queries.

The Shred time is all time that was needed to retrieve XML document not yet in the database and add them.

The Query time is the core query execution time.

The Print time is all time spent on serializing the result.

Finally, the Timer time is the total waiting time at the client side for the answer. If you subtract all other times from this, which are measured at the server side, the difference represents all time spent on network communication between mclient and Mserver.