1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

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;

/// A builder for a [`CommandGetCatalogs`] response.
///
/// Builds rows like this:
///
/// * catalog_name: utf8,
pub struct GetCatalogsBuilder {
    catalogs: Vec<String>,
}

impl CommandGetCatalogs {
    /// Create a builder suitable for constructing a response
    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 {
    /// Create a new instance of [`GetCatalogsBuilder`]
    pub fn new() -> Self {
        Self {
            catalogs: Vec::new(),
        }
    }

    /// Append a row
    pub fn append(&mut self, catalog_name: impl Into<String>) {
        self.catalogs.push(catalog_name.into());
    }

    /// builds a `RecordBatch` with the correct schema for a
    /// [`CommandGetCatalogs`] response
    pub fn build(self) -> Result<RecordBatch> {
        let Self { catalogs } = self;

        let batch = RecordBatch::try_new(
            Arc::clone(&GET_CATALOG_SCHEMA),
            vec![Arc::new(StringArray::from_iter_values(catalogs)) as _],
        )?;

        Ok(batch)
    }

    /// Returns the schema that will result from [`CommandGetCatalogs`]
    ///
    /// [`CommandGetCatalogs`]: crate::sql::CommandGetCatalogs
    pub fn schema(&self) -> SchemaRef {
        get_catalogs_schema()
    }
}

fn get_catalogs_schema() -> SchemaRef {
    Arc::clone(&GET_CATALOG_SCHEMA)
}

/// The schema for GetCatalogs
static GET_CATALOG_SCHEMA: Lazy<SchemaRef> = Lazy::new(|| {
    Arc::new(Schema::new(vec![Field::new(
        "catalog_name",
        DataType::Utf8,
        false,
    )]))
});