Source code for sqlspec.adapters.duckdb.config

"""DuckDB database configuration with connection pooling."""

from collections.abc import Callable, Sequence
from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypedDict, cast

from typing_extensions import NotRequired

from sqlspec.adapters.duckdb._typing import DuckDBConnection, DuckDBCursor, DuckDBSessionContext
from sqlspec.adapters.duckdb.core import (
    apply_driver_features,
    build_connection_config,
    build_statement_config,
    default_statement_config,
)
from sqlspec.adapters.duckdb.driver import DuckDBDriver, DuckDBExceptionHandler
from sqlspec.adapters.duckdb.pool import DuckDBConnectionPool
from sqlspec.config import ExtensionConfigs, SyncDatabaseConfig
from sqlspec.driver._sync import SyncPoolConnectionContext, SyncPoolSessionFactory
from sqlspec.extensions.events import EventRuntimeHints
from sqlspec.utils.config_tools import normalize_connection_config
from sqlspec.utils.serializers import to_json

if TYPE_CHECKING:
    from sqlspec.core import StatementConfig
    from sqlspec.observability import ObservabilityConfig
__all__ = (
    "DuckDBConfig",
    "DuckDBConnectionParams",
    "DuckDBDriverFeatures",
    "DuckDBExtensionConfig",
    "DuckDBPoolParams",
    "DuckDBSecretConfig",
)
EXTENSION_FLAG_KEYS: "tuple[str, ...]" = (
    "allow_community_extensions",
    "allow_unsigned_extensions",
    "enable_external_access",
)


class DuckDBConnectionParams(TypedDict):
    """DuckDB connection parameters.

    Mirrors the keyword arguments accepted by duckdb.connect so callers can drive every DuckDB
    configuration switch directly through SQLSpec. All keys are optional and forwarded verbatim
    to DuckDB, either as top-level parameters or via the nested ``config`` dictionary when DuckDB
    expects them there.
    """

    database: NotRequired[str]
    read_only: NotRequired[bool]
    config: NotRequired["dict[str, Any]"]
    memory_limit: NotRequired[str]
    threads: NotRequired[int]
    temp_directory: NotRequired[str]
    max_temp_directory_size: NotRequired[str]
    autoload_known_extensions: NotRequired[bool]
    autoinstall_known_extensions: NotRequired[bool]
    allow_community_extensions: NotRequired[bool]
    allow_unsigned_extensions: NotRequired[bool]
    extension_directory: NotRequired[str]
    custom_extension_repository: NotRequired[str]
    autoinstall_extension_repository: NotRequired[str]
    allow_persistent_secrets: NotRequired[bool]
    enable_external_access: NotRequired[bool]
    secret_directory: NotRequired[str]
    enable_object_cache: NotRequired[bool]
    parquet_metadata_cache: NotRequired[bool]
    enable_external_file_cache: NotRequired[bool]
    checkpoint_threshold: NotRequired[str]
    enable_progress_bar: NotRequired[bool]
    progress_bar_time: NotRequired[int]
    enable_logging: NotRequired[bool]
    log_query_path: NotRequired[str]
    logging_level: NotRequired[str]
    preserve_insertion_order: NotRequired[bool]
    default_null_order: NotRequired[str]
    default_order: NotRequired[str]
    ieee_floating_point_ops: NotRequired[bool]
    binary_as_string: NotRequired[bool]
    arrow_large_buffer_size: NotRequired[bool]
    errors_as_json: NotRequired[bool]
    extra: NotRequired["dict[str, Any]"]


class DuckDBPoolParams(DuckDBConnectionParams):
    """Complete pool configuration for DuckDB adapter.

    Extends DuckDBConnectionParams with lifecycle settings consumed by SQLSpec's
    thread-local DuckDB connection manager.
    """

    pool_recycle_seconds: NotRequired[int]
    health_check_interval: NotRequired[float]


class DuckDBExtensionConfig(TypedDict):
    """DuckDB extension configuration for auto-management."""

    name: str
    """Name of the extension to install/load."""

    version: NotRequired[str]
    """Specific version of the extension."""

    repository: NotRequired[str]
    """Repository for the extension (core, community, or custom URL)."""

    repository_url: NotRequired[str]
    """Custom repository URL for the extension."""

    force_install: NotRequired[bool]
    """Force reinstallation of the extension."""

    install: NotRequired[bool]
    """Force an explicit install_extension() call even for a name-only config."""

    required: NotRequired[bool]
    """When True, install/load failure raises instead of best-effort WARNING."""
class DuckDBSecretConfig(TypedDict): """DuckDB secret configuration for AI/API integrations.""" secret_type: str """Type of secret.""" name: str """Name of the secret.""" value: NotRequired["dict[str, Any]"] """Secret configuration values.""" provider: NotRequired[str] """Secret provider, such as config or credential_chain.""" scope: NotRequired[str] """Optional path or storage-prefix scope for the secret.""" persistent: NotRequired[bool] """Persist the secret to DuckDB's configured secret directory.""" required: NotRequired[bool] """When True, secret-creation failure raises (and is verified). Default best-effort."""