from collections import OrderedDict
from typing import Any, Dict, List, Optional, Tuple, Union

from django.db.backends.base.base import BaseDatabaseWrapper
from django.db.models.expressions import Expression
from django.db.models.sql.compiler import SQLCompiler
from django.db.models.sql.query import Query
from django.utils import tree

AND: str
OR: str

class WhereNode(tree.Node):
    connector: str
    contains_aggregate: bool
    contains_over_clause: bool
    negated: bool
    default: Any = ...
    resolved: bool = ...
    conditional: bool = ...
    def split_having(self, negated: bool = ...) -> Tuple[Optional[WhereNode], Optional[WhereNode]]: ...
    def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> Any: ...
    def get_group_by_cols(self) -> List[Expression]: ...
    def relabel_aliases(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> None: ...
    def clone(self) -> WhereNode: ...
    def relabeled_clone(self, change_map: Union[Dict[Optional[str], str], OrderedDict]) -> WhereNode: ...
    def resolve_expression(self, *args: Any, **kwargs: Any) -> WhereNode: ...

class NothingNode:
    contains_aggregate: bool = ...
    def as_sql(self, compiler: Optional[SQLCompiler] = ..., connection: Optional[BaseDatabaseWrapper] = ...) -> Any: ...

class ExtraWhere:
    contains_aggregate: bool = ...
    sqls: List[str] = ...
    params: Optional[Union[List[int], List[str]]] = ...
    def __init__(self, sqls: List[str], params: Optional[Union[List[int], List[str]]]) -> None: ...
    def as_sql(
        self, compiler: Optional[SQLCompiler] = ..., connection: Optional[BaseDatabaseWrapper] = ...
    ) -> Tuple[str, Union[List[int], List[str]]]: ...

class SubqueryConstraint:
    contains_aggregate: bool = ...
    alias: str = ...
    columns: List[str] = ...
    targets: List[str] = ...
    query_object: Query = ...
    def __init__(self, alias: str, columns: List[str], targets: List[str], query_object: Query) -> None: ...
    def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> Tuple[str, Tuple]: ...
