| /* | |
| * 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. | |
| */ | |
| #pragma once | |
| /// \file iceberg/catalog/sql/sql_catalog.h | |
| /// SQL catalog implementation. | |
| /// | |
| /// `SqlCatalog` implements the Iceberg `Catalog` API on top of a relational | |
| /// database. Database access goes through the `CatalogStore` interface. | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <unordered_map> | |
| #include <unordered_set> | |
| #include <vector> | |
| #include "iceberg/catalog.h" | |
| #include "iceberg/catalog/sql/catalog_store.h" | |
| #include "iceberg/catalog/sql/iceberg_sql_catalog_export.h" | |
| #include "iceberg/result.h" | |
| #include "iceberg/table_identifier.h" | |
| #include "iceberg/type_fwd.h" | |
| namespace iceberg::sql { | |
| /// \brief Default maximum number of database connections for built-in SQL stores. | |
| constexpr static int32_t kMaxConnections = 10; | |
| /// \brief Configuration for the SQL catalog. | |
| struct ICEBERG_SQL_CATALOG_EXPORT SqlCatalogConfig { | |
| /// Logical catalog name. Scopes all rows via the `catalog_name` column so that | |
| /// multiple catalogs can share one database. | |
| std::string name = "sql_catalog"; | |
| /// Database connection string interpreted by the chosen `CatalogStore`. | |
| std::string uri; | |
| /// Base location used to derive table locations when none is supplied. | |
| std::string warehouse_location; | |
| /// Maximum number of database connections. Built-in stores use a single | |
| /// connection when this is 1 and a bounded sqlpp23 connection pool otherwise. | |
| int32_t max_connections = kMaxConnections; | |
| /// Additional connector-specific properties. | |
| std::unordered_map<std::string, std::string> props; | |
| }; | |
| /// \brief SQL-backed Iceberg catalog. | |
| class ICEBERG_SQL_CATALOG_EXPORT SqlCatalog | |
| : public Catalog, | |
| public std::enable_shared_from_this<SqlCatalog> { | |
| public: | |
| ~SqlCatalog() override; | |
| SqlCatalog(const SqlCatalog&) = delete; | |
| SqlCatalog& operator=(const SqlCatalog&) = delete; | |
| SqlCatalog(SqlCatalog&&) = delete; | |
| SqlCatalog& operator=(SqlCatalog&&) = delete; | |
| /// \brief Create a catalog backed by a user-supplied `CatalogStore`. | |
| /// | |
| /// This is the extension point for custom databases/drivers: implement | |
| /// `CatalogStore` and pass it here. The catalog initializes its schema | |
| /// (creating the backing tables if they do not exist) before returning. | |
| /// | |
| /// \param config Catalog configuration (name and warehouse location are used; | |
| /// `uri` is informational because the store is already constructed). | |
| /// \param file_io File IO used to read and write table metadata files. | |
| /// \param store The catalog metadata store. Must not be null. | |
| static Result<std::shared_ptr<SqlCatalog>> Make(const SqlCatalogConfig& config, | |
| std::shared_ptr<FileIO> file_io, | |
| std::shared_ptr<CatalogStore> store); | |
| std::string_view name() const override; | |
| Status CreateNamespace( | |
| const Namespace& ns, | |
| const std::unordered_map<std::string, std::string>& properties) override; | |
| Result<std::vector<Namespace>> ListNamespaces(const Namespace& ns) const override; | |
| Result<std::unordered_map<std::string, std::string>> GetNamespaceProperties( | |
| const Namespace& ns) const override; | |
| Status DropNamespace(const Namespace& ns) override; | |
| Result<bool> NamespaceExists(const Namespace& ns) const override; | |
| Status UpdateNamespaceProperties( | |
| const Namespace& ns, const std::unordered_map<std::string, std::string>& updates, | |
| const std::unordered_set<std::string>& removals) override; | |
| Result<std::vector<TableIdentifier>> ListTables(const Namespace& ns) const override; | |
| Result<std::shared_ptr<Table>> CreateTable( | |
| const TableIdentifier& identifier, const std::shared_ptr<Schema>& schema, | |
| const std::shared_ptr<PartitionSpec>& spec, const std::shared_ptr<SortOrder>& order, | |
| const std::string& location, | |
| const std::unordered_map<std::string, std::string>& properties) override; | |
| Result<std::shared_ptr<Table>> UpdateTable( | |
| const TableIdentifier& identifier, | |
| const std::vector<std::unique_ptr<TableRequirement>>& requirements, | |
| const std::vector<std::unique_ptr<TableUpdate>>& updates) override; | |
| Result<std::shared_ptr<Transaction>> StageCreateTable( | |
| const TableIdentifier& identifier, const std::shared_ptr<Schema>& schema, | |
| const std::shared_ptr<PartitionSpec>& spec, const std::shared_ptr<SortOrder>& order, | |
| const std::string& location, | |
| const std::unordered_map<std::string, std::string>& properties) override; | |
| Result<bool> TableExists(const TableIdentifier& identifier) const override; | |
| /// \brief Drop a table. | |
| /// | |
| /// SqlCatalog currently removes only the catalog entry. Support for deleting | |
| /// table data and metadata files when `purge` is true is not implemented yet. | |
| Status DropTable(const TableIdentifier& identifier, bool purge) override; | |
| Status RenameTable(const TableIdentifier& from, const TableIdentifier& to) override; | |
| Result<std::shared_ptr<Table>> LoadTable(const TableIdentifier& identifier) override; | |
| Result<std::shared_ptr<Table>> RegisterTable( | |
| const TableIdentifier& identifier, | |
| const std::string& metadata_file_location) override; | |
| /// \brief Create a catalog backed by the built-in SQLite client. | |
| /// | |
| /// \param config `uri` is the SQLite database file path (or ":memory:"). | |
| /// \param file_io File IO used to read and write table metadata files. | |
| /// \return A catalog instance, or ErrorKind::kNotSupported if the SQLite | |
| /// connector was not built. | |
| static Result<std::shared_ptr<SqlCatalog>> MakeSqliteCatalog( | |
| const SqlCatalogConfig& config, std::shared_ptr<FileIO> file_io); | |
| /// \brief Create a catalog backed by the built-in PostgreSQL (libpq) client. | |
| /// | |
| /// \param config `uri` is parsed as | |
| /// `[scheme://][user[:password]@]host[:port][/database]`. | |
| /// \param file_io File IO used to read and write table metadata files. | |
| /// \return A catalog instance, or ErrorKind::kNotSupported if the PostgreSQL | |
| /// connector was not built. | |
| static Result<std::shared_ptr<SqlCatalog>> MakePostgreSqlCatalog( | |
| const SqlCatalogConfig& config, std::shared_ptr<FileIO> file_io); | |
| /// \brief Create a catalog backed by the built-in MySQL client. | |
| /// | |
| /// \param config `uri` is parsed as | |
| /// `[scheme://][user[:password]@]host[:port][/database]`. | |
| /// \param file_io File IO used to read and write table metadata files. | |
| /// \return A catalog instance, or ErrorKind::kNotSupported if the MySQL | |
| /// connector was not built. | |
| static Result<std::shared_ptr<SqlCatalog>> MakeMySqlCatalog( | |
| const SqlCatalogConfig& config, std::shared_ptr<FileIO> file_io); | |
| private: | |
| SqlCatalog(SqlCatalogConfig config, std::shared_ptr<FileIO> file_io, | |
| std::shared_ptr<CatalogStore> store, | |
| std::shared_ptr<MetricsReporter> reporter); | |
| /// \brief Resolve the current metadata location for a table, or NoSuchTable. | |
| Result<std::string> GetTableMetadataLocation(const TableIdentifier& identifier) const; | |
| /// \brief Build a Table object from a metadata location. | |
| Result<std::shared_ptr<Table>> LoadTableFrom(const TableIdentifier& identifier, | |
| const std::string& metadata_location); | |
| SqlCatalogConfig config_; | |
| std::shared_ptr<FileIO> file_io_; | |
| std::shared_ptr<CatalogStore> store_; | |
| std::shared_ptr<MetricsReporter> reporter_; | |
| }; | |
| } // namespace iceberg::sql |