From d0ed4d1a7af8f981c4e2c47248282c8b8def7868 Mon Sep 17 00:00:00 2001 From: Brendan Clement Date: Fri, 9 Oct 2026 13:40:39 -0700 Subject: [PATCH] docs: fix SQL examples a deployment rejects - CREATE INDEX: the example left out USING, which the server requires, and the page said SQL cannot choose the algorithm or name the index. USING names the algorithm, the page lists them, and a name before ON is taken where the deployment's configuration allows it. - The search join passed fts() a bare string; fts() takes JSON. - Sampling a subquery's result is refused, so the sampling and subquery pages sample the table inside the subquery, and the refusals list it. - Two unaliased casts in one projection produce the same column name; the example aliases them. - A json_get nested in another json_get is refused. The page shows one level of nesting and json_extract with a JSONPath for deeper values, and corrects what json_extract and json_extract_with_type return. --- docs/web/basics/limits.mdx | 2 +- docs/web/curation/join.mdx | 5 ++++- docs/web/sql/ddl/index.mdx | 18 ++++++++++++------ docs/web/sql/dql/sampling.mdx | 3 ++- docs/web/sql/dql/subqueries.mdx | 6 +++--- docs/web/sql/operators.mdx | 7 +++++-- docs/web/sql/scalar-functions.mdx | 17 +++++++++++++---- 7 files changed, 40 insertions(+), 18 deletions(-) diff --git a/docs/web/basics/limits.mdx b/docs/web/basics/limits.mdx index c0ad03d80..69815fbab 100644 --- a/docs/web/basics/limits.mdx +++ b/docs/web/basics/limits.mdx @@ -80,7 +80,7 @@ See [Data types](/sql/data-types). | `TABLESAMPLE (n ROWS)` | whole numbers only | | `TABLESAMPLE BUCKET` | not supported | | `TABLESAMPLE` on a WAL-backed table | not supported | -| `CREATE INDEX` | one column, server-chosen name | +| `CREATE INDEX` | one column; `USING` names the algorithm | | `REFRESH MATERIALIZED VIEW ... CASCADE` | depends on the deployment's version; see [REFRESH](/sql/dml/refresh#refresh-materialized-view) | A sampling percentage over 100 is an error rather than a full scan, because a diff --git a/docs/web/curation/join.mdx b/docs/web/curation/join.mdx index 846e2cae9..a0cb24f39 100644 --- a/docs/web/curation/join.mdx +++ b/docs/web/curation/join.mdx @@ -58,12 +58,15 @@ just which rows: ```sql SELECT c.name, count(*) AS hits -FROM fts('documents', 'puppy') AS m +FROM fts('documents', '{"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 ``` +`fts` takes the query as JSON, as in [Full-text search](/sql/dql/fts); a bare +string such as `'puppy'` is refused. + Whether SQL can express vector search [depends on the deployment](/basics/sql#no-vector-sql). Where it cannot, run the diff --git a/docs/web/sql/ddl/index.mdx b/docs/web/sql/ddl/index.mdx index 2ac18dd4c..0c6c63155 100644 --- a/docs/web/sql/ddl/index.mdx +++ b/docs/web/sql/ddl/index.mdx @@ -1,7 +1,7 @@ --- title: "Index" sidebarTitle: "Index" -description: "CREATE INDEX and DROP INDEX — one column, server-chosen name." +description: "CREATE INDEX and DROP INDEX — one column, with the algorithm chosen by USING." icon: bolt keywords: ["create index", "drop index", "sql"] --- @@ -11,14 +11,20 @@ keywords: ["create index", "drop index", "sql"] ## CREATE INDEX {#create} ```sql -CREATE INDEX ON documents (title) +CREATE INDEX ON documents USING btree (title) +CREATE INDEX text_search ON documents USING fts (text) ``` +`USING` is required: it names the algorithm. The scalar algorithms are `btree`, +`bitmap` and `label_list`; `fts` builds a full-text index; and the vector +algorithms are `ivf_pq`, `ivf_rq`, `ivf_flat`, `ivf_hnsw_sq` and `ivf_hnsw_pq`, +where the deployment supports them. Index options go in a `WITH (...)` clause. + -SQL `CREATE INDEX` covers **one column** and takes **no user-chosen name** -- -the server names it. For a multi-column or explicitly-named index, or to -choose the algorithm, use the SDK's -[`create_index`](/indexing). +On a deployment, SQL `CREATE INDEX` covers **one column**. A name between +`INDEX` and `ON` names the index, where the deployment's configuration allows +it; without one, the server names it after the column, as in `title_idx`. For a +multi-column index, use the SDK's [`create_index`](/indexing). diff --git a/docs/web/sql/dql/sampling.mdx b/docs/web/sql/dql/sampling.mdx index 0c190d4d5..e75bc8f23 100644 --- a/docs/web/sql/dql/sampling.mdx +++ b/docs/web/sql/dql/sampling.mdx @@ -64,7 +64,7 @@ It attaches to a table in `FROM`, including inside a subquery, a CTE, or either side of a join: ```sql -SELECT * FROM (SELECT * FROM documents) d TABLESAMPLE (10) +SELECT * FROM (SELECT * FROM documents TABLESAMPLE (10)) d SELECT * FROM a TABLESAMPLE (5 ROWS) JOIN b ON a.id = b.id @@ -86,6 +86,7 @@ be honoured exactly is an error: | `TABLESAMPLE (101)` | a percentage outside `0..=100` is refused, not clamped | | `TABLESAMPLE (1.5 ROWS)` | a row count must be whole | | `TABLESAMPLE (BUCKET 1 OUT OF 4)` | bucket sampling is not supported | +| `(SELECT ...) d TABLESAMPLE (10)` | a subquery's result cannot be sampled; sample the table inside it | | the `SAMPLE` spelling | use `TABLESAMPLE` | | the `OFFSET` modifier | not supported | diff --git a/docs/web/sql/dql/subqueries.mdx b/docs/web/sql/dql/subqueries.mdx index 22eee986b..5a4eb1039 100644 --- a/docs/web/sql/dql/subqueries.mdx +++ b/docs/web/sql/dql/subqueries.mdx @@ -19,11 +19,11 @@ SELECT * FROM ( WHERE n > 100 ``` -A derived table needs an alias. It can be [sampled](/sql/dql/sampling) like a base -table: +A derived table needs an alias. Its result cannot be +[sampled](/sql/dql/sampling); sample the table inside it instead: ```sql -SELECT * FROM (SELECT * FROM documents) d TABLESAMPLE (10) +SELECT * FROM (SELECT * FROM documents TABLESAMPLE (10)) d ``` ## As a scalar {#scalar} diff --git a/docs/web/sql/operators.mdx b/docs/web/sql/operators.mdx index 5ffecc9bf..267da4c59 100644 --- a/docs/web/sql/operators.mdx +++ b/docs/web/sql/operators.mdx @@ -66,10 +66,13 @@ or a name with mixed case: `SELECT "order" FROM "MyTable"`. ## Casting {#casting} ```sql -SELECT CAST(identifier AS VARCHAR), identifier::VARCHAR FROM documents +SELECT CAST(identifier AS VARCHAR) AS with_cast, identifier::VARCHAR AS with_colons +FROM documents ``` -Both forms work. `TRY_CAST` returns null instead of erroring on a value that +Both forms work. Give each its own alias when one projection uses both: they +produce the same expression name, and a projection refuses two columns with +one name. `TRY_CAST` returns null instead of erroring on a value that will not convert, which is the one to use over a column you do not control. ## Precedence {#precedence} diff --git a/docs/web/sql/scalar-functions.mdx b/docs/web/sql/scalar-functions.mdx index f69c16a2f..eb92ebd25 100644 --- a/docs/web/sql/scalar-functions.mdx +++ b/docs/web/sql/scalar-functions.mdx @@ -156,17 +156,26 @@ it over `LIKE` for keyword tests. | `json_get_int(col, key)` | `Int64` | | `json_get_float(col, key)` | `Float64` | | `json_get_bool(col, key)` | `Boolean` | -| `json_extract(col, path)` | `Utf8`, by path | -| `json_extract_with_type(col, path, type)` | the requested type | +| `json_extract(col, path)` | `Utf8`: the value as JSON text, by path | +| `json_extract_with_type(col, path)` | a struct of the value as JSON and a type tag, by path | | `json_exists(col, path)` | `Boolean` | | `json_array_contains(col, value)` | `Boolean` | | `json_array_length(col)` | length | -`json_get` returns JSON, so accessors nest: +`json_get` returns JSON, so a typed accessor can read a field inside it: ```sql SELECT * FROM events -WHERE json_get_string(json_get(json_get(data, 'user'), 'profile'), 'name') = 'Alice' +WHERE json_get_string(json_get(data, 'user'), 'name') = 'Alice' +``` + +That works one level down. A `json_get` nested inside another `json_get` is +refused, so reach a deeper value with `json_extract` and a JSONPath instead. It +returns JSON text, so a string compares with its quotes: + +```sql +SELECT * FROM events +WHERE json_extract(data, '$.user.profile.name') = '"Alice"' ``` **`json_get`, its typed variants, and `json_extract` are index-accelerated** by a