1+ use std:: env;
2+ use std:: panic:: AssertUnwindSafe ;
13use std:: sync:: Arc ;
24use std:: time:: Duration ;
35
46use chrono:: { NaiveDate , NaiveDateTime , NaiveTime } ;
7+ use mysql:: Row ;
58use mysql_async:: prelude:: Queryable ;
69use mysql_async:: OptsBuilder ;
710use readyset_adapter:: backend:: noria_connector:: ReadBehavior ;
@@ -15,11 +18,13 @@ use readyset_client_test_helpers::{sleep, TestBuilder};
1518use readyset_errors:: ReadySetError ;
1619use readyset_server:: Handle ;
1720use readyset_telemetry_reporter:: { TelemetryEvent , TelemetryInitializer , TelemetryReporter } ;
21+ use readyset_util:: eventually;
1822use readyset_util:: shutdown:: ShutdownSender ;
1923use regex:: Regex ;
24+ use serial_test:: serial;
2025use test_utils:: skip_flaky_finder;
2126
22- async fn setup_with_mysql ( ) -> ( mysql_async:: Opts , Handle , ShutdownSender ) {
27+ async fn setup_with_mysql ( recreate_db : bool ) -> ( mysql_async:: Opts , Handle , ShutdownSender ) {
2328 readyset_tracing:: init_test_logging ( ) ;
2429 let mut users = std:: collections:: HashMap :: new ( ) ;
2530 users. insert ( "root" . to_string ( ) , "noria" . to_string ( ) ) ;
@@ -30,6 +35,7 @@ async fn setup_with_mysql() -> (mysql_async::Opts, Handle, ShutdownSender) {
3035 . users ( users) ,
3136 )
3237 . fallback ( true )
38+ . recreate_database ( recreate_db)
3339 . build :: < MySQLAdapter > ( )
3440 . await
3541}
@@ -51,6 +57,14 @@ async fn setup_telemetry() -> (TelemetryReporter, mysql_async::Opts, Handle, Shu
5157 ( reporter, opts, handle, shutdown_tx)
5258}
5359
60+ fn mysql_url ( ) -> String {
61+ format ! (
62+ "mysql://root:noria@{}:{}/noria" ,
63+ env:: var( "MYSQL_HOST" ) . unwrap_or_else( |_| "127.0.0.1" . into( ) ) ,
64+ env:: var( "MYSQL_TCP_PORT" ) . unwrap_or_else( |_| "3306" . into( ) ) ,
65+ )
66+ }
67+
5468#[ tokio:: test( flavor = "multi_thread" ) ]
5569async fn duplicate_join_key ( ) {
5670 // This used to trigger a bug involving weak indexes. See issue #179 for more info.
@@ -1842,8 +1856,9 @@ async fn show_caches_with_always() {
18421856}
18431857
18441858#[ tokio:: test( flavor = "multi_thread" ) ]
1859+ #[ serial]
18451860async fn show_readyset_status ( ) {
1846- let ( opts, _handle, shutdown_tx) = setup_with_mysql ( ) . await ;
1861+ let ( opts, _handle, shutdown_tx) = setup_with_mysql ( true ) . await ;
18471862 let mut conn = mysql_async:: Conn :: new ( opts) . await . unwrap ( ) ;
18481863 let mut ret: Vec < mysql:: Row > = conn. query ( "SHOW READYSET STATUS;" ) . await . unwrap ( ) ;
18491864
@@ -2107,3 +2122,154 @@ async fn test_proxied_queries_telemetry() {
21072122
21082123 shutdown_tx. shutdown ( ) . await ;
21092124}
2125+
2126+ #[ tokio:: test( flavor = "multi_thread" ) ]
2127+ #[ serial]
2128+ async fn datetime_nanosecond_precision_text_protocol ( ) {
2129+ let mut direct_mysql = mysql_async:: Conn :: from_url ( mysql_url ( ) ) . await . unwrap ( ) ;
2130+ direct_mysql. query_drop ( "DROP TABLE IF EXISTS dt_nano_text_protocol CASCADE;
2131+ CREATE TABLE dt_nano_text_protocol (col1 DATETIME, col2 DATETIME(2), col3 DATETIME(4), col4 DATETIME(6));
2132+ INSERT INTO dt_nano_text_protocol VALUES ('2021-01-01 00:00:00', '2021-01-01 00:00:00.00', '2021-01-01 00:00:00.0000', '2021-01-01 00:00:00.000000');
2133+ INSERT INTO dt_nano_text_protocol VALUES ('2021-01-01 00:00:00', '2021-01-01 00:00:00.01', '2021-01-01 00:00:00.0001', '2021-01-01 00:00:00.000001');" )
2134+ . await
2135+ . unwrap ( ) ;
2136+ let ( opts, _handle, shutdown_tx) = setup_with_mysql ( false ) . await ;
2137+ let mut conn = mysql_async:: Conn :: new ( opts) . await . unwrap ( ) ;
2138+ sleep ( ) . await ;
2139+
2140+ conn. query_drop ( "CREATE CACHE FROM SELECT * FROM dt_nano_text_protocol" )
2141+ . await
2142+ . unwrap ( ) ;
2143+ sleep ( ) . await ;
2144+
2145+ let my_rows: Vec < ( String , String , String , String ) > = direct_mysql
2146+ . query ( "SELECT * FROM dt_nano_text_protocol" )
2147+ . await
2148+ . unwrap ( ) ;
2149+ let rs_rows: Vec < ( String , String , String , String ) > = conn
2150+ . query ( "SELECT * FROM dt_nano_text_protocol" )
2151+ . await
2152+ . unwrap ( ) ;
2153+ assert_eq ! ( rs_rows, my_rows) ;
2154+ conn. query_drop ( "INSERT INTO dt_nano_text_protocol VALUES ('2021-01-02 00:00:00', '2021-01-02 00:00:00.00', '2021-01-02 00:00:00.0000', '2021-01-02 00:00:00.000000');" ) . await . unwrap ( ) ;
2155+ conn. query_drop ( "INSERT INTO dt_nano_text_protocol VALUES ('2021-01-02 00:00:00', '2021-01-02 00:00:00.01', '2021-01-02 00:00:00.0001', '2021-01-02 00:00:00.000001');" ) . await . unwrap ( ) ;
2156+
2157+ sleep ( ) . await ;
2158+
2159+ eventually ! ( run_test: {
2160+ let my_rows: Vec <( String , String , String , String ) > = direct_mysql
2161+ . query( "SELECT * FROM dt_nano_text_protocol" )
2162+ . await
2163+ . unwrap( ) ;
2164+
2165+ let rs_rows: Vec <( String , String , String , String ) > = conn
2166+ . query( "SELECT * FROM dt_nano_text_protocol" )
2167+ . await
2168+ . unwrap( ) ;
2169+ AssertUnwindSafe ( move || ( rs_rows, my_rows) )
2170+ } , then_assert: |results| {
2171+ let ( rs_rows, my_rows) = results( ) ;
2172+ assert_eq!( rs_rows, my_rows)
2173+ } ) ;
2174+
2175+ shutdown_tx. shutdown ( ) . await ;
2176+ }
2177+
2178+ #[ tokio:: test( flavor = "multi_thread" ) ]
2179+ #[ serial]
2180+ async fn datetime_nanosecond_precision_binary_protocol ( ) {
2181+ let mut direct_mysql = mysql_async:: Conn :: from_url ( mysql_url ( ) ) . await . unwrap ( ) ;
2182+ direct_mysql. query_drop ( "DROP TABLE IF EXISTS dt_nano_bin_protocol CASCADE;
2183+ CREATE TABLE dt_nano_bin_protocol (ID INT PRIMARY KEY, col1 DATETIME, col2 DATETIME(2), col3 DATETIME(4), col4 DATETIME(6));
2184+ INSERT INTO dt_nano_bin_protocol VALUES (1, '2021-01-01 00:00:00', '2021-01-01 00:00:00.00', '2021-01-01 00:00:00.0000', '2021-01-01 00:00:00.000000');
2185+ INSERT INTO dt_nano_bin_protocol VALUES (2, '2021-01-01 00:00:00', '2021-01-01 00:00:00.01', '2021-01-01 00:00:00.0001', '2021-01-01 00:00:00.000001');" )
2186+ . await
2187+ . unwrap ( ) ;
2188+ let ( opts, _handle, shutdown_tx) = setup_with_mysql ( false ) . await ;
2189+ let mut conn = mysql_async:: Conn :: new ( opts) . await . unwrap ( ) ;
2190+ sleep ( ) . await ;
2191+
2192+ conn. query_drop ( "CREATE CACHE FROM SELECT * FROM dt_nano_bin_protocol WHERE ID = ?" )
2193+ . await
2194+ . unwrap ( ) ;
2195+ sleep ( ) . await ;
2196+
2197+ for id in 1 ..=2 {
2198+ let my_rows: Row = direct_mysql
2199+ . exec_first ( "SELECT * FROM dt_nano_bin_protocol WHERE ID = ?" , ( id, ) )
2200+ . await
2201+ . unwrap ( )
2202+ . unwrap ( ) ;
2203+ let rs_rows: Row = conn
2204+ . exec_first ( "SELECT * FROM dt_nano_bin_protocol WHERE ID = ?" , ( id, ) )
2205+ . await
2206+ . unwrap ( )
2207+ . unwrap ( ) ;
2208+ assert_eq ! ( rs_rows. unwrap_raw( ) , my_rows. unwrap_raw( ) )
2209+ }
2210+
2211+ conn. query_drop ( "INSERT INTO dt_nano_bin_protocol VALUES (3, '2021-01-02 00:00:00', '2021-01-02 00:00:00.00', '2021-01-02 00:00:00.0000', '2021-01-02 00:00:00.000000');" ) . await . unwrap ( ) ;
2212+ conn. query_drop ( "INSERT INTO dt_nano_bin_protocol VALUES (4, '2021-01-02 00:00:00', '2021-01-02 00:00:00.01', '2021-01-02 00:00:00.0001', '2021-01-02 00:00:00.000001');" ) . await . unwrap ( ) ;
2213+
2214+ sleep ( ) . await ;
2215+
2216+ for id in 3 ..=4 {
2217+ eventually ! ( run_test: {
2218+
2219+ let my_rows: Row = direct_mysql
2220+ . exec_first( "SELECT * FROM dt_nano_bin_protocol WHERE ID = ?" , ( id, ) )
2221+ . await
2222+ . unwrap( )
2223+ . unwrap( ) ;
2224+ let rs_rows: Row = conn
2225+ . exec_first( "SELECT * FROM dt_nano_bin_protocol WHERE ID = ?" , ( id, ) )
2226+ . await
2227+ . unwrap( )
2228+ . unwrap( ) ;
2229+ AssertUnwindSafe ( move || ( rs_rows, my_rows) )
2230+ } , then_assert: |results| {
2231+ let ( rs_rows, my_rows) = results( ) ;
2232+ assert_eq!( rs_rows. unwrap_raw( ) , my_rows. unwrap_raw( ) )
2233+ } ) ;
2234+ }
2235+ shutdown_tx. shutdown ( ) . await ;
2236+ }
2237+
2238+ #[ tokio:: test( flavor = "multi_thread" ) ]
2239+ #[ serial]
2240+ async fn datetime_binary_protocol ( ) {
2241+ let ( opts, _handle, shutdown_tx) = setup_with_mysql ( false ) . await ;
2242+ let mut conn = mysql_async:: Conn :: new ( opts) . await . unwrap ( ) ;
2243+ let mut direct_mysql = mysql_async:: Conn :: from_url ( mysql_url ( ) ) . await . unwrap ( ) ;
2244+ direct_mysql. query_drop ( "SET sql_mode='';" ) . await . unwrap ( ) ;
2245+ direct_mysql
2246+ . query_drop ( "DROP TABLE IF EXISTS dt_bin_protocol CASCADE;" )
2247+ . await
2248+ . unwrap ( ) ;
2249+ direct_mysql. query_drop ( "CREATE TABLE dt_bin_protocol (ID INT PRIMARY KEY, col1 DATETIME(6), col2 DATETIME(6), col3 DATETIME(6), col4 DATETIME(6));" ) . await . unwrap ( ) ;
2250+ direct_mysql. query_drop ( "INSERT INTO dt_bin_protocol VALUES (1, '0000-00-00 00:00:00.000000', '2021-01-01 00:00:00.000000', '2021-01-01 00:00:01.0000000', '2021-01-01 00:00:01.000001');" )
2251+ . await
2252+ . unwrap ( ) ;
2253+ sleep ( ) . await ;
2254+
2255+ conn. query_drop ( "CREATE CACHE FROM SELECT * FROM dt_bin_protocol WHERE ID = ?" )
2256+ . await
2257+ . unwrap ( ) ;
2258+ sleep ( ) . await ;
2259+ let rs_rows: Row = conn
2260+ . exec_first ( "SELECT * FROM dt_bin_protocol WHERE ID = 1" , ( ) )
2261+ . await
2262+ . unwrap ( )
2263+ . unwrap ( ) ;
2264+ assert_eq ! (
2265+ rs_rows. unwrap_raw( ) ,
2266+ vec![
2267+ Some ( mysql:: Value :: Int ( 1 ) ) ,
2268+ Some ( mysql:: Value :: NULL ) ,
2269+ Some ( mysql:: Value :: Date ( 2021 , 1 , 1 , 0 , 0 , 0 , 0 ) ) ,
2270+ Some ( mysql:: Value :: Date ( 2021 , 1 , 1 , 0 , 0 , 1 , 0 ) ) ,
2271+ Some ( mysql:: Value :: Date ( 2021 , 1 , 1 , 0 , 0 , 1 , 1 ) )
2272+ ]
2273+ ) ;
2274+ shutdown_tx. shutdown ( ) . await ;
2275+ }
0 commit comments