UnQL Syntax Notes
  1. An UnQL database consists of zero or more collections.

    1. There might also be indices for improving performance. Indices can be specified explicitly. Or, some database engine implementations might deduce appropriate indices and create them automatically.

  2. Each collection is an unordered set of documents.

  3. A document is a unit of data that can be represented by JSON.

    1. The on-disk format and the client/server wire format may be something completely different, as long as it has at least as much expressive power as JSON. Again, that is an implementation detail. For the purposes of this document, the data will be assumed to be JSON.

    2. Note that a document need not be a JSON object. It might be a single integer, a single floating-point value, a single string, or an array. A document is not required to be contained in {...}, though that is the common case.

  4. The names of collections must consist of alphanumeric characters and underscores and must begin with an alphabetic character.

    1. Fields within JSON objects may be named arbitrarily, subject to the rules of JSON. There is no restriction on the use of "$" or "." characters in object field names. However, good style recommends following the same rules for object field names as are required for collection names.

  5. A new collection may be created using the CREATE COLLECTION statement as follows:

    CREATE COLLECTION collection-name
    1. If a collection with the same name already exists, the CREATE COLLECTION statement is a no-op. There is no need for an "IF NOT EXISTS" clause.

    2. A collection will be created automatically if an insert or upsert is made against a collection that does not previously exist.

  6. A collection can be removed from a database using the DROP COLLECTION statement as follows:

    DROP COLLECTION collection-name
    1. If no such collection exists, the DROP COLLECTION statement is a no-op. There is no need for an "IF EXISTS" clause.

    2. Dropping a collection removes all documents that were part of that collection.

    3. Dropping a collection removes any indices associated with that collection.

    4. If all documents are removed from a collection and the collection does not have any user-defined indices, then the database engine may drop the collection automatically.

  7. Within a document, floating point values are preserved to an accuracy of at least 15 significant digits.

    1. Overflows and divisions by zero involving floating point values do not raise errors but rather return NaN, +Inf, or -Inf, as appropriate.

  8. Integers are represented with an implementation-defined precision.

    1. The implementation defined precision must be at least 64 bits and it is recommended to be at least 10Kb.

  9. Implementations may publish well-define limits on the length of any document.

    1. The maximum document length should be measured in megabytes or greater.

  10. Implementations may publish well-define limits on the length of any string.

    1. It is recommended that the length of a string be limited only by the limit on the length of a document. In other words, a maximum-size document that consist of only a string should be allowed.

  11. Binary data can be represented as strings with appropriate escapes for backslash, double-quote, and zero characters.

  12. Documents may be added to a collection using an INSERT statement:

    INSERT INTO collection-name VALUE expression
    1. The named collection is created automatically if it does not previously exist.

    2. The expression can be any javascript-style expression that evaluates to a single JSON value.

      • Object field names need not appear in double-quotes, as long as they contain only alphanumeric characters and underscores and begin with either an alphabetic character or an underscore.
      • Values can involve arithmetic expressions which are resolved before th results is stored in the database. For example: 5+9 is stored as 14.
      • The expression is usually a JSON object, but can also be a floating-point value, and integer, a string, or an array.

    3. An expression may also contain subqueries of the form "(SELECT ...)". Subqueries may be correlated.

  13. Documents may also be inserted as the result of a query:

    INSERT INTO collection-name query
    1. The named collection is created automatically if it does not previously exist.

    2. The syntax for query is described in the sequal. Basically, any content that can be requested from the database by the application can also be fed back into a collection using this style of INSERT statement.

  14. Documents may be removed from a collection using the DELETE statement:

    DELETE FROM collection-name WHERE expression
    1. Only those documents for which expression is true are removed from the collection.

      • A "null" value is not true.
      • A numeric value other than 0 or 0.0 is true.
      • A string value is not true unless it can be interpreted as a non-zero numeric value.
      • Arrays and objects are not true.

    2. The WHERE clause is optional. If the WHERE clause is omitted, all documents are removed from the collection. If there are no explicit indices on the collection, this might also cause the collection to be automatically dropped.

  15. Documents can be changed using the UPDATE statement:

    UPDATE collection-name SET changes WHERE expression
      ELSE INSERT VALUE expression
    1. The changes is a comma-separated list of "field=expression" statements that cause JSON object fields to taken on new values. New fields are created within the JSON object as necessary.

    2. The option WHERE clause controls which documents in the collection are updated. If the WHERE clause is omitted, all documents are updated.

    3. The optional ELSE INSERT clause causes the JSON value from the following expression to be inserted into the collection if the WHERE clause matched no terms in the collection. The ELSE INSERT clause is used to implement "upsert".

  16. Query syntax is as follows:

    SELECT optional-expression
      FROM data-sources
     WHERE expression
     GROUP BY expression-list
    HAVING expression
     ORDER BY expression-list
     LIMIT expression OFFSET expression
    1. The data-source field specifies one or more collections. A join is performed if two or more collections are specified.

    2. The optional WHERE, GROUP BY, HAVING, ORDER BY, LIMIT and OFFSET clauses work as in SQL.

    3. The optional-expression defines a JSON object that is to be returned by the query. If omitted, the document of the first collection in the FROM clause is returned.

  17. Within expressions, supported operators are:

    Logical Operators: &&   ||   !
    Arithmetic Operators (+ also does string concat.): -   +   *   /   %
    Comparison Operators: ==   <   <=   >   >=   !=   <>
    Bitwise Operators: &   |   ~   <<   >>

    In all cases, we strive for compatibility with Javascript.