@@ -2522,72 +2522,77 @@ async fn test_case_expr_then_expr() {
25222522 shutdown_tx. shutdown ( ) . await ;
25232523}
25242524
2525- async fn populate_all_data_types ( direct_mysql : & mut mysql_async:: Conn ) {
2525+ async fn populate_all_data_types (
2526+ direct_mysql : & mut mysql_async:: Conn ,
2527+ table_name : & str ,
2528+ add_sample_data : bool ,
2529+ ) {
25262530 // Drop existing table if any
25272531 direct_mysql
2528- . query_drop ( "DROP TABLE IF EXISTS all_data_types CASCADE;" )
2532+ . query_drop ( format ! ( "DROP TABLE IF EXISTS {} CASCADE;" , table_name ) )
25292533 . await
25302534 . unwrap ( ) ;
25312535 // Create table
25322536 direct_mysql
25332537 . query_drop (
2534- "CREATE TABLE all_data_types (
2538+ format ! ( "CREATE TABLE {} (
25352539 -- Numeric Data Types (Signed and Unsigned Integers)
2536- col_tinyint TINYINT, -- Signed (-128 to 127)
2537- col_tinyint_unsigned TINYINT UNSIGNED, -- Unsigned (0 to 255)
2538-
2539- col_smallint SMALLINT, -- Signed (-32,768 to 32,767)
2540- col_smallint_unsigned SMALLINT UNSIGNED, -- Unsigned (0 to 65,535)
2541-
2542- col_mediumint MEDIUMINT, -- Signed (-8,388,608 to 8,388,607)
2543- col_mediumint_unsigned MEDIUMINT UNSIGNED, -- Unsigned (0 to 16,777,215)
2544-
2545- col_int INT, -- Signed (-2,147,483,648 to 2,147,483,647)
2546- col_int_unsigned INT UNSIGNED, -- Unsigned (0 to 4,294,967,295)
2547-
2548- col_bigint BIGINT, -- Signed (-2^63 to 2^63-1)
2549- col_bigint_unsigned BIGINT UNSIGNED, -- Unsigned (0 to 2^64-1)
2550-
2551- col_decimal DECIMAL(12,2), -- Fixed-point exact decimal (e.g., 99999999.99)
2552- col_numeric NUMERIC(10,2), -- Synonym for DECIMAL
2553-
2554- col_float FLOAT, -- 32-bit floating point (approximate value)
2555- col_double DOUBLE, -- 64-bit floating point (approximate value)
2556- col_real REAL, -- Synonym for DOUBLE
2557-
2558- col_bit BIT(8), -- Bit field (e.g., 8-bit binary)
2559- col_boolean BOOLEAN, -- Alias for TINYINT(1) (0 = false, 1 = true)
2560-
2540+ col_tinyint TINYINT NOT NULL , -- Signed (-128 to 127)
2541+ col_tinyint_unsigned TINYINT UNSIGNED NOT NULL , -- Unsigned (0 to 255)
2542+
2543+ col_smallint SMALLINT NOT NULL , -- Signed (-32,768 to 32,767)
2544+ col_smallint_unsigned SMALLINT UNSIGNED NOT NULL , -- Unsigned (0 to 65,535)
2545+
2546+ col_mediumint MEDIUMINT NOT NULL , -- Signed (-8,388,608 to 8,388,607)
2547+ col_mediumint_unsigned MEDIUMINT UNSIGNED NOT NULL , -- Unsigned (0 to 16,777,215)
2548+
2549+ col_int INT NOT NULL , -- Signed (-2,147,483,648 to 2,147,483,647)
2550+ col_int_unsigned INT UNSIGNED NOT NULL , -- Unsigned (0 to 4,294,967,295)
2551+
2552+ col_bigint BIGINT NOT NULL , -- Signed (-2^63 to 2^63-1)
2553+ col_bigint_unsigned BIGINT UNSIGNED NOT NULL , -- Unsigned (0 to 2^64-1)
2554+
2555+ col_decimal DECIMAL(12,2) NOT NULL , -- Fixed-point exact decimal (e.g., 99999999.99)
2556+ col_numeric NUMERIC(10,2) NOT NULL , -- Synonym for DECIMAL
2557+
2558+ col_float FLOAT NOT NULL , -- 32-bit floating point (approximate value)
2559+ col_double DOUBLE NOT NULL , -- 64-bit floating point (approximate value)
2560+ col_real REAL NOT NULL , -- Synonym for DOUBLE
2561+
2562+ col_bit BIT(8) NOT NULL , -- Bit field (e.g., 8-bit binary)
2563+ col_boolean BOOLEAN NOT NULL , -- Alias for TINYINT(1) (0 = false, 1 = true)
2564+
25612565 -- Date and Time Data Types
2562- col_date DATE,
2563- col_datetime DATETIME(2),
2564- col_timestamp TIMESTAMP,
2565- col_time TIME,
2566+ col_date DATE NOT NULL ,
2567+ col_datetime DATETIME(2) NOT NULL ,
2568+ col_timestamp TIMESTAMP NOT NULL ,
2569+ col_time TIME NOT NULL ,
25662570
25672571 -- String Data Types
2568- col_char CHAR(10),
2569- col_varchar VARCHAR(255),
2570-
2571- col_text TEXT,
2572- col_tinytext TINYTEXT,
2573- col_mediumtext MEDIUMTEXT,
2574- col_longtext LONGTEXT,
2575-
2576- col_blob BLOB,
2577- col_tinyblob TINYBLOB,
2578- col_mediumblob MEDIUMBLOB,
2579- col_longblob LONGBLOB,
2580-
2581- col_enum ENUM('small', 'medium', 'large'),
2582- col_json JSON
2583- );" ,
2572+ col_char CHAR(10) NOT NULL ,
2573+ col_varchar VARCHAR(255) NOT NULL ,
2574+
2575+ col_text TEXT NOT NULL ,
2576+ col_tinytext TINYTEXT NOT NULL ,
2577+ col_mediumtext MEDIUMTEXT NOT NULL ,
2578+ col_longtext LONGTEXT NOT NULL ,
2579+
2580+ col_blob BLOB NOT NULL ,
2581+ col_tinyblob TINYBLOB NOT NULL ,
2582+ col_mediumblob MEDIUMBLOB NOT NULL ,
2583+ col_longblob LONGBLOB NOT NULL ,
2584+
2585+ col_enum ENUM('small', 'medium', 'large') NOT NULL ,
2586+ col_json JSON NOT NULL
2587+ );" , table_name )
25842588 )
25852589 . await
25862590 . unwrap ( ) ;
2587- // Insert test data
2588- direct_mysql
2589- . query_drop (
2590- "INSERT INTO all_data_types (
2591+ if add_sample_data {
2592+ // Insert test data
2593+ direct_mysql
2594+ . query_drop ( format ! (
2595+ "INSERT INTO {} (
25912596col_tinyint, col_tinyint_unsigned,
25922597col_smallint, col_smallint_unsigned,
25932598col_mediumint, col_mediumint_unsigned,
@@ -2643,23 +2648,29 @@ CURRENT_TIMESTAMP,
26432648'long blob contents here',
26442649
26452650'medium',
2646- '{\" name\" : \" Alice\" , \" roles\" : [\" admin\" , \" editor\" ], \" active\" : true}'
2651+ '{{ \" name\" : \" Alice\" , \" roles\" : [\" admin\" , \" editor\" ], \" active\" : true} }'
26472652);" ,
2648- )
2649- . await
2650- . unwrap ( ) ;
2653+ table_name
2654+ ) )
2655+ . await
2656+ . unwrap ( ) ;
2657+ }
26512658}
26522659
26532660async fn test_column_definition_verify (
26542661 direct_mysql : & mut mysql_async:: Conn ,
26552662 rs_conn : & mut mysql_async:: Conn ,
2663+ table_name : & str ,
26562664) {
26572665 // Verify results
26582666 let direct_rows: Vec < Row > = direct_mysql
2659- . query ( "SELECT * FROM all_data_types" )
2667+ . query ( format ! ( "SELECT * FROM {}" , table_name) )
2668+ . await
2669+ . unwrap ( ) ;
2670+ let rs_rows: Vec < Row > = rs_conn
2671+ . query ( format ! ( "SELECT * FROM {}" , table_name) )
26602672 . await
26612673 . unwrap ( ) ;
2662- let rs_rows: Vec < Row > = rs_conn. query ( "SELECT * FROM all_data_types" ) . await . unwrap ( ) ;
26632674
26642675 let direct_columns = direct_rows[ 0 ] . columns ( ) ;
26652676 let rs_columns = rs_rows[ 0 ] . columns ( ) ;
@@ -2711,7 +2722,7 @@ async fn test_column_definition_verify(
27112722async fn test_column_definition_upstream_readyset_snapshot ( ) {
27122723 readyset_tracing:: init_test_logging ( ) ;
27132724 let mut direct_mysql = mysql_async:: Conn :: from_url ( mysql_url ( ) ) . await . unwrap ( ) ;
2714- populate_all_data_types ( & mut direct_mysql) . await ;
2725+ populate_all_data_types ( & mut direct_mysql, "all_data_types" , true ) . await ;
27152726
27162727 // Setup ReadySet connection after table creation
27172728 let ( rs_opts, _rs_handle, tx) = TestBuilder :: default ( )
@@ -2720,7 +2731,7 @@ async fn test_column_definition_upstream_readyset_snapshot() {
27202731 . await ;
27212732 let mut conn = mysql_async:: Conn :: new ( rs_opts) . await . unwrap ( ) ;
27222733
2723- test_column_definition_verify ( & mut direct_mysql, & mut conn) . await ;
2734+ test_column_definition_verify ( & mut direct_mysql, & mut conn, "all_data_types" ) . await ;
27242735 tx. shutdown ( ) . await ;
27252736}
27262737
@@ -2737,8 +2748,8 @@ async fn test_column_definition_upstream_readyset_replication() {
27372748 . await ;
27382749 let mut conn = mysql_async:: Conn :: new ( rs_opts) . await . unwrap ( ) ;
27392750
2740- populate_all_data_types ( & mut direct_mysql) . await ;
2741- test_column_definition_verify ( & mut direct_mysql, & mut conn) . await ;
2751+ populate_all_data_types ( & mut direct_mysql, "all_data_types" , true ) . await ;
2752+ test_column_definition_verify ( & mut direct_mysql, & mut conn, "all_data_types" ) . await ;
27422753 tx. shutdown ( ) . await ;
27432754}
27442755
@@ -2790,3 +2801,51 @@ async fn text_citext_default_coercion_minimal_row_base_replication() {
27902801 assert_eq ! ( rs_row[ 1 ] , direct_row[ 1 ] ) ;
27912802 tx. shutdown ( ) . await ;
27922803}
2804+
2805+ #[ tokio:: test( flavor = "multi_thread" ) ]
2806+ #[ serial( mysql) ]
2807+ async fn test_default_value_not_null_for_replication ( ) {
2808+ readyset_tracing:: init_test_logging ( ) ;
2809+ let ( rs_opts, _rs_handle, tx) = TestBuilder :: default ( )
2810+ . recreate_database ( false )
2811+ . fallback ( true )
2812+ . build :: < MySQLAdapter > ( )
2813+ . await ;
2814+ sleep ( ) . await ;
2815+ let mut direct_mysql = mysql_async:: Conn :: from_url ( mysql_url ( ) ) . await . unwrap ( ) ;
2816+ direct_mysql
2817+ . query_drop ( "SET SESSION binlog_row_image = MINIMAL; SET SESSION sql_mode = '';" )
2818+ . await
2819+ . unwrap ( ) ;
2820+ populate_all_data_types ( & mut direct_mysql, "all_data_types_not_null" , false ) . await ;
2821+ direct_mysql
2822+ . query_drop ( "INSERT INTO all_data_types_not_null () VALUES ();" )
2823+ . await
2824+ . unwrap ( ) ;
2825+
2826+ let mut conn = mysql_async:: Conn :: new ( rs_opts) . await . unwrap ( ) ;
2827+ conn. query_drop ( "CREATE CACHE FROM SELECT * FROM all_data_types_not_null" )
2828+ . await
2829+ . unwrap ( ) ;
2830+ let rs_row: Row = conn
2831+ . query_first ( "SELECT * FROM all_data_types_not_null" )
2832+ . await
2833+ . unwrap ( )
2834+ . unwrap ( ) ;
2835+ let direct_row: Row = direct_mysql
2836+ . query_first ( "SELECT * FROM all_data_types_not_null" )
2837+ . await
2838+ . unwrap ( )
2839+ . unwrap ( ) ;
2840+ assert_eq ! ( rs_row. len( ) , direct_row. len( ) ) ;
2841+ let row_length = rs_row. len ( ) ;
2842+ for i in 0 ..row_length {
2843+ assert_eq ! (
2844+ rs_row[ i] ,
2845+ direct_row[ i] ,
2846+ "Value mismatch for column: {}" ,
2847+ String :: from_utf8_lossy( rs_row. columns( ) [ i] . name_ref( ) )
2848+ ) ;
2849+ }
2850+ tx. shutdown ( ) . await ;
2851+ }
0 commit comments