# NXQL language definition (classic)

While the NXQL tutorial guides you through your first steps with NXQL, this document gives a more formal definition of the query capabilities of NXQL.

## Selecting plain objects <a href="#nxqllanguagedefinition-classic-selectingplainobjects" id="nxqllanguagedefinition-classic-selectingplainobjects"></a>

To select objects from an object table, use this form of the select statement:

```
(select ([field]...)
    (from [object]      
        (where [object] [filter])...))
```

Example:

```
(select (device_uid name)
    (from device))
```

## Selecting plain events <a href="#nxqllanguagedefinition-classic-selectingplainevents" id="nxqllanguagedefinition-classic-selectingplainevents"></a>

To select events from an event table, use this form of the select statement:

```
(select ([field]...)
    (from [event]       
        (where [event] [filter]...)... 
        (between datetime datetime))
    (order_by start_time [asc|desc]) // optional
    (limit number))
```

Example:

```
(select (start_time incoming_traffic outgoing_traffic)
    (from connection
        (where connection (ne status (enum established))   
                          (ne status (enum closed)))
        (where user (eq name (string "siesme@AONNETWORK"))) 
        (between now-7d now))
    (order_by start_time asc)
    (limit 100))
```

This query returns the start time and the incoming and outgoing traffic of the last 100 connections whose status is not equal to **established** or **closed**. That is, those connection with a status equal to **rejected**, **no host** or **no service**.

## Selecting events with decoration <a href="#nxqllanguagedefinition-classic-selectingeventswithdecoration" id="nxqllanguagedefinition-classic-selectingeventswithdecoration"></a>

To select events and their linked objects from a given event table, use the following form of the select statement. Note that there is no limit on the number of object tables that you can specify, as long as the object table is really linked to the events.

```
(select (([object|event] [field]...)...)
    (from ([event] [object]...)     
        (where [object|event] [filter]...)... 
        (between datetime datetime))
    (order_by start_time [asc|desc]) // optional
    (limit number))
```

Example:

```
(select ((connection (start_time)) (user (name)))
    (from (connection user)
        (where connection (ne status (enum established))   
                          (ne status (enum closed)))
        (between now-7d now))
    (order_by start_time desc)
    (limit 100))
```

The query returns the start time as well as the name of the user who initiated the last 100 connections whose status is not equal to **established** or **closed**, that is, with a status equal to **rejected**, **no host** or **no service**.

Another example:

```
(select ((user (name)) (device (name)))
    (from (connection user device)
        (where connection (ne status (enum established))   
                          (ne status (enum closed)))
        (between now-7d now))
    (order_by start_time desc)
    (limit 100))
```

This last query is identical to the previous one, except that it does not return the start time of the connection. Since these kinds of queries return one tuple per event, you may see a tuple with the same user name and device name appearing more than once in the results. These tuples are not really duplicated results, they actually belong to different connections although you may not see the difference due to the selected fields.

## Selecting objects with activity <a href="#nxqllanguagedefinition-classic-selectingobjectswithactivity" id="nxqllanguagedefinition-classic-selectingobjectswithactivity"></a>

To select objects linked to an activity (event), use the following select statement. The difference with the previous family of queries is that in the former you get one result tuple per event, while in this latter you get one result tuple per object.

```
(select ([field]...)
    (from [object] 
        (with [event]   
            (where [object|event] [filter]...)...
            (compute [aggregate]...)      // optional 
            (between datetime datetime))
        (having [filter on aggregate]...) // optional 
    (order_by [field] [asc|desc])         // optional
    (limit number))                       // optional
```

Example:

```
(select (name)
    (from device 
        (with execution
            (where binary (eq threat_level (enum high))) 
            (where binary (eq threat_level (enum intermediate)))
            (compute number_of_binaries)
            (between midnight-1d midnight)))
   (limit 100)
   (order_by name desc))
```

This query returns those devices which executed a binary whose threat level is **intermediate** or **high** yesterday. In addition, for each device, the query computes the number of distinct binaries matching the condition.

## Selecting two objects <a href="#nxqllanguagedefinition-classic-selectingtwoobjects" id="nxqllanguagedefinition-classic-selectingtwoobjects"></a>

To select unique pairs of objects linked to a given type of events, use the following select statement. Note that you can select no more than two object tables and that you cannot use any logic operator.

```
(select (([object] [field]...)...)
    (from ([object] [object])       
        (with [event]   
            (where [object|event] [filter]...)...
            (between datetime datetime))
    (limit number))
```

Example:

```
(select ((package name) (device name))
    (from (package device)
        (with package
            (where package (eq name (pattern "*Office*")))))
    (limit 100))
```

This query returns the unique pairs of devices and packages, where the name of the package contains the term **Office**.

## Updating objects <a href="#nxqllanguagedefinition-classic-updatingobjects" id="nxqllanguagedefinition-classic-updatingobjects"></a>

The update statement modifies categories or custom fields of an object table:

