Repository: risingwavelabs/risingwave
File: src/meta/src/controller/catalog/get_op.rs (Rust)

Code before:
            .await?;
        if let Some((table, obj)) = table_obj {
            Ok(ObjectModel(table, obj.unwrap()).into())
        } else {
            Err(MetaError::catalog_id_not_found("table", table_id))
        }
    }

    pub async fn get_user_created_table_by_ids(
        &self,
        job_ids: impl Iterator<Item = JobId>,
    ) -> MetaResult<Vec<PbTable>> {
        let inner = self.inner.read().await;
        let table_objs = Table::find()
            .find_also_related(Object)
            .filter(
                table::Column::TableId
                    .is_in(job_ids.map(|job_id| job_id.as_mv_table_id()).collect_vec())
                    .and(table::Column::TableType.eq(TableType::Table)),
            )
            .all(&inner.db)
            .await?;
        let tables = table_objs
            .into_iter()
            .map(|(table, obj)| ObjectModel(table, obj.unwrap()).into())
            .collect();
        Ok(tables)
    }

    pub async fn get_table_by_ids(
        &self,
        table_ids: Vec<TableId>,
        include_dropped_table: bool,
    ) -> MetaResult<Vec<PbTable>> {
        let inner = self.inner.read().await;
        let table_objs = Table::find()
            .find_also_related(Object)
            .filter(table::Column::TableId.is_in(table_ids.clone()))
            .all(&inner.db)
            .await?;
        let tables = table_objs
            .into_iter()
            .map(|(table, obj)| ObjectModel(table, obj.unwrap()).into());
        let tables = if include_dropped_table {
            tables
                .chain(inner.dropped_tables.iter().filter_map(|(id, t)| {
                    if table_ids.contains(id) {
                        Some(t.clone())
                    } else {
                        None
                    }

Review comment (suggestion):
The new public method `get_user_created_table_by_ids_in_txn` lacks rustdoc documentation. This public API method should include documentation explaining:
- The purpose of the transactional variant
- Parameter descriptions (the generic transaction parameter and `job_ids` iterator)
- Return value semantics
- When to use this variant vs the non-transactional `get_user_created_table_by_ids`

Code after:
            .one(&inner.db)
            .await?;
        if let Some((table, obj)) = table_obj {
            Ok(ObjectModel(table, obj.unwrap()).into())
        } else {
            Err(MetaError::catalog_id_not_found("table", table_id))
        }
    }

    pub async fn get_user_created_table_by_ids(
        &self,
        job_ids: impl Iterator<Item = JobId>,
    ) -> MetaResult<Vec<PbTable>> {
        let inner = self.inner.read().await;
        self.get_user_created_table_by_ids_in_txn(&inner.db, job_ids)
            .await
    }

    pub async fn get_user_created_table_by_ids_in_txn<C>(
        &self,
        txn: &C,
        job_ids: impl Iterator<Item = JobId>,
    ) -> MetaResult<Vec<PbTable>>
    where
        C: ConnectionTrait,
    {
        let table_objs = Table::find()
            .find_also_related(Object)
            .filter(
                table::Column::TableId
                    .is_in(job_ids.map(|job_id| job_id.as_mv_table_id()).collect_vec())
                    .and(table::Column::TableType.eq(TableType::Table)),
            )
            .all(txn)
            .await?;
        Ok(table_objs
            .into_iter()
            .map(|(table, obj)| ObjectModel(table, obj.unwrap()).into())
            .collect())
    }

    pub async fn get_table_by_ids(
        &self,
        table_ids: Vec<TableId>,
        include_dropped_table: bool,
    ) -> MetaResult<Vec<PbTable>> {
        let inner = self.inner.read().await;
        let table_objs = Table::find()
            .find_also_related(Object)
            .filter(table::Column::TableId.is_in(table_ids.clone()))
            .all(&inner.db)