33namespace Keboola \Test \Backend \Snowflake ;
44
55use Keboola \StorageApi \ClientException ;
6+ use Keboola \StorageApi \WorkspaceLoginType ;
67use Keboola \StorageApi \Workspaces ;
78use Keboola \TableBackendUtils \Escaping \Snowflake \SnowflakeQuote ;
89use Keboola \Test \Backend \WorkspaceConnectionTrait ;
910use Keboola \Test \Backend \WorkspaceCredentialsAssertTrait ;
1011use Keboola \Test \Backend \Workspaces \Backend \WorkspaceBackendFactory ;
1112use Keboola \Test \Backend \Workspaces \ParallelWorkspacesTestCase ;
13+ use Keboola \Test \Utils \PemKeyCertificateGenerator ;
1214use PDO ;
1315
1416class WorkspacesQueryTest extends ParallelWorkspacesTestCase
@@ -24,11 +26,18 @@ public function testWorkspaceQuery(): void
2426 $ defaultBranchId = $ this ->getDefaultBranchId ($ this );
2527 $ branchClient = $ this ->getBranchAwareDefaultClient ($ defaultBranchId );
2628 $ workspaces = new Workspaces ($ branchClient );
29+ $ key = (new PemKeyCertificateGenerator ())->createPemKeyCertificate (null );
2730 $ workspace = $ this ->initTestWorkspace (
31+ options: [
32+ 'backend ' => self ::BACKEND_SNOWFLAKE ,
33+ 'loginType ' => WorkspaceLoginType::SNOWFLAKE_PERSON_KEYPAIR ,
34+ 'publicKey ' => $ key ->getPublicKey (),
35+ ],
2836 forceRecreate: true ,
2937 );
3038 $ workspaceId = $ workspace ['id ' ];
31- $ backend = WorkspaceBackendFactory::createWorkspaceBackend ($ workspace );
39+ $ workspace ['connection ' ]['privateKey ' ] = $ key ->getPrivateKey ();
40+ $ backend = WorkspaceBackendFactory::createWorkspaceForSnowflakeDbal ($ workspace );
3241
3342 // Workspace not found
3443 $ exception = null ;
@@ -214,5 +223,148 @@ public function testWorkspaceQuery(): void
214223 'message ' => "An exception occurred while executing a query: SQL compilation error: \nObject 'BLACK_HOLE' does not exist or not authorized. " ,
215224 ],
216225 );
226+
227+ $ table = $ this ->_client ->createTableAsync (
228+ $ this ->getTestBucketId (self ::STAGE_IN ),
229+ 'test ' ,
230+ new \Keboola \Csv \CsvFile (__DIR__ . '/../../_data/languages.csv ' ),
231+ );
232+
233+ $ testDropDatabase = $ workspaces ->executeQuery (
234+ $ workspaceId ,
235+ sprintf ('DROP DATABASE %s ' , $ workspace ['connection ' ]['database ' ]),
236+ );
237+ $ this ->assertSame (
238+ $ testDropDatabase ,
239+ [
240+ 'status ' => 'error ' ,
241+ 'message ' => sprintf ("An exception occurred while executing a query: SQL access control error:
242+ Insufficient privileges to operate on database '%s' " , $ workspace ['connection ' ]['database ' ]),
243+ ],
244+ );
245+
246+ $ testDropSchema = $ workspaces ->executeQuery (
247+ $ workspaceId ,
248+ sprintf ('DROP SCHEMA %s ' , $ workspace ['connection ' ]['schema ' ]),
249+ );
250+ $ this ->assertSame (
251+ $ testDropSchema ,
252+ [
253+ 'status ' => 'error ' ,
254+ 'message ' => sprintf ("An exception occurred while executing a query: SQL access control error:
255+ Insufficient privileges to operate on schema '%s' " , $ workspace ['connection ' ]['schema ' ]),
256+ ],
257+ );
258+
259+ // in most cases project role should be same as project database
260+ $ testUseProjectUserRole = $ workspaces ->executeQuery (
261+ $ workspaceId ,
262+ sprintf ('USE ROLE %s ' , $ workspace ['connection ' ]['database ' ]),
263+ );
264+ $ this ->assertSame (
265+ $ testUseProjectUserRole ,
266+ [
267+ 'status ' => 'error ' ,
268+ 'message ' => 'An exception occurred while executing a query: SQL execution error:
269+ Current session is restricted. USE ROLE not allowed. ' ,
270+ ],
271+ );
272+
273+ $ this ->_client ->createTableAsync (
274+ $ this ->getTestBucketId (self ::STAGE_IN ),
275+ 'test-delete ' ,
276+ new \Keboola \Csv \CsvFile (__DIR__ . '/../../_data/languages.csv ' ),
277+ );
278+
279+ $ testDropTable = $ workspaces ->executeQuery (
280+ $ workspaceId ,
281+ sprintf (
282+ 'DROP TABLE %s.%s."test-delete" ' ,
283+ $ workspace ['connection ' ]['database ' ],
284+ SnowflakeQuote::quoteSingleIdentifier ($ this ->getTestBucketId (self ::STAGE_IN )),
285+ ),
286+ );
287+ $ this ->assertSame (
288+ $ testDropTable ,
289+ [
290+ 'status ' => 'error ' ,
291+ 'message ' => "An exception occurred while executing a query: SQL access control error:
292+ Insufficient privileges to operate on table 'test-delete' " ,
293+ ],
294+ );
295+
296+ // in most cases project role should be same as project database
297+ $ executeImmediate = $ workspaces ->executeQuery (
298+ $ workspaceId ,
299+ sprintf (
300+ <<<EOD
301+ EXECUTE IMMEDIATE $$
302+ BEGIN
303+ USE ROLE %s;
304+ DROP TABLE %s.%s."test-delete";
305+ RETURN 'done';
306+ END;
307+ $$
308+ ;
309+ EOD ,
310+ $ workspace ['connection ' ]['database ' ],
311+ $ workspace ['connection ' ]['database ' ],
312+ SnowflakeQuote::quoteSingleIdentifier ($ this ->getTestBucketId (self ::STAGE_IN )),
313+ ),
314+ );
315+ $ this ->assertSame (
316+ $ executeImmediate ,
317+ [
318+ 'status ' => 'error ' ,
319+ 'message ' => "An exception occurred while executing a query: Uncaught exception of type 'STATEMENT_ERROR' on line 3 at position 2 : SQL execution error:
320+ Current session is restricted. USE ROLE not allowed. " ,
321+ ],
322+ );
323+ }
324+
325+ public function testWorkspaceQueryLegacyService (): void
326+ {
327+ $ defaultBranchId = $ this ->getDefaultBranchId ($ this );
328+ $ branchClient = $ this ->getBranchAwareDefaultClient ($ defaultBranchId );
329+ $ workspaces = new Workspaces ($ branchClient );
330+ $ workspace = $ this ->initTestWorkspace (
331+ options: [
332+ 'backend ' => self ::BACKEND_SNOWFLAKE ,
333+ 'loginType ' => WorkspaceLoginType::SNOWFLAKE_LEGACY_SERVICE_PASSWORD ,
334+ ],
335+ forceRecreate: true ,
336+ );
337+ try {
338+ $ workspaces ->executeQuery (
339+ $ workspace ['id ' ],
340+ sprintf (
341+ 'CREATE OR REPLACE TABLE %s (ID INT, NAME VARCHAR(32)) ' ,
342+ SnowflakeQuote::quoteSingleIdentifier (self ::TABLE ),
343+ ),
344+ );
345+ $ this ->fail ('Executing query on workspace with legacy service login type should fail. ' );
346+ } catch (ClientException $ e ) {
347+ $ this ->assertSame ('storage.executeQuery.notSupportedLoginType ' , $ e ->getStringCode ());
348+ }
349+
350+ $ workspace = $ this ->initTestWorkspace (
351+ options: [
352+ 'backend ' => self ::BACKEND_SNOWFLAKE ,
353+ 'loginType ' => WorkspaceLoginType::DEFAULT ,
354+ ],
355+ forceRecreate: true ,
356+ );
357+ try {
358+ $ workspaces ->executeQuery (
359+ $ workspace ['id ' ],
360+ sprintf (
361+ 'CREATE OR REPLACE TABLE %s (ID INT, NAME VARCHAR(32)) ' ,
362+ SnowflakeQuote::quoteSingleIdentifier (self ::TABLE ),
363+ ),
364+ );
365+ $ this ->fail ('Executing query on workspace with legacy service login type should fail. ' );
366+ } catch (ClientException $ e ) {
367+ $ this ->assertSame ('storage.executeQuery.notSupportedLoginType ' , $ e ->getStringCode ());
368+ }
217369 }
218370}
0 commit comments