# coding: utf-8

"""
    Mixpeek API

    This is the Mixpeek API, providing access to various endpoints for data processing and retrieval.

    The version of the OpenAPI document: 1.3.0
    Contact: info@mixpeek.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, Field, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from mixpeek.models.error_handling import ErrorHandling
from mixpeek.models.logical_operator import LogicalOperator
from mixpeek.models.on_no_results import OnNoResults
from mixpeek.models.result_handling import ResultHandling
from typing import Optional, Set
from typing_extensions import Self

class StageParamsSqlLookup(BaseModel):
    """
    Configuration for SQL Lookup enrichment stage.  **Stage Category**: APPLY (1-1 Enrichment or 0-M Document Creation)  **Transformation**: - With documents: N documents -> N documents (expanded schema) - Without documents: 0 documents -> M documents (from SQL results)  **Purpose**: Enriches documents by running SQL queries against organization connections (PostgreSQL, Snowflake). Enables joining structured database data with document pipelines.  **Security**: - Only SELECT queries allowed (no INSERT/UPDATE/DELETE/DROP) - Uses parameterized queries to prevent SQL injection - Connection credentials managed via organization connections - Query timeout enforced  **Supported Providers**: - PostgreSQL: Full SQL support with $1, $2 placeholders - Snowflake: Full SQL support (coming soon)  **When to Use**: - Lookup customer data from database by ID - Enrich products with inventory information - Join document metadata with relational data - Create documents from SQL query results  **When NOT to Use**: - Complex analytics queries (use dedicated analytics tools) - High-volume batch operations (use ETL pipelines) - Real-time streaming (use event systems)  Requirements:     - connection_id: REQUIRED, organization connection ID or name     - query: REQUIRED, SQL SELECT query     - parameters: OPTIONAL, named parameters for query     - output_field: OPTIONAL, where to store results     - result_handling: OPTIONAL, how to handle multiple rows     - timeout: OPTIONAL, query timeout (default: 30s)     - when: OPTIONAL, conditional enrichment filter     - on_error: OPTIONAL, error handling strategy
    """ # noqa: E501
    connection_id: StrictStr = Field(description="REQUIRED. Organization connection ID (conn_...) or name. Connection must be SQL-capable (PostgreSQL or Snowflake). Use POST /v1/organizations/connections to create connections. Example: 'conn_abc123' or 'my_postgres_db'")
    query: StrictStr = Field(description="REQUIRED. SQL SELECT query to execute. Only SELECT queries allowed - mutations are blocked. Use $1, $2, etc. for PostgreSQL parameter placeholders. Supports template variables in 'parameters' field values. Example: 'SELECT * FROM products WHERE sku = $1'")
    parameters: Optional[Dict[str, Any]] = Field(default=None, description="OPTIONAL. Named parameters for SQL query. Keys are parameter names, values support template syntax. Parameters are converted to positional args ($1, $2) in order. Template variables: {{DOC.field}}, {{INPUT.field}}, {{SECRET.name}}. Example: {'sku': '{{DOC.metadata.sku}}'}")
    output_field: Optional[StrictStr] = Field(default='sql_result', description="OPTIONAL. Dot-path where SQL results should be stored. Creates nested structure if needed. For FIRST mode: single object. For ALL mode: array of objects. Default: 'sql_result'. Note: Avoid using 'metadata.*' paths as the metadata field is excluded from API responses.")
    result_handling: Optional[ResultHandling] = Field(default=None, description="OPTIONAL. How to handle multiple result rows. 'first': Return only first row (default). 'all': Return all rows as array. 'error_if_empty': Error if no results. 'error_if_multiple': Error if more than one result. ")
    on_no_results: Optional[OnNoResults] = Field(default=None, description="OPTIONAL. Behavior when query returns no rows. 'skip': Keep document unchanged. 'null': Set output_field to null (default). 'error': Raise error.")
    timeout: Optional[Annotated[int, Field(le=300, strict=True, ge=1)]] = Field(default=30, description="OPTIONAL. Query timeout in seconds. Range: 1-300. Default: 30. Increase for complex queries.")
    when: Optional[LogicalOperator] = Field(default=None, description="OPTIONAL. Conditional filter for selective enrichment. Only documents matching condition will execute SQL lookup. RECOMMENDED for performance optimization.")
    on_error: Optional[ErrorHandling] = Field(default=None, description="OPTIONAL. Error handling strategy. 'skip': Pass document through unchanged (default). 'remove': Remove failed documents. 'raise': Halt pipeline on error.")
    __properties: ClassVar[List[str]] = ["connection_id", "query", "parameters", "output_field", "result_handling", "on_no_results", "timeout", "when", "on_error"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of StageParamsSqlLookup from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of when
        if self.when:
            _dict['when'] = self.when.to_dict()
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of StageParamsSqlLookup from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "connection_id": obj.get("connection_id"),
            "query": obj.get("query"),
            "parameters": obj.get("parameters"),
            "output_field": obj.get("output_field") if obj.get("output_field") is not None else 'sql_result',
            "result_handling": obj.get("result_handling"),
            "on_no_results": obj.get("on_no_results"),
            "timeout": obj.get("timeout") if obj.get("timeout") is not None else 30,
            "when": LogicalOperator.from_dict(obj["when"]) if obj.get("when") is not None else None,
            "on_error": obj.get("on_error")
        })
        return _obj


