| 
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