Skip to content
Merged
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
28 changes: 24 additions & 4 deletions Darling/Darling.Tests/RestartRowIndexLiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,32 @@ public async Task EachReader_PlansOnItsPartialIndex_OnAnUncompressedChunk_AndRet
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, ct);
await Exec(connection, "SELECT _timescaledb_functions.stop_background_workers()", ct);

var rawNow = DateTime.UtcNow;
var utcNow = DateTime.SpecifyKind(new DateTime(rawNow.Ticks - (rawNow.Ticks % 10)), DateTimeKind.Unspecified);
/* A fixed anchor, 23:50 UTC on a fixed past day, not the wall clock. The seed reaches back 5,000 seconds
from this instant, and chunks are one day aligned to UTC midnight, so a seed ending at the real "now"
straddles two daily chunks between 00:00 and about 01:23 UTC. On either chunk a Seq Scan can then
cost less than the partial index, and the no-heap-scan assertion fails. Ending at 23:50 keeps the
whole seed inside one day. */
var utcNow = new DateTime(2026, 1, 15, 23, 50, 0, DateTimeKind.Unspecified);
var windowStart = utcNow.AddHours(-2);

await SeedAsync(connection, "collect.query_stats", utcNow, ct);
await SeedAsync(connection, "collect.procedure_stats", utcNow, ct);

/* The whole seed must sit in one daily chunk: no row may fall before the anchor's date, and the
chunk must hold a realistic number of rows. */
foreach (var table in new[] { "collect.query_stats", "collect.procedure_stats" })
{
await using var older = new NpgsqlCommand("SELECT count(*) FROM " + table + " WHERE collection_time < $1", connection);
older.Parameters.Add(new NpgsqlParameter { NpgsqlDbType = NpgsqlDbType.Timestamp, Value = utcNow.Date });
var olderRows = Convert.ToInt64(await older.ExecuteScalarAsync(ct), CultureInfo.InvariantCulture);
Assert.True(olderRows == 0, table + " has " + olderRows + " seeded rows before " + utcNow.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + "; the seed must sit inside one daily chunk");

await using var newest = new NpgsqlCommand("SELECT count(*) FROM " + table + " WHERE collection_time >= $1", connection);
newest.Parameters.Add(new NpgsqlParameter { NpgsqlDbType = NpgsqlDbType.Timestamp, Value = utcNow.Date });
var newestRows = Convert.ToInt64(await newest.ExecuteScalarAsync(ct), CultureInfo.InvariantCulture);
Assert.True(newestRows >= 1000, table + " holds only " + newestRows + " seeded rows; the seed must be a realistic day");
}

await TuningStartPasses.ConvergeAsync(connection, ct);
await Exec(connection, "ANALYZE collect.query_stats", ct);
await Exec(connection, "ANALYZE collect.procedure_stats", ct);
Expand Down Expand Up @@ -193,9 +213,9 @@ private static async Task AssertReaderAsync(NpgsqlConnection connection, string
var heapScans = new List<string>();
Collect(doc.RootElement[0].GetProperty("Plan"), reads, heapScans);

Assert.NotEmpty(reads);
Assert.True(reads.Count > 0, "no index read found in the plan:\n" + json);
Assert.All(reads, r => Assert.Contains(indexName, r.Index, StringComparison.Ordinal));
Assert.Empty(heapScans);
Assert.True(heapScans.Count == 0, "the plan scans the heap (" + string.Join(", ", heapScans) + "):\n" + json);
}

/// <summary>
Expand Down
Loading