(
primary_key: Option<ValueTuple>,
statement: InsertStatement,
db: &C,
)
| 331 | } |
| 332 | |
| 333 | async fn exec_insert<A, C>( |
| 334 | primary_key: Option<ValueTuple>, |
| 335 | statement: InsertStatement, |
| 336 | db: &C, |
| 337 | ) -> Result<InsertResult<A>, DbErr> |
| 338 | where |
| 339 | C: ConnectionTrait, |
| 340 | A: ActiveModelTrait, |
| 341 | { |
| 342 | type ValueTypeOf<A> = <PrimaryKey<A> as PrimaryKeyTrait>::ValueType; |
| 343 | |
| 344 | let db_backend = db.get_database_backend(); |
| 345 | let statement = db_backend.build(&statement); |
| 346 | |
| 347 | let last_insert_id = match (primary_key, db.support_returning()) { |
| 348 | (Some(value_tuple), _) => { |
| 349 | let res = db.execute(statement).await?; |
| 350 | if res.rows_affected() == 0 { |
| 351 | return Err(DbErr::RecordNotInserted); |
| 352 | } |
| 353 | FromValueTuple::from_value_tuple(value_tuple) |
| 354 | } |
| 355 | (None, true) => { |
| 356 | let mut rows = db.query_all(statement).await?; |
| 357 | let row = match rows.pop() { |
| 358 | Some(row) => row, |
| 359 | None => return Err(DbErr::RecordNotInserted), |
| 360 | }; |
| 361 | let cols = PrimaryKey::<A>::iter() |
| 362 | .map(|col| col.to_string()) |
| 363 | .collect::<Vec<_>>(); |
| 364 | row.try_get_many("", cols.as_ref()) |
| 365 | .map_err(|_| DbErr::UnpackInsertId)? |
| 366 | } |
| 367 | (None, false) => { |
| 368 | let res = db.execute(statement).await?; |
| 369 | if res.rows_affected() == 0 { |
| 370 | return Err(DbErr::RecordNotInserted); |
| 371 | } |
| 372 | let last_insert_id = res.last_insert_id(); |
| 373 | // For MySQL, the affected-rows number: |
| 374 | // - The affected-rows value per row is `1` if the row is inserted as a new row, |
| 375 | // - `2` if an existing row is updated, |
| 376 | // - and `0` if an existing row is set to its current values. |
| 377 | // Reference: https://dev.mysql.com/doc/refman/8.4/en/insert-on-duplicate.html |
| 378 | if db_backend == DbBackend::MySql && last_insert_id == 0 { |
| 379 | return Err(DbErr::RecordNotInserted); |
| 380 | } |
| 381 | ValueTypeOf::<A>::try_from_u64(last_insert_id).map_err(|_| DbErr::UnpackInsertId)? |
| 382 | } |
| 383 | }; |
| 384 | |
| 385 | Ok(InsertResult { last_insert_id }) |
| 386 | } |
| 387 | |
| 388 | async fn exec_insert_without_returning<C>( |
| 389 | insert_statement: InsertStatement, |
no test coverage detected