mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-14 16:03:27 +00:00
* fix(operator): unify unknown flow option rejection across OSS and enterprise builds Remove the enterprise-gated passthrough that let unknown flow options through SQL-layer validation. Both OSS and enterprise binaries now reject unknown flow options with a single 1004(InvalidArguments) error at the SQL layer, producing identical sqlness output. The metasrv-side validate_flow_options remains as a defensive check. Signed-off-by: discord9 <discord9@163.com> * fix(flow): use DISTINCT output columns as sink key for streaming flows When a streaming flow's source table has no primary key, sink key inference produced an empty key. For SELECT DISTINCT v, the DISTINCT establishes v as the output key, but the inference only looked at source primary keys. Combined with the zero-valued placeholder timestamp, all output rows shared the same storage identity and were deduplicated into a single row. Use all non-time-index output columns as the sink key when the plan is a DISTINCT and no source primary key was inherited. Signed-off-by: discord9 <discord9@163.com> * fix(flow): preserve extension options and complete DISTINCT sink identity Keep enterprise CREATE FLOW options available to the existing handler and report unknown ordinary options as InvalidArguments with the OSS SQL error text. Infer DISTINCT sink keys from every selected non-time-index output column, including when source key columns survive. Wait for asynchronous mirrors in show_create_flow and exercise 1000 distinct sink rows in the SQL regression. Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * test(flow): align meta unknown option status assertions Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * test(flow): use valid aliases in DISTINCT sink regression SQL Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> * test(flow): record complete DISTINCT sink SQL results Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com> --------- Signed-off-by: discord9 <discord9@163.com> Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
237 lines
6.6 KiB
SQL
237 lines
6.6 KiB
SQL
-- test ttl = instant
|
|
CREATE TABLE distinct_basic (
|
|
"number" INT,
|
|
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY(number),
|
|
TIME INDEX(ts)
|
|
)WITH ('ttl' = 'instant');
|
|
|
|
-- request-local DISTINCT is supported in streaming mode
|
|
-- SQLNESS REPLACE id=\d+ id=REDACTED
|
|
CREATE FLOW test_distinct_basic SINK TO out_distinct_basic AS
|
|
SELECT
|
|
DISTINCT number as dis
|
|
FROM
|
|
distinct_basic;
|
|
|
|
-- instant-TTL sources reject non-stateless LIMIT plans
|
|
CREATE FLOW test_limit_instant_rejected SINK TO out_limit_instant_rejected AS
|
|
SELECT
|
|
number
|
|
FROM
|
|
distinct_basic
|
|
LIMIT 1;
|
|
|
|
-- flow_options should have a flow_type:streaming
|
|
-- since source table's ttl=instant and DISTINCT is request-local
|
|
SELECT flow_name, options FROM INFORMATION_SCHEMA.FLOWS;
|
|
|
|
SHOW CREATE TABLE distinct_basic;
|
|
|
|
-- SQLNESS REPLACE \d{4} REDACTED
|
|
SHOW CREATE TABLE out_distinct_basic;
|
|
|
|
-- SQLNESS SLEEP 3s
|
|
INSERT INTO
|
|
distinct_basic
|
|
VALUES
|
|
(20, "2021-07-01 00:00:00.200"),
|
|
(20, "2021-07-01 00:00:00.200"),
|
|
(22, "2021-07-01 00:00:00.600");
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_basic');
|
|
|
|
SELECT
|
|
dis
|
|
FROM
|
|
out_distinct_basic;
|
|
|
|
SELECT number FROM distinct_basic;
|
|
|
|
ADMIN FLUSH_TABLE('distinct_basic');
|
|
|
|
-- Recover the persisted streaming DISTINCT flow, then replan its first write
|
|
-- against an extended source schema without recreating the flow.
|
|
-- SQLNESS ARG restart=true
|
|
SELECT 1;
|
|
|
|
ALTER TABLE distinct_basic ADD COLUMN extra INT NULL;
|
|
|
|
INSERT INTO
|
|
distinct_basic (number, ts)
|
|
VALUES
|
|
(23, "2021-07-01 00:00:01.600"),
|
|
(23, "2021-07-01 00:00:01.600");
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_basic');
|
|
|
|
SELECT
|
|
dis
|
|
FROM
|
|
out_distinct_basic;
|
|
|
|
SELECT number FROM distinct_basic;
|
|
|
|
DROP FLOW test_distinct_basic;
|
|
DROP TABLE distinct_basic;
|
|
DROP TABLE out_distinct_basic;
|
|
|
|
-- test ttl = instant with EVAL INTERVAL must be rejected
|
|
-- since the batching scheduler cannot read instant-TTL source tables and the
|
|
-- streaming engine cannot honor the schedule
|
|
CREATE TABLE distinct_basic (
|
|
"number" INT,
|
|
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY(number),
|
|
TIME INDEX(ts)
|
|
)WITH ('ttl' = 'instant');
|
|
|
|
-- SQLNESS REPLACE id=\d+ id=REDACTED
|
|
CREATE FLOW test_distinct_basic SINK TO out_distinct_basic EVAL INTERVAL '1m' AS
|
|
SELECT
|
|
DISTINCT number as dis
|
|
FROM
|
|
distinct_basic;
|
|
|
|
SELECT count(*) FROM INFORMATION_SCHEMA.FLOWS WHERE flow_name = 'test_distinct_basic';
|
|
|
|
DROP TABLE distinct_basic;
|
|
|
|
-- test ttl = 5s (DISTINCT remains batching for persisted sources)
|
|
CREATE TABLE distinct_basic (
|
|
"number" INT,
|
|
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY(number),
|
|
TIME INDEX(ts)
|
|
)WITH ('ttl' = '5s');
|
|
|
|
-- Without a schedule, persisted DISTINCT must reach batching validation,
|
|
-- not silently become request-local streaming.
|
|
CREATE FLOW test_distinct_persisted_unscheduled
|
|
SINK TO out_distinct_persisted_unscheduled AS
|
|
SELECT DISTINCT number AS dis FROM distinct_basic;
|
|
|
|
DROP FLOW IF EXISTS test_distinct_persisted_unscheduled;
|
|
DROP TABLE IF EXISTS out_distinct_persisted_unscheduled;
|
|
|
|
CREATE FLOW test_distinct_basic SINK TO out_distinct_basic EVAL INTERVAL '1m' AS
|
|
SELECT
|
|
DISTINCT number as dis
|
|
FROM
|
|
distinct_basic;
|
|
|
|
-- flow_options should have a flow_type:batching
|
|
-- persisted-source DISTINCT retains batching semantics
|
|
SELECT flow_name, options FROM INFORMATION_SCHEMA.FLOWS;
|
|
|
|
-- SQLNESS ARG restart=true
|
|
SELECT 1;
|
|
|
|
-- SQLNESS SLEEP 3s
|
|
INSERT INTO
|
|
distinct_basic
|
|
VALUES
|
|
(20, "2021-07-01 00:00:00.200"),
|
|
(20, "2021-07-01 00:00:00.200"),
|
|
(22, "2021-07-01 00:00:00.600");
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_basic');
|
|
|
|
SHOW CREATE TABLE distinct_basic;
|
|
|
|
SHOW CREATE TABLE out_distinct_basic;
|
|
|
|
SELECT
|
|
dis
|
|
FROM
|
|
out_distinct_basic;
|
|
|
|
SELECT number FROM distinct_basic;
|
|
|
|
ADMIN FLUSH_TABLE('distinct_basic');
|
|
|
|
INSERT INTO
|
|
distinct_basic
|
|
VALUES
|
|
(23, "2021-07-01 00:00:01.600");
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_basic');
|
|
|
|
SELECT
|
|
dis
|
|
FROM
|
|
out_distinct_basic;
|
|
|
|
SELECT number FROM distinct_basic;
|
|
|
|
DROP FLOW test_distinct_basic;
|
|
DROP TABLE distinct_basic;
|
|
DROP TABLE out_distinct_basic;
|
|
|
|
-- Streaming DISTINCT auto-sink retains all 1000 output tuples.
|
|
CREATE TABLE distinct_auto_sink (
|
|
v INT,
|
|
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP TIME INDEX
|
|
) WITH ('ttl' = 'instant');
|
|
|
|
CREATE FLOW test_distinct_auto_sink SINK TO out_distinct_auto_sink AS
|
|
SELECT DISTINCT v FROM distinct_auto_sink;
|
|
|
|
INSERT INTO distinct_auto_sink (v)
|
|
SELECT number FROM numbers LIMIT 1000;
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_auto_sink');
|
|
|
|
SELECT count(*) AS rows, count(DISTINCT v) AS distinct_values, min(v) AS min_v, max(v) AS max_v
|
|
FROM out_distinct_auto_sink;
|
|
|
|
DROP FLOW test_distinct_auto_sink;
|
|
DROP TABLE distinct_auto_sink;
|
|
DROP TABLE out_distinct_auto_sink;
|
|
|
|
CREATE TABLE distinct_auto_sink_pk (
|
|
v INT,
|
|
k INT,
|
|
extra_value INT,
|
|
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP TIME INDEX,
|
|
PRIMARY KEY (v, k)
|
|
) WITH ('ttl' = 'instant');
|
|
|
|
CREATE FLOW test_distinct_auto_sink_pk SINK TO out_distinct_auto_sink_pk AS
|
|
SELECT DISTINCT v, extra_value FROM distinct_auto_sink_pk;
|
|
|
|
INSERT INTO distinct_auto_sink_pk (v, k, extra_value)
|
|
SELECT number % 10 AS v, number AS k, number AS extra_value FROM numbers LIMIT 1000;
|
|
|
|
-- Mirror inserts reach the flownode asynchronously; wait before flushing.
|
|
-- SQLNESS SLEEP 3s
|
|
-- SQLNESS REPLACE (ADMIN\sFLUSH_FLOW\('\w+'\)\s+\|\n\+-+\+\n\|\s+)[0-9]+\s+\| $1 FLOW_FLUSHED |
|
|
ADMIN FLUSH_FLOW('test_distinct_auto_sink_pk');
|
|
|
|
SELECT
|
|
count(*) AS rows,
|
|
count(DISTINCT extra_value) AS distinct_values,
|
|
min(extra_value) AS min_value,
|
|
max(extra_value) AS max_value,
|
|
sum(CASE WHEN v = extra_value % 10 THEN 0 ELSE 1 END) AS mismatched_keys
|
|
FROM out_distinct_auto_sink_pk;
|
|
|
|
DROP FLOW test_distinct_auto_sink_pk;
|
|
DROP TABLE distinct_auto_sink_pk;
|
|
DROP TABLE out_distinct_auto_sink_pk;
|