@@ -516,3 +516,81 @@ def test_qcc_updated_regardless_of_query_success(success):
516516 entry_ids = {e .id for e in conn .query_context_cache ._get_elements ()}
517517 assert 1 in entry_ids , "Original entry should still be present"
518518 assert 2 in entry_ids , "New entry from server response should have been merged"
519+
520+
521+ def test_qcc_not_shrunk_after_failed_query_with_hybrid_table ():
522+ """SNOW-3010877: QCC must not shrink when a query on a hybrid table fails.
523+
524+ Simulates the hybrid table scenario: a successful INSERT populates
525+ the QCC with 2 entries (main + DPO), then a duplicate-key INSERT
526+ fails but the server still sends queryContext in the error response.
527+ The connector must merge it so the cache does not shrink.
528+ """
529+ from snowflake .connector .connection import SnowflakeConnection
530+
531+ conn = MagicMock ()
532+ conn ._disable_query_context_cache = False
533+ conn .is_query_context_cache_disabled = False
534+ conn .query_context_cache = QueryContextCache (5 )
535+ conn .query_context_cache_size = 5
536+
537+ conn .get_query_context = types .MethodType (
538+ SnowflakeConnection .get_query_context , conn
539+ )
540+ conn .set_query_context = types .MethodType (
541+ SnowflakeConnection .set_query_context , conn
542+ )
543+
544+ # Q1 — successful insert: server returns queryContext with 2 entries
545+ conn .rest .request .return_value = {
546+ "success" : True ,
547+ "data" : {
548+ "queryId" : "success-query-id" ,
549+ "queryContext" : {
550+ "entries" : [
551+ {"id" : 0 , "timestamp" : 100 , "priority" : 0 , "context" : "main_ctx" },
552+ {"id" : 1 , "timestamp" : 100 , "priority" : 1 , "context" : "ht_dpo_ctx" },
553+ ]
554+ },
555+ },
556+ }
557+ SnowflakeConnection .cmd_query (
558+ conn , "INSERT INTO ht VALUES ('k1','v1')" , 1 , uuid .uuid4 ()
559+ )
560+ qcc_after_success = len (conn .query_context_cache )
561+ assert qcc_after_success == 2 , "QCC should have 2 entries after successful query"
562+
563+ # Q2 — duplicate key insert fails, but server still sends queryContext
564+ conn .rest .request .return_value = {
565+ "success" : False ,
566+ "code" : "100072" ,
567+ "message" : "Duplicate key value violates unique constraint" ,
568+ "data" : {
569+ "queryId" : "failed-query-id" ,
570+ "queryContext" : {
571+ "entries" : [
572+ {
573+ "id" : 0 ,
574+ "timestamp" : 200 ,
575+ "priority" : 0 ,
576+ "context" : "main_ctx_v2" ,
577+ },
578+ {
579+ "id" : 1 ,
580+ "timestamp" : 200 ,
581+ "priority" : 1 ,
582+ "context" : "ht_dpo_ctx_v2" ,
583+ },
584+ ]
585+ },
586+ },
587+ }
588+ SnowflakeConnection .cmd_query (
589+ conn , "INSERT INTO ht VALUES ('k1','v1')" , 2 , uuid .uuid4 ()
590+ )
591+
592+ qcc_after_failure = len (conn .query_context_cache )
593+ assert qcc_after_failure >= qcc_after_success , (
594+ f"QCC should not shrink after a failed query: "
595+ f"before={ qcc_after_success } , after={ qcc_after_failure } "
596+ )
0 commit comments