Repository: risingwavelabs/risingwave
File: src/connector/src/parser/mysql.rs (Rust)

Code before:
                .context(format!(
                    "column: {}, index: {}, rw_type: {}",
                    $name,
                    $i,
                    stringify!($rw_type),
                ))),
        }
    }};
}

macro_rules! handle_data_type_with_signed {
    (
        $mysql_row:expr,
        $mysql_datum_index:expr,
        $column_name:expr,
        $signed_type:ty,
        $unsigned_type:ty
    ) => {{
        let column_flags = $mysql_row.columns()[$mysql_datum_index].flags();

        if column_flags.contains(ColumnFlags::UNSIGNED_FLAG) {
            // UNSIGNED type: use unsigned type conversion, then convert to signed
            match $mysql_row.take_opt::<Option<$unsigned_type>, _>($mysql_datum_index) {
                Some(Ok(Some(val))) => Ok(Some(ScalarImpl::from(val as $signed_type))),
                Some(Ok(None)) => Ok(None),
                Some(Err(e)) => Err(anyhow::Error::new(e.clone())
                    .context("failed to deserialize MySQL value into rust value")
                    .context(format!(
                        "column: {}, index: {}, rust_type: {}",
                        $column_name,
                        $mysql_datum_index,
                        stringify!($unsigned_type),
                    ))),
                None => bail!(
                    "no value found at column: {}, index: {}",
                    $column_name,
                    $mysql_datum_index
                ),
            }
        } else {
            // SIGNED type: use default signed type conversion
            handle_data_type!($mysql_row, $mysql_datum_index, $column_name, $signed_type)
        }
    }};
}

/// The decoding result can be interpreted as follows:
/// Ok(value) => The value was found and successfully decoded.
/// Err(error) => The value was found but could not be decoded,
///               either because it was not supported,
///               or there was an error during conversion.

Review comment (suggestion):
Add a comment here to acknowledge we are intentionally converting `18446251075179777772u64` into `-492998529773844i64`

Code after:
                .context(format!(
                    "column: {}, index: {}, rw_type: {}",
                    $name,
                    $i,
                    stringify!($rw_type),
                ))),
        }
    }};
}

macro_rules! handle_data_type_with_signed {
    (
        $mysql_row:expr,
        $mysql_datum_index:expr,
        $column_name:expr,
        $signed_type:ty,
        $unsigned_type:ty
    ) => {{
        let column_flags = $mysql_row.columns()[$mysql_datum_index].flags();

        if column_flags.contains(ColumnFlags::UNSIGNED_FLAG) {
            // UNSIGNED type: use unsigned type conversion, then convert to signed
            match $mysql_row.take_opt::<Option<$unsigned_type>, _>($mysql_datum_index) {
                // Note: We are intentionally converting unsigned to signed here.
                // For example, 18446251075179777772u64 will be converted to -492998529773844i64.
                Some(Ok(Some(val))) => Ok(Some(ScalarImpl::from(val as $signed_type))),
                Some(Ok(None)) => Ok(None),
                Some(Err(e)) => Err(anyhow::Error::new(e.clone())
                    .context("failed to deserialize MySQL value into rust value")
                    .context(format!(
                        "column: {}, index: {}, rust_type: {}",
                        $column_name,
                        $mysql_datum_index,
                        stringify!($unsigned_type),
                    ))),
                None => bail!(
                    "no value found at column: {}, index: {}",
                    $column_name,
                    $mysql_datum_index
                ),
            }
        } else {
            // SIGNED type: use default signed type conversion
            handle_data_type!($mysql_row, $mysql_datum_index, $column_name, $signed_type)
        }
    }};
}

/// The decoding result can be interpreted as follows:
/// Ok(value) => The value was found and successfully decoded.
/// Err(error) => The value was found but could not be decoded,