---
layout: 2ColLeft
title: GQL Documentation
sidebar: nav.html
---

The Google Query Language (GQL) interface provides an alternative method for accessing data.
The version of GQL implemented here is based on the Google Visualization API Query Language
(https://developers.google.com/chart/interactive/docs/querylanguage).
The syntax of GQL queries should be familiar to those who have used SQL,
but the capabilities of GQL are much more limited.

GQL queries are performed by passing a query object to the gql method along with a callback.
Callbacks are in the node.js idiom of `function(err, data)` Where the first argument will be undefined
unless there is an error, and further arguments specify the result.
Note that only identifiers and string literals are case-sensitive.

### Language Syntax

 * [Select](#select)
 * [Where](#where)
 * [Group By](#groupBy)
 * [Pivot](#pivot)
 * [Label](#label)
 * [Functions](#functions)
  * [Aggregation Functions](#aggregation_functions)
  * [Scalar Functions](#scalar_functions)
  * [Arithmetic Operators](#arithmetic_operators)
 * [Miscellaneous](#miscellaneous)
  * [Literals](#literals)
  * [Identifiers](#identifiers)
  * [Reserved Words](#reserved_words)

## Perform a Query

    db.gql(query, [options], [callback])

Although only the query is mandatory, the callback is required to access the query result.
Currently no query options are implemented.

    const pouchdb;
    PouchDB('idb://test', function(err, db) {
       pouchdb = db;
      // Use pouchdb to call further functions
        db.gql({select: "*", where: "type='Fire' and name is not null"}, function(err, result){
            if(!err){
            // Use the results of the query here
            }
          }
    })

## Select

    db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback)

Select returns an object for each document in the database (unless limited by another clause).
Each of these objects will be populated with the properties specified in the select clause.
Arithmetic operators, aggregation functions, and scalar functions are all fair game.
Properties that are missing from an object in the database are assigned null.

With these documents in the database

    {name!: "pencil", price: 2, discount: 0.7, vendor: "store1"},
    {name!: "pen", price:3, discount: 2, vendor: "store2"}

The above query will return

    {name!: "pen", price - discount: 1, upper(vendor): "STORE2"},
    {name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"}


## Where

    db.gql({select: "*", where: "type='Fire' and name is not null"}, callback)

Where allows filtering of the objects that are passed to the select clause.  In this way, unwanted documents
can be excluded from the query result.  The where clause is composed of conditions which are joined by the
logical operators AND and OR.  An additional operator, NOT, provides negation.

Comparison operators can be used in conditions to perform comparisons.  The supported comparison operators are
<=, <, >, >=, !=, and <>.  != and <> are equivalent.  Null is treated slightly differently; to check if
something is null IS NULL is used.  To check if something is not null, IS NOT NULL is used.

With these documents in the database

    {name: "charmander", type: "Fire"},
    {type: "Fire", attack:"tail whip"},
    {name: "charizard", type: "Fire", attack:"slash"}

The above query will return

    {_id: "0D715E2C-CEDD-46B4-A060-9C9C290BEBE8", _rev: "1-71d1e0f8ab00cf432306890a4116602b",
    attack: "slash", name: "charizard", type: "Fire"},
    {_id: "3153F94B-0568-4D4C-BFA1-83EDF6185915" _rev: "1-d24f7405c5a63943391eaff9a260139c",
    name: "charmander", type: "Fire"}

Note the inclusion of the \_rev and \_id fields.  This is the result of using 'select \*' instead of naming the
desired fields explicitly.

## Group By

    db.gql({select: "max(charizard), charmeleon", groupBy: "charmeleon"}, callback)

Group by creates one object for each unique combination of values in the group by clause. For the query above,
if every document in the database had the value "Level 22" for the property "charmeleon", only a single
object would be generated.

If a group by clause is present, every identifier in the select clause must either be the argument of an
aggregation function or present in the group by clause.  Otherwise, the composite objects formed by the group by
clause could have multiple values for some identifiers.

With these documents in the database

    {charizard: 50, charmander: 24, charmeleon: 2, haunter:true},
    {charizard: 40, charmeleon: 2, charmander: 50},
    {charizard: 7, charmeleon: 20, charmander: 15}

The above query will return

    {charmeleon: 2, max(charizard): 50}
    {charmeleon: 20, max(charizard): 7}

## Pivot

     db.gql({select: "max(charizard)", pivot: "charmeleon"}, callback)

Pivot is essentially group by for properties.  Each distinct value in the pivot clause gets its own property.
Unless used with group by, the result will have only a single document.

The same restriction for group by applies here; every identifier in the select clause must either be the
argument of an aggregation function or preset in the group by clause.  Additionally, identifiers in the pivot
clause may not be used in the group by clause.

Note that using pivot will generate novel property names.  See below for an example.

With these documents in the database

    {charizard: 50, charmeleon: "hello"},
    {charizard: 40, charmeleon: "hello"},
    {charizard: 7, charmeleon: "world", charmander: 15}

The above query will return

    {'hello max(charizard)': 50, 'world max(charizard)': 7}

## Label

     db.gql({select: 'upper(dept), charizard',
     label: "upper(dept) 'Department', charizard 'Maximum Charizard!'"}, callback)

Label is used to transform cryptic identifiers into something that can be displayed directly to the end user.
Items in the label clause can be identifiers, aggregation functions, scalar functions, or operators.  The label
clause is composed of any number of statement label pairs, where the statement corresponds to some statement in
the select clause and the label is a string literal.

With these documents in the database

    {charizard: 50, dept: "eng", lunch:"2"},
    {charizard: 40, lunch: "1", dept: "market"},·
    {charizard: 99, dept: "eng", lunch: 1},
    {charizard: 7, dept: "eng", lunch: 2}

The above query will return

    {Department: "ENG", Maximum Charizard!: 7},
    {Department: "ENG", Maximum Charizard!: 99},
    {Department: "MARKET", Maximum Charizard!: 40},
    {Department: "ENG", Maximum Charizard!: 50}

## Functions

GQL contains a number of operators and functions that can operate on retrieved documents.

### Aggregation Functions

    db.gql({select: "max(charizard), min(charizard), average(charizard), count(charizard), sum(charizard)"},
    callback)

The currently supported aggregation functions are avg, count, max, min, and sum.  Each of these takes a single
statement as an argument.  A statement can be composed of one or more identifiers joined by operators.
Avg and sum expect their arguments to evaluate to numbers; the other aggregators will accept any type of input.
Aggregation functions operate on entire identifiers, returning only a single property. Aggregation functions
may only appear in the select and label clauses.

With these documents in the database

    {charizard: 50},
    {charizard: 40},
    {charizard: 7}

The above query will return

    {average(charizard): 32.333333333333336, count(charizard): 3, max(charizard): 50,
    min(charizard): 7, sum(charizard): 97}

### Scalar Functions

    db.gql({select: "`name!`, price-discount, upper(vendor)"}, callback)

Currently only two scalar functions are supported, upper and lower.  These change the characters in their inputs
to uppercase and lowercase respectively.  Unlike aggregator functions, scalar functions take only a single
identifier as their input.  Scalar functions may only appear in the select and label clauses.

With these documents in the database

    {name!: "pencil", price: 2, discount: 0.7, vendor: "store1"},
    {name!: "pen", price:3, discount: 2, vendor: "store2"}

The above query will return

    {name!: "pen", price - discount: 1, upper(vendor): "STORE2"},
    {name!: "pencil", price - discount: 1.3, upper(vendor): "STORE1"}


### Arithmetic Operators

    db.gql({select: "*", where: "charizard <=charmander * charmeleon + 2 and (charmander - 7 !=  24/3)"},
    callback)

Arithmetic operators are used to perform basic math on the values from documents.  Their arguments must be
numbers.  Arithmetic operators may only appear in the select, label, and where clauses.  The arguments are
implicitly upcast to floats if necessary. The supported arithmetic operators are:

* Addition: '+'
* Subtraction: '-'
* Multiplication: '\*'
* Division: '/'


With these documents in the database

    {charizard: 50, charmander: 24, charmeleon: 2, haunter:true},
    {charizard: 40, charmeleon: .5, charmander: 50},
    {charizard: 7, charmeleon: 20, charmander: 15}

The above query will return

    {charizard: 50, charmander: 24, charmeleon: 2, haunter: true}

## Miscellaneous

Some features that are not covered in other sections.

### Literals

Literals are used for comparison or arithmetic.  These are the supported literals:

* string: Any characters surrounded by single or double quotes
* number: Numbers in regular decimal form.  They may have a single period, a single negative sign, and no commas
* boolean: Either true or false

### Identifiers

Identifiers correspond to the properties of documents in the database.  There are strict rules governing the
way that identifiers can be expressed in queries.  If your identifier has spaces, is a reserved word, contains
any characters that are not letters or numbers or underscores, or starts with a digit, it must be surrounded
by backquotes \(\`identifier\`\).

### Reserved Words

This is the current list of reserved words.  Because the GQL implementation is currently under development,
this list is likely to grow over time.

    and
    asc
    by
    date
    datetime
    desc
    false
    format
    group
    label
    limit
    not
    offset
    options
    or
    order
    pivot
    select
    timeofday
    timestamp
    true
    where
