Debugger

any programming language, a debugger comes handy to prevent bugs during the development phase of an application.

XQuery is no exception to this rule. Zorba provides XQuery debugging capabilities through tree medias: a high level C++ API to embed and build front-end XQuery debuggers, a command-line tool called XQDB and the XQuery Development Toolkit project, an Eclipse plugin that supports XQuery.

XQDB, Command Line Tool

XQDB is integrated in Zorba's command line utility.

Command-line Options.

You need to use -c to start a query in debug mode.
zorba -c -q -f query.xq

With the port option (-p or --ports), you can specify the ports of the debugger server. By default it is 8000 for requests and 9000 for events. If you are using a firewall, you need to have these ports unblocked.

zorba -p 1111:2222 -c -q query.xq -f

Once XQDB is started, you can use the debugger client commands. There are basically divided in 3 categories: execution commands, breakpoints commands and data commands. Use help to get an overview.

    (xqdb) help
    List of available commands:
    Execution commands:
      run      -- Run the query.
      stop     -- Stop the query execution.
      quit     -- Quit Zorba debugger.
      continue -- Resume the query execution.
      status   -- Display the status of the query.
    Breakpoint commands:
      break    -- Set a breakpoint at the specified file and line.
      watch    -- Add watchpoint to the query
      list     -- Display the executed query line.
      clear    -- Clear breakpoints.
    Data commands:
      vars     -- List all variables that are in scope.
      eval     -- Evaluate an xquery expression and print its result.
    Zorba debugger:
      version  -- Display the version of Zorba engine and its debugger
      help     -- This help.

Execution Commands

Breakpoint Commands

Data Commands

Example Debug Session

Let's run a query in debug mode using the -c option:
$ zorba -c -f -q test_query.xq

You can use list all to print the query:

    (xqdb) list all
    1    <html>
    2      <head>
    3      <body>
    4      {
    5        for $act in <doc>
    6                      <ACT>
    7                        <TITLE>T</TITLE>
    8                        <SPEAKER>S1</SPEAKER>
    9                        <SPEAKER>S2</SPEAKER>
    10                      </ACT>
    11                    </doc>
    12        let $speakers := distinct-values($act//SPEAKER)
    13        return
    14          
    15            <h1>{$act/TITLE/text()}</h1>
    16            <ul>
    17            {
    18              for $speaker in $speakers
    19              return <li>{ $speaker }</li>
    20            }
    21            </ul>
    22          
    23      }
    24      </body>
    25    </html>
    26

Now we would like to set breakpoints in the query. In Zorba, the following expressions are breakable: For, Let and Return clauses; function calls and If/Else expressions. In the query above, we can set breakpoints at lines 5, 12, 13, 18 and 19:

Use b or break to set any of these breakpoints. For example,

    (xqdb) b 19
    Set breakpoint at line 19.

And r or run the query:

    (xqdb) r
    Launch the query
    19    return <li>{ $speaker }</li>

The query suspended at line 19. If you are lost, you can use the list command to see the neighboring lines. The expression at which the query has suspended is printed in bold face.

    (xqdb) list
    16    <ul>
    17    {
    18        for $speaker in $speakers
    19        return <li>{ $speaker }</li>
    20    }
    21    </ul>

Let's list all variables that are in scope with the vars command:

    (xqdb) vars
    Global variables:

    Local variables:
    $act [XS_UNTYPED]
    $speaker [XS_UNTYPED]
    $speakers [XS_UNTYPED]

You can use the print command to fetch the value of any of these variables. Note that you can execute arbitrary XQuery expressions having the in-scope variables being bound.

    (xqdb) p $act
    <ACT><TITLE>T</TITLE><SPEAKER>S1</SPEAKER><SPEAKER>S2</SPEAKER></ACT>
    (xqdb) p $act/TITLE/text()
    T

Now, we would like to remove the breakpoint and set a watchpoint whenever $speaker is equal to S2, i.e. the execution of the query only suspends if the boolean effective value of the condition evalutes to true.

    (xqdb) l b
    List of breakpoints and watchpoints:
    id:1    line:16
    (xqdb) delete 1
    Breakpoint 1 has been cleared.
    (xqdb) w $speaker=S2
    Set watchpoint: $speaker=S2

If you rerun the query, it will again break at line 16. However it will break only once, the single time where $speaker is equal to S2:

    (xqdb) r
    The query being debugged has already started.
    Reload query and start it from beginning? (y or n)
    y
    Launch the query
    19        return <li>{ $speaker }</li>
    (xqdb) p $speaker
    S2

Working with modules

Zorba debugger is aware of modules when you run a query. Use list to print the module. You can set breakpoints in the module with the following syntax: <filename>:<line number>="">:
(xqdb) list mymodule.xq
1 module namespace shopping = "http://www.zorba-xquery.com/shopping";
2 
3 declare function shopping:discount($price as xs:decimal?, $discount as xs:decimal?) as xs:decimal?
4 {
5   let $disc := ($price*$discount) div 100
6   return ($price - $disc)
7 };
8 
(xqdb) b mymodule.xq:5
(xqdb) r
let $disc:= ($price*$discount) div 100