Skip to main content

odbc_api/catalog/
primary_keys.rs

1use crate::{
2    CursorImpl, Error, TruncationInfo,
3    buffers::{FetchRow, FetchRowMember as _},
4    handles::{AsStatementRef, SqlText, Statement, StatementRef},
5    parameter::VarCharArray,
6};
7
8/// A row returned by the iterator returned by [`crate::Preallocated::primary_keys`]. The members
9/// are associated with the columns of the result set returned by
10/// [`crate::Preallocated::primary_keys_cursor`].
11///
12/// See: <https://learn.microsoft.com/sql/odbc/reference/syntax/sqlprimarykeys-function>
13#[derive(Clone, Copy, Default)]
14pub struct PrimaryKeysRow {
15    // The maximum length of the VARCHAR columns is driver specific. Since this type needs to be
16    // `Copy` in order to be suitable for row wise bulk fetchings sensible upper bounds have been
17    // chosen. They have been determined by using the maximum lengths reported by PostgreSQL and
18    // Microsoft SQL Server, MariaDB and SQLite.
19    //
20    /// Binds to the `TABLE_CAT` column. Primary key table catalog name. NULL if not applicable to
21    /// the data source. If a driver supports catalogs for some tables but not for others, such as
22    /// when the driver retrieves data from different DBMSs, it returns an empty string ("") for
23    /// those tables that do not have catalogs.
24    pub catalog: VarCharArray<128>,
25    /// Binds to `TABLE_SCHEM`. Primary key table schema name; NULL if not applicable to the data
26    /// source. If a driver supports schemas for some tables but not for others, such as when the
27    /// driver retrieves data from different DBMSs, it returns an empty string ("") for those tables
28    /// that do not have schemas.
29    pub schema: VarCharArray<128>,
30    /// Binds to the `TABLE_NAME` column. Primary key table name. Drivers must not return NULL.
31    pub table: VarCharArray<255>,
32    /// Binds to the `COLUMN_NAME` column. Primary key column name. The driver returns an empty
33    /// string for a column that does not have a name. Drivers must not return NULL.
34    pub column: VarCharArray<255>,
35    /// Binds to the `KEY_SEQ` column. Column sequence number in key (starting with 1).
36    pub key_seq: i16,
37    /// Binds to the `PK_NAME` column. Primary key name. NULL if not applicable to the data source.
38    pub pk_name: VarCharArray<128>,
39}
40
41unsafe impl FetchRow for PrimaryKeysRow {
42    unsafe fn bind_columns_to_cursor(&mut self, mut cursor: StatementRef<'_>) -> Result<(), Error> {
43        unsafe {
44            self.catalog.bind_to_col(1, &mut cursor)?;
45            self.schema.bind_to_col(2, &mut cursor)?;
46            self.table.bind_to_col(3, &mut cursor)?;
47            self.column.bind_to_col(4, &mut cursor)?;
48            self.key_seq.bind_to_col(5, &mut cursor)?;
49            self.pk_name.bind_to_col(6, &mut cursor)?;
50            Ok(())
51        }
52    }
53
54    fn find_truncation(&self) -> Option<TruncationInfo> {
55        if let Some(t) = self.catalog.find_truncation(0) {
56            return Some(t);
57        }
58        if let Some(t) = self.schema.find_truncation(1) {
59            return Some(t);
60        }
61        if let Some(t) = self.table.find_truncation(2) {
62            return Some(t);
63        }
64        if let Some(t) = self.column.find_truncation(3) {
65            return Some(t);
66        }
67        if let Some(t) = self.key_seq.find_truncation(4) {
68            return Some(t);
69        }
70        if let Some(t) = self.pk_name.find_truncation(5) {
71            return Some(t);
72        }
73        None
74    }
75}
76
77pub fn execute_primary_keys<S>(
78    mut statement: S,
79    catalog_name: Option<&str>,
80    schema_name: Option<&str>,
81    table_name: &str,
82) -> Result<CursorImpl<S>, Error>
83where
84    S: AsStatementRef,
85{
86    let mut stmt = statement.as_stmt_ref();
87    stmt.primary_keys(
88        catalog_name.map(SqlText::new).as_ref(),
89        schema_name.map(SqlText::new).as_ref(),
90        &SqlText::new(table_name),
91    )
92    .into_result(&stmt)?;
93    // SAFETY: primary_keys puts stmt into cursor state.
94    let cursor = unsafe { CursorImpl::new(statement) };
95    Ok(cursor)
96}