---
title: "Functions"
sidebarTitle: "Functions"
description: "Where to find each kind of function, and the dialect version they come from."
icon: function
keywords: ["functions", "datafusion", "scalar", "aggregate", "window", "fts", "table function"]
---
Enterprise [SQL runs on a deployment.](/sql)
LanceDB executes SQL with [Apache DataFusion](https://datafusion.apache.org),
currently **version 54**. The function set is DataFusion's default registration
plus what Lance adds.
| | |
| --- | --- |
| [Scalar functions](/sql/scalar-functions) | per row — math, string, regex, date/time, array, struct, JSON |
| [Aggregate functions](/sql/dql/aggregation#functions) | per group — `count`, `sum`, statistical, approximate |
| [Window functions](/sql/dql/window#functions) | per window — ranking, offset, running aggregates |
| [Table functions](#table-functions) | produce a relation rather than a value |
Function availability is version-specific. DataFusion adds functions in most
releases, so one documented on `main` may not exist in 54. When a name is not
recognised, check it against the reference for that version before assuming a
bug.
## Table functions {#table-functions}
A table function appears in `FROM` and produces a relation, which is what lets
it return columns a scalar function has nowhere to put.
### `fts(table, query)` {#fts}
Full-text search is a table function rather than a predicate, because it
produces relevance alongside the matching rows. The following query assumes
`my_docs` has `id` and `text` columns and a full-text index on `text`; see the
[setup example](/sql/dql/fts#setup):
```sql
SELECT id, text, _score
FROM fts('my_docs', '{"match":{"column":"text","terms":"puppy"}}')
ORDER BY _score DESC
LIMIT 5
```
The second argument is a string literal containing a JSON query object. A bare
query string such as `'puppy'` is rejected. Match, fuzzy, phrase, boolean, boost
and multi-match queries use this JSON encoding.
Its schema contains the dataset's columns plus `_score`, so every stored
column is available in the result. Projections push into the scan.
Being a relation is also what makes it compose — join it, filter it, aggregate
over it. This join additionally requires `my_docs.category_id` and a
`categories` table with `id` and `name` columns:
```sql
SELECT c.name, count(*) AS hits
FROM fts('my_docs', '{"match":{"column":"text","terms":"puppy"}}') AS m
JOIN categories AS c ON c.id = m.category_id
GROUP BY c.name
ORDER BY hits DESC
```
For a keyword test that needs no score, the
[`contains_tokens`](/sql/scalar-functions#contains-tokens) predicate is
index-accelerated and usable directly in `WHERE`.
See [Full-Text Search](/sql/dql/fts) for the fuzzy, phrase, boolean, boost and
multi-match query forms.
### `_score` {#score}
A pseudo-column produced by `fts()`, carrying relevance for the row. It behaves
like any other column — order by it, filter on it, project it — and exists only
in a relation that came from `fts()`. See
[Data types](/sql/data-types#pseudo-columns).
### `generate_series` {#generate-series}
```sql
SELECT * FROM generate_series(1, 10)
```
Rows from a range, useful for building a dense axis to left-join sparse data
onto.
## What Lance accelerates {#accelerated}
Two function families use an index rather than scanning, which is the difference
between a fast predicate and a slow one:
| | Index used |
| --- | --- |
| [`contains_tokens`](/sql/scalar-functions#contains-tokens) | full-text index |
| [`json_get`, typed variants, `json_extract`](/sql/scalar-functions#json) | JSON scalar index |
Confirm with [`EXPLAIN`](/sql/dql/explain): an accelerated predicate shows an
index node rather than a `LanceScan` followed by a filter.