diff --git a/tests/config/config.d/storage_conf.xml b/tests/config/config.d/storage_conf.xml
index f046b9c31dce..1f80b8ae05a4 100644
--- a/tests/config/config.d/storage_conf.xml
+++ b/tests/config/config.d/storage_conf.xml
@@ -112,7 +112,13 @@
default
- s3_disk
+
+
+ s3_disk
+ 0
+
diff --git a/tests/integration/test_hedged_requests/test.py b/tests/integration/test_hedged_requests/test.py
index 1aafc1aadafa..6c53ef01a5d4 100644
--- a/tests/integration/test_hedged_requests/test.py
+++ b/tests/integration/test_hedged_requests/test.py
@@ -7,6 +7,7 @@
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from helpers.cluster import ClickHouseCluster
+from helpers.network import PartitionManager
from helpers.test_tools import TSV
cluster = ClickHouseCluster(__file__)
@@ -429,28 +430,46 @@ def test_async_connect(started_cluster):
Distributed('test_cluster_connect', 'default', 'test_hedged')"""
)
- NODES["node"].query(
- "SELECT hostName(), id FROM distributed_connect ORDER BY id LIMIT 1 SETTINGS prefer_localhost_replica = 0, connect_timeout_with_failover_ms=5000, async_query_sending_for_remote=0, max_threads=1, max_distributed_connections=1"
- )
- check_changing_replica_events(2)
- check_if_query_sending_was_not_suspended()
-
- # Restart server to reset connection pool state
- NODES["node"].restart_clickhouse()
+ # The first replica of each shard in test_cluster_connect is an unreachable
+ # address (129.0.0.1 / 129.0.0.2). Silently drop the initiator's packets to
+ # them so the connect always stalls and is preempted by the
+ # hedged_connection_timeout_ms timer (the path HedgedRequestsChangeReplica
+ # counts). Otherwise, on slow builds the connect can fail fast (host
+ # unreachable), switching the replica through the connection-failure path,
+ # which does not increment that event.
+ with PartitionManager() as pm:
+ for unreachable_ip in ("129.0.0.1", "129.0.0.2"):
+ pm.add_rule(
+ {
+ "instance": NODES["node"],
+ "chain": "OUTPUT",
+ "destination": unreachable_ip,
+ "action": "DROP",
+ }
+ )
- attempt = 0
- while attempt < 100:
NODES["node"].query(
- "SELECT hostName(), id FROM distributed_connect ORDER BY id LIMIT 1 SETTINGS prefer_localhost_replica = 0, connect_timeout_with_failover_ms=5000, async_query_sending_for_remote=1, max_threads=1, max_distributed_connections=1"
+ "SELECT hostName(), id FROM distributed_connect ORDER BY id LIMIT 1 SETTINGS prefer_localhost_replica = 0, connect_timeout_with_failover_ms=5000, async_query_sending_for_remote=0, max_threads=1, max_distributed_connections=1"
)
-
check_changing_replica_events(2)
- if check_if_query_sending_was_suspended():
- break
+ check_if_query_sending_was_not_suspended()
- attempt += 1
+ # Restart server to reset connection pool state
+ NODES["node"].restart_clickhouse()
- assert attempt < 100
+ attempt = 0
+ while attempt < 100:
+ NODES["node"].query(
+ "SELECT hostName(), id FROM distributed_connect ORDER BY id LIMIT 1 SETTINGS prefer_localhost_replica = 0, connect_timeout_with_failover_ms=5000, async_query_sending_for_remote=1, max_threads=1, max_distributed_connections=1"
+ )
+
+ check_changing_replica_events(2)
+ if check_if_query_sending_was_suspended():
+ break
+
+ attempt += 1
+
+ assert attempt < 100
NODES["node"].query("DROP TABLE distributed_connect")
diff --git a/tests/integration/test_keeper_auth/test.py b/tests/integration/test_keeper_auth/test.py
index 68a1c95e7d5c..ebf78ab4d6b3 100644
--- a/tests/integration/test_keeper_auth/test.py
+++ b/tests/integration/test_keeper_auth/test.py
@@ -61,6 +61,22 @@ def zk_stop_and_close(zk):
zk.close()
+# ZooKeeper checks delete against the PARENT's ACL, and its setACL leaves the
+# outstanding change record carrying the old ACL (duplicate() copies acl verbatim
+# and updates only stat.aversion), so a delete issued right after a widening
+# setACL can still be authorized against the pre-setACL ACL and get NoAuthError.
+def zk_delete_after_acl_change(zk, path, timeout=30.0):
+ deadline = time.monotonic() + timeout
+ while True:
+ try:
+ zk.delete(path)
+ return
+ except NoAuthError:
+ if time.monotonic() >= deadline:
+ raise
+ time.sleep(0.1)
+
+
@pytest.mark.parametrize(("get_zk"), [get_genuine_zk, get_fake_zk])
def test_remove_acl(started_cluster, get_zk):
auth_connection = None
@@ -412,7 +428,9 @@ def test_partial_auth(started_cluster, get_zk):
)
auth_connection.set_acls("/test_partial_acl_delete", acls=[acl])
auth_connection.set_acls("/test_partial_acl_delete/subnode", acls=[acl])
- auth_connection.delete("/test_partial_acl_delete/subnode")
+ zk_delete_after_acl_change(auth_connection, "/test_partial_acl_delete/subnode")
+ # Authorized against "/", whose ACL this test never touches, so a
+ # NoAuthError here would be a real problem: do not retry it.
auth_connection.delete("/test_partial_acl_delete")
zk_stop_and_close(auth_connection)
diff --git a/tests/integration/test_named_collections_encrypted2/test.py b/tests/integration/test_named_collections_encrypted2/test.py
index aaa0d7989982..b7e29e127b4c 100644
--- a/tests/integration/test_named_collections_encrypted2/test.py
+++ b/tests/integration/test_named_collections_encrypted2/test.py
@@ -62,6 +62,7 @@ def wait_not_exists(node, collection, timeout=10):
def check_encrypted(zk, collection):
+ zk.sync(ZK_PATH)
content = zk.get(f"{ZK_PATH}/{collection}.sql")[0]
assert content[:3] == b"ENC"
return content
@@ -717,6 +718,7 @@ def test_new_replica_encrypted_data_integrity(stopped_node3):
password='P@ssw0rd!Complex#123'
""")
+ zk.sync(ZK_PATH)
content = zk.get(f"{ZK_PATH}/encrypted_coll.sql")[0]
assert content[:3] == b"ENC"
assert b"super_secret_api_key_12345" not in content
diff --git a/tests/integration/test_replication_credentials/test.py b/tests/integration/test_replication_credentials/test.py
index e1ce61067d94..44df4ccd4f15 100644
--- a/tests/integration/test_replication_credentials/test.py
+++ b/tests/integration/test_replication_credentials/test.py
@@ -46,13 +46,13 @@ def same_credentials_cluster():
def test_same_credentials(same_credentials_cluster):
node1.query("insert into test_table values ('2017-06-16', 111, 0)")
- time.sleep(1)
+ node2.query("SYSTEM SYNC REPLICA test_table", timeout=60)
assert node1.query("SELECT id FROM test_table order by id") == "111\n"
assert node2.query("SELECT id FROM test_table order by id") == "111\n"
node2.query("insert into test_table values ('2017-06-17', 222, 1)")
- time.sleep(1)
+ node1.query("SYSTEM SYNC REPLICA test_table", timeout=60)
assert node1.query("SELECT id FROM test_table order by id") == "111\n222\n"
assert node2.query("SELECT id FROM test_table order by id") == "111\n222\n"
@@ -85,13 +85,13 @@ def no_credentials_cluster():
def test_no_credentials(no_credentials_cluster):
node3.query("insert into test_table values ('2017-06-18', 111, 0)")
- time.sleep(1)
+ node4.query("SYSTEM SYNC REPLICA test_table", timeout=60)
assert node3.query("SELECT id FROM test_table order by id") == "111\n"
assert node4.query("SELECT id FROM test_table order by id") == "111\n"
node4.query("insert into test_table values ('2017-06-19', 222, 1)")
- time.sleep(1)
+ node3.query("SYSTEM SYNC REPLICA test_table", timeout=60)
assert node3.query("SELECT id FROM test_table order by id") == "111\n222\n"
assert node4.query("SELECT id FROM test_table order by id") == "111\n222\n"
diff --git a/tests/integration/test_s3_table_functions/test.py b/tests/integration/test_s3_table_functions/test.py
index b2dfddb23ebd..ec565de617ca 100644
--- a/tests/integration/test_s3_table_functions/test.py
+++ b/tests/integration/test_s3_table_functions/test.py
@@ -78,14 +78,25 @@ def test_s3_table_functions(started_cluster):
def test_s3_table_functions_timeouts(started_cluster):
"""
- Test with timeout limit of 1200ms.
- This should raise an Exception and pass.
+ A 1200ms network delay must make the S3 write time out and raise.
"""
+ # Make the S3 request timeout (not the connect timeout) the single failure mechanism:
+ # disable adaptive timeouts and keep the connect timeout above the delay, so the write
+ # can only fail via s3_request_timeout_ms. This exercises the send/receive idleness
+ # timeout that applies to every attempt on both fresh and reused (pooled keep-alive)
+ # connections, which is the path that was silently not timing out before.
+ timeout_settings = {
+ **settings,
+ "s3_use_adaptive_timeouts": "0",
+ "s3_connect_timeout_ms": "10000",
+ "s3_request_timeout_ms": "500",
+ }
+
with PartitionManager() as pm:
pm.add_network_delay(node, 1200)
- with pytest.raises(QueryRuntimeException):
+ with pytest.raises(QueryRuntimeException, match="Timeout"):
node.query(
"""
INSERT INTO FUNCTION s3
@@ -98,5 +109,5 @@ def test_s3_table_functions_timeouts(started_cluster):
)
SELECT * FROM numbers(1000000)
""",
- settings=settings,
+ settings=timeout_settings,
)
diff --git a/tests/integration/test_storage_kafka/test_batch_fast.py b/tests/integration/test_storage_kafka/test_batch_fast.py
index c9705f2eafdb..5608582281f5 100644
--- a/tests/integration/test_storage_kafka/test_batch_fast.py
+++ b/tests/integration/test_storage_kafka/test_batch_fast.py
@@ -2081,10 +2081,19 @@ def test_kafka_flush_by_time(kafka_cluster, create_query_generator):
cancel = threading.Event()
+ # Reuse one producer: `k.kafka_produce` opens a new connection per call,
+ # and a single broker-version probe there can cost seconds, which is
+ # enough to miss the row count asserted below.
+ producer = k.get_kafka_producer(
+ kafka_cluster.kafka_port, k.producer_serializer, retries=15
+ )
+
def produce():
while not cancel.is_set():
- messages = [json.dumps({"key": 0, "value": 0})]
- k.kafka_produce(kafka_cluster, topic_name, messages)
+ producer.send(
+ topic=topic_name, value=json.dumps({"key": 0, "value": 0})
+ )
+ producer.flush()
time.sleep(0.8)
kafka_thread = threading.Thread(target=produce)
@@ -2102,6 +2111,7 @@ def produce():
cancel.set()
kafka_thread.join()
+ producer.close()
instance.query(f"""
DROP TABLE test.{kafka_table}_consumer;
diff --git a/tests/integration/test_storage_kafka/test_batch_slow_0.py b/tests/integration/test_storage_kafka/test_batch_slow_0.py
index 03e7297aa3dd..6f6393f0bd00 100644
--- a/tests/integration/test_storage_kafka/test_batch_slow_0.py
+++ b/tests/integration/test_storage_kafka/test_batch_slow_0.py
@@ -301,7 +301,6 @@ def test_kafka_formats_with_broken_message(kafka_cluster, create_query_generator
data_prefix = data_prefix + [""]
if format_opts.get("printable", False) == False:
raw_message = "hex(_raw_message)"
- k.kafka_produce(kafka_cluster, topic_name, data_prefix + data_sample)
create_query = create_query_generator(
f"kafka_{format_name}",
"id Int64, blockNo UInt16, val1 String, val2 Float32, val3 UInt8",
@@ -313,6 +312,10 @@ def test_kafka_formats_with_broken_message(kafka_cluster, create_query_generator
"kafka_flush_interval_ms": 1000,
},
)
+ # Create both materialized views, then detach/re-attach the Kafka table,
+ # before producing any message. Creating the first view starts the
+ # streaming loop, so producing earlier lets the loop consume and commit
+ # the broken message before the errors view is attached, leaving it empty.
instance.query(
f"""
DROP TABLE IF EXISTS test.kafka_{format_name};
@@ -328,8 +331,12 @@ def test_kafka_formats_with_broken_message(kafka_cluster, create_query_generator
CREATE MATERIALIZED VIEW test.kafka_errors_{format_name}_mv ENGINE=MergeTree ORDER BY tuple() AS
SELECT {raw_message} as raw_message, _error as error, _topic as topic, _partition as partition, _offset as offset FROM test.kafka_{format_name}
WHERE length(_error) > 0;
+
+ DETACH TABLE test.kafka_{format_name};
+ ATTACH TABLE test.kafka_{format_name};
"""
)
+ k.kafka_produce(kafka_cluster, topic_name, data_prefix + data_sample)
raw_expected = """\
0 0 AM 0.5 1 {topic_name} 0 {offset_0}
diff --git a/tests/integration/test_tcp_handler_connection_limits/test.py b/tests/integration/test_tcp_handler_connection_limits/test.py
index ef9a35f40f2a..ac9ec0a4eddd 100644
--- a/tests/integration/test_tcp_handler_connection_limits/test.py
+++ b/tests/integration/test_tcp_handler_connection_limits/test.py
@@ -1,6 +1,5 @@
import pytest
import subprocess
-import time
from helpers.cluster import ClickHouseCluster
cluster = ClickHouseCluster(__file__)
@@ -14,11 +13,6 @@ def started_cluster():
finally:
cluster.shutdown()
-@pytest.fixture(scope="module", autouse=True)
-def stabilize_container(started_cluster):
- """Wait for container startup processes to complete before running tests"""
- time.sleep(1)
-
def execute_queries_persistent_connection(queries):
"""Execute multiple queries through a single persistent clickhouse-client connection"""
proc = subprocess.Popen(
@@ -34,17 +28,19 @@ def execute_queries_persistent_connection(queries):
return stdout, stderr
-def get_connection_done_count():
- try:
- log_result = node.exec_in_container(
- ["grep", "-c", "Done processing connection", "/var/log/clickhouse-server/clickhouse-server.log"]
- )
- return int(log_result.strip())
- except Exception:
- return 0
+def get_limit_closed_count(reason):
+ """Count the connections that the server closed because a limit was reached.
+
+ Counting every closed connection instead would be racy: the readiness probe of
+ `cluster.start` connects to the port and closes it without sending any data, and the
+ server accepts that connection only once it starts serving, which can happen after the
+ test has already sampled the initial count. Connections closed for other reasons never
+ report a limit, so counting only those keeps the assertion exact.
+ """
+ return int(node.count_in_log(f"Closing connection due to limits: {reason}").strip())
def test_query_count_limit(started_cluster):
- initial_count = get_connection_done_count()
+ initial_count = get_limit_closed_count("queries=")
queries = ["SELECT 1;", "SELECT 2;", "SELECT 3;", "SELECT 4;", "SELECT 5;"]
stdout, stderr = execute_queries_persistent_connection(queries)
@@ -53,11 +49,11 @@ def test_query_count_limit(started_cluster):
assert "4" not in stdout and "5" not in stdout
assert "TCP_CONNECTION_LIMIT_REACHED" in stderr
- final_count = get_connection_done_count()
+ final_count = get_limit_closed_count("queries=")
assert final_count == initial_count + 1, f"Expected exactly 1 connection closure, got {final_count - initial_count}"
def test_time_limit(started_cluster):
- initial_count = get_connection_done_count()
+ initial_count = get_limit_closed_count("elapsed=")
queries = ["SELECT sleep(3);", "SELECT 1;", "SELECT 2;"]
stdout, stderr = execute_queries_persistent_connection(queries)
@@ -65,5 +61,5 @@ def test_time_limit(started_cluster):
assert "1" not in stdout and "2" not in stdout
assert "TCP_CONNECTION_LIMIT_REACHED" in stderr
- final_count = get_connection_done_count()
+ final_count = get_limit_closed_count("elapsed=")
assert final_count == initial_count + 1, f"Expected exactly 1 connection closure, got {final_count - initial_count}"
diff --git a/tests/queries/0_stateless/01184_long_insert_values_huge_strings.sh b/tests/queries/0_stateless/01184_long_insert_values_huge_strings.sh
index 8d41c32467d2..0973bf5d17d2 100755
--- a/tests/queries/0_stateless/01184_long_insert_values_huge_strings.sh
+++ b/tests/queries/0_stateless/01184_long_insert_values_huge_strings.sh
@@ -17,7 +17,8 @@ done;
wait
$CLICKHOUSE_CLIENT -q "select count() from huge_strings"
-$CLICKHOUSE_CLIENT -q "select sum(l = length(s)) from huge_strings"
-$CLICKHOUSE_CLIENT -q "select sum(h = cityHash64(s)) from huge_strings"
+# Pin `max_threads`: each read stream holds its own buffer for a ~9 MB row of `s`, so the randomized 32-thread draw exceeds `max_memory_usage`.
+$CLICKHOUSE_CLIENT -q "select sum(l = length(s)) from huge_strings SETTINGS max_threads = 3"
+$CLICKHOUSE_CLIENT -q "select sum(h = cityHash64(s)) from huge_strings SETTINGS max_threads = 3"
$CLICKHOUSE_CLIENT -q "drop table huge_strings"
diff --git a/tests/queries/0_stateless/01661_extract_all_groups_throw_fast.sql b/tests/queries/0_stateless/01661_extract_all_groups_throw_fast.sql
index afb6866a0df5..f16e83a6d0f5 100644
--- a/tests/queries/0_stateless/01661_extract_all_groups_throw_fast.sql
+++ b/tests/queries/0_stateless/01661_extract_all_groups_throw_fast.sql
@@ -1,2 +1,4 @@
-SELECT repeat('abcdefghijklmnopqrstuvwxyz', number * 100) AS haystack, extractAllGroupsHorizontal(haystack, '(\\w)') AS matches FROM numbers(1023); -- { serverError TOO_LARGE_ARRAY_SIZE }
+-- 1001 matches in one row exceeds `regexp_max_matches_per_row` (default 1000) and trips the fast-throw.
+-- The low `max_memory_usage` also guards against regressing to a huge fixture that could hit MEMORY_LIMIT_EXCEEDED first.
+SELECT extractAllGroupsHorizontal(materialize(repeat('a', 1001)), '(\\w)') FORMAT Null SETTINGS max_memory_usage = 100000000; -- { serverError TOO_LARGE_ARRAY_SIZE }
SELECT count(extractAllGroupsHorizontal(materialize('a'), '(a)')) FROM numbers(1000000) FORMAT Null; -- shouldn't fail
diff --git a/tests/queries/0_stateless/02040_clickhouse_benchmark_query_id_pass_through.sh b/tests/queries/0_stateless/02040_clickhouse_benchmark_query_id_pass_through.sh
index 59538534fa71..6d084cfd9858 100755
--- a/tests/queries/0_stateless/02040_clickhouse_benchmark_query_id_pass_through.sh
+++ b/tests/queries/0_stateless/02040_clickhouse_benchmark_query_id_pass_through.sh
@@ -6,6 +6,11 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
query_id="${CLICKHOUSE_DATABASE}_$$"
benchmark_args=(
+ # A loaded runner can take longer than the default 10 s handshake_timeout_ms
+ # to send Hello; the benchmark then exits without running a query and
+ # query_log has 0 rows instead of 3.
+ --connect_timeout 60
+ --handshake_timeout_ms 60000
--iterations 1
--log_queries 1
--query_id "$query_id"
diff --git a/tests/queries/0_stateless/02423_ddl_for_opentelemetry.sh b/tests/queries/0_stateless/02423_ddl_for_opentelemetry.sh
index 0dc7b7500797..ef1bff5d47d6 100755
--- a/tests/queries/0_stateless/02423_ddl_for_opentelemetry.sh
+++ b/tests/queries/0_stateless/02423_ddl_for_opentelemetry.sh
@@ -39,17 +39,31 @@ function check_span()
extra_condition=""
fi
- ret=$(${CLICKHOUSE_CLIENT} -q "
- SYSTEM FLUSH LOGS opentelemetry_span_log;
-
- SELECT count()
- FROM system.opentelemetry_span_log
- WHERE finish_date >= yesterday()
- AND lower(hex(trace_id)) = '${2}'
- AND operation_name like '${3}'
- ${extra_condition};")
-
- if [ $ret = $1 ]; then
+ # A span is enqueued into the async opentelemetry_span_log only when its holder is
+ # destroyed, and the TCPHandler holder is destroyed after the client already has its
+ # answer, so a single flush+count can legitimately read a short count. Retry while the
+ # count is below the expectation; a non-numeric result (client or flush error) breaks
+ # out immediately, and the sleep budget is shared by the whole test so a genuinely
+ # broken assertion cannot multiply the added wall time by the number of call sites.
+ for _ in {1..30}; do
+ ret=$(${CLICKHOUSE_CLIENT} -q "
+ SYSTEM FLUSH LOGS opentelemetry_span_log;
+
+ SELECT count()
+ FROM system.opentelemetry_span_log
+ WHERE finish_date >= yesterday()
+ AND lower(hex(trace_id)) = '${2}'
+ AND operation_name like '${3}'
+ ${extra_condition};")
+
+ [[ "$ret" =~ ^[0-9]+$ ]] || break
+ [[ "$ret" -ge "$1" ]] && break
+ [[ "${span_poll_sleeps_left:-0}" -gt 0 ]] || break
+ span_poll_sleeps_left=$((span_poll_sleeps_left - 1))
+ sleep 1
+ done
+
+ if [ "$ret" = "$1" ]; then
echo 1
else
echo "[operation_name like '${3}' ${extra_condition}]=$ret, expected: ${1}"
@@ -79,6 +93,9 @@ cluster_name=$($CLICKHOUSE_CLIENT -q "select if(engine = 'Replicated', name, 'te
#
# Only format_version 4 enables the tracing
#
+# Total number of 1-second sleeps check_span may spend waiting for spans to be enqueued.
+span_poll_sleeps_left=15
+
for ddl_version in 3 4; do
# Echo a separator so that the reference file is more clear for reading
echo "===ddl_format_version ${ddl_version}===="
diff --git a/tests/queries/0_stateless/02465_limit_trivial_max_rows_to_read.sql b/tests/queries/0_stateless/02465_limit_trivial_max_rows_to_read.sql
index 700a54044271..2b6302292b2a 100644
--- a/tests/queries/0_stateless/02465_limit_trivial_max_rows_to_read.sql
+++ b/tests/queries/0_stateless/02465_limit_trivial_max_rows_to_read.sql
@@ -15,7 +15,10 @@ SELECT number FROM numbers(30) LIMIT 21; -- { serverError TOO_MANY_ROWS }
SELECT number FROM numbers(30) LIMIT 1;
SELECT number FROM numbers(5);
-SELECT a FROM t_max_rows_to_read LIMIT 1;
+-- Under parallel replicas this read is split into per-replica mark ranges, so an
+-- ORDER-less LIMIT 1 may legally return any row (CI saw 32, the first row of the
+-- second task). Project a constant: only `max_rows_to_read` is measured here.
+SELECT 0 FROM t_max_rows_to_read LIMIT 1;
SELECT a FROM t_max_rows_to_read LIMIT 11 offset 11; -- { serverError TOO_MANY_ROWS }
SELECT a FROM t_max_rows_to_read WHERE a > 50 LIMIT 1; -- { serverError TOO_MANY_ROWS }
diff --git a/tests/queries/0_stateless/02559_add_parts.reference b/tests/queries/0_stateless/02559_add_parts.reference
index 50bd3725056e..845bf13dd8d9 100644
--- a/tests/queries/0_stateless/02559_add_parts.reference
+++ b/tests/queries/0_stateless/02559_add_parts.reference
@@ -1,4 +1,4 @@
0 0 0
1 1 2
2 2 4
-2 1 2
+1
diff --git a/tests/queries/0_stateless/02559_add_parts.sql b/tests/queries/0_stateless/02559_add_parts.sql
index 9f4e85a32589..b8f427a90537 100644
--- a/tests/queries/0_stateless/02559_add_parts.sql
+++ b/tests/queries/0_stateless/02559_add_parts.sql
@@ -16,5 +16,7 @@ SELECT parts, active_parts,total_marks FROM system.tables WHERE name = 'check_sy
INSERT INTO check_system_tables VALUES (1, 2, 1);
SELECT parts, active_parts,total_marks FROM system.tables WHERE name = 'check_system_tables' AND database = currentDatabase();
ALTER TABLE check_system_tables DETACH PARTITION 1;
-SELECT parts, active_parts,total_marks FROM system.tables WHERE name = 'check_system_tables' AND database = currentDatabase();
+-- `parts` and `total_marks` count Outdated parts too, and reclamation after DETACH is best-effort,
+-- so only `active_parts` is well defined here.
+SELECT active_parts FROM system.tables WHERE name = 'check_system_tables' AND database = currentDatabase();
DROP TABLE IF EXISTS check_system_tables;
diff --git a/tests/queries/0_stateless/02703_max_local_read_bandwidth.sh b/tests/queries/0_stateless/02703_max_local_read_bandwidth.sh
index fb7f47613c1d..9a049fd34d7f 100755
--- a/tests/queries/0_stateless/02703_max_local_read_bandwidth.sh
+++ b/tests/queries/0_stateless/02703_max_local_read_bandwidth.sh
@@ -11,8 +11,10 @@ $CLICKHOUSE_CLIENT -m -q "
create table data (key UInt64 CODEC(NONE)) engine=MergeTree() order by tuple() settings min_bytes_for_wide_part=1e9;
"
-# reading 1e6*8 bytes with 1M bandwith it should take (8-1)/1=7 seconds
-$CLICKHOUSE_CLIENT -q "insert into data select * from numbers(1e6)"
+# Reading 2e5*8 bytes at 160000 B/s takes 1.6e6/160000-1 = 9 seconds (-1 is the 1s token burst).
+# The throttler only sleeps while the arrival rate exceeds the cap, so the cap must stay far
+# below the natural read rate or the sleep assertion flaps on loaded runners.
+$CLICKHOUSE_CLIENT -q "insert into data select * from numbers(2e5)"
read_methods=(
read
@@ -25,14 +27,14 @@ read_methods=(
)
for read_method in "${read_methods[@]}"; do
query_id=$(random_str 10)
- $CLICKHOUSE_CLIENT --query_id "$query_id" -q "select * from data format Null settings max_local_read_bandwidth='1M', local_filesystem_read_method='$read_method'"
+ $CLICKHOUSE_CLIENT --query_id "$query_id" -q "select * from data format Null settings max_local_read_bandwidth=160000, local_filesystem_read_method='$read_method'"
$CLICKHOUSE_CLIENT -m -q "
SYSTEM FLUSH LOGS query_log;
SELECT
'$read_method',
query_duration_ms >= 7e3,
- ProfileEvents['ReadBufferFromFileDescriptorReadBytes'] > 8e6,
- ProfileEvents['QueryLocalReadThrottlerBytes'] > 8e6,
+ ProfileEvents['ReadBufferFromFileDescriptorReadBytes'] > 1.5e6,
+ ProfileEvents['QueryLocalReadThrottlerBytes'] > 1.5e6,
ProfileEvents['QueryLocalReadThrottlerSleepMicroseconds'] > 7e6*0.5
FROM system.query_log
WHERE event_date >= yesterday() AND event_time >= now() - 600 AND current_database = '$CLICKHOUSE_DATABASE' AND query_id = '$query_id' AND type != 'QueryStart'
diff --git a/tests/queries/0_stateless/03100_lwu_15_future_reads.sh b/tests/queries/0_stateless/03100_lwu_15_future_reads.sh
index 3c74ff76ba0d..518dce65dde0 100755
--- a/tests/queries/0_stateless/03100_lwu_15_future_reads.sh
+++ b/tests/queries/0_stateless/03100_lwu_15_future_reads.sh
@@ -26,7 +26,11 @@ $CLICKHOUSE_CLIENT --query "
ORDER BY id
SETTINGS
enable_block_number_column = 1,
- enable_block_offset_column = 1;
+ enable_block_offset_column = 1,
+ -- The test checks the number of rows in patch parts at the end.
+ -- Once the patches are applied, the cleanup thread is free to drop them,
+ -- so keep them around to make the last query deterministic.
+ remove_unused_patch_parts = 0;
INSERT INTO t_lwu_future_reads SELECT number, number FROM numbers(1000);
SYSTEM ENABLE FAILPOINT $failpoint_name;
diff --git a/tests/queries/0_stateless/03356_analyzer_unused_scalar_subquery.sql b/tests/queries/0_stateless/03356_analyzer_unused_scalar_subquery.sql
index cb8594046ad0..90242ab22a2d 100644
--- a/tests/queries/0_stateless/03356_analyzer_unused_scalar_subquery.sql
+++ b/tests/queries/0_stateless/03356_analyzer_unused_scalar_subquery.sql
@@ -1,16 +1,31 @@
+-- An unused scalar subquery or an unused `WITH` expression must not be evaluated,
+-- so `throwIf` never fires. This is checked with `throwIf` rather than with a
+-- timeout, because a timeout makes the test flaky on a loaded machine.
+
set enable_analyzer = 1;
WITH (
- SELECT sleepEachRow(3)
+ SELECT throwIf(1)
) AS res
SELECT *
FROM system.one
-FORMAT Null
-SETTINGS max_execution_time = 2;
+FORMAT Null;
-WITH sleepEachRow(3) AS res
+WITH throwIf(1) AS res
SELECT *
FROM system.one
-FORMAT Null
-SETTINGS max_execution_time = 2;
+FORMAT Null;
+
+-- But it is evaluated when it is actually used.
+WITH (
+ SELECT throwIf(1)
+ ) AS res
+SELECT res
+FROM system.one
+FORMAT Null; -- { serverError FUNCTION_THROW_IF_VALUE_IS_NON_ZERO }
+
+WITH throwIf(1) AS res
+SELECT res
+FROM system.one
+FORMAT Null; -- { serverError FUNCTION_THROW_IF_VALUE_IS_NON_ZERO }
diff --git a/tests/queries/0_stateless/03394_distributed_shuffle_join_with_aggregation.sql b/tests/queries/0_stateless/03394_distributed_shuffle_join_with_aggregation.sql
index cdf868a409fc..9f196df7108b 100644
--- a/tests/queries/0_stateless/03394_distributed_shuffle_join_with_aggregation.sql
+++ b/tests/queries/0_stateless/03394_distributed_shuffle_join_with_aggregation.sql
@@ -14,6 +14,10 @@ INSERT INTO test SELECT 'path_' || number::String, 'en', number FROM numbers(5);
INSERT INTO test SELECT 'path_' || (number%3)::String, 'de', number%4 FROM numbers(10);
SET query_plan_join_swap_table = 0;
+SET query_plan_optimize_join_order_randomize = 0; -- Pinned because the test asserts on join plan/order
+-- Pinned because the test asserts that the runtime join filter is built; the default threshold
+-- skips it when the probe side is estimated to be tiny.
+SET join_runtime_filter_min_probe_rows = 0;
SET
optimize_move_to_prewhere = 1,
diff --git a/tests/queries/0_stateless/03394_distributed_shuffle_join_with_in.sql b/tests/queries/0_stateless/03394_distributed_shuffle_join_with_in.sql
index 6e7680024dc9..655401b1ec40 100644
--- a/tests/queries/0_stateless/03394_distributed_shuffle_join_with_in.sql
+++ b/tests/queries/0_stateless/03394_distributed_shuffle_join_with_in.sql
@@ -14,6 +14,10 @@ INSERT INTO test SELECT 'path_' || number::String, 'en', number FROM numbers(5);
INSERT INTO test SELECT 'path_' || (number%3)::String, 'de', number%4 FROM numbers(10);
SET query_plan_join_swap_table = 0;
+SET query_plan_optimize_join_order_randomize = 0; -- Pinned because the test asserts on join plan/order
+-- Pinned because the test asserts that the runtime join filter is built; the default threshold
+-- skips it when the probe side is estimated to be tiny.
+SET join_runtime_filter_min_probe_rows = 0;
SET