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}