@@ -617,3 +617,85 @@ def test_binding_identifier(conn_cnx, db_parameters):
617617""" ,
618618 (db_parameters ["name" ],),
619619 )
620+
621+
622+ def create_or_replace_table (cur , table_name : str , columns ):
623+ sql = f"CREATE OR REPLACE TEMP TABLE { table_name } ({ ',' .join (columns )} )"
624+ cur .execute (sql )
625+
626+
627+ def insert_multiple_records (
628+ cur ,
629+ table_name : str ,
630+ ts : str ,
631+ row_count : int ,
632+ should_bind : bool ,
633+ ):
634+ sql = f"INSERT INTO { table_name } values (?)"
635+ dates = [[ts ] for _ in range (row_count )]
636+ cur .executemany (sql , dates )
637+ is_bind_sql_scoped = "SHOW stages like 'SNOWPARK_TEMP_STAGE_BIND'"
638+ is_bind_sql_non_scoped = "SHOW stages like 'SYSTEMBIND'"
639+ res1 = cur .execute (is_bind_sql_scoped ).fetchall ()
640+ res2 = cur .execute (is_bind_sql_non_scoped ).fetchall ()
641+ if should_bind :
642+ assert len (res1 ) != 0 or len (res2 ) != 0
643+ else :
644+ assert len (res1 ) == 0 and len (res2 ) == 0
645+
646+
647+ @pytest .mark .skipolddriver
648+ @pytest .mark .parametrize (
649+ "timestamp_type, timestamp_precision, timestamp, expected_style" ,
650+ [
651+ ("TIMESTAMPTZ" , 6 , "2023-03-15 13:17:29.207 +05:00" , "%Y-%m-%d %H:%M:%S.%f %z" ),
652+ ("TIMESTAMP" , 6 , "2023-03-15 13:17:29.207" , "%Y-%m-%d %H:%M:%S.%f" ),
653+ (
654+ "TIMESTAMPLTZ" ,
655+ 6 ,
656+ "2023-03-15 13:17:29.207 +05:00" ,
657+ "%Y-%m-%d %H:%M:%S.%f %z" ,
658+ ),
659+ (
660+ "TIMESTAMPTZ" ,
661+ None ,
662+ "2023-03-15 13:17:29.207 +05:00" ,
663+ "%Y-%m-%d %H:%M:%S.%f %z" ,
664+ ),
665+ ("TIMESTAMP" , None , "2023-03-15 13:17:29.207" , "%Y-%m-%d %H:%M:%S.%f" ),
666+ (
667+ "TIMESTAMPLTZ" ,
668+ None ,
669+ "2023-03-15 13:17:29.207 +05:00" ,
670+ "%Y-%m-%d %H:%M:%S.%f %z" ,
671+ ),
672+ ("TIMESTAMPNTZ" , 6 , "2023-03-15 13:17:29.207" , "%Y-%m-%d %H:%M:%S.%f" ),
673+ ("TIMESTAMPNTZ" , None , "2023-03-15 13:17:29.207" , "%Y-%m-%d %H:%M:%S.%f" ),
674+ ],
675+ )
676+ def test_timestamp_bindings (
677+ conn_cnx , timestamp_type , timestamp_precision , timestamp , expected_style
678+ ):
679+ column_name = (
680+ f"ts { timestamp_type } ({ timestamp_precision } )"
681+ if timestamp_precision is not None
682+ else f"ts { timestamp_type } "
683+ )
684+ table_name = f"TEST_TIMESTAMP_BINDING_{ random_string (10 )} "
685+ binding_threshold = 65280
686+
687+ with conn_cnx (paramstyle = "qmark" ) as cnx :
688+ with cnx .cursor () as cur :
689+ create_or_replace_table (cur , table_name , [column_name ])
690+ insert_multiple_records (cur , table_name , timestamp , 2 , False )
691+ insert_multiple_records (
692+ cur , table_name , timestamp , binding_threshold + 1 , True
693+ )
694+ res = cur .execute (f"select ts from { table_name } " ).fetchall ()
695+ expected = datetime .strptime (timestamp , expected_style )
696+ assert len (res ) == 65283
697+ for r in res :
698+ if timestamp_type == "TIMESTAMP" :
699+ assert r [0 ].replace (tzinfo = None ) == expected .replace (tzinfo = None )
700+ else :
701+ assert r [0 ] == expected
0 commit comments