couchbase 3.8.1 → 3.9.0
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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/CMakeLists.txt +16 -1
- data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
- data/ext/cache/extconf_include.rb +6 -6
- data/ext/cache/mozilla-ca-bundle.crt +214 -155
- data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
- data/ext/couchbase/CMakeLists.txt +130 -21
- data/ext/couchbase/cmake/APKBUILD.in +25 -4
- data/ext/couchbase/cmake/Bundler.cmake +143 -34
- data/ext/couchbase/cmake/CPM.cmake +126 -12
- data/ext/couchbase/cmake/Cache.cmake +7 -1
- data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
- data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
- data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
- data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
- data/ext/couchbase/cmake/Packaging.cmake +519 -65
- data/ext/couchbase/cmake/Protostellar.cmake +250 -0
- data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
- data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
- data/ext/couchbase/cmake/TestFramework.cmake +283 -0
- data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
- data/ext/couchbase/cmake/Testing.cmake +27 -9
- data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
- data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
- data/ext/couchbase/cmake/build_config.hxx.in +2 -1
- data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
- data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
- data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
- data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
- data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
- data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
- data/ext/couchbase/cmake/tarball_glob.txt +49 -0
- data/ext/couchbase/core/agent_group.cxx +0 -8
- data/ext/couchbase/core/agent_group.hxx +0 -4
- data/ext/couchbase/core/analytics_stream.cxx +314 -0
- data/ext/couchbase/core/analytics_stream.hxx +129 -0
- data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
- data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
- data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
- data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
- data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
- data/ext/couchbase/core/bucket.cxx +381 -87
- data/ext/couchbase/core/bucket.hxx +105 -25
- data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
- data/ext/couchbase/core/capella.hxx +91 -0
- data/ext/couchbase/core/cluster.cxx +1554 -398
- data/ext/couchbase/core/cluster.hxx +39 -8
- data/ext/couchbase/core/cluster_agent.cxx +0 -8
- data/ext/couchbase/core/cluster_agent.hxx +0 -4
- data/ext/couchbase/core/cluster_options.hxx +26 -3
- data/ext/couchbase/core/collections_component.cxx +39 -15
- data/ext/couchbase/core/config_profiles.cxx +1 -1
- data/ext/couchbase/core/crud_component.cxx +2 -2
- data/ext/couchbase/core/crud_options.hxx +34 -0
- data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
- data/ext/couchbase/core/document_id_redaction.hxx +81 -0
- data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
- data/ext/couchbase/core/error_context/key_value.cxx +25 -2
- data/ext/couchbase/core/error_context/key_value.hxx +60 -33
- data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
- data/ext/couchbase/core/error_context/search.hxx +5 -0
- data/ext/couchbase/core/error_context/search_json.hxx +3 -0
- data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
- data/ext/couchbase/core/error_context/view.hxx +5 -0
- data/ext/couchbase/core/free_form_http_request.cxx +237 -4
- data/ext/couchbase/core/free_form_http_request.hxx +41 -8
- data/ext/couchbase/core/http_component.cxx +300 -284
- data/ext/couchbase/core/http_component.hxx +0 -4
- data/ext/couchbase/core/impl/analytics.cxx +38 -5
- data/ext/couchbase/core/impl/analytics.hxx +34 -0
- data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
- data/ext/couchbase/core/impl/collection.cxx +215 -202
- data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
- data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
- data/ext/couchbase/core/impl/error.cxx +22 -2
- data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
- data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
- data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
- data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
- data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
- data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
- data/ext/couchbase/core/impl/node_id.cxx +49 -13
- data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
- data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
- data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
- data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
- data/ext/couchbase/core/impl/public_cluster.cxx +325 -25
- data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
- data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
- data/ext/couchbase/core/impl/query.cxx +76 -7
- data/ext/couchbase/core/impl/query.hxx +36 -0
- data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
- data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
- data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
- data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
- data/ext/couchbase/core/impl/scope.cxx +70 -0
- data/ext/couchbase/core/impl/search.cxx +31 -1
- data/ext/couchbase/core/impl/transactions.cxx +130 -0
- data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
- data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
- data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
- data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
- data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +66 -0
- data/ext/couchbase/core/io/dns_client.cxx +122 -45
- data/ext/couchbase/core/io/dns_codec.hxx +21 -21
- data/ext/couchbase/core/io/dns_config.cxx +21 -6
- data/ext/couchbase/core/io/http_command.hxx +149 -121
- data/ext/couchbase/core/io/http_error.hxx +107 -0
- data/ext/couchbase/core/io/http_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_session.cxx +606 -154
- data/ext/couchbase/core/io/http_session.hxx +147 -30
- data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
- data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
- data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
- data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
- data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
- data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
- data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
- data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
- data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
- data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
- data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
- data/ext/couchbase/core/io/mcbp_session.cxx +316 -317
- data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
- data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
- data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
- data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
- data/ext/couchbase/core/io/streams.cxx +275 -14
- data/ext/couchbase/core/io/streams.hxx +53 -0
- data/ext/couchbase/core/logger/logger.cxx +36 -0
- data/ext/couchbase/core/logger/logger.hxx +46 -6
- data/ext/couchbase/core/logger/redaction.hxx +503 -0
- data/ext/couchbase/core/management/eventing_status.hxx +10 -0
- data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
- data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
- data/ext/couchbase/core/mcbp/codec.cxx +27 -18
- data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
- data/ext/couchbase/core/mcbp/packet.hxx +2 -2
- data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
- data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
- data/ext/couchbase/core/meta/features.hxx +13 -0
- data/ext/couchbase/core/meta/version.cxx +6 -3
- data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
- data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
- data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
- data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
- data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
- data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
- data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
- data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
- data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
- data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
- data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
- data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
- data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
- data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
- data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
- data/ext/couchbase/core/operations/document_query.cxx +108 -221
- data/ext/couchbase/core/operations/document_query.hxx +18 -4
- data/ext/couchbase/core/operations/document_search.cxx +52 -8
- data/ext/couchbase/core/operations/document_search.hxx +3 -0
- data/ext/couchbase/core/operations/document_view.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
- data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
- data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
- data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
- data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
- data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
- data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
- data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
- data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
- data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
- data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
- data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
- data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
- data/ext/couchbase/core/operations/management/bucket_create.cxx +37 -38
- data/ext/couchbase/core/operations/management/bucket_update.cxx +26 -28
- data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
- data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
- data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
- data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
- data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
- data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
- data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
- data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
- data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
- data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
- data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
- data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
- data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
- data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
- data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
- data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
- data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
- data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
- data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
- data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
- data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
- data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
- data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
- data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
- data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
- data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
- data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
- data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
- data/ext/couchbase/core/operations_fwd.hxx +3 -3
- data/ext/couchbase/core/origin.cxx +54 -26
- data/ext/couchbase/core/origin.hxx +12 -0
- data/ext/couchbase/core/orphan_reporter.cxx +2 -1
- data/ext/couchbase/core/platform/random.cc +7 -7
- data/ext/couchbase/core/protocol/client_request.cxx +2 -2
- data/ext/couchbase/core/protocol/client_request.hxx +38 -21
- data/ext/couchbase/core/protocol/client_response.cxx +11 -3
- data/ext/couchbase/core/protocol/client_response.hxx +27 -6
- data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
- data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
- data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
- data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
- data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
- data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
- data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
- data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
- data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
- data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
- data/ext/couchbase/core/protocol/datatype.hxx +118 -1
- data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
- data/ext/couchbase/core/protocol/magic.hxx +4 -0
- data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
- data/ext/couchbase/core/protocol/server_request.hxx +3 -1
- data/ext/couchbase/core/protocol/status.cxx +1 -1
- data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
- data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
- data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
- data/ext/couchbase/core/protostellar/component.cxx +2445 -0
- data/ext/couchbase/core/protostellar/component.hxx +391 -0
- data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
- data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
- data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
- data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
- data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
- data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
- data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
- data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
- data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
- data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
- data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
- data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
- data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
- data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
- data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
- data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
- data/ext/couchbase/core/query_stream.cxx +447 -0
- data/ext/couchbase/core/query_stream.hxx +141 -0
- data/ext/couchbase/core/query_stream_component.cxx +243 -0
- data/ext/couchbase/core/query_stream_component.hxx +68 -0
- data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
- data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
- data/ext/couchbase/core/response_handler.hxx +41 -4
- data/ext/couchbase/core/row_streamer.cxx +332 -46
- data/ext/couchbase/core/row_streamer.hxx +31 -1
- data/ext/couchbase/core/row_streamer_options.hxx +55 -0
- data/ext/couchbase/core/sasl/client.h +3 -0
- data/ext/couchbase/core/search_scoring.hxx +66 -0
- data/ext/couchbase/core/stream_error_details.hxx +69 -0
- data/ext/couchbase/core/timeout_defaults.hxx +0 -1
- data/ext/couchbase/core/topology/capabilities.hxx +6 -0
- data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
- data/ext/couchbase/core/topology/configuration.cxx +21 -6
- data/ext/couchbase/core/topology/configuration.hxx +29 -8
- data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
- data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
- data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
- data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
- data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
- data/ext/couchbase/core/transactions/attempt_context_impl.cxx +362 -241
- data/ext/couchbase/core/transactions/attempt_context_impl.hxx +24 -3
- data/ext/couchbase/core/transactions/error_list.hxx +2 -2
- data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
- data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
- data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
- data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
- data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
- data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
- data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
- data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
- data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
- data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
- data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
- data/ext/couchbase/core/transactions/transactions.cxx +3 -55
- data/ext/couchbase/core/transactions/transactions_cleanup.cxx +194 -66
- data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
- data/ext/couchbase/core/transactions/utils.cxx +10 -0
- data/ext/couchbase/core/transactions/waitable_op_list.hxx +15 -4
- data/ext/couchbase/core/transactions.hxx +9 -9
- data/ext/couchbase/core/utils/byteswap.hxx +166 -9
- data/ext/couchbase/core/utils/connection_string.cxx +50 -85
- data/ext/couchbase/core/utils/connection_string.hxx +15 -0
- data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
- data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
- data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
- data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
- data/ext/couchbase/core/utils/movable_function.hxx +301 -52
- data/ext/couchbase/core/utils/name_codec.hxx +154 -11
- data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
- data/ext/couchbase/core/utils/url_codec.cxx +12 -51
- data/ext/couchbase/core/websocket_codec.cxx +3 -29
- data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
- data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
- data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
- data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
- data/ext/couchbase/couchbase/bucket.hxx +57 -0
- data/ext/couchbase/couchbase/cluster.hxx +216 -5
- data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
- data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
- data/ext/couchbase/couchbase/collection.hxx +234 -14
- data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
- data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
- data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
- data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
- data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
- data/ext/couchbase/couchbase/error.hxx +32 -0
- data/ext/couchbase/couchbase/error_codes.hxx +32 -0
- data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
- data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
- data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
- data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
- data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
- data/ext/couchbase/couchbase/get_result.hxx +1 -0
- data/ext/couchbase/couchbase/increment_options.hxx +1 -1
- data/ext/couchbase/couchbase/insert_options.hxx +1 -1
- data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/match_query.hxx +1 -1
- data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
- data/ext/couchbase/couchbase/network_options.hxx +1 -1
- data/ext/couchbase/couchbase/node_id.hxx +42 -14
- data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
- data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
- data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
- data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
- data/ext/couchbase/couchbase/query_options.hxx +23 -12
- data/ext/couchbase/couchbase/query_row.hxx +111 -0
- data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
- data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
- data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
- data/ext/couchbase/couchbase/replace_options.hxx +3 -3
- data/ext/couchbase/couchbase/result.hxx +14 -3
- data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
- data/ext/couchbase/couchbase/scope.hxx +85 -2
- data/ext/couchbase/couchbase/search_options.hxx +58 -8
- data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
- data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
- data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
- data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
- data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
- data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
- data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
- data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
- data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
- data/ext/couchbase/couchbase/transactions.hxx +27 -18
- data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
- data/ext/couchbase/couchbase/vector_query.hxx +1 -1
- data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
- data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
- data/ext/extconf.rb +15 -10
- data/ext/rcb_analytics.cxx +82 -102
- data/ext/rcb_backend.cxx +42 -36
- data/ext/rcb_backend.hxx +2 -0
- data/ext/rcb_buckets.cxx +47 -59
- data/ext/rcb_collections.cxx +42 -52
- data/ext/rcb_crud.cxx +345 -224
- data/ext/rcb_diagnostics.cxx +117 -27
- data/ext/rcb_exceptions.cxx +152 -99
- data/ext/rcb_exceptions.hxx +25 -0
- data/ext/rcb_extras.cxx +18 -19
- data/ext/rcb_hdr_histogram.cxx +19 -4
- data/ext/rcb_logger.cxx +202 -27
- data/ext/rcb_logger.hxx +12 -0
- data/ext/rcb_multi.cxx +40 -40
- data/ext/rcb_observability.cxx +7 -5
- data/ext/rcb_query.cxx +99 -142
- data/ext/rcb_range_scan.cxx +41 -35
- data/ext/rcb_search.cxx +98 -99
- data/ext/rcb_users.cxx +36 -56
- data/ext/rcb_utils.cxx +100 -37
- data/ext/rcb_utils.hxx +287 -33
- data/ext/rcb_version.cxx +1 -1
- data/ext/rcb_views.cxx +55 -51
- data/lib/active_support/cache/couchbase_store.rb +77 -12
- data/lib/couchbase/bucket.rb +20 -0
- data/lib/couchbase/cluster.rb +33 -14
- data/lib/couchbase/collection.rb +36 -1
- data/lib/couchbase/errors.rb +18 -0
- data/lib/couchbase/fork_hooks.rb +16 -7
- data/lib/couchbase/get_replica_strategy.rb +89 -0
- data/lib/couchbase/logger.rb +1 -1
- data/lib/couchbase/management/analytics_index_manager.rb +15 -15
- data/lib/couchbase/management/bucket_manager.rb +6 -6
- data/lib/couchbase/management/collection_manager.rb +6 -6
- data/lib/couchbase/management/query_index_manager.rb +7 -7
- data/lib/couchbase/management/search_index_manager.rb +13 -13
- data/lib/couchbase/management/user_manager.rb +10 -10
- data/lib/couchbase/management/view_index_manager.rb +5 -5
- data/lib/couchbase/options.rb +181 -44
- data/lib/couchbase/protostellar/bucket.rb +4 -0
- data/lib/couchbase/protostellar/cluster.rb +4 -0
- data/lib/couchbase/protostellar/collection.rb +4 -0
- data/lib/couchbase/protostellar/error_handling.rb +2 -1
- data/lib/couchbase/protostellar/request.rb +1 -0
- data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
- data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
- data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
- data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
- data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
- data/lib/couchbase/search_options.rb +95 -6
- data/lib/couchbase/version.rb +1 -1
- metadata +92 -33
- data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
- data/ext/couchbase/core/columnar/agent.hxx +0 -71
- data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
- data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
- data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
- data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
- data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
- data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
- data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
- data/ext/couchbase/core/columnar/error.hxx +0 -51
- data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
- data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
- data/ext/couchbase/core/columnar/management_component.cxx +0 -300
- data/ext/couchbase/core/columnar/management_component.hxx +0 -56
- data/ext/couchbase/core/columnar/query_component.cxx +0 -523
- data/ext/couchbase/core/columnar/query_component.hxx +0 -57
- data/ext/couchbase/core/columnar/query_options.hxx +0 -59
- data/ext/couchbase/core/columnar/query_result.cxx +0 -130
- data/ext/couchbase/core/columnar/query_result.hxx +0 -78
- data/ext/couchbase/core/io/config_tracker.cxx +0 -687
- data/ext/couchbase/core/io/config_tracker.hxx +0 -123
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
// Translates the core FTS search request/response to and from couchbase.search.v1. Hits arrive
|
|
21
|
+
// across streamed SearchQueryResponse messages and are buffered into search_response::rows; the
|
|
22
|
+
// terminal message carries the metadata.
|
|
23
|
+
//
|
|
24
|
+
// The couchbase2 SearchQueryRequest models the FTS query as a structured `Query` oneof of 21 types,
|
|
25
|
+
// whereas the core request carries an opaque pre-serialized JSON `query`. This converter translates
|
|
26
|
+
// the trivial forms -- query_string (optionally boosted), match_all and match_none -- and reports
|
|
27
|
+
// every other shape as unmappable so the component surfaces feature_not_available. Structured
|
|
28
|
+
// facets, structured sort specs, vector search, mutation-token consistency, the `raw`
|
|
29
|
+
// passthrough, and score fusion (rrf/rsf) have no couchbase2 home and are likewise gated;
|
|
30
|
+
// `scoring(none())` predates fusion and maps onto the protocol's existing disable_scoring field, so
|
|
31
|
+
// it is not gated. Translating the remaining eighteen query arms is a follow-up; the gate is what
|
|
32
|
+
// keeps an untranslated one from being dropped in silence in the meantime.
|
|
33
|
+
|
|
34
|
+
#include "core/operations/document_search.hxx"
|
|
35
|
+
#include "core/utils/json.hxx"
|
|
36
|
+
|
|
37
|
+
#include <couchbase/search/v1/search.pb.h>
|
|
38
|
+
|
|
39
|
+
// core/utils/json.hxx only forward-declares tao::json::value; this header instantiates one and
|
|
40
|
+
// calls its members, so it needs the full definition.
|
|
41
|
+
#include <tao/json/value.hpp>
|
|
42
|
+
|
|
43
|
+
#include <chrono>
|
|
44
|
+
#include <cstdint>
|
|
45
|
+
#include <optional>
|
|
46
|
+
#include <string>
|
|
47
|
+
#include <vector>
|
|
48
|
+
|
|
49
|
+
namespace couchbase::core::protostellar::search
|
|
50
|
+
{
|
|
51
|
+
namespace v1 = ::couchbase::search::v1;
|
|
52
|
+
|
|
53
|
+
// Coarse, cheap gate for request features with no couchbase2 mapping. Query-shape support is
|
|
54
|
+
// decided in encode() (which must parse the query JSON).
|
|
55
|
+
[[nodiscard]] inline auto
|
|
56
|
+
can_encode(const operations::search_request& request) -> bool
|
|
57
|
+
{
|
|
58
|
+
return request.raw.empty() && request.facets.empty() && request.sort_specs.empty() &&
|
|
59
|
+
request.mutation_state.empty() && !request.vector_search.has_value() &&
|
|
60
|
+
!request.vector_query_combination.has_value() && !request.row_callback.has_value() &&
|
|
61
|
+
!couchbase::core::is_score_fusion(request.scoring);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// True when request.query does not parse as JSON at all, as opposed to parsing into a shape this
|
|
65
|
+
// converter does not translate. The component maps the two to different errors: a query the caller
|
|
66
|
+
// failed to serialize is their own invalid_argument, not a gap in couchbase2 support.
|
|
67
|
+
[[nodiscard]] inline auto
|
|
68
|
+
query_is_malformed(const operations::search_request& request) -> bool
|
|
69
|
+
{
|
|
70
|
+
try {
|
|
71
|
+
static_cast<void>(utils::json::parse(request.query));
|
|
72
|
+
} catch (...) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Translate the parsed core query JSON into the structured Query oneof, for the trivial forms only.
|
|
79
|
+
// Returns false, leaving proto.query unset, for every shape this converter does not translate.
|
|
80
|
+
[[nodiscard]] inline auto
|
|
81
|
+
apply_query(const tao::json::value& parsed, v1::SearchQueryRequest& proto) -> bool
|
|
82
|
+
{
|
|
83
|
+
if (!parsed.is_object()) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
// A boost is serialized beside the query key rather than inside it: query_string("foo").boost(2)
|
|
87
|
+
// encodes as {"query":"foo","boost":2}. Rejecting every two-key object would therefore make an
|
|
88
|
+
// ordinary boosted query unroutable, so a boost is read as a modifier of the recognized key.
|
|
89
|
+
// Whether it can actually be carried depends on the arm, and is decided below. Any other sibling
|
|
90
|
+
// (an analyzer, a field) would be lost in translation, so a wider object is reported as
|
|
91
|
+
// unmappable and the component surfaces feature_not_available.
|
|
92
|
+
const auto* boost = parsed.find("boost");
|
|
93
|
+
if (parsed.get_object().size() > (boost == nullptr ? 1U : 2U)) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const auto* match_all = parsed.find("match_all");
|
|
97
|
+
const auto* match_none = parsed.find("match_none");
|
|
98
|
+
if (match_all != nullptr || match_none != nullptr) {
|
|
99
|
+
// MatchAllQuery and MatchNoneQuery are empty messages, so a boost on either has nowhere to go.
|
|
100
|
+
// Refusing the request keeps it from being run at a weight the caller did not ask for.
|
|
101
|
+
if (boost != nullptr) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (match_all != nullptr) {
|
|
105
|
+
proto.mutable_query()->mutable_match_all_query();
|
|
106
|
+
} else {
|
|
107
|
+
proto.mutable_query()->mutable_match_none_query();
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (const auto* q = parsed.find("query"); q != nullptr && q->is_string()) {
|
|
112
|
+
auto* query_string = proto.mutable_query()->mutable_query_string_query();
|
|
113
|
+
query_string->set_query_string(q->get_string());
|
|
114
|
+
if (boost != nullptr) {
|
|
115
|
+
if (!boost->is_number()) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
query_string->set_boost(static_cast<float>(boost->as<double>()));
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Encode the request; returns nullopt for a gated feature, an untranslated query shape, or a query
|
|
126
|
+
// that is not JSON. The component separates the last case with query_is_malformed().
|
|
127
|
+
[[nodiscard]] inline auto
|
|
128
|
+
encode(const operations::search_request& request) -> std::optional<v1::SearchQueryRequest>
|
|
129
|
+
{
|
|
130
|
+
if (!can_encode(request)) {
|
|
131
|
+
return std::nullopt;
|
|
132
|
+
}
|
|
133
|
+
v1::SearchQueryRequest proto;
|
|
134
|
+
proto.set_index_name(request.index_name);
|
|
135
|
+
if (request.bucket_name.has_value()) {
|
|
136
|
+
proto.set_bucket_name(*request.bucket_name);
|
|
137
|
+
}
|
|
138
|
+
if (request.scope_name.has_value()) {
|
|
139
|
+
proto.set_scope_name(*request.scope_name);
|
|
140
|
+
}
|
|
141
|
+
tao::json::value parsed;
|
|
142
|
+
try {
|
|
143
|
+
parsed = utils::json::parse(request.query);
|
|
144
|
+
} catch (...) {
|
|
145
|
+
return std::nullopt;
|
|
146
|
+
}
|
|
147
|
+
if (!apply_query(parsed, proto)) {
|
|
148
|
+
return std::nullopt;
|
|
149
|
+
}
|
|
150
|
+
if (request.limit.has_value()) {
|
|
151
|
+
proto.set_limit(*request.limit);
|
|
152
|
+
}
|
|
153
|
+
if (request.skip.has_value()) {
|
|
154
|
+
proto.set_skip(*request.skip);
|
|
155
|
+
}
|
|
156
|
+
if (request.explain.value_or(false)) {
|
|
157
|
+
proto.set_include_explanation(true);
|
|
158
|
+
}
|
|
159
|
+
proto.set_disable_scoring(
|
|
160
|
+
request.disable_scoring ||
|
|
161
|
+
std::holds_alternative<couchbase::core::search_scoring_none>(request.scoring));
|
|
162
|
+
proto.set_include_locations(request.include_locations);
|
|
163
|
+
proto.set_scan_consistency(v1::SearchQueryRequest_ScanConsistency_SCAN_CONSISTENCY_NOT_BOUNDED);
|
|
164
|
+
if (request.highlight_style.has_value()) {
|
|
165
|
+
proto.set_highlight_style(*request.highlight_style == search_highlight_style::ansi
|
|
166
|
+
? v1::SearchQueryRequest_HighlightStyle_HIGHLIGHT_STYLE_ANSI
|
|
167
|
+
: v1::SearchQueryRequest_HighlightStyle_HIGHLIGHT_STYLE_HTML);
|
|
168
|
+
}
|
|
169
|
+
for (const auto& field : request.highlight_fields) {
|
|
170
|
+
proto.add_highlight_fields(field);
|
|
171
|
+
}
|
|
172
|
+
for (const auto& field : request.fields) {
|
|
173
|
+
proto.add_fields(field);
|
|
174
|
+
}
|
|
175
|
+
for (const auto& collection : request.collections) {
|
|
176
|
+
proto.add_collections(collection);
|
|
177
|
+
}
|
|
178
|
+
return proto;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Append the hits from one streamed message onto the buffered response and, if present, decode the
|
|
182
|
+
// terminal metadata. Structured facets are gated by can_encode(), so a response cannot carry any.
|
|
183
|
+
inline void
|
|
184
|
+
decode(const v1::SearchQueryResponse& message, operations::search_response& response)
|
|
185
|
+
{
|
|
186
|
+
for (const auto& hit : message.hits()) {
|
|
187
|
+
operations::search_response::search_row row;
|
|
188
|
+
row.index = hit.index();
|
|
189
|
+
row.id = hit.id();
|
|
190
|
+
row.score = hit.score();
|
|
191
|
+
row.explanation = hit.explanation();
|
|
192
|
+
for (const auto& [field, fragment] : hit.fragments()) {
|
|
193
|
+
row.fragments[field] =
|
|
194
|
+
std::vector<std::string>{ fragment.content().begin(), fragment.content().end() };
|
|
195
|
+
}
|
|
196
|
+
// The proto keys each requested field to its value as raw JSON, whereas the core row carries
|
|
197
|
+
// the whole set as one JSON object, so the object is reassembled here.
|
|
198
|
+
if (!hit.fields().empty()) {
|
|
199
|
+
tao::json::value fields = tao::json::empty_object;
|
|
200
|
+
for (const auto& [name, value] : hit.fields()) {
|
|
201
|
+
try {
|
|
202
|
+
fields[name] = utils::json::parse(value);
|
|
203
|
+
} catch (...) {
|
|
204
|
+
// decode() runs on the io_context out of a stream callback, where an escaping exception
|
|
205
|
+
// would take down the loop. A value that is not JSON is kept verbatim as a string so the
|
|
206
|
+
// field still reaches the caller.
|
|
207
|
+
fields[name] = value;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
row.fields = utils::json::generate(fields);
|
|
211
|
+
}
|
|
212
|
+
for (const auto& location : hit.locations()) {
|
|
213
|
+
operations::search_response::search_location out;
|
|
214
|
+
out.field = location.field();
|
|
215
|
+
out.term = location.term();
|
|
216
|
+
out.position = location.position();
|
|
217
|
+
out.start_offset = location.start();
|
|
218
|
+
out.end_offset = location.end();
|
|
219
|
+
if (location.array_positions_size() > 0) {
|
|
220
|
+
out.array_positions = std::vector<std::uint64_t>{ location.array_positions().begin(),
|
|
221
|
+
location.array_positions().end() };
|
|
222
|
+
}
|
|
223
|
+
row.locations.push_back(std::move(out));
|
|
224
|
+
}
|
|
225
|
+
response.rows.push_back(std::move(row));
|
|
226
|
+
}
|
|
227
|
+
if (message.has_meta_data()) {
|
|
228
|
+
const auto& meta = message.meta_data();
|
|
229
|
+
if (meta.has_metrics()) {
|
|
230
|
+
const auto& m = meta.metrics();
|
|
231
|
+
response.meta.metrics.took = std::chrono::seconds{ m.execution_time().seconds() } +
|
|
232
|
+
std::chrono::nanoseconds{ m.execution_time().nanos() };
|
|
233
|
+
response.meta.metrics.total_rows = m.total_rows();
|
|
234
|
+
response.meta.metrics.max_score = m.max_score();
|
|
235
|
+
response.meta.metrics.success_partition_count = m.success_partition_count();
|
|
236
|
+
response.meta.metrics.error_partition_count = m.error_partition_count();
|
|
237
|
+
}
|
|
238
|
+
for (const auto& [location, msg] : meta.errors()) {
|
|
239
|
+
response.meta.errors.try_emplace(location, msg);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
} // namespace couchbase::core::protostellar::search
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
// Translates core FTS index settings to and from couchbase.admin.search.v1. The one non-trivial
|
|
21
|
+
// bit: core stores params/plan_params/source_params as single JSON-object strings, while the proto
|
|
22
|
+
// Index uses map<string,bytes> keyed by the object's top-level members (each value a raw-JSON
|
|
23
|
+
// blob). fill_params/params_to_json round-trip between the two representations.
|
|
24
|
+
//
|
|
25
|
+
// Every conversion that can lose a member reports failure instead. A definition that cannot be
|
|
26
|
+
// represented must not be truncated in silence: the caller edits what get_index returned and
|
|
27
|
+
// upserts it back, so a dropped member deletes part of the index definition while the call reports
|
|
28
|
+
// success.
|
|
29
|
+
|
|
30
|
+
#include "core/management/search_index.hxx"
|
|
31
|
+
#include "core/utils/json.hxx"
|
|
32
|
+
|
|
33
|
+
#include <tao/json/value.hpp>
|
|
34
|
+
|
|
35
|
+
#include <couchbase/admin/search/v1/search.pb.h>
|
|
36
|
+
|
|
37
|
+
#include <google/protobuf/map.h>
|
|
38
|
+
|
|
39
|
+
#include <optional>
|
|
40
|
+
#include <string>
|
|
41
|
+
|
|
42
|
+
namespace couchbase::core::protostellar::search_index_admin
|
|
43
|
+
{
|
|
44
|
+
namespace v1 = ::couchbase::admin::search::v1;
|
|
45
|
+
|
|
46
|
+
// Explode a JSON-object string into the proto map: one entry per top-level member, value = the
|
|
47
|
+
// member's raw JSON. An empty input is the "unset" convention and contributes nothing. Anything
|
|
48
|
+
// that is not a JSON object has no representation in the map and is refused.
|
|
49
|
+
[[nodiscard]] inline auto
|
|
50
|
+
fill_params(const std::string& json, ::google::protobuf::Map<std::string, std::string>* target)
|
|
51
|
+
-> bool
|
|
52
|
+
{
|
|
53
|
+
if (json.empty()) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
tao::json::value parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = utils::json::parse(json);
|
|
59
|
+
} catch (...) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!parsed.is_object()) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
for (const auto& [key, value] : parsed.get_object()) {
|
|
66
|
+
(*target)[key] = utils::json::generate(value);
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Rebuild a JSON-object string from the proto map (inverse of fill_params). Empty map -> empty
|
|
72
|
+
// string so the core struct keeps its "unset" convention. A member whose bytes are not JSON cannot
|
|
73
|
+
// be placed in the object, and dropping it would hand back a definition short of what the server
|
|
74
|
+
// holds, so the whole conversion fails.
|
|
75
|
+
[[nodiscard]] inline auto
|
|
76
|
+
params_to_json(const ::google::protobuf::Map<std::string, std::string>& source)
|
|
77
|
+
-> std::optional<std::string>
|
|
78
|
+
{
|
|
79
|
+
if (source.empty()) {
|
|
80
|
+
return std::string{};
|
|
81
|
+
}
|
|
82
|
+
tao::json::value object = tao::json::empty_object;
|
|
83
|
+
for (const auto& [key, value] : source) {
|
|
84
|
+
try {
|
|
85
|
+
object[key] = utils::json::parse(value);
|
|
86
|
+
} catch (...) {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return utils::json::generate(object);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// The fields shared by CreateIndexRequest and Index. The two messages carry the same index
|
|
94
|
+
// definition under the same field names, but they are unrelated proto types and neither derives
|
|
95
|
+
// from the other, so the assignments are written once against whichever is passed.
|
|
96
|
+
template<typename Proto>
|
|
97
|
+
[[nodiscard]] auto
|
|
98
|
+
apply_index_fields(const management::search::index& index, Proto& proto) -> bool
|
|
99
|
+
{
|
|
100
|
+
proto.set_name(index.name);
|
|
101
|
+
proto.set_type(index.type);
|
|
102
|
+
if (!index.source_name.empty()) {
|
|
103
|
+
proto.set_source_name(index.source_name);
|
|
104
|
+
}
|
|
105
|
+
if (!index.source_type.empty()) {
|
|
106
|
+
proto.set_source_type(index.source_type);
|
|
107
|
+
}
|
|
108
|
+
if (!index.source_uuid.empty()) {
|
|
109
|
+
proto.set_source_uuid(index.source_uuid);
|
|
110
|
+
}
|
|
111
|
+
return fill_params(index.params_json, proto.mutable_params()) &&
|
|
112
|
+
fill_params(index.plan_params_json, proto.mutable_plan_params()) &&
|
|
113
|
+
fill_params(index.source_params_json, proto.mutable_source_params());
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Encode a core index into a CreateIndexRequest. A create carries no uuid: an upsert that supplies
|
|
117
|
+
// one is an update and goes to UpdateIndex instead.
|
|
118
|
+
[[nodiscard]] inline auto
|
|
119
|
+
apply_index(const management::search::index& index, v1::CreateIndexRequest& proto) -> bool
|
|
120
|
+
{
|
|
121
|
+
return apply_index_fields(index, proto);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Encode a core index into the Index of an UpdateIndexRequest. The uuid is what makes it an
|
|
125
|
+
// update: the gateway rejects the call without one, and the server matches it against the current
|
|
126
|
+
// definition so a concurrent update is not overwritten.
|
|
127
|
+
[[nodiscard]] inline auto
|
|
128
|
+
apply_index(const management::search::index& index, v1::Index& proto) -> bool
|
|
129
|
+
{
|
|
130
|
+
proto.set_uuid(index.uuid);
|
|
131
|
+
return apply_index_fields(index, proto);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
[[nodiscard]] inline auto
|
|
135
|
+
decode_index(const v1::Index& proto) -> std::optional<management::search::index>
|
|
136
|
+
{
|
|
137
|
+
auto params = params_to_json(proto.params());
|
|
138
|
+
auto plan_params = params_to_json(proto.plan_params());
|
|
139
|
+
auto source_params = params_to_json(proto.source_params());
|
|
140
|
+
if (!params.has_value() || !plan_params.has_value() || !source_params.has_value()) {
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
management::search::index index;
|
|
144
|
+
index.uuid = proto.uuid();
|
|
145
|
+
index.name = proto.name();
|
|
146
|
+
index.type = proto.type();
|
|
147
|
+
index.source_uuid = proto.source_uuid();
|
|
148
|
+
index.source_name = proto.source_name();
|
|
149
|
+
index.source_type = proto.source_type();
|
|
150
|
+
index.params_json = std::move(*params);
|
|
151
|
+
index.plan_params_json = std::move(*plan_params);
|
|
152
|
+
index.source_params_json = std::move(*source_params);
|
|
153
|
+
return index;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
} // namespace couchbase::core::protostellar::search_index_admin
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
// Views are deprecated in the core API but still routable over couchbase2; suppress the core
|
|
21
|
+
// deprecation attribute for this header. push/pop the macro so an including translation unit that
|
|
22
|
+
// already defined it keeps its state restored, rather than having it clobbered at the bottom.
|
|
23
|
+
#pragma push_macro("COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS")
|
|
24
|
+
#define COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS
|
|
25
|
+
|
|
26
|
+
// Translates the core map/reduce view request/response to and from couchbase.view.v1. Rows arrive
|
|
27
|
+
// across streamed ViewQueryResponse messages and are buffered into document_view_response::rows;
|
|
28
|
+
// the terminal message carries the metadata.
|
|
29
|
+
//
|
|
30
|
+
// The couchbase2 ViewQueryRequest has no home for the core request's `raw`, `query_string`,
|
|
31
|
+
// `full_set`, or streaming `row_callback` fields; can_encode() reports those so the component
|
|
32
|
+
// surfaces feature_not_available rather than silently dropping them. The proto `limit`/`skip` are
|
|
33
|
+
// uint32 while core carries uint64, so can_encode() also rejects values that would truncate.
|
|
34
|
+
// `client_context_id`/`timeout` likewise have no proto field but do not change results, so they are
|
|
35
|
+
// simply not sent.
|
|
36
|
+
|
|
37
|
+
#include "core/operations/document_view.hxx"
|
|
38
|
+
|
|
39
|
+
#include <couchbase/view/v1/view.pb.h>
|
|
40
|
+
|
|
41
|
+
#include <cstdint>
|
|
42
|
+
#include <limits>
|
|
43
|
+
#include <string>
|
|
44
|
+
|
|
45
|
+
namespace couchbase::core::protostellar::view
|
|
46
|
+
{
|
|
47
|
+
namespace v1 = ::couchbase::view::v1;
|
|
48
|
+
|
|
49
|
+
[[nodiscard]] inline auto
|
|
50
|
+
can_encode(const operations::document_view_request& request) -> bool
|
|
51
|
+
{
|
|
52
|
+
constexpr auto u32_max = (std::numeric_limits<std::uint32_t>::max)();
|
|
53
|
+
return request.raw.empty() && request.query_string.empty() && !request.full_set.value_or(false) &&
|
|
54
|
+
!request.row_callback.has_value() && request.limit.value_or(0) <= u32_max &&
|
|
55
|
+
request.skip.value_or(0) <= u32_max;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
inline auto
|
|
59
|
+
encode(const operations::document_view_request& request) -> v1::ViewQueryRequest
|
|
60
|
+
{
|
|
61
|
+
v1::ViewQueryRequest proto;
|
|
62
|
+
proto.set_bucket_name(request.bucket_name);
|
|
63
|
+
proto.set_design_document_name(request.document_name);
|
|
64
|
+
proto.set_view_name(request.view_name);
|
|
65
|
+
proto.set_namespace_(request.ns == design_document_namespace::development
|
|
66
|
+
? v1::ViewQueryRequest_Namespace_NAMESPACE_DEVELOPMENT
|
|
67
|
+
: v1::ViewQueryRequest_Namespace_NAMESPACE_PRODUCTION);
|
|
68
|
+
|
|
69
|
+
for (const auto& key : request.keys) {
|
|
70
|
+
proto.add_keys(key);
|
|
71
|
+
}
|
|
72
|
+
if (request.key.has_value()) {
|
|
73
|
+
proto.set_key(*request.key);
|
|
74
|
+
}
|
|
75
|
+
if (request.start_key.has_value()) {
|
|
76
|
+
proto.set_start_key(*request.start_key);
|
|
77
|
+
}
|
|
78
|
+
if (request.end_key.has_value()) {
|
|
79
|
+
proto.set_end_key(*request.end_key);
|
|
80
|
+
}
|
|
81
|
+
if (request.start_key_doc_id.has_value()) {
|
|
82
|
+
proto.set_start_key_doc_id(*request.start_key_doc_id);
|
|
83
|
+
}
|
|
84
|
+
if (request.end_key_doc_id.has_value()) {
|
|
85
|
+
proto.set_end_key_doc_id(*request.end_key_doc_id);
|
|
86
|
+
}
|
|
87
|
+
if (request.limit.has_value()) {
|
|
88
|
+
proto.set_limit(static_cast<std::uint32_t>(*request.limit));
|
|
89
|
+
}
|
|
90
|
+
if (request.skip.has_value()) {
|
|
91
|
+
proto.set_skip(static_cast<std::uint32_t>(*request.skip));
|
|
92
|
+
}
|
|
93
|
+
if (request.reduce.has_value()) {
|
|
94
|
+
proto.set_reduce(*request.reduce);
|
|
95
|
+
}
|
|
96
|
+
if (request.group.has_value()) {
|
|
97
|
+
proto.set_group(*request.group);
|
|
98
|
+
}
|
|
99
|
+
if (request.group_level.has_value()) {
|
|
100
|
+
proto.set_group_level(*request.group_level);
|
|
101
|
+
}
|
|
102
|
+
if (request.inclusive_end.has_value()) {
|
|
103
|
+
proto.set_inclusive_end(*request.inclusive_end);
|
|
104
|
+
}
|
|
105
|
+
proto.set_debug(request.debug);
|
|
106
|
+
if (request.consistency.has_value()) {
|
|
107
|
+
switch (*request.consistency) {
|
|
108
|
+
case view_scan_consistency::not_bounded:
|
|
109
|
+
proto.set_scan_consistency(
|
|
110
|
+
v1::ViewQueryRequest_ScanConsistency_SCAN_CONSISTENCY_NOT_BOUNDED);
|
|
111
|
+
break;
|
|
112
|
+
case view_scan_consistency::update_after:
|
|
113
|
+
proto.set_scan_consistency(
|
|
114
|
+
v1::ViewQueryRequest_ScanConsistency_SCAN_CONSISTENCY_UPDATE_AFTER);
|
|
115
|
+
break;
|
|
116
|
+
case view_scan_consistency::request_plus:
|
|
117
|
+
proto.set_scan_consistency(
|
|
118
|
+
v1::ViewQueryRequest_ScanConsistency_SCAN_CONSISTENCY_REQUEST_PLUS);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (request.order.has_value()) {
|
|
123
|
+
proto.set_order(*request.order == view_sort_order::descending
|
|
124
|
+
? v1::ViewQueryRequest_Order_ORDER_DESCENDING
|
|
125
|
+
: v1::ViewQueryRequest_Order_ORDER_ASCENDING);
|
|
126
|
+
}
|
|
127
|
+
if (request.on_error.has_value()) {
|
|
128
|
+
proto.set_on_error(*request.on_error == view_on_error::stop
|
|
129
|
+
? v1::ViewQueryRequest_ErrorMode_ERROR_MODE_STOP
|
|
130
|
+
: v1::ViewQueryRequest_ErrorMode_ERROR_MODE_CONTINUE);
|
|
131
|
+
}
|
|
132
|
+
return proto;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Append the rows from one streamed message onto the buffered response.
|
|
136
|
+
inline void
|
|
137
|
+
decode_rows(const v1::ViewQueryResponse& message, operations::document_view_response& response)
|
|
138
|
+
{
|
|
139
|
+
for (const auto& row : message.rows()) {
|
|
140
|
+
operations::document_view_response::row out;
|
|
141
|
+
if (!row.id().empty()) {
|
|
142
|
+
out.id = row.id();
|
|
143
|
+
}
|
|
144
|
+
out.key = row.key();
|
|
145
|
+
out.value = row.value();
|
|
146
|
+
response.rows.push_back(std::move(out));
|
|
147
|
+
}
|
|
148
|
+
if (message.has_meta_data()) {
|
|
149
|
+
response.meta.total_rows = message.meta_data().total_rows();
|
|
150
|
+
if (!message.meta_data().debug().empty()) {
|
|
151
|
+
response.meta.debug_info = message.meta_data().debug();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
} // namespace couchbase::core::protostellar::view
|
|
157
|
+
|
|
158
|
+
#pragma pop_macro("COUCHBASE_CXX_CLIENT_IGNORE_CORE_DEPRECATIONS")
|