Skip to main content

sqlx_mssql_odbc_core/
describe.rs

1//! Compile-time query description for the MSSQL ODBC macros.
2//!
3//! Only available with the `offline` feature.
4
5use crate::{Mssql, MssqlConnectOptions, MssqlConnection, MssqlStatement};
6use sqlx_core::describe::Describe;
7use sqlx_core::sql_str::{AssertSqlSafe, SqlSafeStr};
8use sqlx_core::statement::Statement as _;
9use sqlx_core::Either;
10
11/// Compile-time query descriptor plugged into [`sqlx_macros_core`].
12#[doc(hidden)]
13pub const MSSQL_DRIVER: sqlx_macros_core::query::QueryDriver =
14    sqlx_macros_core::query::QueryDriver::new::<Mssql>();
15
16impl sqlx_macros_core::database::DatabaseExt for Mssql {
17    const DATABASE_PATH: &'static str = "sqlx_mssql_odbc::Mssql";
18    const ROW_PATH: &'static str = "sqlx_mssql_odbc::MssqlRow";
19
20    fn describe_blocking(
21        query: &str,
22        database_url: &str,
23        driver_config: &sqlx_core::config::drivers::Config,
24    ) -> sqlx_core::Result<Describe<Self>> {
25        describe_blocking(query, database_url, driver_config)
26    }
27}
28
29/// Connects to an MSSQL database via ODBC at compile time and describes a SQL query.
30///
31/// Returns column metadata, parameter count, and nullability information.
32/// This function is `#[doc(hidden)]` — it is only used by the proc macros.
33///
34/// # Limitations
35///
36/// - Parameter types are not available (only the count is reported).
37#[doc(hidden)]
38pub fn describe_blocking(
39    query: &str,
40    database_url: &str,
41    _driver_config: &sqlx_core::config::drivers::Config,
42) -> Result<Describe<Mssql>, sqlx_core::Error> {
43    // Parse the database URL into connection options.
44    let options: MssqlConnectOptions = database_url
45        .parse()
46        .map_err(|e| sqlx_core::Error::Configuration(Box::new(e)))?;
47
48    // Open a blocking connection.
49    let mut conn = MssqlConnection::connect_blocking(&options)?;
50
51    // Prepare the statement to get column metadata and parameter count.
52    let sql_str = AssertSqlSafe(query.to_owned()).into_sql_str();
53    let statement: MssqlStatement = conn.prepare_blocking(sql_str)?;
54
55    let column_count = statement.columns().len();
56    let parameter_count = statement
57        .parameters()
58        .map(|p| match p {
59            Either::Left(types) => types.len(),
60            Either::Right(count) => count,
61        })
62        .unwrap_or(0);
63
64    Ok(Describe {
65        columns: statement.columns().to_vec(),
66        parameters: Some(Either::Right(parameter_count)),
67        nullable: statement
68            .columns()
69            .iter()
70            .map(|col| col.nullable())
71            .collect(),
72    })
73}