Skip to content

Improve metadata bwc tests #352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
74 changes: 69 additions & 5 deletions tests/bwc/test_rolling_upgrade.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest
from crate.client import connect
from crate.client.exceptions import ProgrammingError

from crate.qa.tests import NodeProvider, insert_data, wait_for_active_shards, UpgradePath

ROLLING_UPGRADES_V4 = (
Expand Down Expand Up @@ -103,14 +105,34 @@ def _test_rolling_upgrade(self, path, nodes):
) CLUSTERED INTO {shards} SHARDS
WITH (number_of_replicas={replicas})
''')
c.execute("deny dql on table doc.t1 to arthur")
c.execute("CREATE VIEW doc.v1 AS SELECT type, title, value FROM doc.t1")
insert_data(conn, 'doc', 't1', 1000)

c.execute("INSERT INTO doc.t1 (type, value, title, author) VALUES (1, 1, 'matchMe title', {name='no match name'})")
c.execute("INSERT INTO doc.t1 (type, value, title, author) VALUES (2, 2, 'no match title', {name='matchMe name'})")

c.execute("INSERT INTO doc.t1 (title, author, o) VALUES ('prefix_check', {\"dyn_empty_array\" = []}, {\"dyn_ignored_subcol\" = 'hello'})")

if int(path.from_version.split('.')[0]) >= 5:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constraint causes a syntax error and the create fails, iirc 4.6.

c.execute('''
create table doc.t2 (
a int primary key,
b int not null,
c int default (random() + 1),
d generated always as (a + b + c),
constraint d CHECK (d > a + b)
) clustered into 1 shards with (number_of_replicas = 0)
''')
expected_active_shards += 1
c.execute('''
create table doc.t3 (
a int primary key,
b int not null,
c int default (random() + 1),
d generated always as (a + b + c),
constraint d CHECK (d > a + b)
) partitioned by (a) clustered into 1 shards with (number_of_replicas = 0)
''')

c.execute('''
CREATE FUNCTION foo(INT)
RETURNS INT
Expand Down Expand Up @@ -148,8 +170,13 @@ def _test_rolling_upgrade(self, path, nodes):
# Run a query as a user created on an older version (ensure user is read correctly from cluster state, auth works, etc)
with connect(cluster.node().http_url, username='arthur', password='secret', error_trace=True) as custom_user_conn:
c = custom_user_conn.cursor()
wait_for_active_shards(c, expected_active_shards)
wait_for_active_shards(c)
Copy link
Contributor Author

@jeeminso jeeminso May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behaviour change starting 5.6. With deny dql on table doc.t1 to arthur, arthur cannot see t1 anymore -> cannot wait for t1 to be active anymore.

We could add version dependent behaviours or simply wait for all shards to be active.

c.execute("SELECT 1")
# has no privilege
with self.assertRaises(ProgrammingError):
c.execute("EXPLAIN SELECT * FROM doc.t1")
# has privilege
c.execute("EXPLAIN SELECT * FROM doc.v1")

cluster[idx] = new_node
with connect(new_node.http_url, error_trace=True) as conn:
Expand All @@ -159,8 +186,11 @@ def _test_rolling_upgrade(self, path, nodes):
c.execute("select name from sys.users order by 1")
self.assertEqual(c.fetchall(), [["arthur"], ["crate"]])

c.execute("select * from sys.privileges")
self.assertEqual(c.fetchall(), [["CLUSTER", "arthur", "crate", None, "GRANT", "DQL"]])
c.execute("select * from sys.privileges order by ident")
self.assertEqual(
c.fetchall(),
[['TABLE', 'arthur', 'crate', 'doc.t1', 'DENY', 'DQL'],
['CLUSTER', 'arthur', 'crate', None, 'GRANT', 'DQL']])

c.execute('''
SELECT type, AVG(value)
Expand Down Expand Up @@ -225,6 +255,29 @@ def _test_rolling_upgrade(self, path, nodes):
# Add the shards of the new partition primaries
expected_active_shards += shards

if int(path.from_version.split('.')[0]) >= 5:
c.execute(f"insert into doc.t2(a, b) values ({idx}, {idx})")
c.execute("refresh table t2")
c.execute(f"select a, b, c>=1 and c<=2, d>a+b from doc.t2 where a = {idx}")
self.assertEqual(c.fetchall(), [[idx, idx, True, True]])
old_version = '.'.join(map(str, node.version))
c.execute("select distinct(version['created']) from information_schema.tables where table_name = 't2'")
self.assertEqual(c.fetchall(), [[old_version]])
if int(path.from_version.split('.')[1]) >= 9:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After all nodes are upgraded, newly added partitions' versions follow the newer version, starting 5.9.

c.execute(f"insert into doc.t3(a, b) values ({idx}, {idx})")
expected_active_shards += 1
c.execute("refresh table t3")
c.execute(f"select a, b, c>=1 and c<=2, d>a+b from doc.t3 where a = {idx}")
self.assertEqual(c.fetchall(), [[idx, idx, True, True]])
c.execute("select distinct(version['created']) from information_schema.tables where table_name = 't3'")
self.assertEqual(c.fetchall(), [[old_version]])
partition_version = old_version
# after all 3 nodes are upgraded, newly created partition's version should follow the newer version
if idx == 2:
partition_version = '.'.join(map(str, new_node.version))
c.execute(f"select version['created'] from information_schema.table_partitions where table_name = 't3' and values['a'] = {idx}")
self.assertEqual(c.fetchall(), [[partition_version]])

# Finally validate that all shards (primaries and replicas) of all partitions are started
# and writes into the partitioned table while upgrading were successful
with connect(cluster.node().http_url, error_trace=True) as conn:
Expand All @@ -239,3 +292,14 @@ def _test_rolling_upgrade(self, path, nodes):
''')
res = c.fetchone()
self.assertEqual(res[0], nodes + 1)

# Ensure Arthur can be dropped and re-added
c.execute("drop user arthur")
c.execute("select * from sys.privileges")
self.assertEqual(c.fetchall(), [])

# Ensure view 'v' can be dropped and re-added
c.execute("DROP VIEW doc.v1")
c.execute("CREATE VIEW doc.v1 AS SELECT 11")
c.execute("SELECT * FROM doc.v1")
self.assertEqual(c.fetchall(), [[11]])