Skip to main content

odbc_api/catalog/
tables.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 [`crate::Preallocated::tables`]. The members are associated with the columns
9/// of the result set returned by [`crate::Preallocated::tables_cursor`].
10///
11/// See: <https://learn.microsoft.com/sql/odbc/reference/syntax/sqltables-function>
12#[derive(Clone, Copy, Default)]
13pub struct TablesRow {
14    /// Binds to the `TABLE_CAT` column. Catalog name. NULL if not applicable.
15    pub catalog: VarCharArray<128>,
16    /// Binds to the `TABLE_SCHEM` column. Schema name. NULL if not applicable.
17    pub schema: VarCharArray<128>,
18    /// Binds to the `TABLE_NAME` column. Table name.
19    pub table: VarCharArray<255>,
20    /// Binds to the `TABLE_TYPE` column. Table type identifier, e.g. `"TABLE"`, `"VIEW"`.
21    pub table_type: VarCharArray<255>,
22    /// Binds to the `REMARKS` column. Description of the table. NULL if unavailable.
23    pub remarks: VarCharArray<1024>,
24}
25
26unsafe impl FetchRow for TablesRow {
27    unsafe fn bind_columns_to_cursor(&mut self, mut cursor: StatementRef<'_>) -> Result<(), Error> {
28        unsafe {
29            self.catalog.bind_to_col(1, &mut cursor)?;
30            self.schema.bind_to_col(2, &mut cursor)?;
31            self.table.bind_to_col(3, &mut cursor)?;
32            self.table_type.bind_to_col(4, &mut cursor)?;
33            self.remarks.bind_to_col(5, &mut cursor)?;
34            Ok(())
35        }
36    }
37
38    fn find_truncation(&self) -> Option<TruncationInfo> {
39        if let Some(t) = self.catalog.find_truncation(0) {
40            return Some(t);
41        }
42        if let Some(t) = self.schema.find_truncation(1) {
43            return Some(t);
44        }
45        if let Some(t) = self.table.find_truncation(2) {
46            return Some(t);
47        }
48        if let Some(t) = self.table_type.find_truncation(3) {
49            return Some(t);
50        }
51        if let Some(t) = self.remarks.find_truncation(4) {
52            return Some(t);
53        }
54        None
55    }
56}
57
58pub fn execute_tables<S>(
59    mut statement: S,
60    catalog_name: &str,
61    schema_name: &str,
62    table_name: &str,
63    table_type: &str,
64) -> Result<CursorImpl<S>, Error>
65where
66    S: AsStatementRef,
67{
68    let mut stmt = statement.as_stmt_ref();
69
70    stmt.tables(
71        &SqlText::new(catalog_name),
72        &SqlText::new(schema_name),
73        &SqlText::new(table_name),
74        &SqlText::new(table_type),
75    )
76    .into_result(&stmt)?;
77
78    // We assume tables always creates a result set, since it works like a SELECT statement.
79    debug_assert_ne!(stmt.num_result_cols().unwrap(), 0);
80
81    // Safe: `statement` is in Cursor state.
82    let cursor = unsafe { CursorImpl::new(statement) };
83
84    Ok(cursor)
85}