diff --git a/src/prisma/__init__.py b/src/prisma/__init__.py index 16ce2af28..be99f10f3 100644 --- a/src/prisma/__init__.py +++ b/src/prisma/__init__.py @@ -12,7 +12,11 @@ from .utils import setup_logging from . import errors as errors from .validator import * -from ._types import PrismaMethod as PrismaMethod +from ._types import ( + PrismaMethod as PrismaMethod, + NotGiven as NotGiven, + NOT_GIVEN as NOT_GIVEN, +) from ._metrics import ( Metric as Metric, Metrics as Metrics, diff --git a/src/prisma/_helpers.py b/src/prisma/_helpers.py new file mode 100644 index 000000000..1af6303f5 --- /dev/null +++ b/src/prisma/_helpers.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from typing import Mapping +from typing_extensions import TypeGuard + + +def is_list(value: object) -> TypeGuard[list[object]]: + return isinstance(value, list) + + +def is_mapping(value: object) -> TypeGuard[Mapping[str, object]]: + return isinstance(value, Mapping) diff --git a/src/prisma/_parsers.py b/src/prisma/_parsers.py new file mode 100644 index 000000000..120e9fd2d --- /dev/null +++ b/src/prisma/_parsers.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +from typing import Any, Callable, TypeVar + +from ._helpers import is_list + + +_T = TypeVar('_T') + + +def allow_none(parser: Callable[[Any], _T]) -> Callable[[Any], _T | None]: + """Wrap the given parser function to allow passing in None values.""" + + def wrapped(value: Any) -> _T | None: + if value is None: + return None + + return parser(value) + + return wrapped + + +def as_list(parser: Callable[[Any], _T]) -> Callable[[Any], list[_T]]: + """Wrap the given parser function to accept a list and invoke it for each entry""" + + def wrapped(value: Any) -> list[_T]: + if not is_list(value): + raise TypeError( + f'Expected value to be a list but got {type(value)}' + ) + + return [parser(entry) for entry in value] + + return wrapped diff --git a/src/prisma/_types.py b/src/prisma/_types.py index d7b197202..7c341d20b 100644 --- a/src/prisma/_types.py +++ b/src/prisma/_types.py @@ -1,4 +1,4 @@ -from typing import Callable, Coroutine, TypeVar, Type, Tuple, Any +from typing import Callable, Coroutine, TypeVar, Type, Tuple, Any, Union from pydantic import BaseModel from typing_extensions import ( TypeGuard as TypeGuard, @@ -11,6 +11,8 @@ Method = Literal['GET', 'POST'] +_T = TypeVar('_T') + CallableT = TypeVar('CallableT', bound='FuncType') BaseModelT = TypeVar('BaseModelT', bound=BaseModel) @@ -28,6 +30,23 @@ class _GenericAlias(Protocol): __origin__: Type[object] +class NotGiven: + """Represents cases where a value has not been explicitly given. + + + Useful when `None` is not a possible default value. + """ + + def __bool__(self) -> bool: + return False + + def __repr__(self) -> str: + return 'NOT_GIVEN' + + +NOT_GIVEN = NotGiven() +NotGivenOr = Union[_T, NotGiven] + PrismaMethod = Literal[ # raw queries 'query_raw', diff --git a/src/prisma/engine/json/__init__.py b/src/prisma/engine/json/__init__.py new file mode 100644 index 000000000..4d6326bb7 --- /dev/null +++ b/src/prisma/engine/json/__init__.py @@ -0,0 +1,7 @@ +from .serializer import ( + QueryInput as QueryInput, + build_single_query as build_single_query, + serialize_single_query as serialize_single_query, + serialize_batched_query as serialize_batched_query, +) +from .deserializer import deserialize as deserialize diff --git a/src/prisma/engine/json/deserializer.py b/src/prisma/engine/json/deserializer.py new file mode 100644 index 000000000..635d22d31 --- /dev/null +++ b/src/prisma/engine/json/deserializer.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +from typing import Mapping +from typing_extensions import TypeGuard + +from .types import OutputTaggedValue +from ..._helpers import is_list, is_mapping + + +def deserialize(value: object) -> object: + if not value: + return value + + if is_list(value): + return [deserialize(entry) for entry in value] + + if is_mapping(value): + if is_tagged_value(value): + return deserialize_tagged_value(value) + + return {key: deserialize(item) for key, item in value.items()} + + return value + + +def is_tagged_value( + value: Mapping[str, object] +) -> TypeGuard[OutputTaggedValue]: + return isinstance(value.get('$type'), str) + + +def deserialize_tagged_value(tagged: OutputTaggedValue) -> object: + if tagged['$type'] == 'FieldRef': + raise RuntimeError('Cannot deserialize FieldRef values yet') + + return tagged['value'] diff --git a/src/prisma/engine/json/serializer.py b/src/prisma/engine/json/serializer.py new file mode 100644 index 000000000..c6148b72a --- /dev/null +++ b/src/prisma/engine/json/serializer.py @@ -0,0 +1,271 @@ +from __future__ import annotations + +import json +import inspect +import logging +import decimal +import warnings +from datetime import datetime, timezone +from functools import singledispatch +from typing import Any, Dict, Mapping +from typing_extensions import TypedDict, Required + +from ...utils import DEBUG +from ..._constants import QUERY_BUILDER_ALIASES +from ..._helpers import is_mapping +from ..._types import PrismaMethod, NotGiven + +# Note: this is a codegen'd module +from ... import fields +from ...types import Serializable +from ...bases import _PrismaModel + + +log: logging.Logger = logging.getLogger(__name__) + + +class SingleQuery(TypedDict, total=False): + action: Required[str] + query: Required[FieldQuery] + modelName: str + + +class FieldQuery(TypedDict, total=False): + arguments: dict[str, ArgumentValue] + selection: SelectionSet + + +# TODO: more detailed types +SelectionSet = Dict[str, Any] +ArgumentValue = object + + +class QueryInput(TypedDict, total=False): + method: Required[PrismaMethod] + arguments: Required[dict[str, object]] + model: type[_PrismaModel] | None + + +METHOD_TO_ACTION: dict[PrismaMethod, str] = { + 'create': 'createOne', + 'delete': 'deleteOne', + 'update': 'updateOne', + 'upsert': 'upsertOne', + 'query_raw': 'queryRaw', + 'create_many': 'createMany', + 'execute_raw': 'executeRaw', + 'delete_many': 'deleteMany', + 'update_many': 'updateMany', + 'count': 'aggregate', + 'group_by': 'groupBy', + 'find_many': 'findMany', + 'find_first': 'findFirst', + 'find_first_or_raise': 'findFirstOrThrow', + 'find_unique': 'findUnique', + 'find_unique_or_raise': 'findUniqueOrThrow', +} + + +def _method_to_action(method: PrismaMethod) -> str: + action = METHOD_TO_ACTION.get(method) + if action is None: + raise RuntimeError('TODO') + return action + + +def serialize_single_query( + *, + method: PrismaMethod, + arguments: dict[str, object], + model: type['_PrismaModel'] | None = None, +) -> str: + query = build_single_query( + method=method, + arguments=arguments, + model=model, + ) + return dumps(query, indent=2 if DEBUG else None) + + +def serialize_batched_query(*, queries: list[QueryInput]) -> str: + batched = [build_single_query(**query) for query in queries] + return dumps( + { + 'batch': batched, + 'transaction': {}, + }, + indent=2 if DEBUG else None, + ) + + +def build_single_query( + *, + method: PrismaMethod, + arguments: dict[str, object], + model: type['_PrismaModel'] | None = None, +) -> SingleQuery: + request: SingleQuery = { + 'action': _method_to_action(method), + 'query': _build_query(_transform_aliases(arguments)), + } + + if model is not None: + # TODO: better error message if unset + request['modelName'] = model.__prisma_model__ + + return request + + +def _build_query(args: Mapping[str, object]) -> FieldQuery: + data = _strip_not_given_args(args) + include = data.pop('include', None) + select = data.pop('select', None) + + return { + 'arguments': data, + 'selection': _build_selection(include=include, select=select), + } + + +def _build_selection( + *, + include: object | None, + select: object | None, +) -> SelectionSet: + if select and include: + # TODO: special error + raise RuntimeError('select & include not supported') + + if is_mapping(select): + return _build_explicit_selection(select=select) + + return _build_implicit_selection(include=include) + + +def _build_explicit_selection(*, select: Mapping[str, object]) -> SelectionSet: + selection: SelectionSet = {} + + for key, value in select.items(): + if value is True: + selection[key] = True + elif is_mapping(value): + selection[key] = _build_query(value) + + return selection + + +def _build_implicit_selection(*, include: object | None) -> SelectionSet: + selection: SelectionSet = { + # TODO: don't include these for raw queries + '$scalars': True, + '$composites': True, + } + + if is_mapping(include): + for key, value in include.items(): + if value is True: + selection[key] = True + elif is_mapping(value): + selection[key] = _build_query(value) + + return selection + + +ITERABLES: tuple[type[Any], ...] = (list, tuple, set) + + +def _transform_aliases(arguments: dict[str, Any]) -> dict[str, Any]: + """Transform dict keys to match global aliases + + e.g. order_by -> orderBy + """ + # TODO: this should use type information to transform instead of just naively matching keys + transformed = dict() + for key, value in arguments.items(): + alias = QUERY_BUILDER_ALIASES.get(key, key) + if isinstance(value, dict): + transformed[alias] = _transform_aliases(arguments=value) + elif isinstance(value, ITERABLES): + # it is safe to map any iterable type to a list here as it is only being used + # to serialise the query and we only officially support lists anyway + transformed[alias] = [ + _transform_aliases(data) if isinstance(data, dict) else data # type: ignore + for data in value + ] + else: + transformed[alias] = value + return transformed + + +def _strip_not_given_args(args: Mapping[str, object]) -> dict[str, object]: + result = {} + for key, value in args.items(): + if value is None: + warnings.warn( + f'Encountered `None` value for `{key}`. Please use `prisma.NOT_GIVEN` instead.', + DeprecationWarning, + stacklevel=3, + ) + elif isinstance(value, NotGiven): + continue + else: + result[key] = value + + return result + + +@singledispatch +def serializer(obj: object) -> Serializable: + """Single dispatch generic function for serializing objects to JSON""" + if inspect.isclass(obj): + typ = obj + else: + typ = type(obj) + + raise TypeError(f'Type {typ} not serializable') + + +@serializer.register(datetime) +def serialize_datetime(dt: datetime) -> str: + """Format a datetime object to an ISO8601 string with a timezone. + + This assumes naive datetime objects are in UTC. + """ + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + elif dt.tzinfo != timezone.utc: + dt = dt.astimezone(timezone.utc) + + # truncate microseconds to 3 decimal places + # https://github.com/RobertCraigie/prisma-client-py/issues/129 + dt = dt.replace(microsecond=int(dt.microsecond / 1000) * 1000) + return dt.isoformat() + + +@serializer.register(fields.Json) +def serialize_json(obj: fields.Json) -> Serializable: + """Serialize a Json wrapper to JSON. + + We must tag the data as `Json` so that the query engine knows + which section of the query is just raw JSON, otherwise it may + mis-interpret it. + """ + return {'$type': 'Json', 'value': dumps(obj.data)} + + +@serializer.register(fields.Base64) +def serialize_base64(obj: fields.Base64) -> str: + """Serialize a Base64 wrapper object to raw binary data""" + return str(obj) + + +@serializer.register(decimal.Decimal) +def serialize_decimal(obj: decimal.Decimal) -> str: + """Serialize a Decimal object to a string""" + return str(obj) + + +def dumps(obj: object, **kwargs: Any) -> str: + kwargs.setdefault('default', serializer) + kwargs.setdefault('ensure_ascii', False) + return json.dumps(obj, **kwargs) diff --git a/src/prisma/engine/json/types.py b/src/prisma/engine/json/types.py new file mode 100644 index 000000000..8fbd45353 --- /dev/null +++ b/src/prisma/engine/json/types.py @@ -0,0 +1,76 @@ +# taken from https://github.com/prisma/prisma/blob/main/packages/engine-core/src/common/types/JsonProtocol.ts +from typing import Union +from typing_extensions import Literal, TypedDict + + +DateTaggedValue = TypedDict( + 'DateTaggedValue', + { + '$type': Literal['DateTime'], + 'value': str, + }, +) + +DecimalTaggedValue = TypedDict( + 'DecimalTaggedValue', + { + '$type': Literal['Decimal'], + 'value': str, + }, +) + +BytesTaggedValue = TypedDict( + 'BytesTaggedValue', + { + '$type': Literal['Bytes'], + 'value': str, + }, +) + +BigIntTaggedValue = TypedDict( + 'BigIntTaggedValue', + { + '$type': Literal['BigInt'], + 'value': str, + }, +) + + +class FieldRefValue(TypedDict): + _ref: str + + +FieldRefTaggedValue = TypedDict( + 'FieldRefTaggedValue', + { + '$type': Literal['FieldRef'], + 'value': FieldRefValue, + }, +) + +EnumTaggedValue = TypedDict( + 'EnumTaggedValue', + { + '$type': Literal['Enum'], + 'value': str, + }, +) + +JsonTaggedValue = TypedDict( + 'JsonTaggedValue', + { + '$type': Literal['Json'], + 'value': str, + }, +) + + +OutputTaggedValue = Union[ + DateTaggedValue, + EnumTaggedValue, + JsonTaggedValue, + BytesTaggedValue, + BigIntTaggedValue, + DecimalTaggedValue, + FieldRefTaggedValue, +] diff --git a/src/prisma/generator/templates/actions.py.jinja b/src/prisma/generator/templates/actions.py.jinja index 65a2132d1..941b0356b 100644 --- a/src/prisma/generator/templates/actions.py.jinja +++ b/src/prisma/generator/templates/actions.py.jinja @@ -4,13 +4,17 @@ # -- template actions.py.jinja -- from typing import TypeVar import warnings +import functools as _functools -from . import types, errors, bases +from . import types, errors, bases, _parsers +from ._types import NotGiven, NotGivenOr, NOT_GIVEN +from ._helpers import is_mapping from ._compat import model_parse if TYPE_CHECKING: from .client import Client from .bases import _PrismaModel + from .engine.json.serializer import SelectionSet _PrismaModelT = TypeVar('_PrismaModelT', bound='_PrismaModel') @@ -45,11 +49,13 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[{{ ModelType }}]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) {% if active_provider != 'mongodb' %} {{ maybe_async_def }}query_raw( @@ -134,7 +140,7 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): {{ maybe_async_def }}create( self, data: types.{{ model.name }}CreateInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> {{ ModelType }}: """Create a new {{ model.name }} record. @@ -171,21 +177,22 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) {{ maybe_async_def }}create_many( self, data: List[types.{{ model.name }}CreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple {{ model.name }} records at once. @@ -235,21 +242,21 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) {{ maybe_async_def }}delete( self, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> Optional[{{ ModelType }}]: """Delete a single {{ model.name }} record. @@ -282,24 +289,22 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - try: - resp = {{ maybe_await }}self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return {{ maybe_await }}self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) {{ maybe_async_def }}find_unique( self, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN ) -> Optional[{{ ModelType }}]: """Find a unique {{ model.name }} record. @@ -332,23 +337,21 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) {{ maybe_async_def }}find_unique_or_raise( self, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[Optional[types.{{ model.name}}Include]] = NOT_GIVEN ) -> {{ ModelType }}: """Find a unique {{ model.name }} record. Raises `RecordNotFoundError` if no record is found. @@ -381,25 +384,26 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) {{ maybe_async_def }}find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, - include: Optional[types.{{ model.name }}Include] = None, - order: Optional[Union[types.{{ model.name }}OrderByInput, List[types.{{ model.name }}OrderByInput]]] = None, - distinct: Optional[List[types.{{ model.name }}ScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.{{ model.name }}Include | None] = NOT_GIVEN, + order: NotGivenOr[types.{{ model.name }}OrderByInput | List[types.{{ model.name }}OrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.{{ model.name }}ScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[{{ ModelType }}]: """Find multiple {{ model.name }} records. @@ -447,9 +451,8 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -459,17 +462,19 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] {{ maybe_async_def }}find_first( self, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, - include: Optional[types.{{ model.name }}Include] = None, - order: Optional[Union[types.{{ model.name }}OrderByInput, List[types.{{ model.name }}OrderByInput]]] = None, - distinct: Optional[List[types.{{ model.name }}ScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.{{ model.name }}Include | None] = NOT_GIVEN, + order: NotGivenOr[types.{{ model.name }}OrderByInput | List[types.{{ model.name }}OrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.{{ model.name }}ScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[{{ ModelType }}]: """Find a single {{ model.name }} record. @@ -512,9 +517,8 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -523,21 +527,19 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) {{ maybe_async_def }}find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, - include: Optional[types.{{ model.name }}Include] = None, - order: Optional[Union[types.{{ model.name }}OrderByInput, List[types.{{ model.name }}OrderByInput]]] = None, - distinct: Optional[List[types.{{ model.name }}ScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.{{ model.name }}Include | None] = NOT_GIVEN, + order: NotGivenOr[types.{{ model.name }}OrderByInput | list[types.{{ model.name }}OrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.{{ model.name }}ScalarFieldKeys] | None] = NOT_GIVEN, ) -> {{ ModelType }}: """Find a single {{ model.name }} record. Raises `RecordNotFoundError` if no record was found. @@ -580,9 +582,8 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -591,14 +592,16 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) {{ maybe_async_def }}update( self, data: types.{{ model.name }}UpdateInput, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN ) -> Optional[{{ ModelType }}]: """Update a single {{ model.name }} record. @@ -635,26 +638,24 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - try: - resp = {{ maybe_await }}self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return {{ maybe_await }}self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) {{ maybe_async_def }}upsert( self, where: types.{{ model.name }}WhereUniqueInput, data: types.{{ model.name }}UpsertInput, - include: Optional[types.{{ model.name}}Include] = None, + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> {{ ModelType }}: """Updates an existing record or create a new one @@ -721,17 +722,18 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): {% endif %} ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) {{ maybe_async_def }}update_many( self, @@ -769,22 +771,25 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload {{ maybe_async_def }}count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, ) -> int: {# We add the docstring here as Pylance / VSCode picks up docstrings from the overloads of a function. @@ -845,56 +850,50 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): {{ maybe_async_def }}count( self, select: types.{{ model.name }}CountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, ) -> types.{{ model.name }}CountAggregateOutput: ... {{ maybe_async_def }}count( self, - select: Optional[types.{{ model.name }}CountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.{{ model.name }}WhereInput] = None, - cursor: Optional[types.{{ model.name }}WhereUniqueInput] = None, + select: NotGivenOr[types.{{ model.name }}CountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.{{ model.name }}WhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.{{ model.name }}CountAggregateOutput]: {{ count_doc() }} - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: - {% raw %} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] - {% endraw %} - - resp = {{ maybe_await }}self._client._execute( + selection = select or {'_all': True} + + def parser(value: Any) -> int | types.{{ model.name }}CountAggregateOutput: + if is_mapping(select): + return cast(types.{{ model.name }}CountAggregateOutput, value['_count']) + return int(value['_count']['_all']) + + return {{ maybe_await }}self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.{{ model.name }}CountAggregateOutput, resp['data']['result']['_count']) - {{ maybe_async_def }}delete_many( self, - where: Optional[types.{{ model.name }}WhereInput] = None + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple {{ model.name }} records. @@ -919,13 +918,15 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): total = {{ maybe_await }}{{ model.name }}.prisma().delete_many() ``` """ - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -934,26 +935,26 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): {{ maybe_async_def }}group_by( self, {% if recursive_types %} - by: List['types.{{ model.name }}ScalarFieldKeysT'], + by: list['types.{{ model.name }}ScalarFieldKeysT'], {% else %} - by: List['types.{{ model.name }}ScalarFieldKeys'], + by: list['types.{{ model.name }}ScalarFieldKeys'], {% endif %} *, - where: Optional['types.{{ model.name }}WhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.{{ model.name }}AvgAggregateInput'] = None, - sum: Optional['types.{{ model.name }}SumAggregateInput'] = None, - min: Optional['types.{{ model.name }}MinAggregateInput'] = None, - max: Optional['types.{{ model.name }}MaxAggregateInput'] = None, - having: Optional['types.{{ model.name }}ScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.{{ model.name }}CountAggregateInput']] = None, + where: NotGivenOr['types.{{ model.name }}WhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.{{ model.name }}AvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.{{ model.name }}SumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.{{ model.name }}MinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.{{ model.name }}MaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.{{ model.name }}ScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.{{ model.name }}CountAggregateInput | None'] = NOT_GIVEN, {% if recursive_types %} - order: Optional[Union[Mapping['types.{{ model.name }}ScalarFieldKeysT', 'types.SortOrder'], List[Mapping['types.{{ model.name }}ScalarFieldKeysT', 'types.SortOrder']]]] = None, + order: NotGivenOr[Mapping['types.{{ model.name }}ScalarFieldKeysT', 'types.SortOrder'] | list[Mapping['types.{{ model.name }}ScalarFieldKeysT', 'types.SortOrder']] | None] = NOT_GIVEN, {% else %} - order: Optional[Union[Mapping['types.{{ model.name }}ScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.{{ model.name }}ScalarFieldKeys', 'types.SortOrder']]]] = None, + order: NotGivenOr[Mapping['types.{{ model.name }}ScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.{{ model.name }}ScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, {% endif %} - ) -> List['types.{{ model.name }}GroupByOutput']: + ) -> list['types.{{ model.name }}GroupByOutput']: """Group {{ model.name }} records by one or more field values and perform aggregations each group such as finding the average. @@ -1011,35 +1012,34 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = {{ maybe_await }}self._client._execute( + return {{ maybe_await }}self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -1047,22 +1047,14 @@ class {{ model.name }}Actions(Generic[{{ ModelType }}]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] {% endfor %} -def _select_fields(root: str, select: Mapping[str, Any]) -> str: - """Helper to build a GraphQL selection string - - This is a work around until field selection is added to the query builder. - """ - {% raw %} - return root + ' {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - {% endraw %} - - from . import models diff --git a/src/prisma/generator/templates/client.py.jinja b/src/prisma/generator/templates/client.py.jinja index edca0c132..ad5d7b679 100644 --- a/src/prisma/generator/templates/client.py.jinja +++ b/src/prisma/generator/templates/client.py.jinja @@ -7,14 +7,16 @@ import logging from datetime import timedelta from pathlib import Path from types import TracebackType +from typing import Iterable +from typing_extensions import Unpack from pydantic import BaseModel from . import types, models, errors, actions from .types import DatasourceOverride, HttpConfig, MetricsFormat -from ._types import BaseModelT, PrismaMethod +from ._types import BaseModelT, PrismaMethod, NotGivenOr, NOT_GIVEN from .bases import _PrismaModel -from .engine import AbstractEngine, QueryEngine, TransactionId +from .engine import AbstractEngine, QueryEngine, TransactionId, json as json_proto from .builder import QueryBuilder, dumps from .generator.models import EngineType, OptionalValueFromEnvVar, BinaryPaths from ._compat import removeprefix, model_parse @@ -44,6 +46,8 @@ BINARY_PATHS = model_parse(BinaryPaths, {{ binary_paths.dict(by_alias=True) }}) RegisteredClient = Union['Prisma', Callable[[], 'Prisma']] _registered_client: Optional[RegisteredClient] = None +_T = TypeVar('_T') + class UseClientDefault: """For certain parameters such as `timeout=...` we can make our intent more clear @@ -187,7 +191,7 @@ class Prisma: # client as well as the transaction client the original client cannot # be `free`d before the transaction is finished. So stopping the engine # here should be safe. - if self.__engine is not None and not self.__copied: + if hasattr(self, '__engine') and self.__engine is not None and not self.__copied: log.debug('unclosed client - stopping engine') engine = self.__engine self.__engine = None @@ -294,15 +298,16 @@ class Prisma: {% if active_provider != 'mongodb' %} {{ maybe_async_def }}execute_raw(self, query: LiteralString, *args: Any) -> int: - resp = {{ maybe_await }}self._execute( + return {{ maybe_await }}self._execute_json_proto( method='execute_raw', arguments={ 'query': query, 'parameters': args, }, + data_path=[], model=None, + parser=int, ) - return int(resp['data']['result']) @overload {{ maybe_async_def }}query_first( @@ -365,25 +370,27 @@ class Prisma: query: LiteralString, *args: Any, model: Optional[Type[BaseModelT]] = None, - ) -> Union[List[BaseModelT], List[dict[str, Any]]]: + ) -> list[BaseModelT] | list[dict[str, Any]]: """Execute a raw SQL query against the database. If model is given, each returned record is converted to the pydantic model first, otherwise results will be raw dictionaries. """ - resp = {{ maybe_await }}self._execute( + def parser(value: Any) -> list[BaseModelT] | list[dict[str, Any]]: + if model is not None: + return deserialize_raw_results(value, model=model) + return deserialize_raw_results(value) + + return {{ maybe_await }}self._execute_json_proto( method='query_raw', arguments={ 'query': query, 'parameters': args, }, - model=model, + data_path=[], + model=None, + parser=parser, ) - result = resp['data']['result'] - if model is not None: - return deserialize_raw_results(result, model=model) - - return deserialize_raw_results(result) {% endif %} def batch_(self) -> 'Batch': @@ -462,6 +469,77 @@ class Prisma: return model_parse(Metrics, response) + @overload + {{ maybe_async_def }}_execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ) -> _T: + ... + + @overload + {{ maybe_async_def }}_execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + ignore_exceptions: tuple[type[Exception]] | None, + model: type[_PrismaModel] | None = None, + ) -> _T | None: + ... + + {{ maybe_async_def }}_execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ignore_exceptions: tuple[type[Exception]] | None = None, + ) -> _T | None: + """Execute a query against the query engine. + + If `ignore_exceptions` is given then `None` will be returned if any of the given exceptions + are caught while executing the query. + """ + query = json_proto.serialize_single_query( + method=method, + model=model, + arguments=arguments, + ) + + if ignore_exceptions is not None: + try: + response = {{ maybe_await }}self._engine.query(query, tx_id=self._tx_id) + except ignore_exceptions: + return None + else: + response = {{ maybe_await }}self._engine.query(query, tx_id=self._tx_id) + + + # response is in the structure `{'data': {'findUniqueUser': { ... }}}` + data = next(iter(response['data'].values())) + + for key in data_path: + data = data[key] + + return parser(json_proto.deserialize(data)) + + {{ maybe_async_def }}_execute_json_proto_batched( + self, + *, + queries: list[json_proto.QueryInput], + ) -> object: + query = json_proto.serialize_batched_query(queries=queries) + return {{ maybe_await }}self._engine.query(query, tx_id=self._tx_id) + # TODO: don't return Any {{ maybe_async_def }}_execute( self, @@ -677,36 +755,20 @@ class Batch: def __init__(self, client: Prisma) -> None: self.__client = client - self.__queries: List[str] = [] + self.__queries: list[json_proto.QueryInput] = [] self._active_provider = client._active_provider {% for model in dmmf.datamodel.models %} self.{{ model.name.lower() }} = {{ model.name }}BatchActions(self) {% endfor %} - def _add(self, **kwargs: Any) -> None: - builder = QueryBuilder(**kwargs) - self.__queries.append(builder.build_query()) + def _add(self, **query: Unpack[json_proto.QueryInput]) -> None: + self.__queries.append(query) {{ maybe_async_def }}commit(self) -> None: """Execute the queries""" - # TODO: normalise this, we should still call client._execute queries = self.__queries self.__queries = [] - - payload = { - 'batch': [ - { - 'query': query, - 'variables': {}, - } - for query in queries - ], - 'transaction': True, - } - {{ maybe_await }}self.__client._engine.query( - dumps(payload), - tx_id=self.__client._tx_id, - ) + {{ maybe_await }}self.__client._execute_json_proto_batched(queries=queries) {% if active_provider != 'mongodb' %} def execute_raw(self, query: LiteralString, *args: Any) -> None: @@ -756,7 +818,7 @@ class {{ model.name }}BatchActions: def create( self, data: types.{{ model.name }}CreateInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -771,7 +833,7 @@ class {{ model.name }}BatchActions: self, data: List[types.{{ model.name }}CreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -783,13 +845,12 @@ class {{ model.name }}BatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None, + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -804,7 +865,7 @@ class {{ model.name }}BatchActions: self, data: types.{{ model.name }}UpdateInput, where: types.{{ model.name }}WhereUniqueInput, - include: Optional[types.{{ model.name}}Include] = None + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -820,7 +881,7 @@ class {{ model.name }}BatchActions: self, where: types.{{ model.name }}WhereUniqueInput, data: types.{{ model.name }}UpsertInput, - include: Optional[types.{{ model.name}}Include] = None, + include: NotGivenOr[types.{{ model.name}}Include | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -842,18 +903,16 @@ class {{ model.name }}BatchActions: method='update_many', model=models.{{ model.name }}, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.{{ model.name }}WhereInput] = None, + where: NotGivenOr[types.{{ model.name }}WhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.{{ model.name }}, arguments={'where': where}, - root_selection=['count'], ) diff --git a/src/prisma/generator/templates/engine/query.py.jinja b/src/prisma/generator/templates/engine/query.py.jinja index 700086b09..c17bd4a56 100644 --- a/src/prisma/generator/templates/engine/query.py.jinja +++ b/src/prisma/generator/templates/engine/query.py.jinja @@ -124,7 +124,7 @@ class QueryEngine(HTTPEngine): RUST_LOG='error', RUST_LOG_FORMAT='json', PRISMA_CLIENT_ENGINE_TYPE='binary', - PRISMA_ENGINE_PROTOCOL='graphql', + PRISMA_ENGINE_PROTOCOL='json', ) if DEBUG: diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[actions.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[actions.py].raw index 1670cd45d..2d73427db 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[actions.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[actions.py].raw @@ -42,13 +42,17 @@ LiteralString = str # -- template actions.py.jinja -- from typing import TypeVar import warnings +import functools as _functools -from . import types, errors, bases +from . import types, errors, bases, _parsers +from ._types import NotGiven, NotGivenOr, NOT_GIVEN +from ._helpers import is_mapping from ._compat import model_parse if TYPE_CHECKING: from .client import Client from .bases import _PrismaModel + from .engine.json.serializer import SelectionSet _PrismaModelT = TypeVar('_PrismaModelT', bound='_PrismaModel') @@ -58,11 +62,13 @@ class PostActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -145,7 +151,7 @@ class PostActions(Generic[_PrismaModelT]): async def create( self, data: types.PostCreateInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new Post record. @@ -181,21 +187,22 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.PostCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple Post records at once. @@ -247,21 +254,21 @@ class PostActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single Post record. @@ -296,24 +303,22 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique Post record. @@ -348,23 +353,21 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[Optional[types.PostInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique Post record. Raises `RecordNotFoundError` if no record is found. @@ -399,25 +402,26 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | List[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple Post records. @@ -465,9 +469,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -477,17 +480,19 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | List[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single Post record. @@ -530,9 +535,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -541,21 +545,19 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | list[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single Post record. Raises `RecordNotFoundError` if no record was found. @@ -598,9 +600,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -609,14 +610,16 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.PostUpdateInput, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single Post record. @@ -654,26 +657,24 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.PostWhereUniqueInput, data: types.PostUpsertInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -719,17 +720,18 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -767,22 +769,25 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of Post records present in the database @@ -836,20 +841,20 @@ class PostActions(Generic[_PrismaModelT]): async def count( self, select: types.PostCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> types.PostCountAggregateOutput: ... async def count( self, - select: Optional[types.PostCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + select: NotGivenOr[types.PostCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.PostCountAggregateOutput]: """Count the number of Post records present in the database @@ -898,39 +903,34 @@ class PostActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.PostCountAggregateOutput: + if is_mapping(select): + return cast(types.PostCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.PostCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.PostWhereInput] = None + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple Post records. @@ -956,13 +956,15 @@ class PostActions(Generic[_PrismaModelT]): total = await Post.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -970,19 +972,19 @@ class PostActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.PostScalarFieldKeys'], + by: list['types.PostScalarFieldKeys'], *, - where: Optional['types.PostWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.PostAvgAggregateInput'] = None, - sum: Optional['types.PostSumAggregateInput'] = None, - min: Optional['types.PostMinAggregateInput'] = None, - max: Optional['types.PostMaxAggregateInput'] = None, - having: Optional['types.PostScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.PostCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.PostScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.PostScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.PostGroupByOutput']: + where: NotGivenOr['types.PostWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.PostAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.PostSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.PostMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.PostMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.PostScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.PostCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.PostScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.PostScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.PostGroupByOutput']: """Group Post records by one or more field values and perform aggregations each group such as finding the average. @@ -1040,35 +1042,34 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -1076,21 +1077,25 @@ class PostActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class UserActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -1173,7 +1178,7 @@ class UserActions(Generic[_PrismaModelT]): async def create( self, data: types.UserCreateInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new User record. @@ -1213,21 +1218,22 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.UserCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple User records at once. @@ -1287,21 +1293,21 @@ class UserActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single User record. @@ -1336,24 +1342,22 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique User record. @@ -1388,23 +1392,21 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[Optional[types.UserInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique User record. Raises `RecordNotFoundError` if no record is found. @@ -1439,25 +1441,26 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | List[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple User records. @@ -1505,9 +1508,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -1517,17 +1519,19 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | List[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single User record. @@ -1570,9 +1574,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -1581,21 +1584,19 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | list[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single User record. Raises `RecordNotFoundError` if no record was found. @@ -1638,9 +1639,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -1649,14 +1649,16 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.UserUpdateInput, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single User record. @@ -1694,26 +1696,24 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.UserWhereUniqueInput, data: types.UserUpsertInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -1767,17 +1767,18 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -1815,22 +1816,25 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of User records present in the database @@ -1884,20 +1888,20 @@ class UserActions(Generic[_PrismaModelT]): async def count( self, select: types.UserCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> types.UserCountAggregateOutput: ... async def count( self, - select: Optional[types.UserCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + select: NotGivenOr[types.UserCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.UserCountAggregateOutput]: """Count the number of User records present in the database @@ -1946,39 +1950,34 @@ class UserActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.UserCountAggregateOutput: + if is_mapping(select): + return cast(types.UserCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.UserCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.UserWhereInput] = None + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple User records. @@ -2004,13 +2003,15 @@ class UserActions(Generic[_PrismaModelT]): total = await User.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -2018,19 +2019,19 @@ class UserActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.UserScalarFieldKeys'], + by: list['types.UserScalarFieldKeys'], *, - where: Optional['types.UserWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.UserAvgAggregateInput'] = None, - sum: Optional['types.UserSumAggregateInput'] = None, - min: Optional['types.UserMinAggregateInput'] = None, - max: Optional['types.UserMaxAggregateInput'] = None, - having: Optional['types.UserScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.UserCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.UserScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.UserScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.UserGroupByOutput']: + where: NotGivenOr['types.UserWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.UserAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.UserSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.UserMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.UserMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.UserScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.UserCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.UserScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.UserScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.UserGroupByOutput']: """Group User records by one or more field values and perform aggregations each group such as finding the average. @@ -2088,35 +2089,34 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -2124,21 +2124,25 @@ class UserActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class MActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -2221,7 +2225,7 @@ class MActions(Generic[_PrismaModelT]): async def create( self, data: types.MCreateInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new M record. @@ -2260,21 +2264,22 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.MCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple M records at once. @@ -2332,21 +2337,21 @@ class MActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single M record. @@ -2381,24 +2386,22 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique M record. @@ -2433,23 +2436,21 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[Optional[types.MInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique M record. Raises `RecordNotFoundError` if no record is found. @@ -2484,25 +2485,26 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | List[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple M records. @@ -2550,9 +2552,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -2562,17 +2563,19 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | List[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single M record. @@ -2615,9 +2618,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -2626,21 +2628,19 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | list[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single M record. Raises `RecordNotFoundError` if no record was found. @@ -2683,9 +2683,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -2694,14 +2693,16 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.MUpdateInput, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single M record. @@ -2739,26 +2740,24 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.MWhereUniqueInput, data: types.MUpsertInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -2810,17 +2809,18 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -2858,22 +2858,25 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of M records present in the database @@ -2927,20 +2930,20 @@ class MActions(Generic[_PrismaModelT]): async def count( self, select: types.MCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> types.MCountAggregateOutput: ... async def count( self, - select: Optional[types.MCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + select: NotGivenOr[types.MCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.MCountAggregateOutput]: """Count the number of M records present in the database @@ -2989,39 +2992,34 @@ class MActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.MCountAggregateOutput: + if is_mapping(select): + return cast(types.MCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.MCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.MWhereInput] = None + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple M records. @@ -3047,13 +3045,15 @@ class MActions(Generic[_PrismaModelT]): total = await M.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -3061,19 +3061,19 @@ class MActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.MScalarFieldKeys'], + by: list['types.MScalarFieldKeys'], *, - where: Optional['types.MWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.MAvgAggregateInput'] = None, - sum: Optional['types.MSumAggregateInput'] = None, - min: Optional['types.MMinAggregateInput'] = None, - max: Optional['types.MMaxAggregateInput'] = None, - having: Optional['types.MScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.MCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.MScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.MScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.MGroupByOutput']: + where: NotGivenOr['types.MWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.MAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.MSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.MMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.MMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.MScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.MCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.MScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.MScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.MGroupByOutput']: """Group M records by one or more field values and perform aggregations each group such as finding the average. @@ -3131,35 +3131,34 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -3167,21 +3166,25 @@ class MActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class NActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -3264,7 +3267,7 @@ class NActions(Generic[_PrismaModelT]): async def create( self, data: types.NCreateInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new N record. @@ -3304,21 +3307,22 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.NCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple N records at once. @@ -3378,21 +3382,21 @@ class NActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single N record. @@ -3427,24 +3431,22 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique N record. @@ -3479,23 +3481,21 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[Optional[types.NInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique N record. Raises `RecordNotFoundError` if no record is found. @@ -3530,25 +3530,26 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | List[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple N records. @@ -3596,9 +3597,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -3608,17 +3608,19 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | List[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single N record. @@ -3661,9 +3663,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -3672,21 +3673,19 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | list[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single N record. Raises `RecordNotFoundError` if no record was found. @@ -3729,9 +3728,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -3740,14 +3738,16 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.NUpdateInput, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single N record. @@ -3785,26 +3785,24 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.NWhereUniqueInput, data: types.NUpsertInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -3858,17 +3856,18 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -3906,22 +3905,25 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of N records present in the database @@ -3975,20 +3977,20 @@ class NActions(Generic[_PrismaModelT]): async def count( self, select: types.NCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> types.NCountAggregateOutput: ... async def count( self, - select: Optional[types.NCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + select: NotGivenOr[types.NCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.NCountAggregateOutput]: """Count the number of N records present in the database @@ -4037,39 +4039,34 @@ class NActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.NCountAggregateOutput: + if is_mapping(select): + return cast(types.NCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.NCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.NWhereInput] = None + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple N records. @@ -4095,13 +4092,15 @@ class NActions(Generic[_PrismaModelT]): total = await N.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -4109,19 +4108,19 @@ class NActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.NScalarFieldKeys'], + by: list['types.NScalarFieldKeys'], *, - where: Optional['types.NWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.NAvgAggregateInput'] = None, - sum: Optional['types.NSumAggregateInput'] = None, - min: Optional['types.NMinAggregateInput'] = None, - max: Optional['types.NMaxAggregateInput'] = None, - having: Optional['types.NScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.NCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.NScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.NScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.NGroupByOutput']: + where: NotGivenOr['types.NWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.NAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.NSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.NMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.NMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.NScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.NCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.NScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.NScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.NGroupByOutput']: """Group N records by one or more field values and perform aggregations each group such as finding the average. @@ -4179,35 +4178,34 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -4215,21 +4213,25 @@ class NActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class OneOptionalActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -4312,7 +4314,7 @@ class OneOptionalActions(Generic[_PrismaModelT]): async def create( self, data: types.OneOptionalCreateInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new OneOptional record. @@ -4351,21 +4353,22 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.OneOptionalCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple OneOptional records at once. @@ -4423,21 +4426,21 @@ class OneOptionalActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single OneOptional record. @@ -4472,24 +4475,22 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique OneOptional record. @@ -4524,23 +4525,21 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[Optional[types.OneOptionalInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique OneOptional record. Raises `RecordNotFoundError` if no record is found. @@ -4575,25 +4574,26 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | List[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple OneOptional records. @@ -4641,9 +4641,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -4653,17 +4652,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | List[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single OneOptional record. @@ -4706,9 +4707,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -4717,21 +4717,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | list[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single OneOptional record. Raises `RecordNotFoundError` if no record was found. @@ -4774,9 +4772,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -4785,14 +4782,16 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.OneOptionalUpdateInput, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single OneOptional record. @@ -4830,26 +4829,24 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.OneOptionalWhereUniqueInput, data: types.OneOptionalUpsertInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -4901,17 +4898,18 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -4949,22 +4947,25 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of OneOptional records present in the database @@ -5018,20 +5019,20 @@ class OneOptionalActions(Generic[_PrismaModelT]): async def count( self, select: types.OneOptionalCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> types.OneOptionalCountAggregateOutput: ... async def count( self, - select: Optional[types.OneOptionalCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + select: NotGivenOr[types.OneOptionalCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.OneOptionalCountAggregateOutput]: """Count the number of OneOptional records present in the database @@ -5080,39 +5081,34 @@ class OneOptionalActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.OneOptionalCountAggregateOutput: + if is_mapping(select): + return cast(types.OneOptionalCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.OneOptionalCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.OneOptionalWhereInput] = None + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple OneOptional records. @@ -5138,13 +5134,15 @@ class OneOptionalActions(Generic[_PrismaModelT]): total = await OneOptional.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -5152,19 +5150,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.OneOptionalScalarFieldKeys'], + by: list['types.OneOptionalScalarFieldKeys'], *, - where: Optional['types.OneOptionalWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.OneOptionalAvgAggregateInput'] = None, - sum: Optional['types.OneOptionalSumAggregateInput'] = None, - min: Optional['types.OneOptionalMinAggregateInput'] = None, - max: Optional['types.OneOptionalMaxAggregateInput'] = None, - having: Optional['types.OneOptionalScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.OneOptionalCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.OneOptionalGroupByOutput']: + where: NotGivenOr['types.OneOptionalWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.OneOptionalAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.OneOptionalSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.OneOptionalMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.OneOptionalMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.OneOptionalScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.OneOptionalCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.OneOptionalGroupByOutput']: """Group OneOptional records by one or more field values and perform aggregations each group such as finding the average. @@ -5222,35 +5220,34 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -5258,21 +5255,25 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class ManyRequiredActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -5355,7 +5356,7 @@ class ManyRequiredActions(Generic[_PrismaModelT]): async def create( self, data: types.ManyRequiredCreateInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new ManyRequired record. @@ -5394,21 +5395,22 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.ManyRequiredCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple ManyRequired records at once. @@ -5466,21 +5468,21 @@ class ManyRequiredActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single ManyRequired record. @@ -5515,24 +5517,22 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique ManyRequired record. @@ -5567,23 +5567,21 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[Optional[types.ManyRequiredInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique ManyRequired record. Raises `RecordNotFoundError` if no record is found. @@ -5618,25 +5616,26 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | List[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple ManyRequired records. @@ -5684,9 +5683,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -5696,17 +5694,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | List[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single ManyRequired record. @@ -5749,9 +5749,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -5760,21 +5759,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | list[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single ManyRequired record. Raises `RecordNotFoundError` if no record was found. @@ -5817,9 +5814,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -5828,14 +5824,16 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.ManyRequiredUpdateInput, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single ManyRequired record. @@ -5873,26 +5871,24 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.ManyRequiredWhereUniqueInput, data: types.ManyRequiredUpsertInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -5944,17 +5940,18 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -5992,22 +5989,25 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of ManyRequired records present in the database @@ -6061,20 +6061,20 @@ class ManyRequiredActions(Generic[_PrismaModelT]): async def count( self, select: types.ManyRequiredCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ManyRequiredCountAggregateOutput: ... async def count( self, - select: Optional[types.ManyRequiredCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + select: NotGivenOr[types.ManyRequiredCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ManyRequiredCountAggregateOutput]: """Count the number of ManyRequired records present in the database @@ -6123,39 +6123,34 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ManyRequiredCountAggregateOutput: + if is_mapping(select): + return cast(types.ManyRequiredCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ManyRequiredCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.ManyRequiredWhereInput] = None + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple ManyRequired records. @@ -6181,13 +6176,15 @@ class ManyRequiredActions(Generic[_PrismaModelT]): total = await ManyRequired.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -6195,19 +6192,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.ManyRequiredScalarFieldKeys'], + by: list['types.ManyRequiredScalarFieldKeys'], *, - where: Optional['types.ManyRequiredWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.ManyRequiredAvgAggregateInput'] = None, - sum: Optional['types.ManyRequiredSumAggregateInput'] = None, - min: Optional['types.ManyRequiredMinAggregateInput'] = None, - max: Optional['types.ManyRequiredMaxAggregateInput'] = None, - having: Optional['types.ManyRequiredScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ManyRequiredCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.ManyRequiredGroupByOutput']: + where: NotGivenOr['types.ManyRequiredWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.ManyRequiredAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ManyRequiredSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.ManyRequiredMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.ManyRequiredMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.ManyRequiredScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ManyRequiredCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.ManyRequiredGroupByOutput']: """Group ManyRequired records by one or more field values and perform aggregations each group such as finding the average. @@ -6265,35 +6262,34 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -6301,21 +6297,25 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class ListsActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -6398,7 +6398,7 @@ class ListsActions(Generic[_PrismaModelT]): async def create( self, data: types.ListsCreateInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new Lists record. @@ -6432,21 +6432,22 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.ListsCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple Lists records at once. @@ -6494,21 +6495,21 @@ class ListsActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single Lists record. @@ -6543,24 +6544,22 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique Lists record. @@ -6595,23 +6594,21 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[Optional[types.ListsInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique Lists record. Raises `RecordNotFoundError` if no record is found. @@ -6646,25 +6643,26 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | List[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple Lists records. @@ -6712,9 +6710,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -6724,17 +6721,19 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | List[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single Lists record. @@ -6777,9 +6776,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -6788,21 +6786,19 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | list[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single Lists record. Raises `RecordNotFoundError` if no record was found. @@ -6845,9 +6841,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -6856,14 +6851,16 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.ListsUpdateInput, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single Lists record. @@ -6901,26 +6898,24 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.ListsWhereUniqueInput, data: types.ListsUpsertInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -6962,17 +6957,18 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -7010,22 +7006,25 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of Lists records present in the database @@ -7079,20 +7078,20 @@ class ListsActions(Generic[_PrismaModelT]): async def count( self, select: types.ListsCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ListsCountAggregateOutput: ... async def count( self, - select: Optional[types.ListsCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + select: NotGivenOr[types.ListsCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ListsCountAggregateOutput]: """Count the number of Lists records present in the database @@ -7141,39 +7140,34 @@ class ListsActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ListsCountAggregateOutput: + if is_mapping(select): + return cast(types.ListsCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ListsCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.ListsWhereInput] = None + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple Lists records. @@ -7199,13 +7193,15 @@ class ListsActions(Generic[_PrismaModelT]): total = await Lists.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -7213,19 +7209,19 @@ class ListsActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.ListsScalarFieldKeys'], + by: list['types.ListsScalarFieldKeys'], *, - where: Optional['types.ListsWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.ListsAvgAggregateInput'] = None, - sum: Optional['types.ListsSumAggregateInput'] = None, - min: Optional['types.ListsMinAggregateInput'] = None, - max: Optional['types.ListsMaxAggregateInput'] = None, - having: Optional['types.ListsScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ListsCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.ListsGroupByOutput']: + where: NotGivenOr['types.ListsWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.ListsAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ListsSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.ListsMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.ListsMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.ListsScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ListsCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.ListsGroupByOutput']: """Group Lists records by one or more field values and perform aggregations each group such as finding the average. @@ -7283,35 +7279,34 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -7319,21 +7314,25 @@ class ListsActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class AActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -7416,7 +7415,7 @@ class AActions(Generic[_PrismaModelT]): async def create( self, data: types.ACreateInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new A record. @@ -7454,21 +7453,22 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.ACreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple A records at once. @@ -7524,21 +7524,21 @@ class AActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single A record. @@ -7573,24 +7573,22 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique A record. @@ -7625,23 +7623,21 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[Optional[types.AInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique A record. Raises `RecordNotFoundError` if no record is found. @@ -7676,25 +7672,26 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | List[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple A records. @@ -7742,9 +7739,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -7754,17 +7750,19 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | List[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single A record. @@ -7807,9 +7805,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -7818,21 +7815,19 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | list[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single A record. Raises `RecordNotFoundError` if no record was found. @@ -7875,9 +7870,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -7886,14 +7880,16 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.AUpdateInput, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single A record. @@ -7931,26 +7927,24 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.AWhereUniqueInput, data: types.AUpsertInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -7998,17 +7992,18 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -8046,22 +8041,25 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of A records present in the database @@ -8115,20 +8113,20 @@ class AActions(Generic[_PrismaModelT]): async def count( self, select: types.ACountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ACountAggregateOutput: ... async def count( self, - select: Optional[types.ACountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + select: NotGivenOr[types.ACountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ACountAggregateOutput]: """Count the number of A records present in the database @@ -8177,39 +8175,34 @@ class AActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ACountAggregateOutput: + if is_mapping(select): + return cast(types.ACountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ACountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.AWhereInput] = None + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple A records. @@ -8235,13 +8228,15 @@ class AActions(Generic[_PrismaModelT]): total = await A.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -8249,19 +8244,19 @@ class AActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.AScalarFieldKeys'], + by: list['types.AScalarFieldKeys'], *, - where: Optional['types.AWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.AAvgAggregateInput'] = None, - sum: Optional['types.ASumAggregateInput'] = None, - min: Optional['types.AMinAggregateInput'] = None, - max: Optional['types.AMaxAggregateInput'] = None, - having: Optional['types.AScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ACountAggregateInput']] = None, - order: Optional[Union[Mapping['types.AScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.AScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.AGroupByOutput']: + where: NotGivenOr['types.AWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.AAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ASumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.AMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.AMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.AScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ACountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.AScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.AScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.AGroupByOutput']: """Group A records by one or more field values and perform aggregations each group such as finding the average. @@ -8319,35 +8314,34 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -8355,21 +8349,25 @@ class AActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class BActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -8452,7 +8450,7 @@ class BActions(Generic[_PrismaModelT]): async def create( self, data: types.BCreateInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new B record. @@ -8490,21 +8488,22 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.BCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple B records at once. @@ -8560,21 +8559,21 @@ class BActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single B record. @@ -8609,24 +8608,22 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique B record. @@ -8661,23 +8658,21 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[Optional[types.BInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique B record. Raises `RecordNotFoundError` if no record is found. @@ -8712,25 +8707,26 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | List[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple B records. @@ -8778,9 +8774,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -8790,17 +8785,19 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | List[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single B record. @@ -8843,9 +8840,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -8854,21 +8850,19 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | list[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single B record. Raises `RecordNotFoundError` if no record was found. @@ -8911,9 +8905,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -8922,14 +8915,16 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.BUpdateInput, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single B record. @@ -8967,26 +8962,24 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.BWhereUniqueInput, data: types.BUpsertInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -9036,17 +9029,18 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -9084,22 +9078,25 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of B records present in the database @@ -9153,20 +9150,20 @@ class BActions(Generic[_PrismaModelT]): async def count( self, select: types.BCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> types.BCountAggregateOutput: ... async def count( self, - select: Optional[types.BCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + select: NotGivenOr[types.BCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.BCountAggregateOutput]: """Count the number of B records present in the database @@ -9215,39 +9212,34 @@ class BActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.BCountAggregateOutput: + if is_mapping(select): + return cast(types.BCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.BCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.BWhereInput] = None + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple B records. @@ -9273,13 +9265,15 @@ class BActions(Generic[_PrismaModelT]): total = await B.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -9287,19 +9281,19 @@ class BActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.BScalarFieldKeys'], + by: list['types.BScalarFieldKeys'], *, - where: Optional['types.BWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.BAvgAggregateInput'] = None, - sum: Optional['types.BSumAggregateInput'] = None, - min: Optional['types.BMinAggregateInput'] = None, - max: Optional['types.BMaxAggregateInput'] = None, - having: Optional['types.BScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.BCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.BScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.BScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.BGroupByOutput']: + where: NotGivenOr['types.BWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.BAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.BSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.BMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.BMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.BScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.BCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.BScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.BScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.BGroupByOutput']: """Group B records by one or more field values and perform aggregations each group such as finding the average. @@ -9357,35 +9351,34 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -9393,21 +9386,25 @@ class BActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class CActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -9490,7 +9487,7 @@ class CActions(Generic[_PrismaModelT]): async def create( self, data: types.CCreateInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new C record. @@ -9530,21 +9527,22 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.CCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple C records at once. @@ -9604,21 +9602,21 @@ class CActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single C record. @@ -9654,24 +9652,22 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique C record. @@ -9707,23 +9703,21 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[Optional[types.CInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique C record. Raises `RecordNotFoundError` if no record is found. @@ -9759,25 +9753,26 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | List[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple C records. @@ -9825,9 +9820,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -9837,17 +9831,19 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | List[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single C record. @@ -9890,9 +9886,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -9901,21 +9896,19 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | list[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single C record. Raises `RecordNotFoundError` if no record was found. @@ -9958,9 +9951,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -9969,14 +9961,16 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.CUpdateInput, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single C record. @@ -10015,26 +10009,24 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.CWhereUniqueInput, data: types.CUpsertInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -10077,17 +10069,18 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -10125,22 +10118,25 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of C records present in the database @@ -10194,20 +10190,20 @@ class CActions(Generic[_PrismaModelT]): async def count( self, select: types.CCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> types.CCountAggregateOutput: ... async def count( self, - select: Optional[types.CCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + select: NotGivenOr[types.CCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.CCountAggregateOutput]: """Count the number of C records present in the database @@ -10256,39 +10252,34 @@ class CActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.CCountAggregateOutput: + if is_mapping(select): + return cast(types.CCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.CCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.CWhereInput] = None + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple C records. @@ -10314,13 +10305,15 @@ class CActions(Generic[_PrismaModelT]): total = await C.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -10328,19 +10321,19 @@ class CActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.CScalarFieldKeys'], + by: list['types.CScalarFieldKeys'], *, - where: Optional['types.CWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.CAvgAggregateInput'] = None, - sum: Optional['types.CSumAggregateInput'] = None, - min: Optional['types.CMinAggregateInput'] = None, - max: Optional['types.CMaxAggregateInput'] = None, - having: Optional['types.CScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.CCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.CScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.CScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.CGroupByOutput']: + where: NotGivenOr['types.CWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.CAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.CSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.CMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.CMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.CScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.CCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.CScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.CScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.CGroupByOutput']: """Group C records by one or more field values and perform aggregations each group such as finding the average. @@ -10398,35 +10391,34 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -10434,21 +10426,25 @@ class CActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class DActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -10531,7 +10527,7 @@ class DActions(Generic[_PrismaModelT]): async def create( self, data: types.DCreateInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new D record. @@ -10570,21 +10566,22 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.DCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple D records at once. @@ -10642,21 +10639,21 @@ class DActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single D record. @@ -10691,24 +10688,22 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique D record. @@ -10743,23 +10738,21 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[Optional[types.DInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique D record. Raises `RecordNotFoundError` if no record is found. @@ -10794,25 +10787,26 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | List[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple D records. @@ -10860,9 +10854,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -10872,17 +10865,19 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | List[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single D record. @@ -10925,9 +10920,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -10936,21 +10930,19 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | list[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single D record. Raises `RecordNotFoundError` if no record was found. @@ -10993,9 +10985,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -11004,14 +10995,16 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.DUpdateInput, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single D record. @@ -11049,26 +11042,24 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.DWhereUniqueInput, data: types.DUpsertInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -11120,17 +11111,18 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -11168,22 +11160,25 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of D records present in the database @@ -11237,20 +11232,20 @@ class DActions(Generic[_PrismaModelT]): async def count( self, select: types.DCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> types.DCountAggregateOutput: ... async def count( self, - select: Optional[types.DCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + select: NotGivenOr[types.DCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.DCountAggregateOutput]: """Count the number of D records present in the database @@ -11299,39 +11294,34 @@ class DActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.DCountAggregateOutput: + if is_mapping(select): + return cast(types.DCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.DCountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.DWhereInput] = None + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple D records. @@ -11357,13 +11347,15 @@ class DActions(Generic[_PrismaModelT]): total = await D.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -11371,19 +11363,19 @@ class DActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.DScalarFieldKeys'], + by: list['types.DScalarFieldKeys'], *, - where: Optional['types.DWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.DAvgAggregateInput'] = None, - sum: Optional['types.DSumAggregateInput'] = None, - min: Optional['types.DMinAggregateInput'] = None, - max: Optional['types.DMaxAggregateInput'] = None, - having: Optional['types.DScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.DCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.DScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.DScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.DGroupByOutput']: + where: NotGivenOr['types.DWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.DAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.DSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.DMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.DMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.DScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.DCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.DScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.DScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.DGroupByOutput']: """Group D records by one or more field values and perform aggregations each group such as finding the average. @@ -11441,35 +11433,34 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -11477,21 +11468,25 @@ class DActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class EActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) async def query_raw( self, @@ -11574,7 +11569,7 @@ class EActions(Generic[_PrismaModelT]): async def create( self, data: types.ECreateInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new E record. @@ -11611,21 +11606,22 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def create_many( self, data: List[types.ECreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple E records at once. @@ -11679,21 +11675,21 @@ class EActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = await self._client._execute( + return await self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) async def delete( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single E record. @@ -11728,24 +11724,22 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) async def find_unique( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique E record. @@ -11780,23 +11774,21 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) async def find_unique_or_raise( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[Optional[types.EInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique E record. Raises `RecordNotFoundError` if no record is found. @@ -11831,25 +11823,26 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | List[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple E records. @@ -11897,9 +11890,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -11909,17 +11901,19 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] async def find_first( self, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | List[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single E record. @@ -11962,9 +11956,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -11973,21 +11966,19 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) async def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | list[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single E record. Raises `RecordNotFoundError` if no record was found. @@ -12030,9 +12021,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -12041,14 +12031,16 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update( self, data: types.EUpdateInput, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single E record. @@ -12086,26 +12078,24 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = await self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return await self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) async def upsert( self, where: types.EWhereUniqueInput, data: types.EUpsertInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -12153,17 +12143,18 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) async def update_many( self, @@ -12201,22 +12192,25 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload async def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of E records present in the database @@ -12270,20 +12264,20 @@ class EActions(Generic[_PrismaModelT]): async def count( self, select: types.ECountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ECountAggregateOutput: ... async def count( self, - select: Optional[types.ECountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + select: NotGivenOr[types.ECountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ECountAggregateOutput]: """Count the number of E records present in the database @@ -12332,39 +12326,34 @@ class EActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ECountAggregateOutput: + if is_mapping(select): + return cast(types.ECountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = await self._client._execute( + return await self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ECountAggregateOutput, resp['data']['result']['_count']) - async def delete_many( self, - where: Optional[types.EWhereInput] = None + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple E records. @@ -12390,13 +12379,15 @@ class EActions(Generic[_PrismaModelT]): total = await E.prisma().delete_many() ``` """ - resp = await self._client._execute( + return await self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -12404,19 +12395,19 @@ class EActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present async def group_by( self, - by: List['types.EScalarFieldKeys'], + by: list['types.EScalarFieldKeys'], *, - where: Optional['types.EWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.EAvgAggregateInput'] = None, - sum: Optional['types.ESumAggregateInput'] = None, - min: Optional['types.EMinAggregateInput'] = None, - max: Optional['types.EMaxAggregateInput'] = None, - having: Optional['types.EScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ECountAggregateInput']] = None, - order: Optional[Union[Mapping['types.EScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.EScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.EGroupByOutput']: + where: NotGivenOr['types.EWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.EAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ESumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.EMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.EMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.EScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ECountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.EScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.EScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.EGroupByOutput']: """Group E records by one or more field values and perform aggregations each group such as finding the average. @@ -12474,35 +12465,34 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = await self._client._execute( + return await self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -12510,20 +12500,13 @@ class EActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] - - - -def _select_fields(root: str, select: Mapping[str, Any]) -> str: - """Helper to build a GraphQL selection string - - This is a work around until field selection is added to the query builder. - """ - return root + ' {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) from . import models diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[client.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[client.py].raw index 951e4ee72..79dc549d6 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[client.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[client.py].raw @@ -45,14 +45,16 @@ import logging from datetime import timedelta from pathlib import Path from types import TracebackType +from typing import Iterable +from typing_extensions import Unpack from pydantic import BaseModel from . import types, models, errors, actions from .types import DatasourceOverride, HttpConfig, MetricsFormat -from ._types import BaseModelT, PrismaMethod +from ._types import BaseModelT, PrismaMethod, NotGivenOr, NOT_GIVEN from .bases import _PrismaModel -from .engine import AbstractEngine, QueryEngine, TransactionId +from .engine import AbstractEngine, QueryEngine, TransactionId, json as json_proto from .builder import QueryBuilder, dumps from .generator.models import EngineType, OptionalValueFromEnvVar, BinaryPaths from ._compat import removeprefix, model_parse @@ -82,6 +84,8 @@ BINARY_PATHS = '' RegisteredClient = Union['Prisma', Callable[[], 'Prisma']] _registered_client: Optional[RegisteredClient] = None +_T = TypeVar('_T') + class UseClientDefault: """For certain parameters such as `timeout=...` we can make our intent more clear @@ -252,7 +256,7 @@ class Prisma: # client as well as the transaction client the original client cannot # be `free`d before the transaction is finished. So stopping the engine # here should be safe. - if self.__engine is not None and not self.__copied: + if hasattr(self, '__engine') and self.__engine is not None and not self.__copied: log.debug('unclosed client - stopping engine') engine = self.__engine self.__engine = None @@ -333,15 +337,16 @@ class Prisma: engine.stop(timeout=timeout) async def execute_raw(self, query: LiteralString, *args: Any) -> int: - resp = await self._execute( + return await self._execute_json_proto( method='execute_raw', arguments={ 'query': query, 'parameters': args, }, + data_path=[], model=None, + parser=int, ) - return int(resp['data']['result']) @overload async def query_first( @@ -404,25 +409,27 @@ class Prisma: query: LiteralString, *args: Any, model: Optional[Type[BaseModelT]] = None, - ) -> Union[List[BaseModelT], List[dict[str, Any]]]: + ) -> list[BaseModelT] | list[dict[str, Any]]: """Execute a raw SQL query against the database. If model is given, each returned record is converted to the pydantic model first, otherwise results will be raw dictionaries. """ - resp = await self._execute( + def parser(value: Any) -> list[BaseModelT] | list[dict[str, Any]]: + if model is not None: + return deserialize_raw_results(value, model=model) + return deserialize_raw_results(value) + + return await self._execute_json_proto( method='query_raw', arguments={ 'query': query, 'parameters': args, }, - model=model, + data_path=[], + model=None, + parser=parser, ) - result = resp['data']['result'] - if model is not None: - return deserialize_raw_results(result, model=model) - - return deserialize_raw_results(result) def batch_(self) -> 'Batch': """Returns a context manager for grouping write queries into a single transaction.""" @@ -500,6 +507,77 @@ class Prisma: return model_parse(Metrics, response) + @overload + async def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ) -> _T: + ... + + @overload + async def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + ignore_exceptions: tuple[type[Exception]] | None, + model: type[_PrismaModel] | None = None, + ) -> _T | None: + ... + + async def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ignore_exceptions: tuple[type[Exception]] | None = None, + ) -> _T | None: + """Execute a query against the query engine. + + If `ignore_exceptions` is given then `None` will be returned if any of the given exceptions + are caught while executing the query. + """ + query = json_proto.serialize_single_query( + method=method, + model=model, + arguments=arguments, + ) + + if ignore_exceptions is not None: + try: + response = await self._engine.query(query, tx_id=self._tx_id) + except ignore_exceptions: + return None + else: + response = await self._engine.query(query, tx_id=self._tx_id) + + + # response is in the structure `{'data': {'findUniqueUser': { ... }}}` + data = next(iter(response['data'].values())) + + for key in data_path: + data = data[key] + + return parser(json_proto.deserialize(data)) + + async def _execute_json_proto_batched( + self, + *, + queries: list[json_proto.QueryInput], + ) -> object: + query = json_proto.serialize_batched_query(queries=queries) + return await self._engine.query(query, tx_id=self._tx_id) + # TODO: don't return Any async def _execute( self, @@ -698,7 +776,7 @@ class Batch: def __init__(self, client: Prisma) -> None: self.__client = client - self.__queries: List[str] = [] + self.__queries: list[json_proto.QueryInput] = [] self._active_provider = client._active_provider self.post = PostBatchActions(self) self.user = UserBatchActions(self) @@ -713,30 +791,14 @@ class Batch: self.d = DBatchActions(self) self.e = EBatchActions(self) - def _add(self, **kwargs: Any) -> None: - builder = QueryBuilder(**kwargs) - self.__queries.append(builder.build_query()) + def _add(self, **query: Unpack[json_proto.QueryInput]) -> None: + self.__queries.append(query) async def commit(self) -> None: """Execute the queries""" - # TODO: normalise this, we should still call client._execute queries = self.__queries self.__queries = [] - - payload = { - 'batch': [ - { - 'query': query, - 'variables': {}, - } - for query in queries - ], - 'transaction': True, - } - await self.__client._engine.query( - dumps(payload), - tx_id=self.__client._tx_id, - ) + await self.__client._execute_json_proto_batched(queries=queries) def execute_raw(self, query: LiteralString, *args: Any) -> None: self._add( @@ -769,7 +831,7 @@ class PostBatchActions: def create( self, data: types.PostCreateInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -784,7 +846,7 @@ class PostBatchActions: self, data: List[types.PostCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -796,13 +858,12 @@ class PostBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -817,7 +878,7 @@ class PostBatchActions: self, data: types.PostUpdateInput, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -833,7 +894,7 @@ class PostBatchActions: self, where: types.PostWhereUniqueInput, data: types.PostUpsertInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -855,18 +916,16 @@ class PostBatchActions: method='update_many', model=models.Post, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.PostWhereInput] = None, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.Post, arguments={'where': where}, - root_selection=['count'], ) @@ -880,7 +939,7 @@ class UserBatchActions: def create( self, data: types.UserCreateInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -895,7 +954,7 @@ class UserBatchActions: self, data: List[types.UserCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -907,13 +966,12 @@ class UserBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -928,7 +986,7 @@ class UserBatchActions: self, data: types.UserUpdateInput, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -944,7 +1002,7 @@ class UserBatchActions: self, where: types.UserWhereUniqueInput, data: types.UserUpsertInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -966,18 +1024,16 @@ class UserBatchActions: method='update_many', model=models.User, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.UserWhereInput] = None, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.User, arguments={'where': where}, - root_selection=['count'], ) @@ -991,7 +1047,7 @@ class MBatchActions: def create( self, data: types.MCreateInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1006,7 +1062,7 @@ class MBatchActions: self, data: List[types.MCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1018,13 +1074,12 @@ class MBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1039,7 +1094,7 @@ class MBatchActions: self, data: types.MUpdateInput, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1055,7 +1110,7 @@ class MBatchActions: self, where: types.MWhereUniqueInput, data: types.MUpsertInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1077,18 +1132,16 @@ class MBatchActions: method='update_many', model=models.M, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.MWhereInput] = None, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.M, arguments={'where': where}, - root_selection=['count'], ) @@ -1102,7 +1155,7 @@ class NBatchActions: def create( self, data: types.NCreateInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1117,7 +1170,7 @@ class NBatchActions: self, data: List[types.NCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1129,13 +1182,12 @@ class NBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1150,7 +1202,7 @@ class NBatchActions: self, data: types.NUpdateInput, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1166,7 +1218,7 @@ class NBatchActions: self, where: types.NWhereUniqueInput, data: types.NUpsertInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1188,18 +1240,16 @@ class NBatchActions: method='update_many', model=models.N, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.NWhereInput] = None, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.N, arguments={'where': where}, - root_selection=['count'], ) @@ -1213,7 +1263,7 @@ class OneOptionalBatchActions: def create( self, data: types.OneOptionalCreateInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1228,7 +1278,7 @@ class OneOptionalBatchActions: self, data: List[types.OneOptionalCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1240,13 +1290,12 @@ class OneOptionalBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1261,7 +1310,7 @@ class OneOptionalBatchActions: self, data: types.OneOptionalUpdateInput, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1277,7 +1326,7 @@ class OneOptionalBatchActions: self, where: types.OneOptionalWhereUniqueInput, data: types.OneOptionalUpsertInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1299,18 +1348,16 @@ class OneOptionalBatchActions: method='update_many', model=models.OneOptional, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.OneOptionalWhereInput] = None, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.OneOptional, arguments={'where': where}, - root_selection=['count'], ) @@ -1324,7 +1371,7 @@ class ManyRequiredBatchActions: def create( self, data: types.ManyRequiredCreateInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1339,7 +1386,7 @@ class ManyRequiredBatchActions: self, data: List[types.ManyRequiredCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1351,13 +1398,12 @@ class ManyRequiredBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1372,7 +1418,7 @@ class ManyRequiredBatchActions: self, data: types.ManyRequiredUpdateInput, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1388,7 +1434,7 @@ class ManyRequiredBatchActions: self, where: types.ManyRequiredWhereUniqueInput, data: types.ManyRequiredUpsertInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1410,18 +1456,16 @@ class ManyRequiredBatchActions: method='update_many', model=models.ManyRequired, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.ManyRequiredWhereInput] = None, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.ManyRequired, arguments={'where': where}, - root_selection=['count'], ) @@ -1435,7 +1479,7 @@ class ListsBatchActions: def create( self, data: types.ListsCreateInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1450,7 +1494,7 @@ class ListsBatchActions: self, data: List[types.ListsCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1462,13 +1506,12 @@ class ListsBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1483,7 +1526,7 @@ class ListsBatchActions: self, data: types.ListsUpdateInput, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1499,7 +1542,7 @@ class ListsBatchActions: self, where: types.ListsWhereUniqueInput, data: types.ListsUpsertInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1521,18 +1564,16 @@ class ListsBatchActions: method='update_many', model=models.Lists, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.ListsWhereInput] = None, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.Lists, arguments={'where': where}, - root_selection=['count'], ) @@ -1546,7 +1587,7 @@ class ABatchActions: def create( self, data: types.ACreateInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1561,7 +1602,7 @@ class ABatchActions: self, data: List[types.ACreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1573,13 +1614,12 @@ class ABatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1594,7 +1634,7 @@ class ABatchActions: self, data: types.AUpdateInput, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1610,7 +1650,7 @@ class ABatchActions: self, where: types.AWhereUniqueInput, data: types.AUpsertInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1632,18 +1672,16 @@ class ABatchActions: method='update_many', model=models.A, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.AWhereInput] = None, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.A, arguments={'where': where}, - root_selection=['count'], ) @@ -1657,7 +1695,7 @@ class BBatchActions: def create( self, data: types.BCreateInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1672,7 +1710,7 @@ class BBatchActions: self, data: List[types.BCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1684,13 +1722,12 @@ class BBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1705,7 +1742,7 @@ class BBatchActions: self, data: types.BUpdateInput, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1721,7 +1758,7 @@ class BBatchActions: self, where: types.BWhereUniqueInput, data: types.BUpsertInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1743,18 +1780,16 @@ class BBatchActions: method='update_many', model=models.B, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.BWhereInput] = None, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.B, arguments={'where': where}, - root_selection=['count'], ) @@ -1768,7 +1803,7 @@ class CBatchActions: def create( self, data: types.CCreateInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1783,7 +1818,7 @@ class CBatchActions: self, data: List[types.CCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1795,13 +1830,12 @@ class CBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1816,7 +1850,7 @@ class CBatchActions: self, data: types.CUpdateInput, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1832,7 +1866,7 @@ class CBatchActions: self, where: types.CWhereUniqueInput, data: types.CUpsertInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1854,18 +1888,16 @@ class CBatchActions: method='update_many', model=models.C, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.CWhereInput] = None, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.C, arguments={'where': where}, - root_selection=['count'], ) @@ -1879,7 +1911,7 @@ class DBatchActions: def create( self, data: types.DCreateInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1894,7 +1926,7 @@ class DBatchActions: self, data: List[types.DCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1906,13 +1938,12 @@ class DBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1927,7 +1958,7 @@ class DBatchActions: self, data: types.DUpdateInput, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1943,7 +1974,7 @@ class DBatchActions: self, where: types.DWhereUniqueInput, data: types.DUpsertInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1965,18 +1996,16 @@ class DBatchActions: method='update_many', model=models.D, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.DWhereInput] = None, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.D, arguments={'where': where}, - root_selection=['count'], ) @@ -1990,7 +2019,7 @@ class EBatchActions: def create( self, data: types.ECreateInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -2005,7 +2034,7 @@ class EBatchActions: self, data: List[types.ECreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -2017,13 +2046,12 @@ class EBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -2038,7 +2066,7 @@ class EBatchActions: self, data: types.EUpdateInput, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -2054,7 +2082,7 @@ class EBatchActions: self, where: types.EWhereUniqueInput, data: types.EUpsertInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -2076,18 +2104,16 @@ class EBatchActions: method='update_many', model=models.E, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.EWhereInput] = None, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.E, arguments={'where': where}, - root_selection=['count'], ) diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[enginequery.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[enginequery.py].raw index b3b5a1eba..b0300a99b 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[enginequery.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_async[enginequery.py].raw @@ -159,7 +159,7 @@ class QueryEngine(HTTPEngine): RUST_LOG='error', RUST_LOG_FORMAT='json', PRISMA_CLIENT_ENGINE_TYPE='binary', - PRISMA_ENGINE_PROTOCOL='graphql', + PRISMA_ENGINE_PROTOCOL='json', ) if DEBUG: diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[actions.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[actions.py].raw index cacee73d5..fb064ad60 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[actions.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[actions.py].raw @@ -42,13 +42,17 @@ LiteralString = str # -- template actions.py.jinja -- from typing import TypeVar import warnings +import functools as _functools -from . import types, errors, bases +from . import types, errors, bases, _parsers +from ._types import NotGiven, NotGivenOr, NOT_GIVEN +from ._helpers import is_mapping from ._compat import model_parse if TYPE_CHECKING: from .client import Client from .bases import _PrismaModel + from .engine.json.serializer import SelectionSet _PrismaModelT = TypeVar('_PrismaModelT', bound='_PrismaModel') @@ -58,11 +62,13 @@ class PostActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -145,7 +151,7 @@ class PostActions(Generic[_PrismaModelT]): def create( self, data: types.PostCreateInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new Post record. @@ -181,21 +187,22 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.PostCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple Post records at once. @@ -247,21 +254,21 @@ class PostActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single Post record. @@ -296,24 +303,22 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique Post record. @@ -348,23 +353,21 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[Optional[types.PostInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique Post record. Raises `RecordNotFoundError` if no record is found. @@ -399,25 +402,26 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | List[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple Post records. @@ -465,9 +469,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -477,17 +480,19 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | List[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single Post record. @@ -530,9 +535,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -541,21 +545,19 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, - include: Optional[types.PostInclude] = None, - order: Optional[Union[types.PostOrderByInput, List[types.PostOrderByInput]]] = None, - distinct: Optional[List[types.PostScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.PostOrderByInput | list[types.PostOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.PostScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single Post record. Raises `RecordNotFoundError` if no record was found. @@ -598,9 +600,8 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -609,14 +610,16 @@ class PostActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.PostUpdateInput, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single Post record. @@ -654,26 +657,24 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.PostWhereUniqueInput, data: types.PostUpsertInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -719,17 +720,18 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -767,22 +769,25 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of Post records present in the database @@ -836,20 +841,20 @@ class PostActions(Generic[_PrismaModelT]): def count( self, select: types.PostCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> types.PostCountAggregateOutput: ... def count( self, - select: Optional[types.PostCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.PostWhereInput] = None, - cursor: Optional[types.PostWhereUniqueInput] = None, + select: NotGivenOr[types.PostCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.PostWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.PostCountAggregateOutput]: """Count the number of Post records present in the database @@ -898,39 +903,34 @@ class PostActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.PostCountAggregateOutput: + if is_mapping(select): + return cast(types.PostCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.PostCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.PostWhereInput] = None + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple Post records. @@ -956,13 +956,15 @@ class PostActions(Generic[_PrismaModelT]): total = Post.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -970,19 +972,19 @@ class PostActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.PostScalarFieldKeys'], + by: list['types.PostScalarFieldKeys'], *, - where: Optional['types.PostWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.PostAvgAggregateInput'] = None, - sum: Optional['types.PostSumAggregateInput'] = None, - min: Optional['types.PostMinAggregateInput'] = None, - max: Optional['types.PostMaxAggregateInput'] = None, - having: Optional['types.PostScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.PostCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.PostScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.PostScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.PostGroupByOutput']: + where: NotGivenOr['types.PostWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.PostAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.PostSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.PostMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.PostMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.PostScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.PostCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.PostScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.PostScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.PostGroupByOutput']: """Group Post records by one or more field values and perform aggregations each group such as finding the average. @@ -1040,35 +1042,34 @@ class PostActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -1076,21 +1077,25 @@ class PostActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class UserActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -1173,7 +1178,7 @@ class UserActions(Generic[_PrismaModelT]): def create( self, data: types.UserCreateInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new User record. @@ -1213,21 +1218,22 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.UserCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple User records at once. @@ -1287,21 +1293,21 @@ class UserActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single User record. @@ -1336,24 +1342,22 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique User record. @@ -1388,23 +1392,21 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[Optional[types.UserInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique User record. Raises `RecordNotFoundError` if no record is found. @@ -1439,25 +1441,26 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | List[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple User records. @@ -1505,9 +1508,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -1517,17 +1519,19 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | List[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single User record. @@ -1570,9 +1574,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -1581,21 +1584,19 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, - include: Optional[types.UserInclude] = None, - order: Optional[Union[types.UserOrderByInput, List[types.UserOrderByInput]]] = None, - distinct: Optional[List[types.UserScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.UserOrderByInput | list[types.UserOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.UserScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single User record. Raises `RecordNotFoundError` if no record was found. @@ -1638,9 +1639,8 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -1649,14 +1649,16 @@ class UserActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.UserUpdateInput, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single User record. @@ -1694,26 +1696,24 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.UserWhereUniqueInput, data: types.UserUpsertInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -1767,17 +1767,18 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -1815,22 +1816,25 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of User records present in the database @@ -1884,20 +1888,20 @@ class UserActions(Generic[_PrismaModelT]): def count( self, select: types.UserCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> types.UserCountAggregateOutput: ... def count( self, - select: Optional[types.UserCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.UserWhereInput] = None, - cursor: Optional[types.UserWhereUniqueInput] = None, + select: NotGivenOr[types.UserCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.UserWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.UserCountAggregateOutput]: """Count the number of User records present in the database @@ -1946,39 +1950,34 @@ class UserActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.UserCountAggregateOutput: + if is_mapping(select): + return cast(types.UserCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.UserCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.UserWhereInput] = None + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple User records. @@ -2004,13 +2003,15 @@ class UserActions(Generic[_PrismaModelT]): total = User.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -2018,19 +2019,19 @@ class UserActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.UserScalarFieldKeys'], + by: list['types.UserScalarFieldKeys'], *, - where: Optional['types.UserWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.UserAvgAggregateInput'] = None, - sum: Optional['types.UserSumAggregateInput'] = None, - min: Optional['types.UserMinAggregateInput'] = None, - max: Optional['types.UserMaxAggregateInput'] = None, - having: Optional['types.UserScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.UserCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.UserScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.UserScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.UserGroupByOutput']: + where: NotGivenOr['types.UserWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.UserAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.UserSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.UserMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.UserMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.UserScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.UserCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.UserScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.UserScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.UserGroupByOutput']: """Group User records by one or more field values and perform aggregations each group such as finding the average. @@ -2088,35 +2089,34 @@ class UserActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -2124,21 +2124,25 @@ class UserActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class MActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -2221,7 +2225,7 @@ class MActions(Generic[_PrismaModelT]): def create( self, data: types.MCreateInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new M record. @@ -2260,21 +2264,22 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.MCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple M records at once. @@ -2332,21 +2337,21 @@ class MActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single M record. @@ -2381,24 +2386,22 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique M record. @@ -2433,23 +2436,21 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[Optional[types.MInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique M record. Raises `RecordNotFoundError` if no record is found. @@ -2484,25 +2485,26 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | List[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple M records. @@ -2550,9 +2552,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -2562,17 +2563,19 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | List[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single M record. @@ -2615,9 +2618,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -2626,21 +2628,19 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, - include: Optional[types.MInclude] = None, - order: Optional[Union[types.MOrderByInput, List[types.MOrderByInput]]] = None, - distinct: Optional[List[types.MScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.MOrderByInput | list[types.MOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.MScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single M record. Raises `RecordNotFoundError` if no record was found. @@ -2683,9 +2683,8 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -2694,14 +2693,16 @@ class MActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.MUpdateInput, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single M record. @@ -2739,26 +2740,24 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.MWhereUniqueInput, data: types.MUpsertInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -2810,17 +2809,18 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -2858,22 +2858,25 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of M records present in the database @@ -2927,20 +2930,20 @@ class MActions(Generic[_PrismaModelT]): def count( self, select: types.MCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> types.MCountAggregateOutput: ... def count( self, - select: Optional[types.MCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.MWhereInput] = None, - cursor: Optional[types.MWhereUniqueInput] = None, + select: NotGivenOr[types.MCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.MWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.MCountAggregateOutput]: """Count the number of M records present in the database @@ -2989,39 +2992,34 @@ class MActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.MCountAggregateOutput: + if is_mapping(select): + return cast(types.MCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.MCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.MWhereInput] = None + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple M records. @@ -3047,13 +3045,15 @@ class MActions(Generic[_PrismaModelT]): total = M.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -3061,19 +3061,19 @@ class MActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.MScalarFieldKeys'], + by: list['types.MScalarFieldKeys'], *, - where: Optional['types.MWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.MAvgAggregateInput'] = None, - sum: Optional['types.MSumAggregateInput'] = None, - min: Optional['types.MMinAggregateInput'] = None, - max: Optional['types.MMaxAggregateInput'] = None, - having: Optional['types.MScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.MCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.MScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.MScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.MGroupByOutput']: + where: NotGivenOr['types.MWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.MAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.MSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.MMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.MMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.MScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.MCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.MScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.MScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.MGroupByOutput']: """Group M records by one or more field values and perform aggregations each group such as finding the average. @@ -3131,35 +3131,34 @@ class MActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -3167,21 +3166,25 @@ class MActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class NActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -3264,7 +3267,7 @@ class NActions(Generic[_PrismaModelT]): def create( self, data: types.NCreateInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new N record. @@ -3304,21 +3307,22 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.NCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple N records at once. @@ -3378,21 +3382,21 @@ class NActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single N record. @@ -3427,24 +3431,22 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique N record. @@ -3479,23 +3481,21 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[Optional[types.NInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique N record. Raises `RecordNotFoundError` if no record is found. @@ -3530,25 +3530,26 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | List[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple N records. @@ -3596,9 +3597,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -3608,17 +3608,19 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | List[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single N record. @@ -3661,9 +3663,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -3672,21 +3673,19 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, - include: Optional[types.NInclude] = None, - order: Optional[Union[types.NOrderByInput, List[types.NOrderByInput]]] = None, - distinct: Optional[List[types.NScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.NOrderByInput | list[types.NOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.NScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single N record. Raises `RecordNotFoundError` if no record was found. @@ -3729,9 +3728,8 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -3740,14 +3738,16 @@ class NActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.NUpdateInput, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single N record. @@ -3785,26 +3785,24 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.NWhereUniqueInput, data: types.NUpsertInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -3858,17 +3856,18 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -3906,22 +3905,25 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of N records present in the database @@ -3975,20 +3977,20 @@ class NActions(Generic[_PrismaModelT]): def count( self, select: types.NCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> types.NCountAggregateOutput: ... def count( self, - select: Optional[types.NCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.NWhereInput] = None, - cursor: Optional[types.NWhereUniqueInput] = None, + select: NotGivenOr[types.NCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.NWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.NCountAggregateOutput]: """Count the number of N records present in the database @@ -4037,39 +4039,34 @@ class NActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.NCountAggregateOutput: + if is_mapping(select): + return cast(types.NCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.NCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.NWhereInput] = None + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple N records. @@ -4095,13 +4092,15 @@ class NActions(Generic[_PrismaModelT]): total = N.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -4109,19 +4108,19 @@ class NActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.NScalarFieldKeys'], + by: list['types.NScalarFieldKeys'], *, - where: Optional['types.NWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.NAvgAggregateInput'] = None, - sum: Optional['types.NSumAggregateInput'] = None, - min: Optional['types.NMinAggregateInput'] = None, - max: Optional['types.NMaxAggregateInput'] = None, - having: Optional['types.NScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.NCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.NScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.NScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.NGroupByOutput']: + where: NotGivenOr['types.NWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.NAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.NSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.NMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.NMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.NScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.NCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.NScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.NScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.NGroupByOutput']: """Group N records by one or more field values and perform aggregations each group such as finding the average. @@ -4179,35 +4178,34 @@ class NActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -4215,21 +4213,25 @@ class NActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class OneOptionalActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -4312,7 +4314,7 @@ class OneOptionalActions(Generic[_PrismaModelT]): def create( self, data: types.OneOptionalCreateInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new OneOptional record. @@ -4351,21 +4353,22 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.OneOptionalCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple OneOptional records at once. @@ -4423,21 +4426,21 @@ class OneOptionalActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single OneOptional record. @@ -4472,24 +4475,22 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique OneOptional record. @@ -4524,23 +4525,21 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[Optional[types.OneOptionalInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique OneOptional record. Raises `RecordNotFoundError` if no record is found. @@ -4575,25 +4574,26 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | List[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple OneOptional records. @@ -4641,9 +4641,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -4653,17 +4652,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | List[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single OneOptional record. @@ -4706,9 +4707,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -4717,21 +4717,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, - include: Optional[types.OneOptionalInclude] = None, - order: Optional[Union[types.OneOptionalOrderByInput, List[types.OneOptionalOrderByInput]]] = None, - distinct: Optional[List[types.OneOptionalScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.OneOptionalOrderByInput | list[types.OneOptionalOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.OneOptionalScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single OneOptional record. Raises `RecordNotFoundError` if no record was found. @@ -4774,9 +4772,8 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -4785,14 +4782,16 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.OneOptionalUpdateInput, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single OneOptional record. @@ -4830,26 +4829,24 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.OneOptionalWhereUniqueInput, data: types.OneOptionalUpsertInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -4901,17 +4898,18 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -4949,22 +4947,25 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of OneOptional records present in the database @@ -5018,20 +5019,20 @@ class OneOptionalActions(Generic[_PrismaModelT]): def count( self, select: types.OneOptionalCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> types.OneOptionalCountAggregateOutput: ... def count( self, - select: Optional[types.OneOptionalCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.OneOptionalWhereInput] = None, - cursor: Optional[types.OneOptionalWhereUniqueInput] = None, + select: NotGivenOr[types.OneOptionalCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.OneOptionalWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.OneOptionalCountAggregateOutput]: """Count the number of OneOptional records present in the database @@ -5080,39 +5081,34 @@ class OneOptionalActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.OneOptionalCountAggregateOutput: + if is_mapping(select): + return cast(types.OneOptionalCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.OneOptionalCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.OneOptionalWhereInput] = None + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple OneOptional records. @@ -5138,13 +5134,15 @@ class OneOptionalActions(Generic[_PrismaModelT]): total = OneOptional.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -5152,19 +5150,19 @@ class OneOptionalActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.OneOptionalScalarFieldKeys'], + by: list['types.OneOptionalScalarFieldKeys'], *, - where: Optional['types.OneOptionalWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.OneOptionalAvgAggregateInput'] = None, - sum: Optional['types.OneOptionalSumAggregateInput'] = None, - min: Optional['types.OneOptionalMinAggregateInput'] = None, - max: Optional['types.OneOptionalMaxAggregateInput'] = None, - having: Optional['types.OneOptionalScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.OneOptionalCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.OneOptionalGroupByOutput']: + where: NotGivenOr['types.OneOptionalWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.OneOptionalAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.OneOptionalSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.OneOptionalMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.OneOptionalMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.OneOptionalScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.OneOptionalCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.OneOptionalScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.OneOptionalGroupByOutput']: """Group OneOptional records by one or more field values and perform aggregations each group such as finding the average. @@ -5222,35 +5220,34 @@ class OneOptionalActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -5258,21 +5255,25 @@ class OneOptionalActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class ManyRequiredActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -5355,7 +5356,7 @@ class ManyRequiredActions(Generic[_PrismaModelT]): def create( self, data: types.ManyRequiredCreateInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new ManyRequired record. @@ -5394,21 +5395,22 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.ManyRequiredCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple ManyRequired records at once. @@ -5466,21 +5468,21 @@ class ManyRequiredActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single ManyRequired record. @@ -5515,24 +5517,22 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique ManyRequired record. @@ -5567,23 +5567,21 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[Optional[types.ManyRequiredInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique ManyRequired record. Raises `RecordNotFoundError` if no record is found. @@ -5618,25 +5616,26 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | List[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple ManyRequired records. @@ -5684,9 +5683,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -5696,17 +5694,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | List[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single ManyRequired record. @@ -5749,9 +5749,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -5760,21 +5759,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, - include: Optional[types.ManyRequiredInclude] = None, - order: Optional[Union[types.ManyRequiredOrderByInput, List[types.ManyRequiredOrderByInput]]] = None, - distinct: Optional[List[types.ManyRequiredScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ManyRequiredOrderByInput | list[types.ManyRequiredOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.ManyRequiredScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single ManyRequired record. Raises `RecordNotFoundError` if no record was found. @@ -5817,9 +5814,8 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -5828,14 +5824,16 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.ManyRequiredUpdateInput, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single ManyRequired record. @@ -5873,26 +5871,24 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.ManyRequiredWhereUniqueInput, data: types.ManyRequiredUpsertInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -5944,17 +5940,18 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -5992,22 +5989,25 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of ManyRequired records present in the database @@ -6061,20 +6061,20 @@ class ManyRequiredActions(Generic[_PrismaModelT]): def count( self, select: types.ManyRequiredCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ManyRequiredCountAggregateOutput: ... def count( self, - select: Optional[types.ManyRequiredCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ManyRequiredWhereInput] = None, - cursor: Optional[types.ManyRequiredWhereUniqueInput] = None, + select: NotGivenOr[types.ManyRequiredCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ManyRequiredWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ManyRequiredCountAggregateOutput]: """Count the number of ManyRequired records present in the database @@ -6123,39 +6123,34 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ManyRequiredCountAggregateOutput: + if is_mapping(select): + return cast(types.ManyRequiredCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ManyRequiredCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.ManyRequiredWhereInput] = None + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple ManyRequired records. @@ -6181,13 +6176,15 @@ class ManyRequiredActions(Generic[_PrismaModelT]): total = ManyRequired.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -6195,19 +6192,19 @@ class ManyRequiredActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.ManyRequiredScalarFieldKeys'], + by: list['types.ManyRequiredScalarFieldKeys'], *, - where: Optional['types.ManyRequiredWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.ManyRequiredAvgAggregateInput'] = None, - sum: Optional['types.ManyRequiredSumAggregateInput'] = None, - min: Optional['types.ManyRequiredMinAggregateInput'] = None, - max: Optional['types.ManyRequiredMaxAggregateInput'] = None, - having: Optional['types.ManyRequiredScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ManyRequiredCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.ManyRequiredGroupByOutput']: + where: NotGivenOr['types.ManyRequiredWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.ManyRequiredAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ManyRequiredSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.ManyRequiredMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.ManyRequiredMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.ManyRequiredScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ManyRequiredCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.ManyRequiredScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.ManyRequiredGroupByOutput']: """Group ManyRequired records by one or more field values and perform aggregations each group such as finding the average. @@ -6265,35 +6262,34 @@ class ManyRequiredActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -6301,21 +6297,25 @@ class ManyRequiredActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class ListsActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -6398,7 +6398,7 @@ class ListsActions(Generic[_PrismaModelT]): def create( self, data: types.ListsCreateInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new Lists record. @@ -6432,21 +6432,22 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.ListsCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple Lists records at once. @@ -6494,21 +6495,21 @@ class ListsActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single Lists record. @@ -6543,24 +6544,22 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique Lists record. @@ -6595,23 +6594,21 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[Optional[types.ListsInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique Lists record. Raises `RecordNotFoundError` if no record is found. @@ -6646,25 +6643,26 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | List[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple Lists records. @@ -6712,9 +6710,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -6724,17 +6721,19 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | List[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single Lists record. @@ -6777,9 +6776,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -6788,21 +6786,19 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, - include: Optional[types.ListsInclude] = None, - order: Optional[Union[types.ListsOrderByInput, List[types.ListsOrderByInput]]] = None, - distinct: Optional[List[types.ListsScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.ListsOrderByInput | list[types.ListsOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.ListsScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single Lists record. Raises `RecordNotFoundError` if no record was found. @@ -6845,9 +6841,8 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -6856,14 +6851,16 @@ class ListsActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.ListsUpdateInput, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single Lists record. @@ -6901,26 +6898,24 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.ListsWhereUniqueInput, data: types.ListsUpsertInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -6962,17 +6957,18 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -7010,22 +7006,25 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of Lists records present in the database @@ -7079,20 +7078,20 @@ class ListsActions(Generic[_PrismaModelT]): def count( self, select: types.ListsCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ListsCountAggregateOutput: ... def count( self, - select: Optional[types.ListsCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.ListsWhereInput] = None, - cursor: Optional[types.ListsWhereUniqueInput] = None, + select: NotGivenOr[types.ListsCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.ListsWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ListsCountAggregateOutput]: """Count the number of Lists records present in the database @@ -7141,39 +7140,34 @@ class ListsActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ListsCountAggregateOutput: + if is_mapping(select): + return cast(types.ListsCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ListsCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.ListsWhereInput] = None + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple Lists records. @@ -7199,13 +7193,15 @@ class ListsActions(Generic[_PrismaModelT]): total = Lists.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -7213,19 +7209,19 @@ class ListsActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.ListsScalarFieldKeys'], + by: list['types.ListsScalarFieldKeys'], *, - where: Optional['types.ListsWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.ListsAvgAggregateInput'] = None, - sum: Optional['types.ListsSumAggregateInput'] = None, - min: Optional['types.ListsMinAggregateInput'] = None, - max: Optional['types.ListsMaxAggregateInput'] = None, - having: Optional['types.ListsScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ListsCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.ListsGroupByOutput']: + where: NotGivenOr['types.ListsWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.ListsAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ListsSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.ListsMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.ListsMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.ListsScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ListsCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.ListsScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.ListsGroupByOutput']: """Group Lists records by one or more field values and perform aggregations each group such as finding the average. @@ -7283,35 +7279,34 @@ class ListsActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -7319,21 +7314,25 @@ class ListsActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class AActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -7416,7 +7415,7 @@ class AActions(Generic[_PrismaModelT]): def create( self, data: types.ACreateInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new A record. @@ -7454,21 +7453,22 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.ACreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple A records at once. @@ -7524,21 +7524,21 @@ class AActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single A record. @@ -7573,24 +7573,22 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique A record. @@ -7625,23 +7623,21 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[Optional[types.AInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique A record. Raises `RecordNotFoundError` if no record is found. @@ -7676,25 +7672,26 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | List[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple A records. @@ -7742,9 +7739,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -7754,17 +7750,19 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | List[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single A record. @@ -7807,9 +7805,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -7818,21 +7815,19 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, - include: Optional[types.AInclude] = None, - order: Optional[Union[types.AOrderByInput, List[types.AOrderByInput]]] = None, - distinct: Optional[List[types.AScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.AOrderByInput | list[types.AOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.AScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single A record. Raises `RecordNotFoundError` if no record was found. @@ -7875,9 +7870,8 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -7886,14 +7880,16 @@ class AActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.AUpdateInput, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single A record. @@ -7931,26 +7927,24 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.AWhereUniqueInput, data: types.AUpsertInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -7998,17 +7992,18 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -8046,22 +8041,25 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of A records present in the database @@ -8115,20 +8113,20 @@ class AActions(Generic[_PrismaModelT]): def count( self, select: types.ACountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ACountAggregateOutput: ... def count( self, - select: Optional[types.ACountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.AWhereInput] = None, - cursor: Optional[types.AWhereUniqueInput] = None, + select: NotGivenOr[types.ACountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.AWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ACountAggregateOutput]: """Count the number of A records present in the database @@ -8177,39 +8175,34 @@ class AActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ACountAggregateOutput: + if is_mapping(select): + return cast(types.ACountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ACountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.AWhereInput] = None + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple A records. @@ -8235,13 +8228,15 @@ class AActions(Generic[_PrismaModelT]): total = A.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -8249,19 +8244,19 @@ class AActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.AScalarFieldKeys'], + by: list['types.AScalarFieldKeys'], *, - where: Optional['types.AWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.AAvgAggregateInput'] = None, - sum: Optional['types.ASumAggregateInput'] = None, - min: Optional['types.AMinAggregateInput'] = None, - max: Optional['types.AMaxAggregateInput'] = None, - having: Optional['types.AScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ACountAggregateInput']] = None, - order: Optional[Union[Mapping['types.AScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.AScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.AGroupByOutput']: + where: NotGivenOr['types.AWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.AAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ASumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.AMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.AMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.AScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ACountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.AScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.AScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.AGroupByOutput']: """Group A records by one or more field values and perform aggregations each group such as finding the average. @@ -8319,35 +8314,34 @@ class AActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -8355,21 +8349,25 @@ class AActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class BActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -8452,7 +8450,7 @@ class BActions(Generic[_PrismaModelT]): def create( self, data: types.BCreateInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new B record. @@ -8490,21 +8488,22 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.BCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple B records at once. @@ -8560,21 +8559,21 @@ class BActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single B record. @@ -8609,24 +8608,22 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique B record. @@ -8661,23 +8658,21 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[Optional[types.BInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique B record. Raises `RecordNotFoundError` if no record is found. @@ -8712,25 +8707,26 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | List[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple B records. @@ -8778,9 +8774,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -8790,17 +8785,19 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | List[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single B record. @@ -8843,9 +8840,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -8854,21 +8850,19 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, - include: Optional[types.BInclude] = None, - order: Optional[Union[types.BOrderByInput, List[types.BOrderByInput]]] = None, - distinct: Optional[List[types.BScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.BOrderByInput | list[types.BOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.BScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single B record. Raises `RecordNotFoundError` if no record was found. @@ -8911,9 +8905,8 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -8922,14 +8915,16 @@ class BActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.BUpdateInput, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single B record. @@ -8967,26 +8962,24 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.BWhereUniqueInput, data: types.BUpsertInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -9036,17 +9029,18 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -9084,22 +9078,25 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of B records present in the database @@ -9153,20 +9150,20 @@ class BActions(Generic[_PrismaModelT]): def count( self, select: types.BCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> types.BCountAggregateOutput: ... def count( self, - select: Optional[types.BCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.BWhereInput] = None, - cursor: Optional[types.BWhereUniqueInput] = None, + select: NotGivenOr[types.BCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.BWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.BCountAggregateOutput]: """Count the number of B records present in the database @@ -9215,39 +9212,34 @@ class BActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.BCountAggregateOutput: + if is_mapping(select): + return cast(types.BCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.BCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.BWhereInput] = None + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple B records. @@ -9273,13 +9265,15 @@ class BActions(Generic[_PrismaModelT]): total = B.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -9287,19 +9281,19 @@ class BActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.BScalarFieldKeys'], + by: list['types.BScalarFieldKeys'], *, - where: Optional['types.BWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.BAvgAggregateInput'] = None, - sum: Optional['types.BSumAggregateInput'] = None, - min: Optional['types.BMinAggregateInput'] = None, - max: Optional['types.BMaxAggregateInput'] = None, - having: Optional['types.BScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.BCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.BScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.BScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.BGroupByOutput']: + where: NotGivenOr['types.BWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.BAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.BSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.BMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.BMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.BScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.BCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.BScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.BScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.BGroupByOutput']: """Group B records by one or more field values and perform aggregations each group such as finding the average. @@ -9357,35 +9351,34 @@ class BActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -9393,21 +9386,25 @@ class BActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class CActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -9490,7 +9487,7 @@ class CActions(Generic[_PrismaModelT]): def create( self, data: types.CCreateInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new C record. @@ -9530,21 +9527,22 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.CCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple C records at once. @@ -9604,21 +9602,21 @@ class CActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single C record. @@ -9654,24 +9652,22 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique C record. @@ -9707,23 +9703,21 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[Optional[types.CInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique C record. Raises `RecordNotFoundError` if no record is found. @@ -9759,25 +9753,26 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | List[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple C records. @@ -9825,9 +9820,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -9837,17 +9831,19 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | List[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single C record. @@ -9890,9 +9886,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -9901,21 +9896,19 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, - include: Optional[types.CInclude] = None, - order: Optional[Union[types.COrderByInput, List[types.COrderByInput]]] = None, - distinct: Optional[List[types.CScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.COrderByInput | list[types.COrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.CScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single C record. Raises `RecordNotFoundError` if no record was found. @@ -9958,9 +9951,8 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -9969,14 +9961,16 @@ class CActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.CUpdateInput, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single C record. @@ -10015,26 +10009,24 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.CWhereUniqueInput, data: types.CUpsertInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -10077,17 +10069,18 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -10125,22 +10118,25 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of C records present in the database @@ -10194,20 +10190,20 @@ class CActions(Generic[_PrismaModelT]): def count( self, select: types.CCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> types.CCountAggregateOutput: ... def count( self, - select: Optional[types.CCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.CWhereInput] = None, - cursor: Optional[types.CWhereUniqueInput] = None, + select: NotGivenOr[types.CCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.CWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.CCountAggregateOutput]: """Count the number of C records present in the database @@ -10256,39 +10252,34 @@ class CActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.CCountAggregateOutput: + if is_mapping(select): + return cast(types.CCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.CCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.CWhereInput] = None + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple C records. @@ -10314,13 +10305,15 @@ class CActions(Generic[_PrismaModelT]): total = C.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -10328,19 +10321,19 @@ class CActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.CScalarFieldKeys'], + by: list['types.CScalarFieldKeys'], *, - where: Optional['types.CWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.CAvgAggregateInput'] = None, - sum: Optional['types.CSumAggregateInput'] = None, - min: Optional['types.CMinAggregateInput'] = None, - max: Optional['types.CMaxAggregateInput'] = None, - having: Optional['types.CScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.CCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.CScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.CScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.CGroupByOutput']: + where: NotGivenOr['types.CWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.CAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.CSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.CMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.CMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.CScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.CCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.CScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.CScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.CGroupByOutput']: """Group C records by one or more field values and perform aggregations each group such as finding the average. @@ -10398,35 +10391,34 @@ class CActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -10434,21 +10426,25 @@ class CActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class DActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -10531,7 +10527,7 @@ class DActions(Generic[_PrismaModelT]): def create( self, data: types.DCreateInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new D record. @@ -10570,21 +10566,22 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.DCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple D records at once. @@ -10642,21 +10639,21 @@ class DActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single D record. @@ -10691,24 +10688,22 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique D record. @@ -10743,23 +10738,21 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[Optional[types.DInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique D record. Raises `RecordNotFoundError` if no record is found. @@ -10794,25 +10787,26 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | List[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple D records. @@ -10860,9 +10854,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -10872,17 +10865,19 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | List[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single D record. @@ -10925,9 +10920,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -10936,21 +10930,19 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, - include: Optional[types.DInclude] = None, - order: Optional[Union[types.DOrderByInput, List[types.DOrderByInput]]] = None, - distinct: Optional[List[types.DScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.DOrderByInput | list[types.DOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.DScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single D record. Raises `RecordNotFoundError` if no record was found. @@ -10993,9 +10985,8 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -11004,14 +10995,16 @@ class DActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.DUpdateInput, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single D record. @@ -11049,26 +11042,24 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.DWhereUniqueInput, data: types.DUpsertInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -11120,17 +11111,18 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -11168,22 +11160,25 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of D records present in the database @@ -11237,20 +11232,20 @@ class DActions(Generic[_PrismaModelT]): def count( self, select: types.DCountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> types.DCountAggregateOutput: ... def count( self, - select: Optional[types.DCountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.DWhereInput] = None, - cursor: Optional[types.DWhereUniqueInput] = None, + select: NotGivenOr[types.DCountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.DWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.DCountAggregateOutput]: """Count the number of D records present in the database @@ -11299,39 +11294,34 @@ class DActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.DCountAggregateOutput: + if is_mapping(select): + return cast(types.DCountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.DCountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.DWhereInput] = None + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple D records. @@ -11357,13 +11347,15 @@ class DActions(Generic[_PrismaModelT]): total = D.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -11371,19 +11363,19 @@ class DActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.DScalarFieldKeys'], + by: list['types.DScalarFieldKeys'], *, - where: Optional['types.DWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.DAvgAggregateInput'] = None, - sum: Optional['types.DSumAggregateInput'] = None, - min: Optional['types.DMinAggregateInput'] = None, - max: Optional['types.DMaxAggregateInput'] = None, - having: Optional['types.DScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.DCountAggregateInput']] = None, - order: Optional[Union[Mapping['types.DScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.DScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.DGroupByOutput']: + where: NotGivenOr['types.DWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.DAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.DSumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.DMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.DMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.DScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.DCountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.DScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.DScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.DGroupByOutput']: """Group D records by one or more field values and perform aggregations each group such as finding the average. @@ -11441,35 +11433,34 @@ class DActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -11477,21 +11468,25 @@ class DActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] class EActions(Generic[_PrismaModelT]): __slots__ = ( '_client', '_model', + '_model_parser', ) def __init__(self, client: 'Client', model: Type[_PrismaModelT]) -> None: self._client = client self._model = model + self._model_parser = _functools.partial(model_parse, self._model) def query_raw( self, @@ -11574,7 +11569,7 @@ class EActions(Generic[_PrismaModelT]): def create( self, data: types.ECreateInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Create a new E record. @@ -11611,21 +11606,22 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='create', - model=self._model, arguments={ 'data': data, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def create_many( self, data: List[types.ECreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> int: """Create multiple E records at once. @@ -11679,21 +11675,21 @@ class EActions(Generic[_PrismaModelT]): if self._client._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') - resp = self._client._execute( + return self._client._execute_json_proto( method='create_many', - model=self._model, arguments={ 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], + data_path=['count'], + model=self._model, + parser=int, ) - return int(resp['data']['result']['count']) def delete( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Delete a single E record. @@ -11728,24 +11724,22 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='delete', - model=self._model, - arguments={ - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='delete', + arguments={ + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,) + ) def find_unique( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Find a unique E record. @@ -11780,23 +11774,21 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - return model_parse(self._model, result) def find_unique_or_raise( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[Optional[types.EInclude]] = NOT_GIVEN ) -> _PrismaModelT: """Find a unique E record. Raises `RecordNotFoundError` if no record is found. @@ -11831,25 +11823,26 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_unique_or_raise', - model=self._model, arguments={ 'where': where, 'include': include, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def find_many( self, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | List[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> List[_PrismaModelT]: """Find multiple E records. @@ -11897,9 +11890,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_many', - model=self._model, arguments={ 'take': take, 'skip': skip, @@ -11909,17 +11901,19 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.as_list(self._model_parser), ) - return [model_parse(self._model, r) for r in resp['data']['result']] def find_first( self, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | List[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[List[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> Optional[_PrismaModelT]: """Find a single E record. @@ -11962,9 +11956,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -11973,21 +11966,19 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=_parsers.allow_none(self._model_parser), ) - result = resp['data']['result'] - if result is None: - return None - - return model_parse(self._model, result) def find_first_or_raise( self, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, - include: Optional[types.EInclude] = None, - order: Optional[Union[types.EOrderByInput, List[types.EOrderByInput]]] = None, - distinct: Optional[List[types.EScalarFieldKeys]] = None, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, + order: NotGivenOr[types.EOrderByInput | list[types.EOrderByInput] | None] = NOT_GIVEN, + distinct: NotGivenOr[list[types.EScalarFieldKeys] | None] = NOT_GIVEN, ) -> _PrismaModelT: """Find a single E record. Raises `RecordNotFoundError` if no record was found. @@ -12030,9 +12021,8 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='find_first_or_raise', - model=self._model, arguments={ 'skip': skip, 'where': where, @@ -12041,14 +12031,16 @@ class EActions(Generic[_PrismaModelT]): 'include': include, 'distinct': distinct, }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update( self, data: types.EUpdateInput, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> Optional[_PrismaModelT]: """Update a single E record. @@ -12086,26 +12078,24 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - try: - resp = self._client._execute( - method='update', - model=self._model, - arguments={ - 'data': data, - 'where': where, - 'include': include, - }, - ) - except errors.RecordNotFoundError: - return None - - return model_parse(self._model, resp['data']['result']) + return self._client._execute_json_proto( + method='update', + arguments={ + 'data': data, + 'where': where, + 'include': include, + }, + data_path=[], + model=self._model, + parser=self._model_parser, + ignore_exceptions=(errors.RecordNotFoundError,), + ) def upsert( self, where: types.EWhereUniqueInput, data: types.EUpsertInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> _PrismaModelT: """Updates an existing record or create a new one @@ -12153,17 +12143,18 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='upsert', - model=self._model, arguments={ 'where': where, 'include': include, 'create': data.get('create'), 'update': data.get('update'), }, + data_path=[], + model=self._model, + parser=self._model_parser, ) - return model_parse(self._model, resp['data']['result']) def update_many( self, @@ -12201,22 +12192,25 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='update_many', + arguments={ + 'data': data, + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'data': data, 'where': where,}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) @overload def count( self, - select: None = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + select: NotGivenOr[None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> int: """Count the number of E records present in the database @@ -12270,20 +12264,20 @@ class EActions(Generic[_PrismaModelT]): def count( self, select: types.ECountAggregateInput, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> types.ECountAggregateOutput: ... def count( self, - select: Optional[types.ECountAggregateInput] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - where: Optional[types.EWhereInput] = None, - cursor: Optional[types.EWhereUniqueInput] = None, + select: NotGivenOr[types.ECountAggregateInput | None] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, + cursor: NotGivenOr[types.EWhereUniqueInput | None] = NOT_GIVEN, ) -> Union[int, types.ECountAggregateOutput]: """Count the number of E records present in the database @@ -12332,39 +12326,34 @@ class EActions(Generic[_PrismaModelT]): ``` """ - # TODO: this selection building should be moved to the QueryBuilder - # - # note the distinction between checking for `not select` here and `select is None` - # later is to handle the case that the given select dictionary is empty, this - # is a limitation of our types. - if not select: - root_selection = ['_count { _all }'] - else: + selection = select or {'_all': True} - root_selection = [ - '_count {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) - ] + def parser(value: Any) -> int | types.ECountAggregateOutput: + if is_mapping(select): + return cast(types.ECountAggregateOutput, value['_count']) + return int(value['_count']['_all']) - resp = self._client._execute( + return self._client._execute_json_proto( method='count', - model=self._model, arguments={ 'take': take, 'skip': skip, 'where': where, 'cursor': cursor, + 'select': { + '_count': { + 'select': selection, + }, + }, }, - root_selection=root_selection, + data_path=[], + model=self._model, + parser=parser, ) - if select is None: - return cast(int, resp['data']['result']['_count']['_all']) - else: - return cast(types.ECountAggregateOutput, resp['data']['result']['_count']) - def delete_many( self, - where: Optional[types.EWhereInput] = None + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN ) -> int: """Delete multiple E records. @@ -12390,13 +12379,15 @@ class EActions(Generic[_PrismaModelT]): total = E.prisma().delete_many() ``` """ - resp = self._client._execute( + return self._client._execute_json_proto( method='delete_many', + arguments={ + 'where': where, + }, + data_path=['count'], model=self._model, - arguments={'where': where}, - root_selection=['count'], + parser=int, ) - return int(resp['data']['result']['count']) # TODO: make this easier to work with safely, currently output fields are typed as # not required, we should refactor the return type @@ -12404,19 +12395,19 @@ class EActions(Generic[_PrismaModelT]): # TODO: statically type that the order argument is required when take or skip are present def group_by( self, - by: List['types.EScalarFieldKeys'], + by: list['types.EScalarFieldKeys'], *, - where: Optional['types.EWhereInput'] = None, - take: Optional[int] = None, - skip: Optional[int] = None, - avg: Optional['types.EAvgAggregateInput'] = None, - sum: Optional['types.ESumAggregateInput'] = None, - min: Optional['types.EMinAggregateInput'] = None, - max: Optional['types.EMaxAggregateInput'] = None, - having: Optional['types.EScalarWhereWithAggregatesInput'] = None, - count: Optional[Union[bool, 'types.ECountAggregateInput']] = None, - order: Optional[Union[Mapping['types.EScalarFieldKeys', 'types.SortOrder'], List[Mapping['types.EScalarFieldKeys', 'types.SortOrder']]]] = None, - ) -> List['types.EGroupByOutput']: + where: NotGivenOr['types.EWhereInput | None'] = NOT_GIVEN, + take: NotGivenOr[int | None] = NOT_GIVEN, + skip: NotGivenOr[int | None] = NOT_GIVEN, + avg: NotGivenOr['types.EAvgAggregateInput | None'] = NOT_GIVEN, + sum: NotGivenOr['types.ESumAggregateInput | None'] = NOT_GIVEN, + min: NotGivenOr['types.EMinAggregateInput | None'] = NOT_GIVEN, + max: NotGivenOr['types.EMaxAggregateInput | None'] = NOT_GIVEN, + having: NotGivenOr['types.EScalarWhereWithAggregatesInput | None'] = NOT_GIVEN, + count: NotGivenOr['bool | types.ECountAggregateInput | None'] = NOT_GIVEN, + order: NotGivenOr[Mapping['types.EScalarFieldKeys', 'types.SortOrder'] | list[Mapping['types.EScalarFieldKeys', 'types.SortOrder']] | None] = NOT_GIVEN, + ) -> list['types.EGroupByOutput']: """Group E records by one or more field values and perform aggregations each group such as finding the average. @@ -12474,35 +12465,34 @@ class EActions(Generic[_PrismaModelT]): ) ``` """ - if order is None: - if take is not None: + if not order: + if take: raise TypeError('Missing argument: \'order\' which is required when \'take\' is present') - if skip is not None: + if skip: raise TypeError('Missing argument: \'order\' which is required when \'skip\' is present') - root_selection: List[str] = [*by] - if avg is not None: - root_selection.append(_select_fields('_avg', avg)) + selection: SelectionSet = {key: True for key in by} + if avg: + selection['_avg'] = {'select': avg} - if min is not None: - root_selection.append(_select_fields('_min', min)) + if min: + selection['_min'] = {'select': min} - if sum is not None: - root_selection.append(_select_fields('_sum', sum)) + if sum: + selection['_sum'] = {'select': sum} - if max is not None: - root_selection.append(_select_fields('_max', max)) + if max: + selection['_max'] = {'select': max} - if count is not None: + if count: if count is True: - root_selection.append('_count { _all }') + selection['_count'] = {'select': {'_all': True}} elif isinstance(count, dict): - root_selection.append(_select_fields('_count', count)) + selection['_count'] = {'select': count} - resp = self._client._execute( + return self._client._execute_json_proto( method='group_by', - model=self._model, arguments={ 'by': by, 'take': take, @@ -12510,20 +12500,13 @@ class EActions(Generic[_PrismaModelT]): 'where': where, 'having': having, 'orderBy': order, + 'select': selection, }, - root_selection=root_selection, + model=self._model, + data_path=[], + parser=lambda v: v, ) - return resp['data']['result'] # type: ignore[no-any-return] - - - -def _select_fields(root: str, select: Mapping[str, Any]) -> str: - """Helper to build a GraphQL selection string - - This is a work around until field selection is added to the query builder. - """ - return root + ' {{ {0} }}'.format(' '.join(k for k, v in select.items() if v is True)) from . import models diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[client.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[client.py].raw index b5dd1182c..b18f86f5e 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[client.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[client.py].raw @@ -45,14 +45,16 @@ import logging from datetime import timedelta from pathlib import Path from types import TracebackType +from typing import Iterable +from typing_extensions import Unpack from pydantic import BaseModel from . import types, models, errors, actions from .types import DatasourceOverride, HttpConfig, MetricsFormat -from ._types import BaseModelT, PrismaMethod +from ._types import BaseModelT, PrismaMethod, NotGivenOr, NOT_GIVEN from .bases import _PrismaModel -from .engine import AbstractEngine, QueryEngine, TransactionId +from .engine import AbstractEngine, QueryEngine, TransactionId, json as json_proto from .builder import QueryBuilder, dumps from .generator.models import EngineType, OptionalValueFromEnvVar, BinaryPaths from ._compat import removeprefix, model_parse @@ -82,6 +84,8 @@ BINARY_PATHS = '' RegisteredClient = Union['Prisma', Callable[[], 'Prisma']] _registered_client: Optional[RegisteredClient] = None +_T = TypeVar('_T') + class UseClientDefault: """For certain parameters such as `timeout=...` we can make our intent more clear @@ -252,7 +256,7 @@ class Prisma: # client as well as the transaction client the original client cannot # be `free`d before the transaction is finished. So stopping the engine # here should be safe. - if self.__engine is not None and not self.__copied: + if hasattr(self, '__engine') and self.__engine is not None and not self.__copied: log.debug('unclosed client - stopping engine') engine = self.__engine self.__engine = None @@ -333,15 +337,16 @@ class Prisma: engine.stop(timeout=timeout) def execute_raw(self, query: LiteralString, *args: Any) -> int: - resp = self._execute( + return self._execute_json_proto( method='execute_raw', arguments={ 'query': query, 'parameters': args, }, + data_path=[], model=None, + parser=int, ) - return int(resp['data']['result']) @overload def query_first( @@ -404,25 +409,27 @@ class Prisma: query: LiteralString, *args: Any, model: Optional[Type[BaseModelT]] = None, - ) -> Union[List[BaseModelT], List[dict[str, Any]]]: + ) -> list[BaseModelT] | list[dict[str, Any]]: """Execute a raw SQL query against the database. If model is given, each returned record is converted to the pydantic model first, otherwise results will be raw dictionaries. """ - resp = self._execute( + def parser(value: Any) -> list[BaseModelT] | list[dict[str, Any]]: + if model is not None: + return deserialize_raw_results(value, model=model) + return deserialize_raw_results(value) + + return self._execute_json_proto( method='query_raw', arguments={ 'query': query, 'parameters': args, }, - model=model, + data_path=[], + model=None, + parser=parser, ) - result = resp['data']['result'] - if model is not None: - return deserialize_raw_results(result, model=model) - - return deserialize_raw_results(result) def batch_(self) -> 'Batch': """Returns a context manager for grouping write queries into a single transaction.""" @@ -500,6 +507,77 @@ class Prisma: return model_parse(Metrics, response) + @overload + def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ) -> _T: + ... + + @overload + def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + ignore_exceptions: tuple[type[Exception]] | None, + model: type[_PrismaModel] | None = None, + ) -> _T | None: + ... + + def _execute_json_proto( + self, + *, + method: PrismaMethod, + arguments: dict[str, Any], + data_path: Iterable[str], + parser: Callable[[Any], _T], + model: type[_PrismaModel] | None = None, + ignore_exceptions: tuple[type[Exception]] | None = None, + ) -> _T | None: + """Execute a query against the query engine. + + If `ignore_exceptions` is given then `None` will be returned if any of the given exceptions + are caught while executing the query. + """ + query = json_proto.serialize_single_query( + method=method, + model=model, + arguments=arguments, + ) + + if ignore_exceptions is not None: + try: + response = self._engine.query(query, tx_id=self._tx_id) + except ignore_exceptions: + return None + else: + response = self._engine.query(query, tx_id=self._tx_id) + + + # response is in the structure `{'data': {'findUniqueUser': { ... }}}` + data = next(iter(response['data'].values())) + + for key in data_path: + data = data[key] + + return parser(json_proto.deserialize(data)) + + def _execute_json_proto_batched( + self, + *, + queries: list[json_proto.QueryInput], + ) -> object: + query = json_proto.serialize_batched_query(queries=queries) + return self._engine.query(query, tx_id=self._tx_id) + # TODO: don't return Any def _execute( self, @@ -698,7 +776,7 @@ class Batch: def __init__(self, client: Prisma) -> None: self.__client = client - self.__queries: List[str] = [] + self.__queries: list[json_proto.QueryInput] = [] self._active_provider = client._active_provider self.post = PostBatchActions(self) self.user = UserBatchActions(self) @@ -713,30 +791,14 @@ class Batch: self.d = DBatchActions(self) self.e = EBatchActions(self) - def _add(self, **kwargs: Any) -> None: - builder = QueryBuilder(**kwargs) - self.__queries.append(builder.build_query()) + def _add(self, **query: Unpack[json_proto.QueryInput]) -> None: + self.__queries.append(query) def commit(self) -> None: """Execute the queries""" - # TODO: normalise this, we should still call client._execute queries = self.__queries self.__queries = [] - - payload = { - 'batch': [ - { - 'query': query, - 'variables': {}, - } - for query in queries - ], - 'transaction': True, - } - self.__client._engine.query( - dumps(payload), - tx_id=self.__client._tx_id, - ) + self.__client._execute_json_proto_batched(queries=queries) def execute_raw(self, query: LiteralString, *args: Any) -> None: self._add( @@ -769,7 +831,7 @@ class PostBatchActions: def create( self, data: types.PostCreateInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -784,7 +846,7 @@ class PostBatchActions: self, data: List[types.PostCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -796,13 +858,12 @@ class PostBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -817,7 +878,7 @@ class PostBatchActions: self, data: types.PostUpdateInput, where: types.PostWhereUniqueInput, - include: Optional[types.PostInclude] = None + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -833,7 +894,7 @@ class PostBatchActions: self, where: types.PostWhereUniqueInput, data: types.PostUpsertInput, - include: Optional[types.PostInclude] = None, + include: NotGivenOr[types.PostInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -855,18 +916,16 @@ class PostBatchActions: method='update_many', model=models.Post, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.PostWhereInput] = None, + where: NotGivenOr[types.PostWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.Post, arguments={'where': where}, - root_selection=['count'], ) @@ -880,7 +939,7 @@ class UserBatchActions: def create( self, data: types.UserCreateInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -895,7 +954,7 @@ class UserBatchActions: self, data: List[types.UserCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -907,13 +966,12 @@ class UserBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -928,7 +986,7 @@ class UserBatchActions: self, data: types.UserUpdateInput, where: types.UserWhereUniqueInput, - include: Optional[types.UserInclude] = None + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -944,7 +1002,7 @@ class UserBatchActions: self, where: types.UserWhereUniqueInput, data: types.UserUpsertInput, - include: Optional[types.UserInclude] = None, + include: NotGivenOr[types.UserInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -966,18 +1024,16 @@ class UserBatchActions: method='update_many', model=models.User, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.UserWhereInput] = None, + where: NotGivenOr[types.UserWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.User, arguments={'where': where}, - root_selection=['count'], ) @@ -991,7 +1047,7 @@ class MBatchActions: def create( self, data: types.MCreateInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1006,7 +1062,7 @@ class MBatchActions: self, data: List[types.MCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1018,13 +1074,12 @@ class MBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1039,7 +1094,7 @@ class MBatchActions: self, data: types.MUpdateInput, where: types.MWhereUniqueInput, - include: Optional[types.MInclude] = None + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1055,7 +1110,7 @@ class MBatchActions: self, where: types.MWhereUniqueInput, data: types.MUpsertInput, - include: Optional[types.MInclude] = None, + include: NotGivenOr[types.MInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1077,18 +1132,16 @@ class MBatchActions: method='update_many', model=models.M, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.MWhereInput] = None, + where: NotGivenOr[types.MWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.M, arguments={'where': where}, - root_selection=['count'], ) @@ -1102,7 +1155,7 @@ class NBatchActions: def create( self, data: types.NCreateInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1117,7 +1170,7 @@ class NBatchActions: self, data: List[types.NCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1129,13 +1182,12 @@ class NBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1150,7 +1202,7 @@ class NBatchActions: self, data: types.NUpdateInput, where: types.NWhereUniqueInput, - include: Optional[types.NInclude] = None + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1166,7 +1218,7 @@ class NBatchActions: self, where: types.NWhereUniqueInput, data: types.NUpsertInput, - include: Optional[types.NInclude] = None, + include: NotGivenOr[types.NInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1188,18 +1240,16 @@ class NBatchActions: method='update_many', model=models.N, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.NWhereInput] = None, + where: NotGivenOr[types.NWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.N, arguments={'where': where}, - root_selection=['count'], ) @@ -1213,7 +1263,7 @@ class OneOptionalBatchActions: def create( self, data: types.OneOptionalCreateInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1228,7 +1278,7 @@ class OneOptionalBatchActions: self, data: List[types.OneOptionalCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1240,13 +1290,12 @@ class OneOptionalBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1261,7 +1310,7 @@ class OneOptionalBatchActions: self, data: types.OneOptionalUpdateInput, where: types.OneOptionalWhereUniqueInput, - include: Optional[types.OneOptionalInclude] = None + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1277,7 +1326,7 @@ class OneOptionalBatchActions: self, where: types.OneOptionalWhereUniqueInput, data: types.OneOptionalUpsertInput, - include: Optional[types.OneOptionalInclude] = None, + include: NotGivenOr[types.OneOptionalInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1299,18 +1348,16 @@ class OneOptionalBatchActions: method='update_many', model=models.OneOptional, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.OneOptionalWhereInput] = None, + where: NotGivenOr[types.OneOptionalWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.OneOptional, arguments={'where': where}, - root_selection=['count'], ) @@ -1324,7 +1371,7 @@ class ManyRequiredBatchActions: def create( self, data: types.ManyRequiredCreateInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1339,7 +1386,7 @@ class ManyRequiredBatchActions: self, data: List[types.ManyRequiredCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1351,13 +1398,12 @@ class ManyRequiredBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1372,7 +1418,7 @@ class ManyRequiredBatchActions: self, data: types.ManyRequiredUpdateInput, where: types.ManyRequiredWhereUniqueInput, - include: Optional[types.ManyRequiredInclude] = None + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1388,7 +1434,7 @@ class ManyRequiredBatchActions: self, where: types.ManyRequiredWhereUniqueInput, data: types.ManyRequiredUpsertInput, - include: Optional[types.ManyRequiredInclude] = None, + include: NotGivenOr[types.ManyRequiredInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1410,18 +1456,16 @@ class ManyRequiredBatchActions: method='update_many', model=models.ManyRequired, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.ManyRequiredWhereInput] = None, + where: NotGivenOr[types.ManyRequiredWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.ManyRequired, arguments={'where': where}, - root_selection=['count'], ) @@ -1435,7 +1479,7 @@ class ListsBatchActions: def create( self, data: types.ListsCreateInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1450,7 +1494,7 @@ class ListsBatchActions: self, data: List[types.ListsCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1462,13 +1506,12 @@ class ListsBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1483,7 +1526,7 @@ class ListsBatchActions: self, data: types.ListsUpdateInput, where: types.ListsWhereUniqueInput, - include: Optional[types.ListsInclude] = None + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1499,7 +1542,7 @@ class ListsBatchActions: self, where: types.ListsWhereUniqueInput, data: types.ListsUpsertInput, - include: Optional[types.ListsInclude] = None, + include: NotGivenOr[types.ListsInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1521,18 +1564,16 @@ class ListsBatchActions: method='update_many', model=models.Lists, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.ListsWhereInput] = None, + where: NotGivenOr[types.ListsWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.Lists, arguments={'where': where}, - root_selection=['count'], ) @@ -1546,7 +1587,7 @@ class ABatchActions: def create( self, data: types.ACreateInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1561,7 +1602,7 @@ class ABatchActions: self, data: List[types.ACreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1573,13 +1614,12 @@ class ABatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1594,7 +1634,7 @@ class ABatchActions: self, data: types.AUpdateInput, where: types.AWhereUniqueInput, - include: Optional[types.AInclude] = None + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1610,7 +1650,7 @@ class ABatchActions: self, where: types.AWhereUniqueInput, data: types.AUpsertInput, - include: Optional[types.AInclude] = None, + include: NotGivenOr[types.AInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1632,18 +1672,16 @@ class ABatchActions: method='update_many', model=models.A, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.AWhereInput] = None, + where: NotGivenOr[types.AWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.A, arguments={'where': where}, - root_selection=['count'], ) @@ -1657,7 +1695,7 @@ class BBatchActions: def create( self, data: types.BCreateInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1672,7 +1710,7 @@ class BBatchActions: self, data: List[types.BCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1684,13 +1722,12 @@ class BBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1705,7 +1742,7 @@ class BBatchActions: self, data: types.BUpdateInput, where: types.BWhereUniqueInput, - include: Optional[types.BInclude] = None + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1721,7 +1758,7 @@ class BBatchActions: self, where: types.BWhereUniqueInput, data: types.BUpsertInput, - include: Optional[types.BInclude] = None, + include: NotGivenOr[types.BInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1743,18 +1780,16 @@ class BBatchActions: method='update_many', model=models.B, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.BWhereInput] = None, + where: NotGivenOr[types.BWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.B, arguments={'where': where}, - root_selection=['count'], ) @@ -1768,7 +1803,7 @@ class CBatchActions: def create( self, data: types.CCreateInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1783,7 +1818,7 @@ class CBatchActions: self, data: List[types.CCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1795,13 +1830,12 @@ class CBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1816,7 +1850,7 @@ class CBatchActions: self, data: types.CUpdateInput, where: types.CWhereUniqueInput, - include: Optional[types.CInclude] = None + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1832,7 +1866,7 @@ class CBatchActions: self, where: types.CWhereUniqueInput, data: types.CUpsertInput, - include: Optional[types.CInclude] = None, + include: NotGivenOr[types.CInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1854,18 +1888,16 @@ class CBatchActions: method='update_many', model=models.C, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.CWhereInput] = None, + where: NotGivenOr[types.CWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.C, arguments={'where': where}, - root_selection=['count'], ) @@ -1879,7 +1911,7 @@ class DBatchActions: def create( self, data: types.DCreateInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -1894,7 +1926,7 @@ class DBatchActions: self, data: List[types.DCreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -1906,13 +1938,12 @@ class DBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -1927,7 +1958,7 @@ class DBatchActions: self, data: types.DUpdateInput, where: types.DWhereUniqueInput, - include: Optional[types.DInclude] = None + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -1943,7 +1974,7 @@ class DBatchActions: self, where: types.DWhereUniqueInput, data: types.DUpsertInput, - include: Optional[types.DInclude] = None, + include: NotGivenOr[types.DInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -1965,18 +1996,16 @@ class DBatchActions: method='update_many', model=models.D, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.DWhereInput] = None, + where: NotGivenOr[types.DWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.D, arguments={'where': where}, - root_selection=['count'], ) @@ -1990,7 +2019,7 @@ class EBatchActions: def create( self, data: types.ECreateInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='create', @@ -2005,7 +2034,7 @@ class EBatchActions: self, data: List[types.ECreateWithoutRelationsInput], *, - skip_duplicates: Optional[bool] = None, + skip_duplicates: NotGivenOr[bool | None] = NOT_GIVEN, ) -> None: if self._batcher._active_provider == 'sqlite': raise errors.UnsupportedDatabaseError('sqlite', 'create_many()') @@ -2017,13 +2046,12 @@ class EBatchActions: 'data': data, 'skipDuplicates': skip_duplicates, }, - root_selection=['count'], ) def delete( self, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete', @@ -2038,7 +2066,7 @@ class EBatchActions: self, data: types.EUpdateInput, where: types.EWhereUniqueInput, - include: Optional[types.EInclude] = None + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN ) -> None: self._batcher._add( method='update', @@ -2054,7 +2082,7 @@ class EBatchActions: self, where: types.EWhereUniqueInput, data: types.EUpsertInput, - include: Optional[types.EInclude] = None, + include: NotGivenOr[types.EInclude | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='upsert', @@ -2076,18 +2104,16 @@ class EBatchActions: method='update_many', model=models.E, arguments={'data': data, 'where': where,}, - root_selection=['count'], ) def delete_many( self, - where: Optional[types.EWhereInput] = None, + where: NotGivenOr[types.EWhereInput | None] = NOT_GIVEN, ) -> None: self._batcher._add( method='delete_many', model=models.E, arguments={'where': where}, - root_selection=['count'], ) diff --git a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[enginequery.py].raw b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[enginequery.py].raw index b5bd3d917..5a393e54c 100644 --- a/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[enginequery.py].raw +++ b/tests/test_generation/exhaustive/__snapshots__/test_exhaustive/test_sync[enginequery.py].raw @@ -160,7 +160,7 @@ class QueryEngine(HTTPEngine): RUST_LOG='error', RUST_LOG_FORMAT='json', PRISMA_CLIENT_ENGINE_TYPE='binary', - PRISMA_ENGINE_PROTOCOL='graphql', + PRISMA_ENGINE_PROTOCOL='json', ) if DEBUG: