|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include "duckdb.hpp" |
| 4 | +#include "duckdb/common/mutex.hpp" |
| 5 | + |
| 6 | +#include <memory> |
| 7 | +#include <string> |
| 8 | +#include <vector> |
| 9 | + |
| 10 | +namespace duckdb { |
| 11 | + |
| 12 | +// Forward declaration |
| 13 | +class LanceTableEntry; |
| 14 | + |
| 15 | +//===--------------------------------------------------------------------===// |
| 16 | +// Policy for dataset path resolution behavior |
| 17 | +//===--------------------------------------------------------------------===// |
| 18 | +enum class LanceResolvePolicy : uint8_t { |
| 19 | + // Must be a Lance table, throw exception if not found or not Lance table |
| 20 | + STRICT = 0, |
| 21 | + // First try catalog lookup, fallback to file path if failed |
| 22 | + FALLBACK_TO_PATH = 1, |
| 23 | +}; |
| 24 | + |
| 25 | +//===--------------------------------------------------------------------===// |
| 26 | +// Result of dataset resolution |
| 27 | +//===--------------------------------------------------------------------===// |
| 28 | +struct LanceResolveResult { |
| 29 | + bool success; |
| 30 | + string dataset_uri; |
| 31 | + string error_message; |
| 32 | + |
| 33 | + // Explicit constructor for C++11 compatibility |
| 34 | + LanceResolveResult() : success(false), dataset_uri(), error_message() {} |
| 35 | + |
| 36 | + LanceResolveResult(bool success_, string uri, string error) |
| 37 | + : success(success_), dataset_uri(std::move(uri)), |
| 38 | + error_message(std::move(error)) {} |
| 39 | + |
| 40 | + static LanceResolveResult Success(string uri) { |
| 41 | + return LanceResolveResult(true, std::move(uri), ""); |
| 42 | + } |
| 43 | + |
| 44 | + static LanceResolveResult Failure(string error) { |
| 45 | + return LanceResolveResult(false, "", std::move(error)); |
| 46 | + } |
| 47 | +}; |
| 48 | + |
| 49 | +//===--------------------------------------------------------------------===// |
| 50 | +// Interface for Lance dataset resolver |
| 51 | +// Third-party can implement this to provide custom resolution logic |
| 52 | +//===--------------------------------------------------------------------===// |
| 53 | +class ILanceDatasetResolver { |
| 54 | +public: |
| 55 | + virtual ~ILanceDatasetResolver() = default; |
| 56 | + |
| 57 | + //! Try to resolve the input string to a Lance dataset URI |
| 58 | + //! Returns LanceResolveResult indicating success/failure |
| 59 | + virtual LanceResolveResult TryResolve(ClientContext &context, |
| 60 | + const string &input) = 0; |
| 61 | + |
| 62 | + //! Priority of this resolver (higher priority runs first) |
| 63 | + //! Default implementation has priority 0 |
| 64 | + //! Third-party can use higher priority to override default behavior |
| 65 | + //! or use negative priority to serve as fallback |
| 66 | + virtual int Priority() const { return 0; } |
| 67 | + |
| 68 | + //! Name of this resolver for debugging and unregistration |
| 69 | + virtual string Name() const = 0; |
| 70 | +}; |
| 71 | + |
| 72 | +//===--------------------------------------------------------------------===// |
| 73 | +// Registry for dataset resolvers (singleton pattern) |
| 74 | +//===--------------------------------------------------------------------===// |
| 75 | +class LanceDatasetResolverRegistry { |
| 76 | +public: |
| 77 | + //! Get the singleton instance |
| 78 | + static LanceDatasetResolverRegistry &Get(); |
| 79 | + |
| 80 | + //! Register a custom resolver |
| 81 | + //! Resolvers are sorted by priority (descending) after registration |
| 82 | + void RegisterResolver(shared_ptr<ILanceDatasetResolver> resolver); |
| 83 | + |
| 84 | + //! Unregister a resolver by name |
| 85 | + //! Returns true if a resolver was removed |
| 86 | + bool UnregisterResolver(const string &name); |
| 87 | + |
| 88 | + //! Get all registered resolver names (for debugging) |
| 89 | + vector<string> GetResolverNames() const; |
| 90 | + |
| 91 | + //! Main resolution function |
| 92 | + //! This is the public API that should be called by all Lance functions |
| 93 | + //! @param context The client context |
| 94 | + //! @param input The input value (table name or file path) |
| 95 | + //! @param policy The resolution policy (STRICT or FALLBACK_TO_PATH) |
| 96 | + //! @param function_name The name of the calling function (for error messages) |
| 97 | + //! @return The resolved dataset URI |
| 98 | + string Resolve(ClientContext &context, const Value &input, |
| 99 | + LanceResolvePolicy policy, const string &function_name); |
| 100 | + |
| 101 | +private: |
| 102 | + LanceDatasetResolverRegistry(); |
| 103 | + ~LanceDatasetResolverRegistry() = default; |
| 104 | + |
| 105 | + // Non-copyable |
| 106 | + LanceDatasetResolverRegistry(const LanceDatasetResolverRegistry &) = delete; |
| 107 | + LanceDatasetResolverRegistry & |
| 108 | + operator=(const LanceDatasetResolverRegistry &) = delete; |
| 109 | + |
| 110 | + //! Sort resolvers by priority (descending) |
| 111 | + void SortResolvers(); |
| 112 | + |
| 113 | + mutable mutex lock_; |
| 114 | + vector<shared_ptr<ILanceDatasetResolver>> resolvers_; |
| 115 | +}; |
| 116 | + |
| 117 | +//===--------------------------------------------------------------------===// |
| 118 | +// Default catalog resolver implementation |
| 119 | +// Resolves table names through DuckDB's catalog system |
| 120 | +//===--------------------------------------------------------------------===// |
| 121 | +class DefaultCatalogResolver : public ILanceDatasetResolver { |
| 122 | +public: |
| 123 | + LanceResolveResult TryResolve(ClientContext &context, |
| 124 | + const string &input) override; |
| 125 | + |
| 126 | + int Priority() const override { return 0; } |
| 127 | + |
| 128 | + string Name() const override { return "default_catalog"; } |
| 129 | +}; |
| 130 | + |
| 131 | +//===--------------------------------------------------------------------===// |
| 132 | +// Convenience function (wraps registry call) |
| 133 | +// This is the recommended API for resolving Lance dataset URIs |
| 134 | +//===--------------------------------------------------------------------===// |
| 135 | +string ResolveLanceDatasetUri(ClientContext &context, const Value &input, |
| 136 | + LanceResolvePolicy policy, |
| 137 | + const string &function_name); |
| 138 | + |
| 139 | +} // namespace duckdb |
0 commit comments