Overview

HTTPS SSH

Overview

Relational eXpression Map (rxm) is a terse database- and output-agnostic query language for generating structured documents.

Requirements

The software requirements include:

  • Java 8 - Development environment
  • Gradle - Automated build process

Quick Start

Download, compile, build, and parse the example using:

git clone https://bitbucket.org/djarvis/rxm.git
gradle -Dbeautify=true clean build javadoc run -Pargs=test/people.rxm

Usage

This section describes how to invoke the Java API to generate documents.

Basic

Generate an XML document using rxm. For example:

import com.whitemagicsoftware.rxm.RXM;

public class QueryTest {
  public static void main( String args[] ) throws Exception {
    RXM rxm = new RXM(
      "root   > people," +
      "person > person," +
      ".*,"
    );

    System.out.println( rxm.toString( getConnection() ) );
  }
}

Modules

A module is a set of rxm expressions that can be reused. For example:

import com.whitemagicsoftware.rxm.RXM;

public class QueryTest {
  public static void main( String args[] ) throws Exception {
    RXM rxm = new RXM(
      "module person," +
      "person > person," +
      ".*,"
    );

    rxm.add( "root > people, import person," );

    System.out.println( rxm.toString( getConnection(), "json" ) );
  }
}

Syntax

This section describes the rxm syntax, which involves:

  • a Map;
  • a Where clause;
  • namespace definitions; and
  • module definitions.

Map

An example map resembles:

root               > people,           # "root" keyword starts the document
person             > person,           # maps table context to a node
.age               > @age,             # @ maps a column to an attribute node
.first_name        > name/first,       # maps a column to a node
.last_name         > .../last,         # ... reuses the previous node's path
account.person_id +> person.person_id, # +> performs an INNER JOIN
account            > account,          # context is now "account" node
.id                > @id,              # account id attribute
^,                                     # pop stack to previous table context
address            > address,          # switch context to "address" node
.*,                                    # glob remaining columns
;                                      # Denotes optional WHERE clause

The example mapping produces:

<people>
  <person age="42">
    <name>
      <first>Charles</first>
      <last>Goldfarb</last>
    </name>
    <account id="123"/>
    <address>
      <id>456</id>
      <street>123 Query Lane</street>
      <city>San Francisco</city>
    </address>
  </person>
</people>

Any structured document format can be produced, including JSON.

Pops

Stack pops (^) switch context to a previous element. Multiple consecutive pop lines are permitted; extraneous pops are silently ignored: context never traverses beyond the root node.

Globs

A column demarcation followed by a Kleene star (.*) maps remaining columns automatically. Each node name corresponds directly to the entity column name.

Where

Example rxm expressions for SQL WHERE clauses include:

account.id  = :id      # : starts a named parameter
account.id <> :id      # inequality parameter comparison
account.id  = {:id, 1} # becomes IN set
account.id <> {:id, 1} # becomes NOT IN set
account.id  = null     # becomes IS NULL
account.id <> null     # becomes IS NOT NULL
account.id  = 'text'   # string equality comparison
account.id  = -42      # numeric equality comparison
account.id  < 42       # numeric less than comparison
account.id  > 42       # numeric greater than comparison
account.id <= 42       # numeric less than or equal to comparison
account.id >= 42       # numeric greater than or equal to comparison

Additionally, the && and || tokens perform logical and and or operations, respectively.

Namespace

Namespace syntax resembles:

root       > people(html, http://www.w3.org/TR/html4/),
person     > html:person,
person.id  > people:id( people, http://www.people.com ),

Module

Modules are defined using the module keyword. For example:

module person,
person             > person,
.first_name        > first,
.last_name         > name/last,
.age               > @age,

Modules are referenced using the import keyword. For example:

root               > people,
import person,
address            > address,
.*,

Modules may not contain a root element.

Rationale

The reasons for rxm include:

  • Eliminate repetitious code.
  • Decouple SQL statements from document output format.
  • Few databases are fully compliant with SQL/XML:2006.
  • Provide a database-agnostic mechanism to generate structured documents.
  • XQuery has limited open-source implementations for major RDBMS software.

Addendum

Review the JDBC documentation to understand how database connections are established.