From 1873f3c5bac8dfe4a6510799e36d1e67fae284ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 19 May 2022 10:32:47 +0200
Subject: [PATCH] sql: add created_at & updated_at columns on wcs_meta table
 (#63466)

---
 tests/test_sql.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++
 wcs/sql.py        | 33 +++++++++++++++++++++++++++----
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/tests/test_sql.py b/tests/test_sql.py
index f932007e8..90d2dd812 100644
--- a/tests/test_sql.py
+++ b/tests/test_sql.py
@@ -1074,6 +1074,56 @@ def index_exists(cur, index_name):
     return bool(cur.fetchone()[0] == 1)
 
 
+def test_wcs_meta_dates(pub):
+    conn, cur = sql.get_connection_and_cursor()
+
+    # reindex flags
+    sql.set_reindex('foo', 'bar', conn=conn, cur=cur)
+    conn.commit()
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('reindex_foo',))
+    row = cur.fetchone()
+    assert row[0] is not None
+    assert row[1] is not None
+    old_created_at = row[0]
+    old_updated_at = row[0]
+
+    sql.set_reindex('foo', 'bar', conn=conn, cur=cur)
+    conn.commit()
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('reindex_foo',))
+    row = cur.fetchone()
+    assert row[0] == old_created_at
+    assert row[1] == old_updated_at
+
+    sql.set_reindex('foo', 'bar-2', conn=conn, cur=cur)
+    conn.commit()
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('reindex_foo',))
+    row = cur.fetchone()
+    assert row[0] == old_created_at
+    assert row[1] != old_updated_at
+
+    # sql_level
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('sql_level',))
+    row = cur.fetchone()
+    assert row[0] is not None
+    assert row[1] is not None
+    old_created_at = row[0]
+    old_updated_at = row[0]
+
+    sql.migrate()
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('sql_level',))
+    row = cur.fetchone()
+    assert row[0] == old_created_at
+    assert row[1] == old_updated_at
+
+    cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', (str(1), 'sql_level'))
+    conn.commit()
+    sql.migrate()
+    cur.execute('SELECT created_at, updated_at FROM wcs_meta WHERE key = %s', ('sql_level',))
+    row = cur.fetchone()
+    assert row[0] == old_created_at
+    assert row[1] != old_updated_at
+
+
 def test_sql_level(pub):
     conn, cur = sql.get_connection_and_cursor()
     cur.execute('DROP TABLE wcs_meta')
diff --git a/wcs/sql.py b/wcs/sql.py
index b6f18be83..dca9839bc 100644
--- a/wcs/sql.py
+++ b/wcs/sql.py
@@ -1487,12 +1487,17 @@ def do_meta_table(conn=None, cur=None, insert_current_sql_level=True):
                       AND table_name = %s''',
         ('wcs_meta',),
     )
-    if cur.fetchone()[0] == 0:
+    table_exists = cur.fetchone()[0] > 0
+
+    if not table_exists:
         cur.execute(
             '''CREATE TABLE wcs_meta (id serial PRIMARY KEY,
                                     key varchar,
-                                    value varchar)'''
+                                    value varchar,
+                                    created_at timestamptz DEFAULT NOW(),
+                                    updated_at timestamptz DEFAULT NOW())'''
         )
+
         if insert_current_sql_level:
             sql_level = SQL_LEVEL[0]
         else:
@@ -1503,6 +1508,19 @@ def do_meta_table(conn=None, cur=None, insert_current_sql_level=True):
             ('sql_level', str(sql_level)),
         )
 
+    else:
+        cur.execute(
+            '''SELECT column_name FROM information_schema.columns
+                        WHERE table_schema = 'public'
+                          AND table_name = %s''',
+            ('wcs_meta',),
+        )
+        existing_fields = {x[0] for x in cur.fetchall()}
+        if 'created_at' not in existing_fields:
+            cur.execute('''ALTER TABLE wcs_meta ADD COLUMN created_at timestamptz DEFAULT NOW()''')
+        if 'updated_at' not in existing_fields:
+            cur.execute('''ALTER TABLE wcs_meta ADD COLUMN updated_at timestamptz DEFAULT NOW()''')
+
     if own_conn:
         conn.commit()
         cur.close()
@@ -4153,7 +4171,10 @@ def set_reindex(index, value, conn=None, cur=None):
             (key_name, value),
         )
     else:
-        cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', (value, key_name))
+        if row[0] != value:
+            cur.execute(
+                '''UPDATE wcs_meta SET value = %s, updated_at = NOW() WHERE key = %s''', (value, key_name)
+            )
     if own_conn:
         conn.commit()
         cur.close()
@@ -4315,7 +4336,11 @@ def migrate():
         for formdef in FormDef.select():
             do_formdef_tables(formdef, rebuild_views=False, rebuild_global_views=False)
 
-    cur.execute('''UPDATE wcs_meta SET value = %s WHERE key = %s''', (str(SQL_LEVEL[0]), 'sql_level'))
+    if sql_level != SQL_LEVEL[0]:
+        cur.execute(
+            '''UPDATE wcs_meta SET value = %s, updated_at=NOW() WHERE key = %s''',
+            (str(SQL_LEVEL[0]), 'sql_level'),
+        )
 
     conn.commit()
     cur.close()
-- 
2.35.1