```
(update (set [field] ([type] [value]))...
    (from [object]
            (where [object] [filter]...)...))
```

To reset the value of a category or custom field, use the following update statement:

```
(update (set [field] nil)...
    (from [object]
            (where [object] [filter]...)...))
```

Examples:

```
(update (set #Location (enum Paris))
    (from device
        (where device (eq name (pattern "PA*")))))
```

This query updates the **Location** category of every device whose name begins with **PA** to **Paris**.

```
(update (set #Location nil)
    (from device
        (where device (eq name (pattern "PA*")))))
```

This query resets the **Location** category to *nil*. If an auto-tagging rule for the **Location** of devices is in force, the system will reset the value to the keyword of the matching auto-tagging rule.

## Filter <a href="#nxqllanguagedefinition-classic-filter" id="nxqllanguagedefinition-classic-filter"></a>

A filter is a condition on a field value. It has the following format:

```
([comparer] [field] ([type] [value]))
([comparer] [field] nil)
```

Where \[comparer] may have one of the following values:

* `eq`: equal. If the type of the field is an array of \[type], `eq` is true if at least one element of the array is equal to the value.
* `ne`: not equal. If the type of the field is an array of \[type], `ne` is true if no element of the array is equal to the value.
* `lt`: less than.
* `le`: less or equal.
* `gt`: greater than.
* `ge`: greater or equal.

Where \[type] may have one of the following values:

* `boolean`: A true or false value. Use keywords *true* and *false*, *yes* and *no*, or *1* and *0* as boolean literals.
* `string`: A string, If the string contains a space or a double-quote, it must be double-quoted and the quote duplicated, for example, `"Softy ""Visual"""`.
* `integer`: An integer number, for example `10`.
* `real`: A floating-point number, for example `12.56`.
* `enum`: A list of distinct values. As in the case of strings, if the value contains a space or a double-quote, it must be double-quoted.
* `second`: A natural number representing seconds, for example `60 seconds`.
* `millisecond`: A natural number representing milliseconds, for example `60000 milliseconds`.
* `microsecond`: A natural number representing microseconds, for example `60000000 microseconds`.
* `byte`: A natural number representing bytes, for example `1048576 bytes`.
* `ip_address`: An IP address, for example `172.16.10.5`.
* `ip_network`: An IP network, for example `172.16.0.0/16`.
* `mac_address`: A MAC address, for example `48:5b:39:18:70:bb`.
* `mhz`: A natural number representing mega hertz, for example `1600 mhz`.
* `sid`: A Windows security token, for example `S-1-5-21-3623811015-3361044348-30300820-1013`.
* `md5`: A MD5 hash code in hexadecimal format, for example `d41d8cd98f00b204e9800998ecf8427e`.
* `port`: A port type (udp/tcp) followed by a port number, for example `tcp/8080`.
* `version`: Four integers separated by a '.', for example `5.1.0.34`.
* `datetime`: A date and time in ISO 8601 format, for example `2014-06-12T13:54:51`.
* `time`: A time in ISO 8601 format, for example `13:54:51`.
* `date`: A date in ISO 8601 format, for example `2014-06-12`.
* `day`: A natural number representing days, for example `7 days`.
* `percent`: A fraction of 1 represented with 2 decimal places, for example `0.75`, or `75%` when displaying formatted output.
* `permill`: A fraction of 1 represented with 3 decimal places, for example `0.752`, or `75.2%` when displaying formatted output.

Use the special type `pattern` to match a string against a star pattern expression. Note that only the `eq` and `ne` operators are available for the type `pattern`, for example:

`(eq name (pattern "NY*"))`

Filters belonging to the same `where` clause are composed with a logic `AND`. For instance, the following `where` clause selects only devices whose name begins with NY and whose manufacturer is Dell:

```
(where device (eq name (pattern "NY*"))
(eq device_manufacturer (string "Dell"))
```

## Between <a href="#nxqllanguagedefinition-classic-between" id="nxqllanguagedefinition-classic-between"></a>

Date and time in a `between` clause is composed of a date time in ISO 8601 format or one of the following keywords:

* `now`: query time.
* `midnight`: last midnight.
* `sunday`: last Sunday at 00:00:00.
* `monday`: last Monday at 00:00:00.
* `tuesday`: last Tuesday at 00:00:00.
* `wednesday`: last Wednesday at 00:00:00.
* `thursday`: last Thursday at 00:00:00.
* `friday`: last Friday at 00:00:00.
* `saturday`: last Saturday at 00:00:00.

Optionally followed by a positive or negative integer and one of the following units:

* `w`: week, for example 7 days.
* `d`: day for example 24 hours.
* `h`: 1 hour.
* `m`: 1 minute.
* `s`: 1 second.

Examples:

* (between midnight now): today.
* (between midnight-1d midnight): yesterday.
* (between monday monday+24h): last monday.
* (between 2014-7-16\@14:00:00 2014-7-16\@15:00:00): on 2014-7-16 between 2 and 3 PM.
