Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion core/src/main/resources/help/commands/ddl/_index.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"drop_watcher.json",
"create_enrich_policy.json",
"drop_enrich_policy.json",
"execute_enrich_policy.json"
"execute_enrich_policy.json",
"create_materialized_view.json",
"drop_materialized_view.json",
"refresh_materialized_view.json"
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{
"name": "CREATE MATERIALIZED VIEW",
"category": "DDL",
"shortDescription": "Create a materialized view maintained by Elasticsearch transforms",
"syntax": [
"CREATE MATERIALIZED VIEW [IF NOT EXISTS] view_name",
" [REFRESH EVERY n time_unit]",
" [WITH (option = value, ...)]",
" AS select_statement",
"",
"-- Or replace an existing view (IF NOT EXISTS is NOT accepted on this form):",
"CREATE OR REPLACE MATERIALIZED VIEW view_name",
" [REFRESH EVERY n time_unit]",
" [WITH (option = value, ...)]",
" AS select_statement"
],
"description": "Materialize the result of a SELECT into its own Elasticsearch index, kept up to date by a chain of transforms. A view over a single table generates one transform (source to view); a view with a JOIN also generates changelog transforms, an enrich policy, an ingest pipeline and an enrichment transform. Requires the Materialized Views extension (softclient4es-extensions) on the engine that executes the statement: the core parser accepts the statement, but an engine with no materialized-view extension registered rejects it at execution time with `Unsupported table DDL statement`.",
"clauses": [
{
"name": "IF NOT EXISTS",
"description": "Do nothing if the view already exists. Accepted only on CREATE MATERIALIZED VIEW - the parser rejects it after CREATE OR REPLACE.",
"optional": true
},
{
"name": "OR REPLACE",
"description": "Drop the existing view and its artifacts, then recreate them. Mutually exclusive with IF NOT EXISTS.",
"optional": true
},
{
"name": "REFRESH EVERY",
"description": "How often the transforms look for new data: an integer, whitespace, then MILLISECOND(S), SECOND(S), MINUTE(S), HOUR(S), DAY(S), WEEK(S), MONTH(S) or YEAR(S). Must come before WITH (...). Unlike every other keyword in the dialect the UNIT is case-SENSITIVE and must be upper case, and the whitespace is required: REFRESH EVERY 30 seconds and REFRESH EVERY 30SECONDS are both rejected.",
"optional": true
},
{
"name": "WITH (...)",
"description": "View options: delay (how long to wait for late-arriving data) and user_latency (acceptable query latency). Must come after REFRESH EVERY.",
"optional": true
},
{
"name": "AS select_statement",
"description": "The SELECT that defines the view. WHERE, GROUP BY, aggregations and one JOIN are supported.",
"optional": false
}
],
"examples": [
{
"title": "Single-table view",
"description": "A view over one table generates exactly one transform - no JOIN is required",
"sql": "CREATE MATERIALIZED VIEW active_orders_mv REFRESH EVERY 30 SECONDS AS SELECT id, amount, status, created_at FROM orders WHERE status = 'active'"
},
{
"title": "Create only if absent",
"description": "IF NOT EXISTS makes the statement a no-op when the view is already there",
"sql": "CREATE MATERIALIZED VIEW IF NOT EXISTS active_orders_mv AS SELECT id, amount FROM orders WHERE status = 'active'"
},
{
"title": "Replace a view with a JOIN",
"description": "OR REPLACE drops the existing artifacts first; REFRESH EVERY precedes WITH (...)",
"sql": "CREATE OR REPLACE MATERIALIZED VIEW orders_with_customers_mv REFRESH EVERY 60 SECONDS WITH (delay = '1s', user_latency = '1s') AS SELECT o.id, o.amount, c.name AS customer_name FROM orders AS o JOIN customers AS c ON o.customer_id = c.id WHERE o.status = 'completed'"
},
{
"title": "Aggregated view",
"description": "A GROUP BY adds a pivot transform to the chain",
"sql": "CREATE MATERIALIZED VIEW orders_by_city_mv AS SELECT c.city, COUNT(*) AS order_count, SUM(o.amount) AS total_amount FROM orders o JOIN customers c ON o.customer_id = c.id GROUP BY c.city"
},
{
"title": "Quoted name",
"description": "A view name may be written bare, double-quoted or back-quoted",
"sql": "CREATE MATERIALIZED VIEW \"orders_mv\" AS SELECT id, amount FROM orders"
}
],
"notes": [
"Requires the Materialized Views extension - an engine without it parses the statement and then rejects it at execution time",
"Clause order is fixed: REFRESH EVERY comes before WITH (...); the reverse order is rejected",
"IF NOT EXISTS and OR REPLACE cannot be combined",
"A view name may be bare, \"double-quoted\" or `back-quoted`. A QUALIFIER behaves differently in the two spellings and the parser does not interpret it: a quoted qualifier is recorded but is NOT part of the name, so \"analytics\".\"orders_mv\" creates orders_mv, while the bare analytics.orders_mv is one name and creates the index analytics.orders_mv",
"With REFRESH EVERY and no explicit delay, the frequency must be at least 2 x (number of transforms) x 10 seconds - 20 seconds for a single-table view, 60 seconds for one JOIN with a WHERE, 80 seconds when computed columns are present",
"A JOIN view creates a watcher to re-run its enrich policies. On a cluster whose LICENCE does not include Watcher the view is still created, with a warning, and REFRESH MATERIALIZED VIEW is the manual equivalent - but a cluster with Watcher explicitly DISABLED (xpack.watcher.enabled: false) fails the CREATE and rolls back"
],
"limitations": [
"Only INNER and LEFT JOIN are supported; RIGHT and FULL JOIN are rejected",
"UNNEST is not supported in a materialized view definition"
],
"seeAlso": [
"DROP MATERIALIZED VIEW",
"REFRESH MATERIALIZED VIEW",
"SHOW MATERIALIZED VIEWS",
"SHOW CREATE MATERIALIZED VIEW",
"CREATE TABLE"
],
"minVersion": null,
"aliases": []
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"category": "DDL",
"shortDescription": "Create an ingest pipeline for document processing",
"syntax": [
"CREATE [OR REPLACE] PIPELINE [IF NOT EXISTS] pipeline_name",
"CREATE PIPELINE [IF NOT EXISTS] pipeline_name",
"WITH PROCESSORS (",
" processor_definition,",
" ...",
Expand All @@ -16,13 +16,16 @@
"REMOVE (field = 'field_name')",
"RENAME (field = 'old_name', target_field = 'new_name')",
"ENRICH (policy_name = 'policy', field = 'match_field', target_field = 'enriched')",
"... (refer to documentation for full list of processors and syntax)"
"... (refer to documentation for full list of processors and syntax)",
"",
"-- Or replace an existing pipeline (IF NOT EXISTS is not accepted after OR REPLACE):",
"CREATE OR REPLACE PIPELINE pipeline_name WITH PROCESSORS ( ... )"
],
"description": "Create an Elasticsearch ingest pipeline that processes documents before indexing. Pipelines can transform, enrich, and validate data.",
"clauses": [
{
"name": "OR REPLACE",
"description": "Replace existing pipeline if it exists",
"description": "Replace existing pipeline if it exists. Cannot be combined with IF NOT EXISTS - the parser rejects CREATE OR REPLACE PIPELINE IF NOT EXISTS.",
"optional": true
},
{
Expand Down
7 changes: 5 additions & 2 deletions core/src/main/resources/help/commands/ddl/create_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"category": "DDL",
"shortDescription": "Create a new table (Elasticsearch index)",
"syntax": [
"CREATE [OR REPLACE] TABLE [IF NOT EXISTS] table_name (",
"CREATE TABLE [IF NOT EXISTS] table_name (",
" column_name data_type [NOT NULL] [DEFAULT value] [COMMENT 'text']",
" [FIELDS (subfield_name subfield_type [OPTIONS (...)])]",
" [OPTIONS (option = value, ...)]",
Expand All @@ -18,14 +18,17 @@
" [aliases = (alias = value, ...)],",
")]",
"",
"-- Or replace an existing table (IF NOT EXISTS is not accepted after OR REPLACE):",
"CREATE OR REPLACE TABLE table_name ( ... )",
"",
"-- Or create from SELECT:",
"CREATE [OR REPLACE] TABLE table_name AS SELECT ..."
],
"description": "Create a new Elasticsearch index with the specified schema. Automatically generates mappings, settings, and ingest pipeline based on column definitions. Supports complex types like STRUCT and ARRAY<STRUCT> for nested documents.",
"clauses": [
{
"name": "OR REPLACE",
"description": "Drop existing table before creating. If the table exists, it will be deleted first.",
"description": "Drop existing table before creating. If the table exists, it will be deleted first. Cannot be combined with IF NOT EXISTS - the parser rejects CREATE OR REPLACE TABLE IF NOT EXISTS.",
"optional": true
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "DROP MATERIALIZED VIEW",
"category": "DDL",
"shortDescription": "Drop a materialized view and every artifact it deployed",
"syntax": [
"DROP MATERIALIZED VIEW [IF EXISTS] view_name"
],
"description": "Drop a materialized view together with everything its creation deployed: the transforms, the intermediate indices, the ingest pipelines, the enrich policies, the watcher and the view index itself. Requires the Materialized Views extension (softclient4es-extensions) on the engine that executes the statement: an engine without it rejects the statement at execution time with `Unsupported table DDL statement`.",
"clauses": [
{
"name": "IF EXISTS",
"description": "Do not raise an error when the view does not exist.",
"optional": true
}
],
"examples": [
{
"title": "Drop a view",
"description": "Remove the view and its artifacts",
"sql": "DROP MATERIALIZED VIEW orders_with_customers_mv"
},
{
"title": "Drop if it exists",
"description": "Safe in a script that may run twice",
"sql": "DROP MATERIALIZED VIEW IF EXISTS orders_with_customers_mv"
}
],
"notes": [
"Requires the Materialized Views extension - an engine without it parses the statement and then rejects it at execution time",
"The drop removes the transforms, intermediate indices, ingest pipelines, enrich policies, the watcher and the view index"
],
"limitations": [],
"seeAlso": [
"CREATE MATERIALIZED VIEW",
"SHOW MATERIALIZED VIEWS",
"DROP TABLE"
],
"minVersion": null,
"aliases": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "REFRESH MATERIALIZED VIEW",
"category": "DDL",
"shortDescription": "Force a materialized view to pick up new data now",
"syntax": [
"REFRESH MATERIALIZED VIEW [IF EXISTS] view_name [WITH SCHEDULE NOW]"
],
"description": "Refresh a materialized view immediately: the changelog indices are refreshed and the enrich policies re-executed - exactly the work the view's watcher performs on a schedule. Use it on a cluster where Watcher is unavailable, or to make a change visible without waiting for the next refresh interval. Requires the Materialized Views extension (softclient4es-extensions) on the engine that executes the statement: an engine without it rejects the statement at execution time with `Unsupported table DDL statement`.",
"clauses": [
{
"name": "IF EXISTS",
"description": "Do not raise an error when the view does not exist.",
"optional": true
},
{
"name": "WITH SCHEDULE NOW",
"description": "Also schedule the view's transforms for immediate execution instead of waiting for their next run.",
"optional": true
}
],
"examples": [
{
"title": "Refresh a view",
"description": "Re-run the changelogs and enrich policies",
"sql": "REFRESH MATERIALIZED VIEW orders_with_customers_mv"
},
{
"title": "Refresh and schedule now",
"description": "Also trigger the transforms immediately",
"sql": "REFRESH MATERIALIZED VIEW orders_with_customers_mv WITH SCHEDULE NOW"
},
{
"title": "Refresh if it exists",
"description": "No error when the view is absent",
"sql": "REFRESH MATERIALIZED VIEW IF EXISTS orders_with_customers_mv"
}
],
"notes": [
"Requires the Materialized Views extension - an engine without it parses the statement and then rejects it at execution time",
"This is the documented manual equivalent of the view's watcher, and the supported path on a cluster whose licence does not include Watcher"
],
"limitations": [
"A single-table view deploys no enrich policy and no watcher, so it has nothing to re-execute here - it is refreshed by its own transform on its REFRESH EVERY schedule"
],
"seeAlso": [
"CREATE MATERIALIZED VIEW",
"SHOW MATERIALIZED VIEW STATUS",
"DROP MATERIALIZED VIEW"
],
"minVersion": null,
"aliases": []
}
7 changes: 6 additions & 1 deletion core/src/main/resources/help/commands/dql/_index.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@
"show_enrich_policy.json",
"show_cluster_name.json",
"show_license.json",
"refresh_license.json"
"refresh_license.json",
"show_materialized_view.json",
"show_materialized_views.json",
"show_materialized_view_status.json",
"show_create_materialized_view.json",
"describe_materialized_view.json"
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "DESCRIBE MATERIALIZED VIEW",
"category": "DQL",
"shortDescription": "Show the columns of a materialized view index",
"syntax": [
"{DESCRIBE | DESC} MATERIALIZED VIEW view_name"
],
"description": "Show the schema of the index a materialized view writes to: one row per column, with its type, nullability, default, comment and script. Requires the Materialized Views extension (softclient4es-extensions) on the engine that executes the statement: an engine without it rejects the statement at execution time with `Unsupported table DDL statement`.",
"clauses": [],
"examples": [
{
"title": "Describe a view",
"description": "List the view's columns and types",
"sql": "DESCRIBE MATERIALIZED VIEW orders_with_customers_mv"
},
{
"title": "DESC abbreviation",
"description": "DESC is accepted wherever DESCRIBE is",
"sql": "DESC MATERIALIZED VIEW orders_with_customers_mv"
}
],
"notes": [
"Requires the Materialized Views extension - an engine without it parses the statement and then rejects it at execution time",
"IF EXISTS is not accepted here - the parser rejects DESCRIBE MATERIALIZED VIEW IF EXISTS view_name",
"Computed columns of the view appear with the script that produces them"
],
"limitations": [],
"seeAlso": [
"DESCRIBE TABLE",
"SHOW MATERIALIZED VIEW",
"SHOW CREATE MATERIALIZED VIEW"
],
"minVersion": null,
"aliases": []
}
17 changes: 16 additions & 1 deletion core/src/main/resources/help/commands/dql/select.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"[GROUP BY columns]",
"[HAVING condition]",
"[ORDER BY columns [ASC|DESC]]",
"[LIMIT n [OFFSET m]]"
"[LIMIT n [OFFSET m]]",
"",
"-- Two or more SELECTs may be concatenated. UNION ALL is the ONLY spelling accepted:",
"-- bare UNION (de-duplicating) is rejected.",
"SELECT ... UNION ALL SELECT ..."
],
"description": "The SELECT statement retrieves rows from Elasticsearch indices. It supports most standard SQL features including joins, aggregations, and subqueries.",
"clauses": [
Expand Down Expand Up @@ -51,6 +55,11 @@
"optional": true,
"modifiers": ["ASC", "DESC", "NULLS FIRST", "NULLS LAST"]
},
{
"name": "UNION ALL",
"description": "Concatenate the rows of two or more SELECT statements. Only UNION ALL is accepted - bare UNION, which would de-duplicate, is rejected by the parser.",
"optional": true
},
{
"name": "LIMIT/OFFSET",
"description": "Limit number of returned rows",
Expand Down Expand Up @@ -81,6 +90,12 @@
"description": "Get the 10 most recent products",
"sql": "SELECT name, created_at\nFROM products\nORDER BY created_at DESC\nLIMIT 10",
"output": null
},
{
"title": "Concatenate two result sets",
"description": "UNION ALL keeps every row of both sides; bare UNION is not accepted",
"sql": "SELECT id, amount FROM orders UNION ALL SELECT id, amount FROM archived_orders",
"output": null
}
],
"notes": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "SHOW CREATE MATERIALIZED VIEW",
"category": "DQL",
"shortDescription": "Show the CREATE statement that defines a materialized view",
"syntax": [
"SHOW CREATE MATERIALIZED VIEW view_name"
],
"description": "Return the CREATE MATERIALIZED VIEW statement the engine recorded for a view, rendered from the stored definition. The rendered statement is itself accepted by the parser, so it can be replayed against another cluster. Requires the Materialized Views extension (softclient4es-extensions) on the engine that executes the statement: an engine without it rejects the statement at execution time with `Unsupported table DDL statement`.",
"clauses": [],
"examples": [
{
"title": "Show the definition",
"description": "Recover the statement that created a view",
"sql": "SHOW CREATE MATERIALIZED VIEW orders_with_customers_mv"
}
],
"notes": [
"Requires the Materialized Views extension - an engine without it parses the statement and then rejects it at execution time",
"The rendered statement is normalised, not the original text: clauses appear in canonical order and identifiers in canonical spelling"
],
"limitations": [],
"seeAlso": [
"SHOW MATERIALIZED VIEW",
"CREATE MATERIALIZED VIEW",
"SHOW CREATE TABLE"
],
"minVersion": null,
"aliases": []
}
Loading
Loading