@@ -33,6 +33,34 @@ const emptyResponse = {
3333 rows : 0
3434} ;
3535
36+ class MockConnection extends ConnectionV2 {
37+ updateParameters ( params : Record < string , string > ) {
38+ this . parameters = {
39+ ...this . parameters ,
40+ ...params
41+ } ;
42+ }
43+ }
44+
45+ // A hack to allow updating connection parameters stored internally
46+ async function mockConnect ( connectionOptions : ConnectionOptions ) {
47+ const context = {
48+ logger : new Logger ( ) ,
49+ httpClient : new NodeHttpClient ( ) ,
50+ apiEndpoint
51+ } ;
52+ const queryFormatter = new QueryFormatter ( ) ;
53+ const auth = new Authenticator ( context , connectionOptions ) ;
54+ const connection = new MockConnection (
55+ queryFormatter ,
56+ context ,
57+ connectionOptions
58+ ) ;
59+ await auth . authenticate ( ) ;
60+ await connection . resolveEngineEndpoint ( ) ;
61+ return connection ;
62+ }
63+
3664function resetServerHandlers ( server : any ) {
3765 server . use (
3866 rest . post ( `https://id.fake.firebolt.io/oauth/token` , ( req , res , ctx ) => {
@@ -420,34 +448,6 @@ INFO: SYNTAX_ERROR - Unexpected character at {"failingLine":42,"startOffset":120
420448 } )
421449 ) ;
422450
423- class MockConnection extends ConnectionV2 {
424- updateParameters ( params : Record < string , string > ) {
425- this . parameters = {
426- ...this . parameters ,
427- ...params
428- } ;
429- }
430- }
431-
432- // A hack to allow updating connection parameters stored internally
433- async function mockConnect ( connectionOptions : ConnectionOptions ) {
434- const context = {
435- logger : new Logger ( ) ,
436- httpClient : new NodeHttpClient ( ) ,
437- apiEndpoint
438- } ;
439- const queryFormatter = new QueryFormatter ( ) ;
440- const auth = new Authenticator ( context , connectionOptions ) ;
441- const connection = new MockConnection (
442- queryFormatter ,
443- context ,
444- connectionOptions
445- ) ;
446- await auth . authenticate ( ) ;
447- await connection . resolveEngineEndpoint ( ) ;
448- return connection ;
449- }
450-
451451 const connection = await mockConnect ( connectionParams ) ;
452452 connection . updateParameters ( { param : "value" } ) ;
453453
@@ -462,6 +462,247 @@ INFO: SYNTAX_ERROR - Unexpected character at {"failingLine":42,"startOffset":120
462462 expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
463463 } ) ;
464464
465+ it ( "handles remove parameters header" , async ( ) => {
466+ const connectionParams : ConnectionOptions = {
467+ auth : {
468+ client_id : "dummy" ,
469+ client_secret : "dummy"
470+ } ,
471+ database : "dummy" ,
472+ engineName : "dummy" ,
473+ account : "my_account"
474+ } ;
475+
476+ let searchParamsUsed = new URLSearchParams ( ) ;
477+ server . use (
478+ rest . post ( `https://some_engine.com` , async ( req , res , ctx ) => {
479+ const body = await req . text ( ) ;
480+ if ( body . startsWith ( "SELECT 1" ) ) {
481+ // First query - return with remove parameters header
482+ return res (
483+ ctx . json ( selectOneResponse ) ,
484+ ctx . set ( "Firebolt-Remove-Parameters" , "param1,param2" )
485+ ) ;
486+ }
487+ if ( body . startsWith ( "SELECT 2" ) ) {
488+ searchParamsUsed = req . url . searchParams ;
489+ return res ( ctx . json ( selectOneResponse ) ) ;
490+ }
491+ } )
492+ ) ;
493+
494+ const connection = await mockConnect ( connectionParams ) ;
495+ connection . updateParameters ( {
496+ param1 : "value1" ,
497+ param2 : "value2" ,
498+ param3 : "value3"
499+ } ) ;
500+
501+ // Execute query that triggers remove parameters header
502+ await connection . execute ( "SELECT 1" ) ;
503+
504+ // Execute another query to check parameters
505+ await connection . execute ( "SELECT 2" ) ;
506+
507+ expect ( searchParamsUsed . get ( "param1" ) ) . toEqual ( null ) ;
508+ expect ( searchParamsUsed . get ( "param2" ) ) . toEqual ( null ) ;
509+ expect ( searchParamsUsed . get ( "param3" ) ) . toEqual ( "value3" ) ;
510+ expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
511+ } ) ;
512+
513+ it ( "handles remove parameters header with whitespace" , async ( ) => {
514+ const connectionParams : ConnectionOptions = {
515+ auth : {
516+ client_id : "dummy" ,
517+ client_secret : "dummy"
518+ } ,
519+ database : "dummy" ,
520+ engineName : "dummy" ,
521+ account : "my_account"
522+ } ;
523+
524+ let searchParamsUsed = new URLSearchParams ( ) ;
525+ server . use (
526+ rest . post ( `https://some_engine.com` , async ( req , res , ctx ) => {
527+ const body = await req . text ( ) ;
528+ if ( body . startsWith ( "SELECT 1" ) ) {
529+ // Return with remove parameters header containing whitespace
530+ return res (
531+ ctx . json ( selectOneResponse ) ,
532+ ctx . set ( "Firebolt-Remove-Parameters" , " param1 , param2 , param3 " )
533+ ) ;
534+ }
535+ if ( body . startsWith ( "SELECT 2" ) ) {
536+ searchParamsUsed = req . url . searchParams ;
537+ return res ( ctx . json ( selectOneResponse ) ) ;
538+ }
539+ } )
540+ ) ;
541+
542+ const connection = await mockConnect ( connectionParams ) ;
543+ connection . updateParameters ( {
544+ param1 : "value1" ,
545+ param2 : "value2" ,
546+ param3 : "value3" ,
547+ param4 : "value4"
548+ } ) ;
549+
550+ // Execute query that triggers remove parameters header
551+ await connection . execute ( "SELECT 1" ) ;
552+
553+ // Execute another query to check parameters
554+ await connection . execute ( "SELECT 2" ) ;
555+
556+ expect ( searchParamsUsed . get ( "param1" ) ) . toEqual ( null ) ;
557+ expect ( searchParamsUsed . get ( "param2" ) ) . toEqual ( null ) ;
558+ expect ( searchParamsUsed . get ( "param3" ) ) . toEqual ( null ) ;
559+ expect ( searchParamsUsed . get ( "param4" ) ) . toEqual ( "value4" ) ;
560+ expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
561+ } ) ;
562+
563+ it ( "handles remove parameters header with non-existent parameters" , async ( ) => {
564+ const connectionParams : ConnectionOptions = {
565+ auth : {
566+ client_id : "dummy" ,
567+ client_secret : "dummy"
568+ } ,
569+ database : "dummy" ,
570+ engineName : "dummy" ,
571+ account : "my_account"
572+ } ;
573+
574+ let searchParamsUsed = new URLSearchParams ( ) ;
575+ server . use (
576+ rest . post ( `https://some_engine.com` , async ( req , res , ctx ) => {
577+ const body = await req . text ( ) ;
578+ if ( body . startsWith ( "SELECT 1" ) ) {
579+ // Remove both existing and non-existent parameters
580+ return res (
581+ ctx . json ( selectOneResponse ) ,
582+ ctx . set (
583+ "Firebolt-Remove-Parameters" ,
584+ "existing_param,non_existent_param"
585+ )
586+ ) ;
587+ }
588+ if ( body . startsWith ( "SELECT 2" ) ) {
589+ searchParamsUsed = req . url . searchParams ;
590+ return res ( ctx . json ( selectOneResponse ) ) ;
591+ }
592+ } )
593+ ) ;
594+
595+ const connection = await mockConnect ( connectionParams ) ;
596+ connection . updateParameters ( {
597+ existing_param : "value1" ,
598+ other_param : "value2"
599+ } ) ;
600+
601+ // Execute query that triggers remove parameters header
602+ await connection . execute ( "SELECT 1" ) ;
603+
604+ // Execute another query to check parameters
605+ await connection . execute ( "SELECT 2" ) ;
606+
607+ expect ( searchParamsUsed . get ( "existing_param" ) ) . toEqual ( null ) ;
608+ expect ( searchParamsUsed . get ( "non_existent_param" ) ) . toEqual ( null ) ;
609+ expect ( searchParamsUsed . get ( "other_param" ) ) . toEqual ( "value2" ) ;
610+ expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
611+ } ) ;
612+
613+ it ( "handles remove parameters header with single parameter" , async ( ) => {
614+ const connectionParams : ConnectionOptions = {
615+ auth : {
616+ client_id : "dummy" ,
617+ client_secret : "dummy"
618+ } ,
619+ database : "dummy" ,
620+ engineName : "dummy" ,
621+ account : "my_account"
622+ } ;
623+
624+ let searchParamsUsed = new URLSearchParams ( ) ;
625+ server . use (
626+ rest . post ( `https://some_engine.com` , async ( req , res , ctx ) => {
627+ const body = await req . text ( ) ;
628+ if ( body . startsWith ( "SELECT 1" ) ) {
629+ // Remove single parameter
630+ return res (
631+ ctx . json ( selectOneResponse ) ,
632+ ctx . set ( "Firebolt-Remove-Parameters" , "transaction_id" )
633+ ) ;
634+ }
635+ if ( body . startsWith ( "SELECT 2" ) ) {
636+ searchParamsUsed = req . url . searchParams ;
637+ return res ( ctx . json ( selectOneResponse ) ) ;
638+ }
639+ } )
640+ ) ;
641+
642+ const connection = await mockConnect ( connectionParams ) ;
643+ connection . updateParameters ( {
644+ transaction_id : "tx_123" ,
645+ other_param : "value"
646+ } ) ;
647+
648+ // Execute query that triggers remove parameters header
649+ await connection . execute ( "SELECT 1" ) ;
650+
651+ // Execute another query to check parameters
652+ await connection . execute ( "SELECT 2" ) ;
653+
654+ expect ( searchParamsUsed . get ( "transaction_id" ) ) . toEqual ( null ) ;
655+ expect ( searchParamsUsed . get ( "other_param" ) ) . toEqual ( "value" ) ;
656+ expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
657+ } ) ;
658+
659+ it ( "handles empty remove parameters header" , async ( ) => {
660+ const connectionParams : ConnectionOptions = {
661+ auth : {
662+ client_id : "dummy" ,
663+ client_secret : "dummy"
664+ } ,
665+ database : "dummy" ,
666+ engineName : "dummy" ,
667+ account : "my_account"
668+ } ;
669+
670+ let searchParamsUsed = new URLSearchParams ( ) ;
671+ server . use (
672+ rest . post ( `https://some_engine.com` , async ( req , res , ctx ) => {
673+ const body = await req . text ( ) ;
674+ if ( body . startsWith ( "SELECT 1" ) ) {
675+ // Empty remove parameters header
676+ return res (
677+ ctx . json ( selectOneResponse ) ,
678+ ctx . set ( "Firebolt-Remove-Parameters" , "" )
679+ ) ;
680+ }
681+ if ( body . startsWith ( "SELECT 2" ) ) {
682+ searchParamsUsed = req . url . searchParams ;
683+ return res ( ctx . json ( selectOneResponse ) ) ;
684+ }
685+ } )
686+ ) ;
687+
688+ const connection = await mockConnect ( connectionParams ) ;
689+ connection . updateParameters ( {
690+ param1 : "value1" ,
691+ param2 : "value2"
692+ } ) ;
693+
694+ // Execute query that triggers empty remove parameters header
695+ await connection . execute ( "SELECT 1" ) ;
696+
697+ // Execute another query to check parameters
698+ await connection . execute ( "SELECT 2" ) ;
699+
700+ // All parameters should still be present
701+ expect ( searchParamsUsed . get ( "param1" ) ) . toEqual ( "value1" ) ;
702+ expect ( searchParamsUsed . get ( "param2" ) ) . toEqual ( "value2" ) ;
703+ expect ( searchParamsUsed . get ( "database" ) ) . toEqual ( "dummy" ) ;
704+ } ) ;
705+
465706 it ( "handles set statements correctly" , async ( ) => {
466707 let searchParamsUsed = new URLSearchParams ( ) ;
467708 server . use (
0 commit comments