hare-orm 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hare/__init__.py +47 -0
- hare/__main__.py +8 -0
- hare/classes/__init__.py +1 -0
- hare/classes/class_path.py +50 -0
- hare/classes/class_property.py +18 -0
- hare/classes/comparable_values.py +113 -0
- hare/classes/constants.py +11 -0
- hare/classes/declared_subclass.py +26 -0
- hare/classes/lazy_exports.py +56 -0
- hare/classes/shown_value_repr.py +21 -0
- hare/classes/value_descriptions.py +81 -0
- hare/cli/__init__.py +3 -0
- hare/cli/__main__.py +7 -0
- hare/cli/arg_parser_builder.py +344 -0
- hare/cli/commands/__init__.py +0 -0
- hare/cli/commands/database_shell_commands.py +56 -0
- hare/cli/commands/distributed_recovery_commands.py +86 -0
- hare/cli/commands/interactive_rename_questions.py +30 -0
- hare/cli/commands/migration_commands.py +579 -0
- hare/cli/commands/schema_commands.py +123 -0
- hare/cli/commands/stub_commands.py +52 -0
- hare/cli/config_locator.py +37 -0
- hare/cli/constants.py +24 -0
- hare/cli/context/__init__.py +9 -0
- hare/cli/context/cli_context.py +17 -0
- hare/cli/context/command_context.py +108 -0
- hare/cli/exceptions.py +9 -0
- hare/cli/hare_cli.py +111 -0
- hare/cli/output/__init__.py +1 -0
- hare/cli/output/output_formatter.py +145 -0
- hare/cli/output/terminal_colors.py +89 -0
- hare/cli/plugins/__init__.py +16 -0
- hare/cli/plugins/cli_command.py +43 -0
- hare/cli/plugins/cli_command_registry.py +144 -0
- hare/cli/plugins/loaded_cli_command.py +13 -0
- hare/cli/shell_launcher.py +95 -0
- hare/contrib/__init__.py +0 -0
- hare/contrib/application_lifecycle.py +157 -0
- hare/contrib/factories/__init__.py +39 -0
- hare/contrib/factories/constants.py +21 -0
- hare/contrib/factories/factory_reference.py +27 -0
- hare/contrib/factories/field_declarations/__init__.py +1 -0
- hare/contrib/factories/field_declarations/declaration.py +19 -0
- hare/contrib/factories/field_declarations/faker.py +49 -0
- hare/contrib/factories/field_declarations/iterator.py +36 -0
- hare/contrib/factories/field_declarations/lazy_attribute.py +35 -0
- hare/contrib/factories/field_declarations/lazy_function.py +22 -0
- hare/contrib/factories/field_declarations/many_to_many.py +40 -0
- hare/contrib/factories/field_declarations/post_declaration.py +22 -0
- hare/contrib/factories/field_declarations/related_factory.py +37 -0
- hare/contrib/factories/field_declarations/sequence.py +22 -0
- hare/contrib/factories/field_declarations/sub_factory.py +30 -0
- hare/contrib/factories/model_factory.py +284 -0
- hare/contrib/factories/trait.py +23 -0
- hare/contrib/frameworks/__init__.py +14 -0
- hare/contrib/frameworks/constants.py +45 -0
- hare/contrib/frameworks/error_answers.py +93 -0
- hare/contrib/frameworks/exceptions.py +19 -0
- hare/contrib/frameworks/fastapi/__init__.py +12 -0
- hare/contrib/frameworks/fastapi/constants.py +4 -0
- hare/contrib/frameworks/fastapi/hare_exception_handlers.py +103 -0
- hare/contrib/frameworks/fastapi/hare_fast_api.py +139 -0
- hare/contrib/frameworks/fastapi/middleware/__init__.py +7 -0
- hare/contrib/frameworks/fastapi/middleware/request_state_reset_middleware.py +27 -0
- hare/contrib/frameworks/fastapi/middleware/transaction_failing_handler.py +31 -0
- hare/contrib/frameworks/fastapi/middleware/transaction_middleware.py +72 -0
- hare/contrib/frameworks/fastapi/request_query_dependency.py +88 -0
- hare/contrib/frameworks/hare_lifecycle.py +50 -0
- hare/contrib/frameworks/health_routes.py +101 -0
- hare/contrib/frameworks/litestar/__init__.py +14 -0
- hare/contrib/frameworks/litestar/constants.py +18 -0
- hare/contrib/frameworks/litestar/hare_dto.py +194 -0
- hare/contrib/frameworks/litestar/hare_exception_handlers.py +77 -0
- hare/contrib/frameworks/litestar/hare_plugin.py +181 -0
- hare/contrib/frameworks/litestar/hare_transfer_function_factory.py +38 -0
- hare/contrib/frameworks/litestar/middleware/__init__.py +7 -0
- hare/contrib/frameworks/litestar/middleware/request_state_reset_middleware.py +23 -0
- hare/contrib/frameworks/litestar/middleware/transaction_middleware.py +35 -0
- hare/contrib/frameworks/litestar/request_query_di_plugin.py +96 -0
- hare/contrib/frameworks/pages/__init__.py +22 -0
- hare/contrib/frameworks/pages/cursor_page_schema.py +25 -0
- hare/contrib/frameworks/pages/page_schema.py +25 -0
- hare/contrib/frameworks/pages/scroll_page_schema.py +23 -0
- hare/contrib/frameworks/parameter_annotation.py +110 -0
- hare/contrib/frameworks/request_state.py +16 -0
- hare/contrib/frameworks/request_transaction.py +186 -0
- hare/contrib/frameworks/robyn/__init__.py +13 -0
- hare/contrib/frameworks/robyn/application/__init__.py +11 -0
- hare/contrib/frameworks/robyn/application/hare_robyn.py +199 -0
- hare/contrib/frameworks/robyn/application/hare_sub_router.py +50 -0
- hare/contrib/frameworks/robyn/constants.py +32 -0
- hare/contrib/frameworks/robyn/hare_exception_handlers.py +128 -0
- hare/contrib/frameworks/robyn/hare_open_api.py +91 -0
- hare/contrib/frameworks/robyn/route_handler.py +198 -0
- hare/contrib/mypy/__init__.py +11 -0
- hare/contrib/mypy/annotation_types.py +170 -0
- hare/contrib/mypy/constants.py +83 -0
- hare/contrib/mypy/enums.py +18 -0
- hare/contrib/mypy/field_names_check.py +222 -0
- hare/contrib/mypy/filter_arguments_check.py +129 -0
- hare/contrib/mypy/hare_mypy_plugin.py +166 -0
- hare/contrib/mypy/instance_attribute_types.py +137 -0
- hare/contrib/mypy/model_registry.py +127 -0
- hare/contrib/mypy/mypy_types.py +383 -0
- hare/contrib/mypy/queryset_extension_methods.py +109 -0
- hare/contrib/mypy/values_row_types.py +146 -0
- hare/contrib/mypy/write_arguments_check.py +159 -0
- hare/contrib/notify/__init__.py +5 -0
- hare/contrib/notify/constants.py +14 -0
- hare/contrib/notify/notification_listener.py +317 -0
- hare/contrib/opentelemetry/__init__.py +16 -0
- hare/contrib/opentelemetry/constants.py +31 -0
- hare/contrib/opentelemetry/open_telemetry_instrumentor.py +60 -0
- hare/contrib/opentelemetry/pool_metric_instruments.py +210 -0
- hare/contrib/opentelemetry/query_spans.py +69 -0
- hare/contrib/outbox/__init__.py +65 -0
- hare/contrib/outbox/broker_arguments.py +40 -0
- hare/contrib/outbox/brokers/__init__.py +1 -0
- hare/contrib/outbox/brokers/rabbitmq_connection.py +55 -0
- hare/contrib/outbox/brokers/redis_connection.py +42 -0
- hare/contrib/outbox/capture/__init__.py +6 -0
- hare/contrib/outbox/capture/change_capture.py +366 -0
- hare/contrib/outbox/capture/change_extension.py +22 -0
- hare/contrib/outbox/capture/constants.py +19 -0
- hare/contrib/outbox/constants.py +31 -0
- hare/contrib/outbox/deliveries/__init__.py +22 -0
- hare/contrib/outbox/deliveries/callable_delivery.py +44 -0
- hare/contrib/outbox/deliveries/constants.py +19 -0
- hare/contrib/outbox/deliveries/kafka_delivery.py +124 -0
- hare/contrib/outbox/deliveries/outbox_delivery.py +106 -0
- hare/contrib/outbox/deliveries/rabbitmq_delivery.py +63 -0
- hare/contrib/outbox/deliveries/redis_streams_delivery.py +110 -0
- hare/contrib/outbox/deliveries/topic_router.py +103 -0
- hare/contrib/outbox/deliveries/webhook_delivery.py +106 -0
- hare/contrib/outbox/exceptions.py +7 -0
- hare/contrib/outbox/outbox_event.py +362 -0
- hare/contrib/outbox/outbox_json_encoding.py +87 -0
- hare/contrib/outbox/relay/__init__.py +7 -0
- hare/contrib/outbox/relay/constants.py +41 -0
- hare/contrib/outbox/relay/declarations.py +76 -0
- hare/contrib/outbox/relay/outbox_backlog.py +18 -0
- hare/contrib/outbox/relay/outbox_relay.py +646 -0
- hare/contrib/outbox/wakeups/__init__.py +20 -0
- hare/contrib/outbox/wakeups/constants.py +20 -0
- hare/contrib/outbox/wakeups/in_process_wakeup.py +17 -0
- hare/contrib/outbox/wakeups/kafka_wakeup.py +123 -0
- hare/contrib/outbox/wakeups/listen_notify_wakeup.py +75 -0
- hare/contrib/outbox/wakeups/outbox_wakeup.py +202 -0
- hare/contrib/outbox/wakeups/rabbitmq_wakeup.py +64 -0
- hare/contrib/outbox/wakeups/redis_wakeup.py +53 -0
- hare/contrib/pydantic/__init__.py +12 -0
- hare/contrib/pydantic/constants.py +41 -0
- hare/contrib/pydantic/creation/__init__.py +1 -0
- hare/contrib/pydantic/creation/computed_field_schemas.py +77 -0
- hare/contrib/pydantic/creation/data_field_schemas.py +230 -0
- hare/contrib/pydantic/creation/field_descriptions.py +17 -0
- hare/contrib/pydantic/creation/field_map.py +138 -0
- hare/contrib/pydantic/creation/generic_foreign_key_schemas.py +136 -0
- hare/contrib/pydantic/creation/generic_foreign_key_tag_reader.py +35 -0
- hare/contrib/pydantic/creation/model_annotations.py +44 -0
- hare/contrib/pydantic/creation/pydantic_creators.py +163 -0
- hare/contrib/pydantic/creation/pydantic_meta_reading.py +134 -0
- hare/contrib/pydantic/creation/pydantic_model_creator.py +434 -0
- hare/contrib/pydantic/creation/relation_field_schemas.py +269 -0
- hare/contrib/pydantic/descriptions/__init__.py +5 -0
- hare/contrib/pydantic/descriptions/computed_field_description.py +12 -0
- hare/contrib/pydantic/descriptions/model_description.py +69 -0
- hare/contrib/pydantic/descriptions/pydantic_meta_data.py +144 -0
- hare/contrib/pydantic/enums.py +12 -0
- hare/contrib/pydantic/models/__init__.py +9 -0
- hare/contrib/pydantic/models/pydantic_list_model.py +34 -0
- hare/contrib/pydantic/models/pydantic_model.py +292 -0
- hare/contrib/pytest/__init__.py +17 -0
- hare/contrib/pytest/constants.py +26 -0
- hare/contrib/pytest/hare_fixtures.py +112 -0
- hare/contrib/pytest/missing_pytest_asyncio_fixtures.py +34 -0
- hare/contrib/pytest/plugin.py +49 -0
- hare/contrib/repeated_queries/__init__.py +19 -0
- hare/contrib/repeated_queries/constants.py +10 -0
- hare/contrib/repeated_queries/repeated_query_collection.py +116 -0
- hare/contrib/repeated_queries/repeated_query_detector.py +227 -0
- hare/contrib/repeated_queries/repeated_query_entry.py +20 -0
- hare/contrib/repeated_queries/repeated_query_report.py +31 -0
- hare/contrib/repeated_queries/shape_stats.py +18 -0
- hare/contrib/request_query/__init__.py +71 -0
- hare/contrib/request_query/bounds/__init__.py +6 -0
- hare/contrib/request_query/bounds/constants.py +4 -0
- hare/contrib/request_query/bounds/lookup_pair_bounds.py +40 -0
- hare/contrib/request_query/bounds/parameter_bounds.py +41 -0
- hare/contrib/request_query/bounds/range_bounds.py +30 -0
- hare/contrib/request_query/constants.py +45 -0
- hare/contrib/request_query/declaration/__init__.py +6 -0
- hare/contrib/request_query/declaration/constants.py +19 -0
- hare/contrib/request_query/declaration/declaration_builder.py +515 -0
- hare/contrib/request_query/declaration/filter_declaration.py +25 -0
- hare/contrib/request_query/declaration/filter_parameter_builder.py +201 -0
- hare/contrib/request_query/declaration/parameter_filter.py +17 -0
- hare/contrib/request_query/declaration/request_query_declaration.py +138 -0
- hare/contrib/request_query/declaration/request_query_parameters.py +54 -0
- hare/contrib/request_query/declaration/request_query_registry.py +90 -0
- hare/contrib/request_query/descriptions/__init__.py +11 -0
- hare/contrib/request_query/descriptions/constants.py +11 -0
- hare/contrib/request_query/descriptions/parameter_choice.py +17 -0
- hare/contrib/request_query/descriptions/parameter_describer.py +240 -0
- hare/contrib/request_query/descriptions/parameter_description.py +66 -0
- hare/contrib/request_query/descriptions/relation_description.py +30 -0
- hare/contrib/request_query/enums.py +69 -0
- hare/contrib/request_query/exceptions.py +52 -0
- hare/contrib/request_query/options/__init__.py +33 -0
- hare/contrib/request_query/options/constants.py +25 -0
- hare/contrib/request_query/options/deleted_config.py +90 -0
- hare/contrib/request_query/options/fields_config.py +55 -0
- hare/contrib/request_query/options/filter.py +34 -0
- hare/contrib/request_query/options/filter_field.py +81 -0
- hare/contrib/request_query/options/in_path.py +12 -0
- hare/contrib/request_query/options/include_config.py +56 -0
- hare/contrib/request_query/options/latest_versions.py +71 -0
- hare/contrib/request_query/options/no_filter.py +11 -0
- hare/contrib/request_query/options/ordering_config.py +81 -0
- hare/contrib/request_query/options/parameter_field.py +27 -0
- hare/contrib/request_query/options/request_option.py +152 -0
- hare/contrib/request_query/options/search_config.py +83 -0
- hare/contrib/request_query/paginations/__init__.py +1 -0
- hare/contrib/request_query/paginations/base_offset_pagination.py +78 -0
- hare/contrib/request_query/paginations/constants.py +17 -0
- hare/contrib/request_query/paginations/cursor.py +83 -0
- hare/contrib/request_query/paginations/cursor_pagination.py +184 -0
- hare/contrib/request_query/paginations/offset_pagination.py +31 -0
- hare/contrib/request_query/paginations/pagination.py +120 -0
- hare/contrib/request_query/paginations/scroll_pagination.py +31 -0
- hare/contrib/request_query/request_query.py +1259 -0
- hare/contrib/request_query/results/__init__.py +11 -0
- hare/contrib/request_query/results/cursor_page.py +25 -0
- hare/contrib/request_query/results/page.py +25 -0
- hare/contrib/request_query/results/scroll_page.py +23 -0
- hare/contrib/request_query/row_changes.py +80 -0
- hare/contrib/request_query/types/__init__.py +15 -0
- hare/contrib/request_query/types/comma_separated.py +46 -0
- hare/contrib/request_query/types/constants.py +16 -0
- hare/contrib/request_query/types/generic_target.py +87 -0
- hare/contrib/request_query/types/key_columns.py +60 -0
- hare/contrib/request_query/types/text_parameter.py +18 -0
- hare/contrib/request_query/value_annotation.py +216 -0
- hare/contrib/request_query/value_counter.py +115 -0
- hare/contrib/request_query/value_target.py +50 -0
- hare/contrib/taskiq/__init__.py +15 -0
- hare/contrib/taskiq/constants.py +23 -0
- hare/contrib/taskiq/hare_taskiq.py +76 -0
- hare/contrib/taskiq/hare_taskiq_middleware.py +195 -0
- hare/contrib/taskiq/running_task.py +29 -0
- hare/contrib/taskiq/task_tenant_labels.py +102 -0
- hare/contrib/taskiq/taskiq_delivery.py +117 -0
- hare/contrib/test/__init__.py +39 -0
- hare/contrib/test/conditions/__init__.py +10 -0
- hare/contrib/test/conditions/condition.py +11 -0
- hare/contrib/test/conditions/in_condition.py +21 -0
- hare/contrib/test/conditions/not_eq.py +18 -0
- hare/contrib/test/conditions/not_in.py +21 -0
- hare/contrib/test/constants.py +18 -0
- hare/contrib/test/databases/__init__.py +1 -0
- hare/contrib/test/databases/kept_test_schema.py +51 -0
- hare/contrib/test/databases/model_truncation.py +128 -0
- hare/contrib/test/databases/reusable_test_databases.py +244 -0
- hare/contrib/test/databases/rollback_isolation.py +149 -0
- hare/contrib/test/databases/temporary_databases.py +118 -0
- hare/contrib/test/exceptions.py +5 -0
- hare/contrib/test/features/__init__.py +1 -0
- hare/contrib/test/features/feature_conditions.py +65 -0
- hare/contrib/test/features/feature_requirements.py +84 -0
- hare/contrib/test/isolated_contexts.py +144 -0
- hare/contrib/test/queries/__init__.py +1 -0
- hare/contrib/test/queries/query_counter.py +35 -0
- hare/contrib/test/queries/query_counting.py +59 -0
- hare/contrib/versioning/__init__.py +7 -0
- hare/contrib/versioning/constants.py +5 -0
- hare/contrib/versioning/versioned_model.py +139 -0
- hare/core/__init__.py +4 -0
- hare/core/apps/__init__.py +8 -0
- hare/core/apps/apps.py +693 -0
- hare/core/apps/cross_connection_checks.py +76 -0
- hare/core/apps/model_connection_checks.py +199 -0
- hare/core/apps/model_discovery.py +142 -0
- hare/core/apps/relation_linking.py +773 -0
- hare/core/apps/swappable_models.py +118 -0
- hare/core/apps/table_names.py +39 -0
- hare/core/caching/__init__.py +1 -0
- hare/core/caching/cache.py +426 -0
- hare/core/caching/caches.py +58 -0
- hare/core/caching/constants.py +13 -0
- hare/core/caching/declarations.py +8 -0
- hare/core/caching/forgettable_cache.py +16 -0
- hare/core/caching/model_cache.py +138 -0
- hare/core/config/__init__.py +25 -0
- hare/core/config/app_config.py +64 -0
- hare/core/config/cli_config.py +38 -0
- hare/core/config/config_secrets.py +101 -0
- hare/core/config/config_section.py +37 -0
- hare/core/config/connection_config.py +69 -0
- hare/core/config/constants.py +17 -0
- hare/core/config/db_url_config.py +24 -0
- hare/core/config/hare_config.py +407 -0
- hare/core/config/migration_safety_config.py +54 -0
- hare/core/config/migrations_config.py +72 -0
- hare/core/connections/__init__.py +1 -0
- hare/core/connections/connection_handler.py +457 -0
- hare/core/connections/connection_token.py +36 -0
- hare/core/connections/connections.py +133 -0
- hare/core/constants.py +40 -0
- hare/core/hare.py +205 -0
- hare/core/hare_context.py +854 -0
- hare/core/hare_meta.py +18 -0
- hare/core/log.py +6 -0
- hare/core/registries.py +22 -0
- hare/core/routing/__init__.py +5 -0
- hare/core/routing/connection_router.py +109 -0
- hare/core/routing/primary_reads.py +42 -0
- hare/core/routing/routing.py +28 -0
- hare/core/routing/written_connections.py +63 -0
- hare/ddl/__init__.py +57 -0
- hare/ddl/conditions/__init__.py +1 -0
- hare/ddl/conditions/constraint_condition.py +154 -0
- hare/ddl/conditions/exclusive_arc_condition.py +80 -0
- hare/ddl/conditions/tenant_condition.py +48 -0
- hare/ddl/conditions/trigger_condition.py +44 -0
- hare/ddl/constants.py +68 -0
- hare/ddl/constraints/__init__.py +7 -0
- hare/ddl/constraints/check_constraint.py +38 -0
- hare/ddl/constraints/exclusion_constraint.py +116 -0
- hare/ddl/constraints/foreign_key_constraint.py +39 -0
- hare/ddl/constraints/unique_constraint.py +150 -0
- hare/ddl/ddl_term_sql.py +45 -0
- hare/ddl/declared_names.py +47 -0
- hare/ddl/enums.py +117 -0
- hare/ddl/expressions/__init__.py +0 -0
- hare/ddl/expressions/declared_expressions.py +102 -0
- hare/ddl/expressions/expression_field_renaming.py +150 -0
- hare/ddl/generated_names.py +87 -0
- hare/ddl/indexes/__init__.py +11 -0
- hare/ddl/indexes/index.py +531 -0
- hare/ddl/indexes/ordered_index_key.py +27 -0
- hare/ddl/indexes/partial_index.py +75 -0
- hare/ddl/raw_sql_term.py +44 -0
- hare/ddl/schema_objects/__init__.py +12 -0
- hare/ddl/schema_objects/database_function.py +91 -0
- hare/ddl/schema_objects/database_sequence.py +87 -0
- hare/ddl/schema_objects/dictionary.py +69 -0
- hare/ddl/schema_objects/enum_type.py +24 -0
- hare/ddl/schema_objects/materialized_view.py +52 -0
- hare/ddl/schema_objects/named_schema_object.py +24 -0
- hare/ddl/schema_objects/trigger.py +151 -0
- hare/ddl/schema_objects/view.py +132 -0
- hare/ddl/security/__init__.py +8 -0
- hare/ddl/security/grant.py +106 -0
- hare/ddl/security/policy.py +92 -0
- hare/ddl/table_options.py +364 -0
- hare/dialects/__init__.py +0 -0
- hare/dialects/base/__init__.py +0 -0
- hare/dialects/base/clauses/__init__.py +1 -0
- hare/dialects/base/clauses/enums.py +37 -0
- hare/dialects/base/clauses/limit_returning_conflict_query_clauses.py +194 -0
- hare/dialects/base/clauses/merge_when_sql.py +24 -0
- hare/dialects/base/clauses/query_clauses.py +636 -0
- hare/dialects/base/client/__init__.py +16 -0
- hare/dialects/base/client/connect_failure_reports.py +49 -0
- hare/dialects/base/client/connection_ping.py +48 -0
- hare/dialects/base/client/connection_wrapper.py +126 -0
- hare/dialects/base/client/constants.py +41 -0
- hare/dialects/base/client/database_client.py +1187 -0
- hare/dialects/base/client/declarations.py +37 -0
- hare/dialects/base/client/driver_statement_log_filter.py +33 -0
- hare/dialects/base/client/password_provider.py +144 -0
- hare/dialects/base/client/pool/__init__.py +1 -0
- hare/dialects/base/client/pool/pool_connection_wrapper.py +37 -0
- hare/dialects/base/client/pool/pool_statistics.py +84 -0
- hare/dialects/base/client/pool/pool_timeouts.py +48 -0
- hare/dialects/base/client/transaction_client.py +621 -0
- hare/dialects/base/client/transaction_lifecycle/__init__.py +1 -0
- hare/dialects/base/client/transaction_lifecycle/pending_statements.py +74 -0
- hare/dialects/base/client/transaction_lifecycle/transaction_callbacks.py +128 -0
- hare/dialects/base/client/transaction_lifecycle/transaction_ending.py +360 -0
- hare/dialects/base/connection/__init__.py +1 -0
- hare/dialects/base/connection/connection_option.py +142 -0
- hare/dialects/base/connection/connection_options.py +69 -0
- hare/dialects/base/connection/constants.py +27 -0
- hare/dialects/base/connection/db_url_config_generator.py +194 -0
- hare/dialects/base/connection/driver.py +136 -0
- hare/dialects/base/constants.py +72 -0
- hare/dialects/base/dialect.py +360 -0
- hare/dialects/base/features.py +369 -0
- hare/dialects/base/literals/__init__.py +1 -0
- hare/dialects/base/literals/constants.py +12 -0
- hare/dialects/base/literals/sql_literals.py +254 -0
- hare/dialects/base/lookups/__init__.py +1 -0
- hare/dialects/base/lookups/filter_operators.py +171 -0
- hare/dialects/base/migration_safety/__init__.py +12 -0
- hare/dialects/base/migration_safety/add_field_backfill_rule.py +37 -0
- hare/dialects/base/migration_safety/alter_field_rewrite_rule.py +39 -0
- hare/dialects/base/migration_safety/constants.py +4 -0
- hare/dialects/base/migration_safety/delete_model_rule.py +33 -0
- hare/dialects/base/migration_safety/migration_safety_rule.py +45 -0
- hare/dialects/base/migration_safety/migration_safety_rules.py +72 -0
- hare/dialects/base/migration_safety/remove_field_rule.py +31 -0
- hare/dialects/base/migration_safety/rename_field_rule.py +41 -0
- hare/dialects/base/migration_safety/rename_model_rule.py +42 -0
- hare/dialects/base/migration_safety/run_sql_rule.py +27 -0
- hare/dialects/base/migration_safety/schema_change_with_run_python_rule.py +49 -0
- hare/dialects/base/parameters/__init__.py +1 -0
- hare/dialects/base/parameters/large_in_list.py +147 -0
- hare/dialects/base/parameters/sql_parameters.py +185 -0
- hare/dialects/base/renderers/__init__.py +7 -0
- hare/dialects/base/renderers/checked_term_renderers.py +61 -0
- hare/dialects/base/renderers/json_renderers.py +60 -0
- hare/dialects/base/renderers/term_renderers.py +508 -0
- hare/dialects/base/results/__init__.py +9 -0
- hare/dialects/base/results/described_result.py +22 -0
- hare/dialects/base/results/statement_result.py +53 -0
- hare/dialects/base/schema/__init__.py +0 -0
- hare/dialects/base/schema/base_schema_editor.py +1139 -0
- hare/dialects/base/schema/columns/__init__.py +1 -0
- hare/dialects/base/schema/columns/column_backfill.py +347 -0
- hare/dialects/base/schema/columns/column_conversion_check.py +51 -0
- hare/dialects/base/schema/columns/column_definitions.py +473 -0
- hare/dialects/base/schema/columns/column_narrowing_check.py +178 -0
- hare/dialects/base/schema/columns/column_renames.py +77 -0
- hare/dialects/base/schema/columns/column_type_changes.py +140 -0
- hare/dialects/base/schema/constants.py +30 -0
- hare/dialects/base/schema/constraints/__init__.py +1 -0
- hare/dialects/base/schema/constraints/constraint_names.py +45 -0
- hare/dialects/base/schema/constraints/constraint_statements.py +262 -0
- hare/dialects/base/schema/data/__init__.py +9 -0
- hare/dialects/base/schema/data/model_sql_data.py +41 -0
- hare/dialects/base/schema/data/referencing_key_columns.py +24 -0
- hare/dialects/base/schema/indexes/__init__.py +1 -0
- hare/dialects/base/schema/indexes/generated_index_names.py +180 -0
- hare/dialects/base/schema/indexes/index_statements.py +397 -0
- hare/dialects/base/schema/relations/__init__.py +1 -0
- hare/dialects/base/schema/relations/foreign_key_rebuild.py +480 -0
- hare/dialects/base/schema/relations/many_to_many_through_tables.py +285 -0
- hare/dialects/base/schema/runtime_statements/__init__.py +1 -0
- hare/dialects/base/schema/runtime_statements/table_clearing.py +54 -0
- hare/dialects/base/schema/runtime_statements/table_locks.py +34 -0
- hare/dialects/base/schema/runtime_statements/tenant_conditions.py +71 -0
- hare/dialects/base/schema/schema_editor_part.py +34 -0
- hare/dialects/base/schema/schema_objects/__init__.py +1 -0
- hare/dialects/base/schema/schema_objects/database_functions.py +74 -0
- hare/dialects/base/schema/schema_objects/dictionaries.py +75 -0
- hare/dialects/base/schema/schema_objects/enum_types.py +88 -0
- hare/dialects/base/schema/schema_objects/extensions.py +69 -0
- hare/dialects/base/schema/schema_objects/grants.py +49 -0
- hare/dialects/base/schema/schema_objects/materialized_views.py +111 -0
- hare/dialects/base/schema/schema_objects/row_level_security_policies.py +82 -0
- hare/dialects/base/schema/schema_objects/schemas.py +65 -0
- hare/dialects/base/schema/schema_objects/sequences.py +95 -0
- hare/dialects/base/schema/schema_objects/views.py +81 -0
- hare/dialects/base/schema/shadow/__init__.py +0 -0
- hare/dialects/base/schema/shadow/shadow_database.py +77 -0
- hare/dialects/base/schema/tables/__init__.py +1 -0
- hare/dialects/base/schema/tables/table_comments.py +92 -0
- hare/dialects/base/schema/tables/table_creation.py +742 -0
- hare/dialects/base/schema/tables/table_partitions.py +78 -0
- hare/dialects/base/schema/tables/table_rebuild.py +268 -0
- hare/dialects/base/schema/triggers/__init__.py +1 -0
- hare/dialects/base/schema/triggers/trigger_statements.py +85 -0
- hare/dialects/base/search/__init__.py +1 -0
- hare/dialects/base/search/text_search.py +135 -0
- hare/dialects/base/sql_dialect.py +23 -0
- hare/dialects/base/transactions/__init__.py +1 -0
- hare/dialects/base/transactions/constants.py +5 -0
- hare/dialects/base/transactions/contexts/__init__.py +1 -0
- hare/dialects/base/transactions/contexts/joined_transaction_context.py +36 -0
- hare/dialects/base/transactions/contexts/nested_transaction_context.py +149 -0
- hare/dialects/base/transactions/contexts/non_transactional_context.py +32 -0
- hare/dialects/base/transactions/contexts/top_level_transaction_context.py +79 -0
- hare/dialects/base/transactions/contexts/transaction_context.py +148 -0
- hare/dialects/base/transactions/savepoints/__init__.py +1 -0
- hare/dialects/base/transactions/savepoints/nested_savepoint_lock.py +152 -0
- hare/dialects/base/transactions/savepoints/savepoint_span.py +51 -0
- hare/dialects/base/transactions/transaction_callback.py +32 -0
- hare/dialects/base/transactions/transaction_statements.py +128 -0
- hare/dialects/base/transactions/two_phase_commit.py +134 -0
- hare/dialects/base/types/__init__.py +9 -0
- hare/dialects/base/types/type_mapping.py +63 -0
- hare/dialects/base/types/type_registry.py +395 -0
- hare/dialects/clickhouse/__init__.py +1 -0
- hare/dialects/clickhouse/clauses/__init__.py +1 -0
- hare/dialects/clickhouse/clauses/clickhouse_query_clauses.py +475 -0
- hare/dialects/clickhouse/clauses/constants.py +42 -0
- hare/dialects/clickhouse/clickhouse_dialect.py +260 -0
- hare/dialects/clickhouse/clickhouse_introspector.py +414 -0
- hare/dialects/clickhouse/clickhouse_table_options.py +727 -0
- hare/dialects/clickhouse/client/__init__.py +1 -0
- hare/dialects/clickhouse/client/clickhouse_client.py +913 -0
- hare/dialects/clickhouse/client/clickhouse_connection.py +30 -0
- hare/dialects/clickhouse/client/clickhouse_error_codes.py +26 -0
- hare/dialects/clickhouse/client/clickhouse_external_sets.py +109 -0
- hare/dialects/clickhouse/client/clickhouse_query_templates.py +79 -0
- hare/dialects/clickhouse/client/clickhouse_statement_result.py +15 -0
- hare/dialects/clickhouse/client/clickhouse_streamed_row.py +52 -0
- hare/dialects/clickhouse/client/clickhouse_transaction_client.py +188 -0
- hare/dialects/clickhouse/client/constants.py +211 -0
- hare/dialects/clickhouse/client/declarations.py +47 -0
- hare/dialects/clickhouse/cluster/__init__.py +0 -0
- hare/dialects/clickhouse/cluster/clickhouse_cluster.py +162 -0
- hare/dialects/clickhouse/cluster/clickhouse_cluster_statements.py +154 -0
- hare/dialects/clickhouse/cluster/constants.py +82 -0
- hare/dialects/clickhouse/connection/__init__.py +1 -0
- hare/dialects/clickhouse/connection/clickhouse_driver.py +40 -0
- hare/dialects/clickhouse/constants.py +226 -0
- hare/dialects/clickhouse/drivers/__init__.py +1 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/__init__.py +1 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/clickhouse_connect_driver.py +43 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/__init__.py +1 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_connect_client.py +390 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_connect_dynamic_type.py +76 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_connect_totals_query.py +70 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_connect_transaction_client.py +56 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_connect_whole_response_query.py +127 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/client/clickhouse_json_compact_values.py +96 -0
- hare/dialects/clickhouse/drivers/clickhouse_connect/constants.py +60 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/__init__.py +1 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/clickhouse_driver_driver.py +48 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/__init__.py +1 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_client.py +361 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_client_info.py +70 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_column_types.py +104 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_connections.py +189 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_decompressors.py +48 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_dynamic_column.py +51 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_library_client.py +239 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_library_connection.py +16 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_map_columns.py +49 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_moment_columns.py +85 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_query_result.py +24 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_row_stream.py +127 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_service_block_stream.py +95 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_settings.py +62 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_transaction_client.py +23 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_tuple_columns.py +38 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/client/clickhouse_driver_variant_column.py +76 -0
- hare/dialects/clickhouse/drivers/clickhouse_driver/constants.py +133 -0
- hare/dialects/clickhouse/drivers/clickhouse_shared_variant_values.py +878 -0
- hare/dialects/clickhouse/drivers/constants.py +143 -0
- hare/dialects/clickhouse/enums.py +38 -0
- hare/dialects/clickhouse/fields/__init__.py +43 -0
- hare/dialects/clickhouse/fields/clickhouse_date_field.py +32 -0
- hare/dialects/clickhouse/fields/clickhouse_datetime_field.py +162 -0
- hare/dialects/clickhouse/fields/clickhouse_integer_field.py +20 -0
- hare/dialects/clickhouse/fields/constants.py +31 -0
- hare/dialects/clickhouse/fields/declarations.py +81 -0
- hare/dialects/clickhouse/fields/dynamic_field.py +122 -0
- hare/dialects/clickhouse/fields/fixed_string_field.py +81 -0
- hare/dialects/clickhouse/fields/float32_field.py +39 -0
- hare/dialects/clickhouse/fields/low_cardinality_field.py +72 -0
- hare/dialects/clickhouse/fields/variant_field.py +174 -0
- hare/dialects/clickhouse/functions/__init__.py +39 -0
- hare/dialects/clickhouse/functions/aggregates/__init__.py +37 -0
- hare/dialects/clickhouse/functions/aggregates/arg_extremum.py +23 -0
- hare/dialects/clickhouse/functions/aggregates/declarations.py +120 -0
- hare/dialects/clickhouse/functions/aggregates/group_array.py +48 -0
- hare/dialects/clickhouse/functions/aggregates/median.py +18 -0
- hare/dialects/clickhouse/functions/aggregates/parametric_aggregate.py +48 -0
- hare/dialects/clickhouse/functions/aggregates/parametric_aggregate_function.py +45 -0
- hare/dialects/clickhouse/functions/aggregates/parametric_analytic_function.py +27 -0
- hare/dialects/clickhouse/functions/aggregates/quantile.py +74 -0
- hare/dialects/clickhouse/functions/aggregates/quantiles.py +58 -0
- hare/dialects/clickhouse/functions/aggregates/top_k.py +44 -0
- hare/dialects/clickhouse/functions/dict_get.py +199 -0
- hare/dialects/clickhouse/indexes/__init__.py +19 -0
- hare/dialects/clickhouse/indexes/bloom_filter_index.py +49 -0
- hare/dialects/clickhouse/indexes/clickhouse_index.py +145 -0
- hare/dialects/clickhouse/indexes/constants.py +14 -0
- hare/dialects/clickhouse/indexes/min_max_index.py +22 -0
- hare/dialects/clickhouse/indexes/ngram_bloom_filter_index.py +43 -0
- hare/dialects/clickhouse/indexes/set_index.py +35 -0
- hare/dialects/clickhouse/indexes/token_bloom_filter_index.py +60 -0
- hare/dialects/clickhouse/introspection/__init__.py +0 -0
- hare/dialects/clickhouse/introspection/clickhouse_check_constraints.py +40 -0
- hare/dialects/clickhouse/introspection/clickhouse_observed_table_options.py +280 -0
- hare/dialects/clickhouse/introspection/clickhouse_sql_parts.py +302 -0
- hare/dialects/clickhouse/introspection/clickhouse_type_parser.py +276 -0
- hare/dialects/clickhouse/introspection/constants.py +69 -0
- hare/dialects/clickhouse/keeper/__init__.py +0 -0
- hare/dialects/clickhouse/keeper/clickhouse_migration_lock.py +114 -0
- hare/dialects/clickhouse/keeper/constants.py +38 -0
- hare/dialects/clickhouse/keeper/keeper_codec.py +152 -0
- hare/dialects/clickhouse/keeper/keeper_session.py +213 -0
- hare/dialects/clickhouse/literals/__init__.py +1 -0
- hare/dialects/clickhouse/literals/clickhouse_literals.py +362 -0
- hare/dialects/clickhouse/lookups/__init__.py +0 -0
- hare/dialects/clickhouse/lookups/clickhouse_array_elements_key.py +32 -0
- hare/dialects/clickhouse/lookups/clickhouse_filter_operators.py +49 -0
- hare/dialects/clickhouse/lookups/clickhouse_global_lookups.py +129 -0
- hare/dialects/clickhouse/lookups/clickhouse_json_equality.py +78 -0
- hare/dialects/clickhouse/lookups/clickhouse_json_key_existence.py +38 -0
- hare/dialects/clickhouse/lookups/clickhouse_json_lookups.py +57 -0
- hare/dialects/clickhouse/lookups/clickhouse_json_path_lookups.py +102 -0
- hare/dialects/clickhouse/lookups/clickhouse_json_value_text.py +24 -0
- hare/dialects/clickhouse/lookups/clickhouse_typed_value_lookups.py +213 -0
- hare/dialects/clickhouse/lookups/constants.py +67 -0
- hare/dialects/clickhouse/lookups/declarations.py +14 -0
- hare/dialects/clickhouse/lookups/global_contains_criterion.py +15 -0
- hare/dialects/clickhouse/lookups/in_list/__init__.py +0 -0
- hare/dialects/clickhouse/lookups/in_list/clickhouse_large_in_list.py +95 -0
- hare/dialects/clickhouse/lookups/in_list/clickhouse_value_set_values.py +45 -0
- hare/dialects/clickhouse/migration_safety/__init__.py +9 -0
- hare/dialects/clickhouse/migration_safety/clickhouse_migration_safety_rules.py +34 -0
- hare/dialects/clickhouse/migration_safety/constants.py +10 -0
- hare/dialects/clickhouse/parameters/__init__.py +1 -0
- hare/dialects/clickhouse/parameters/clickhouse_parameters.py +42 -0
- hare/dialects/clickhouse/query/__init__.py +1 -0
- hare/dialects/clickhouse/query/clickhouse_dialect_variants.py +31 -0
- hare/dialects/clickhouse/query/clickhouse_queryset_methods.py +356 -0
- hare/dialects/clickhouse/query/clickhouse_sql_context.py +47 -0
- hare/dialects/clickhouse/query/clickhouse_totals.py +34 -0
- hare/dialects/clickhouse/query/constants.py +24 -0
- hare/dialects/clickhouse/query/declarations.py +21 -0
- hare/dialects/clickhouse/query/totals_result.py +21 -0
- hare/dialects/clickhouse/renderers/__init__.py +1 -0
- hare/dialects/clickhouse/renderers/clickhouse_aggregate_renderers.py +124 -0
- hare/dialects/clickhouse/renderers/clickhouse_assigned_enum_number.py +30 -0
- hare/dialects/clickhouse/renderers/clickhouse_cast_renderers.py +49 -0
- hare/dialects/clickhouse/renderers/clickhouse_checked_integer_result.py +34 -0
- hare/dialects/clickhouse/renderers/clickhouse_condition_renderers.py +27 -0
- hare/dialects/clickhouse/renderers/clickhouse_container_renderers.py +129 -0
- hare/dialects/clickhouse/renderers/clickhouse_json_renderers.py +105 -0
- hare/dialects/clickhouse/renderers/clickhouse_json_texts.py +34 -0
- hare/dialects/clickhouse/renderers/clickhouse_number_renderers.py +76 -0
- hare/dialects/clickhouse/renderers/clickhouse_renderers.py +339 -0
- hare/dialects/clickhouse/renderers/clickhouse_temporal_renderers.py +262 -0
- hare/dialects/clickhouse/renderers/clickhouse_text_renderers.py +117 -0
- hare/dialects/clickhouse/renderers/clickhouse_value_casts.py +115 -0
- hare/dialects/clickhouse/renderers/clickhouse_window_renderers.py +72 -0
- hare/dialects/clickhouse/renderers/constants.py +341 -0
- hare/dialects/clickhouse/schema/__init__.py +1 -0
- hare/dialects/clickhouse/schema/columns/__init__.py +1 -0
- hare/dialects/clickhouse/schema/columns/clickhouse_column_backfill.py +106 -0
- hare/dialects/clickhouse/schema/columns/clickhouse_column_conversion_check.py +173 -0
- hare/dialects/clickhouse/schema/columns/clickhouse_column_definitions.py +62 -0
- hare/dialects/clickhouse/schema/columns/clickhouse_column_narrowing_check.py +109 -0
- hare/dialects/clickhouse/schema/columns/clickhouse_column_renames.py +45 -0
- hare/dialects/clickhouse/schema/constants.py +201 -0
- hare/dialects/clickhouse/schema/declarations.py +95 -0
- hare/dialects/clickhouse/schema/indexes/__init__.py +0 -0
- hare/dialects/clickhouse/schema/indexes/clickhouse_index_statements.py +60 -0
- hare/dialects/clickhouse/schema/runtime_statements/__init__.py +1 -0
- hare/dialects/clickhouse/schema/runtime_statements/clickhouse_table_clearing.py +19 -0
- hare/dialects/clickhouse/schema/schema_objects/__init__.py +0 -0
- hare/dialects/clickhouse/schema/schema_objects/clickhouse_dictionaries.py +169 -0
- hare/dialects/clickhouse/schema/schema_objects/clickhouse_materialized_views.py +221 -0
- hare/dialects/clickhouse/schema/schema_objects/clickhouse_schemas.py +69 -0
- hare/dialects/clickhouse/schema/schema_objects/clickhouse_views.py +59 -0
- hare/dialects/clickhouse/schema/shadow/__init__.py +0 -0
- hare/dialects/clickhouse/schema/shadow/clickhouse_shadow_database.py +155 -0
- hare/dialects/clickhouse/schema/tables/__init__.py +1 -0
- hare/dialects/clickhouse/schema/tables/clickhouse_table_comments.py +43 -0
- hare/dialects/clickhouse/schema/tables/clickhouse_table_creation.py +50 -0
- hare/dialects/clickhouse/schema/tables/clickhouse_table_partitions.py +160 -0
- hare/dialects/clickhouse/schema/tables/clickhouse_table_rebuild.py +227 -0
- hare/dialects/clickhouse/schema_objects/__init__.py +5 -0
- hare/dialects/clickhouse/schema_objects/clickhouse_dictionary.py +118 -0
- hare/dialects/clickhouse/schema_objects/clickhouse_materialized_view.py +159 -0
- hare/dialects/clickhouse/schema_objects/clickhouse_projection.py +204 -0
- hare/dialects/clickhouse/server_versions.py +5 -0
- hare/dialects/clickhouse/spatial/__init__.py +0 -0
- hare/dialects/clickhouse/spatial/clickhouse_geometry_values.py +208 -0
- hare/dialects/clickhouse/spatial/clickhouse_spatial_renderers.py +265 -0
- hare/dialects/clickhouse/spatial/constants.py +66 -0
- hare/dialects/clickhouse/transactions/__init__.py +0 -0
- hare/dialects/clickhouse/transactions/clickhouse_transaction_statements.py +19 -0
- hare/dialects/clickhouse/types/__init__.py +1 -0
- hare/dialects/clickhouse/types/clickhouse_address_values.py +35 -0
- hare/dialects/clickhouse/types/clickhouse_binary_values.py +58 -0
- hare/dialects/clickhouse/types/clickhouse_container_values.py +267 -0
- hare/dialects/clickhouse/types/clickhouse_dynamic_values.py +307 -0
- hare/dialects/clickhouse/types/clickhouse_enum_types.py +232 -0
- hare/dialects/clickhouse/types/clickhouse_json_values.py +202 -0
- hare/dialects/clickhouse/types/clickhouse_low_cardinality_values.py +95 -0
- hare/dialects/clickhouse/types/clickhouse_nullable_types.py +27 -0
- hare/dialects/clickhouse/types/clickhouse_type_names.py +128 -0
- hare/dialects/clickhouse/types/clickhouse_types.py +258 -0
- hare/dialects/clickhouse/types/clickhouse_variant_values.py +128 -0
- hare/dialects/clickhouse/types/constants.py +139 -0
- hare/dialects/clickhouse/types/declarations.py +23 -0
- hare/dialects/constants.py +32 -0
- hare/dialects/dialect_registry.py +340 -0
- hare/dialects/enums.py +34 -0
- hare/dialects/postgresql/__init__.py +0 -0
- hare/dialects/postgresql/clauses/__init__.py +1 -0
- hare/dialects/postgresql/clauses/constants.py +44 -0
- hare/dialects/postgresql/clauses/postgresql_query_clauses.py +114 -0
- hare/dialects/postgresql/client/__init__.py +10 -0
- hare/dialects/postgresql/client/constants.py +328 -0
- hare/dialects/postgresql/client/postgresql_client.py +1224 -0
- hare/dialects/postgresql/client/postgresql_connect_errors.py +66 -0
- hare/dialects/postgresql/client/postgresql_transaction_client.py +80 -0
- hare/dialects/postgresql/client/reusable_test_schemas.py +197 -0
- hare/dialects/postgresql/client/transaction_pooler.py +137 -0
- hare/dialects/postgresql/connection/__init__.py +1 -0
- hare/dialects/postgresql/connection/constants.py +11 -0
- hare/dialects/postgresql/connection/postgresql_driver.py +99 -0
- hare/dialects/postgresql/constants.py +862 -0
- hare/dialects/postgresql/drivers/__init__.py +0 -0
- hare/dialects/postgresql/drivers/asyncpg/__init__.py +0 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_date_codec.py +81 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_driver.py +37 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_extension_type_codecs.py +78 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_hstore_codec.py +84 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_interval_codec.py +72 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_timestamp_codec.py +74 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_timestamptz_codec.py +88 -0
- hare/dialects/postgresql/drivers/asyncpg/asyncpg_tsvector_codec.py +264 -0
- hare/dialects/postgresql/drivers/asyncpg/client/__init__.py +9 -0
- hare/dialects/postgresql/drivers/asyncpg/client/asyncpg_client.py +738 -0
- hare/dialects/postgresql/drivers/asyncpg/client/asyncpg_transaction_client.py +197 -0
- hare/dialects/postgresql/drivers/asyncpg/constants.py +150 -0
- hare/dialects/postgresql/drivers/asyncpg/pre_epoch_local_zone.py +27 -0
- hare/dialects/postgresql/drivers/constants.py +22 -0
- hare/dialects/postgresql/drivers/rust_pg/__init__.py +0 -0
- hare/dialects/postgresql/drivers/rust_pg/client/__init__.py +9 -0
- hare/dialects/postgresql/drivers/rust_pg/client/rust_pg_client.py +461 -0
- hare/dialects/postgresql/drivers/rust_pg/client/rust_pg_transaction_client.py +306 -0
- hare/dialects/postgresql/drivers/rust_pg/client/rust_pg_transaction_connection_wrapper.py +53 -0
- hare/dialects/postgresql/drivers/rust_pg/constants.py +43 -0
- hare/dialects/postgresql/drivers/rust_pg/rust_pg_driver.py +66 -0
- hare/dialects/postgresql/enums.py +99 -0
- hare/dialects/postgresql/fields/__init__.py +68 -0
- hare/dialects/postgresql/fields/citext_field.py +42 -0
- hare/dialects/postgresql/fields/constants.py +115 -0
- hare/dialects/postgresql/fields/fixed_char_field.py +23 -0
- hare/dialects/postgresql/fields/hstore/__init__.py +5 -0
- hare/dialects/postgresql/fields/hstore/h_store_field.py +105 -0
- hare/dialects/postgresql/fields/hstore/h_store_text.py +86 -0
- hare/dialects/postgresql/fields/interval_field.py +31 -0
- hare/dialects/postgresql/fields/ltree_field.py +98 -0
- hare/dialects/postgresql/fields/multiranges/__init__.py +19 -0
- hare/dialects/postgresql/fields/multiranges/declarations.py +55 -0
- hare/dialects/postgresql/fields/multiranges/multi_range_field.py +326 -0
- hare/dialects/postgresql/fields/naive_datetime_field.py +74 -0
- hare/dialects/postgresql/fields/naive_time_field.py +64 -0
- hare/dialects/postgresql/fields/native_enum/__init__.py +5 -0
- hare/dialects/postgresql/fields/native_enum/native_enum_field.py +23 -0
- hare/dialects/postgresql/fields/native_enum/native_enum_field_instance.py +87 -0
- hare/dialects/postgresql/fields/network/__init__.py +7 -0
- hare/dialects/postgresql/fields/network/cidr_field.py +24 -0
- hare/dialects/postgresql/fields/network/inet_field.py +25 -0
- hare/dialects/postgresql/fields/network/mac_address_field.py +59 -0
- hare/dialects/postgresql/fields/network/network_field.py +80 -0
- hare/dialects/postgresql/fields/postgis_field.py +206 -0
- hare/dialects/postgresql/fields/ranges/__init__.py +19 -0
- hare/dialects/postgresql/fields/ranges/date_range_field.py +48 -0
- hare/dialects/postgresql/fields/ranges/date_time_range_field.py +153 -0
- hare/dialects/postgresql/fields/ranges/decimal_range_field.py +42 -0
- hare/dialects/postgresql/fields/ranges/declarations.py +15 -0
- hare/dialects/postgresql/fields/ranges/int_range_field.py +60 -0
- hare/dialects/postgresql/fields/ranges/range.py +26 -0
- hare/dialects/postgresql/fields/ranges/range_field.py +349 -0
- hare/dialects/postgresql/fields/ts_vector_field.py +143 -0
- hare/dialects/postgresql/functions/__init__.py +72 -0
- hare/dialects/postgresql/functions/aggregates/__init__.py +21 -0
- hare/dialects/postgresql/functions/aggregates/declarations.py +67 -0
- hare/dialects/postgresql/functions/aggregates/jsonb_agg.py +35 -0
- hare/dialects/postgresql/functions/aggregates/jsonb_agg_field.py +29 -0
- hare/dialects/postgresql/functions/aggregates/range_agg.py +22 -0
- hare/dialects/postgresql/functions/aggregates/string_agg.py +101 -0
- hare/dialects/postgresql/functions/aggregates/string_agg_function.py +13 -0
- hare/dialects/postgresql/functions/array/__init__.py +13 -0
- hare/dialects/postgresql/functions/array/any_value.py +13 -0
- hare/dialects/postgresql/functions/array/array_slice.py +28 -0
- hare/dialects/postgresql/functions/array/array_subquery.py +62 -0
- hare/dialects/postgresql/functions/array/array_subscript.py +66 -0
- hare/dialects/postgresql/functions/constants.py +8 -0
- hare/dialects/postgresql/functions/ltree/__init__.py +7 -0
- hare/dialects/postgresql/functions/ltree/subpath.py +54 -0
- hare/dialects/postgresql/functions/random_uuid.py +26 -0
- hare/dialects/postgresql/functions/spatial/__init__.py +9 -0
- hare/dialects/postgresql/functions/spatial/st_distance.py +63 -0
- hare/dialects/postgresql/functions/spatial/std_within.py +46 -0
- hare/dialects/postgresql/functions/statistics/__init__.py +31 -0
- hare/dialects/postgresql/functions/statistics/covar_pop.py +49 -0
- hare/dialects/postgresql/functions/statistics/declarations.py +84 -0
- hare/dialects/postgresql/functions/statistics/regr_count.py +21 -0
- hare/dialects/postgresql/functions/statistics/statistic_pair_aggregate.py +55 -0
- hare/dialects/postgresql/functions/transaction_now.py +27 -0
- hare/dialects/postgresql/functions/trigram/__init__.py +21 -0
- hare/dialects/postgresql/functions/trigram/declarations.py +53 -0
- hare/dialects/postgresql/functions/trigram/trigram_function.py +61 -0
- hare/dialects/postgresql/functions/trigram/trigram_word_similarity.py +19 -0
- hare/dialects/postgresql/indexes/__init__.py +25 -0
- hare/dialects/postgresql/indexes/constants.py +16 -0
- hare/dialects/postgresql/indexes/declarations.py +36 -0
- hare/dialects/postgresql/indexes/hnsw_index.py +63 -0
- hare/dialects/postgresql/indexes/ivfflat_index.py +37 -0
- hare/dialects/postgresql/indexes/postgresql_index.py +112 -0
- hare/dialects/postgresql/introspection/__init__.py +0 -0
- hare/dialects/postgresql/introspection/postgresql_array_literals.py +101 -0
- hare/dialects/postgresql/introspection/postgresql_definitions.py +193 -0
- hare/dialects/postgresql/introspection/postgresql_inspected_schema_objects.py +196 -0
- hare/dialects/postgresql/introspection/postgresql_object_parts.py +102 -0
- hare/dialects/postgresql/literals/__init__.py +1 -0
- hare/dialects/postgresql/literals/postgresql_literals.py +99 -0
- hare/dialects/postgresql/lookups/__init__.py +0 -0
- hare/dialects/postgresql/lookups/array/__init__.py +5 -0
- hare/dialects/postgresql/lookups/array/array_length.py +26 -0
- hare/dialects/postgresql/lookups/constants.py +44 -0
- hare/dialects/postgresql/lookups/hstore/__init__.py +11 -0
- hare/dialects/postgresql/lookups/hstore/h_store_value_term.py +18 -0
- hare/dialects/postgresql/lookups/hstore/postgresql_h_store_field_lookups.py +75 -0
- hare/dialects/postgresql/lookups/hstore/postgresql_h_store_lookups.py +38 -0
- hare/dialects/postgresql/lookups/in_list/__init__.py +11 -0
- hare/dialects/postgresql/lookups/in_list/array_parameter.py +104 -0
- hare/dialects/postgresql/lookups/in_list/postgresql_large_in_list.py +78 -0
- hare/dialects/postgresql/lookups/in_list/unnest_row_values.py +32 -0
- hare/dialects/postgresql/lookups/json/__init__.py +9 -0
- hare/dialects/postgresql/lookups/json/postgresql_json_filter_guards.py +111 -0
- hare/dialects/postgresql/lookups/json/postgresql_json_lookups.py +59 -0
- hare/dialects/postgresql/lookups/ltree/__init__.py +9 -0
- hare/dialects/postgresql/lookups/ltree/postgresql_ltree_field_lookups.py +54 -0
- hare/dialects/postgresql/lookups/ltree/postgresql_ltree_lookups.py +35 -0
- hare/dialects/postgresql/lookups/multiranges/__init__.py +9 -0
- hare/dialects/postgresql/lookups/multiranges/postgresql_multi_range_field_lookups.py +50 -0
- hare/dialects/postgresql/lookups/network/__init__.py +1 -0
- hare/dialects/postgresql/lookups/network/postgresql_network_field_lookups.py +46 -0
- hare/dialects/postgresql/lookups/network/postgresql_network_lookups.py +35 -0
- hare/dialects/postgresql/lookups/postgresql_filter_operators.py +96 -0
- hare/dialects/postgresql/lookups/postgresql_regex_lookups.py +22 -0
- hare/dialects/postgresql/lookups/postgresql_value_encoders.py +163 -0
- hare/dialects/postgresql/lookups/ranges/__init__.py +9 -0
- hare/dialects/postgresql/lookups/ranges/postgresql_range_field_lookups.py +49 -0
- hare/dialects/postgresql/lookups/ranges/postgresql_range_lookups.py +49 -0
- hare/dialects/postgresql/lookups/trigram/__init__.py +1 -0
- hare/dialects/postgresql/lookups/trigram/postgresql_trigram_lookups.py +69 -0
- hare/dialects/postgresql/lookups/trigram/trigram_operator_term.py +16 -0
- hare/dialects/postgresql/lookups/unaccent_transform.py +39 -0
- hare/dialects/postgresql/migration_safety/__init__.py +9 -0
- hare/dialects/postgresql/migration_safety/check_constraint_validation_rule.py +36 -0
- hare/dialects/postgresql/migration_safety/constants.py +18 -0
- hare/dialects/postgresql/migration_safety/foreign_key_validation_rule.py +74 -0
- hare/dialects/postgresql/migration_safety/index_without_concurrently_rule.py +45 -0
- hare/dialects/postgresql/migration_safety/postgresql_migration_safety_rules.py +59 -0
- hare/dialects/postgresql/migration_safety/set_not_null_rule.py +47 -0
- hare/dialects/postgresql/migration_safety/unique_constraint_index_rule.py +65 -0
- hare/dialects/postgresql/migration_safety/volatile_default_rule.py +40 -0
- hare/dialects/postgresql/parameters/__init__.py +1 -0
- hare/dialects/postgresql/parameters/constants.py +83 -0
- hare/dialects/postgresql/parameters/postgresql_parameters.py +86 -0
- hare/dialects/postgresql/partitioning/__init__.py +23 -0
- hare/dialects/postgresql/partitioning/constants.py +56 -0
- hare/dialects/postgresql/partitioning/explicit_partitioning.py +97 -0
- hare/dialects/postgresql/partitioning/hash_partitioning.py +50 -0
- hare/dialects/postgresql/partitioning/list_partitioning.py +55 -0
- hare/dialects/postgresql/partitioning/observed_partitioning.py +205 -0
- hare/dialects/postgresql/partitioning/partitioning.py +280 -0
- hare/dialects/postgresql/partitioning/partitions/__init__.py +1 -0
- hare/dialects/postgresql/partitioning/partitions/default_partition.py +30 -0
- hare/dialects/postgresql/partitioning/partitions/list_partition.py +36 -0
- hare/dialects/postgresql/partitioning/partitions/partition.py +46 -0
- hare/dialects/postgresql/partitioning/partitions/range_partition.py +94 -0
- hare/dialects/postgresql/partitioning/range_partitioning.py +60 -0
- hare/dialects/postgresql/postgresql_dialect.py +207 -0
- hare/dialects/postgresql/postgresql_introspector.py +1055 -0
- hare/dialects/postgresql/postgresql_table_options.py +165 -0
- hare/dialects/postgresql/query/__init__.py +7 -0
- hare/dialects/postgresql/query/declarations.py +13 -0
- hare/dialects/postgresql/renderers/__init__.py +7 -0
- hare/dialects/postgresql/renderers/constants.py +43 -0
- hare/dialects/postgresql/renderers/postgresql_container_renderers.py +90 -0
- hare/dialects/postgresql/renderers/postgresql_defaults.py +88 -0
- hare/dialects/postgresql/renderers/postgresql_json_renderers.py +57 -0
- hare/dialects/postgresql/renderers/postgresql_number_renderers.py +58 -0
- hare/dialects/postgresql/renderers/postgresql_renderers.py +82 -0
- hare/dialects/postgresql/renderers/postgresql_temporal_renderers.py +179 -0
- hare/dialects/postgresql/renderers/postgresql_text_renderers.py +67 -0
- hare/dialects/postgresql/request_query/__init__.py +8 -0
- hare/dialects/postgresql/request_query/declarations.py +17 -0
- hare/dialects/postgresql/schema/__init__.py +0 -0
- hare/dialects/postgresql/schema/columns/__init__.py +1 -0
- hare/dialects/postgresql/schema/columns/postgresql_column_backfill.py +13 -0
- hare/dialects/postgresql/schema/columns/postgresql_column_narrowing_check.py +42 -0
- hare/dialects/postgresql/schema/columns/postgresql_column_type_changes.py +129 -0
- hare/dialects/postgresql/schema/constants.py +384 -0
- hare/dialects/postgresql/schema/constraints/__init__.py +1 -0
- hare/dialects/postgresql/schema/constraints/postgresql_constraint_statements.py +119 -0
- hare/dialects/postgresql/schema/indexes/__init__.py +1 -0
- hare/dialects/postgresql/schema/indexes/postgresql_index_statements.py +24 -0
- hare/dialects/postgresql/schema/postgresql_schema_editor.py +280 -0
- hare/dialects/postgresql/schema/relations/__init__.py +1 -0
- hare/dialects/postgresql/schema/relations/postgresql_foreign_key_rebuild.py +230 -0
- hare/dialects/postgresql/schema/runtime_statements/__init__.py +1 -0
- hare/dialects/postgresql/schema/runtime_statements/postgresql_foreign_key_deferral.py +109 -0
- hare/dialects/postgresql/schema/runtime_statements/postgresql_table_clearing.py +80 -0
- hare/dialects/postgresql/schema/runtime_statements/postgresql_table_locks.py +27 -0
- hare/dialects/postgresql/schema/runtime_statements/postgresql_tenant_conditions.py +34 -0
- hare/dialects/postgresql/schema/schema_objects/__init__.py +1 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_database_functions.py +95 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_enum_types.py +130 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_extensions.py +35 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_grants.py +89 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_materialized_views.py +107 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_row_level_security_policies.py +125 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_schemas.py +51 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_sequences.py +132 -0
- hare/dialects/postgresql/schema/schema_objects/postgresql_views.py +53 -0
- hare/dialects/postgresql/schema/shadow/__init__.py +0 -0
- hare/dialects/postgresql/schema/shadow/postgresql_shadow_database.py +78 -0
- hare/dialects/postgresql/schema/tables/__init__.py +1 -0
- hare/dialects/postgresql/schema/tables/postgresql_table_comments.py +74 -0
- hare/dialects/postgresql/schema/tables/postgresql_table_partitions.py +229 -0
- hare/dialects/postgresql/schema/tables/postgresql_table_rebuild.py +118 -0
- hare/dialects/postgresql/schema/triggers/__init__.py +1 -0
- hare/dialects/postgresql/schema/triggers/postgresql_trigger_statements.py +141 -0
- hare/dialects/postgresql/search/__init__.py +8 -0
- hare/dialects/postgresql/search/constants.py +43 -0
- hare/dialects/postgresql/search/criterion/__init__.py +14 -0
- hare/dialects/postgresql/search/criterion/declarations.py +14 -0
- hare/dialects/postgresql/search/criterion/search_criterion.py +62 -0
- hare/dialects/postgresql/search/criterion/ts_query_function.py +20 -0
- hare/dialects/postgresql/search/criterion/ts_query_invert.py +32 -0
- hare/dialects/postgresql/search/enums.py +12 -0
- hare/dialects/postgresql/search/functions/__init__.py +9 -0
- hare/dialects/postgresql/search/functions/plain_to_ts_query.py +18 -0
- hare/dialects/postgresql/search/functions/to_ts_vector.py +20 -0
- hare/dialects/postgresql/search/lexemes/__init__.py +1 -0
- hare/dialects/postgresql/search/lexemes/combined_lexeme.py +35 -0
- hare/dialects/postgresql/search/lexemes/lexeme.py +77 -0
- hare/dialects/postgresql/search/lexemes/lexeme_combinable.py +59 -0
- hare/dialects/postgresql/search/postgresql_text_search.py +237 -0
- hare/dialects/postgresql/search/ts_vector_expression_reader.py +106 -0
- hare/dialects/postgresql/server_versions.py +26 -0
- hare/dialects/postgresql/spatial/__init__.py +7 -0
- hare/dialects/postgresql/spatial/constants.py +118 -0
- hare/dialects/postgresql/spatial/postgresql_spatial_renderers.py +102 -0
- hare/dialects/postgresql/transactions/__init__.py +1 -0
- hare/dialects/postgresql/transactions/constants.py +21 -0
- hare/dialects/postgresql/transactions/postgresql_transaction_statements.py +40 -0
- hare/dialects/postgresql/transactions/postgresql_two_phase_commit.py +87 -0
- hare/dialects/postgresql/types/__init__.py +1 -0
- hare/dialects/postgresql/types/postgresql_container_values.py +104 -0
- hare/dialects/postgresql/types/postgresql_types.py +213 -0
- hare/dialects/postgresql/validators/__init__.py +15 -0
- hare/dialects/postgresql/validators/keys_validator.py +32 -0
- hare/dialects/postgresql/validators/range_bound_validator.py +33 -0
- hare/dialects/postgresql/validators/range_max_value_validator.py +17 -0
- hare/dialects/postgresql/validators/range_min_value_validator.py +17 -0
- hare/dialects/postgresql/vectors/__init__.py +1 -0
- hare/dialects/postgresql/vectors/constants.py +13 -0
- hare/dialects/postgresql/vectors/postgresql_vector_renderers.py +40 -0
- hare/dialects/postgresql/vectors/postgresql_vector_values.py +94 -0
- hare/dialects/sqlite/__init__.py +0 -0
- hare/dialects/sqlite/clauses/__init__.py +1 -0
- hare/dialects/sqlite/clauses/constants.py +7 -0
- hare/dialects/sqlite/clauses/sqlite_query_clauses.py +100 -0
- hare/dialects/sqlite/client/__init__.py +12 -0
- hare/dialects/sqlite/client/constants.py +103 -0
- hare/dialects/sqlite/client/declarations.py +27 -0
- hare/dialects/sqlite/client/sqlite_client.py +507 -0
- hare/dialects/sqlite/client/sqlite_migration_lock.py +76 -0
- hare/dialects/sqlite/client/sqlite_transaction_client.py +160 -0
- hare/dialects/sqlite/connection/__init__.py +1 -0
- hare/dialects/sqlite/connection/constants.py +7 -0
- hare/dialects/sqlite/connection/sqlite_driver.py +59 -0
- hare/dialects/sqlite/constants.py +451 -0
- hare/dialects/sqlite/drivers/__init__.py +1 -0
- hare/dialects/sqlite/drivers/aiosqlite/__init__.py +1 -0
- hare/dialects/sqlite/drivers/aiosqlite/aiosqlite_driver.py +41 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/__init__.py +23 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_client.py +428 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_client_with_regexp_support.py +16 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_connection_wrapper.py +62 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_statement_timeout_connection_wrapper.py +53 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_transaction_client.py +176 -0
- hare/dialects/sqlite/drivers/aiosqlite/client/aiosqlite_transaction_connection_wrapper.py +23 -0
- hare/dialects/sqlite/drivers/aiosqlite/constants.py +11 -0
- hare/dialects/sqlite/drivers/constants.py +19 -0
- hare/dialects/sqlite/enums.py +37 -0
- hare/dialects/sqlite/exceptions.py +10 -0
- hare/dialects/sqlite/functions/__init__.py +0 -0
- hare/dialects/sqlite/functions/comparison/__init__.py +11 -0
- hare/dialects/sqlite/functions/comparison/sqlite_cast.py +204 -0
- hare/dialects/sqlite/functions/comparison/sqlite_greatest_least.py +63 -0
- hare/dialects/sqlite/functions/constants.py +102 -0
- hare/dialects/sqlite/functions/datetime/__init__.py +13 -0
- hare/dialects/sqlite/functions/datetime/date_truncation.py +115 -0
- hare/dialects/sqlite/functions/datetime/sqlite_date_part_extraction.py +77 -0
- hare/dialects/sqlite/functions/datetime/sqlite_date_timestamp.py +48 -0
- hare/dialects/sqlite/functions/datetime/sqlite_local_now.py +54 -0
- hare/dialects/sqlite/functions/datetime/temporal_arithmetic_functions.py +147 -0
- hare/dialects/sqlite/functions/decimal/__init__.py +1 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_arithmetic.py +152 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_average.py +23 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_collation.py +125 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_comparand.py +23 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_operation.py +33 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_round.py +50 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_storage.py +77 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_sum.py +62 -0
- hare/dialects/sqlite/functions/decimal/sqlite_decimal_text.py +22 -0
- hare/dialects/sqlite/functions/decimal/sqlite_stored_decimal.py +29 -0
- hare/dialects/sqlite/functions/json/__init__.py +9 -0
- hare/dialects/sqlite/functions/json/sqlite_json_datetime.py +124 -0
- hare/dialects/sqlite/functions/json/sqlite_json_path.py +116 -0
- hare/dialects/sqlite/functions/regex/__init__.py +5 -0
- hare/dialects/sqlite/functions/regex/sqlite_posix_regex.py +102 -0
- hare/dialects/sqlite/functions/regex/sqlite_regex_criterion.py +18 -0
- hare/dialects/sqlite/functions/sqlite_checked_integer.py +15 -0
- hare/dialects/sqlite/functions/sqlite_collation.py +51 -0
- hare/dialects/sqlite/functions/sqlite_connection_function.py +17 -0
- hare/dialects/sqlite/functions/sqlite_function_errors.py +45 -0
- hare/dialects/sqlite/functions/sqlite_integer_range.py +48 -0
- hare/dialects/sqlite/functions/sqlite_math_functions.py +233 -0
- hare/dialects/sqlite/functions/sqlite_native_functions.py +12 -0
- hare/dialects/sqlite/functions/sqlite_sort_keys.py +58 -0
- hare/dialects/sqlite/functions/statistics/__init__.py +19 -0
- hare/dialects/sqlite/functions/statistics/declarations.py +31 -0
- hare/dialects/sqlite/functions/statistics/sqlite_statistic.py +118 -0
- hare/dialects/sqlite/functions/statistics/sqlite_statistics.py +51 -0
- hare/dialects/sqlite/functions/text/__init__.py +1 -0
- hare/dialects/sqlite/functions/text/sqlite_text_functions.py +140 -0
- hare/dialects/sqlite/indexes/__init__.py +7 -0
- hare/dialects/sqlite/indexes/constants.py +45 -0
- hare/dialects/sqlite/indexes/full_text_index.py +228 -0
- hare/dialects/sqlite/indexes/separate_table_index.py +105 -0
- hare/dialects/sqlite/indexes/spatialite_index.py +228 -0
- hare/dialects/sqlite/literals/__init__.py +1 -0
- hare/dialects/sqlite/literals/sqlite_literals.py +51 -0
- hare/dialects/sqlite/lookups/__init__.py +0 -0
- hare/dialects/sqlite/lookups/constants.py +18 -0
- hare/dialects/sqlite/lookups/in_list/__init__.py +11 -0
- hare/dialects/sqlite/lookups/in_list/json_array_row_values.py +39 -0
- hare/dialects/sqlite/lookups/in_list/json_array_values.py +116 -0
- hare/dialects/sqlite/lookups/in_list/sqlite_large_in_list.py +96 -0
- hare/dialects/sqlite/lookups/json/__init__.py +1 -0
- hare/dialects/sqlite/lookups/json/sqlite_json_filter_guards.py +128 -0
- hare/dialects/sqlite/lookups/json/sqlite_json_lookups.py +51 -0
- hare/dialects/sqlite/lookups/json/sqlite_json_path_lookups.py +56 -0
- hare/dialects/sqlite/lookups/json/sqlite_json_type_criterion.py +13 -0
- hare/dialects/sqlite/lookups/sqlite_filter_operators.py +89 -0
- hare/dialects/sqlite/migration_safety/__init__.py +9 -0
- hare/dialects/sqlite/migration_safety/sqlite_migration_safety_rules.py +32 -0
- hare/dialects/sqlite/parameters/__init__.py +1 -0
- hare/dialects/sqlite/parameters/constants.py +11 -0
- hare/dialects/sqlite/parameters/sqlite_parameter_adapters.py +61 -0
- hare/dialects/sqlite/parameters/sqlite_parameters.py +27 -0
- hare/dialects/sqlite/query/__init__.py +7 -0
- hare/dialects/sqlite/query/declarations.py +13 -0
- hare/dialects/sqlite/renderers/__init__.py +7 -0
- hare/dialects/sqlite/renderers/constants.py +43 -0
- hare/dialects/sqlite/renderers/sqlite_defaults.py +84 -0
- hare/dialects/sqlite/renderers/sqlite_json_renderers.py +142 -0
- hare/dialects/sqlite/renderers/sqlite_number_renderers.py +137 -0
- hare/dialects/sqlite/renderers/sqlite_renderers.py +235 -0
- hare/dialects/sqlite/renderers/sqlite_temporal_renderers.py +138 -0
- hare/dialects/sqlite/renderers/sqlite_text_renderers.py +60 -0
- hare/dialects/sqlite/request_query/__init__.py +8 -0
- hare/dialects/sqlite/request_query/declarations.py +16 -0
- hare/dialects/sqlite/schema/__init__.py +0 -0
- hare/dialects/sqlite/schema/columns/__init__.py +1 -0
- hare/dialects/sqlite/schema/columns/sqlite_column_backfill.py +29 -0
- hare/dialects/sqlite/schema/columns/sqlite_column_conversion_check.py +181 -0
- hare/dialects/sqlite/schema/columns/sqlite_column_narrowing_check.py +24 -0
- hare/dialects/sqlite/schema/columns/sqlite_column_type_changes.py +148 -0
- hare/dialects/sqlite/schema/constants.py +108 -0
- hare/dialects/sqlite/schema/constraints/__init__.py +1 -0
- hare/dialects/sqlite/schema/constraints/sqlite_constraint_statements.py +32 -0
- hare/dialects/sqlite/schema/indexes/__init__.py +1 -0
- hare/dialects/sqlite/schema/indexes/sqlite_generated_index_names.py +61 -0
- hare/dialects/sqlite/schema/indexes/sqlite_index_statements.py +78 -0
- hare/dialects/sqlite/schema/relations/__init__.py +1 -0
- hare/dialects/sqlite/schema/relations/sqlite_foreign_key_rebuild.py +100 -0
- hare/dialects/sqlite/schema/runtime_statements/__init__.py +1 -0
- hare/dialects/sqlite/schema/runtime_statements/sqlite_foreign_key_deferral.py +87 -0
- hare/dialects/sqlite/schema/runtime_statements/sqlite_table_clearing.py +39 -0
- hare/dialects/sqlite/schema/runtime_statements/sqlite_tenant_conditions.py +21 -0
- hare/dialects/sqlite/schema/shadow/__init__.py +0 -0
- hare/dialects/sqlite/schema/shadow/sqlite_shadow_database.py +36 -0
- hare/dialects/sqlite/schema/sqlite_schema_editor.py +492 -0
- hare/dialects/sqlite/schema/tables/__init__.py +1 -0
- hare/dialects/sqlite/schema/tables/sqlite_table_comments.py +32 -0
- hare/dialects/sqlite/schema/tables/sqlite_table_rebuild.py +164 -0
- hare/dialects/sqlite/schema/triggers/__init__.py +1 -0
- hare/dialects/sqlite/schema/triggers/sqlite_trigger_statements.py +70 -0
- hare/dialects/sqlite/search/__init__.py +8 -0
- hare/dialects/sqlite/search/constants.py +33 -0
- hare/dialects/sqlite/search/sqlite_full_text_query.py +137 -0
- hare/dialects/sqlite/search/sqlite_search_renderers.py +33 -0
- hare/dialects/sqlite/search/sqlite_text_search.py +308 -0
- hare/dialects/sqlite/search/terms/__init__.py +1 -0
- hare/dialects/sqlite/search/terms/full_text_headline.py +56 -0
- hare/dialects/sqlite/search/terms/full_text_match.py +73 -0
- hare/dialects/sqlite/search/terms/full_text_query.py +42 -0
- hare/dialects/sqlite/search/terms/full_text_query_combination.py +82 -0
- hare/dialects/sqlite/search/terms/full_text_rank.py +34 -0
- hare/dialects/sqlite/search/terms/full_text_row_value.py +104 -0
- hare/dialects/sqlite/server_versions.py +17 -0
- hare/dialects/sqlite/spatial/__init__.py +0 -0
- hare/dialects/sqlite/spatial/constants.py +173 -0
- hare/dialects/sqlite/spatial/spatialite_blob_reader.py +166 -0
- hare/dialects/sqlite/spatial/spatialite_blob_writer.py +105 -0
- hare/dialects/sqlite/spatial/sqlite_geometry_values.py +75 -0
- hare/dialects/sqlite/spatial/sqlite_spatial_extension.py +116 -0
- hare/dialects/sqlite/spatial/sqlite_spatial_renderers.py +202 -0
- hare/dialects/sqlite/sqlite_dialect.py +138 -0
- hare/dialects/sqlite/sqlite_introspector.py +1025 -0
- hare/dialects/sqlite/sqlite_table_options.py +92 -0
- hare/dialects/sqlite/table_option_constants.py +15 -0
- hare/dialects/sqlite/transactions/__init__.py +1 -0
- hare/dialects/sqlite/transactions/constants.py +10 -0
- hare/dialects/sqlite/transactions/sqlite_transaction_statements.py +19 -0
- hare/dialects/sqlite/types/__init__.py +1 -0
- hare/dialects/sqlite/types/sqlite_types.py +87 -0
- hare/dialects/sqlite/vectors/__init__.py +1 -0
- hare/dialects/sqlite/vectors/constants.py +16 -0
- hare/dialects/sqlite/vectors/sqlite_vector_extension.py +112 -0
- hare/dialects/sqlite/vectors/sqlite_vector_renderers.py +55 -0
- hare/dialects/sqlite/vectors/sqlite_vector_values.py +113 -0
- hare/exceptions.py +397 -0
- hare/fields/__init__.py +133 -0
- hare/fields/composite_primary_key.py +40 -0
- hare/fields/constants.py +120 -0
- hare/fields/data/__init__.py +3 -0
- hare/fields/data/binary_field.py +62 -0
- hare/fields/data/boolean_field.py +57 -0
- hare/fields/data/choices/__init__.py +16 -0
- hare/fields/data/choices/char_enum_field.py +27 -0
- hare/fields/data/choices/char_enum_field_instance.py +117 -0
- hare/fields/data/choices/int_enum_field.py +23 -0
- hare/fields/data/choices/int_enum_field_instance.py +102 -0
- hare/fields/data/constants.py +122 -0
- hare/fields/data/containers/__init__.py +10 -0
- hare/fields/data/containers/array_field.py +152 -0
- hare/fields/data/containers/constants.py +25 -0
- hare/fields/data/containers/container_field.py +342 -0
- hare/fields/data/containers/declarations.py +13 -0
- hare/fields/data/containers/map_field.py +165 -0
- hare/fields/data/containers/nested_field.py +47 -0
- hare/fields/data/containers/tuple_field.py +177 -0
- hare/fields/data/json/__init__.py +7 -0
- hare/fields/data/json/json_codec.py +152 -0
- hare/fields/data/json/json_field.py +387 -0
- hare/fields/data/json/json_path_field.py +77 -0
- hare/fields/data/json/json_text_field.py +13 -0
- hare/fields/data/network/__init__.py +8 -0
- hare/fields/data/network/constants.py +6 -0
- hare/fields/data/network/ip_address_field.py +109 -0
- hare/fields/data/network/ipv4_address_field.py +26 -0
- hare/fields/data/numeric/__init__.py +23 -0
- hare/fields/data/numeric/big_int_field.py +22 -0
- hare/fields/data/numeric/decimal_field.py +187 -0
- hare/fields/data/numeric/float_field.py +83 -0
- hare/fields/data/numeric/int_field.py +239 -0
- hare/fields/data/numeric/positive_big_int_field.py +19 -0
- hare/fields/data/numeric/positive_int_field.py +19 -0
- hare/fields/data/numeric/positive_small_int_field.py +19 -0
- hare/fields/data/numeric/small_int_field.py +22 -0
- hare/fields/data/temporal/__init__.py +11 -0
- hare/fields/data/temporal/date_field.py +87 -0
- hare/fields/data/temporal/datetime_field.py +384 -0
- hare/fields/data/temporal/parse_datetime.py +17 -0
- hare/fields/data/temporal/temporal_values.py +119 -0
- hare/fields/data/temporal/time_delta_field.py +111 -0
- hare/fields/data/temporal/time_field.py +193 -0
- hare/fields/data/text/__init__.py +20 -0
- hare/fields/data/text/char_field.py +78 -0
- hare/fields/data/text/email_field.py +76 -0
- hare/fields/data/text/phone_field.py +114 -0
- hare/fields/data/text/slug_field.py +52 -0
- hare/fields/data/text/text_field.py +33 -0
- hare/fields/data/text/text_values.py +39 -0
- hare/fields/data/text/url_field.py +62 -0
- hare/fields/data/uuid_field.py +82 -0
- hare/fields/database_default.py +28 -0
- hare/fields/db_default_not_set.py +36 -0
- hare/fields/db_defaults/__init__.py +13 -0
- hare/fields/db_defaults/now.py +108 -0
- hare/fields/db_defaults/random_hex.py +30 -0
- hare/fields/db_defaults/sql_default.py +95 -0
- hare/fields/db_defaults/uuid_v7.py +36 -0
- hare/fields/encrypted/__init__.py +7 -0
- hare/fields/encrypted/blind_index_field.py +49 -0
- hare/fields/encrypted/constants.py +41 -0
- hare/fields/encrypted/encrypted_field_base.py +143 -0
- hare/fields/encrypted/encrypted_json_field.py +238 -0
- hare/fields/encrypted/encrypted_text_field.py +130 -0
- hare/fields/encrypted/field_encryption.py +267 -0
- hare/fields/enums.py +91 -0
- hare/fields/field.py +1231 -0
- hare/fields/field_meta.py +16 -0
- hare/fields/generated_field.py +211 -0
- hare/fields/narrowing/__init__.py +7 -0
- hare/fields/narrowing/decimal_digits_limit.py +11 -0
- hare/fields/narrowing/enum_values_limit.py +32 -0
- hare/fields/narrowing/integer_range_limit.py +13 -0
- hare/fields/narrowing/narrowing_limit.py +8 -0
- hare/fields/narrowing/text_length_limit.py +13 -0
- hare/fields/registrations/__init__.py +1 -0
- hare/fields/registrations/registered_lookup.py +29 -0
- hare/fields/registrations/registered_transform.py +22 -0
- hare/fields/relations/__init__.py +3 -0
- hare/fields/relations/constants.py +10 -0
- hare/fields/relations/declarations.py +5 -0
- hare/fields/relations/fields/__init__.py +35 -0
- hare/fields/relations/fields/backward_foreign_key_relation.py +46 -0
- hare/fields/relations/fields/declarations.py +21 -0
- hare/fields/relations/fields/foreign_key_field.py +89 -0
- hare/fields/relations/fields/foreign_key_field_instance.py +124 -0
- hare/fields/relations/fields/generic_foreign_key_field.py +56 -0
- hare/fields/relations/fields/generic_foreign_key_field_instance.py +455 -0
- hare/fields/relations/fields/many_to_many_field.py +60 -0
- hare/fields/relations/fields/many_to_many_field_instance.py +126 -0
- hare/fields/relations/fields/one_to_one_field.py +89 -0
- hare/fields/relations/fields/one_to_one_field_instance.py +45 -0
- hare/fields/relations/fields/relational_field.py +153 -0
- hare/fields/relations/inherited_relation.py +30 -0
- hare/fields/relations/relation_accessors.py +271 -0
- hare/fields/relations/relation_values.py +106 -0
- hare/fields/relations/swappable_model_reference.py +60 -0
- hare/fields/validators/__init__.py +63 -0
- hare/fields/validators/exceptions.py +52 -0
- hare/fields/validators/formats/__init__.py +1 -0
- hare/fields/validators/formats/comma_separated_integer_list_validator.py +22 -0
- hare/fields/validators/formats/domain_name_validator.py +74 -0
- hare/fields/validators/formats/e164_phone_validator.py +32 -0
- hare/fields/validators/formats/email_validator.py +87 -0
- hare/fields/validators/formats/ipv46_validator.py +28 -0
- hare/fields/validators/formats/ipv4_validator.py +23 -0
- hare/fields/validators/formats/ipv6_validator.py +23 -0
- hare/fields/validators/formats/regex_validator.py +38 -0
- hare/fields/validators/formats/slug_validator.py +36 -0
- hare/fields/validators/formats/url_validator.py +95 -0
- hare/fields/validators/limits/__init__.py +1 -0
- hare/fields/validators/limits/length_validator.py +17 -0
- hare/fields/validators/limits/max_digits_validator.py +58 -0
- hare/fields/validators/limits/max_length_validator.py +20 -0
- hare/fields/validators/limits/max_value_validator.py +19 -0
- hare/fields/validators/limits/min_length_validator.py +20 -0
- hare/fields/validators/limits/min_value_validator.py +19 -0
- hare/fields/validators/limits/numeric_validator.py +19 -0
- hare/fields/validators/validator.py +34 -0
- hare/gis/__init__.py +52 -0
- hare/gis/aggregates/__init__.py +5 -0
- hare/gis/aggregates/declarations.py +42 -0
- hare/gis/aggregates/spatial_aggregate.py +57 -0
- hare/gis/constants.py +126 -0
- hare/gis/enums.py +74 -0
- hare/gis/fields/__init__.py +23 -0
- hare/gis/fields/declarations.py +61 -0
- hare/gis/fields/extent_field.py +60 -0
- hare/gis/fields/geometry_field.py +239 -0
- hare/gis/fields/made_line_field.py +86 -0
- hare/gis/functions/__init__.py +53 -0
- hare/gis/functions/buffer.py +29 -0
- hare/gis/functions/constants.py +17 -0
- hare/gis/functions/declarations.py +188 -0
- hare/gis/functions/simplify.py +29 -0
- hare/gis/functions/spatial_function.py +115 -0
- hare/gis/functions/transform.py +41 -0
- hare/gis/geometries/__init__.py +19 -0
- hare/gis/geometries/declarations.py +38 -0
- hare/gis/geometries/geometry.py +297 -0
- hare/gis/geometries/geometry_collection.py +62 -0
- hare/gis/geometries/line_string.py +46 -0
- hare/gis/geometries/multi_geometry.py +75 -0
- hare/gis/geometries/point.py +65 -0
- hare/gis/geometries/polygon.py +89 -0
- hare/gis/lookups/__init__.py +3 -0
- hare/gis/lookups/spatial_field_lookups.py +219 -0
- hare/gis/readers/__init__.py +11 -0
- hare/gis/readers/constants.py +15 -0
- hare/gis/readers/ewkb_reader.py +148 -0
- hare/gis/readers/geo_json_reader.py +54 -0
- hare/gis/readers/wkt_reader.py +226 -0
- hare/gis/spatial_features.py +57 -0
- hare/gis/terms/__init__.py +11 -0
- hare/gis/terms/geometry_value.py +33 -0
- hare/gis/terms/spatial_aggregate_function.py +30 -0
- hare/gis/terms/spatial_function_term.py +39 -0
- hare/gis/terms/spatial_relation_term.py +39 -0
- hare/health/__init__.py +19 -0
- hare/health/constants.py +32 -0
- hare/health/criteria/__init__.py +27 -0
- hare/health/criteria/acquire_wait_time.py +35 -0
- hare/health/criteria/all_of.py +38 -0
- hare/health/criteria/declarations.py +33 -0
- hare/health/criteria/health_criterion.py +87 -0
- hare/health/criteria/ping_failed.py +27 -0
- hare/health/criteria/ping_latency.py +29 -0
- hare/health/criteria/pool_count_criterion.py +37 -0
- hare/health/criteria/pool_saturation.py +35 -0
- hare/health/criteria/waiting_requests.py +33 -0
- hare/health/declarations.py +83 -0
- hare/health/enums.py +14 -0
- hare/health/health_check.py +240 -0
- hare/health/health_report.py +65 -0
- hare/inspectdb/__init__.py +38 -0
- hare/inspectdb/constants.py +60 -0
- hare/inspectdb/exceptions.py +72 -0
- hare/inspectdb/generation/__init__.py +1 -0
- hare/inspectdb/generation/column_type_mapper.py +113 -0
- hare/inspectdb/generation/declarations.py +34 -0
- hare/inspectdb/generation/inspected_model.py +35 -0
- hare/inspectdb/generation/inspected_model_builder.py +1174 -0
- hare/inspectdb/generation/many_to_many_tables.py +91 -0
- hare/inspectdb/generation/model_factory.py +88 -0
- hare/inspectdb/generation/model_naming.py +75 -0
- hare/inspectdb/generation/model_source_builder.py +148 -0
- hare/inspectdb/introspection/__init__.py +28 -0
- hare/inspectdb/introspection/column_info.py +67 -0
- hare/inspectdb/introspection/composite_foreign_key_info.py +27 -0
- hare/inspectdb/introspection/database_catalog.py +252 -0
- hare/inspectdb/introspection/enums.py +26 -0
- hare/inspectdb/introspection/foreign_key_info.py +25 -0
- hare/inspectdb/introspection/index_info.py +265 -0
- hare/inspectdb/introspection/inspected_field_specification.py +47 -0
- hare/inspectdb/introspection/schema_introspector.py +564 -0
- hare/inspectdb/introspection/schema_part.py +103 -0
- hare/inspectdb/introspection/table_info.py +112 -0
- hare/inspectdb/introspection/table_parts.py +101 -0
- hare/inspectdb/schema_inspector.py +224 -0
- hare/instrumentation/__init__.py +31 -0
- hare/instrumentation/capture/__init__.py +9 -0
- hare/instrumentation/capture/capture_needs.py +54 -0
- hare/instrumentation/capture/captured_change.py +38 -0
- hare/instrumentation/capture/captured_write.py +223 -0
- hare/instrumentation/capture/change_capturing.py +496 -0
- hare/instrumentation/capture/change_sink.py +57 -0
- hare/instrumentation/change_events.py +246 -0
- hare/instrumentation/constants.py +41 -0
- hare/instrumentation/declarations.py +196 -0
- hare/instrumentation/enums.py +35 -0
- hare/instrumentation/observers/__init__.py +1 -0
- hare/instrumentation/observers/observer.py +56 -0
- hare/instrumentation/observers/observer_dispatch.py +197 -0
- hare/instrumentation/observers/observer_set.py +138 -0
- hare/instrumentation/observers/observers.py +368 -0
- hare/instrumentation/pools/__init__.py +1 -0
- hare/instrumentation/pools/duration_records.py +50 -0
- hare/instrumentation/pools/pool_metrics.py +50 -0
- hare/instrumentation/pools/pool_registry.py +49 -0
- hare/instrumentation/queries/__init__.py +1 -0
- hare/instrumentation/queries/query_tags.py +133 -0
- hare/instrumentation/queries/query_wrapper.py +37 -0
- hare/lazy_loading/__init__.py +1 -0
- hare/lazy_loading/lazy_pattern.py +45 -0
- hare/lazy_loading/pydantic_classes.py +96 -0
- hare/migrations/__init__.py +90 -0
- hare/migrations/api/__init__.py +24 -0
- hare/migrations/api/checkmigrations.py +55 -0
- hare/migrations/api/makemigrations.py +78 -0
- hare/migrations/api/migrate.py +47 -0
- hare/migrations/api/migration_request_parser.py +86 -0
- hare/migrations/api/plan.py +39 -0
- hare/migrations/api/sqlmigrate.py +51 -0
- hare/migrations/api/squashmigrations.py +51 -0
- hare/migrations/autodetection/__init__.py +4 -0
- hare/migrations/autodetection/constants.py +49 -0
- hare/migrations/autodetection/diffs/__init__.py +1 -0
- hare/migrations/autodetection/diffs/constraint_diff.py +48 -0
- hare/migrations/autodetection/diffs/declarations.py +73 -0
- hare/migrations/autodetection/diffs/declared_schema_object_diff.py +47 -0
- hare/migrations/autodetection/diffs/grant_diff.py +24 -0
- hare/migrations/autodetection/diffs/index_diff.py +73 -0
- hare/migrations/autodetection/diffs/materialized_view_diff.py +44 -0
- hare/migrations/autodetection/diffs/partition_diff.py +99 -0
- hare/migrations/autodetection/diffs/schema_object_diff.py +153 -0
- hare/migrations/autodetection/diffs/state_field_diff.py +566 -0
- hare/migrations/autodetection/diffs/state_model_diff.py +355 -0
- hare/migrations/autodetection/diffs/trigger_diff.py +31 -0
- hare/migrations/autodetection/diffs/view_diff.py +24 -0
- hare/migrations/autodetection/field_comparable_values.py +20 -0
- hare/migrations/autodetection/migration_autodetector.py +337 -0
- hare/migrations/autodetection/migration_splitter.py +151 -0
- hare/migrations/autodetection/operation_generator.py +1115 -0
- hare/migrations/autodetection/operation_sorter.py +213 -0
- hare/migrations/autodetection/rename_questions.py +98 -0
- hare/migrations/autodetection/required_extensions.py +118 -0
- hare/migrations/autodetection/schema_object_operations.py +150 -0
- hare/migrations/autodetection/split_migration.py +24 -0
- hare/migrations/autodetection/state_signatures.py +192 -0
- hare/migrations/constants.py +109 -0
- hare/migrations/drift/__init__.py +13 -0
- hare/migrations/drift/column_mismatch.py +14 -0
- hare/migrations/drift/constants.py +43 -0
- hare/migrations/drift/detect_drift.py +40 -0
- hare/migrations/drift/detect_drift_for_alias.py +87 -0
- hare/migrations/drift/drift_result.py +22 -0
- hare/migrations/drift/shadow/__init__.py +0 -0
- hare/migrations/drift/shadow/column_field_names.py +26 -0
- hare/migrations/drift/shadow/schema_comparison.py +557 -0
- hare/migrations/drift/shadow/shadow_drift.py +318 -0
- hare/migrations/drift/shadow/shadow_state.py +83 -0
- hare/migrations/exceptions.py +69 -0
- hare/migrations/execution/__init__.py +3 -0
- hare/migrations/execution/connections_plan.py +192 -0
- hare/migrations/execution/constants.py +4 -0
- hare/migrations/execution/executor/__init__.py +11 -0
- hare/migrations/execution/executor/migration_executor.py +640 -0
- hare/migrations/execution/executor/migration_target.py +9 -0
- hare/migrations/execution/executor/plan_step.py +30 -0
- hare/migrations/execution/migration_runner.py +304 -0
- hare/migrations/execution/swappable_setting_check.py +161 -0
- hare/migrations/loading/__init__.py +4 -0
- hare/migrations/loading/graph/__init__.py +13 -0
- hare/migrations/loading/graph/dummy_node.py +22 -0
- hare/migrations/loading/graph/migration_graph.py +235 -0
- hare/migrations/loading/graph/migration_key.py +14 -0
- hare/migrations/loading/graph/node.py +40 -0
- hare/migrations/loading/migration_loader.py +256 -0
- hare/migrations/loading/migrations_modules.py +207 -0
- hare/migrations/loading/recorder/__init__.py +9 -0
- hare/migrations/loading/recorder/migration_recorder.py +130 -0
- hare/migrations/loading/recorder/noop_recorder.py +26 -0
- hare/migrations/making/__init__.py +1 -0
- hare/migrations/making/declared_attribute_values.py +27 -0
- hare/migrations/making/migration_changes.py +27 -0
- hare/migrations/making/migration_checks.py +115 -0
- hare/migrations/making/migration_maker.py +291 -0
- hare/migrations/making/migration_optimizer.py +70 -0
- hare/migrations/making/migration_squasher.py +193 -0
- hare/migrations/making/squashed_migration.py +24 -0
- hare/migrations/migration.py +341 -0
- hare/migrations/operations/__init__.py +132 -0
- hare/migrations/operations/columns/__init__.py +11 -0
- hare/migrations/operations/columns/alter_column_not_null_safe.py +140 -0
- hare/migrations/operations/columns/backfill_column.py +118 -0
- hare/migrations/operations/constants.py +20 -0
- hare/migrations/operations/constraints/__init__.py +15 -0
- hare/migrations/operations/constraints/add_constraint.py +129 -0
- hare/migrations/operations/constraints/declarations.py +13 -0
- hare/migrations/operations/constraints/rename_constraint.py +21 -0
- hare/migrations/operations/constraints/validate_constraint.py +66 -0
- hare/migrations/operations/database_functions/__init__.py +10 -0
- hare/migrations/operations/database_functions/add_function.py +28 -0
- hare/migrations/operations/database_functions/alter_function.py +30 -0
- hare/migrations/operations/database_functions/remove_function.py +20 -0
- hare/migrations/operations/database_functions/rename_function.py +21 -0
- hare/migrations/operations/declared_uniqueness_checks.py +76 -0
- hare/migrations/operations/dependencies/__init__.py +1 -0
- hare/migrations/operations/dependencies/operation_dependency.py +89 -0
- hare/migrations/operations/dependencies/relation_dependencies.py +157 -0
- hare/migrations/operations/dictionaries/__init__.py +10 -0
- hare/migrations/operations/dictionaries/add_dictionary.py +28 -0
- hare/migrations/operations/dictionaries/alter_dictionary.py +29 -0
- hare/migrations/operations/dictionaries/remove_dictionary.py +20 -0
- hare/migrations/operations/dictionaries/rename_dictionary.py +21 -0
- hare/migrations/operations/enum_types/__init__.py +7 -0
- hare/migrations/operations/enum_types/alter_enum_type.py +64 -0
- hare/migrations/operations/enum_types/create_enum_type.py +57 -0
- hare/migrations/operations/enum_types/drop_enum_type.py +66 -0
- hare/migrations/operations/enum_types/enum_type_operation.py +35 -0
- hare/migrations/operations/enums.py +24 -0
- hare/migrations/operations/extensions/__init__.py +15 -0
- hare/migrations/operations/extensions/create_collation.py +82 -0
- hare/migrations/operations/extensions/create_extension.py +47 -0
- hare/migrations/operations/extensions/remove_collation.py +35 -0
- hare/migrations/operations/extensions/remove_extension.py +40 -0
- hare/migrations/operations/fields/__init__.py +11 -0
- hare/migrations/operations/fields/add_field.py +135 -0
- hare/migrations/operations/fields/alter_field.py +128 -0
- hare/migrations/operations/fields/field_add_remove_operation.py +41 -0
- hare/migrations/operations/fields/field_like.py +14 -0
- hare/migrations/operations/fields/remove_field.py +326 -0
- hare/migrations/operations/fields/rename_field.py +725 -0
- hare/migrations/operations/grants/__init__.py +8 -0
- hare/migrations/operations/grants/add_grant.py +31 -0
- hare/migrations/operations/grants/remove_grant.py +35 -0
- hare/migrations/operations/hare_operation.py +174 -0
- hare/migrations/operations/indexes/__init__.py +13 -0
- hare/migrations/operations/indexes/add_index.py +42 -0
- hare/migrations/operations/indexes/declarations.py +12 -0
- hare/migrations/operations/indexes/remove_index.py +36 -0
- hare/migrations/operations/materialized_views/__init__.py +17 -0
- hare/migrations/operations/materialized_views/add_materialized_view.py +37 -0
- hare/migrations/operations/materialized_views/alter_materialized_view.py +32 -0
- hare/migrations/operations/materialized_views/refresh_materialized_view.py +57 -0
- hare/migrations/operations/materialized_views/remove_materialized_view.py +28 -0
- hare/migrations/operations/materialized_views/rename_materialized_view.py +23 -0
- hare/migrations/operations/model_bound_operation.py +95 -0
- hare/migrations/operations/models/__init__.py +12 -0
- hare/migrations/operations/models/alter_model_options.py +158 -0
- hare/migrations/operations/models/alter_model_schema.py +114 -0
- hare/migrations/operations/models/alter_model_table.py +65 -0
- hare/migrations/operations/models/create_model.py +407 -0
- hare/migrations/operations/models/delete_model.py +122 -0
- hare/migrations/operations/models/model_table_operation.py +45 -0
- hare/migrations/operations/models/rename_model.py +165 -0
- hare/migrations/operations/models/table_renaming_operation.py +101 -0
- hare/migrations/operations/operation.py +252 -0
- hare/migrations/operations/partitions/__init__.py +11 -0
- hare/migrations/operations/partitions/add_partition.py +36 -0
- hare/migrations/operations/partitions/partition_operation.py +93 -0
- hare/migrations/operations/partitions/remove_partition.py +36 -0
- hare/migrations/operations/policies/__init__.py +11 -0
- hare/migrations/operations/policies/add_policy.py +28 -0
- hare/migrations/operations/policies/alter_policy.py +30 -0
- hare/migrations/operations/policies/alter_row_level_security.py +90 -0
- hare/migrations/operations/policies/remove_policy.py +21 -0
- hare/migrations/operations/policies/rename_policy.py +21 -0
- hare/migrations/operations/schema_objects/__init__.py +11 -0
- hare/migrations/operations/schema_objects/add_schema_object.py +103 -0
- hare/migrations/operations/schema_objects/alter_schema_object.py +89 -0
- hare/migrations/operations/schema_objects/object_types/__init__.py +1 -0
- hare/migrations/operations/schema_objects/object_types/constraint_object_type.py +98 -0
- hare/migrations/operations/schema_objects/object_types/dictionary_object_type.py +51 -0
- hare/migrations/operations/schema_objects/object_types/function_object_type.py +55 -0
- hare/migrations/operations/schema_objects/object_types/grant_object_type.py +71 -0
- hare/migrations/operations/schema_objects/object_types/index_object_type.py +140 -0
- hare/migrations/operations/schema_objects/object_types/materialized_view_object_type.py +63 -0
- hare/migrations/operations/schema_objects/object_types/policy_object_type.py +53 -0
- hare/migrations/operations/schema_objects/object_types/schema_object_type.py +234 -0
- hare/migrations/operations/schema_objects/object_types/sequence_object_type.py +54 -0
- hare/migrations/operations/schema_objects/object_types/trigger_object_type.py +46 -0
- hare/migrations/operations/schema_objects/object_types/view_object_type.py +60 -0
- hare/migrations/operations/schema_objects/remove_schema_object.py +105 -0
- hare/migrations/operations/schema_objects/rename_schema_object.py +116 -0
- hare/migrations/operations/schemas/__init__.py +11 -0
- hare/migrations/operations/schemas/create_schema.py +45 -0
- hare/migrations/operations/schemas/drop_schema.py +40 -0
- hare/migrations/operations/sequences/__init__.py +10 -0
- hare/migrations/operations/sequences/add_sequence.py +28 -0
- hare/migrations/operations/sequences/alter_sequence.py +29 -0
- hare/migrations/operations/sequences/remove_sequence.py +20 -0
- hare/migrations/operations/sequences/rename_sequence.py +21 -0
- hare/migrations/operations/special/__init__.py +16 -0
- hare/migrations/operations/special/run_python.py +82 -0
- hare/migrations/operations/special/run_sql.py +107 -0
- hare/migrations/operations/special/separate_database_and_state.py +95 -0
- hare/migrations/operations/special/synchronize_key_series.py +51 -0
- hare/migrations/operations/triggers/__init__.py +15 -0
- hare/migrations/operations/triggers/add_trigger.py +28 -0
- hare/migrations/operations/triggers/alter_trigger.py +28 -0
- hare/migrations/operations/triggers/remove_trigger.py +20 -0
- hare/migrations/operations/triggers/rename_trigger.py +21 -0
- hare/migrations/operations/views/__init__.py +10 -0
- hare/migrations/operations/views/add_view.py +29 -0
- hare/migrations/operations/views/alter_view.py +29 -0
- hare/migrations/operations/views/remove_view.py +20 -0
- hare/migrations/operations/views/rename_view.py +21 -0
- hare/migrations/reports/__init__.py +12 -0
- hare/migrations/reports/operation_effect.py +28 -0
- hare/migrations/reports/operation_plan.py +23 -0
- hare/migrations/runtime_enums.py +88 -0
- hare/migrations/safety/__init__.py +16 -0
- hare/migrations/safety/enums.py +37 -0
- hare/migrations/safety/migration_risk.py +33 -0
- hare/migrations/safety/migration_safety_checker.py +250 -0
- hare/migrations/safety/migration_safety_context.py +142 -0
- hare/migrations/state/__init__.py +11 -0
- hare/migrations/state/model_state.py +359 -0
- hare/migrations/state/state.py +297 -0
- hare/migrations/state/state_apps.py +315 -0
- hare/migrations/state/state_rendering.py +222 -0
- hare/migrations/swappable_dependency.py +36 -0
- hare/migrations/writer/__init__.py +9 -0
- hare/migrations/writer/constants.py +28 -0
- hare/migrations/writer/import_manager.py +106 -0
- hare/migrations/writer/migration_writer.py +986 -0
- hare/models/__init__.py +20 -0
- hare/models/class_building/__init__.py +1 -0
- hare/models/class_building/abstract_meta_inheritance.py +116 -0
- hare/models/class_building/blind_indexes.py +54 -0
- hare/models/class_building/constants.py +61 -0
- hare/models/class_building/extension_model_options.py +20 -0
- hare/models/class_building/field_comments.py +131 -0
- hare/models/class_building/generic_foreign_keys.py +287 -0
- hare/models/class_building/instance_constructors.py +110 -0
- hare/models/class_building/lazy_relation_fields.py +140 -0
- hare/models/class_building/model_definition_checks.py +710 -0
- hare/models/class_building/model_field_collection.py +185 -0
- hare/models/class_building/model_managers.py +62 -0
- hare/models/class_building/primary_key_declaration.py +204 -0
- hare/models/class_building/schema_object_declarations.py +106 -0
- hare/models/constants.py +75 -0
- hare/models/deletion/__init__.py +0 -0
- hare/models/deletion/cascade/__init__.py +1 -0
- hare/models/deletion/cascade/cascade_deletion.py +818 -0
- hare/models/deletion/cascade/cascade_restore.py +150 -0
- hare/models/deletion/cascade/deletion_collector.py +646 -0
- hare/models/deletion/cascade/deletion_graph.py +418 -0
- hare/models/deletion/cascade/deletion_plan.py +94 -0
- hare/models/deletion/cascade/protect_constraint_deferral.py +91 -0
- hare/models/deletion/cascade/related_rows.py +417 -0
- hare/models/deletion/cascade/tenant_schema_visits.py +96 -0
- hare/models/deletion/constants.py +29 -0
- hare/models/deletion/instance_deletion.py +288 -0
- hare/models/deletion/preview/__init__.py +1 -0
- hare/models/deletion/preview/delete_preview.py +93 -0
- hare/models/deletion/preview/delete_preview_builder.py +431 -0
- hare/models/deletion/soft_deletion.py +207 -0
- hare/models/enums.py +76 -0
- hare/models/instances/__init__.py +1 -0
- hare/models/instances/dirty_fields.py +99 -0
- hare/models/instances/field_snapshot.py +116 -0
- hare/models/instances/instance_connections.py +61 -0
- hare/models/instances/instance_copies.py +46 -0
- hare/models/instances/instance_initialization.py +323 -0
- hare/models/instances/instance_refresh.py +158 -0
- hare/models/instances/instance_saving.py +512 -0
- hare/models/meta_info.py +1143 -0
- hare/models/model.py +935 -0
- hare/models/model_meta.py +255 -0
- hare/models/tenancy/__init__.py +1 -0
- hare/models/tenancy/constants.py +16 -0
- hare/models/tenancy/tenancy.py +363 -0
- hare/models/tenancy/tenant_row_level_security.py +76 -0
- hare/models/tenancy/tenant_schemas.py +232 -0
- hare/models/uniqueness/__init__.py +0 -0
- hare/models/uniqueness/declared_uniqueness.py +99 -0
- hare/models/write/__init__.py +3 -0
- hare/models/write/generated_keys.py +97 -0
- hare/models/write/insert/__init__.py +1 -0
- hare/models/write/insert/insert_conflict.py +88 -0
- hare/models/write/insert/insert_statement.py +155 -0
- hare/models/write/instance_capture.py +173 -0
- hare/models/write/instance_values.py +126 -0
- hare/models/write/instance_writer.py +949 -0
- hare/models/write/returned_values.py +98 -0
- hare/models/write/rollback_restores.py +213 -0
- hare/models/write/rules/__init__.py +2 -0
- hare/models/write/rules/constants.py +65 -0
- hare/models/write/rules/enums.py +18 -0
- hare/models/write/rules/relation_key_values.py +50 -0
- hare/models/write/rules/row_write_rules.py +635 -0
- hare/models/write/rules/tenant_write_rules.py +300 -0
- hare/models/write/rules/written_instances.py +37 -0
- hare/models/write/rules/written_target_checks.py +63 -0
- hare/models/write/update/__init__.py +1 -0
- hare/models/write/update/expression_assignment.py +162 -0
- hare/models/write/update/update_parameter_slot.py +43 -0
- hare/models/write/write_steps.py +98 -0
- hare/native/__init__.py +1 -0
- hare/native/native_modules.py +19 -0
- hare/numbers/__init__.py +1 -0
- hare/numbers/finite_numbers.py +27 -0
- hare/py.typed +0 -0
- hare/query/__init__.py +0 -0
- hare/query/constants.py +41 -0
- hare/query/enums.py +129 -0
- hare/query/expressions/__init__.py +63 -0
- hare/query/expressions/aggregate.py +442 -0
- hare/query/expressions/aggregate_paths/__init__.py +9 -0
- hare/query/expressions/aggregate_paths/aggregate_crossing.py +20 -0
- hare/query/expressions/aggregate_paths/aggregated_multi_valued_paths.py +581 -0
- hare/query/expressions/aggregate_paths/constants.py +10 -0
- hare/query/expressions/arithmetic/__init__.py +1 -0
- hare/query/expressions/arithmetic/arithmetic_operators.py +57 -0
- hare/query/expressions/arithmetic/combinable_expression.py +47 -0
- hare/query/expressions/arithmetic/combined_expression.py +614 -0
- hare/query/expressions/arithmetic/constants.py +37 -0
- hare/query/expressions/case/__init__.py +1 -0
- hare/query/expressions/case/case.py +230 -0
- hare/query/expressions/case/case_branch_value.py +14 -0
- hare/query/expressions/case/when.py +167 -0
- hare/query/expressions/compatibility/__init__.py +9 -0
- hare/query/expressions/compatibility/constants.py +107 -0
- hare/query/expressions/compatibility/output_field_compatibility.py +248 -0
- hare/query/expressions/compatibility/result_branch.py +46 -0
- hare/query/expressions/conditions/__init__.py +1 -0
- hare/query/expressions/conditions/q.py +525 -0
- hare/query/expressions/conditions/query_modifier.py +90 -0
- hare/query/expressions/constants.py +120 -0
- hare/query/expressions/declarations.py +12 -0
- hare/query/expressions/enums.py +39 -0
- hare/query/expressions/expression.py +129 -0
- hare/query/expressions/expression_context.py +63 -0
- hare/query/expressions/expression_result.py +41 -0
- hare/query/expressions/f.py +212 -0
- hare/query/expressions/frames/__init__.py +12 -0
- hare/query/expressions/frames/constants.py +14 -0
- hare/query/expressions/frames/declarations.py +22 -0
- hare/query/expressions/frames/window_frame.py +126 -0
- hare/query/expressions/function.py +490 -0
- hare/query/expressions/joins/__init__.py +1 -0
- hare/query/expressions/joins/array_join.py +147 -0
- hare/query/expressions/joins/array_join_element.py +27 -0
- hare/query/expressions/joins/asof_join.py +263 -0
- hare/query/expressions/joins/filtered_relation.py +338 -0
- hare/query/expressions/joins/json_table.py +147 -0
- hare/query/expressions/joins/json_table_column.py +21 -0
- hare/query/expressions/joins/lateral.py +88 -0
- hare/query/expressions/joins/merge_source_row.py +44 -0
- hare/query/expressions/joins/named_columns.py +43 -0
- hare/query/expressions/joins/named_join.py +204 -0
- hare/query/expressions/numeric/__init__.py +11 -0
- hare/query/expressions/numeric/numeric_type.py +18 -0
- hare/query/expressions/numeric/numeric_typing.py +216 -0
- hare/query/expressions/numeric/unrounded_decimal_field.py +16 -0
- hare/query/expressions/ordering.py +55 -0
- hare/query/expressions/raw_sql.py +168 -0
- hare/query/expressions/subqueries/__init__.py +1 -0
- hare/query/expressions/subqueries/cte_rows.py +46 -0
- hare/query/expressions/subqueries/declarations.py +8 -0
- hare/query/expressions/subqueries/exists.py +181 -0
- hare/query/expressions/subqueries/outer_reference.py +157 -0
- hare/query/expressions/subqueries/outer_scope.py +74 -0
- hare/query/expressions/subqueries/recursive_rows.py +177 -0
- hare/query/expressions/subqueries/subquery.py +236 -0
- hare/query/expressions/temporal/__init__.py +9 -0
- hare/query/expressions/temporal/constants.py +43 -0
- hare/query/expressions/temporal/temporal_arithmetic.py +254 -0
- hare/query/expressions/temporal/temporal_operand.py +25 -0
- hare/query/expressions/term_expression.py +28 -0
- hare/query/expressions/value.py +259 -0
- hare/query/expressions/value_references/__init__.py +49 -0
- hare/query/expressions/value_references/array_value_reference.py +41 -0
- hare/query/expressions/value_references/composite_key_value_reference.py +61 -0
- hare/query/expressions/value_references/cursor_value_reference.py +41 -0
- hare/query/expressions/value_references/encoded_value_reference.py +43 -0
- hare/query/expressions/value_references/expression_arguments.py +181 -0
- hare/query/expressions/value_references/like_value_reference.py +46 -0
- hare/query/expressions/value_references/list_parameter_value_reference.py +65 -0
- hare/query/expressions/value_references/list_value_reference.py +55 -0
- hare/query/expressions/value_references/literal_value_reference.py +38 -0
- hare/query/expressions/value_references/open_range_value_reference.py +53 -0
- hare/query/expressions/value_references/range_value_reference.py +49 -0
- hare/query/expressions/value_references/rebuilt_criterion_value_reference.py +93 -0
- hare/query/expressions/value_references/related_key_value_reference.py +67 -0
- hare/query/expressions/value_references/related_value_reference.py +33 -0
- hare/query/expressions/value_references/row_list_value_reference.py +67 -0
- hare/query/expressions/value_references/scalar_value_reference.py +41 -0
- hare/query/expressions/value_references/value_reference_types.py +65 -0
- hare/query/expressions/value_references/write_value_reference.py +41 -0
- hare/query/expressions/window.py +220 -0
- hare/query/filters/__init__.py +21 -0
- hare/query/filters/constants.py +89 -0
- hare/query/filters/lookups/__init__.py +1 -0
- hare/query/filters/lookups/annotation_container_lookups.py +40 -0
- hare/query/filters/lookups/constants.py +60 -0
- hare/query/filters/lookups/containers/__init__.py +3 -0
- hare/query/filters/lookups/containers/container_field_lookups.py +78 -0
- hare/query/filters/lookups/containers/container_lookups.py +80 -0
- hare/query/filters/lookups/containers/container_value_encoders.py +94 -0
- hare/query/filters/lookups/date_part_lookups.py +292 -0
- hare/query/filters/lookups/dialect_implemented_operators.py +39 -0
- hare/query/filters/lookups/field_lookup.py +59 -0
- hare/query/filters/lookups/field_lookups.py +289 -0
- hare/query/filters/lookups/field_transforms.py +98 -0
- hare/query/filters/lookups/json/__init__.py +1 -0
- hare/query/filters/lookups/json/json_filter_guards.py +412 -0
- hare/query/filters/lookups/json/json_filter_parser.py +82 -0
- hare/query/filters/lookups/json/json_lookups.py +67 -0
- hare/query/filters/lookups/json/json_path_lookups.py +184 -0
- hare/query/filters/lookups/lookups.py +371 -0
- hare/query/filters/lookups/value_encoders.py +246 -0
- hare/query/filters/resolution/__init__.py +1 -0
- hare/query/filters/resolution/annotation_filters.py +280 -0
- hare/query/filters/resolution/composite_key_filters.py +439 -0
- hare/query/filters/resolution/filter_kwargs.py +704 -0
- hare/query/filters/resolution/filter_values.py +565 -0
- hare/query/filters/resolution/json_path_filters.py +157 -0
- hare/query/filters/resolution/lookup_support.py +84 -0
- hare/query/filters/resolution/relation_filters.py +510 -0
- hare/query/filters/resolution/sensitive_filter_keys.py +91 -0
- hare/query/filters/resolution/to_many_filters.py +436 -0
- hare/query/functions/__init__.py +185 -0
- hare/query/functions/aggregates/__init__.py +9 -0
- hare/query/functions/aggregates/array_agg.py +48 -0
- hare/query/functions/aggregates/avg.py +59 -0
- hare/query/functions/aggregates/constants.py +5 -0
- hare/query/functions/aggregates/count.py +81 -0
- hare/query/functions/aggregates/declarations.py +51 -0
- hare/query/functions/aggregates/statistic_aggregate.py +67 -0
- hare/query/functions/aggregates/sum.py +55 -0
- hare/query/functions/comparison/__init__.py +9 -0
- hare/query/functions/comparison/cast.py +121 -0
- hare/query/functions/comparison/coalesce.py +140 -0
- hare/query/functions/comparison/collate.py +45 -0
- hare/query/functions/comparison/declarations.py +21 -0
- hare/query/functions/comparison/function_arguments.py +70 -0
- hare/query/functions/comparison/greatest_least_function.py +108 -0
- hare/query/functions/comparison/null_if.py +78 -0
- hare/query/functions/containers/__init__.py +7 -0
- hare/query/functions/containers/array_item.py +69 -0
- hare/query/functions/datetime/__init__.py +55 -0
- hare/query/functions/datetime/date_function_source.py +31 -0
- hare/query/functions/datetime/declarations.py +193 -0
- hare/query/functions/datetime/extract.py +97 -0
- hare/query/functions/datetime/now.py +26 -0
- hare/query/functions/datetime/trunc.py +124 -0
- hare/query/functions/json/__init__.py +6 -0
- hare/query/functions/json/json_array.py +34 -0
- hare/query/functions/json/json_object.py +161 -0
- hare/query/functions/math/__init__.py +53 -0
- hare/query/functions/math/declarations.py +192 -0
- hare/query/functions/math/enums.py +16 -0
- hare/query/functions/math/math_function.py +110 -0
- hare/query/functions/math/mod.py +52 -0
- hare/query/functions/math/pi.py +21 -0
- hare/query/functions/math/random.py +22 -0
- hare/query/functions/math/round.py +85 -0
- hare/query/functions/text/__init__.py +55 -0
- hare/query/functions/text/concat.py +99 -0
- hare/query/functions/text/declarations.py +197 -0
- hare/query/functions/text/l_pad.py +17 -0
- hare/query/functions/text/length.py +38 -0
- hare/query/functions/text/r_pad.py +17 -0
- hare/query/functions/text/replace.py +17 -0
- hare/query/functions/text/text_function.py +114 -0
- hare/query/functions/window/__init__.py +45 -0
- hare/query/functions/window/aggregate_window_function.py +43 -0
- hare/query/functions/window/avg.py +23 -0
- hare/query/functions/window/constants.py +3 -0
- hare/query/functions/window/count.py +54 -0
- hare/query/functions/window/declarations.py +153 -0
- hare/query/functions/window/distribution_window_function.py +21 -0
- hare/query/functions/window/field_window_function.py +149 -0
- hare/query/functions/window/n_tile.py +41 -0
- hare/query/functions/window/nth_value.py +54 -0
- hare/query/functions/window/offset_window_function.py +85 -0
- hare/query/functions/window/rank_like_window_function.py +21 -0
- hare/query/functions/window/statistic_window_function.py +44 -0
- hare/query/functions/window/sum.py +23 -0
- hare/query/functions/window/window_function.py +134 -0
- hare/query/generic_foreign_keys/__init__.py +3 -0
- hare/query/generic_foreign_keys/constants.py +21 -0
- hare/query/generic_foreign_keys/generic_foreign_key_filters.py +251 -0
- hare/query/generic_foreign_keys/generic_foreign_key_paths.py +183 -0
- hare/query/generic_foreign_keys/generic_foreign_key_types.py +94 -0
- hare/query/grouping/__init__.py +14 -0
- hare/query/grouping/declarations.py +21 -0
- hare/query/grouping/grouping.py +60 -0
- hare/query/grouping/grouping_set.py +67 -0
- hare/query/grouping/grouping_sets.py +55 -0
- hare/query/key_columns.py +297 -0
- hare/query/lookup_info/__init__.py +12 -0
- hare/query/lookup_info/declarations.py +27 -0
- hare/query/lookup_info/lookup_info.py +89 -0
- hare/query/lookup_info/lookup_info_builder.py +807 -0
- hare/query/lookup_info/lookup_path.py +94 -0
- hare/query/lookup_info/lookup_paths.py +415 -0
- hare/query/lookup_info/ordering_info.py +43 -0
- hare/query/lookup_info/value_paths.py +135 -0
- hare/query/managers/__init__.py +1 -0
- hare/query/managers/base_manager.py +20 -0
- hare/query/managers/manager.py +130 -0
- hare/query/plans/__init__.py +4 -0
- hare/query/plans/call_signatures/__init__.py +1 -0
- hare/query/plans/call_signatures/call_signature_plans.py +318 -0
- hare/query/plans/call_signatures/call_signature_runs.py +466 -0
- hare/query/plans/constants.py +37 -0
- hare/query/plans/description/__init__.py +11 -0
- hare/query/plans/description/declared_plan_parts.py +7 -0
- hare/query/plans/description/filter_plan_descriptions.py +229 -0
- hare/query/plans/description/hashable_values.py +22 -0
- hare/query/plans/description/plan_context.py +33 -0
- hare/query/plans/description/plan_describer_compiler.py +355 -0
- hare/query/plans/description/plan_description.py +66 -0
- hare/query/plans/description/plan_parts.py +150 -0
- hare/query/plans/description/plannable.py +69 -0
- hare/query/plans/description/term_plan_descriptions.py +92 -0
- hare/query/plans/enums.py +97 -0
- hare/query/plans/plan_origins.py +99 -0
- hare/query/plans/recording/__init__.py +1 -0
- hare/query/plans/recording/plan_recording.py +100 -0
- hare/query/plans/recording/scope_value_source.py +67 -0
- hare/query/plans/statement/__init__.py +1 -0
- hare/query/plans/statement/declared_plan_slots.py +11 -0
- hare/query/plans/statement/query_key_compiler.py +171 -0
- hare/query/plans/statement/raw_sql_plan.py +47 -0
- hare/query/plans/statement/statement_plan.py +522 -0
- hare/query/plans/statement/statement_plan_descriptions.py +451 -0
- hare/query/plans/statement/statement_plan_runs.py +306 -0
- hare/query/plans/statement/statement_plans.py +128 -0
- hare/query/query_connection.py +110 -0
- hare/query/queryset/__init__.py +19 -0
- hare/query/queryset/annotation_access_tracker.py +20 -0
- hare/query/queryset/arguments/__init__.py +1 -0
- hare/query/queryset/arguments/annotation_arguments.py +215 -0
- hare/query/queryset/arguments/collection_arguments.py +29 -0
- hare/query/queryset/arguments/filter_arguments.py +260 -0
- hare/query/queryset/arguments/ordering_arguments.py +242 -0
- hare/query/queryset/arguments/values_arguments.py +145 -0
- hare/query/queryset/combination/__init__.py +1 -0
- hare/query/queryset/combination/combination.py +58 -0
- hare/query/queryset/combination/queryset_combination.py +109 -0
- hare/query/queryset/concrete_field_paths.py +109 -0
- hare/query/queryset/constants.py +83 -0
- hare/query/queryset/date_lists.py +74 -0
- hare/query/queryset/declarations.py +7 -0
- hare/query/queryset/extensions/__init__.py +9 -0
- hare/query/queryset/extensions/query_set_extension.py +78 -0
- hare/query/queryset/extensions/query_set_extension_call.py +19 -0
- hare/query/queryset/extensions/query_set_extension_query.py +146 -0
- hare/query/queryset/extensions/query_set_extensions.py +247 -0
- hare/query/queryset/lazy_relation_names.py +33 -0
- hare/query/queryset/model_query.py +79 -0
- hare/query/queryset/objects_by_key.py +79 -0
- hare/query/queryset/options/__init__.py +1 -0
- hare/query/queryset/options/query_option.py +42 -0
- hare/query/queryset/options/query_options.py +313 -0
- hare/query/queryset/pending_calls/__init__.py +1 -0
- hare/query/queryset/pending_calls/calls_before_setup.py +185 -0
- hare/query/queryset/pending_calls/pending_filter_calls.py +144 -0
- hare/query/queryset/query_specification.py +1088 -0
- hare/query/queryset/queryset.py +2527 -0
- hare/query/queryset/relations/__init__.py +3 -0
- hare/query/queryset/relations/linked_many_to_many_relation.py +41 -0
- hare/query/queryset/relations/many_to_many/__init__.py +1 -0
- hare/query/queryset/relations/many_to_many/linked_keys.py +147 -0
- hare/query/queryset/relations/many_to_many/linked_rows_queries.py +175 -0
- hare/query/queryset/relations/many_to_many/many_to_many_members.py +173 -0
- hare/query/queryset/relations/many_to_many/many_to_many_scope_checks.py +332 -0
- hare/query/queryset/relations/many_to_many/through_defaults.py +244 -0
- hare/query/queryset/relations/many_to_many/through_row_inserting.py +516 -0
- hare/query/queryset/relations/many_to_many/through_row_unlinking.py +333 -0
- hare/query/queryset/relations/many_to_many/through_rows.py +185 -0
- hare/query/queryset/relations/many_to_many_relation.py +382 -0
- hare/query/queryset/relations/related_queryset/__init__.py +9 -0
- hare/query/queryset/relations/related_queryset/related_query_set.py +366 -0
- hare/query/queryset/relations/related_queryset/related_rows_iterator.py +42 -0
- hare/query/queryset/relations/related_queryset/relation_rows.py +73 -0
- hare/query/queryset/relations/related_queryset/unsaved_owner_condition.py +37 -0
- hare/query/queryset/relations/reverse_relation.py +474 -0
- hare/query/queryset/row_multiplication.py +151 -0
- hare/query/queryset/schema_object_calls.py +45 -0
- hare/query/queryset/selection/__init__.py +1 -0
- hare/query/queryset/selection/statement_selection.py +217 -0
- hare/query/queryset/selection/values_selection.py +65 -0
- hare/query/queryset/single_rows/__init__.py +1 -0
- hare/query/queryset/single_rows/get_exception_argument.py +7 -0
- hare/query/queryset/single_rows/get_exceptions.py +91 -0
- hare/query/queryset/single_rows/none_awaitable_type.py +21 -0
- hare/query/queryset/single_rows/query_set_single.py +49 -0
- hare/query/queryset/single_rows/single_row.py +103 -0
- hare/query/queryset/specification_copying.py +123 -0
- hare/query/queryset/table_sample.py +60 -0
- hare/query/raw_sql/__init__.py +6 -0
- hare/query/raw_sql/execute_sql.py +71 -0
- hare/query/raw_sql/sql_query_result.py +38 -0
- hare/query/relation_loading/__init__.py +14 -0
- hare/query/relation_loading/constants.py +8 -0
- hare/query/relation_loading/prefetching/__init__.py +1 -0
- hare/query/relation_loading/prefetching/declarations.py +32 -0
- hare/query/relation_loading/prefetching/direct_relation_prefetch.py +234 -0
- hare/query/relation_loading/prefetching/many_to_many_prefetch.py +496 -0
- hare/query/relation_loading/prefetching/prefetch.py +198 -0
- hare/query/relation_loading/prefetching/prefetch_checks.py +80 -0
- hare/query/relation_loading/prefetching/prefetch_related_objects.py +48 -0
- hare/query/relation_loading/prefetching/prefetch_request.py +30 -0
- hare/query/relation_loading/prefetching/prefetcher.py +200 -0
- hare/query/relation_loading/prefetching/related_rows_fetch.py +116 -0
- hare/query/relation_loading/prefetching/reverse_relation_prefetch.py +201 -0
- hare/query/relation_loading/prefetching/sliced_prefetch.py +165 -0
- hare/query/relation_loading/select.py +26 -0
- hare/query/rows/__init__.py +3 -0
- hare/query/rows/constants.py +33 -0
- hare/query/rows/enums.py +81 -0
- hare/query/rows/model_rows/__init__.py +1 -0
- hare/query/rows/model_rows/combined_model_rows.py +254 -0
- hare/query/rows/model_rows/model_columns.py +210 -0
- hare/query/rows/model_rows/model_rows.py +462 -0
- hare/query/rows/native/__init__.py +1 -0
- hare/query/rows/native/enums.py +12 -0
- hare/query/rows/native/field_codecs.py +450 -0
- hare/query/rows/native/hydrate_accelerator.py +264 -0
- hare/query/rows/native/hydration_layout.py +114 -0
- hare/query/rows/values_rows/__init__.py +1 -0
- hare/query/rows/values_rows/combined_values_rows.py +133 -0
- hare/query/rows/values_rows/dict_rows.py +92 -0
- hare/query/rows/values_rows/flat_rows.py +33 -0
- hare/query/rows/values_rows/named_rows.py +52 -0
- hare/query/rows/values_rows/tuple_rows.py +128 -0
- hare/query/rows/values_rows/value_field.py +26 -0
- hare/query/rows/values_rows/values_rows.py +175 -0
- hare/query/scopes/__init__.py +21 -0
- hare/query/scopes/constants.py +14 -0
- hare/query/scopes/manager_scope.py +51 -0
- hare/query/scopes/row_scope.py +46 -0
- hare/query/scopes/row_scopes.py +281 -0
- hare/query/scopes/row_visibility.py +89 -0
- hare/query/scopes/scope_join_conditions.py +273 -0
- hare/query/scopes/soft_delete_scope.py +17 -0
- hare/query/scopes/tenants/__init__.py +1 -0
- hare/query/scopes/tenants/all_tenants.py +11 -0
- hare/query/scopes/tenants/model_tenants.py +79 -0
- hare/query/scopes/tenants/tenant_scope.py +70 -0
- hare/query/scopes/tenants/tenant_values.py +52 -0
- hare/query/statements/__init__.py +30 -0
- hare/query/statements/awaitable_query.py +709 -0
- hare/query/statements/building/__init__.py +1 -0
- hare/query/statements/building/keyset_bounds.py +179 -0
- hare/query/statements/building/query_annotations.py +350 -0
- hare/query/statements/building/query_conditions.py +244 -0
- hare/query/statements/building/query_ctes.py +70 -0
- hare/query/statements/building/query_grouping.py +347 -0
- hare/query/statements/building/query_joins.py +282 -0
- hare/query/statements/building/query_ordering.py +275 -0
- hare/query/statements/building/row_locks.py +216 -0
- hare/query/statements/constants.py +111 -0
- hare/query/statements/select/__init__.py +4 -0
- hare/query/statements/select/combined/__init__.py +1 -0
- hare/query/statements/select/combined/combined_branches.py +380 -0
- hare/query/statements/select/combined/combined_derived_queries.py +220 -0
- hare/query/statements/select/combined/combined_plan_descriptions.py +43 -0
- hare/query/statements/select/combined_query.py +354 -0
- hare/query/statements/select/model_rows/__init__.py +1 -0
- hare/query/statements/select/model_rows/instance_hydration.py +162 -0
- hare/query/statements/select/model_rows/model_rows_plan_descriptions.py +108 -0
- hare/query/statements/select/model_rows/only_defer_fields.py +243 -0
- hare/query/statements/select/model_rows/select_related_joins.py +112 -0
- hare/query/statements/select/model_rows_query.py +416 -0
- hare/query/statements/select/raw_sql_query.py +151 -0
- hare/query/statements/select/rows_query.py +210 -0
- hare/query/statements/select/select_query.py +110 -0
- hare/query/statements/select/values/__init__.py +1 -0
- hare/query/statements/select/values/constants.py +9 -0
- hare/query/statements/select/values/values_distinct.py +41 -0
- hare/query/statements/select/values/values_grouping.py +118 -0
- hare/query/statements/select/values/values_output.py +298 -0
- hare/query/statements/select/values/values_reading.py +26 -0
- hare/query/statements/select/values/window_filter_wrapping.py +91 -0
- hare/query/statements/select/values_query.py +754 -0
- hare/query/statements/summary/__init__.py +3 -0
- hare/query/statements/summary/aggregate_query.py +732 -0
- hare/query/statements/summary/contains_query.py +66 -0
- hare/query/statements/summary/count_query.py +117 -0
- hare/query/statements/summary/exists_query.py +151 -0
- hare/query/statements/summary/rows_summary_query.py +187 -0
- hare/query/statements/write/__init__.py +3 -0
- hare/query/statements/write/bulk/__init__.py +1 -0
- hare/query/statements/write/bulk/bulk_objects.py +61 -0
- hare/query/statements/write/bulk/bulk_update_checks.py +92 -0
- hare/query/statements/write/bulk/bulk_update_query.py +1012 -0
- hare/query/statements/write/bulk/bulk_write_batches.py +368 -0
- hare/query/statements/write/bulk/create/__init__.py +1 -0
- hare/query/statements/write/bulk/create/bulk_create_query.py +936 -0
- hare/query/statements/write/bulk/create/bulk_create_reports.py +316 -0
- hare/query/statements/write/bulk/create/conflict_clause.py +137 -0
- hare/query/statements/write/bulk/create/copy_insert.py +143 -0
- hare/query/statements/write/bulk/create/default_rows_insert.py +85 -0
- hare/query/statements/write/bulk/create/inline_insert.py +93 -0
- hare/query/statements/write/bulk/create/multi_row_insert.py +277 -0
- hare/query/statements/write/bulk/create/returned_rows_matching.py +136 -0
- hare/query/statements/write/bulk/create/template_insert.py +185 -0
- hare/query/statements/write/bulk/declarations.py +61 -0
- hare/query/statements/write/create_or_update.py +193 -0
- hare/query/statements/write/declarations.py +26 -0
- hare/query/statements/write/delete_query.py +402 -0
- hare/query/statements/write/insert_from_query.py +373 -0
- hare/query/statements/write/matching_rows_query.py +268 -0
- hare/query/statements/write/merge/__init__.py +1 -0
- hare/query/statements/write/merge/merge_query.py +818 -0
- hare/query/statements/write/merge/merge_when.py +87 -0
- hare/query/statements/write/restore_query.py +105 -0
- hare/query/statements/write/returning/__init__.py +1 -0
- hare/query/statements/write/returning/delete_returning_query.py +154 -0
- hare/query/statements/write/returning/returned_rows.py +246 -0
- hare/query/statements/write/returning/update_returning_query.py +120 -0
- hare/query/statements/write/update_query.py +851 -0
- hare/search/__init__.py +29 -0
- hare/search/constants.py +22 -0
- hare/search/enums.py +26 -0
- hare/search/query/__init__.py +8 -0
- hare/search/query/combined_search_query.py +46 -0
- hare/search/query/declarations.py +9 -0
- hare/search/query/search_query.py +75 -0
- hare/search/query/search_query_combinable.py +40 -0
- hare/search/search_arguments.py +79 -0
- hare/search/search_features.py +35 -0
- hare/search/search_headline.py +186 -0
- hare/search/search_rank.py +144 -0
- hare/search/types.py +16 -0
- hare/search/vector/__init__.py +7 -0
- hare/search/vector/combined_search_vector.py +32 -0
- hare/search/vector/search_vector.py +77 -0
- hare/search/vector/search_vector_combinable.py +30 -0
- hare/sql/__init__.py +71 -0
- hare/sql/analytics/__init__.py +17 -0
- hare/sql/analytics/count.py +13 -0
- hare/sql/analytics/current_row.py +10 -0
- hare/sql/analytics/declarations.py +15 -0
- hare/sql/analytics/row_number.py +13 -0
- hare/sql/builder/__init__.py +29 -0
- hare/sql/builder/joins/__init__.py +16 -0
- hare/sql/builder/joins/join.py +71 -0
- hare/sql/builder/joins/join_on.py +73 -0
- hare/sql/builder/joins/joiner.py +38 -0
- hare/sql/builder/queries/__init__.py +17 -0
- hare/sql/builder/queries/constants.py +5 -0
- hare/sql/builder/queries/correlated_subqueries.py +583 -0
- hare/sql/builder/queries/pagination_sql.py +19 -0
- hare/sql/builder/queries/query.py +109 -0
- hare/sql/builder/queries/query_builder.py +1090 -0
- hare/sql/builder/queries/query_sql_rendering.py +407 -0
- hare/sql/builder/queries/set_operation_query.py +203 -0
- hare/sql/builder/returned_value.py +19 -0
- hare/sql/builder/tables/__init__.py +22 -0
- hare/sql/builder/tables/aliased_query.py +33 -0
- hare/sql/builder/tables/array_join_source.py +39 -0
- hare/sql/builder/tables/asof_join_source.py +29 -0
- hare/sql/builder/tables/cte.py +18 -0
- hare/sql/builder/tables/database.py +12 -0
- hare/sql/builder/tables/json_table_query.py +76 -0
- hare/sql/builder/tables/lateral_query.py +26 -0
- hare/sql/builder/tables/schema.py +42 -0
- hare/sql/builder/tables/selectable.py +83 -0
- hare/sql/builder/tables/table.py +170 -0
- hare/sql/builder_methods.py +56 -0
- hare/sql/constants.py +87 -0
- hare/sql/enums.py +211 -0
- hare/sql/exceptions.py +31 -0
- hare/sql/functions/__init__.py +81 -0
- hare/sql/functions/address_text.py +18 -0
- hare/sql/functions/cast.py +19 -0
- hare/sql/functions/cast_to.py +38 -0
- hare/sql/functions/coalesce.py +13 -0
- hare/sql/functions/count.py +14 -0
- hare/sql/functions/datetime/__init__.py +1 -0
- hare/sql/functions/datetime/date.py +16 -0
- hare/sql/functions/datetime/date_as_timestamp.py +23 -0
- hare/sql/functions/datetime/date_trunc.py +65 -0
- hare/sql/functions/datetime/datetime_as_text.py +16 -0
- hare/sql/functions/datetime/datetime_cast.py +68 -0
- hare/sql/functions/datetime/extract.py +92 -0
- hare/sql/functions/datetime/now.py +14 -0
- hare/sql/functions/datetime/temporal_difference.py +26 -0
- hare/sql/functions/datetime/temporal_shift.py +38 -0
- hare/sql/functions/datetime/timestamp_comparand.py +18 -0
- hare/sql/functions/declarations.py +19 -0
- hare/sql/functions/distinct_option_function.py +33 -0
- hare/sql/functions/greatest_least.py +25 -0
- hare/sql/functions/grouping_function.py +13 -0
- hare/sql/functions/json/__init__.py +1 -0
- hare/sql/functions/json/json_array.py +14 -0
- hare/sql/functions/json/json_object.py +14 -0
- hare/sql/functions/json/json_sort_key.py +15 -0
- hare/sql/functions/json/json_value.py +19 -0
- hare/sql/functions/numeric_cast.py +16 -0
- hare/sql/functions/random_number.py +13 -0
- hare/sql/functions/round.py +20 -0
- hare/sql/functions/statistic.py +20 -0
- hare/sql/functions/std_dev.py +13 -0
- hare/sql/functions/text/__init__.py +1 -0
- hare/sql/functions/text/collate.py +61 -0
- hare/sql/functions/text/concat.py +18 -0
- hare/sql/functions/text/concat_function.py +53 -0
- hare/sql/functions/text/decimal_text_collate.py +16 -0
- hare/sql/functions/text/lower.py +12 -0
- hare/sql/functions/text/replace.py +12 -0
- hare/sql/functions/text/upper.py +12 -0
- hare/sql/identifiers.py +61 -0
- hare/sql/sql_context.py +155 -0
- hare/sql/terms/__init__.py +90 -0
- hare/sql/terms/arithmetic_expression.py +120 -0
- hare/sql/terms/array.py +109 -0
- hare/sql/terms/bracket.py +12 -0
- hare/sql/terms/case/__init__.py +1 -0
- hare/sql/terms/case/case.py +123 -0
- hare/sql/terms/case/when_then.py +11 -0
- hare/sql/terms/constants.py +5 -0
- hare/sql/terms/containers/__init__.py +35 -0
- hare/sql/terms/containers/array_element_term.py +58 -0
- hare/sql/terms/containers/array_slice_term.py +28 -0
- hare/sql/terms/containers/constants.py +6 -0
- hare/sql/terms/containers/container_function.py +22 -0
- hare/sql/terms/containers/container_literal.py +37 -0
- hare/sql/terms/containers/declarations.py +47 -0
- hare/sql/terms/containers/map_value_term.py +30 -0
- hare/sql/terms/containers/tuple_element_term.py +21 -0
- hare/sql/terms/criteria/__init__.py +37 -0
- hare/sql/terms/criteria/basic_criterion.py +92 -0
- hare/sql/terms/criteria/between_criterion.py +39 -0
- hare/sql/terms/criteria/complex_criterion.py +47 -0
- hare/sql/terms/criteria/contains_criterion.py +81 -0
- hare/sql/terms/criteria/criterion.py +87 -0
- hare/sql/terms/criteria/empty_criterion.py +38 -0
- hare/sql/terms/criteria/is_distinct_from_criterion.py +52 -0
- hare/sql/terms/criteria/is_not_true_criterion.py +49 -0
- hare/sql/terms/criteria/json_attribute_criterion.py +62 -0
- hare/sql/terms/criteria/like.py +56 -0
- hare/sql/terms/criteria/nested_criterion.py +78 -0
- hare/sql/terms/criteria/not_criterion.py +78 -0
- hare/sql/terms/criteria/null_criterion.py +47 -0
- hare/sql/terms/criteria/range_criterion.py +28 -0
- hare/sql/terms/criteria/true_criterion.py +13 -0
- hare/sql/terms/field.py +65 -0
- hare/sql/terms/functions/__init__.py +30 -0
- hare/sql/terms/functions/aggregate_function.py +119 -0
- hare/sql/terms/functions/analytic_function.py +107 -0
- hare/sql/terms/functions/custom_function.py +39 -0
- hare/sql/terms/functions/decimal_mod.py +27 -0
- hare/sql/terms/functions/float_mod.py +24 -0
- hare/sql/terms/functions/function.py +131 -0
- hare/sql/terms/functions/interval.py +110 -0
- hare/sql/terms/functions/mod.py +22 -0
- hare/sql/terms/functions/pow.py +11 -0
- hare/sql/terms/functions/window_frame_analytic_function.py +78 -0
- hare/sql/terms/grouping/__init__.py +14 -0
- hare/sql/terms/grouping/declarations.py +17 -0
- hare/sql/terms/grouping/grouping_element.py +42 -0
- hare/sql/terms/grouping/grouping_sets_element.py +46 -0
- hare/sql/terms/index.py +15 -0
- hare/sql/terms/infix_operator.py +34 -0
- hare/sql/terms/json.py +100 -0
- hare/sql/terms/negative.py +49 -0
- hare/sql/terms/node.py +135 -0
- hare/sql/terms/parameters/__init__.py +1 -0
- hare/sql/terms/parameters/list_parameter.py +33 -0
- hare/sql/terms/parameters/parameter.py +35 -0
- hare/sql/terms/parameters/parameterized_value_wrapper.py +19 -0
- hare/sql/terms/parameters/parameterizer.py +99 -0
- hare/sql/terms/parameters/query_parameters.py +74 -0
- hare/sql/terms/parameters/recording_parameterizer.py +27 -0
- hare/sql/terms/qualified_outer_field.py +58 -0
- hare/sql/terms/select_reference.py +80 -0
- hare/sql/terms/star.py +30 -0
- hare/sql/terms/subqueries/__init__.py +1 -0
- hare/sql/terms/subqueries/exists_term.py +111 -0
- hare/sql/terms/subqueries/outer_aggregate_term.py +51 -0
- hare/sql/terms/term.py +334 -0
- hare/sql/terms/term_identity_text.py +60 -0
- hare/sql/terms/tuple.py +52 -0
- hare/sql/terms/values/__init__.py +1 -0
- hare/sql/terms/values/literal_value.py +21 -0
- hare/sql/terms/values/null_value.py +10 -0
- hare/sql/terms/values/old_row_value.py +28 -0
- hare/sql/terms/values/row_value_list.py +15 -0
- hare/sql/terms/values/value_wrapper.py +129 -0
- hare/sql/types/__init__.py +1 -0
- hare/sql/types/sql_type.py +13 -0
- hare/sql/types/sql_types.py +17 -0
- hare/stubs/__init__.py +2 -0
- hare/stubs/constants.py +18 -0
- hare/stubs/model_stub.py +415 -0
- hare/stubs/module_stub.py +150 -0
- hare/stubs/stub_imports.py +91 -0
- hare/stubs/stub_writer.py +60 -0
- hare/stubs/value_type_text.py +98 -0
- hare/time/__init__.py +12 -0
- hare/time/constants.py +27 -0
- hare/time/system_clock.py +84 -0
- hare/time/timezone.py +534 -0
- hare/time/zone_info.py +13 -0
- hare/transactions/__init__.py +25 -0
- hare/transactions/atomic/__init__.py +1 -0
- hare/transactions/atomic/atomic.py +138 -0
- hare/transactions/atomic/atomic_attempt.py +62 -0
- hare/transactions/atomic/atomic_attempts.py +73 -0
- hare/transactions/constants.py +41 -0
- hare/transactions/distributed/__init__.py +9 -0
- hare/transactions/distributed/declarations.py +32 -0
- hare/transactions/distributed/distributed_coordinator.py +784 -0
- hare/transactions/distributed/distributed_transactions.py +26 -0
- hare/transactions/distributed/stale_prepared_transaction.py +23 -0
- hare/transactions/enums.py +31 -0
- hare/transactions/transaction_options.py +86 -0
- hare/transactions/transactions.py +228 -0
- hare/typing_info/__init__.py +3 -0
- hare/typing_info/bound_models.py +73 -0
- hare/typing_info/constants.py +13 -0
- hare/typing_info/declarations.py +44 -0
- hare/typing_info/filter_value_types.py +144 -0
- hare/vectors/__init__.py +18 -0
- hare/vectors/constants.py +10 -0
- hare/vectors/declarations.py +41 -0
- hare/vectors/enums.py +14 -0
- hare/vectors/terms/__init__.py +6 -0
- hare/vectors/terms/vector_distance_term.py +22 -0
- hare/vectors/terms/vector_literal.py +18 -0
- hare/vectors/vector_distance_expression.py +107 -0
- hare/vectors/vector_field.py +147 -0
- hare/warnings.py +13 -0
- hare_orm-0.9.0.dist-info/LICENSE +27 -0
- hare_orm-0.9.0.dist-info/METADATA +321 -0
- hare_orm-0.9.0.dist-info/NOTICE.md +96 -0
- hare_orm-0.9.0.dist-info/NOTICE.ru.md +98 -0
- hare_orm-0.9.0.dist-info/RECORD +2267 -0
- hare_orm-0.9.0.dist-info/WHEEL +4 -0
- hare_orm-0.9.0.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,2527 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncIterator, Generator, Iterable, Mapping, Sequence
|
|
4
|
+
from dataclasses import replace
|
|
5
|
+
from datetime import tzinfo as TzInfo
|
|
6
|
+
from functools import partial
|
|
7
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, NoReturn, Self, cast, overload
|
|
8
|
+
|
|
9
|
+
from typing_extensions import TypeVar
|
|
10
|
+
|
|
11
|
+
from hare.core.connections.connections import Connections
|
|
12
|
+
from hare.ddl.table_options import TableOptions
|
|
13
|
+
from hare.dialects.base.clauses.enums import RowLockStrength
|
|
14
|
+
from hare.dialects.base.client.database_client import DatabaseClient
|
|
15
|
+
from hare.exceptions import (
|
|
16
|
+
DoesNotExist,
|
|
17
|
+
FieldError,
|
|
18
|
+
QueryError,
|
|
19
|
+
)
|
|
20
|
+
from hare.fields.data.temporal.date_field import DateField
|
|
21
|
+
from hare.fields.data.temporal.datetime_field import DatetimeField
|
|
22
|
+
from hare.fields.relations.fields.generic_foreign_key_field_instance import GenericForeignKeyFieldInstance
|
|
23
|
+
from hare.models.class_building.generic_foreign_keys import GenericForeignKeys
|
|
24
|
+
from hare.models.instances.instance_connections import InstanceConnections
|
|
25
|
+
from hare.models.write.rules.enums import WriteType
|
|
26
|
+
from hare.models.write.rules.row_write_rules import RowWriteRules
|
|
27
|
+
from hare.models.write.rules.tenant_write_rules import TenantWriteRules
|
|
28
|
+
from hare.models.write.rules.written_target_checks import WrittenTargetChecks
|
|
29
|
+
from hare.query.constants import AGGREGATE_OVER_DISTINCT_ON_MESSAGE, GET_FETCH_LIMIT_FOR_MULTIPLICITY_CHECK
|
|
30
|
+
from hare.query.enums import GetException, RowShape, TableSampleMethod
|
|
31
|
+
from hare.query.expressions import Exists, Expression, F, Ordering, Q
|
|
32
|
+
from hare.query.expressions.joins.named_join import NamedJoin
|
|
33
|
+
from hare.query.expressions.subqueries.recursive_rows import RecursiveRows
|
|
34
|
+
from hare.query.filters.resolution.filter_values import FilterValues
|
|
35
|
+
from hare.query.functions.datetime.trunc import Trunc
|
|
36
|
+
from hare.query.functions.math.random import Random
|
|
37
|
+
from hare.query.generic_foreign_keys.generic_foreign_key_filters import GenericForeignKeyFilters
|
|
38
|
+
from hare.query.generic_foreign_keys.generic_foreign_key_paths import GenericForeignKeyPaths
|
|
39
|
+
from hare.query.generic_foreign_keys.generic_foreign_key_types import GenericForeignKeyTypes
|
|
40
|
+
from hare.query.grouping.grouping_set import GroupingSet
|
|
41
|
+
from hare.query.lookup_info.lookup_info import LookupInfo
|
|
42
|
+
from hare.query.lookup_info.lookup_info_builder import LookupInfoBuilder
|
|
43
|
+
from hare.query.lookup_info.lookup_path import LookupPath
|
|
44
|
+
from hare.query.lookup_info.ordering_info import OrderingInfo
|
|
45
|
+
from hare.query.plans.call_signatures.call_signature_runs import CallSignatureRuns
|
|
46
|
+
from hare.query.plans.description.plan_context import PlanContext
|
|
47
|
+
from hare.query.plans.description.plan_description import PlanDescription
|
|
48
|
+
from hare.query.plans.description.plannable import Plannable
|
|
49
|
+
from hare.query.queryset.arguments.annotation_arguments import AnnotationArguments
|
|
50
|
+
from hare.query.queryset.arguments.filter_arguments import FilterArguments
|
|
51
|
+
from hare.query.queryset.arguments.ordering_arguments import OrderingArguments
|
|
52
|
+
from hare.query.queryset.arguments.values_arguments import ValuesArguments
|
|
53
|
+
from hare.query.queryset.combination.queryset_combination import QuerySetCombination
|
|
54
|
+
from hare.query.queryset.concrete_field_paths import ConcreteFieldPaths
|
|
55
|
+
from hare.query.queryset.constants import (
|
|
56
|
+
AGGREGATE_OVER_GROUPING_SETS_MESSAGE,
|
|
57
|
+
DATES_TRUNC_TYPES,
|
|
58
|
+
DATETIMES_TRUNC_TYPES,
|
|
59
|
+
LATEST_WITHOUT_FIELDS_MESSAGE,
|
|
60
|
+
LOCKED_SUMMARY_MESSAGE,
|
|
61
|
+
MAX_ROW_COUNT,
|
|
62
|
+
RANDOM_ORDERING,
|
|
63
|
+
RANDOM_ORDERING_ALIAS,
|
|
64
|
+
)
|
|
65
|
+
from hare.query.queryset.date_lists import DateLists
|
|
66
|
+
from hare.query.queryset.declarations import NoAnnotations
|
|
67
|
+
from hare.query.queryset.extensions.query_set_extensions import QuerySetExtensions
|
|
68
|
+
from hare.query.queryset.objects_by_key import ObjectsByKey
|
|
69
|
+
from hare.query.queryset.options.query_options import QueryOptions
|
|
70
|
+
from hare.query.queryset.pending_calls.calls_before_setup import CallsBeforeSetup
|
|
71
|
+
from hare.query.queryset.pending_calls.pending_filter_calls import PendingFilterCalls
|
|
72
|
+
from hare.query.queryset.query_specification import QuerySpecification
|
|
73
|
+
from hare.query.queryset.row_multiplication import RowMultiplication
|
|
74
|
+
from hare.query.queryset.schema_object_calls import SchemaObjectCalls
|
|
75
|
+
from hare.query.queryset.selection.statement_selection import StatementSelection
|
|
76
|
+
from hare.query.queryset.selection.values_selection import ValuesSelection
|
|
77
|
+
from hare.query.queryset.single_rows.get_exceptions import GetExceptions
|
|
78
|
+
from hare.query.queryset.single_rows.query_set_single import QuerySetSingle
|
|
79
|
+
from hare.query.queryset.single_rows.single_row import SingleRow
|
|
80
|
+
from hare.query.queryset.table_sample import TableSample
|
|
81
|
+
from hare.query.relation_loading.prefetching.prefetch import Prefetch
|
|
82
|
+
from hare.query.relation_loading.select import Select
|
|
83
|
+
from hare.query.statements.awaitable_query import AwaitableQuery
|
|
84
|
+
from hare.query.statements.select.combined.combined_derived_queries import CombinedDerivedQueries
|
|
85
|
+
from hare.query.statements.select.model_rows_query import ModelRowsQuery
|
|
86
|
+
from hare.query.statements.select.rows_query import RowsQuery
|
|
87
|
+
from hare.query.statements.select.values.values_grouping import ValuesGrouping
|
|
88
|
+
from hare.query.statements.write.create_or_update import CreateOrUpdate
|
|
89
|
+
from hare.sql import Order
|
|
90
|
+
from hare.sql.builder.tables.selectable import Selectable
|
|
91
|
+
from hare.sql.enums import SetOperation, TruncType
|
|
92
|
+
from hare.sql.terms.term import Term
|
|
93
|
+
|
|
94
|
+
if TYPE_CHECKING:
|
|
95
|
+
from hare.ddl.raw_sql_term import RawSQLTerm
|
|
96
|
+
from hare.dialects.base.dialect import Dialect
|
|
97
|
+
from hare.models import Model
|
|
98
|
+
from hare.query.queryset.single_rows.get_exception_argument import GetExceptionArgument
|
|
99
|
+
from hare.query.statements.select.values_query import ValuesQuery
|
|
100
|
+
|
|
101
|
+
TModel = TypeVar("TModel", bound="Model")
|
|
102
|
+
#: What a row of a queryset is - the model instance, or what ``.values()``/``.values_list()`` select.
|
|
103
|
+
TRow = TypeVar("TRow", default=TModel)
|
|
104
|
+
#: The names and types of the queryset's ``.annotate()``/``.alias()`` expressions, as a ``TypedDict`` -
|
|
105
|
+
#: only the type checker reads it (the ``hare.contrib.mypy`` plugin fills it in). Covariant: a
|
|
106
|
+
#: queryset with annotations is still a ``QuerySet[Model]``.
|
|
107
|
+
TAnnotations = TypeVar("TAnnotations", bound=NoAnnotations, covariant=True, default=NoAnnotations)
|
|
108
|
+
TDerivedQuery = TypeVar("TDerivedQuery", bound="AwaitableQuery[Any]")
|
|
109
|
+
TMadeQuerySet = TypeVar("TMadeQuerySet", bound="QuerySet[Any, Any]")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class QuerySet(QuerySpecification[TModel], Generic[TModel, TRow, TAnnotations]):
|
|
113
|
+
"""A query for the rows of a model - model instances, the values ``.values()``/``.values_list()``
|
|
114
|
+
select, or the rows a set operation combines. Every chained method returns a changed copy;
|
|
115
|
+
awaiting, iterating or streaming it builds its SQL and runs it.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
accepts_extension_methods: ClassVar[bool] = True
|
|
119
|
+
|
|
120
|
+
__slots__ = (
|
|
121
|
+
# The calls this queryset was made with from its manager's queryset, when it was made by
|
|
122
|
+
# simple calls alone (filter()/exclude() of plain values, order_by() of names, slices,
|
|
123
|
+
# first()/last(), values()/values_list()/only()/select_related() of names) - None
|
|
124
|
+
# otherwise. Its queries run on the plan kept under the key of the calls, built not even in
|
|
125
|
+
# part. Any other change - a clone, an in-place change - leaves None.
|
|
126
|
+
"_call_signature",
|
|
127
|
+
# The values of the signature's filter calls, in call order.
|
|
128
|
+
"_call_values",
|
|
129
|
+
# The object this queryset, made again for each description or build of a query it is
|
|
130
|
+
# part of, stands for - unset otherwise (PlanOrigins).
|
|
131
|
+
"_plan_origin",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# The dict/list/set slots a clone gets its own shallow copy of. `_prefetch_queries` is a dict of
|
|
135
|
+
# lists - _clone() copies it separately.
|
|
136
|
+
mutable_clone_slots: ClassVar[dict[str, str]] = QuerySpecification.MUTABLE_SPECIFICATION_SLOTS
|
|
137
|
+
|
|
138
|
+
def __init__(self, model: type[TModel]) -> None:
|
|
139
|
+
model._meta.check_not_swapped()
|
|
140
|
+
super().__init__(model)
|
|
141
|
+
self._call_signature: tuple[Any, ...] | None = None
|
|
142
|
+
self._call_values: tuple[Any, ...] = ()
|
|
143
|
+
|
|
144
|
+
def __copy__(self) -> Self:
|
|
145
|
+
queryset = cast("Self", super().__copy__())
|
|
146
|
+
# A copy is changed by whoever made it - its calls aren't known.
|
|
147
|
+
queryset._call_signature = None
|
|
148
|
+
return queryset
|
|
149
|
+
|
|
150
|
+
def __deepcopy__(self, memo: dict[int, Any]) -> Self:
|
|
151
|
+
"""A copy as every method of the queryset makes one - its model, connection and expressions
|
|
152
|
+
are shared, being never changed in place.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
memo: The objects copied so far.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
The copy.
|
|
159
|
+
"""
|
|
160
|
+
return self._clone()
|
|
161
|
+
|
|
162
|
+
def __reduce__(self) -> NoReturn:
|
|
163
|
+
"""Refuses pickling - a queryset holds its connection and model classes, which another
|
|
164
|
+
process has its own of.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
TypeError: Always.
|
|
168
|
+
"""
|
|
169
|
+
raise TypeError(
|
|
170
|
+
f"A QuerySet of {self.model.__name__} can't be pickled - pickle the rows it reads (await it), "
|
|
171
|
+
"or the arguments it is built from"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
def _continue_call_signature(
|
|
175
|
+
self, queryset: TMadeQuerySet, call: tuple[Any, ...] | None, values: tuple[Any, ...] = ()
|
|
176
|
+
) -> TMadeQuerySet:
|
|
177
|
+
"""Gives a queryset made from this one by a simple call this one's call signature with the
|
|
178
|
+
call appended.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
queryset: The queryset made.
|
|
182
|
+
call: The call - its name and the arguments shaping the SQL; None for a call changing
|
|
183
|
+
nothing.
|
|
184
|
+
values: The filter values the call binds.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
``queryset``.
|
|
188
|
+
"""
|
|
189
|
+
call_signature = self._call_signature
|
|
190
|
+
if call_signature is not None:
|
|
191
|
+
queryset._call_signature = call_signature if call is None else (*call_signature, call)
|
|
192
|
+
queryset._call_values = (*self._call_values, *values) if values else self._call_values
|
|
193
|
+
return queryset
|
|
194
|
+
|
|
195
|
+
def _hand_call_signature(self, query: AwaitableQuery[Any]) -> None:
|
|
196
|
+
"""Hands this queryset's call signature to the query made to run it.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
query: The query.
|
|
200
|
+
"""
|
|
201
|
+
if self._call_signature is not None:
|
|
202
|
+
query._call_signature = self._call_signature
|
|
203
|
+
query._call_values = self._call_values
|
|
204
|
+
|
|
205
|
+
@CallsBeforeSetup.recorded
|
|
206
|
+
def all_tenants(self) -> Self:
|
|
207
|
+
"""Returns a clone spanning every tenant - without the ``Meta.tenant_field`` filter, for this
|
|
208
|
+
model and for the tenant-scoped models the query reaches through relations.
|
|
209
|
+
"""
|
|
210
|
+
QuerySetCombination.raise_if_combined(self, "all_tenants")
|
|
211
|
+
queryset = self._clone()
|
|
212
|
+
queryset._visibility = replace(queryset._visibility, all_tenants=True)
|
|
213
|
+
return queryset
|
|
214
|
+
|
|
215
|
+
@CallsBeforeSetup.recorded
|
|
216
|
+
def include_deleted(self) -> Self:
|
|
217
|
+
"""Returns a clone including soft-deleted rows. After ``.only_deleted()`` it replaces it.
|
|
218
|
+
|
|
219
|
+
Raises:
|
|
220
|
+
QueryError: The model has no ``Meta.soft_delete_field``.
|
|
221
|
+
"""
|
|
222
|
+
QuerySetCombination.raise_if_combined(self, "include_deleted")
|
|
223
|
+
return self._with_deleted_rows(only_deleted=False)
|
|
224
|
+
|
|
225
|
+
@CallsBeforeSetup.recorded
|
|
226
|
+
def only_deleted(self) -> Self:
|
|
227
|
+
"""Returns a clone with only soft-deleted rows; relations reached from it see deleted rows too.
|
|
228
|
+
The ``Meta.tenant_field`` filter still applies. After ``.include_deleted()`` it replaces it.
|
|
229
|
+
|
|
230
|
+
Raises:
|
|
231
|
+
QueryError: The model has no ``Meta.soft_delete_field``.
|
|
232
|
+
"""
|
|
233
|
+
QuerySetCombination.raise_if_combined(self, "only_deleted")
|
|
234
|
+
return self._with_deleted_rows(only_deleted=True)
|
|
235
|
+
|
|
236
|
+
def _with_deleted_rows(self, *, only_deleted: bool) -> Self:
|
|
237
|
+
"""A clone seeing soft-deleted rows - them alone, or together with the live ones.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
only_deleted: See only the soft-deleted rows of the model itself.
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
QueryError: If the model has no ``Meta.soft_delete_field`` configured.
|
|
244
|
+
"""
|
|
245
|
+
QuerySetCombination.raise_if_combined(self, "only_deleted" if only_deleted else "include_deleted")
|
|
246
|
+
if not self.model._meta.soft_delete_field:
|
|
247
|
+
raise QueryError(f"{self.model.__name__} has no Meta.soft_delete_field configured")
|
|
248
|
+
queryset = self._clone()
|
|
249
|
+
queryset._visibility = replace(queryset._visibility, include_deleted=True, only_deleted=only_deleted)
|
|
250
|
+
return queryset
|
|
251
|
+
|
|
252
|
+
def _clone(self) -> Self:
|
|
253
|
+
queryset = self._clone_keeping_calls()
|
|
254
|
+
queryset._call_signature = None
|
|
255
|
+
return queryset
|
|
256
|
+
|
|
257
|
+
def _clone_keeping_calls(self) -> Self:
|
|
258
|
+
"""A clone keeping this queryset's call signature - for a simple call to extend it.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
The clone.
|
|
262
|
+
"""
|
|
263
|
+
# _prefetch_queries is a dict of lists - each list is copied, so clones don't share them.
|
|
264
|
+
queryset: Self = QuerySpecification.__copy__(self) # type: ignore[assignment]
|
|
265
|
+
prefetch_queries = self._prefetch_queries
|
|
266
|
+
queryset._prefetch_queries = (
|
|
267
|
+
{key: list(value) for key, value in prefetch_queries.items()} if prefetch_queries else {}
|
|
268
|
+
)
|
|
269
|
+
return queryset
|
|
270
|
+
|
|
271
|
+
def _append_filters(self, negate: bool, args: tuple[Q | Exists, ...], kwargs: dict[str, Any]) -> None:
|
|
272
|
+
"""Appends the Q objects built from ``args``/``kwargs`` onto ``self._q_objects``, without
|
|
273
|
+
cloning. Everything one call appends shares one filter-call generation, so its conditions
|
|
274
|
+
over a to-many relation share a JOIN; a later call gets a new one.
|
|
275
|
+
"""
|
|
276
|
+
self._call_signature = None
|
|
277
|
+
self._filter_call_counter += 1
|
|
278
|
+
generation = self._filter_call_counter
|
|
279
|
+
if not all(isinstance(arg, (Q, Exists)) for arg in args):
|
|
280
|
+
raise TypeError("expected Q objects or Exists(...) conditions as args")
|
|
281
|
+
conditions = [(arg if isinstance(arg, Q) else Q(arg))._with_filter_call_generation(generation) for arg in args]
|
|
282
|
+
conditions.extend(PendingFilterCalls.get_filter_kwarg_conditions(self, kwargs, generation))
|
|
283
|
+
PendingFilterCalls.add_filter_conditions(self, negate, conditions, generation)
|
|
284
|
+
|
|
285
|
+
def _filter_or_exclude(self, negate: bool, args: tuple[Q | Exists, ...], kwargs: dict[str, Any]) -> Self:
|
|
286
|
+
FilterArguments.raise_if_slice_taken(self, "Cannot filter a query once a slice has been taken.")
|
|
287
|
+
if GenericForeignKeyFieldInstance.declared_names:
|
|
288
|
+
args, kwargs = GenericForeignKeyFilters.rewrite_arguments(self.model, args, kwargs)
|
|
289
|
+
FilterArguments.check_filter_keys(self, args, kwargs, "exclude" if negate else "filter")
|
|
290
|
+
# An iterable __in value is read once - the filter and the call signature share the list. A list,
|
|
291
|
+
# set or dict is taken as it is now: the caller changing it later changes no query.
|
|
292
|
+
kwargs = {
|
|
293
|
+
key: FilterValues.get_list_lookup_value(key, FilterValues.get_detached_value(value))
|
|
294
|
+
for key, value in kwargs.items()
|
|
295
|
+
}
|
|
296
|
+
if (
|
|
297
|
+
self._call_signature is not None
|
|
298
|
+
and (not args or FilterArguments.takes_pending_conditions(self, args))
|
|
299
|
+
and FilterArguments.takes_pending_filters(self, kwargs)
|
|
300
|
+
):
|
|
301
|
+
for value in kwargs.values():
|
|
302
|
+
# A SQL term built by hand describes itself by its rendered text alone.
|
|
303
|
+
if isinstance(value, Term) and not isinstance(value, Plannable):
|
|
304
|
+
break
|
|
305
|
+
else:
|
|
306
|
+
# Built only when a query of the queryset doesn't run on the plan of its calls.
|
|
307
|
+
queryset = self._clone_keeping_calls()
|
|
308
|
+
queryset._filter_call_counter += 1
|
|
309
|
+
generation = queryset._filter_call_counter
|
|
310
|
+
conditions = tuple(
|
|
311
|
+
[(arg if isinstance(arg, Q) else Q(arg))._with_filter_call_generation(generation) for arg in args]
|
|
312
|
+
)
|
|
313
|
+
queryset._pending_filter_calls = (
|
|
314
|
+
*self._pending_filter_calls,
|
|
315
|
+
(negate, generation, conditions, kwargs),
|
|
316
|
+
)
|
|
317
|
+
if not conditions:
|
|
318
|
+
return self._continue_call_signature(
|
|
319
|
+
queryset, ("exclude" if negate else "filter", tuple(kwargs)), tuple(kwargs.values())
|
|
320
|
+
)
|
|
321
|
+
# The conditions come first - each is described by its tree in the key of the calls.
|
|
322
|
+
return self._continue_call_signature(
|
|
323
|
+
queryset,
|
|
324
|
+
("exclude_conditions" if negate else "filter_conditions", tuple(kwargs), len(conditions)),
|
|
325
|
+
(*conditions, *kwargs.values()),
|
|
326
|
+
)
|
|
327
|
+
queryset = self._clone()
|
|
328
|
+
queryset._append_filters(negate, args, kwargs)
|
|
329
|
+
return queryset
|
|
330
|
+
|
|
331
|
+
def get_lookup_info(self, key: str) -> LookupInfo:
|
|
332
|
+
"""Describes a ``.filter()`` key of this queryset - like ``Model._meta.get_lookup_info()``,
|
|
333
|
+
and a key may start with one of the queryset's annotations, described by the
|
|
334
|
+
annotation's output field.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
key: The filter key.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
The description.
|
|
341
|
+
|
|
342
|
+
Raises:
|
|
343
|
+
FieldError: The key names no field, relation or annotation, or a lookup its field
|
|
344
|
+
doesn't have.
|
|
345
|
+
QueryError: The key is a lookup other than equality, membership or ``isnull`` on a
|
|
346
|
+
relation to a composite key.
|
|
347
|
+
QueryError: The model isn't bound yet (``Model._meta.is_bound``).
|
|
348
|
+
"""
|
|
349
|
+
self.model._meta._check_bound()
|
|
350
|
+
if key.partition("__")[0] not in self._annotations:
|
|
351
|
+
return self.model._meta.get_lookup_info(key)
|
|
352
|
+
return AnnotationArguments.get_annotation_description(
|
|
353
|
+
self,
|
|
354
|
+
"lookup_info",
|
|
355
|
+
key,
|
|
356
|
+
lambda: LookupInfoBuilder.get_lookup_info(
|
|
357
|
+
self.model,
|
|
358
|
+
key,
|
|
359
|
+
annotations=self._annotations,
|
|
360
|
+
annotation_fields=AnnotationArguments.get_annotation_output_fields(self),
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
def get_lookups(self, path: str, dialect: Dialect | None = None) -> dict[str, LookupInfo]:
|
|
365
|
+
"""Describes every lookup of a field path or annotation of this queryset that a dialect
|
|
366
|
+
runs - see ``Model._meta.get_lookups()``.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
path: A field, relation or annotation, after any relations.
|
|
370
|
+
dialect: The dialect - by default the one of the connection this queryset runs on.
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
Each lookup's suffix after ``path`` to its description.
|
|
374
|
+
|
|
375
|
+
Raises:
|
|
376
|
+
FieldError: The path names no field, relation or annotation.
|
|
377
|
+
QueryError: The model isn't bound yet (``Model._meta.is_bound``).
|
|
378
|
+
"""
|
|
379
|
+
self.model._meta._check_bound()
|
|
380
|
+
if dialect is None:
|
|
381
|
+
dialect = self.get_connection().dialect
|
|
382
|
+
if path.partition("__")[0] not in self._annotations:
|
|
383
|
+
return self.model._meta.get_lookups(path, dialect)
|
|
384
|
+
lookups = AnnotationArguments.get_annotation_description(
|
|
385
|
+
self,
|
|
386
|
+
"lookups",
|
|
387
|
+
path,
|
|
388
|
+
lambda: LookupInfoBuilder.get_lookups(
|
|
389
|
+
self.model,
|
|
390
|
+
path,
|
|
391
|
+
dialect,
|
|
392
|
+
annotations=self._annotations,
|
|
393
|
+
annotation_fields=AnnotationArguments.get_annotation_output_fields(self),
|
|
394
|
+
),
|
|
395
|
+
dialect,
|
|
396
|
+
)
|
|
397
|
+
return dict(lookups)
|
|
398
|
+
|
|
399
|
+
def get_ordering_info(self, name: str) -> OrderingInfo:
|
|
400
|
+
"""Describes an ``.order_by()`` name of this queryset - like
|
|
401
|
+
``Model._meta.get_ordering_info()``, and a name may be one of the queryset's annotations.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
name: The ordering name, optionally with a leading ``-``.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
The description.
|
|
408
|
+
|
|
409
|
+
Raises:
|
|
410
|
+
FieldError: The name names no field, relation or annotation.
|
|
411
|
+
QueryError: The model isn't bound yet (``Model._meta.is_bound``).
|
|
412
|
+
"""
|
|
413
|
+
self.model._meta._check_bound()
|
|
414
|
+
if name.removeprefix("-").partition("__")[0] not in self._annotations:
|
|
415
|
+
return self.model._meta.get_ordering_info(name)
|
|
416
|
+
return AnnotationArguments.get_annotation_description(
|
|
417
|
+
self,
|
|
418
|
+
"ordering_info",
|
|
419
|
+
name,
|
|
420
|
+
lambda: LookupInfoBuilder.get_ordering_info(
|
|
421
|
+
self.model,
|
|
422
|
+
name,
|
|
423
|
+
annotations=self._annotations,
|
|
424
|
+
annotation_fields=AnnotationArguments.get_annotation_output_fields(self),
|
|
425
|
+
),
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
@CallsBeforeSetup.recorded
|
|
429
|
+
def filter(self, *args: Q | Exists, **kwargs: Any) -> Self:
|
|
430
|
+
"""
|
|
431
|
+
The queryset of the rows matching every condition given - keyword lookups, ``Q`` objects and
|
|
432
|
+
``Exists(...)``; a lookup path crosses relations:
|
|
433
|
+
|
|
434
|
+
Example:
|
|
435
|
+
::
|
|
436
|
+
|
|
437
|
+
Team.objects.filter(events__tournament__name="Test")
|
|
438
|
+
|
|
439
|
+
Raises:
|
|
440
|
+
QueryError: The queryset is sliced.
|
|
441
|
+
"""
|
|
442
|
+
QuerySetCombination.raise_if_combined(self, "filter")
|
|
443
|
+
return self._filter_or_exclude(False, args, kwargs)
|
|
444
|
+
|
|
445
|
+
@CallsBeforeSetup.recorded
|
|
446
|
+
def exclude(self, *args: Q | Exists, **kwargs: Any) -> Self:
|
|
447
|
+
"""
|
|
448
|
+
As ``filter()``, but excludes the rows matching all given conditions together -
|
|
449
|
+
``exclude(a=1, b=2)`` is ``NOT (a = 1 AND b = 2)``, like ``exclude(Q(a=1, b=2))``.
|
|
450
|
+
"""
|
|
451
|
+
QuerySetCombination.raise_if_combined(self, "exclude")
|
|
452
|
+
return self._filter_or_exclude(True, args, kwargs)
|
|
453
|
+
|
|
454
|
+
def _get_field_may_be_null(self, field_name: str) -> bool:
|
|
455
|
+
"""Whether ordering by ``field_name`` can meet NULLs: a nullable column, or anything that is
|
|
456
|
+
not a plain column of this model (a related-model path - its LEFT JOIN yields NULLs - or an
|
|
457
|
+
annotation)."""
|
|
458
|
+
field_object = self.model._meta.fields_map.get(field_name)
|
|
459
|
+
return field_object is None or field_object.null
|
|
460
|
+
|
|
461
|
+
@property
|
|
462
|
+
def orderings(self) -> tuple[tuple[str, Order], ...]:
|
|
463
|
+
"""The ordering ``order_by()`` gave the queryset, one ``(path, Order)`` per column: ``pk``
|
|
464
|
+
stands for every field of the primary key, a forward relation for its key column(s), an
|
|
465
|
+
``Ordering`` for its field, direction and NULL placement.
|
|
466
|
+
|
|
467
|
+
Empty when ``order_by()`` wasn't called (``Meta.ordering`` is never included) and after
|
|
468
|
+
``order_by()`` with no arguments. ``before_cursor()`` doesn't change it.
|
|
469
|
+
"""
|
|
470
|
+
orderings = tuple(self._orderings)
|
|
471
|
+
if self._reverse_result_order:
|
|
472
|
+
return tuple((path, order.get_reversed()) for path, order in orderings)
|
|
473
|
+
return orderings
|
|
474
|
+
|
|
475
|
+
@CallsBeforeSetup.recorded
|
|
476
|
+
def order_by(self, *orderings: str | Expression | Ordering) -> Self:
|
|
477
|
+
"""
|
|
478
|
+
The queryset ordered by fields (``-`` for descending), paths over relations and expressions:
|
|
479
|
+
|
|
480
|
+
Example:
|
|
481
|
+
::
|
|
482
|
+
|
|
483
|
+
.order_by('name', '-tournament__name')
|
|
484
|
+
.order_by(F('score').desc(nulls_last=True), 'name')
|
|
485
|
+
.order_by('-created__year', 'data__owner')
|
|
486
|
+
.order_by(Lower('name').desc(nulls_last=True), F('price') * F('quantity'))
|
|
487
|
+
|
|
488
|
+
Supports ordering by related models too, and by a path inside a field's value as in
|
|
489
|
+
``.values()`` - a JSON key, an array item, a part of a date, time or datetime.
|
|
490
|
+
A '-' before the name will result in descending sort order, default is ascending.
|
|
491
|
+
``order_by()`` with no arguments removes every ordering, ``Meta.ordering`` included - the
|
|
492
|
+
rows come in whatever order the database returns them.
|
|
493
|
+
A plain string leaves the position of NULLs to the dialect (``Features.sorts_nulls_first``). To
|
|
494
|
+
fix it on every
|
|
495
|
+
dialect, pass ``F('field').asc()``/``F('field').desc()`` with ``nulls_first=True`` or
|
|
496
|
+
``nulls_last=True``.
|
|
497
|
+
|
|
498
|
+
Raises:
|
|
499
|
+
FieldError: If unknown field has been provided.
|
|
500
|
+
QueryError: The queryset is sliced (``[a:b]``, ``.limit()``, ``.offset()``) - order it
|
|
501
|
+
before slicing.
|
|
502
|
+
QueryError: ``.after_cursor()`` was already called - its values are bound to the
|
|
503
|
+
ordering by position; call ``.order_by()`` first.
|
|
504
|
+
"""
|
|
505
|
+
if self._combination is not None:
|
|
506
|
+
return cast(
|
|
507
|
+
"Self",
|
|
508
|
+
CombinedDerivedQueries.get_ordered_queryset(QuerySetCombination.get_combined_query(self), orderings),
|
|
509
|
+
)
|
|
510
|
+
FilterArguments.raise_if_slice_taken(self, "Cannot reorder a query once a slice has been taken.")
|
|
511
|
+
# A loop, not any(): every order_by() runs it, and a generator is a call more.
|
|
512
|
+
is_plain = True
|
|
513
|
+
for ordering in orderings:
|
|
514
|
+
if type(ordering) is not str:
|
|
515
|
+
is_plain = False
|
|
516
|
+
elif ordering == RANDOM_ORDERING:
|
|
517
|
+
return self.alias(**{RANDOM_ORDERING_ALIAS: Random()}).order_by(
|
|
518
|
+
*(
|
|
519
|
+
RANDOM_ORDERING_ALIAS if type(ordering) is str and ordering == RANDOM_ORDERING else ordering
|
|
520
|
+
for ordering in orderings
|
|
521
|
+
)
|
|
522
|
+
)
|
|
523
|
+
if not is_plain:
|
|
524
|
+
expression_aliases, orderings = OrderingArguments.get_expression_aliases(orderings)
|
|
525
|
+
if expression_aliases:
|
|
526
|
+
# An expression is ordered by an alias of its own, never selected.
|
|
527
|
+
return self.alias(**expression_aliases).order_by(*orderings)
|
|
528
|
+
if GenericForeignKeyFieldInstance.declared_names and (
|
|
529
|
+
type_aliases := GenericForeignKeyTypes.get_pending_type_aliases(self, orderings)
|
|
530
|
+
):
|
|
531
|
+
return self.alias(**type_aliases).order_by(*orderings)
|
|
532
|
+
OrderingArguments.forbid_reordering_after_cursor(self, "order_by")
|
|
533
|
+
queryset = self._with_orderings(*orderings)
|
|
534
|
+
queryset._default_ordering_disabled = not orderings
|
|
535
|
+
if is_plain:
|
|
536
|
+
return self._continue_call_signature(queryset, ("order_by", orderings))
|
|
537
|
+
return queryset
|
|
538
|
+
|
|
539
|
+
def _with_orderings(self, *orderings: str | Expression | Ordering) -> Self:
|
|
540
|
+
"""A clone ordered by the given fields, even when sliced - for a single-row query that
|
|
541
|
+
orders the slice itself.
|
|
542
|
+
|
|
543
|
+
Args:
|
|
544
|
+
orderings: The ordering fields.
|
|
545
|
+
|
|
546
|
+
Returns:
|
|
547
|
+
The clone.
|
|
548
|
+
"""
|
|
549
|
+
queryset = self._clone()
|
|
550
|
+
if not self._annotations:
|
|
551
|
+
plain_orderings = OrderingArguments.get_plain_orderings(self, orderings)
|
|
552
|
+
if plain_orderings is not None:
|
|
553
|
+
queryset._orderings = list(plain_orderings)
|
|
554
|
+
return queryset
|
|
555
|
+
# A path into a JSON field or annotation orders by an alias of its own, never selected.
|
|
556
|
+
path_annotations = AnnotationArguments.get_path_annotations(
|
|
557
|
+
self, (self._get_ordering_name(ordering)[0] for ordering in orderings)
|
|
558
|
+
)
|
|
559
|
+
if path_annotations:
|
|
560
|
+
AnnotationArguments.detach_annotation_descriptions(queryset, path_annotations)
|
|
561
|
+
queryset._annotations = {**queryset._annotations, **path_annotations}
|
|
562
|
+
queryset._alias_keys = queryset._alias_keys | set(path_annotations)
|
|
563
|
+
queryset._orderings = OrderingArguments.parse_orderings(queryset, orderings)
|
|
564
|
+
return queryset
|
|
565
|
+
|
|
566
|
+
@CallsBeforeSetup.recorded
|
|
567
|
+
def after_cursor(self, *values: Any) -> Self:
|
|
568
|
+
"""Keyset pagination: filters to the rows strictly after the given values in the current
|
|
569
|
+
``.order_by(...)``. With ``.before_cursor()`` it makes a window; calling it again replaces
|
|
570
|
+
the lower boundary.
|
|
571
|
+
|
|
572
|
+
Args:
|
|
573
|
+
values: The ordering values of the last row of the previous page, one per ordering
|
|
574
|
+
field.
|
|
575
|
+
|
|
576
|
+
Raises:
|
|
577
|
+
QueryError: ``.order_by()`` wasn't called, or the number of values doesn't match the
|
|
578
|
+
ordering fields.
|
|
579
|
+
FieldError: An ordering field is an annotation.
|
|
580
|
+
"""
|
|
581
|
+
QuerySetCombination.raise_if_combined(self, "after_cursor")
|
|
582
|
+
OrderingArguments.check_cursor_values(self, "after_cursor", values)
|
|
583
|
+
queryset = SingleRow.with_distinct_on_rows_as_subquery(self)
|
|
584
|
+
if queryset._reverse_result_order:
|
|
585
|
+
# .before_cursor() already reversed _orderings - "after" in the caller's ordering is
|
|
586
|
+
# "before" in the reversed one.
|
|
587
|
+
queryset._before_cursor_values = values
|
|
588
|
+
else:
|
|
589
|
+
queryset._cursor_values = values
|
|
590
|
+
return queryset
|
|
591
|
+
|
|
592
|
+
@CallsBeforeSetup.recorded
|
|
593
|
+
def before_cursor(self, *values: Any) -> Self:
|
|
594
|
+
"""Keyset pagination backwards: filters to the rows strictly before the given values in the
|
|
595
|
+
current ``.order_by(...)``. The query runs in the reversed ordering, so ``.limit(n)`` takes
|
|
596
|
+
the ``n`` rows closest to the cursor; the fetched rows are returned in the original order.
|
|
597
|
+
``.first()``/``.get()`` pick the row right before the cursor. With ``.after_cursor()`` it
|
|
598
|
+
makes a window; calling it again replaces the upper boundary.
|
|
599
|
+
|
|
600
|
+
Args:
|
|
601
|
+
values: The ordering values of the first row of the current page, one per ordering
|
|
602
|
+
field.
|
|
603
|
+
|
|
604
|
+
Raises:
|
|
605
|
+
QueryError: ``.order_by()`` wasn't called, or the number of values doesn't match the
|
|
606
|
+
ordering fields.
|
|
607
|
+
FieldError: An ordering field is an annotation.
|
|
608
|
+
"""
|
|
609
|
+
QuerySetCombination.raise_if_combined(self, "before_cursor")
|
|
610
|
+
OrderingArguments.check_cursor_values(self, "before_cursor", values)
|
|
611
|
+
queryset = SingleRow.with_distinct_on_rows_as_subquery(self)
|
|
612
|
+
if not queryset._reverse_result_order:
|
|
613
|
+
queryset._orderings = [(field_name, order.get_reversed()) for field_name, order in self._orderings]
|
|
614
|
+
# A lower boundary from an earlier .after_cursor() becomes the upper one in the
|
|
615
|
+
# reversed ordering.
|
|
616
|
+
queryset._before_cursor_values = self._cursor_values
|
|
617
|
+
queryset._reverse_result_order = True
|
|
618
|
+
queryset._cursor_values = values
|
|
619
|
+
return queryset
|
|
620
|
+
|
|
621
|
+
def cursor_values(self, obj: TModel) -> tuple[Any, ...]:
|
|
622
|
+
"""The keyset boundary values of ``obj`` for the current ``.order_by(...)`` - what
|
|
623
|
+
``.after_cursor()``/``.before_cursor()`` take. An ordering across a relation reads the
|
|
624
|
+
related object off ``obj``; a missing relation gives ``None``.
|
|
625
|
+
|
|
626
|
+
Args:
|
|
627
|
+
obj: A row of this queryset's model.
|
|
628
|
+
|
|
629
|
+
Returns:
|
|
630
|
+
One value per ordering field.
|
|
631
|
+
|
|
632
|
+
Raises:
|
|
633
|
+
QueryError: ``.order_by()`` wasn't called, or a related ordering's relation isn't
|
|
634
|
+
loaded.
|
|
635
|
+
FieldError: An ordering field is an annotation, or crosses a to-many relation.
|
|
636
|
+
QueryError: ``obj`` isn't of this queryset's model.
|
|
637
|
+
"""
|
|
638
|
+
if not isinstance(obj, self.model):
|
|
639
|
+
raise QueryError(f"cursor_values() expects a {self.model.__name__} instance, got {type(obj).__name__}")
|
|
640
|
+
if not self._orderings:
|
|
641
|
+
raise QueryError(".cursor_values() requires .order_by() to be called first")
|
|
642
|
+
values = []
|
|
643
|
+
for field_name, __ in self._orderings:
|
|
644
|
+
if field_name in self._annotations:
|
|
645
|
+
raise FieldError(f".cursor_values() does not support ordering by an annotation, got {field_name!r}")
|
|
646
|
+
values.append(OrderingArguments.get_cursor_value(obj, field_name))
|
|
647
|
+
return tuple(values)
|
|
648
|
+
|
|
649
|
+
def _get_single_queryset(
|
|
650
|
+
self,
|
|
651
|
+
args: tuple[Any, ...],
|
|
652
|
+
kwargs: dict[str, Any],
|
|
653
|
+
*,
|
|
654
|
+
does_not_exist_exception: GetExceptionArgument,
|
|
655
|
+
multiple_objects_returned_exception: GetExceptionArgument,
|
|
656
|
+
) -> Self:
|
|
657
|
+
"""The queryset of the one row matching the conditions.
|
|
658
|
+
|
|
659
|
+
Args:
|
|
660
|
+
args: ``Q`` conditions.
|
|
661
|
+
kwargs: Filter keyword arguments.
|
|
662
|
+
does_not_exist_exception: What is raised when no row matches - ``GetException.STANDARD``
|
|
663
|
+
for ``DoesNotExist``, None to give None instead.
|
|
664
|
+
multiple_objects_returned_exception: What is raised when more than one row matches -
|
|
665
|
+
``GetException.STANDARD`` for ``MultipleObjectsReturned``, None to read one row of
|
|
666
|
+
them without counting.
|
|
667
|
+
|
|
668
|
+
Returns:
|
|
669
|
+
The single-row queryset.
|
|
670
|
+
"""
|
|
671
|
+
if GenericForeignKeyFieldInstance.declared_names:
|
|
672
|
+
args, kwargs = GenericForeignKeyFilters.rewrite_arguments(self.model, args, kwargs)
|
|
673
|
+
get_call = CallSignatureRuns.get_get_call(self, kwargs) if kwargs and not args else None
|
|
674
|
+
if get_call is not None:
|
|
675
|
+
# Its queries run on the plan of the call; the filters are built only when the
|
|
676
|
+
# queryset is built after all.
|
|
677
|
+
queryset = self._clone_keeping_calls()
|
|
678
|
+
queryset._filter_call_counter += 1
|
|
679
|
+
queryset._pending_filter_calls = ((False, queryset._filter_call_counter, (), kwargs),)
|
|
680
|
+
queryset._call_signature = (type(self), get_call)
|
|
681
|
+
queryset._call_values = tuple(kwargs.values())
|
|
682
|
+
else:
|
|
683
|
+
filtered_queryset = self.filter(*args, **kwargs) if args or kwargs else self
|
|
684
|
+
queryset = SingleRow.with_rows_as_subquery(filtered_queryset)
|
|
685
|
+
filtered_queryset._continue_call_signature(queryset, ("single_row",))
|
|
686
|
+
queryset._limit = 1 if multiple_objects_returned_exception is None else GET_FETCH_LIMIT_FOR_MULTIPLICITY_CHECK
|
|
687
|
+
queryset._single = True
|
|
688
|
+
queryset._raise_does_not_exist = does_not_exist_exception is not None
|
|
689
|
+
# Nothing to keep for the standard exceptions - the call left out of the common get().
|
|
690
|
+
if (
|
|
691
|
+
does_not_exist_exception is not GetException.STANDARD
|
|
692
|
+
or multiple_objects_returned_exception is not GetException.STANDARD
|
|
693
|
+
or queryset._options is not QueryOptions.DEFAULT
|
|
694
|
+
):
|
|
695
|
+
GetExceptions.set_get_exceptions(queryset, does_not_exist_exception, multiple_objects_returned_exception)
|
|
696
|
+
return queryset
|
|
697
|
+
|
|
698
|
+
def _get_filter_value_query(self) -> ValuesQuery:
|
|
699
|
+
"""The query a filter compares with when this queryset is its value - the values it
|
|
700
|
+
selects, else its primary key, as the filter resolves it.
|
|
701
|
+
|
|
702
|
+
Returns:
|
|
703
|
+
The query.
|
|
704
|
+
"""
|
|
705
|
+
if self._selection is not None:
|
|
706
|
+
return StatementSelection.get_values_query(self)
|
|
707
|
+
return self._get_field_values_query("pk")
|
|
708
|
+
|
|
709
|
+
def _get_filter_value_compiler(self) -> AwaitableQuery[Any]:
|
|
710
|
+
"""The query a filter compares with when this queryset is its value, as the filter builds
|
|
711
|
+
it: the values it selects, else its primary key - or the query combining its rows.
|
|
712
|
+
|
|
713
|
+
Returns:
|
|
714
|
+
The query - made again for each description and build, its values coming from this
|
|
715
|
+
queryset.
|
|
716
|
+
"""
|
|
717
|
+
self._build_conditions_for_copies()
|
|
718
|
+
query = self._get_filter_value_query() if self._combination is None else self._get_compiler()
|
|
719
|
+
query._plan_origin = self
|
|
720
|
+
return query
|
|
721
|
+
|
|
722
|
+
def _get_field_values_query(self, field_name: str) -> ValuesQuery:
|
|
723
|
+
"""One field of each row this queryset returns, as a query to embed - a queryset passed as
|
|
724
|
+
a ``__in`` filter value.
|
|
725
|
+
|
|
726
|
+
Args:
|
|
727
|
+
field_name: The field to select, ``"pk"`` included.
|
|
728
|
+
|
|
729
|
+
Returns:
|
|
730
|
+
A flat ``values_list()`` query of the field.
|
|
731
|
+
"""
|
|
732
|
+
return StatementSelection.get_values_query(
|
|
733
|
+
StatementSelection.get_values_rows_queryset(self).values_list(field_name, flat=True)
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
@CallsBeforeSetup.recorded_result
|
|
737
|
+
def latest(self, *orderings: str | Expression | Ordering) -> QuerySetSingle[TRow | None]:
|
|
738
|
+
"""Returns the most recent object - the first in the descending ordering by the given fields. A
|
|
739
|
+
plain field name gets ``NULLS LAST``; an ``Ordering`` is reversed exactly.
|
|
740
|
+
|
|
741
|
+
Args:
|
|
742
|
+
orderings: Fields to order by - the model's ``Meta.get_latest_by`` when none is given.
|
|
743
|
+
|
|
744
|
+
Raises:
|
|
745
|
+
FieldError: A field is unknown, or none is given and the model has no ``Meta.get_latest_by``.
|
|
746
|
+
"""
|
|
747
|
+
QuerySetCombination.raise_if_combined(self, "latest")
|
|
748
|
+
SingleRow.raise_if_sliced_values_rows_differ(self, "latest")
|
|
749
|
+
orderings = orderings or self.model._meta.get_latest_by
|
|
750
|
+
if not orderings:
|
|
751
|
+
raise FieldError(LATEST_WITHOUT_FIELDS_MESSAGE.format(method="latest"))
|
|
752
|
+
expression_aliases, orderings = OrderingArguments.get_expression_aliases(orderings)
|
|
753
|
+
if expression_aliases:
|
|
754
|
+
return self.alias(**expression_aliases).latest(*orderings)
|
|
755
|
+
OrderingArguments.forbid_reordering_after_cursor(self, "latest")
|
|
756
|
+
queryset = SingleRow.with_rows_as_subquery(self)
|
|
757
|
+
queryset._orderings = OrderingArguments.parse_orderings(
|
|
758
|
+
self, orderings, reverse=True, nulls_last_by_default=True
|
|
759
|
+
)
|
|
760
|
+
return SingleRow.as_single(queryset)
|
|
761
|
+
|
|
762
|
+
@CallsBeforeSetup.recorded_result
|
|
763
|
+
def earliest(self, *orderings: str | Expression | Ordering) -> QuerySetSingle[TRow | None]:
|
|
764
|
+
"""Returns the earliest object - the first in the ascending ordering by the given fields. A
|
|
765
|
+
plain field name gets ``NULLS LAST``; an ``Ordering`` is used as given.
|
|
766
|
+
|
|
767
|
+
Args:
|
|
768
|
+
orderings: Fields to order by - the model's ``Meta.get_latest_by`` when none is given.
|
|
769
|
+
|
|
770
|
+
Raises:
|
|
771
|
+
FieldError: A field is unknown, or none is given and the model has no ``Meta.get_latest_by``.
|
|
772
|
+
"""
|
|
773
|
+
QuerySetCombination.raise_if_combined(self, "earliest")
|
|
774
|
+
SingleRow.raise_if_sliced_values_rows_differ(self, "earliest")
|
|
775
|
+
orderings = orderings or self.model._meta.get_latest_by
|
|
776
|
+
if not orderings:
|
|
777
|
+
raise FieldError(LATEST_WITHOUT_FIELDS_MESSAGE.format(method="earliest"))
|
|
778
|
+
expression_aliases, orderings = OrderingArguments.get_expression_aliases(orderings)
|
|
779
|
+
if expression_aliases:
|
|
780
|
+
return self.alias(**expression_aliases).earliest(*orderings)
|
|
781
|
+
OrderingArguments.forbid_reordering_after_cursor(self, "earliest")
|
|
782
|
+
queryset = SingleRow.with_rows_as_subquery(self)
|
|
783
|
+
queryset._orderings = OrderingArguments.parse_orderings(self, orderings, nulls_last_by_default=True)
|
|
784
|
+
return SingleRow.as_single(queryset)
|
|
785
|
+
|
|
786
|
+
@CallsBeforeSetup.recorded
|
|
787
|
+
def reverse(self) -> Self:
|
|
788
|
+
"""Reverses the ordering exactly - its explicit NULL placements too - the ordering given by
|
|
789
|
+
``order_by()``, else ``Meta.ordering``; an unordered queryset stays unordered.
|
|
790
|
+
|
|
791
|
+
Raises:
|
|
792
|
+
QueryError: The queryset is sliced or combined (``union()``...).
|
|
793
|
+
QueryError: ``.after_cursor()`` was called - see ``order_by()``.
|
|
794
|
+
"""
|
|
795
|
+
QuerySetCombination.raise_if_combined(self, "reverse")
|
|
796
|
+
FilterArguments.raise_if_slice_taken(self, "Cannot reverse a query once a slice has been taken.")
|
|
797
|
+
OrderingArguments.forbid_reordering_after_cursor(self, "reverse")
|
|
798
|
+
queryset = self._clone()
|
|
799
|
+
current = list(self._apply_default_ordering(self._orderings))
|
|
800
|
+
queryset._orderings = [(field_name, order.get_reversed()) for field_name, order in current]
|
|
801
|
+
return queryset
|
|
802
|
+
|
|
803
|
+
def dates(self, field_name: str, trunc_type: str, order: str = "ASC") -> Self:
|
|
804
|
+
"""The distinct dates of a date or datetime field, truncated to ``trunc_type`` - a datetime's in the
|
|
805
|
+
current zone - NULLs left out.
|
|
806
|
+
|
|
807
|
+
Args:
|
|
808
|
+
field_name: A ``DateField`` or ``DatetimeField`` of the model.
|
|
809
|
+
trunc_type: ``year``, ``quarter``, ``month``, ``week`` or ``day``.
|
|
810
|
+
order: ``ASC`` or ``DESC``.
|
|
811
|
+
|
|
812
|
+
Returns:
|
|
813
|
+
A ``values_list(flat=True)`` queryset of ``datetime.date`` values.
|
|
814
|
+
|
|
815
|
+
Raises:
|
|
816
|
+
FieldError: The field isn't a date or datetime field of the model, or ``trunc_type`` or
|
|
817
|
+
``order`` is unknown.
|
|
818
|
+
"""
|
|
819
|
+
field = DateLists.get_dates_field(
|
|
820
|
+
self, field_name, "dates", (DateField, DatetimeField), DATES_TRUNC_TYPES, trunc_type, order
|
|
821
|
+
)
|
|
822
|
+
truncated: Expression = Trunc(field_name, trunc_type)
|
|
823
|
+
if isinstance(field, DatetimeField):
|
|
824
|
+
truncated = Trunc(truncated, str(TruncType.DATE))
|
|
825
|
+
return DateLists.get_distinct_dates(self, truncated, order)
|
|
826
|
+
|
|
827
|
+
def datetimes(
|
|
828
|
+
self, field_name: str, trunc_type: str, order: str = "ASC", tzinfo: str | TzInfo | None = None
|
|
829
|
+
) -> Self:
|
|
830
|
+
"""The distinct values of a datetime field, truncated to ``trunc_type`` in ``tzinfo`` (the current
|
|
831
|
+
zone by default), NULLs left out.
|
|
832
|
+
|
|
833
|
+
Args:
|
|
834
|
+
field_name: A ``DatetimeField`` of the model.
|
|
835
|
+
trunc_type: ``year``, ``quarter``, ``month``, ``week``, ``day``, ``hour``, ``minute`` or ``second``.
|
|
836
|
+
order: ``ASC`` or ``DESC``.
|
|
837
|
+
tzinfo: The zone the values are truncated in - an IANA name or a ``ZoneInfo``.
|
|
838
|
+
|
|
839
|
+
Returns:
|
|
840
|
+
A ``values_list(flat=True)`` queryset of ``datetime.datetime`` values.
|
|
841
|
+
|
|
842
|
+
Raises:
|
|
843
|
+
FieldError: The field isn't a datetime field of the model, or ``trunc_type`` or ``order`` is
|
|
844
|
+
unknown.
|
|
845
|
+
ConfigurationError: ``tzinfo`` isn't a known IANA zone.
|
|
846
|
+
"""
|
|
847
|
+
DateLists.get_dates_field(
|
|
848
|
+
self, field_name, "datetimes", (DatetimeField,), DATETIMES_TRUNC_TYPES, trunc_type, order
|
|
849
|
+
)
|
|
850
|
+
return DateLists.get_distinct_dates(self, Trunc(field_name, trunc_type, tzinfo=tzinfo), order)
|
|
851
|
+
|
|
852
|
+
@CallsBeforeSetup.recorded
|
|
853
|
+
def limit(self, limit: int) -> Self:
|
|
854
|
+
"""Sets the limit to the given value, replacing a limit already set - unlike slicing, which
|
|
855
|
+
composes.
|
|
856
|
+
|
|
857
|
+
Raises:
|
|
858
|
+
QueryError: The limit isn't an integer from 0 to ``MAX_ROW_COUNT``.
|
|
859
|
+
"""
|
|
860
|
+
if type(limit) is not int or not 0 <= limit <= MAX_ROW_COUNT:
|
|
861
|
+
self.check_row_count(limit, "Limit")
|
|
862
|
+
|
|
863
|
+
queryset = self._clone()
|
|
864
|
+
queryset._limit = limit
|
|
865
|
+
return self._continue_call_signature(queryset, ("limit",))
|
|
866
|
+
|
|
867
|
+
@CallsBeforeSetup.recorded
|
|
868
|
+
def offset(self, offset: int) -> Self:
|
|
869
|
+
"""Sets the offset to the given value, replacing an offset already set - unlike slicing, which
|
|
870
|
+
composes.
|
|
871
|
+
|
|
872
|
+
Raises:
|
|
873
|
+
QueryError: The offset isn't an integer from 0 to ``MAX_ROW_COUNT``.
|
|
874
|
+
"""
|
|
875
|
+
if type(offset) is not int or not 0 <= offset <= MAX_ROW_COUNT:
|
|
876
|
+
self.check_row_count(offset, "Offset")
|
|
877
|
+
|
|
878
|
+
queryset = self._clone()
|
|
879
|
+
queryset._offset = offset
|
|
880
|
+
# A query may leave a zero offset out of its SQL - whether there is one shapes it.
|
|
881
|
+
return self._continue_call_signature(queryset, ("offset", offset > 0))
|
|
882
|
+
|
|
883
|
+
@overload
|
|
884
|
+
def __getitem__(self, key: slice) -> Self: ...
|
|
885
|
+
|
|
886
|
+
@overload
|
|
887
|
+
def __getitem__(self, key: int) -> QuerySetSingle[TRow]: ...
|
|
888
|
+
|
|
889
|
+
@CallsBeforeSetup.recorded_result
|
|
890
|
+
def __getitem__(self, key: slice | int) -> QuerySet[TModel, TRow, TAnnotations] | QuerySetSingle[TRow]:
|
|
891
|
+
"""Slices the queryset, or takes the one object at an index. A slice composes with the offset
|
|
892
|
+
and limit already set, like slicing a list: ``queryset[5:10][2:4]`` selects positions 7 and
|
|
893
|
+
8. ``queryset[3]`` raises ``IndexError`` when awaited if there is no such row.
|
|
894
|
+
|
|
895
|
+
Raises:
|
|
896
|
+
QueryError: The key isn't a slice or a non-negative integer, the step isn't 1, or a
|
|
897
|
+
bound is negative.
|
|
898
|
+
"""
|
|
899
|
+
if isinstance(key, int) and not isinstance(key, bool):
|
|
900
|
+
if key < 0:
|
|
901
|
+
raise QueryError("Negative indexing is not supported.")
|
|
902
|
+
single_queryset = self[key : key + 1]
|
|
903
|
+
single_queryset._single = True
|
|
904
|
+
single_queryset._is_single_row_of_slice = True
|
|
905
|
+
single_queryset._raise_does_not_exist = True
|
|
906
|
+
single_queryset._does_not_exist_exception = IndexError(f"Index {key} is out of range")
|
|
907
|
+
return cast("QuerySetSingle[TRow]", single_queryset)
|
|
908
|
+
if not isinstance(key, slice):
|
|
909
|
+
raise QueryError("QuerySet indices must be slices or non-negative integers.")
|
|
910
|
+
|
|
911
|
+
offset, limit = self._get_sliced_bounds(key, self._offset, self._limit)
|
|
912
|
+
queryset = self.offset(offset)
|
|
913
|
+
if limit is not None:
|
|
914
|
+
queryset = queryset.limit(limit)
|
|
915
|
+
return queryset
|
|
916
|
+
|
|
917
|
+
@CallsBeforeSetup.recorded
|
|
918
|
+
def distinct(self, *field_names: str) -> Self:
|
|
919
|
+
"""Makes the queryset return distinct rows. Without arguments it adds ``DISTINCT``; with field
|
|
920
|
+
names it keeps one row per combination of them - an ``order_by()`` must then begin with the
|
|
921
|
+
same fields: ``DISTINCT ON (fields)``, refused when run on a database without it.
|
|
922
|
+
|
|
923
|
+
Example:
|
|
924
|
+
::
|
|
925
|
+
|
|
926
|
+
await Tournament.objects.all().distinct().values("name")
|
|
927
|
+
await Tournament.objects.all().distinct("name").order_by("name", "-desc")
|
|
928
|
+
|
|
929
|
+
Args:
|
|
930
|
+
field_names: Field names for ``DISTINCT ON`` - an annotation, or a path inside a field's value
|
|
931
|
+
(``created__year``), too.
|
|
932
|
+
|
|
933
|
+
Raises:
|
|
934
|
+
QueryError: The queryset is sliced.
|
|
935
|
+
"""
|
|
936
|
+
QuerySetCombination.raise_if_combined(self, "distinct")
|
|
937
|
+
FilterArguments.raise_if_not_names(self, field_names, "distinct")
|
|
938
|
+
FilterArguments.raise_if_slice_taken(self, "Cannot create distinct fields once a slice has been taken.")
|
|
939
|
+
queryset = self._clone_keeping_calls()
|
|
940
|
+
# A path into a JSON field or a date part (``created__year``) is an alias of its own, never
|
|
941
|
+
# selected.
|
|
942
|
+
path_annotations = AnnotationArguments.get_path_annotations(self, field_names)
|
|
943
|
+
if path_annotations:
|
|
944
|
+
AnnotationArguments.detach_annotation_descriptions(queryset, path_annotations)
|
|
945
|
+
queryset._annotations = {**queryset._annotations, **path_annotations}
|
|
946
|
+
queryset._alias_keys = queryset._alias_keys | set(path_annotations)
|
|
947
|
+
queryset._distinct = True
|
|
948
|
+
queryset._distinct_on = list(field_names)
|
|
949
|
+
return self._continue_call_signature(queryset, ("distinct", field_names))
|
|
950
|
+
|
|
951
|
+
@CallsBeforeSetup.recorded
|
|
952
|
+
def union(self, *other_querysets: QuerySet[Any, Any], all: bool = False) -> Self:
|
|
953
|
+
"""Returns the queryset of the combined rows (``UNION``). Chained set operations combine each
|
|
954
|
+
new queryset with the whole result so far. Model querysets combine with model querysets,
|
|
955
|
+
values querysets with values querysets - the rows take the shape of the first one.
|
|
956
|
+
|
|
957
|
+
Args:
|
|
958
|
+
other_querysets: The querysets to combine with.
|
|
959
|
+
all: Keep duplicate rows (``UNION ALL``).
|
|
960
|
+
|
|
961
|
+
Raises:
|
|
962
|
+
QueryError: Model instances are combined with ``.values()``/``.values_list()`` rows.
|
|
963
|
+
"""
|
|
964
|
+
return QuerySetCombination.combine(
|
|
965
|
+
self, other_querysets, SetOperation.UNION_ALL if all else SetOperation.UNION
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
@CallsBeforeSetup.recorded
|
|
969
|
+
def intersection(self, *other_querysets: QuerySet[Any, Any]) -> Self:
|
|
970
|
+
"""
|
|
971
|
+
The rows every queryset returns (``INTERSECT``).
|
|
972
|
+
|
|
973
|
+
Args:
|
|
974
|
+
other_querysets: Another QuerySet(s) to intersect with.
|
|
975
|
+
|
|
976
|
+
Returns:
|
|
977
|
+
The queryset of the combined rows.
|
|
978
|
+
|
|
979
|
+
Raises:
|
|
980
|
+
QueryError: Model instances are combined with ``.values()``/``.values_list()`` rows.
|
|
981
|
+
"""
|
|
982
|
+
return QuerySetCombination.combine(self, other_querysets, SetOperation.INTERSECT)
|
|
983
|
+
|
|
984
|
+
@CallsBeforeSetup.recorded
|
|
985
|
+
def difference(self, *other_querysets: QuerySet[Any, Any]) -> Self:
|
|
986
|
+
"""
|
|
987
|
+
This queryset's rows no other one returns (``EXCEPT``).
|
|
988
|
+
|
|
989
|
+
Args:
|
|
990
|
+
other_querysets: Another QuerySet(s) to subtract.
|
|
991
|
+
|
|
992
|
+
Returns:
|
|
993
|
+
The queryset of the combined rows.
|
|
994
|
+
|
|
995
|
+
Raises:
|
|
996
|
+
QueryError: Model instances are combined with ``.values()``/``.values_list()`` rows.
|
|
997
|
+
"""
|
|
998
|
+
return QuerySetCombination.combine(self, other_querysets, SetOperation.EXCEPT_OF)
|
|
999
|
+
|
|
1000
|
+
@CallsBeforeSetup.recorded
|
|
1001
|
+
def sample(
|
|
1002
|
+
self, percent: float, *, method: TableSampleMethod | str = TableSampleMethod.BERNOULLI, seed: int | None = None
|
|
1003
|
+
) -> Self:
|
|
1004
|
+
"""Reads a random sample of the model's table instead of all of it - ``TABLESAMPLE``: each row
|
|
1005
|
+
(``BERNOULLI``) or each storage block with its rows (``SYSTEM``) is kept with ``percent``
|
|
1006
|
+
chance, before the queryset's filters apply. The same ``seed`` reads the same sample while the
|
|
1007
|
+
table doesn't change.
|
|
1008
|
+
|
|
1009
|
+
Args:
|
|
1010
|
+
percent: The chance, in percent - an int or float from 0 to ``MAX_TABLE_SAMPLE_PERCENT``.
|
|
1011
|
+
method: ``TableSampleMethod.BERNOULLI`` or ``SYSTEM``, or its name in any case.
|
|
1012
|
+
seed: None for a new sample each run, or an int from 0 to ``MAX_TABLE_SAMPLE_SEED``.
|
|
1013
|
+
|
|
1014
|
+
Returns:
|
|
1015
|
+
The queryset reading the sample.
|
|
1016
|
+
|
|
1017
|
+
Raises:
|
|
1018
|
+
QueryError: An argument is of another type or out of its range; the queryset is combined.
|
|
1019
|
+
UnSupportedError: When run - the database has no ``TABLESAMPLE``.
|
|
1020
|
+
"""
|
|
1021
|
+
QuerySetCombination.raise_if_combined(self, "sample")
|
|
1022
|
+
table_sample = TableSample.build(percent, method, seed)
|
|
1023
|
+
queryset = self._clone()
|
|
1024
|
+
queryset._table_sample = table_sample
|
|
1025
|
+
return queryset
|
|
1026
|
+
|
|
1027
|
+
@CallsBeforeSetup.recorded
|
|
1028
|
+
def with_cte(self, name: str, query: AwaitableQuery[Any] | Selectable) -> Self:
|
|
1029
|
+
"""Attaches a named ``WITH`` to the queryset's SQL - recursive when ``query`` references its
|
|
1030
|
+
own name. The queryset still selects from the model's table; its rows are read from the CTE
|
|
1031
|
+
by a filter (``id__in=CteRows(name, "id")``), a ``Subquery`` or hand-built SQL. A walk along a
|
|
1032
|
+
relation of the model to itself is ``with_recursive()``.
|
|
1033
|
+
|
|
1034
|
+
A hand-built ``Selectable`` doesn't get the model's row scope
|
|
1035
|
+
(``Meta.soft_delete_field``/``Meta.tenant_field``): a recursive step without it walks
|
|
1036
|
+
through a hidden row. Add ``RowScopes.of(model).get_criterion(...)`` to the base case and to
|
|
1037
|
+
the step.
|
|
1038
|
+
|
|
1039
|
+
Args:
|
|
1040
|
+
name: The CTE's name.
|
|
1041
|
+
query: A queryset, or a ``hare.sql`` ``Selectable`` built with the ``query_class`` of
|
|
1042
|
+
the connection the query runs on.
|
|
1043
|
+
|
|
1044
|
+
Example:
|
|
1045
|
+
::
|
|
1046
|
+
|
|
1047
|
+
connection = Category.get_connection()
|
|
1048
|
+
query_class = connection.query_class
|
|
1049
|
+
category, ancestors = Table("category"), Table("ancestors")
|
|
1050
|
+
scope = RowScopes.of(Category).get_criterion(
|
|
1051
|
+
category, dialect=connection.dialect, connection=connection
|
|
1052
|
+
)
|
|
1053
|
+
base_where = category.id == root_id
|
|
1054
|
+
step_where = category.id == ancestors.parent_id
|
|
1055
|
+
if scope is not None:
|
|
1056
|
+
base_where, step_where = base_where & scope, step_where & scope
|
|
1057
|
+
columns = (category.id, category.parent_id)
|
|
1058
|
+
base = query_class.from_(category).select(*columns).where(base_where)
|
|
1059
|
+
step = query_class.from_(category).join(ancestors).on(step_where).select(*columns)
|
|
1060
|
+
union_all = base * step
|
|
1061
|
+
union_all.base_query.wrap_set_operation_queries = False
|
|
1062
|
+
await (
|
|
1063
|
+
Category.objects.all()
|
|
1064
|
+
.using(connection)
|
|
1065
|
+
.with_cte("ancestors", union_all)
|
|
1066
|
+
.filter(id__in=CteRows("ancestors", "id"))
|
|
1067
|
+
)
|
|
1068
|
+
"""
|
|
1069
|
+
QuerySetCombination.raise_if_combined(self, "with_cte")
|
|
1070
|
+
queryset = self._clone()
|
|
1071
|
+
# A queryset selecting values is built by its values query.
|
|
1072
|
+
cte_body = query._get_compiler() if isinstance(query, QuerySpecification) else query
|
|
1073
|
+
queryset._with_ctes = (*queryset._with_ctes, (name, cte_body))
|
|
1074
|
+
return queryset
|
|
1075
|
+
|
|
1076
|
+
def with_recursive(self, relation: str, *, max_depth: int | None = None) -> QuerySet[TModel, TModel]:
|
|
1077
|
+
"""The rows reachable from this queryset's rows through ``relation`` - a relation of the model
|
|
1078
|
+
to itself - followed again and again, these rows included, in one ``WITH RECURSIVE`` query:
|
|
1079
|
+
``Category.objects.filter(pk=root.pk).with_recursive("children")`` is the root and every
|
|
1080
|
+
descendant, ``with_recursive("parent")`` a row and its ancestors. A row reached twice comes
|
|
1081
|
+
once, so a cycle ends; the rows the model's default scope hides aren't walked through.
|
|
1082
|
+
|
|
1083
|
+
Args:
|
|
1084
|
+
relation: The relation - forward, reverse or many-to-many.
|
|
1085
|
+
max_depth: How many steps from this queryset's rows - 0 for them alone; None for no
|
|
1086
|
+
limit.
|
|
1087
|
+
|
|
1088
|
+
Returns:
|
|
1089
|
+
A queryset of the model's rows reached - on this queryset's connection and with its
|
|
1090
|
+
visibility, otherwise unfiltered, to filter, order and read like any other.
|
|
1091
|
+
|
|
1092
|
+
Raises:
|
|
1093
|
+
QueryError: ``max_depth`` isn't None or an int in ``0..MAX_RECURSIVE_DEPTH``; the
|
|
1094
|
+
queryset is combined (``union()``...).
|
|
1095
|
+
FieldError: When run - ``relation`` isn't a relation of the model to itself.
|
|
1096
|
+
"""
|
|
1097
|
+
QuerySetCombination.raise_if_combined(self, "with_recursive")
|
|
1098
|
+
reachable_keys = RecursiveRows(self, relation, max_depth=max_depth)
|
|
1099
|
+
self.model._meta.raise_if_no_primary_key("with_recursive()")
|
|
1100
|
+
rows = cast("QuerySet[TModel, TModel]", self.model._meta.manager.get_queryset())
|
|
1101
|
+
rows._apply_connection(self._connection)
|
|
1102
|
+
rows._connection_explicitly_chosen = self._connection_explicitly_chosen
|
|
1103
|
+
rows._visibility = self._visibility
|
|
1104
|
+
primary_key_attribute = self.model._meta.primary_key_attribute
|
|
1105
|
+
key_filter = "pk__in" if isinstance(primary_key_attribute, tuple) else f"{primary_key_attribute}__in"
|
|
1106
|
+
return rows.filter(**{key_filter: reachable_keys})
|
|
1107
|
+
|
|
1108
|
+
@CallsBeforeSetup.recorded
|
|
1109
|
+
def select_for_update(
|
|
1110
|
+
self,
|
|
1111
|
+
*,
|
|
1112
|
+
nowait: bool = False,
|
|
1113
|
+
skip_locked: bool = False,
|
|
1114
|
+
of: Sequence[str] = (),
|
|
1115
|
+
no_key: bool = False,
|
|
1116
|
+
share: bool = False,
|
|
1117
|
+
key_share: bool = False,
|
|
1118
|
+
) -> Self:
|
|
1119
|
+
"""
|
|
1120
|
+
The queryset locking its rows until the end of the transaction - ``SELECT ... FOR UPDATE``.
|
|
1121
|
+
|
|
1122
|
+
Args:
|
|
1123
|
+
share: If `True`, take the shared ``FOR SHARE`` lock - other transactions may lock the
|
|
1124
|
+
rows the same way, none may update or delete them.
|
|
1125
|
+
key_share: If `True`, take the weakest ``FOR KEY SHARE`` lock - it keeps the rows from
|
|
1126
|
+
being deleted or having their key changed only.
|
|
1127
|
+
nowait: If `True`, raise an error if the lock cannot be obtained immediately.
|
|
1128
|
+
skip_locked: If `True`, skip rows that are already locked by other transactions
|
|
1129
|
+
instead of waiting.
|
|
1130
|
+
of: What to lock when the query joins related tables: ``"self"`` (or the model's own
|
|
1131
|
+
table name) for the model's rows, and a forward relation path as passed to
|
|
1132
|
+
``select_related()`` (``"author"``, ``"author__country"``) for a joined model's
|
|
1133
|
+
rows. A named relation is joined with INNER JOIN, so every hop of its path must be
|
|
1134
|
+
a NOT NULL foreign key with a database constraint and no soft delete/tenant/
|
|
1135
|
+
``Select(extra_condition=...)`` condition. By default, all fetched rows are
|
|
1136
|
+
locked - only the model's own rows when the query joins any relation.
|
|
1137
|
+
no_key: If `True`, use the lower SELECT ... FOR NO KEY UPDATE lock strength to allow
|
|
1138
|
+
creating or deleting rows in other tables that reference the locked rows via foreign
|
|
1139
|
+
keys; a plain ``FOR UPDATE`` where the dialect has no such strength
|
|
1140
|
+
(``Features.supports_select_for_no_key_update``).
|
|
1141
|
+
|
|
1142
|
+
Raises:
|
|
1143
|
+
QueryError: ``nowait`` and ``skip_locked``, or more than one of ``no_key``, ``share`` and
|
|
1144
|
+
``key_share``, are set; or, when the query is built, an
|
|
1145
|
+
``of`` name is not a forward relation path, isn't joined by the query, or crosses a
|
|
1146
|
+
relation that can't be INNER JOINed.
|
|
1147
|
+
UnSupportedError: when the query runs, the database has no SELECT ... FOR UPDATE
|
|
1148
|
+
equivalent, or no ``FOR SHARE``/``FOR KEY SHARE`` asked for.
|
|
1149
|
+
"""
|
|
1150
|
+
QuerySetCombination.raise_if_combined(self, "select_for_update")
|
|
1151
|
+
if nowait and skip_locked:
|
|
1152
|
+
raise QueryError("select_for_update() options nowait and skip_locked are mutually exclusive")
|
|
1153
|
+
strengths = [
|
|
1154
|
+
strength
|
|
1155
|
+
for strength, chosen in (
|
|
1156
|
+
(RowLockStrength.NO_KEY_UPDATE, no_key),
|
|
1157
|
+
(RowLockStrength.SHARE, share),
|
|
1158
|
+
(RowLockStrength.KEY_SHARE, key_share),
|
|
1159
|
+
)
|
|
1160
|
+
if chosen
|
|
1161
|
+
]
|
|
1162
|
+
if len(strengths) > 1:
|
|
1163
|
+
raise QueryError("select_for_update() takes one of no_key, share and key_share")
|
|
1164
|
+
of = tuple(of)
|
|
1165
|
+
queryset = self._clone()
|
|
1166
|
+
queryset._select_for_update = True
|
|
1167
|
+
queryset._select_for_update_nowait = nowait
|
|
1168
|
+
queryset._select_for_update_skip_locked = skip_locked
|
|
1169
|
+
queryset._select_for_update_of = set(of)
|
|
1170
|
+
queryset._select_for_update_strength = strengths[0] if strengths else None
|
|
1171
|
+
return queryset
|
|
1172
|
+
|
|
1173
|
+
@CallsBeforeSetup.recorded
|
|
1174
|
+
def annotate(self, **kwargs: Expression | Term) -> Self:
|
|
1175
|
+
"""
|
|
1176
|
+
The queryset with each row's value of every expression given, under its name.
|
|
1177
|
+
|
|
1178
|
+
Raises:
|
|
1179
|
+
TypeError: A value is neither an expression nor a SQL term - a bare field name, say.
|
|
1180
|
+
FieldError: A key is a field of the model or ``pk``.
|
|
1181
|
+
"""
|
|
1182
|
+
QuerySetCombination.raise_if_combined(self, "annotate")
|
|
1183
|
+
kwargs = AnnotationArguments.get_annotations(kwargs)
|
|
1184
|
+
relation_aliases = {key: value for key, value in kwargs.items() if isinstance(value, NamedJoin)}
|
|
1185
|
+
if relation_aliases:
|
|
1186
|
+
# A named JOIN (FilteredRelation, Lateral) is never a selected value - annotated, it is an alias.
|
|
1187
|
+
other_annotations = {key: value for key, value in kwargs.items() if key not in relation_aliases}
|
|
1188
|
+
aliased = self.alias(**relation_aliases)
|
|
1189
|
+
return aliased.annotate(**other_annotations) if other_annotations else aliased
|
|
1190
|
+
AnnotationArguments.raise_if_annotation_names_collide_with_fields(self, kwargs)
|
|
1191
|
+
queryset = self._clone_keeping_calls()
|
|
1192
|
+
AnnotationArguments.detach_annotation_descriptions(queryset, kwargs)
|
|
1193
|
+
for key, annotation in kwargs.items():
|
|
1194
|
+
queryset._annotations[key] = annotation
|
|
1195
|
+
# A previous .alias(key=...) on this same key is superseded by a real .annotate() -
|
|
1196
|
+
# the key should now behave like an ordinary annotation (selected by default).
|
|
1197
|
+
queryset._alias_keys = queryset._alias_keys - {key}
|
|
1198
|
+
if queryset._selection is not None:
|
|
1199
|
+
queryset._selection = queryset._selection.with_added_names(kwargs)
|
|
1200
|
+
return self._continue_annotation_call_signature(queryset, "annotate", kwargs)
|
|
1201
|
+
|
|
1202
|
+
@CallsBeforeSetup.recorded
|
|
1203
|
+
def alias(self, **kwargs: Expression | Term) -> Self:
|
|
1204
|
+
"""
|
|
1205
|
+
Like ``.annotate()`` - usable in ``.filter()``/``.order_by()`` - but the expression is
|
|
1206
|
+
never added to the SELECT list on its own, only when explicitly requested via
|
|
1207
|
+
``.values()``/``.values_list()``.
|
|
1208
|
+
|
|
1209
|
+
Raises:
|
|
1210
|
+
TypeError: A value is neither an expression nor a SQL term - a bare field name, say.
|
|
1211
|
+
FieldError: A key is a field of the model or ``pk``.
|
|
1212
|
+
"""
|
|
1213
|
+
QuerySetCombination.raise_if_combined(self, "alias")
|
|
1214
|
+
kwargs = AnnotationArguments.get_annotations(kwargs)
|
|
1215
|
+
AnnotationArguments.raise_if_annotation_names_collide_with_fields(self, kwargs)
|
|
1216
|
+
queryset = self._clone_keeping_calls()
|
|
1217
|
+
AnnotationArguments.detach_annotation_descriptions(queryset, kwargs)
|
|
1218
|
+
for key, annotation in kwargs.items():
|
|
1219
|
+
if isinstance(annotation, NamedJoin):
|
|
1220
|
+
annotation.check_for_model(self._get_probe_expression_context(self._annotations))
|
|
1221
|
+
annotation = annotation.with_name(key)
|
|
1222
|
+
queryset._annotations[key] = annotation
|
|
1223
|
+
queryset._alias_keys = queryset._alias_keys | {key}
|
|
1224
|
+
if queryset._selection is not None:
|
|
1225
|
+
queryset._selection = queryset._selection.with_added_names((), kwargs)
|
|
1226
|
+
return self._continue_annotation_call_signature(
|
|
1227
|
+
queryset, "alias", {key: queryset._annotations[key] for key in kwargs}
|
|
1228
|
+
)
|
|
1229
|
+
|
|
1230
|
+
def _continue_annotation_call_signature(self, queryset: Self, call_name: str, annotations: dict[str, Any]) -> Self:
|
|
1231
|
+
"""Gives a queryset ``annotate()``/``alias()`` made this one's call signature with the call
|
|
1232
|
+
appended, when each annotation describes itself for a plan - the expressions are the call's
|
|
1233
|
+
values, each described by its own description; else the queryset has no call signature.
|
|
1234
|
+
|
|
1235
|
+
Args:
|
|
1236
|
+
queryset: The queryset made.
|
|
1237
|
+
call_name: The call.
|
|
1238
|
+
annotations: The annotations it added, by key.
|
|
1239
|
+
|
|
1240
|
+
Returns:
|
|
1241
|
+
``queryset``.
|
|
1242
|
+
"""
|
|
1243
|
+
if self._call_signature is None:
|
|
1244
|
+
return queryset
|
|
1245
|
+
for annotation in annotations.values():
|
|
1246
|
+
if not isinstance(annotation, Plannable):
|
|
1247
|
+
queryset._call_signature = None
|
|
1248
|
+
return queryset
|
|
1249
|
+
return self._continue_call_signature(queryset, (call_name, tuple(annotations)), tuple(annotations.values()))
|
|
1250
|
+
|
|
1251
|
+
@CallsBeforeSetup.recorded
|
|
1252
|
+
def group_by(self, *fields: str | GroupingSet) -> Self:
|
|
1253
|
+
"""
|
|
1254
|
+
The queryset of groups of rows by the fields given - before or after
|
|
1255
|
+
``.values()``/``.values_list()``. One ``Rollup``/``Cube``/``GroupingSets`` among the fields groups
|
|
1256
|
+
the rows several ways at once - the plain fields given beside it are in every grouping.
|
|
1257
|
+
|
|
1258
|
+
Raises:
|
|
1259
|
+
QueryError: More than one ``Rollup``/``Cube``/``GroupingSets`` is given, or a field isn't a name.
|
|
1260
|
+
"""
|
|
1261
|
+
QuerySetCombination.raise_if_combined(self, "group_by")
|
|
1262
|
+
grouping_sets = [field for field in fields if isinstance(field, GroupingSet)]
|
|
1263
|
+
if len(grouping_sets) > 1:
|
|
1264
|
+
raise QueryError("group_by() takes one Rollup, Cube or GroupingSets")
|
|
1265
|
+
grouping_set = grouping_sets[0] if grouping_sets else None
|
|
1266
|
+
# Checked as names below - an expression is refused, not left out.
|
|
1267
|
+
plain_names = tuple(field for field in fields if not isinstance(field, GroupingSet))
|
|
1268
|
+
FilterArguments.raise_if_not_names(
|
|
1269
|
+
self, (*plain_names, *(grouping_set.field_names if grouping_set is not None else ())), "group_by"
|
|
1270
|
+
)
|
|
1271
|
+
queryset = self._clone_keeping_calls()
|
|
1272
|
+
queryset._group_bys = (
|
|
1273
|
+
plain_names if grouping_set is None else tuple(dict.fromkeys((*plain_names, *grouping_set.field_names)))
|
|
1274
|
+
)
|
|
1275
|
+
queryset._grouping_set = grouping_set
|
|
1276
|
+
return self._continue_call_signature(
|
|
1277
|
+
queryset, ("group_by", plain_names, None if grouping_set is None else grouping_set.get_plan_key())
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1280
|
+
@overload
|
|
1281
|
+
def values_list(
|
|
1282
|
+
self,
|
|
1283
|
+
*field_names: str,
|
|
1284
|
+
flat: Literal[False] = False,
|
|
1285
|
+
named: Literal[False] = False,
|
|
1286
|
+
**expressions: Expression | Term,
|
|
1287
|
+
) -> QuerySet[TModel, tuple[Any, ...], TAnnotations]: ...
|
|
1288
|
+
|
|
1289
|
+
@overload
|
|
1290
|
+
def values_list(
|
|
1291
|
+
self, *field_names: str, flat: bool = False, named: bool = False, **expressions: Expression | Term
|
|
1292
|
+
) -> QuerySet[TModel, Any, TAnnotations]: ...
|
|
1293
|
+
|
|
1294
|
+
@CallsBeforeSetup.recorded
|
|
1295
|
+
def values_list(
|
|
1296
|
+
self, *field_names: str, flat: bool = False, named: bool = False, **expressions: Expression | Term
|
|
1297
|
+
) -> QuerySet[TModel, Any, TAnnotations]:
|
|
1298
|
+
"""Makes the queryset return tuples of the given fields - all fields in declaration order when
|
|
1299
|
+
none are given. A kwarg selects an expression under its key, after the positional names. A
|
|
1300
|
+
name may read inside a field's value, as in ``.values()``. On a queryset already selecting
|
|
1301
|
+
values, it selects other fields instead.
|
|
1302
|
+
|
|
1303
|
+
Args:
|
|
1304
|
+
field_names: Field names.
|
|
1305
|
+
flat: Return the single selected value instead of a one-item tuple.
|
|
1306
|
+
named: Return namedtuples; a name that isn't an identifier becomes ``_<index>``.
|
|
1307
|
+
expressions: Expressions by key.
|
|
1308
|
+
|
|
1309
|
+
Raises:
|
|
1310
|
+
QueryError: ``flat`` and ``named`` are both set, ``flat`` with other than one name, a
|
|
1311
|
+
positional argument isn't a field name, or a kwarg isn't an expression.
|
|
1312
|
+
"""
|
|
1313
|
+
if self._combination is not None:
|
|
1314
|
+
return CombinedDerivedQueries.get_values_queryset( # type: ignore[return-value]
|
|
1315
|
+
QuerySetCombination.get_combined_query(self),
|
|
1316
|
+
lambda branch: branch.values_list(*field_names, flat=flat, named=named, **expressions),
|
|
1317
|
+
)
|
|
1318
|
+
if flat and named:
|
|
1319
|
+
raise QueryError(".values_list() can't use flat=True and named=True together.")
|
|
1320
|
+
if GenericForeignKeyFieldInstance.declared_names and (
|
|
1321
|
+
type_aliases := GenericForeignKeyTypes.get_pending_type_aliases(self, field_names)
|
|
1322
|
+
):
|
|
1323
|
+
return self.alias(**type_aliases).values_list(*field_names, flat=flat, named=named, **expressions)
|
|
1324
|
+
queryset = self._get_values_source_queryset()
|
|
1325
|
+
FilterArguments.check_selected_names(queryset, field_names, "values_list")
|
|
1326
|
+
ValuesArguments.raise_if_values_unusable(
|
|
1327
|
+
queryset, ".values_list()", field_names, expressions, allow_field_name_kwargs=False
|
|
1328
|
+
)
|
|
1329
|
+
names = (*field_names, *expressions)
|
|
1330
|
+
if flat and len(names or ValuesArguments.get_every_selected_name(queryset)) != 1:
|
|
1331
|
+
raise QueryError(".values_list(flat=True) selects exactly one field")
|
|
1332
|
+
queryset = queryset.alias(**expressions) if expressions else queryset._clone()
|
|
1333
|
+
shape = RowShape.FLAT if flat else RowShape.NAMED if named else RowShape.TUPLE
|
|
1334
|
+
queryset._selection = ValuesSelection(shape, field_names=names)
|
|
1335
|
+
if self._selection is None and not expressions:
|
|
1336
|
+
self._continue_call_signature(queryset, ("values_list", field_names, flat, named))
|
|
1337
|
+
else:
|
|
1338
|
+
# The calls of the alias() above select none of it - they key no plan of these rows.
|
|
1339
|
+
queryset._call_signature = None
|
|
1340
|
+
return queryset # type: ignore[return-value]
|
|
1341
|
+
|
|
1342
|
+
@CallsBeforeSetup.recorded
|
|
1343
|
+
def values(
|
|
1344
|
+
self, *field_names: str, **expressions: str | Expression | Term
|
|
1345
|
+
) -> QuerySet[TModel, dict[str, Any], TAnnotations]:
|
|
1346
|
+
"""Makes the queryset return dicts - of all fields when no arguments are given. A kwarg renames
|
|
1347
|
+
a field (``key=field_name``) or selects an expression under its key. A name may read inside
|
|
1348
|
+
a field's value, through relations too: a JSON key path, an array item or range bound, or a
|
|
1349
|
+
part of a date, time or datetime. On a queryset already selecting values, it selects other
|
|
1350
|
+
fields instead.
|
|
1351
|
+
|
|
1352
|
+
Raises:
|
|
1353
|
+
FieldError: A key is given twice, or an expression kwarg is named after a field of the
|
|
1354
|
+
model.
|
|
1355
|
+
QueryError: A positional argument isn't a field name, or a kwarg is neither a field name
|
|
1356
|
+
nor an expression.
|
|
1357
|
+
"""
|
|
1358
|
+
if self._combination is not None:
|
|
1359
|
+
return CombinedDerivedQueries.get_values_queryset( # type: ignore[return-value]
|
|
1360
|
+
QuerySetCombination.get_combined_query(self), lambda branch: branch.values(*field_names, **expressions)
|
|
1361
|
+
)
|
|
1362
|
+
if GenericForeignKeyFieldInstance.declared_names and (
|
|
1363
|
+
type_aliases := GenericForeignKeyTypes.get_pending_type_aliases(self, field_names)
|
|
1364
|
+
):
|
|
1365
|
+
return self.alias(**type_aliases).values(*field_names, **expressions)
|
|
1366
|
+
queryset = self._get_values_source_queryset()
|
|
1367
|
+
FilterArguments.check_selected_names(queryset, field_names, "values")
|
|
1368
|
+
ValuesArguments.raise_if_values_unusable(
|
|
1369
|
+
queryset, ".values()", field_names, expressions, allow_field_name_kwargs=True
|
|
1370
|
+
)
|
|
1371
|
+
selected_keys: set[str] = set()
|
|
1372
|
+
for key in (*field_names, *expressions):
|
|
1373
|
+
if key in selected_keys:
|
|
1374
|
+
raise FieldError(f"Duplicate key {key}")
|
|
1375
|
+
selected_keys.add(key)
|
|
1376
|
+
# An expression is an alias of the queryset under its key; so is a renamed field
|
|
1377
|
+
# (values(k="name")) - a later filter, ordering or aggregate reads either by that name. A new
|
|
1378
|
+
# name that is a field or an annotation of the model keeps meaning that one.
|
|
1379
|
+
aliases: dict[str, Expression | Term] = {
|
|
1380
|
+
key: value for key, value in expressions.items() if not isinstance(value, str)
|
|
1381
|
+
}
|
|
1382
|
+
aliases.update(
|
|
1383
|
+
(key, F(value))
|
|
1384
|
+
for key, value in expressions.items()
|
|
1385
|
+
if isinstance(value, str)
|
|
1386
|
+
and key not in (value, "pk")
|
|
1387
|
+
and key not in self.model._meta.fields_map
|
|
1388
|
+
and key not in queryset._annotations
|
|
1389
|
+
)
|
|
1390
|
+
queryset = queryset.alias(**aliases) if aliases else queryset._clone()
|
|
1391
|
+
queryset._selection = ValuesSelection(
|
|
1392
|
+
RowShape.DICT,
|
|
1393
|
+
field_names=field_names,
|
|
1394
|
+
renamed_fields=tuple(
|
|
1395
|
+
(key, value if isinstance(value, str) else key) for key, value in expressions.items()
|
|
1396
|
+
),
|
|
1397
|
+
)
|
|
1398
|
+
if self._selection is None and not expressions:
|
|
1399
|
+
self._continue_call_signature(queryset, ("values", field_names))
|
|
1400
|
+
else:
|
|
1401
|
+
# The calls of the alias() above select none of it - they key no plan of these rows.
|
|
1402
|
+
queryset._call_signature = None
|
|
1403
|
+
return queryset # type: ignore[return-value]
|
|
1404
|
+
|
|
1405
|
+
def _get_values_source_queryset(self) -> QuerySet[TModel, TModel]:
|
|
1406
|
+
"""The queryset a ``.values()``/``.values_list()`` call selects from - this one, or, when it
|
|
1407
|
+
already selects values, this one selecting model instances again, explicitly grouped by the
|
|
1408
|
+
selected fields an aggregate implicitly groups it by.
|
|
1409
|
+
|
|
1410
|
+
Returns:
|
|
1411
|
+
The queryset.
|
|
1412
|
+
"""
|
|
1413
|
+
if self._selection is None:
|
|
1414
|
+
return self # type: ignore[return-value]
|
|
1415
|
+
return ValuesGrouping.get_grouped_source_queryset(StatementSelection.get_values_query(self))
|
|
1416
|
+
|
|
1417
|
+
def _with_selection(self, selection: ValuesSelection | None) -> QuerySet[TModel, Any]:
|
|
1418
|
+
"""A clone returning its rows as ``selection`` selects them.
|
|
1419
|
+
|
|
1420
|
+
Args:
|
|
1421
|
+
selection: What the rows select, None for model instances.
|
|
1422
|
+
|
|
1423
|
+
Returns:
|
|
1424
|
+
The clone.
|
|
1425
|
+
"""
|
|
1426
|
+
queryset = self._clone()
|
|
1427
|
+
queryset._selection = selection
|
|
1428
|
+
return cast("QuerySet[TModel, Any]", queryset)
|
|
1429
|
+
|
|
1430
|
+
def _get_compiler(self) -> AwaitableQuery[Any]:
|
|
1431
|
+
"""The query building this queryset's SQL - the queryset itself for model instances.
|
|
1432
|
+
|
|
1433
|
+
Returns:
|
|
1434
|
+
The query.
|
|
1435
|
+
"""
|
|
1436
|
+
CallsBeforeSetup.raise_if_invalid(self)
|
|
1437
|
+
return StatementSelection.get_select_query(self)
|
|
1438
|
+
|
|
1439
|
+
def _raise_if_prefetching(self, method_name: str, result_description: str) -> None:
|
|
1440
|
+
"""Rejects a method returning no instances on a query prefetching relations.
|
|
1441
|
+
|
|
1442
|
+
Args:
|
|
1443
|
+
method_name: The method.
|
|
1444
|
+
result_description: What the method returns instead.
|
|
1445
|
+
|
|
1446
|
+
Raises:
|
|
1447
|
+
QueryError: ``prefetch_related()`` was called.
|
|
1448
|
+
"""
|
|
1449
|
+
if self._prefetch_map or self._prefetch_queries:
|
|
1450
|
+
raise QueryError(
|
|
1451
|
+
f"{method_name}() cannot be used with prefetch_related() - the result is {result_description}, "
|
|
1452
|
+
"not model instances, so there's nothing to attach a prefetched relation to."
|
|
1453
|
+
)
|
|
1454
|
+
|
|
1455
|
+
def _get_count_query(self) -> CountQuery:
|
|
1456
|
+
"""The number of rows - counted as returned when a primary key can repeat.
|
|
1457
|
+
|
|
1458
|
+
Raises:
|
|
1459
|
+
QueryError: ``prefetch_related()`` was called.
|
|
1460
|
+
"""
|
|
1461
|
+
self._raise_if_prefetching("count", "a plain int")
|
|
1462
|
+
rows_query = StatementSelection.get_rows_query_if_rows_repeat(self)
|
|
1463
|
+
count_query = CountQuery(self, rows_query=rows_query)
|
|
1464
|
+
if rows_query is None:
|
|
1465
|
+
self._hand_call_signature(count_query)
|
|
1466
|
+
return count_query
|
|
1467
|
+
|
|
1468
|
+
def _get_exists_query(self) -> ExistsQuery:
|
|
1469
|
+
"""Whether any row matches.
|
|
1470
|
+
|
|
1471
|
+
Raises:
|
|
1472
|
+
QueryError: ``prefetch_related()`` was called.
|
|
1473
|
+
"""
|
|
1474
|
+
self._raise_if_prefetching("exists", "a plain bool")
|
|
1475
|
+
# Without an offset the repeated rows can't change whether any row exists - a call of the
|
|
1476
|
+
# dialect's QuerySet method changing the rows can.
|
|
1477
|
+
rows_query = (
|
|
1478
|
+
StatementSelection.get_rows_query_if_rows_repeat(self)
|
|
1479
|
+
if self._offset or (self._extension_calls and QuerySetExtensions.changes_rows(self))
|
|
1480
|
+
else None
|
|
1481
|
+
)
|
|
1482
|
+
exists_query = ExistsQuery(self, rows_query=rows_query)
|
|
1483
|
+
if rows_query is None:
|
|
1484
|
+
self._hand_call_signature(exists_query)
|
|
1485
|
+
return exists_query
|
|
1486
|
+
|
|
1487
|
+
def _get_aggregate_query(self, **kwargs: Expression | Term) -> AggregateQuery:
|
|
1488
|
+
"""Aggregates over the rows - of a slice, restricted to them by their primary key.
|
|
1489
|
+
|
|
1490
|
+
Raises:
|
|
1491
|
+
QueryError: The query is sliced and its rows can repeat a primary key.
|
|
1492
|
+
QueryError: ``prefetch_related()`` was called.
|
|
1493
|
+
"""
|
|
1494
|
+
if self._limit is not None or self._offset:
|
|
1495
|
+
if RowMultiplication.rows_repeat_per_primary_key(ModelRowsQuery(self)) or (
|
|
1496
|
+
not self._distinct_on
|
|
1497
|
+
and StatementSelection.get_rows_query_if_rows_repeat(self, counts_changed_rows=False) is not None
|
|
1498
|
+
):
|
|
1499
|
+
raise QueryError(
|
|
1500
|
+
"aggregate() can't be used on a sliced queryset whose rows can repeat a primary key (a filter, "
|
|
1501
|
+
"annotation or ordering over a to-many relation) - the slice would hold repeated rows the "
|
|
1502
|
+
"aggregate can't tell apart. Aggregate a sliced .values()/.values_list() query instead."
|
|
1503
|
+
)
|
|
1504
|
+
# An unordered slice holds the first rows by primary key, the rows first() reads.
|
|
1505
|
+
rows_queryset = SingleRow.with_rows_as_subquery(
|
|
1506
|
+
OrderingArguments.with_primary_key_ordering_if_unordered_slice(self)
|
|
1507
|
+
)
|
|
1508
|
+
# A .distinct() slice's filters can still join a to-many relation: its rows are then
|
|
1509
|
+
# reduced to one per primary key before the metrics run, as an unsliced .distinct().
|
|
1510
|
+
rows_queryset._distinct = self._distinct and not self._distinct_on
|
|
1511
|
+
return rows_queryset.aggregate(**kwargs)
|
|
1512
|
+
self._raise_if_prefetching("aggregate", "a plain dict")
|
|
1513
|
+
aggregate_query = AggregateQuery(self, kwargs)
|
|
1514
|
+
self._hand_call_signature(aggregate_query)
|
|
1515
|
+
return aggregate_query
|
|
1516
|
+
|
|
1517
|
+
def _get_update_query(self, **kwargs: Any) -> UpdateQuery:
|
|
1518
|
+
"""Updates the rows.
|
|
1519
|
+
|
|
1520
|
+
Raises:
|
|
1521
|
+
QueryError, FieldError: A value is given to a field the update can't set.
|
|
1522
|
+
"""
|
|
1523
|
+
update_query = UpdateQuery(self, kwargs)
|
|
1524
|
+
self._hand_call_signature(update_query)
|
|
1525
|
+
return update_query
|
|
1526
|
+
|
|
1527
|
+
def _get_first(self, *, reverse: bool) -> QuerySetSingle[TRow | None]:
|
|
1528
|
+
"""The first (or last) row - of the ordering, else of the primary key. The last row
|
|
1529
|
+
reverses the ordering exactly; an unordered slice takes its rows by the primary key.
|
|
1530
|
+
|
|
1531
|
+
Args:
|
|
1532
|
+
reverse: Take the last row.
|
|
1533
|
+
|
|
1534
|
+
Returns:
|
|
1535
|
+
The single-row queryset.
|
|
1536
|
+
|
|
1537
|
+
Raises:
|
|
1538
|
+
QueryError: ``last()`` after ``after_cursor()``/``before_cursor()``.
|
|
1539
|
+
"""
|
|
1540
|
+
if not reverse:
|
|
1541
|
+
queryset = self._clone()
|
|
1542
|
+
if not self._apply_default_ordering(self._orderings) and not self._group_bys and not self._distinct_on:
|
|
1543
|
+
queryset._orderings = [
|
|
1544
|
+
(primary_key_attribute_name, Order.ASC)
|
|
1545
|
+
for primary_key_attribute_name in self.model._meta.primary_key_attribute_names
|
|
1546
|
+
]
|
|
1547
|
+
return SingleRow.as_single(queryset)
|
|
1548
|
+
OrderingArguments.forbid_reordering_after_cursor(self, "last")
|
|
1549
|
+
queryset = SingleRow.with_rows_as_subquery(
|
|
1550
|
+
OrderingArguments.with_primary_key_ordering_if_unordered_slice(self)
|
|
1551
|
+
)
|
|
1552
|
+
effective_orderings = self._apply_default_ordering(queryset._orderings)
|
|
1553
|
+
if effective_orderings:
|
|
1554
|
+
queryset._orderings = [(field, order_type.get_reversed()) for field, order_type in effective_orderings]
|
|
1555
|
+
else:
|
|
1556
|
+
queryset._orderings = [
|
|
1557
|
+
(primary_key_attribute_name, Order.DESC)
|
|
1558
|
+
for primary_key_attribute_name in self.model._meta.primary_key_attribute_names
|
|
1559
|
+
]
|
|
1560
|
+
return SingleRow.as_single(queryset)
|
|
1561
|
+
|
|
1562
|
+
def get_plan_description(self, context: PlanContext) -> PlanDescription | None:
|
|
1563
|
+
"""Describes this query built into another one.
|
|
1564
|
+
|
|
1565
|
+
Args:
|
|
1566
|
+
context: The enclosing query's - this query resolves names against its own
|
|
1567
|
+
annotations.
|
|
1568
|
+
|
|
1569
|
+
Returns:
|
|
1570
|
+
The description, None for a query that keeps no plan.
|
|
1571
|
+
"""
|
|
1572
|
+
if self._combination is not None:
|
|
1573
|
+
return QuerySetCombination.get_combined_query(self).get_plan_description(context)
|
|
1574
|
+
if self._selection is not None:
|
|
1575
|
+
return StatementSelection.get_values_query(self).get_plan_description(context)
|
|
1576
|
+
return ModelRowsQuery(self).get_plan_description(context)
|
|
1577
|
+
|
|
1578
|
+
@CallsBeforeSetup.recorded_result
|
|
1579
|
+
def delete(self) -> DeleteQuery:
|
|
1580
|
+
"""
|
|
1581
|
+
Deletes every row of the queryset, with the cascade its relations declare.
|
|
1582
|
+
|
|
1583
|
+
Raises:
|
|
1584
|
+
QueryError: The queryset selects values - call ``delete()`` before ``.values()``, like Django.
|
|
1585
|
+
"""
|
|
1586
|
+
WrittenTargetChecks.raise_if_refused(self, "delete")
|
|
1587
|
+
|
|
1588
|
+
return DeleteQuery(self)
|
|
1589
|
+
|
|
1590
|
+
@CallsBeforeSetup.recorded_result
|
|
1591
|
+
def hard_delete(self) -> HardDeleteQuery:
|
|
1592
|
+
"""Deletes every matched row for real, even with ``Meta.soft_delete_field`` - a soft-deleted
|
|
1593
|
+
row too, when the queryset sees it (``only_deleted().hard_delete()``). Related rows follow
|
|
1594
|
+
their ``on_delete``.
|
|
1595
|
+
|
|
1596
|
+
Raises:
|
|
1597
|
+
QueryError: The queryset selects values.
|
|
1598
|
+
"""
|
|
1599
|
+
WrittenTargetChecks.raise_if_refused(self, "hard_delete")
|
|
1600
|
+
|
|
1601
|
+
return HardDeleteQuery(self)
|
|
1602
|
+
|
|
1603
|
+
def restore(self, *, cascade: bool = False) -> RestoreQuery:
|
|
1604
|
+
"""Reverses the soft delete of the queryset's rows - of those among them that are
|
|
1605
|
+
soft-deleted, whatever visibility the queryset has (``Model.objects.filter(...).restore()``
|
|
1606
|
+
reads the deleted rows). Awaits to the number of rows restored.
|
|
1607
|
+
|
|
1608
|
+
Args:
|
|
1609
|
+
cascade: Also restore the rows the soft delete of each removed along with it - those still
|
|
1610
|
+
carrying its deletion time, as ``Model.restore(cascade=True)``.
|
|
1611
|
+
|
|
1612
|
+
Returns:
|
|
1613
|
+
The restore.
|
|
1614
|
+
|
|
1615
|
+
Raises:
|
|
1616
|
+
QueryError: The model has no ``Meta.soft_delete_field``; the queryset selects values, is
|
|
1617
|
+
combined or reads a sample.
|
|
1618
|
+
"""
|
|
1619
|
+
WrittenTargetChecks.raise_if_refused(self, "restore")
|
|
1620
|
+
return RestoreQuery(self, cascade)
|
|
1621
|
+
|
|
1622
|
+
@CallsBeforeSetup.recorded_result
|
|
1623
|
+
def update(self, **kwargs: Any) -> UpdateQuery:
|
|
1624
|
+
"""
|
|
1625
|
+
Sets the fields given on every row of the queryset, by one ``UPDATE``:
|
|
1626
|
+
|
|
1627
|
+
Example:
|
|
1628
|
+
::
|
|
1629
|
+
|
|
1630
|
+
await Employee.objects.filter(occupation="developer").update(salary=5000)
|
|
1631
|
+
|
|
1632
|
+
Raises:
|
|
1633
|
+
QueryError: If ``Meta.soft_delete_field`` is among ``kwargs`` - use
|
|
1634
|
+
``.delete()`` (which applies cascade logic a direct field update would bypass) or
|
|
1635
|
+
``.restore()`` (``cascade=True`` brings back what the delete cascaded) instead. Also raised if
|
|
1636
|
+
``Meta.optimistic_lock_field`` is among ``kwargs`` - it's bumped automatically on every
|
|
1637
|
+
``.update()`` call, not set directly. Also raised
|
|
1638
|
+
if ``Meta.tenant_field`` is among ``kwargs`` with a value outside the model's
|
|
1639
|
+
tenant scope (``Tenancy.scope()``), with an expression, or on a queryset with no
|
|
1640
|
+
tenant scope (``.all_tenants()`` included) - rows move only between the tenants
|
|
1641
|
+
the scope allows.
|
|
1642
|
+
QueryError: The queryset selects values whose rows are groups (an aggregate annotation
|
|
1643
|
+
or ``.group_by()``), or is sliced over rows that aren't one per model row - which
|
|
1644
|
+
model rows to update would be ambiguous. Otherwise the selected fields don't change
|
|
1645
|
+
which rows are updated, like Django.
|
|
1646
|
+
"""
|
|
1647
|
+
WrittenTargetChecks.raise_if_refused(self, "update", allows_values=True)
|
|
1648
|
+
# The values as they are now - the update runs when awaited.
|
|
1649
|
+
kwargs = {key: FilterValues.get_detached_value(value, written=True) for key, value in kwargs.items()}
|
|
1650
|
+
if self.model._meta.generic_foreign_key_fields:
|
|
1651
|
+
kwargs = GenericForeignKeys.expand_kwargs(self.model._meta, kwargs, apply_defaults=False)
|
|
1652
|
+
return StatementSelection.get_rows_source(self)._get_update_query(**kwargs)
|
|
1653
|
+
|
|
1654
|
+
@CallsBeforeSetup.recorded_result
|
|
1655
|
+
def count(self) -> CountQuery:
|
|
1656
|
+
"""
|
|
1657
|
+
The number of rows of the queryset.
|
|
1658
|
+
|
|
1659
|
+
Raises:
|
|
1660
|
+
QueryError: prefetch_related() was called earlier in the chain.
|
|
1661
|
+
QueryError: The queryset locks its rows (``select_for_update()``).
|
|
1662
|
+
"""
|
|
1663
|
+
if self._select_for_update:
|
|
1664
|
+
raise QueryError(LOCKED_SUMMARY_MESSAGE.format(method_name="count"))
|
|
1665
|
+
return StatementSelection.get_rows_source(self)._get_count_query()
|
|
1666
|
+
|
|
1667
|
+
@CallsBeforeSetup.recorded_result
|
|
1668
|
+
def aggregate(self, **kwargs: Expression | Term) -> AggregateQuery:
|
|
1669
|
+
"""Computes aggregate expressions (``Sum``, ``Avg``, ``Count``, ...) across the whole queryset
|
|
1670
|
+
in one query and returns one dict keyed by the kwargs. After ``.group_by()`` they run over
|
|
1671
|
+
the grouped rows and read only the group-by fields and annotations. A sliced queryset
|
|
1672
|
+
aggregates the rows of its slice.
|
|
1673
|
+
|
|
1674
|
+
Example:
|
|
1675
|
+
::
|
|
1676
|
+
|
|
1677
|
+
await Event.objects.filter(tournament=tournament).aggregate(total=Count("event_id"), avg=Avg("id"))
|
|
1678
|
+
|
|
1679
|
+
Raises:
|
|
1680
|
+
QueryError: The queryset is sliced and its rows can repeat a primary key, is
|
|
1681
|
+
``.distinct(<fields>)``, or locks its rows (``select_for_update()``).
|
|
1682
|
+
QueryError: prefetch_related() was called earlier in the chain.
|
|
1683
|
+
"""
|
|
1684
|
+
if self._select_for_update:
|
|
1685
|
+
raise QueryError(LOCKED_SUMMARY_MESSAGE.format(method_name="aggregate"))
|
|
1686
|
+
if self._distinct_on:
|
|
1687
|
+
raise QueryError(AGGREGATE_OVER_DISTINCT_ON_MESSAGE)
|
|
1688
|
+
if self._grouping_set is not None:
|
|
1689
|
+
raise QueryError(AGGREGATE_OVER_GROUPING_SETS_MESSAGE.format(grouping_set=self._grouping_set))
|
|
1690
|
+
return StatementSelection.get_rows_source(self)._get_aggregate_query(**kwargs)
|
|
1691
|
+
|
|
1692
|
+
@CallsBeforeSetup.recorded_result
|
|
1693
|
+
def exists(self) -> ExistsQuery:
|
|
1694
|
+
"""
|
|
1695
|
+
Whether the queryset has any row.
|
|
1696
|
+
|
|
1697
|
+
Raises:
|
|
1698
|
+
QueryError: prefetch_related() was called earlier in the chain.
|
|
1699
|
+
QueryError: The queryset locks its rows (``select_for_update()``).
|
|
1700
|
+
"""
|
|
1701
|
+
if self._select_for_update:
|
|
1702
|
+
raise QueryError(LOCKED_SUMMARY_MESSAGE.format(method_name="exists"))
|
|
1703
|
+
return StatementSelection.get_rows_source(self)._get_exists_query()
|
|
1704
|
+
|
|
1705
|
+
@CallsBeforeSetup.recorded_result
|
|
1706
|
+
def contains(self, obj: TModel) -> ContainsQuery:
|
|
1707
|
+
"""
|
|
1708
|
+
Whether the queryset holds the row of an instance.
|
|
1709
|
+
|
|
1710
|
+
Args:
|
|
1711
|
+
obj: The model instance to check for.
|
|
1712
|
+
|
|
1713
|
+
Returns:
|
|
1714
|
+
True if the QuerySet contains the instance, False otherwise.
|
|
1715
|
+
"""
|
|
1716
|
+
QuerySetCombination.raise_if_combined(self, "contains")
|
|
1717
|
+
ValuesArguments.raise_if_values_selected(self, "contains")
|
|
1718
|
+
if not isinstance(obj, self.model):
|
|
1719
|
+
raise QueryError("The given object is not an instance of the queryset's model.")
|
|
1720
|
+
|
|
1721
|
+
if obj._pk_is_unset():
|
|
1722
|
+
raise QueryError("The given object does not have a primary key.")
|
|
1723
|
+
|
|
1724
|
+
if self._limit is not None or self._offset:
|
|
1725
|
+
# Membership in a slice needs the object's position among the ordered rows, which a plain
|
|
1726
|
+
# `WHERE pk = ...` doesn't express.
|
|
1727
|
+
raise QueryError("contains() can't be used on a sliced queryset (after .limit()/.offset()).")
|
|
1728
|
+
|
|
1729
|
+
return ContainsQuery(self, obj)
|
|
1730
|
+
|
|
1731
|
+
async def in_bulk(self, id_list: Iterable[Any] | None = None, *, field_name: str = "pk") -> dict[Any, TModel]:
|
|
1732
|
+
"""The objects of the queryset by their value of a unique field.
|
|
1733
|
+
|
|
1734
|
+
Args:
|
|
1735
|
+
id_list: The values looked for - None for every object.
|
|
1736
|
+
field_name: The field - ``"pk"``, a unique field, or the one field of ``distinct()``.
|
|
1737
|
+
|
|
1738
|
+
Returns:
|
|
1739
|
+
The objects by value - a tuple of a composite primary key's values.
|
|
1740
|
+
|
|
1741
|
+
Raises:
|
|
1742
|
+
QueryError: The queryset selects values, combines querysets or is sliced, or the field isn't
|
|
1743
|
+
unique.
|
|
1744
|
+
FieldError: The model has no such field.
|
|
1745
|
+
"""
|
|
1746
|
+
return await ObjectsByKey.get(self, id_list, field_name)
|
|
1747
|
+
|
|
1748
|
+
@CallsBeforeSetup.recorded
|
|
1749
|
+
def all(self) -> Self:
|
|
1750
|
+
"""
|
|
1751
|
+
A copy of the queryset - from ``Model.objects``, every row of the model.
|
|
1752
|
+
"""
|
|
1753
|
+
return self._continue_call_signature(self._clone(), None)
|
|
1754
|
+
|
|
1755
|
+
@CallsBeforeSetup.recorded
|
|
1756
|
+
def none(self) -> Self:
|
|
1757
|
+
"""Returns an empty queryset: awaiting it, or anything chained onto it, gives an empty result
|
|
1758
|
+
without a query. Only ``.aggregate()`` still runs, with an always-false condition, so each
|
|
1759
|
+
expression gets its value for an empty set.
|
|
1760
|
+
"""
|
|
1761
|
+
queryset = self._clone()
|
|
1762
|
+
queryset._is_none = True
|
|
1763
|
+
return queryset
|
|
1764
|
+
|
|
1765
|
+
def raw(self, sql: str, parameters: Sequence[Any] = ()) -> RawSQLQuery[TModel]:
|
|
1766
|
+
"""
|
|
1767
|
+
The model's rows a SQL text of yours selects. Any value that varies per call belongs in
|
|
1768
|
+
``parameters`` (bound at each ``%s`` placeholder of ``sql``), never written into ``sql``.
|
|
1769
|
+
"""
|
|
1770
|
+
# The SQL is the caller's own - no default scope is worked out for it.
|
|
1771
|
+
connection = self._connection if self._connection is not None else self.get_connection()
|
|
1772
|
+
return RawSQLQuery(model=self.model, connection=connection, sql=sql, parameters=parameters)
|
|
1773
|
+
|
|
1774
|
+
@CallsBeforeSetup.recorded_result
|
|
1775
|
+
def first(self) -> QuerySetSingle[TRow | None]:
|
|
1776
|
+
"""Limits the queryset to its first object and returns it instead of a list. Without an
|
|
1777
|
+
ordering the rows are ordered by the primary key; a ``.group_by()``/``.distinct(<fields>)``
|
|
1778
|
+
queryset is left unordered.
|
|
1779
|
+
"""
|
|
1780
|
+
rows_source = StatementSelection.get_rows_source(self)
|
|
1781
|
+
first_queryset = rows_source._get_first(reverse=False)
|
|
1782
|
+
if rows_source is self:
|
|
1783
|
+
self._continue_call_signature(first_queryset, ("first",)) # type: ignore[type-var]
|
|
1784
|
+
return first_queryset # type: ignore[return-value]
|
|
1785
|
+
|
|
1786
|
+
@CallsBeforeSetup.recorded_result
|
|
1787
|
+
def last(self) -> QuerySetSingle[TRow | None]:
|
|
1788
|
+
"""Limits the queryset to its last object and returns it instead of a list. The ordering is
|
|
1789
|
+
reversed exactly, NULL placement included. The rows of an unordered slice are taken by the
|
|
1790
|
+
primary key.
|
|
1791
|
+
|
|
1792
|
+
Raises:
|
|
1793
|
+
QueryError: The queryset selects values and is sliced over rows that aren't one per
|
|
1794
|
+
model row.
|
|
1795
|
+
"""
|
|
1796
|
+
rows_source = StatementSelection.get_rows_source(self)
|
|
1797
|
+
last_queryset = rows_source._get_first(reverse=True)
|
|
1798
|
+
if rows_source is self:
|
|
1799
|
+
self._continue_call_signature(cast("Self", last_queryset), ("last",))
|
|
1800
|
+
return cast("QuerySetSingle[TRow | None]", last_queryset)
|
|
1801
|
+
|
|
1802
|
+
@overload
|
|
1803
|
+
def get(
|
|
1804
|
+
self,
|
|
1805
|
+
*args: Q,
|
|
1806
|
+
does_not_exist_exception: None,
|
|
1807
|
+
multiple_objects_returned_exception: GetExceptionArgument = GetException.STANDARD,
|
|
1808
|
+
**kwargs: Any,
|
|
1809
|
+
) -> QuerySetSingle[TRow | None]: ...
|
|
1810
|
+
|
|
1811
|
+
@overload
|
|
1812
|
+
def get(
|
|
1813
|
+
self,
|
|
1814
|
+
*args: Q,
|
|
1815
|
+
does_not_exist_exception: type[BaseException] | BaseException | GetException = GetException.STANDARD,
|
|
1816
|
+
multiple_objects_returned_exception: GetExceptionArgument = GetException.STANDARD,
|
|
1817
|
+
**kwargs: Any,
|
|
1818
|
+
) -> QuerySetSingle[TRow]: ...
|
|
1819
|
+
|
|
1820
|
+
@CallsBeforeSetup.recorded_result
|
|
1821
|
+
def get(
|
|
1822
|
+
self,
|
|
1823
|
+
*args: Q,
|
|
1824
|
+
does_not_exist_exception: GetExceptionArgument = GetException.STANDARD,
|
|
1825
|
+
multiple_objects_returned_exception: GetExceptionArgument = GetException.STANDARD,
|
|
1826
|
+
**kwargs: Any,
|
|
1827
|
+
) -> QuerySetSingle[TRow] | QuerySetSingle[TRow | None]:
|
|
1828
|
+
"""
|
|
1829
|
+
Fetches the one object matching the conditions.
|
|
1830
|
+
|
|
1831
|
+
Args:
|
|
1832
|
+
args: ``Q`` conditions, as ``filter()`` takes them.
|
|
1833
|
+
does_not_exist_exception: What happens when no object matches: ``DoesNotExist`` is
|
|
1834
|
+
raised by default; an exception class (instantiated with no arguments) or instance
|
|
1835
|
+
is raised instead; None gives None.
|
|
1836
|
+
multiple_objects_returned_exception: What happens when more than one object matches:
|
|
1837
|
+
``MultipleObjectsReturned`` is raised by default; an exception class or instance is
|
|
1838
|
+
raised instead; None reads one of them - which one is not defined - without
|
|
1839
|
+
counting the rest (``first()`` takes a defined one).
|
|
1840
|
+
kwargs: Field conditions, as ``filter()`` takes them.
|
|
1841
|
+
|
|
1842
|
+
Raises:
|
|
1843
|
+
QueryError: Conditions are given for a sliced queryset.
|
|
1844
|
+
"""
|
|
1845
|
+
if self._combination is not None:
|
|
1846
|
+
return cast(
|
|
1847
|
+
"QuerySetSingle[TRow]",
|
|
1848
|
+
QuerySetCombination.get_combined_query(self)._get_single_queryset(
|
|
1849
|
+
args,
|
|
1850
|
+
kwargs,
|
|
1851
|
+
does_not_exist_exception=does_not_exist_exception,
|
|
1852
|
+
multiple_objects_returned_exception=multiple_objects_returned_exception,
|
|
1853
|
+
),
|
|
1854
|
+
)
|
|
1855
|
+
if self._selection is not None:
|
|
1856
|
+
SingleRow.raise_if_sliced_values_rows_differ(self, "get")
|
|
1857
|
+
# The single-row queryset - typed without cast()'s call on the path of every get().
|
|
1858
|
+
return self._get_single_queryset( # type: ignore[return-value]
|
|
1859
|
+
args,
|
|
1860
|
+
kwargs,
|
|
1861
|
+
does_not_exist_exception=does_not_exist_exception,
|
|
1862
|
+
multiple_objects_returned_exception=multiple_objects_returned_exception,
|
|
1863
|
+
)
|
|
1864
|
+
|
|
1865
|
+
def insert_from(self, queryset: QuerySet[Any, Any], *, fields: Sequence[str]) -> InsertFromQuery:
|
|
1866
|
+
"""Writes the rows ``queryset`` selects into the model's table in one ``INSERT ... SELECT`` -
|
|
1867
|
+
never read into Python; awaits to the number of rows written. The fields not named get their
|
|
1868
|
+
database default; an ``auto_now``/``auto_now_add`` field the moment of the insert,
|
|
1869
|
+
``Meta.tenant_field`` the active tenant.
|
|
1870
|
+
|
|
1871
|
+
Example:
|
|
1872
|
+
::
|
|
1873
|
+
|
|
1874
|
+
await Archive.objects.insert_from(
|
|
1875
|
+
Event.objects.filter(finished=True).values("name", "tournament_id"),
|
|
1876
|
+
fields=["title", "tournament"],
|
|
1877
|
+
)
|
|
1878
|
+
|
|
1879
|
+
Args:
|
|
1880
|
+
queryset: A ``values()``/``values_list()`` queryset selecting one column per field, in
|
|
1881
|
+
order, or a queryset of models selecting its own fields of these names.
|
|
1882
|
+
fields: The written fields - concrete fields or forward relations to a single-column key.
|
|
1883
|
+
|
|
1884
|
+
Returns:
|
|
1885
|
+
The insert.
|
|
1886
|
+
|
|
1887
|
+
Raises:
|
|
1888
|
+
QueryError: See ``InsertFromQuery``; the queryset is combined.
|
|
1889
|
+
FieldError: See ``InsertFromQuery``.
|
|
1890
|
+
"""
|
|
1891
|
+
WrittenTargetChecks.raise_if_refused(self, "insert_from")
|
|
1892
|
+
return InsertFromQuery(self, queryset, fields)
|
|
1893
|
+
|
|
1894
|
+
async def refresh_materialized_view(self, name: str, *, concurrently: bool = False) -> None:
|
|
1895
|
+
"""Fills a materialized view of ``Meta.materialized_views`` with the rows of its query again,
|
|
1896
|
+
on the connection the model writes to.
|
|
1897
|
+
|
|
1898
|
+
Example:
|
|
1899
|
+
::
|
|
1900
|
+
|
|
1901
|
+
await Order.objects.refresh_materialized_view("order_totals", concurrently=True)
|
|
1902
|
+
|
|
1903
|
+
Args:
|
|
1904
|
+
name: The view's name.
|
|
1905
|
+
concurrently: Keep the view readable while it refreshes - needs its ``unique_columns``.
|
|
1906
|
+
|
|
1907
|
+
Raises:
|
|
1908
|
+
QueryError: The model declares no such view.
|
|
1909
|
+
UnSupportedError: The database has no materialized views.
|
|
1910
|
+
ConfigurationError: ``concurrently`` for a view without ``unique_columns``.
|
|
1911
|
+
"""
|
|
1912
|
+
view = SchemaObjectCalls.get_declared_schema_object(
|
|
1913
|
+
self, self.model._meta.materialized_views, name, "materialized view"
|
|
1914
|
+
)
|
|
1915
|
+
editor = SchemaObjectCalls.get_schema_editor(self)
|
|
1916
|
+
editor.raise_if_unsupported("supports_materialized_views", "materialized views")
|
|
1917
|
+
await editor.materialized_views.refresh_materialized_view(self.model, view, concurrently)
|
|
1918
|
+
|
|
1919
|
+
async def reload_dictionary(self, name: str) -> None:
|
|
1920
|
+
"""Loads a dictionary of ``Meta.dictionaries`` from its source again, on the connection the
|
|
1921
|
+
model writes to - the rows written since its last load are read through it from then on.
|
|
1922
|
+
|
|
1923
|
+
Example:
|
|
1924
|
+
::
|
|
1925
|
+
|
|
1926
|
+
await Country.objects.reload_dictionary("country_names")
|
|
1927
|
+
|
|
1928
|
+
Args:
|
|
1929
|
+
name: The dictionary's name.
|
|
1930
|
+
|
|
1931
|
+
Raises:
|
|
1932
|
+
QueryError: The model declares no such dictionary.
|
|
1933
|
+
UnSupportedError: The database has no dictionaries.
|
|
1934
|
+
"""
|
|
1935
|
+
dictionary = SchemaObjectCalls.get_declared_schema_object(
|
|
1936
|
+
self, self.model._meta.dictionaries, name, "dictionary"
|
|
1937
|
+
)
|
|
1938
|
+
editor = SchemaObjectCalls.get_schema_editor(self)
|
|
1939
|
+
editor.raise_if_unsupported("supports_dictionaries", "dictionaries")
|
|
1940
|
+
await editor.dictionaries.reload_dictionary(self.model, dictionary)
|
|
1941
|
+
|
|
1942
|
+
async def get_next_sequence_value(self, name: str) -> int:
|
|
1943
|
+
"""Takes the next number of a sequence of ``Meta.sequences``, on the connection the model
|
|
1944
|
+
writes to - a number taken is never handed out again, even when the transaction rolls back.
|
|
1945
|
+
|
|
1946
|
+
Example:
|
|
1947
|
+
::
|
|
1948
|
+
|
|
1949
|
+
number = await Invoice.objects.get_next_sequence_value("invoice_number")
|
|
1950
|
+
|
|
1951
|
+
Args:
|
|
1952
|
+
name: The sequence's name.
|
|
1953
|
+
|
|
1954
|
+
Returns:
|
|
1955
|
+
The number.
|
|
1956
|
+
|
|
1957
|
+
Raises:
|
|
1958
|
+
QueryError: The model declares no such sequence.
|
|
1959
|
+
UnSupportedError: The database has no sequences.
|
|
1960
|
+
"""
|
|
1961
|
+
sequence = SchemaObjectCalls.get_declared_schema_object(self, self.model._meta.sequences, name, "sequence")
|
|
1962
|
+
editor = SchemaObjectCalls.get_schema_editor(self)
|
|
1963
|
+
editor.raise_if_unsupported("supports_sequences", "sequences")
|
|
1964
|
+
return await editor.sequences.get_next_sequence_value(self.model, sequence)
|
|
1965
|
+
|
|
1966
|
+
def merge(self, source: Any, *, on: str | Sequence[str] | Mapping[str, str]) -> MergeQuery:
|
|
1967
|
+
"""One ``MERGE`` statement matching ``source``'s rows to the model's rows (of this queryset) on
|
|
1968
|
+
``on`` and, branch by branch, updating, deleting or inserting them - the branches are added
|
|
1969
|
+
with ``when_matched()``, ``when_not_matched()`` and ``when_not_matched_by_source()``.
|
|
1970
|
+
|
|
1971
|
+
Example:
|
|
1972
|
+
::
|
|
1973
|
+
|
|
1974
|
+
await (
|
|
1975
|
+
Stock.objects.merge(deliveries.values("sku", "delivered"), on="sku")
|
|
1976
|
+
.when_matched(update={"count": F("count") + F("merge_source__delivered")})
|
|
1977
|
+
.when_not_matched(insert={"sku": F("merge_source__sku"), "count": F("merge_source__delivered")})
|
|
1978
|
+
)
|
|
1979
|
+
|
|
1980
|
+
Args:
|
|
1981
|
+
source: A ``values()`` queryset, a queryset of models, a union of ``values()`` querysets,
|
|
1982
|
+
or a list of dicts keyed by field names of the model.
|
|
1983
|
+
on: The matched fields - names the source has columns of too, or a dict of the model's
|
|
1984
|
+
field to the source column.
|
|
1985
|
+
|
|
1986
|
+
Returns:
|
|
1987
|
+
The merge.
|
|
1988
|
+
|
|
1989
|
+
Raises:
|
|
1990
|
+
QueryError: See ``MergeQuery``; the queryset is combined.
|
|
1991
|
+
FieldError: See ``MergeQuery``.
|
|
1992
|
+
"""
|
|
1993
|
+
WrittenTargetChecks.raise_if_refused(self, "merge")
|
|
1994
|
+
return MergeQuery(self, source, on)
|
|
1995
|
+
|
|
1996
|
+
def bulk_create(
|
|
1997
|
+
self,
|
|
1998
|
+
objects: Iterable[TModel],
|
|
1999
|
+
batch_size: int | None = None,
|
|
2000
|
+
*,
|
|
2001
|
+
ignore_conflicts: bool = False,
|
|
2002
|
+
update_fields: Iterable[str] | None = None,
|
|
2003
|
+
on_conflict: Iterable[str] | None = None,
|
|
2004
|
+
on_conflict_constraint: str | None = None,
|
|
2005
|
+
conflict_where: Q | RawSQLTerm | None = None,
|
|
2006
|
+
returning: bool | None = None,
|
|
2007
|
+
use_copy: bool = False,
|
|
2008
|
+
) -> BulkCreateQuery[TModel]:
|
|
2009
|
+
"""Inserts the objects efficiently - generally one query. A ``db_default`` field must be set on
|
|
2010
|
+
all objects or on none.
|
|
2011
|
+
|
|
2012
|
+
Args:
|
|
2013
|
+
objects: The objects to create.
|
|
2014
|
+
batch_size: How many objects one query creates.
|
|
2015
|
+
ignore_conflicts: Skip the rows conflicting with an existing one.
|
|
2016
|
+
update_fields: The fields a conflicting row takes from the object (upsert) - a relation
|
|
2017
|
+
name means its key column(s). For a tenant-scoped model only a conflicting row of
|
|
2018
|
+
the active tenant is updated. A conflicting row also gets its ``auto_now`` fields
|
|
2019
|
+
and ``Meta.optimistic_lock_field`` bumped.
|
|
2020
|
+
on_conflict: The conflict target's field names.
|
|
2021
|
+
on_conflict_constraint: The conflict target as a named constraint - instead of
|
|
2022
|
+
``on_conflict``. Needs ``Features.supports_conflict_constraint_names``.
|
|
2023
|
+
conflict_where: The ``WHERE`` of the partial unique index the target matches - a ``Q``
|
|
2024
|
+
over the model's fields or ``RawSQLTerm`` of raw SQL. Needs ``on_conflict`` and
|
|
2025
|
+
``Features.supports_conflict_where``.
|
|
2026
|
+
returning: Read the database-generated primary key, generated columns and omitted
|
|
2027
|
+
``db_default`` columns back onto each object. Needs ``Features.supports_returning``;
|
|
2028
|
+
without ``Features.guarantees_returning_order`` every object needs its pk set. With
|
|
2029
|
+
``ignore_conflicts`` it needs ``on_conflict=[...]`` to match the rows. None takes
|
|
2030
|
+
``Meta.returning``. Not with ``use_copy``.
|
|
2031
|
+
use_copy: Load the rows through the database's bulk load of rows
|
|
2032
|
+
(``Features.supports_copy``) - faster for large batches, with no ``RETURNING`` and
|
|
2033
|
+
no conflict handling. A database whose usual way to write many rows it is
|
|
2034
|
+
(``Features.copies_bulk_inserts``) takes it with or without this.
|
|
2035
|
+
|
|
2036
|
+
Returns:
|
|
2037
|
+
The insert - awaited, it gives the objects as given.
|
|
2038
|
+
|
|
2039
|
+
Raises:
|
|
2040
|
+
UnSupportedError: The dialect has no such option, or ``use_copy`` is combined with
|
|
2041
|
+
``returning`` or conflict handling.
|
|
2042
|
+
QueryError: The parameters contradict each other; a tenant-scoped model has no active
|
|
2043
|
+
tenant or an object of another one;
|
|
2044
|
+
``returning=True`` with skipped rows has no ``on_conflict``; ``update_fields`` names
|
|
2045
|
+
a generated, tenant, lock or soft-delete field; ``batch_size`` isn't positive; an
|
|
2046
|
+
object isn't of this model; a ``db_default`` field is set on some objects only.
|
|
2047
|
+
IncompleteInstanceError: A ``.only()``/``.defer()`` object lacks a written field.
|
|
2048
|
+
FieldError: ``update_fields``/``on_conflict`` names something that isn't a column field
|
|
2049
|
+
of the model.
|
|
2050
|
+
"""
|
|
2051
|
+
return self._share_ambient_scope(
|
|
2052
|
+
BulkCreateQuery(
|
|
2053
|
+
connection=self._connection,
|
|
2054
|
+
model=self.model,
|
|
2055
|
+
objects=objects,
|
|
2056
|
+
batch_size=batch_size,
|
|
2057
|
+
ignore_conflicts=ignore_conflicts,
|
|
2058
|
+
update_fields=update_fields,
|
|
2059
|
+
on_conflict=on_conflict,
|
|
2060
|
+
on_conflict_constraint=on_conflict_constraint,
|
|
2061
|
+
conflict_where=conflict_where,
|
|
2062
|
+
returning=returning,
|
|
2063
|
+
use_copy=use_copy,
|
|
2064
|
+
all_tenants=self._visibility.all_tenants,
|
|
2065
|
+
)
|
|
2066
|
+
)
|
|
2067
|
+
|
|
2068
|
+
def bulk_update(
|
|
2069
|
+
self,
|
|
2070
|
+
objects: Iterable[TModel],
|
|
2071
|
+
fields: Iterable[str],
|
|
2072
|
+
batch_size: int | None = None,
|
|
2073
|
+
*,
|
|
2074
|
+
returning: bool | None = None,
|
|
2075
|
+
) -> BulkUpdateQuery[TModel]:
|
|
2076
|
+
"""
|
|
2077
|
+
Writes the given fields of each object to its row.
|
|
2078
|
+
|
|
2079
|
+
Args:
|
|
2080
|
+
objects: List of objects to bulk update
|
|
2081
|
+
fields: The fields to update - a list of field names; a repeated name is written once
|
|
2082
|
+
batch_size: How many objects are updated in a single query. Without it, the objects are
|
|
2083
|
+
split only to stay under the bind-parameter ceiling, and those statements run in
|
|
2084
|
+
one transaction - an error in any leaves no row updated (a stale version doesn't
|
|
2085
|
+
roll back the others). With it, every batch is an independent statement.
|
|
2086
|
+
returning: Whether to read back, by ``RETURNING``, the value the database computes for
|
|
2087
|
+
every ``GeneratedField`` column of the rows written - a column depending on an updated
|
|
2088
|
+
field may have changed - onto each object, matched by its primary key. Nothing is read
|
|
2089
|
+
for a model without a ``GeneratedField``. None takes ``Meta.returning`` (``False`` by
|
|
2090
|
+
default).
|
|
2091
|
+
|
|
2092
|
+
Raises:
|
|
2093
|
+
QueryError: An object has no primary key; ``fields`` is a string, empty or names the
|
|
2094
|
+
primary key; an object isn't an instance of this queryset's model.
|
|
2095
|
+
FieldError: If ``fields`` names something that isn't a field of the model.
|
|
2096
|
+
IncompleteInstanceError: If a ``.only()``/``.defer()`` object lacks its pk or an
|
|
2097
|
+
updated field.
|
|
2098
|
+
QueryError: If ``Meta.soft_delete_field`` is among ``fields`` - use
|
|
2099
|
+
``.delete()`` (which applies cascade logic a direct field update would bypass) or
|
|
2100
|
+
``.restore()`` (``cascade=True`` brings back what the delete cascaded) instead; if
|
|
2101
|
+
``Meta.optimistic_lock_field`` is among
|
|
2102
|
+
``fields`` - it's bumped automatically, not set directly; if a ``GeneratedField``
|
|
2103
|
+
is among ``fields`` - it's computed by the database, not written to; if
|
|
2104
|
+
``Meta.tenant_field`` is set, this queryset wasn't built via ``.all_tenants()``,
|
|
2105
|
+
and either no tenant is active, one
|
|
2106
|
+
of ``objects`` belongs to a tenant other than the active one, or one of
|
|
2107
|
+
``objects`` still has an unresolved async ``default=`` value pending for
|
|
2108
|
+
``tenant_field`` (save or refresh it first); if two or more objects in
|
|
2109
|
+
``objects`` share the same primary key; or if a field being updated holds an
|
|
2110
|
+
``F()``/expression value (use ``QuerySet.update()`` or ``save()`` for those).
|
|
2111
|
+
"""
|
|
2112
|
+
return BulkUpdateQuery(self, objects, fields, batch_size=batch_size, returning=returning)
|
|
2113
|
+
|
|
2114
|
+
async def create(self, **kwargs: Any) -> TModel:
|
|
2115
|
+
"""
|
|
2116
|
+
Creates a row and returns its object - ``Model(**kwargs)`` saved on the queryset's
|
|
2117
|
+
connection. The queryset's filters don't take part.
|
|
2118
|
+
|
|
2119
|
+
Args:
|
|
2120
|
+
kwargs: The field values.
|
|
2121
|
+
|
|
2122
|
+
Raises:
|
|
2123
|
+
QueryError: A value is an ``F()``/``Expression`` - there is no row yet to read a
|
|
2124
|
+
current value from; or the model has ``Meta.tenant_field`` and the tenant given
|
|
2125
|
+
differs from the active one, or none is given and none is active.
|
|
2126
|
+
"""
|
|
2127
|
+
ValuesArguments.raise_if_values_selected(self, "create")
|
|
2128
|
+
QuerySetCombination.raise_if_combined(self, "create")
|
|
2129
|
+
model = self.model
|
|
2130
|
+
for field_name, value in kwargs.items():
|
|
2131
|
+
if isinstance(value, Expression):
|
|
2132
|
+
raise QueryError(
|
|
2133
|
+
f"create() on {model.__name__} received {field_name}={value!r} - F()/Expression "
|
|
2134
|
+
"values aren't supported when creating a new row, since there's no existing "
|
|
2135
|
+
"row to read a current value from. Pass a plain value instead."
|
|
2136
|
+
)
|
|
2137
|
+
if given_blind_indexes := set(model._meta.blind_index_fields.values()).intersection(kwargs):
|
|
2138
|
+
# Refused as by every write given values - the index is computed from its field's plaintext.
|
|
2139
|
+
RowWriteRules.get(model, WriteType.INSERT, sorted(given_blind_indexes), "create")
|
|
2140
|
+
if model._meta.tenant_field:
|
|
2141
|
+
TenantWriteRules.fill_new_values(model, kwargs, "create")
|
|
2142
|
+
# Model.__init__ leaves the instance unsaved.
|
|
2143
|
+
instance = model(**kwargs)
|
|
2144
|
+
await instance.save(using=self.get_connection(for_write=True), force_create=True)
|
|
2145
|
+
return instance
|
|
2146
|
+
|
|
2147
|
+
async def get_or_create(self, defaults: dict[str, Any] | None = None, **kwargs: Any) -> tuple[TModel, bool]:
|
|
2148
|
+
"""
|
|
2149
|
+
Fetches the object matching ``kwargs`` among the queryset's rows, or creates it.
|
|
2150
|
+
|
|
2151
|
+
Args:
|
|
2152
|
+
defaults: Values of a created object on top of ``kwargs`` (its lookups left out).
|
|
2153
|
+
kwargs: The conditions, as ``get()`` takes them.
|
|
2154
|
+
|
|
2155
|
+
Returns:
|
|
2156
|
+
The object and whether it was created.
|
|
2157
|
+
|
|
2158
|
+
Raises:
|
|
2159
|
+
QueryError: ``defaults`` conflicts with ``kwargs``, or per ``create()``.
|
|
2160
|
+
IntegrityError: The create failed for a reason other than the row already existing.
|
|
2161
|
+
"""
|
|
2162
|
+
ValuesArguments.raise_if_values_selected(self, "get_or_create")
|
|
2163
|
+
QuerySetCombination.raise_if_combined(self, "get_or_create")
|
|
2164
|
+
# The existence check reads on the connection the row would be created on: a replica may not
|
|
2165
|
+
# have the row yet.
|
|
2166
|
+
queryset = CreateOrUpdate.pinned_for_write(self)
|
|
2167
|
+
try:
|
|
2168
|
+
return await CreateOrUpdate.get_matching(queryset, kwargs), False
|
|
2169
|
+
except DoesNotExist:
|
|
2170
|
+
return await CreateOrUpdate.create_or_get(queryset, defaults or {}, kwargs)
|
|
2171
|
+
|
|
2172
|
+
async def update_or_create(
|
|
2173
|
+
self,
|
|
2174
|
+
defaults: dict[str, Any] | None = None,
|
|
2175
|
+
create_defaults: dict[str, Any] | None = None,
|
|
2176
|
+
**kwargs: Any,
|
|
2177
|
+
) -> tuple[TModel, bool]:
|
|
2178
|
+
"""
|
|
2179
|
+
Updates the object matching ``kwargs`` among the queryset's rows with ``defaults``, or
|
|
2180
|
+
creates it.
|
|
2181
|
+
|
|
2182
|
+
Args:
|
|
2183
|
+
defaults: The values to update the object with - and to create it with, when
|
|
2184
|
+
``create_defaults`` isn't given.
|
|
2185
|
+
create_defaults: Values of a created object instead of ``defaults``.
|
|
2186
|
+
kwargs: The conditions, as ``get()`` takes them.
|
|
2187
|
+
|
|
2188
|
+
Returns:
|
|
2189
|
+
The object and whether it was created.
|
|
2190
|
+
|
|
2191
|
+
Raises:
|
|
2192
|
+
QueryError: ``defaults`` sets ``Meta.optimistic_lock_field``, or per ``create()`` for
|
|
2193
|
+
a created object.
|
|
2194
|
+
FieldError: ``defaults`` names a field the model doesn't have.
|
|
2195
|
+
"""
|
|
2196
|
+
ValuesArguments.raise_if_values_selected(self, "update_or_create")
|
|
2197
|
+
QuerySetCombination.raise_if_combined(self, "update_or_create")
|
|
2198
|
+
defaults = defaults or {}
|
|
2199
|
+
# Pinned to the write connection: the SELECT FOR UPDATE and the UPDATE after it must
|
|
2200
|
+
# land on one connection for the lock to mean anything.
|
|
2201
|
+
queryset = CreateOrUpdate.pinned_for_write(self)
|
|
2202
|
+
async with queryset._connection._in_transaction() as connection:
|
|
2203
|
+
matching = TableOptions.get_key_read_queryset(queryset.using(connection).filter(**kwargs))
|
|
2204
|
+
if connection.features.supports_select_for_update:
|
|
2205
|
+
matching = matching.select_for_update()
|
|
2206
|
+
instance = cast("TModel | None", await matching.get(does_not_exist_exception=None))
|
|
2207
|
+
if instance is not None:
|
|
2208
|
+
# The lock field is refused only here, for an existing row - a created row may
|
|
2209
|
+
# set its initial version.
|
|
2210
|
+
await CreateOrUpdate.update_with_defaults(queryset, instance, defaults, connection)
|
|
2211
|
+
return instance, False
|
|
2212
|
+
instance, created = await CreateOrUpdate.create_or_get(
|
|
2213
|
+
queryset, defaults if create_defaults is None else create_defaults, kwargs
|
|
2214
|
+
)
|
|
2215
|
+
if not created and defaults:
|
|
2216
|
+
# A concurrent writer created the row first - this call's values still apply to it.
|
|
2217
|
+
await CreateOrUpdate.update_with_defaults(queryset, instance, defaults, queryset._connection)
|
|
2218
|
+
return instance, created
|
|
2219
|
+
|
|
2220
|
+
@CallsBeforeSetup.recorded
|
|
2221
|
+
def only(self, *fields_for_select: str) -> Self:
|
|
2222
|
+
"""Fetches only the given fields, creating partial model instances. Reading a field left out -
|
|
2223
|
+
``pk`` too when the primary key is - raises ``NoValuesFetched``, an ``AttributeError``;
|
|
2224
|
+
``save()`` of a partial instance needs ``update_fields`` naming loaded fields and the primary
|
|
2225
|
+
key loaded, else it raises ``IncompleteInstanceError``.
|
|
2226
|
+
|
|
2227
|
+
Raises:
|
|
2228
|
+
QueryError: No field names are given, or ``.defer()`` was already used.
|
|
2229
|
+
"""
|
|
2230
|
+
QuerySetCombination.raise_if_combined(self, "only")
|
|
2231
|
+
ValuesArguments.raise_if_values_selected(self, "only")
|
|
2232
|
+
FilterArguments.check_selected_names(self, fields_for_select, "only")
|
|
2233
|
+
if not fields_for_select:
|
|
2234
|
+
raise QueryError(".only() requires at least one field")
|
|
2235
|
+
if self._deferred_fields:
|
|
2236
|
+
raise QueryError(".only() cannot be combined with .defer() on the same queryset")
|
|
2237
|
+
queryset = self._clone()
|
|
2238
|
+
# "pk" and a forward relation name load their own key field(s), like Django, a generic
|
|
2239
|
+
# foreign key the key fields of every branch - a to-many relation name is left as given.
|
|
2240
|
+
only_field_names: list[str] = []
|
|
2241
|
+
for field_name in fields_for_select:
|
|
2242
|
+
concrete_field_paths = self._get_generic_key_field_names(field_name) or ConcreteFieldPaths.get_paths(
|
|
2243
|
+
self.model, field_name
|
|
2244
|
+
)
|
|
2245
|
+
if any(path.startswith(f"{field_name}__") for path in concrete_field_paths):
|
|
2246
|
+
concrete_field_paths = (field_name,)
|
|
2247
|
+
only_field_names.extend(concrete_field_paths)
|
|
2248
|
+
queryset._fields_for_select = tuple(dict.fromkeys(only_field_names))
|
|
2249
|
+
return self._continue_call_signature(queryset, ("only", fields_for_select))
|
|
2250
|
+
|
|
2251
|
+
def _get_generic_key_field_names(self, name: str) -> tuple[str, ...]:
|
|
2252
|
+
"""The key fields of every branch of the generic foreign key ``name`` names.
|
|
2253
|
+
|
|
2254
|
+
Args:
|
|
2255
|
+
name: A name given to ``only()``/``defer()``.
|
|
2256
|
+
|
|
2257
|
+
Returns:
|
|
2258
|
+
The fields, empty when the name isn't a generic foreign key of the model.
|
|
2259
|
+
"""
|
|
2260
|
+
meta = self.model._meta
|
|
2261
|
+
generic_field = meta.generic_foreign_key_fields.get(name)
|
|
2262
|
+
if generic_field is None:
|
|
2263
|
+
return ()
|
|
2264
|
+
return tuple(
|
|
2265
|
+
source_field
|
|
2266
|
+
for branch_name in generic_field.branch_names
|
|
2267
|
+
for source_field in meta.fields_map[branch_name].source_fields # type: ignore[attr-defined]
|
|
2268
|
+
)
|
|
2269
|
+
|
|
2270
|
+
@CallsBeforeSetup.recorded
|
|
2271
|
+
def defer(self, *fields: str) -> Self:
|
|
2272
|
+
"""Fetches every direct field of the model except the given ones, creating partial model
|
|
2273
|
+
instances. Only direct fields can be deferred - a forward relation's name defers its key
|
|
2274
|
+
field(s), like Django; ``.select_related()`` relations are still loaded in full.
|
|
2275
|
+
|
|
2276
|
+
Raises:
|
|
2277
|
+
QueryError: No field names are given, or ``.only()`` was already used.
|
|
2278
|
+
FieldError: A name is not a direct field or a forward relation of the model.
|
|
2279
|
+
"""
|
|
2280
|
+
QuerySetCombination.raise_if_combined(self, "defer")
|
|
2281
|
+
ValuesArguments.raise_if_values_selected(self, "defer")
|
|
2282
|
+
if not fields:
|
|
2283
|
+
raise QueryError(".defer() requires at least one field")
|
|
2284
|
+
if self._fields_for_select:
|
|
2285
|
+
raise QueryError(".defer() cannot be combined with .only() on the same queryset")
|
|
2286
|
+
meta = self.model._meta
|
|
2287
|
+
direct_fields = meta.fields_map.keys() - meta.fetch_fields
|
|
2288
|
+
deferred_field_names: list[str] = []
|
|
2289
|
+
for field_name in fields:
|
|
2290
|
+
if generic_key_field_names := self._get_generic_key_field_names(field_name):
|
|
2291
|
+
deferred_field_names.extend(generic_key_field_names)
|
|
2292
|
+
continue
|
|
2293
|
+
concrete_field_paths = ConcreteFieldPaths.get_paths(self.model, field_name)
|
|
2294
|
+
if field_name in meta.fetch_fields and not any("__" in path for path in concrete_field_paths):
|
|
2295
|
+
# A forward relation's name defers its own key field(s), as only() loads them.
|
|
2296
|
+
deferred_field_names.extend(concrete_field_paths)
|
|
2297
|
+
else:
|
|
2298
|
+
deferred_field_names.append(field_name)
|
|
2299
|
+
unknown_fields = set(deferred_field_names) - direct_fields
|
|
2300
|
+
if unknown_fields:
|
|
2301
|
+
raise FieldError(f"Unknown direct field(s) for .defer(): {sorted(unknown_fields)}")
|
|
2302
|
+
queryset = self._clone()
|
|
2303
|
+
queryset._deferred_fields = tuple(dict.fromkeys((*self._deferred_fields, *deferred_field_names)))
|
|
2304
|
+
return queryset
|
|
2305
|
+
|
|
2306
|
+
@CallsBeforeSetup.recorded
|
|
2307
|
+
def using(self, using: str | DatabaseClient | None) -> Self:
|
|
2308
|
+
"""Runs the query on the given connection.
|
|
2309
|
+
|
|
2310
|
+
Args:
|
|
2311
|
+
using: A connection alias, or a connection's client - a transaction's included;
|
|
2312
|
+
None keeps the connection the query would choose itself.
|
|
2313
|
+
|
|
2314
|
+
Raises:
|
|
2315
|
+
ConfigurationError: ``using`` is no alias, client or None, or an alias that isn't
|
|
2316
|
+
configured.
|
|
2317
|
+
"""
|
|
2318
|
+
connection_alias = Connections.get_client(using)
|
|
2319
|
+
queryset = self._clone_keeping_calls()
|
|
2320
|
+
queryset._apply_connection(connection_alias or queryset._connection)
|
|
2321
|
+
if connection_alias:
|
|
2322
|
+
queryset._connection_explicitly_chosen = True
|
|
2323
|
+
# The connection is in the key of the plan a queryset's calls run on - it shapes no call.
|
|
2324
|
+
return self._continue_call_signature(queryset, None)
|
|
2325
|
+
|
|
2326
|
+
def _set_instance_connection(self, obj: Model) -> None:
|
|
2327
|
+
"""Makes this queryset fall back to the connection ``obj`` was loaded from or saved to
|
|
2328
|
+
when the router has no opinion. The queried model keeps its own choice when the obj
|
|
2329
|
+
never touched the database, when its default connection differs from the obj model's,
|
|
2330
|
+
or when the router routes the obj's model.
|
|
2331
|
+
|
|
2332
|
+
Args:
|
|
2333
|
+
obj: The model obj the relation is read from.
|
|
2334
|
+
"""
|
|
2335
|
+
if (
|
|
2336
|
+
obj._connection_alias is not None
|
|
2337
|
+
and self.model._meta.default_connection == type(obj)._meta.default_connection
|
|
2338
|
+
and not InstanceConnections.is_routed(type(obj))
|
|
2339
|
+
):
|
|
2340
|
+
self._instance_connection_alias = obj._connection_alias
|
|
2341
|
+
|
|
2342
|
+
def _share_ambient_scope(self, query: TDerivedQuery) -> TDerivedQuery:
|
|
2343
|
+
"""Hands this queryset's default scope (``.all_tenants()``/``.include_deleted()`` state
|
|
2344
|
+
included) to a derived (count/update/delete/...) query, together with the connection of
|
|
2345
|
+
the model instance a related manager built it from.
|
|
2346
|
+
|
|
2347
|
+
Args:
|
|
2348
|
+
query: The query just built from this queryset.
|
|
2349
|
+
|
|
2350
|
+
Returns:
|
|
2351
|
+
``query`` itself, with the ambient scope set.
|
|
2352
|
+
"""
|
|
2353
|
+
query._instance_connection_alias = self._instance_connection_alias
|
|
2354
|
+
return self._share_default_scope(query)
|
|
2355
|
+
|
|
2356
|
+
def __await__(self) -> Generator[Any, None, list[TRow]]:
|
|
2357
|
+
connection: DatabaseClient | None = self._connection
|
|
2358
|
+
# A joined relation's rows are read by the query's own layout.
|
|
2359
|
+
if self._call_signature is not None and not self._select_related:
|
|
2360
|
+
# The connection is chosen once - the query run as usual takes it.
|
|
2361
|
+
connection = connection or self.get_connection()
|
|
2362
|
+
if self._selection is not None:
|
|
2363
|
+
awaitable = CallSignatureRuns.await_call_signature_values(self, connection)
|
|
2364
|
+
else:
|
|
2365
|
+
# Annotations are read by the query's own layout.
|
|
2366
|
+
awaitable = (
|
|
2367
|
+
None if self._annotations else CallSignatureRuns.await_call_signature_rows(self, connection)
|
|
2368
|
+
)
|
|
2369
|
+
if awaitable is not None:
|
|
2370
|
+
return awaitable
|
|
2371
|
+
query = StatementSelection.get_select_query(self)
|
|
2372
|
+
if connection is not None and cast("DatabaseClient | None", query._connection) is None:
|
|
2373
|
+
query._apply_connection(connection)
|
|
2374
|
+
if self._combination is None:
|
|
2375
|
+
self._hand_call_signature(query)
|
|
2376
|
+
# Made for this run alone - built and run as it is, not copied first.
|
|
2377
|
+
query._is_execution_query = True
|
|
2378
|
+
return query.__await__()
|
|
2379
|
+
|
|
2380
|
+
async def __aiter__(self) -> AsyncIterator[TRow]:
|
|
2381
|
+
for row in await self:
|
|
2382
|
+
yield row
|
|
2383
|
+
|
|
2384
|
+
#: A queryset is iterated with ``async for`` - without this, ``for``, ``list()`` and ``in`` would
|
|
2385
|
+
#: read ``queryset[0]``, ``queryset[1]``, ... through ``__getitem__`` without end.
|
|
2386
|
+
__iter__ = None
|
|
2387
|
+
|
|
2388
|
+
def iterator(self, chunk_size: int = 1000) -> AsyncIterator[TRow]:
|
|
2389
|
+
"""Pages through the result ``chunk_size`` rows at a time - one page in memory at a time, with
|
|
2390
|
+
no server-side cursor.
|
|
2391
|
+
|
|
2392
|
+
Without an ``order_by()``, pages follow ``Meta.ordering``, else the primary key. An ordering
|
|
2393
|
+
that can tie gets the primary key appended as a tie-breaker. The queryset's own slice and
|
|
2394
|
+
``.after_cursor()`` bound the whole iteration.
|
|
2395
|
+
|
|
2396
|
+
When every ordering field is a column of this model, pages are fetched by keyset - a row
|
|
2397
|
+
deleted from a page already yielded never makes a later page skip a row. An ordering across
|
|
2398
|
+
a relation or by an annotation, a primary key that can repeat, or a window function falls
|
|
2399
|
+
back to ``OFFSET`` paging, which is not safe under concurrent deletes.
|
|
2400
|
+
|
|
2401
|
+
Args:
|
|
2402
|
+
chunk_size: The page size.
|
|
2403
|
+
|
|
2404
|
+
Returns:
|
|
2405
|
+
The rows, as an async iterator. Iterating raises QueryError: ``chunk_size`` isn't an int
|
|
2406
|
+
from 1 to ``2**63 - 2``, or a ``before_cursor()`` query.
|
|
2407
|
+
"""
|
|
2408
|
+
return RowsQuery.iterate_query(partial(StatementSelection.get_select_query, self), chunk_size)
|
|
2409
|
+
|
|
2410
|
+
def stream(self, chunk_size: int = 1000) -> AsyncIterator[TRow]:
|
|
2411
|
+
"""Streams the rows off one server-side cursor - a single consistent snapshot for
|
|
2412
|
+
the whole scan, unlike ``iterator()``, which runs a SELECT per page. Requires an open
|
|
2413
|
+
``Transactions.atomic()`` block. Iterating raises:
|
|
2414
|
+
|
|
2415
|
+
- QueryError: ``chunk_size`` isn't an int from 1 to ``2**31 - 1``, the call is outside a
|
|
2416
|
+
transaction, a ``before_cursor()`` query, or model instances with ``prefetch_related()``.
|
|
2417
|
+
- UnSupportedError: The database has no streaming (``features.supports_streaming``).
|
|
2418
|
+
|
|
2419
|
+
Args:
|
|
2420
|
+
chunk_size: How many rows to fetch per round trip.
|
|
2421
|
+
|
|
2422
|
+
Returns:
|
|
2423
|
+
The rows, as an async iterator.
|
|
2424
|
+
"""
|
|
2425
|
+
return RowsQuery.stream_query(partial(StatementSelection.get_select_query, self), chunk_size)
|
|
2426
|
+
|
|
2427
|
+
@CallsBeforeSetup.recorded
|
|
2428
|
+
def select_related(self, *args: str | Select) -> Self:
|
|
2429
|
+
"""Returns a queryset that also selects the given forward relations with a JOIN. Pass
|
|
2430
|
+
``Select(relation, extra_condition=Q(...))`` instead of a name to condition that relation's
|
|
2431
|
+
JOIN itself.
|
|
2432
|
+
"""
|
|
2433
|
+
QuerySetCombination.raise_if_combined(self, "select_related")
|
|
2434
|
+
ValuesArguments.raise_if_values_selected(self, "select_related")
|
|
2435
|
+
args = GenericForeignKeyPaths.expand_relation_paths(self.model, args, "select_related")
|
|
2436
|
+
|
|
2437
|
+
queryset = self._clone()
|
|
2438
|
+
for arg in args:
|
|
2439
|
+
self._check_select_related_path(arg.relation if isinstance(arg, Select) else arg)
|
|
2440
|
+
if isinstance(arg, Select):
|
|
2441
|
+
queryset._select_related.add(arg.relation)
|
|
2442
|
+
queryset._explicitly_select_related = queryset._explicitly_select_related | {arg.relation}
|
|
2443
|
+
if arg.extra_condition is not None:
|
|
2444
|
+
queryset._select_related_extra_conditions = {
|
|
2445
|
+
**queryset._select_related_extra_conditions,
|
|
2446
|
+
arg.relation: arg.extra_condition,
|
|
2447
|
+
}
|
|
2448
|
+
else:
|
|
2449
|
+
queryset._select_related.add(arg)
|
|
2450
|
+
queryset._explicitly_select_related = queryset._explicitly_select_related | {arg}
|
|
2451
|
+
if all(type(arg) is str for arg in args):
|
|
2452
|
+
return self._continue_call_signature(queryset, ("select_related", args))
|
|
2453
|
+
return queryset
|
|
2454
|
+
|
|
2455
|
+
def _check_select_related_path(self, relation_path: str) -> None:
|
|
2456
|
+
"""Checks every hop of a ``select_related()`` path is a single-valued relation.
|
|
2457
|
+
|
|
2458
|
+
Raises:
|
|
2459
|
+
FieldError: A hop is not found, is not a relation, or is a reverse ForeignKey /
|
|
2460
|
+
ManyToManyField (joining one would repeat the row once per related row).
|
|
2461
|
+
"""
|
|
2462
|
+
lookup_path = LookupPath.parse(self.model, relation_path, crosses_last=True)
|
|
2463
|
+
model: type[Model] = self.model
|
|
2464
|
+
for part, related_field in zip(lookup_path.relation_names, lookup_path.relations, strict=True):
|
|
2465
|
+
if related_field.is_multi_valued:
|
|
2466
|
+
raise FieldError(
|
|
2467
|
+
f"select_related() can't follow {part!r} on {model._meta.full_name} - it can hold many "
|
|
2468
|
+
"related rows (a reverse ForeignKey or a ManyToManyField); use prefetch_related() instead"
|
|
2469
|
+
)
|
|
2470
|
+
model = related_field.related_model
|
|
2471
|
+
if lookup_path.rest:
|
|
2472
|
+
part = lookup_path.rest[0]
|
|
2473
|
+
if part in model._meta.fields_map:
|
|
2474
|
+
raise FieldError(f"select_related() field {part!r} on {model._meta.full_name} is not a relation")
|
|
2475
|
+
raise FieldError(f"select_related() relation {part!r} for {model._meta.full_name} not found")
|
|
2476
|
+
|
|
2477
|
+
@CallsBeforeSetup.recorded
|
|
2478
|
+
def prefetch_related(self, *args: str | Prefetch) -> Self:
|
|
2479
|
+
"""
|
|
2480
|
+
Loads the given relations of every row with one query per relation - the rows of
|
|
2481
|
+
the queryset and, through ``prefetch_related_objects()``, instances already in hand.
|
|
2482
|
+
|
|
2483
|
+
Raises:
|
|
2484
|
+
FieldError: If the field to prefetch on is not a relation, or not found.
|
|
2485
|
+
"""
|
|
2486
|
+
args = GenericForeignKeyPaths.expand_relation_paths(self.model, args, "prefetch_related")
|
|
2487
|
+
if self._combination is not None:
|
|
2488
|
+
return cast(
|
|
2489
|
+
"Self",
|
|
2490
|
+
CombinedDerivedQueries.get_prefetching_queryset(QuerySetCombination.get_combined_query(self), args),
|
|
2491
|
+
)
|
|
2492
|
+
ValuesArguments.raise_if_values_selected(self, "prefetch_related")
|
|
2493
|
+
queryset = self._clone_keeping_calls()
|
|
2494
|
+
Prefetch.add_lookups(self.model, queryset._prefetch_map, queryset._prefetch_queries, args)
|
|
2495
|
+
# The prefetched relations - a forward relation's key column is selected for its prefetch
|
|
2496
|
+
# even past only().
|
|
2497
|
+
return self._continue_call_signature(
|
|
2498
|
+
queryset,
|
|
2499
|
+
("prefetch_related", tuple(sorted({*queryset._prefetch_map, *queryset._prefetch_queries}))),
|
|
2500
|
+
)
|
|
2501
|
+
|
|
2502
|
+
@CallsBeforeSetup.recorded
|
|
2503
|
+
def defer_related(self, *fields: str) -> Self:
|
|
2504
|
+
"""Opts the given relations out of their field-level ``lazy="joined"``/``"select"`` default for
|
|
2505
|
+
this query.
|
|
2506
|
+
"""
|
|
2507
|
+
QuerySetCombination.raise_if_combined(self, "defer_related")
|
|
2508
|
+
ValuesArguments.raise_if_values_selected(self, "defer_related")
|
|
2509
|
+
queryset = self._clone()
|
|
2510
|
+
queryset._deferred_related_fields = queryset._deferred_related_fields | set(fields)
|
|
2511
|
+
return queryset
|
|
2512
|
+
|
|
2513
|
+
|
|
2514
|
+
# Imported last: the statement modules import this one.
|
|
2515
|
+
from hare.query.statements.select.raw_sql_query import RawSQLQuery # noqa: E402
|
|
2516
|
+
from hare.query.statements.summary.aggregate_query import AggregateQuery # noqa: E402
|
|
2517
|
+
from hare.query.statements.summary.contains_query import ContainsQuery # noqa: E402
|
|
2518
|
+
from hare.query.statements.summary.count_query import CountQuery # noqa: E402
|
|
2519
|
+
from hare.query.statements.summary.exists_query import ExistsQuery # noqa: E402
|
|
2520
|
+
from hare.query.statements.write.bulk.bulk_update_query import BulkUpdateQuery # noqa: E402
|
|
2521
|
+
from hare.query.statements.write.bulk.create.bulk_create_query import BulkCreateQuery # noqa: E402
|
|
2522
|
+
from hare.query.statements.write.declarations import HardDeleteQuery # noqa: E402
|
|
2523
|
+
from hare.query.statements.write.delete_query import DeleteQuery # noqa: E402
|
|
2524
|
+
from hare.query.statements.write.insert_from_query import InsertFromQuery # noqa: E402
|
|
2525
|
+
from hare.query.statements.write.merge.merge_query import MergeQuery # noqa: E402
|
|
2526
|
+
from hare.query.statements.write.restore_query import RestoreQuery # noqa: E402
|
|
2527
|
+
from hare.query.statements.write.update_query import UpdateQuery # noqa: E402
|