4
4
5
5
import org .firebirdsql .common .FBTestProperties ;
6
6
import org .firebirdsql .common .extension .UsesDatabaseExtension ;
7
+ import org .firebirdsql .util .FirebirdSupportInfo ;
7
8
import org .junit .jupiter .api .AfterAll ;
8
9
import org .junit .jupiter .api .BeforeAll ;
9
10
import org .junit .jupiter .api .Test ;
10
11
import org .junit .jupiter .api .extension .RegisterExtension ;
12
+ import org .junit .jupiter .params .ParameterizedTest ;
13
+ import org .junit .jupiter .params .provider .CsvSource ;
11
14
12
15
import java .sql .Connection ;
13
16
import java .sql .DatabaseMetaData ;
14
17
import java .sql .ResultSet ;
15
18
import java .sql .SQLException ;
16
- import java .util .Arrays ;
19
+ import java .util .ArrayList ;
17
20
import java .util .Collections ;
18
21
import java .util .EnumMap ;
19
22
import java .util .List ;
22
25
import static org .firebirdsql .common .FBTestProperties .getConnectionViaDriverManager ;
23
26
import static org .firebirdsql .common .FBTestProperties .getDefaultSupportInfo ;
24
27
import static org .firebirdsql .common .FBTestProperties .ifSchemaElse ;
28
+ import static org .firebirdsql .common .FBTestProperties .resolveSchema ;
29
+ import static org .firebirdsql .common .FbAssumptions .assumeFeature ;
25
30
import static org .firebirdsql .common .matchers .MatcherAssume .assumeThat ;
26
31
import static org .hamcrest .Matchers .equalToIgnoringCase ;
27
32
import static org .junit .jupiter .api .Assertions .assertEquals ;
33
38
*/
34
39
class FBDatabaseMetaDataTablePrivilegesTest {
35
40
36
- // TODO Add schema support: tests involving other schema
37
-
38
41
private static final String SYSDBA = "SYSDBA" ;
39
42
private static final String USER1 = "USER1" ;
40
43
private static final String user2 = getDefaultSupportInfo ().supportsCaseSensitiveUserNames () ? "user2" : "USER2" ;
41
44
private static final String PUBLIC = "PUBLIC" ;
42
45
43
46
@ 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 ());
52
49
53
50
private static final MetadataResultSetDefinition getTablePrivilegesDefinition =
54
51
new MetadataResultSetDefinition (TablePrivilegesMetadata .class );
@@ -64,6 +61,26 @@ static void setupAll() throws SQLException {
64
61
dbmd = con .getMetaData ();
65
62
}
66
63
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
+
67
84
@ AfterAll
68
85
static void tearDownAll () throws SQLException {
69
86
try {
@@ -84,9 +101,23 @@ void testTablePrivilegesMetaDataColumns() throws Exception {
84
101
}
85
102
}
86
103
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 (
90
121
createRule ("TBL1" , SYSDBA , true , "DELETE" ),
91
122
createRule ("TBL1" , USER1 , false , "DELETE" ),
92
123
createRule ("TBL1" , SYSDBA , true , "INSERT" ),
@@ -99,22 +130,112 @@ void testTablePrivileges_TBL1_all() throws Exception {
99
130
createRule ("TBL1" , SYSDBA , true , "UPDATE" ),
100
131
createRule ("TBL1" , USER1 , false , "UPDATE" ),
101
132
createRule ("TBL1" , user2 , false , "UPDATE" ));
133
+ }
102
134
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 );
104
148
}
105
149
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 (
109
152
createRule ("tbl2" , SYSDBA , true , "DELETE" ),
110
153
createRule ("tbl2" , SYSDBA , true , "INSERT" ),
111
154
createRule ("tbl2" , SYSDBA , true , "REFERENCES" ),
112
155
createRule ("tbl2" , USER1 , false , "REFERENCES" ),
113
156
createRule ("tbl2" , SYSDBA , true , "SELECT" ),
114
157
createRule ("tbl2" , user2 , true , "SELECT" ),
115
158
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
+ }
116
178
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 );
118
239
}
119
240
120
241
private Map <TablePrivilegesMetadata , Object > createRule (String tableName , String grantee , boolean grantable ,
@@ -133,16 +254,16 @@ private Map<TablePrivilegesMetadata, Object> createRule(String schema, String ta
133
254
return rules ;
134
255
}
135
256
136
- private void validateExpectedColumnPrivileges (String tableNamePattern ,
137
- List <Map <TablePrivilegesMetadata , Object >> expectedTablePrivileges ) throws SQLException {
138
- validateExpectedColumnPrivileges (null , tableNamePattern , expectedTablePrivileges );
139
- }
140
-
141
257
private void validateExpectedColumnPrivileges (String schemaPattern , String tableNamePattern ,
142
258
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 )) {
144
260
int privilegeCount = 0 ;
145
261
while (tablePrivileges .next ()) {
262
+ if (isProbablySystemTable (tablePrivileges .getString ("TABLE_SCHEM" ),
263
+ tablePrivileges .getString ("TABLE_NAME" ))) {
264
+ // skip system tables
265
+ continue ;
266
+ }
146
267
if (privilegeCount < expectedTablePrivileges .size ()) {
147
268
Map <TablePrivilegesMetadata , Object > rules = expectedTablePrivileges .get (privilegeCount );
148
269
getTablePrivilegesDefinition .checkValidationRulesComplete (rules );
@@ -154,6 +275,13 @@ private void validateExpectedColumnPrivileges(String schemaPattern, String table
154
275
}
155
276
}
156
277
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
+
157
285
private static final Map <TablePrivilegesMetadata , Object > DEFAULT_TABLE_PRIVILEGES_VALUES ;
158
286
static {
159
287
Map <TablePrivilegesMetadata , Object > defaults = new EnumMap <>(TablePrivilegesMetadata .class );
0 commit comments