Overview

About ql.io

Language Overview

Runtime Overview

Usage Overview

Getting Started

Prerequisites

Quick Start

Build an App

Examples

Build and Develop ql.io!

Writing Scripts

create table

select

insert into

update

delete

URI Templates

Data Formats

Variable References

Configuration

Script Routes

Monkey Patching

OAuth

Executing Scripts

HTTP Interface

WebSocket Interface

Engine API

Monitoring

Runtime Monitoring

References

Language Reference

URI Template Syntax Reference

Language Overview

ql.io's core consists of a domain-specific procedural-style language based on SQL and JSON. The language does not conform to SQL, but it borrows several concepts from it to keep the language familiar, and extends it to be applicable to HTTP APIs.

We use the term "HTTP API" as a generic reference to any HTTP addressable resource or service. Neither the language nor the runtime of ql.io require the resource or service to be RESTful.

This language currently has the following capabilities:

A script is a set of statements and comments. Statements must be declared in the order of dependencies.

There is no normative specification of the language yet. For now see railroad diagrams for details of the currently implemented syntax.

Comments are single-line, and start with --.

-- Welcome to ql.io

Assignments are optional for create table statements and scripts that have only one statement. Otherwise, statements must be terminated with semi-colons. In single-statement scripts, the return value of the script is implicit as for the script below.

select * from items

Statements can always be split into multiple lines by using carriage return. Line breaks and other white space are insignificant. Multi-statement scripts must always end with a return statement.

Assignment of statements and objects allow later statements in the script to refer to those variables.

items = select * from items;
return items;    

The assignment happens when the right hand side completes. The right hand side can be one of the following:

The predicate following a return can also be any of the above. The above script can be simplified to the following single line script.

return select * from items;

Since return is implicit in single statement scripts, this is the same as the following:

select * from items

Selections and projections are not limited to tables - they can applied to objects as well.

Try me
persons = [
  {"fname": "John","lname": "Doe", "address": {"city": "San Francisco"}},
  {"fname": "Jane","lname": "Doe", "address": {"city": "Bend"}}
];
return select woeid as woeid, centroid as centroid from yahoo.woe where
  loc in ("{persons.$..city}");

Execution of each statement can result in one or more HTTP requests. The table referenced in the statement specifies how to make the HTTP request to a resource. Tables are declared using create table statements. A create table statement provides all the information necessary to send an HTTP request and process the response.

A create table maps each of select, insert, update and delete statements into HTTP requests. The most common mapping is to map a select statement to GET.

create table geocoder
  on select get from "http://maps.googleapis.com/maps/api/geocode/json?address={address}&sensor=true"
  resultset "results";           

Since URIs for reads and writes could be different, a create table statement can map each of select, insert, update, and delete to a different HTTP resource with a different method.

create table bitly.shorten
  on insert get from "http://api.bitly.com/v3/shorten?login={^login}&apiKey={^apikey}&longUrl={^longUrl}&format={format}"
    using defaults apikey = "{config.bitly.apikey}", login = "{config.bitly.login}", format = "json"
    using patch 'shorten.js'
    resultset 'data.url'
  on select get from "http://api.bitly.com/v3/expand?login={^login}&apiKey={^apikey}&shortUrl={^shortUrl}&format={format}"
    using defaults apikey = "{config.bitly.apikey}", login = "{config.bitly.login}", format = "json"
    using patch 'shorten.js'
    resultset 'data.expand'

The mapping between statement types and HTTP methods is arbitrary. The language does not impose any particular mapping between SQL statement types and HTTP methods. For instance, the above script maps an insert into statement to method GET because bitly's API chose to use a GET for a write.

Idempotency and safety of a statement depends directly on the HTTP method used by the API.

The language uses select statements to select all (*) or particular fields from HTTP resources. The naming of fields follow the JSONPath convention.

select name.first, name.last, address.street from users where zip = 98074

The from clause of a select statement can either refer to a table or an object. See select statement for complete syntax and examples.

insert into statements are used to add data.

insert into bitly.shorten (longUrl) values ('http://ql.io/docs')

See insert statement for complete syntax and examples.

update and delete statements are not supported yet.

Statements can depend on other statements by way of using variable references. A variable reference is a JSONPath-style token in curly braces ({token}) in quoted (double or single) strings.

Try me
keyword = "ql.io";
web = select * from bing.search where q = "{keyword}";
tweets = select id as id, from_user_name as user_name, text as text
  from twitter.search where q = "ql.io";

return {
  "keyword": "{keyword}",
  "web": "{web}",
  "tweets": "{tweets}"
}

This script has four statements - the first one assigns a string value to a variable, and the second and third statements refer to that variable, and assign the results to two variables. The fourth statement refers to all three.

Variable references determine the order of execution of statements in a script.

The language also supports selecting from objects.

person = {
 "f": "Jon",
 "l": "Doe"
}
return select f from person;