Skip to content

Commit

Permalink
trying a few things before arriving at a fix which is a patch to sqlx
Browse files Browse the repository at this point in the history
PR launchbadge/sqlx#2688

split has_decimal binaries into separate files

add view_type table which contains a bool column which causes issues
  • Loading branch information
cameronbraid committed Aug 10, 2023
1 parent 099cc01 commit a2a726c
Show file tree
Hide file tree
Showing 24 changed files with 1,050 additions and 89 deletions.
603 changes: 557 additions & 46 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ edition = "2021"
authors = ["Cameron <[email protected]>"]

[workspace.dependencies]

[patch.crates-io]
# sqlx = { path = "../sqlx"}
sqlx = { git = "https://github.com/cameronbraid/sqlx", branch = "decimal_compatibility_lenient" }

77 changes: 75 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@

# MySQL DECIMAL type issue

https://github.com/readysettech/readyset/issues/143

NOTE: fixed using https://github.com/cameronbraid/sqlx/tree/decimal_compatibility_lenient and this repo is configured to use the fix

To reproduce the error

```shell
docker compose up -d

// wait for docker to start
// wait for services to start

// crate schema
cargo run --bin migrate_fresh

cargo run --bin has_decimal
// insert a record directly in mysql
cargo run --bin has_decimal_seaorm_mysql_insert

// select the record from mysql
cargo run --bin has_decimal_seaorm_mysql_select

// select the record from mysql
cargo run --bin has_decimal_seaorm_readyset_select

```
You should get out like
Expand All @@ -23,3 +39,60 @@ To start over run the following, then run the steps above
```shell
docker compose kill readyset; sudo rm -rf data/readyset
```
---
# MySQL bool type issue
mysql treats `bool` as an alias for `tinyint(1)`
So the `view_type` table look like this :
```sql
CREATE TABLE `view_type` (
`channel_id` int NOT NULL,
`view_type` varchar(255) NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`channel_id`,`view_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
```
To reproduce
```shell
docker compose up -d
// wait for services to start
// crate schema
cargo run --bin migrate_fresh
// insert a record directly in mysql
cargo run --bin view_type_insert
// select the record from mysql
cargo run --bin view_type_mysql_select
// select the records from readyset
cargo run --bin view_type_readyset_select
```
observe the error
```
Error: Query Error: error communicating with database: expected to read 4 bytes, got 0 bytes at EOF
Caused by:
error communicating with database: expected to read 4 bytes, got 0 bytes at EOF
Location:
app/src/bin/view_type_readyset_select.rs:12:17
```
and the readyset logs in docker
```
readyset_seaorm_issues-readyset-1 | 2023-08-10T02:10:09.134045Z ERROR connection{addr=172.25.0.1:56330}:connection{addr=172.25.0.1:56330}: readyset_mysql::backend: encountered error while attempting to write column packet err=tried to use 1 as MYSQL_TYPE_BIT
```
8 changes: 6 additions & 2 deletions app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
sea-orm = { version = "0", features = [ "sqlx-mysql", "runtime-tokio-rustls", "macros", "with-chrono", "with-rust_decimal", "debug-print" ] }
sea-orm = { version = "*", features = [ "sqlx-mysql", "runtime-tokio", "macros", "with-chrono", "with-rust_decimal", "debug-print", "with-bigdecimal" ] }
tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "sync", "time","full"] }
migration = { path = "../migration" }
entity = { path = "../entity" }
Expand All @@ -15,4 +15,8 @@ rust_decimal = { version = "1.28.0", features = ["serde-float"] }
rust_decimal_macros = "1.28.0"
tracing = { version = "0.1" }
tracing-subscriber = { version = "0.3", features = ["json", "env-filter", "valuable", "fmt", "std"] }
log = "*"
log = "*"
sqlx = { version = "*", features = [ "runtime-tokio", "rust_decimal", "bigdecimal" ] }

mysql = { version = "*", default-features = false, features = ["minimal", "derive"] }
mysql_common = { version = "*", default-features = false, features = ["rust_decimal"]}
32 changes: 0 additions & 32 deletions app/src/bin/has_decimal.rs

This file was deleted.

29 changes: 29 additions & 0 deletions app/src/bin/has_decimal_mysql_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use app::docker;
use color_eyre::Result;
use entity::has_decimal;
use mysql::Pool;
use mysql::prelude::FromRow;
use rust_decimal::Decimal;

use mysql::prelude::Queryable;
#[tokio::main]
async fn main() -> Result<()> {

#[derive(FromRow, Debug)]
pub struct Row {
pub id : i64,
pub price: Decimal,
}

let url = "mysql://user:password@localhost:3307/db?enable_cleartext_plugin=true";
let pool = Pool::new(url)?;

let mut conn = pool.get_conn()?;
let row: Option<Row> = conn
.exec_first(
"SELECT * from has_decimal",())?;

println!("row: {:?}", row);

Ok(())
}
22 changes: 22 additions & 0 deletions app/src/bin/has_decimal_seaorm_mysql_insert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use app::docker;
use color_eyre::Result;
use entity::has_decimal;
use rust_decimal_macros::dec;
use sea_orm::ActiveModelTrait;
use sea_orm::EntityTrait;
use sea_orm::Set;

#[tokio::main]
async fn main() -> Result<()> {
let db = docker::db_connect().await;

let item = has_decimal::ActiveModel {
id: Set(1),
price: Set(dec!(10.0)),
}
.insert(&db.mysql)
.await?;

println!("item: {:?}", item);
Ok(())
}
18 changes: 18 additions & 0 deletions app/src/bin/has_decimal_seaorm_mysql_select.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use app::docker;
use color_eyre::Result;
use entity::has_decimal;
use rust_decimal_macros::dec;
use sea_orm::ActiveModelTrait;
use sea_orm::EntityTrait;
use sea_orm::Set;

#[tokio::main]
async fn main() -> Result<()> {
let db = docker::db_connect().await;

let item = has_decimal::Entity::find_by_id(1).one(&db.mysql).await?;

println!("item: {:?}", item);

Ok(())
}
17 changes: 17 additions & 0 deletions app/src/bin/has_decimal_seaorm_readyset_select.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use app::docker;
use color_eyre::Result;
use entity::has_decimal;
use sea_orm::EntityTrait;


#[tokio::main]
async fn main() -> Result<()> {
let db = docker::db_connect().await;

let item = has_decimal::Entity::find_by_id(1)
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;
println!("item: {:?}", item);
Ok(())
}
23 changes: 23 additions & 0 deletions app/src/bin/has_decimal_sqlx_mysql.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use color_eyre::Result;
use rust_decimal::Decimal;
use sqlx::{MySqlPool, types::BigDecimal};

#[tokio::main]
async fn main() -> Result<()> {

let pool = MySqlPool::connect("mysql://user:password@localhost:3307/db?ssl-mode=disabled").await?;

#[derive(sqlx::FromRow, Debug)]
pub struct Row {
pub id : i64,
pub price: Decimal,
}

// Make a simple query to return the given parameter (use a question mark `?` instead of `$1` for MySQL)
let row : Row = sqlx::query_as("SELECT id, price from has_decimal")
.fetch_one(&pool).await?;

println!("row: {:?}", row);

Ok(())
}
24 changes: 24 additions & 0 deletions app/src/bin/has_decimal_sqlx_readyset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use color_eyre::Result;
use rust_decimal::Decimal;
use sqlx::MySqlPool;

#[tokio::main]
async fn main() -> Result<()> {
let pool =
MySqlPool::connect("mysql://user:password@localhost:3307/db?ssl-mode=disabled").await?;

#[derive(sqlx::FromRow, Debug)]
pub struct Row {
pub id: i64,
pub price: Decimal,
}

// Make a simple query to return the given parameter (use a question mark `?` instead of `$1` for MySQL)
let row: Row = sqlx::query_as("SELECT id, price from has_decimal")
.fetch_one(&pool)
.await?;

println!("row: {:?}", row);

Ok(())
}
76 changes: 76 additions & 0 deletions app/src/bin/product.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use app::docker;
use color_eyre::Result;
use entity::product;
use sea_orm::ActiveModelTrait;
use sea_orm::ColumnTrait;
use sea_orm::DbBackend;
use sea_orm::EntityTrait;
use sea_orm::FromQueryResult;
use sea_orm::QueryFilter;
use sea_orm::Set;
use sea_orm::Statement;

#[tokio::main]
async fn main() -> Result<()> {
let db = docker::db_connect().await;

let item = product::Entity::find_by_id(1).one(&db.mysql).await?;

if item.is_none() {
product::ActiveModel {
id: Set(1),
name: Set("test".to_string()),
}
.insert(&db.mysql)
.await?;

tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}

let _item = product::Entity::find_by_id(1)
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;

let _item = product::Entity::find()
.filter(product::Column::Id.is_in(vec![1, 2, 3]))
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;

let _item = product::Entity::find()
.from_raw_sql(Statement::from_sql_and_values(
DbBackend::MySql,
r#"SELECT * FROM product WHERE id = ?"#,
[1.into()],
))
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;

let _item = product::Entity::find()
.from_raw_sql(Statement::from_sql_and_values(
DbBackend::MySql,
r#"SELECT * FROM product WHERE id in (1)"#,
[],
))
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;

#[derive(Debug, FromQueryResult)]
pub struct ProductName {
pub name: String,
}

let _foo = ProductName::find_by_statement(Statement::from_sql_and_values(
DbBackend::MySql,
r#"SELECT product.name as name from product left join has_decimal on product.id = has_decimal.id where product.id = 1"#,
[],
))
.one(&db.readyset)
.await?
.ok_or_else(|| color_eyre::eyre::eyre!("not found in readyset"))?;

Ok(())
}
21 changes: 21 additions & 0 deletions app/src/bin/view_type_insert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use app::docker;
use color_eyre::Result;
use entity::view_type;
use sea_orm::ActiveModelTrait;
use sea_orm::Set;

#[tokio::main]
async fn main() -> Result<()> {
let db = docker::db_connect().await;

let item = view_type::ActiveModel {
channel_id: Set(1),
view_type: Set("list".to_string()),
enabled: Set(true)
}
.insert(&db.mysql)
.await?;

println!("item: {:?}", item);
Ok(())
}
Loading

0 comments on commit a2a726c

Please sign in to comment.