44
55import org .firebirdsql .common .FBTestProperties ;
66import org .firebirdsql .common .extension .UsesDatabaseExtension ;
7+ import org .firebirdsql .util .FirebirdSupportInfo ;
78import org .junit .jupiter .api .AfterAll ;
89import org .junit .jupiter .api .BeforeAll ;
910import org .junit .jupiter .api .Test ;
1011import org .junit .jupiter .api .extension .RegisterExtension ;
12+ import org .junit .jupiter .params .ParameterizedTest ;
13+ import org .junit .jupiter .params .provider .CsvSource ;
1114
1215import java .sql .Connection ;
1316import java .sql .DatabaseMetaData ;
1417import java .sql .ResultSet ;
1518import java .sql .SQLException ;
16- import java .util .Arrays ;
19+ import java .util .ArrayList ;
1720import java .util .Collections ;
1821import java .util .EnumMap ;
1922import java .util .List ;
2225import static org .firebirdsql .common .FBTestProperties .getConnectionViaDriverManager ;
2326import static org .firebirdsql .common .FBTestProperties .getDefaultSupportInfo ;
2427import static org .firebirdsql .common .FBTestProperties .ifSchemaElse ;
28+ import static org .firebirdsql .common .FBTestProperties .resolveSchema ;
29+ import static org .firebirdsql .common .FbAssumptions .assumeFeature ;
2530import static org .firebirdsql .common .matchers .MatcherAssume .assumeThat ;
2631import static org .hamcrest .Matchers .equalToIgnoringCase ;
2732import static org .junit .jupiter .api .Assertions .assertEquals ;
3338 */
3439class FBDatabaseMetaDataTablePrivilegesTest {
3540
36- // TODO Add schema support: tests involving other schema
37-
3841 private static final String SYSDBA = "SYSDBA" ;
3942 private static final String USER1 = "USER1" ;
4043 private static final String user2 = getDefaultSupportInfo ().supportsCaseSensitiveUserNames () ? "user2" : "USER2" ;
4144 private static final String PUBLIC = "PUBLIC" ;
4245
4346 @ RegisterExtension
44- static final UsesDatabaseExtension .UsesDatabaseForAll usesDatabase = UsesDatabaseExtension .usesDatabaseForAll (
45- "create table TBL1 (COL1 integer, COL2 varchar(50), \" val3\" varchar(50))" ,
46- "create table \" tbl2\" (COL1 integer, COL2 varchar(50), \" val3\" varchar(50))" ,
47- "grant all on TBL1 to USER1" ,
48- "grant select on TBL1 to PUBLIC" ,
49- "grant update (COL1, \" val3\" ) on TBL1 to \" user2\" " ,
50- "grant select on \" tbl2\" to \" user2\" with grant option" ,
51- "grant references (COL1) on \" tbl2\" to USER1" );
47+ static final UsesDatabaseExtension .UsesDatabaseForAll usesDatabase =
48+ UsesDatabaseExtension .usesDatabaseForAll (createDbInitStatements ());
5249
5350 private static final MetadataResultSetDefinition getTablePrivilegesDefinition =
5451 new MetadataResultSetDefinition (TablePrivilegesMetadata .class );
@@ -64,6 +61,26 @@ static void setupAll() throws SQLException {
6461 dbmd = con .getMetaData ();
6562 }
6663
64+ private static List <String > createDbInitStatements () {
65+ var statements = new ArrayList <>(List .of (
66+ "create table TBL1 (COL1 integer, COL2 varchar(50), \" val3\" varchar(50))" ,
67+ "create table \" tbl2\" (COL1 integer, COL2 varchar(50), \" val3\" varchar(50))" ,
68+ "grant all on TBL1 to USER1" ,
69+ "grant select on TBL1 to PUBLIC" ,
70+ "grant update (COL1, \" val3\" ) on TBL1 to \" user2\" " ,
71+ "grant select on \" tbl2\" to \" user2\" with grant option" ,
72+ "grant references (COL1) on \" tbl2\" to USER1" ));
73+ if (getDefaultSupportInfo ().supportsSchemas ()) {
74+ statements .addAll (List .of (
75+ "create schema OTHER_SCHEMA" ,
76+ "create table OTHER_SCHEMA.TBL3 (COL1 integer, COL2 varchar(50))" ,
77+ "grant all on OTHER_SCHEMA.TBL3 to USER1" ,
78+ "grant select on OTHER_SCHEMA.TBL3 to \" user2\" " ));
79+ }
80+
81+ return statements ;
82+ }
83+
6784 @ AfterAll
6885 static void tearDownAll () throws SQLException {
6986 try {
@@ -84,9 +101,23 @@ void testTablePrivilegesMetaDataColumns() throws Exception {
84101 }
85102 }
86103
87- @ Test
88- void testTablePrivileges_TBL1_all () throws Exception {
89- List <Map <TablePrivilegesMetadata , Object >> rules = Arrays .asList (
104+ @ ParameterizedTest
105+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
106+ schemaPattern, tableNamePattern
107+ <NIL>, TBL1
108+ %, TBL1
109+ PUBLIC, TBL1
110+ #NOTE: Only works because there is no other TBL_ in default schema
111+ PUBLIC, TBL_
112+ """ )
113+ void testTablePrivileges_TBL1_all (String schemaPattern , String tableNamePattern ) throws Exception {
114+ List <Map <TablePrivilegesMetadata , Object >> rules = getTBL1_all ();
115+
116+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
117+ }
118+
119+ private List <Map <TablePrivilegesMetadata , Object >> getTBL1_all () {
120+ return List .of (
90121 createRule ("TBL1" , SYSDBA , true , "DELETE" ),
91122 createRule ("TBL1" , USER1 , false , "DELETE" ),
92123 createRule ("TBL1" , SYSDBA , true , "INSERT" ),
@@ -99,22 +130,112 @@ void testTablePrivileges_TBL1_all() throws Exception {
99130 createRule ("TBL1" , SYSDBA , true , "UPDATE" ),
100131 createRule ("TBL1" , USER1 , false , "UPDATE" ),
101132 createRule ("TBL1" , user2 , false , "UPDATE" ));
133+ }
102134
103- validateExpectedColumnPrivileges ("TBL1" , rules );
135+ @ ParameterizedTest
136+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
137+ schemaPattern, tableNamePattern
138+ <NIL>, tbl2
139+ %, tbl2
140+ PUBLIC, tbl2
141+ #NOTE: Only works because there is no other tbl_ in default schema
142+ PUBLIC, tbl_
143+ """ )
144+ void testColumnPrivileges_tbl2_all (String schemaPattern , String tableNamePattern ) throws Exception {
145+ List <Map <TablePrivilegesMetadata , Object >> rules = getTbl2_all ();
146+
147+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
104148 }
105149
106- @ Test
107- void testColumnPrivileges_tbl2_all () throws Exception {
108- List <Map <TablePrivilegesMetadata , Object >> rules = Arrays .asList (
150+ private List <Map <TablePrivilegesMetadata , Object >> getTbl2_all () {
151+ return List .of (
109152 createRule ("tbl2" , SYSDBA , true , "DELETE" ),
110153 createRule ("tbl2" , SYSDBA , true , "INSERT" ),
111154 createRule ("tbl2" , SYSDBA , true , "REFERENCES" ),
112155 createRule ("tbl2" , USER1 , false , "REFERENCES" ),
113156 createRule ("tbl2" , SYSDBA , true , "SELECT" ),
114157 createRule ("tbl2" , user2 , true , "SELECT" ),
115158 createRule ("tbl2" , SYSDBA , true , "UPDATE" ));
159+ }
160+
161+ @ ParameterizedTest
162+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
163+ schemaPattern, tableNamePattern
164+ <NIL>, TBL3
165+ %, TBL3
166+ OTHER_SCHEMA, TBL3
167+ OTHER\\ _SCHEMA, TBL3
168+ OTHER%, TBL3
169+ #NOTE: Only works because there is no other TBL_ in OTHER_SCHEMA
170+ OTHER_SCHEMA, TBL_
171+ """ )
172+ void testColumnPrivileges_otherSchemaTBL3_all (String schemaPattern , String tableNamePattern ) throws Exception {
173+ assumeFeature (FirebirdSupportInfo ::supportsSchemas , "Test requires schema support" );
174+ List <Map <TablePrivilegesMetadata , Object >> rules = getTBL3_all ();
175+
176+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
177+ }
116178
117- validateExpectedColumnPrivileges ("tbl2" , rules );
179+ private List <Map <TablePrivilegesMetadata , Object >> getTBL3_all () {
180+ return List .of (
181+ createRule ("OTHER_SCHEMA" , "TBL3" , SYSDBA , true , "DELETE" ),
182+ createRule ("OTHER_SCHEMA" , "TBL3" , USER1 , false , "DELETE" ),
183+ createRule ("OTHER_SCHEMA" , "TBL3" , SYSDBA , true , "INSERT" ),
184+ createRule ("OTHER_SCHEMA" , "TBL3" , USER1 , false , "INSERT" ),
185+ createRule ("OTHER_SCHEMA" , "TBL3" , SYSDBA , true , "REFERENCES" ),
186+ createRule ("OTHER_SCHEMA" , "TBL3" , USER1 , false , "REFERENCES" ),
187+ createRule ("OTHER_SCHEMA" , "TBL3" , SYSDBA , true , "SELECT" ),
188+ createRule ("OTHER_SCHEMA" , "TBL3" , USER1 , false , "SELECT" ),
189+ createRule ("OTHER_SCHEMA" , "TBL3" , user2 , false , "SELECT" ),
190+ createRule ("OTHER_SCHEMA" , "TBL3" , SYSDBA , true , "UPDATE" ),
191+ createRule ("OTHER_SCHEMA" , "TBL3" , USER1 , false , "UPDATE" ));
192+ }
193+
194+ @ ParameterizedTest
195+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
196+ schemaPattern, tableNamePattern
197+ <NIL>, <NIL>
198+ %, <NIL>
199+ <NIL>, %
200+ %, %
201+ """ )
202+ void testColumnPrivileges_all (String schemaPattern , String tableNamePattern ) throws Exception {
203+ var rules = new ArrayList <Map <TablePrivilegesMetadata , Object >>();
204+ if (getDefaultSupportInfo ().supportsSchemas ()) {
205+ rules .addAll (getTBL3_all ());
206+ }
207+ rules .addAll (getTBL1_all ());
208+ rules .addAll (getTbl2_all ());
209+
210+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
211+ }
212+
213+ @ ParameterizedTest
214+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
215+ schemaPattern, tableNamePattern
216+ PUBLIC, <NIL>
217+ PUBLIC, %
218+ """ )
219+ void testColumnPrivileges_defaultSchema_all (String schemaPattern , String tableNamePattern ) throws Exception {
220+ var rules = new ArrayList <Map <TablePrivilegesMetadata , Object >>();
221+ rules .addAll (getTBL1_all ());
222+ rules .addAll (getTbl2_all ());
223+
224+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
225+ }
226+
227+ @ ParameterizedTest
228+ @ CsvSource (useHeadersInDisplayName = true , nullValues = "<NIL>" , textBlock = """
229+ schemaPattern, tableNamePattern
230+ OTHER_SCHEMA, <NIL>
231+ OTHER\\ _SCHEMA, %
232+ OTHER%, <NIL>
233+ """ )
234+ void testColumnPrivileges_otherSchema_all (String schemaPattern , String tableNamePattern ) throws Exception {
235+ assumeFeature (FirebirdSupportInfo ::supportsSchemas , "Test requires schema support" );
236+ List <Map <TablePrivilegesMetadata , Object >> rules = getTBL3_all ();
237+
238+ validateExpectedColumnPrivileges (schemaPattern , tableNamePattern , rules );
118239 }
119240
120241 private Map <TablePrivilegesMetadata , Object > createRule (String tableName , String grantee , boolean grantable ,
@@ -133,16 +254,16 @@ private Map<TablePrivilegesMetadata, Object> createRule(String schema, String ta
133254 return rules ;
134255 }
135256
136- private void validateExpectedColumnPrivileges (String tableNamePattern ,
137- List <Map <TablePrivilegesMetadata , Object >> expectedTablePrivileges ) throws SQLException {
138- validateExpectedColumnPrivileges (null , tableNamePattern , expectedTablePrivileges );
139- }
140-
141257 private void validateExpectedColumnPrivileges (String schemaPattern , String tableNamePattern ,
142258 List <Map <TablePrivilegesMetadata , Object >> expectedTablePrivileges ) throws SQLException {
143- try (ResultSet tablePrivileges = dbmd .getTablePrivileges (null , schemaPattern , tableNamePattern )) {
259+ try (ResultSet tablePrivileges = dbmd .getTablePrivileges (null , resolveSchema ( schemaPattern ) , tableNamePattern )) {
144260 int privilegeCount = 0 ;
145261 while (tablePrivileges .next ()) {
262+ if (isProbablySystemTable (tablePrivileges .getString ("TABLE_SCHEM" ),
263+ tablePrivileges .getString ("TABLE_NAME" ))) {
264+ // skip system tables
265+ continue ;
266+ }
146267 if (privilegeCount < expectedTablePrivileges .size ()) {
147268 Map <TablePrivilegesMetadata , Object > rules = expectedTablePrivileges .get (privilegeCount );
148269 getTablePrivilegesDefinition .checkValidationRulesComplete (rules );
@@ -154,6 +275,13 @@ private void validateExpectedColumnPrivileges(String schemaPattern, String table
154275 }
155276 }
156277
278+ private static boolean isProbablySystemTable (String schema , String tableName ) {
279+ return "SYSTEM" .equals (schema )
280+ || tableName .startsWith ("RDB$" )
281+ || tableName .startsWith ("MON$" )
282+ || tableName .startsWith ("SEC$" );
283+ }
284+
157285 private static final Map <TablePrivilegesMetadata , Object > DEFAULT_TABLE_PRIVILEGES_VALUES ;
158286 static {
159287 Map <TablePrivilegesMetadata , Object > defaults = new EnumMap <>(TablePrivilegesMetadata .class );
0 commit comments