From fb0d5d57858b4560ee8fb53a9216a867de5107de Mon Sep 17 00:00:00 2001 From: Jochen Topf Date: Mon, 18 Sep 2023 10:56:16 +0200 Subject: [PATCH] Add first/last timestamps to expire tables This adds two timestamp (with timezone) columns to all expire tables called "first" and "last". When an entry is added, both are set to the current (transaction) timestamp. When an entry already exists a new insert will result in the "last" timestamp being updated. Having these two timestamps allows various expire/updating strategies, for instance: * update oldest entry * update entry that didn't change for the longest time * update older entries but only if there are no recent changes, which indicates that there might be more changes coming For backwards compatibility the code detects which table format is used and falls back to the old behaviour if the timestamp columns aren't there. --- src/expire-output.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/expire-output.cpp b/src/expire-output.cpp index ef26f5135..6a03aac87 100644 --- a/src/expire-output.cpp +++ b/src/expire-output.cpp @@ -59,10 +59,22 @@ expire_output_t::output_tiles_to_table(quadkey_list_t const &tiles_at_maxzoom, pg_conn_t connection{conninfo}; - connection.exec("PREPARE insert_tiles(int4, int4, int4) AS" - " INSERT INTO {} (zoom, x, y) VALUES ($1, $2, $3)" - " ON CONFLICT DO NOTHING", - qn); + auto const result = connection.exec("SELECT * FROM {} LIMIT 1", qn); + + if (result.num_fields() == 3) { + // old format with fields: zoom, x, y + connection.exec("PREPARE insert_tiles(int4, int4, int4) AS" + " INSERT INTO {} (zoom, x, y) VALUES ($1, $2, $3)" + " ON CONFLICT DO NOTHING", + qn); + } else { + // new format with fields: zoom, x, y, first, last + connection.exec("PREPARE insert_tiles(int4, int4, int4) AS" + " INSERT INTO {} (zoom, x, y) VALUES ($1, $2, $3)" + " ON CONFLICT (zoom, x, y)" + " DO UPDATE SET last = CURRENT_TIMESTAMP(0)", + qn); + } auto const count = for_each_tile( tiles_at_maxzoom, m_minzoom, m_maxzoom, [&](tile_t const &tile) { @@ -76,10 +88,13 @@ expire_output_t::output_tiles_to_table(quadkey_list_t const &tiles_at_maxzoom, void expire_output_t::create_output_table(pg_conn_t const &connection) const { auto const qn = qualified_name(m_schema, m_table); - connection.exec("CREATE TABLE IF NOT EXISTS {} (" - " zoom int4 NOT NULL," - " x int4 NOT NULL," - " y int4 NOT NULL," - " PRIMARY KEY (zoom, x, y))", - qn); + connection.exec( + "CREATE TABLE IF NOT EXISTS {} (" + " zoom int4 NOT NULL," + " x int4 NOT NULL," + " y int4 NOT NULL," + " first timestamp with time zone DEFAULT CURRENT_TIMESTAMP(0)," + " last timestamp with time zone DEFAULT CURRENT_TIMESTAMP(0)," + " PRIMARY KEY (zoom, x, y))", + qn); }