11import unittest
22from crate .client import connect
3+ from crate .client .exceptions import ProgrammingError
4+
35from crate .qa .tests import NodeProvider , insert_data , wait_for_active_shards , UpgradePath
46
57ROLLING_UPGRADES_V4 = (
@@ -103,14 +105,34 @@ def _test_rolling_upgrade(self, path, nodes):
103105 ) CLUSTERED INTO { shards } SHARDS
104106 WITH (number_of_replicas={ replicas } )
105107 ''' )
108+ c .execute ("deny dql on table doc.t1 to arthur" )
106109 c .execute ("CREATE VIEW doc.v1 AS SELECT type, title, value FROM doc.t1" )
107110 insert_data (conn , 'doc' , 't1' , 1000 )
108-
109111 c .execute ("INSERT INTO doc.t1 (type, value, title, author) VALUES (1, 1, 'matchMe title', {name='no match name'})" )
110112 c .execute ("INSERT INTO doc.t1 (type, value, title, author) VALUES (2, 2, 'no match title', {name='matchMe name'})" )
111-
112113 c .execute ("INSERT INTO doc.t1 (title, author, o) VALUES ('prefix_check', {\" dyn_empty_array\" = []}, {\" dyn_ignored_subcol\" = 'hello'})" )
113114
115+ if int (path .from_version .split ('.' )[0 ]) >= 5 :
116+ c .execute ('''
117+ create table doc.t2 (
118+ a int primary key,
119+ b int not null,
120+ c int default (random() + 1),
121+ d generated always as (a + b + c),
122+ constraint d CHECK (d > a + b)
123+ ) clustered into 1 shards with (number_of_replicas = 0)
124+ ''' )
125+ expected_active_shards += 1
126+ c .execute ('''
127+ create table doc.t3 (
128+ a int primary key,
129+ b int not null,
130+ c int default (random() + 1),
131+ d generated always as (a + b + c),
132+ constraint d CHECK (d > a + b)
133+ ) partitioned by (a) clustered into 1 shards with (number_of_replicas = 0)
134+ ''' )
135+
114136 c .execute ('''
115137 CREATE FUNCTION foo(INT)
116138 RETURNS INT
@@ -148,8 +170,13 @@ def _test_rolling_upgrade(self, path, nodes):
148170 # Run a query as a user created on an older version (ensure user is read correctly from cluster state, auth works, etc)
149171 with connect (cluster .node ().http_url , username = 'arthur' , password = 'secret' , error_trace = True ) as custom_user_conn :
150172 c = custom_user_conn .cursor ()
151- wait_for_active_shards (c , expected_active_shards )
173+ wait_for_active_shards (c )
152174 c .execute ("SELECT 1" )
175+ # has no privilege
176+ with self .assertRaises (ProgrammingError ):
177+ c .execute ("EXPLAIN SELECT * FROM doc.t1" )
178+ # has privilege
179+ c .execute ("EXPLAIN SELECT * FROM doc.v1" )
153180
154181 cluster [idx ] = new_node
155182 with connect (new_node .http_url , error_trace = True ) as conn :
@@ -159,8 +186,11 @@ def _test_rolling_upgrade(self, path, nodes):
159186 c .execute ("select name from sys.users order by 1" )
160187 self .assertEqual (c .fetchall (), [["arthur" ], ["crate" ]])
161188
162- c .execute ("select * from sys.privileges" )
163- self .assertEqual (c .fetchall (), [["CLUSTER" , "arthur" , "crate" , None , "GRANT" , "DQL" ]])
189+ c .execute ("select * from sys.privileges order by ident" )
190+ self .assertEqual (
191+ c .fetchall (),
192+ [['TABLE' , 'arthur' , 'crate' , 'doc.t1' , 'DENY' , 'DQL' ],
193+ ['CLUSTER' , 'arthur' , 'crate' , None , 'GRANT' , 'DQL' ]])
164194
165195 c .execute ('''
166196 SELECT type, AVG(value)
@@ -225,6 +255,33 @@ def _test_rolling_upgrade(self, path, nodes):
225255 # Add the shards of the new partition primaries
226256 expected_active_shards += shards
227257
258+ # Ensure table/partition versions created are correct
259+ if int (path .from_version .split ('.' )[0 ]) >= 5 :
260+ c .execute ("insert into doc.t2(a, b) values (?, ?)" , [idx , idx ])
261+ c .execute ("refresh table t2" )
262+ c .execute ("select a, b, c>=1 and c<=2, d>a+b from doc.t2 where a = ?" , [idx ])
263+ self .assertEqual (c .fetchall (), [[idx , idx , True , True ]])
264+ old_version = '.' .join (map (str , node .version ))
265+ c .execute ("select distinct(version['created']) from information_schema.tables where table_name = 't2'" )
266+ self .assertEqual (c .fetchall (), [[old_version ]])
267+ # There was a behavior change in 5.9. After fully upgrading all nodes in the cluster, newly added
268+ # partitions' version created will follow the upgraded version.
269+ # E.g., when 5.9 -> 5.10 is completed, the version created for new partitions will be 5.10
270+ if int (path .from_version .split ('.' )[1 ]) >= 9 :
271+ c .execute ("insert into doc.t3(a, b) values (?, ?)" , [idx , idx ])
272+ expected_active_shards += 1
273+ c .execute ("refresh table t3" )
274+ c .execute ("select a, b, c>=1 and c<=2, d>a+b from doc.t3 where a = ?" , [idx ])
275+ self .assertEqual (c .fetchall (), [[idx , idx , True , True ]])
276+ c .execute ("select distinct(version['created']) from information_schema.tables where table_name = 't3'" )
277+ self .assertEqual (c .fetchall (), [[old_version ]])
278+ partition_version = old_version
279+ if idx == nodes - 1 :
280+ # the partition added after all nodes are upgraded should follow the upgraded(latest) version
281+ partition_version = '.' .join (map (str , new_node .version ))
282+ c .execute ("select version['created'] from information_schema.table_partitions where table_name = 't3' and values['a'] = ?" , [idx ])
283+ self .assertEqual (c .fetchall (), [[partition_version ]])
284+
228285 # Finally validate that all shards (primaries and replicas) of all partitions are started
229286 # and writes into the partitioned table while upgrading were successful
230287 with connect (cluster .node ().http_url , error_trace = True ) as conn :
@@ -239,3 +296,14 @@ def _test_rolling_upgrade(self, path, nodes):
239296 ''' )
240297 res = c .fetchone ()
241298 self .assertEqual (res [0 ], nodes + 1 )
299+
300+ # Ensure Arthur can be dropped and re-added
301+ c .execute ("drop user arthur" )
302+ c .execute ("select * from sys.privileges" )
303+ self .assertEqual (c .fetchall (), [])
304+
305+ # Ensure view 'v' can be dropped and re-added
306+ c .execute ("DROP VIEW doc.v1" )
307+ c .execute ("CREATE VIEW doc.v1 AS SELECT 11" )
308+ c .execute ("SELECT * FROM doc.v1" )
309+ self .assertEqual (c .fetchall (), [[11 ]])
0 commit comments