|
1 | 1 | use futures::TryStreamExt;
|
2 | 2 | use sqlx_core::mssql::MssqlRow;
|
3 | 3 | use sqlx_oldapi::mssql::{Mssql, MssqlPoolOptions};
|
4 |
| -use sqlx_oldapi::{Column, Connection, Executor, MssqlConnection, Row, Statement, TypeInfo}; |
| 4 | +use sqlx_oldapi::{ |
| 5 | + Column, Connection, Execute, Executor, MssqlConnection, Row, Statement, TypeInfo, |
| 6 | +}; |
5 | 7 | use sqlx_test::new;
|
6 | 8 | use std::sync::atomic::{AtomicI32, Ordering};
|
7 | 9 | use std::time::Duration;
|
@@ -501,3 +503,158 @@ async fn it_can_decode_tinyint_as_i16() -> anyhow::Result<()> {
|
501 | 503 |
|
502 | 504 | Ok(())
|
503 | 505 | }
|
| 506 | + |
| 507 | +#[sqlx_macros::test] |
| 508 | +async fn it_works_with_query_builder() -> anyhow::Result<()> { |
| 509 | + let mut conn = new::<Mssql>().await?; |
| 510 | + |
| 511 | + // Create a temporary table |
| 512 | + conn.execute( |
| 513 | + r#" |
| 514 | +CREATE TABLE #qb_test ( |
| 515 | + id INT PRIMARY KEY, |
| 516 | + name NVARCHAR(50) |
| 517 | +); |
| 518 | + "#, |
| 519 | + ) |
| 520 | + .await?; |
| 521 | + |
| 522 | + // Insert data using QueryBuilder |
| 523 | + let mut insert_builder = sqlx_oldapi::QueryBuilder::new("INSERT INTO #qb_test (id, name) "); |
| 524 | + |
| 525 | + #[derive(sqlx_oldapi::FromRow, Debug, PartialEq)] |
| 526 | + struct TestItem { |
| 527 | + id: i32, |
| 528 | + name: String, |
| 529 | + } |
| 530 | + |
| 531 | + let items_to_insert = vec![ |
| 532 | + TestItem { |
| 533 | + id: 1, |
| 534 | + name: "Alice".to_string(), |
| 535 | + }, |
| 536 | + TestItem { |
| 537 | + id: 2, |
| 538 | + name: "Bob".to_string(), |
| 539 | + }, |
| 540 | + TestItem { |
| 541 | + id: 3, |
| 542 | + name: "Charlie".to_string(), |
| 543 | + }, |
| 544 | + ]; |
| 545 | + |
| 546 | + insert_builder.push_values(items_to_insert.iter(), |mut b, item| { |
| 547 | + b.push_bind(item.id).push_bind(&item.name); |
| 548 | + }); |
| 549 | + |
| 550 | + let insert_query = insert_builder.build(); |
| 551 | + eprintln!("Generated INSERT SQL: {}", insert_query.sql()); // Debug print |
| 552 | + conn.execute(insert_query).await?; |
| 553 | + |
| 554 | + // Select data using QueryBuilder |
| 555 | + let mut select_builder = |
| 556 | + sqlx_oldapi::QueryBuilder::<'_, Mssql>::new("SELECT id, name FROM #qb_test WHERE id = "); |
| 557 | + select_builder.push_bind(2i32); |
| 558 | + let select_query = select_builder.build_query_as::<TestItem>(); |
| 559 | + |
| 560 | + let selected_item: TestItem = select_query.fetch_one(&mut conn).await?; |
| 561 | + |
| 562 | + assert_eq!(selected_item.id, 2); |
| 563 | + assert_eq!(selected_item.name, "Bob"); |
| 564 | + |
| 565 | + // Select multiple items |
| 566 | + let mut select_all_builder = sqlx_oldapi::QueryBuilder::<'_, Mssql>::new( |
| 567 | + "SELECT id, name FROM #qb_test WHERE name LIKE ", |
| 568 | + ); |
| 569 | + select_all_builder.push_bind("B%"); // Names starting with B |
| 570 | + let select_all_query = select_all_builder.build_query_as::<TestItem>(); |
| 571 | + |
| 572 | + let all_b_items: Vec<TestItem> = select_all_query.fetch_all(&mut conn).await?; |
| 573 | + assert_eq!(all_b_items.len(), 1); |
| 574 | + assert_eq!(all_b_items[0].id, 2); |
| 575 | + assert_eq!(all_b_items[0].name, "Bob"); |
| 576 | + |
| 577 | + conn.close().await?; |
| 578 | + Ok(()) |
| 579 | +} |
| 580 | + |
| 581 | +#[sqlx_macros::test] |
| 582 | +async fn it_executes_query_from_issue_11() -> anyhow::Result<()> { |
| 583 | + // https://github.com/sqlpage/sqlx-oldapi/issues/11 |
| 584 | + let mut conn = new::<Mssql>().await?; |
| 585 | + |
| 586 | + // Create a temporary table similar to the one in the issue |
| 587 | + conn.execute( |
| 588 | + r#" |
| 589 | +CREATE TABLE #temp_issue_table ( |
| 590 | + id INT PRIMARY KEY, |
| 591 | + name NVARCHAR(50) |
| 592 | +); |
| 593 | + "#, |
| 594 | + ) |
| 595 | + .await?; |
| 596 | + |
| 597 | + // Insert some data |
| 598 | + let insert_id1 = 100; |
| 599 | + let insert_name1 = "test_user_1"; |
| 600 | + let insert_id2 = 200; |
| 601 | + let insert_name2 = "test_user_2"; |
| 602 | + |
| 603 | + sqlx_oldapi::query("INSERT INTO #temp_issue_table (id, name) VALUES (@p1, @p2), (@p3, @p4)") |
| 604 | + .bind(insert_id1) |
| 605 | + .bind(insert_name1) |
| 606 | + .bind(insert_id2) |
| 607 | + .bind(insert_name2) |
| 608 | + .execute(&mut conn) |
| 609 | + .await?; |
| 610 | + |
| 611 | + // Define a struct to map the query results |
| 612 | + #[derive(sqlx_oldapi::FromRow, Debug, PartialEq)] |
| 613 | + struct TableRow { |
| 614 | + id: i32, |
| 615 | + name: String, |
| 616 | + } |
| 617 | + |
| 618 | + // Use QueryBuilder as in the issue report |
| 619 | + let id_to_select = insert_id1; |
| 620 | + let name_to_select = insert_name1; |
| 621 | + |
| 622 | + let mut builder = sqlx_oldapi::QueryBuilder::new("SELECT id, name FROM #temp_issue_table "); |
| 623 | + builder |
| 624 | + .push("WHERE id=") |
| 625 | + .push_bind(id_to_select) // Bind the specific id we want to find |
| 626 | + .push(" AND name=") |
| 627 | + .push_bind(name_to_select); // Bind the specific name |
| 628 | + |
| 629 | + let query = builder.build_query_as::<TableRow>(); |
| 630 | + let sql = query.sql(); |
| 631 | + eprintln!("Generated SQL for issue report test: {}", sql); |
| 632 | + assert_eq!( |
| 633 | + sql, |
| 634 | + "SELECT id, name FROM #temp_issue_table WHERE id=@p1 AND name=@p2" |
| 635 | + ); |
| 636 | + |
| 637 | + let selected_row: TableRow = query.fetch_one(&mut conn).await?; |
| 638 | + |
| 639 | + assert_eq!(selected_row.id, id_to_select); |
| 640 | + assert_eq!(selected_row.name, name_to_select); |
| 641 | + |
| 642 | + // Test selecting a non-existent row to ensure a different id/name fails as expected |
| 643 | + let mut builder_no_match = |
| 644 | + sqlx_oldapi::QueryBuilder::new("SELECT id, name FROM #temp_issue_table "); |
| 645 | + builder_no_match |
| 646 | + .push("WHERE id=") |
| 647 | + .push_bind(999) // Non-existent ID |
| 648 | + .push(" AND name=") |
| 649 | + .push_bind("no_such_user"); |
| 650 | + |
| 651 | + let query_no_match = builder_no_match.build_query_as::<TableRow>(); |
| 652 | + let result_no_match = query_no_match.fetch_optional(&mut conn).await?; |
| 653 | + assert!( |
| 654 | + result_no_match.is_none(), |
| 655 | + "Query should not have found a match for non-existent data" |
| 656 | + ); |
| 657 | + |
| 658 | + conn.close().await?; |
| 659 | + Ok(()) |
| 660 | +} |
0 commit comments