use std::sync::Arc;
use arrow_array::{RecordBatch, StringArray};
use arrow_schema::{DataType, Field, Schema, SchemaRef};
use once_cell::sync::Lazy;
use crate::error::Result;
use crate::sql::CommandGetCatalogs;
pub struct GetCatalogsBuilder {
catalogs: Vec<String>,
}
impl CommandGetCatalogs {
pub fn into_builder(self) -> GetCatalogsBuilder {
self.into()
}
}
impl From<CommandGetCatalogs> for GetCatalogsBuilder {
fn from(_: CommandGetCatalogs) -> Self {
Self::new()
}
}
impl Default for GetCatalogsBuilder {
fn default() -> Self {
Self::new()
}
}
impl GetCatalogsBuilder {
pub fn new() -> Self {
Self {
catalogs: Vec::new(),
}
}
pub fn append(&mut self, catalog_name: impl Into<String>) {
self.catalogs.push(catalog_name.into());
}
pub fn build(self) -> Result<RecordBatch> {
let Self { mut catalogs } = self;
catalogs.sort_unstable();
let batch = RecordBatch::try_new(
Arc::clone(&GET_CATALOG_SCHEMA),
vec![Arc::new(StringArray::from_iter_values(catalogs)) as _],
)?;
Ok(batch)
}
pub fn schema(&self) -> SchemaRef {
get_catalogs_schema()
}
}
fn get_catalogs_schema() -> SchemaRef {
Arc::clone(&GET_CATALOG_SCHEMA)
}
static GET_CATALOG_SCHEMA: Lazy<SchemaRef> = Lazy::new(|| {
Arc::new(Schema::new(vec![Field::new(
"catalog_name",
DataType::Utf8,
false,
)]))
});
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_catalogs_are_sorted() {
let batch = ["a_catalog", "c_catalog", "b_catalog"]
.into_iter()
.fold(GetCatalogsBuilder::new(), |mut builder, catalog| {
builder.append(catalog);
builder
})
.build()
.unwrap();
let catalogs = batch
.column(0)
.as_any()
.downcast_ref::<StringArray>()
.unwrap()
.iter()
.flatten()
.collect::<Vec<_>>();
assert!(catalogs.is_sorted());
assert_eq!(catalogs, ["a_catalog", "b_catalog", "c_catalog"]);
}
}