# v1.0.3 Contextual SQL based metrics

***

{% hint style="success" %}
Version 1.0.3
{% endhint %}

## Overview

This release brings a number of new features, bug fixes, optimisations and general usability enhancements. The focus of this release has been providing a solid foundation for in-memory SQL support, metrics processing and multi language scripting support.

<figure><img src="https://cdn-images-1.medium.com/max/1600/1*BQx2hq1LzS5yt5VwTap84g.jpeg" alt=""><figcaption></figcaption></figure>

## Features

* SQL Support
* Metrics engine
* Dynamic Rest APIs
* Multi-Language scripting support
* Parquet support
* Database publisher
* Documentation

***

## **SQL Support**

Joule ships with an embedded in-memory modern SQL engine, [DuckDB](https://duckdb.org/). This is used to capture events flowing through the processing pipeline along with supporting the metrics engine implementation.

* SQL Tap for event capture and storage
* Metrics Engine to provide SQL analytics
* Rest API provides data access and export functions

## **Metrics Engine**

The metrics engine computes SQL-defined metrics using events stored by the SQL Tap and scheduled using a runtime policy.

```

metrics engine:
  runtime policy:
    frequency: 1
    startup delay: 2
    time unit: MINUTES
​
  foreach metric compute:
    metrics:
      - name: BidMovingAverage
          metric key: symbol
          table definition: standardQuoteAnalyticsStream.BidMovingAverage 
                           (symbol VARCHAR, avg_bid_min FLOAT, 
                            avg_bid_avg FLOAT,avg_bid_max FLOAT)
          query:
            SELECT symbol,
            MIN(bid) AS 'avg_bid_min',
            AVG(bid) AS 'avg_bid_avg',
            MAX(bid) AS 'avg_bid_max'
            FROM standardQuoteAnalyticsStream.quote
            WHERE
            ingestTime >= date_trunc('minutes',now() - INTERVAL 2 MINUTES) AND ingestTime <= date_trunc('minutes',now())
            GROUP BY symbol
            ORDER BY 1;
          truncate on start: true
          compaction policy:
            frequency: 8
            time unit: HOURS
```

## **Dynamic Rest APIs**

All SQL tables created by a Joule process are accessible through a well-defined Rest API.

<figure><img src="https://cdn-images-1.medium.com/max/1600/1*7vyjmF4g4fiRIm_pNaq4zQ.png" alt=""><figcaption></figcaption></figure>

## **Multi-Language scripting support**

Joule provides a flexible scripting processor implemented using [GraalVM](https://www.graalvm.org/22.0/docs/getting-started/). This enables the developer to integrate code written using Python, Node.JS, R, Javascript and Ruby within a streaming context.

## **Parquet import/export**

Data can be stored within the Joule process and can be exported as Parquet files for further analytics use cases. Also, Parquet files can be imported into the Joule process to drive user-defined functionality.

```
initialisation:
  sql import:
    schema: banking
    parquet:
      - 
        table: fxrates
        asView: false
        files: [ 'fxrates.parquet' ]
        drop table: true
        index:
          fields: [ 'ccy' ]
          unique: false
```

## **Database publisher**

Publisher transport persists processed events to a configured SQL database and table. The insert statement is dynamically generated from an event, attribute names and types need to match the table definition.

This feature is an idea for offline analytics, business reporting, dashboards and process testing.

## **Documentation**

Joule is now shipping with online documentation.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fractalworks.io/joule/product-updates/release-notes/v1.0.3-contextual-sql-based-metrics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
