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
|
@@ -17,106 +17,355 @@
|
|
|
17
17
|
|
|
18
18
|
#pragma once
|
|
19
19
|
|
|
20
|
+
#include <cstddef>
|
|
20
21
|
#include <functional>
|
|
21
22
|
#include <memory>
|
|
23
|
+
#include <new>
|
|
24
|
+
#include <type_traits>
|
|
25
|
+
#include <utility>
|
|
22
26
|
|
|
23
|
-
/* replace with
|
|
27
|
+
/* replace with std::move_only_function once http://wg21.link/P0288 is available (C++23) */
|
|
24
28
|
namespace couchbase::core::utils
|
|
25
29
|
{
|
|
30
|
+
#ifdef __clang_analyzer__
|
|
31
|
+
// Declared but never defined: an opaque sink (analysis only; analysis does not link, and it is
|
|
32
|
+
// absent from every real build). See emplace() below -- handing the owned target pointer to a
|
|
33
|
+
// non-const opaque sink marks it "escaped" so MallocChecker stops tracking an allocation it would
|
|
34
|
+
// otherwise lose inside asio's deeply templated post/dispatch machinery and report as a spurious
|
|
35
|
+
// leak. The parameter is NON-const on purpose: checkPointerEscapeAux only releases a symbol through
|
|
36
|
+
// a const pointer when it is new/new[]-family, but unconditionally through a non-const pointer.
|
|
37
|
+
void
|
|
38
|
+
movable_function_analyzer_escape(void*) noexcept;
|
|
39
|
+
#endif
|
|
40
|
+
|
|
26
41
|
template<typename Signature>
|
|
27
|
-
class movable_function
|
|
28
|
-
{
|
|
29
|
-
template<typename Functor, typename En = void>
|
|
30
|
-
struct wrapper;
|
|
42
|
+
class movable_function;
|
|
31
43
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
/**
|
|
45
|
+
* A move-only, type-erased callable, equivalent in spirit to std::move_only_function (C++23).
|
|
46
|
+
*
|
|
47
|
+
* A target that fits the inline buffer and is nothrow-move-constructible is stored in place, so the
|
|
48
|
+
* common asio/KV handlers (a captured shared_ptr `self` plus a few members) are type-erased with no
|
|
49
|
+
* heap allocation; larger targets are held on the heap. The type owns its target and transfers
|
|
50
|
+
* ownership on move (copying is not provided). It offers `operator bool` and comparison against
|
|
51
|
+
* nullptr, and throws std::bad_function_call when invoked while empty.
|
|
52
|
+
*/
|
|
53
|
+
template<typename R, typename... Args>
|
|
54
|
+
class movable_function<R(Args...)>
|
|
55
|
+
{
|
|
56
|
+
#ifdef __clang_analyzer__
|
|
57
|
+
// Analyzer-only implementation (compiled only under the Clang Static Analyzer, never in real
|
|
58
|
+
// builds). The production small-buffer path below frees its target through an indirect
|
|
59
|
+
// `vtable_->destroy(buffer_)` function pointer the analyzer cannot resolve; blind to the free,
|
|
60
|
+
// MallocChecker reports spurious "Potential memory leak" at every caller that stores a
|
|
61
|
+
// heap-owning handler (libstdc++'s own std::move_only_function hits the identical limitation,
|
|
62
|
+
// llvm-project#69602). Under analysis we instead own the target via
|
|
63
|
+
// std::unique_ptr<callable_base>, whose destruction is an ordinary virtual delete that
|
|
64
|
+
// MallocChecker models natively -- no manual vtable, no unresolved indirect free, no escape
|
|
65
|
+
// heuristics. This models the same own-once / free-once / move-transfers semantics as the real
|
|
66
|
+
// path, so it does not mask genuine leaks.
|
|
67
|
+
struct callable_base {
|
|
68
|
+
callable_base() = default;
|
|
69
|
+
callable_base(const callable_base&) = delete;
|
|
70
|
+
callable_base(callable_base&&) = delete;
|
|
71
|
+
auto operator=(const callable_base&) -> callable_base& = delete;
|
|
72
|
+
auto operator=(callable_base&&) -> callable_base& = delete;
|
|
73
|
+
virtual ~callable_base() = default;
|
|
74
|
+
virtual auto invoke(Args... args) -> R = 0;
|
|
75
|
+
};
|
|
35
76
|
|
|
36
|
-
|
|
37
|
-
|
|
77
|
+
template<typename F>
|
|
78
|
+
struct callable_model : callable_base {
|
|
79
|
+
F fn;
|
|
80
|
+
// Forwarding ctor so the target is copied from an lvalue or moved from an rvalue, matching the
|
|
81
|
+
// production `decayed(std::forward<F>(f))` -- a plain `F&&` parameter would reject lvalue
|
|
82
|
+
// targets.
|
|
83
|
+
template<typename U>
|
|
84
|
+
explicit callable_model(U&& u)
|
|
85
|
+
: fn(std::forward<U>(u))
|
|
86
|
+
{
|
|
87
|
+
}
|
|
88
|
+
auto invoke(Args... args) -> R override
|
|
38
89
|
{
|
|
39
|
-
|
|
90
|
+
if constexpr (std::is_void_v<R>) {
|
|
91
|
+
fn(std::forward<Args>(args)...);
|
|
92
|
+
} else {
|
|
93
|
+
return fn(std::forward<Args>(args)...);
|
|
94
|
+
}
|
|
40
95
|
}
|
|
41
96
|
};
|
|
42
97
|
|
|
43
|
-
|
|
44
|
-
struct copy_wrapper {
|
|
45
|
-
Functor fn;
|
|
98
|
+
std::unique_ptr<callable_base> holder_{};
|
|
46
99
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
100
|
+
template<typename F>
|
|
101
|
+
void emplace(F&& f)
|
|
102
|
+
{
|
|
103
|
+
holder_ = std::make_unique<callable_model<std::decay_t<F>>>(std::forward<F>(f));
|
|
104
|
+
// Escape the owned block: some callers (e.g. asio::post/dispatch) move *this into templated
|
|
105
|
+
// machinery the analyzer cannot follow, where it would otherwise lose this allocation and
|
|
106
|
+
// report a spurious leak. holder_.get() is a direct object pointer, so the non-const escape
|
|
107
|
+
// releases exactly the callable_model block (see the sink declaration).
|
|
108
|
+
movable_function_analyzer_escape(static_cast<void*>(holder_.get()));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
void move_from(movable_function&& other) noexcept
|
|
112
|
+
{
|
|
113
|
+
holder_ = std::move(other.holder_);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
void reset() noexcept
|
|
117
|
+
{
|
|
118
|
+
holder_.reset();
|
|
119
|
+
}
|
|
120
|
+
#else
|
|
121
|
+
// Sized to hold typical handlers (e.g. a shared_ptr self, a time_point, and a shared_ptr span)
|
|
122
|
+
// inline; larger callables fall back to the heap. The 6-pointer estimate is 48 bytes on 64-bit;
|
|
123
|
+
// a 48-byte floor keeps that inline capacity on 32-bit too (where 6 pointers would be only 24
|
|
124
|
+
// bytes), so the small-buffer optimization does not silently regress to more heap allocations.
|
|
125
|
+
static constexpr std::size_t buffer_size = (6 * sizeof(void*) > 48) ? (6 * sizeof(void*)) : 48;
|
|
126
|
+
|
|
127
|
+
struct vtable {
|
|
128
|
+
R (*invoke)(void* self, Args&&... args);
|
|
129
|
+
void (*move)(void* dst, void* src) noexcept; // move-construct dst from src, then destroy src
|
|
130
|
+
void (*destroy)(void* self) noexcept;
|
|
51
131
|
};
|
|
52
132
|
|
|
53
|
-
template<typename
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
std::shared_ptr<copy_wrapper<Functor>> fnPtr;
|
|
133
|
+
template<typename F>
|
|
134
|
+
static constexpr bool fits_inline_v =
|
|
135
|
+
sizeof(F) <= buffer_size && alignof(F) <= alignof(std::max_align_t) &&
|
|
136
|
+
std::is_nothrow_move_constructible_v<F>;
|
|
58
137
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
138
|
+
template<typename F>
|
|
139
|
+
static auto inline_vtable() -> const vtable&
|
|
140
|
+
{
|
|
141
|
+
// The target lives in buffer_ (an unsigned char array) via placement-new, so accesses go
|
|
142
|
+
// through std::launder to obtain a pointer with the target's lifetime rather than the array's.
|
|
143
|
+
static const vtable vt{
|
|
144
|
+
[](void* self, Args&&... args) -> R {
|
|
145
|
+
// For a void signature the target's result is discardable (std::is_invocable_r_v<void, ...>
|
|
146
|
+
// admits a value-returning callable), so a value-returning target must be invoked without a
|
|
147
|
+
// return statement -- `return <non-void>;` in a void thunk is ill-formed.
|
|
148
|
+
if constexpr (std::is_void_v<R>) {
|
|
149
|
+
(*std::launder(static_cast<F*>(self)))(std::forward<Args>(args)...);
|
|
150
|
+
} else {
|
|
151
|
+
return (*std::launder(static_cast<F*>(self)))(std::forward<Args>(args)...);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
[](void* dst, void* src) noexcept {
|
|
155
|
+
::new (dst) F(std::move(*std::launder(static_cast<F*>(src))));
|
|
156
|
+
std::launder(static_cast<F*>(src))->~F();
|
|
157
|
+
},
|
|
158
|
+
[](void* self) noexcept {
|
|
159
|
+
std::launder(static_cast<F*>(self))->~F();
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
return vt;
|
|
163
|
+
}
|
|
63
164
|
|
|
64
|
-
|
|
65
|
-
|
|
165
|
+
template<typename F>
|
|
166
|
+
static auto heap_vtable() -> const vtable&
|
|
167
|
+
{
|
|
168
|
+
// The buffer holds an owned F* (placement-new'd in emplace()), so every access to that pointer
|
|
169
|
+
// goes through std::launder to reflect the pointer object's lifetime, not the array's.
|
|
170
|
+
static const vtable vt{
|
|
171
|
+
[](void* self, Args&&... args) -> R {
|
|
172
|
+
// Same void-result handling as the inline thunk: discard a value-returning target rather
|
|
173
|
+
// than emit `return <non-void>;` in a void-returning thunk.
|
|
174
|
+
if constexpr (std::is_void_v<R>) {
|
|
175
|
+
(**std::launder(static_cast<F**>(self)))(std::forward<Args>(args)...);
|
|
176
|
+
} else {
|
|
177
|
+
return (**std::launder(static_cast<F**>(self)))(std::forward<Args>(args)...);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
[](void* dst, void* src) noexcept {
|
|
181
|
+
// Begin the lifetime of the owned pointer in dst (uninitialized storage) rather than
|
|
182
|
+
// assigning through an F** into it, matching the placement-new in emplace(). The alias
|
|
183
|
+
// keeps this a new-expression rather than something that reads as a C-style cast.
|
|
184
|
+
using owned_ptr = F*;
|
|
185
|
+
::new (dst) owned_ptr(*std::launder(static_cast<F**>(src)));
|
|
186
|
+
*std::launder(static_cast<F**>(src)) = nullptr;
|
|
187
|
+
},
|
|
188
|
+
[](void* self) noexcept {
|
|
189
|
+
delete *std::launder(static_cast<F**>(self));
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
return vt;
|
|
193
|
+
}
|
|
66
194
|
|
|
67
|
-
|
|
68
|
-
|
|
195
|
+
// Zero-initialized so the object has no uninitialized members; the bytes are always overwritten
|
|
196
|
+
// by emplace()/move_from() before vtable_ is set and are only ever read back through vtable_
|
|
197
|
+
// (null while the buffer holds no target), so the initialization is defensive, not relied upon.
|
|
198
|
+
alignas(std::max_align_t) unsigned char buffer_[buffer_size]{};
|
|
199
|
+
const vtable* vtable_{ nullptr };
|
|
69
200
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
201
|
+
// MSVC emits C4702 (unreachable code) during a late optimization pass, not during parsing, so a
|
|
202
|
+
// push/pop around the individual store does not catch it -- the suppression must wrap the whole
|
|
203
|
+
// function. For an F whose selected constructor can only throw (e.g. throwing_copy_functor in the
|
|
204
|
+
// unit tests) MSVC proves construction never returns and flags every following statement as
|
|
205
|
+
// unreachable; every other F reaches them normally, so the warning is a false positive here.
|
|
206
|
+
#if defined(_MSC_VER)
|
|
207
|
+
#pragma warning(push)
|
|
208
|
+
#pragma warning(disable : 4702)
|
|
209
|
+
#endif
|
|
210
|
+
template<typename F>
|
|
211
|
+
void emplace(F&& f)
|
|
212
|
+
{
|
|
213
|
+
using decayed = std::decay_t<F>;
|
|
214
|
+
if constexpr (fits_inline_v<decayed>) {
|
|
215
|
+
::new (static_cast<void*>(buffer_)) decayed(std::forward<F>(f));
|
|
216
|
+
vtable_ = &inline_vtable<decayed>();
|
|
217
|
+
} else {
|
|
218
|
+
// Begin the lifetime of a decayed* in the buffer (symmetric with the inline placement-new
|
|
219
|
+
// above), then read it back through the heap vtable.
|
|
220
|
+
::new (static_cast<void*>(buffer_)) decayed*(new decayed(std::forward<F>(f)));
|
|
221
|
+
vtable_ = &heap_vtable<decayed>();
|
|
74
222
|
}
|
|
75
|
-
}
|
|
223
|
+
}
|
|
224
|
+
#if defined(_MSC_VER)
|
|
225
|
+
#pragma warning(pop)
|
|
226
|
+
#endif
|
|
76
227
|
|
|
77
|
-
|
|
228
|
+
void move_from(movable_function&& other) noexcept
|
|
229
|
+
{
|
|
230
|
+
if (other.vtable_ != nullptr) {
|
|
231
|
+
other.vtable_->move(buffer_, other.buffer_);
|
|
232
|
+
vtable_ = other.vtable_;
|
|
233
|
+
other.vtable_ = nullptr;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
void reset() noexcept
|
|
238
|
+
{
|
|
239
|
+
if (vtable_ != nullptr) {
|
|
240
|
+
vtable_->destroy(buffer_);
|
|
241
|
+
vtable_ = nullptr;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
#endif
|
|
245
|
+
|
|
246
|
+
// Constrain on constructibility as well as invocability: emplace() stores the target by
|
|
247
|
+
// constructing a std::decay_t<F> from the forwarded argument, so a callable that cannot be
|
|
248
|
+
// constructed there (e.g. a non-movable functor passed as an rvalue) is removed from overload
|
|
249
|
+
// resolution rather than producing a hard error inside emplace().
|
|
250
|
+
//
|
|
251
|
+
// std::conjunction, not &&: the terms have to be instantiated one at a time, stopping at the
|
|
252
|
+
// first that is false. Asking whether this type is copy constructible -- which anything holding
|
|
253
|
+
// it in a std::any does -- instantiates this constraint with F = const movable_function&, and the
|
|
254
|
+
// constructibility term then asks for the trait that is already being computed. && evaluates
|
|
255
|
+
// lazily but instantiates every operand regardless, so the self-exclusion has to gate the others
|
|
256
|
+
// rather than merely precede them.
|
|
257
|
+
template<typename F>
|
|
258
|
+
using enable_if_callable = std::enable_if_t<
|
|
259
|
+
std::conjunction_v<std::negation<std::is_same<std::decay_t<F>, movable_function>>,
|
|
260
|
+
std::is_constructible<std::decay_t<F>, F>,
|
|
261
|
+
std::is_invocable_r<R, std::decay_t<F>&, Args...>>>;
|
|
78
262
|
|
|
79
263
|
public:
|
|
80
264
|
movable_function() noexcept = default;
|
|
81
265
|
movable_function(std::nullptr_t) noexcept
|
|
82
|
-
: base(nullptr)
|
|
83
266
|
{
|
|
84
267
|
}
|
|
85
268
|
|
|
86
|
-
template<typename
|
|
87
|
-
movable_function(
|
|
88
|
-
: base(wrapper<Functor>{ std::forward<Functor>(f) })
|
|
269
|
+
template<typename F, typename = enable_if_callable<F>>
|
|
270
|
+
movable_function(F&& f)
|
|
89
271
|
{
|
|
272
|
+
emplace(std::forward<F>(f));
|
|
90
273
|
}
|
|
91
274
|
|
|
92
275
|
movable_function(movable_function&& other) noexcept
|
|
93
|
-
: base(std::move(static_cast<base&&>(other)))
|
|
94
276
|
{
|
|
95
|
-
other
|
|
277
|
+
move_from(std::move(other));
|
|
96
278
|
}
|
|
97
279
|
|
|
98
280
|
auto operator=(movable_function&& other) noexcept -> movable_function&
|
|
99
281
|
{
|
|
100
|
-
|
|
101
|
-
|
|
282
|
+
if (this != &other) {
|
|
283
|
+
reset();
|
|
284
|
+
move_from(std::move(other));
|
|
285
|
+
}
|
|
102
286
|
return *this;
|
|
103
287
|
}
|
|
104
288
|
|
|
105
|
-
|
|
289
|
+
movable_function(const movable_function&) = delete;
|
|
290
|
+
auto operator=(const movable_function&) -> movable_function& = delete;
|
|
291
|
+
|
|
292
|
+
~movable_function()
|
|
106
293
|
{
|
|
107
|
-
|
|
294
|
+
reset();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
auto operator=(std::nullptr_t) noexcept -> movable_function&
|
|
298
|
+
{
|
|
299
|
+
reset();
|
|
108
300
|
return *this;
|
|
109
301
|
}
|
|
110
302
|
|
|
111
|
-
|
|
112
|
-
|
|
303
|
+
// Same MSVC C4702 false positive as emplace(), and the same whole-function suppression: for an F
|
|
304
|
+
// whose constructor can only throw, the temporary below can never return normally, so MSVC flags
|
|
305
|
+
// the assignment and return as unreachable, even though every other F reaches them normally.
|
|
306
|
+
#if defined(_MSC_VER)
|
|
307
|
+
#pragma warning(push)
|
|
308
|
+
#pragma warning(disable : 4702)
|
|
309
|
+
#endif
|
|
310
|
+
template<typename F, typename = enable_if_callable<F>>
|
|
311
|
+
auto operator=(F&& f) -> movable_function&
|
|
113
312
|
{
|
|
114
|
-
|
|
313
|
+
// Strong exception guarantee, matching std::function / std::move_only_function: build the new
|
|
314
|
+
// target in a temporary first -- the only step that can throw (heap allocation, or a throwing
|
|
315
|
+
// copy when f is an lvalue) -- then adopt it through the noexcept move-assignment. A bare
|
|
316
|
+
// reset()+emplace() would give only the basic guarantee: a throwing emplace() would leave the
|
|
317
|
+
// previous target already destroyed and *this empty.
|
|
318
|
+
*this = movable_function(std::forward<F>(f));
|
|
115
319
|
return *this;
|
|
116
320
|
}
|
|
321
|
+
#if defined(_MSC_VER)
|
|
322
|
+
#pragma warning(pop)
|
|
323
|
+
#endif
|
|
324
|
+
|
|
325
|
+
explicit operator bool() const noexcept
|
|
326
|
+
{
|
|
327
|
+
#ifdef __clang_analyzer__
|
|
328
|
+
return static_cast<bool>(holder_);
|
|
329
|
+
#else
|
|
330
|
+
return vtable_ != nullptr;
|
|
331
|
+
#endif
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
friend auto operator==(const movable_function& f, std::nullptr_t) noexcept -> bool
|
|
335
|
+
{
|
|
336
|
+
return !static_cast<bool>(f);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
friend auto operator==(std::nullptr_t, const movable_function& f) noexcept -> bool
|
|
340
|
+
{
|
|
341
|
+
return !static_cast<bool>(f);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
friend auto operator!=(const movable_function& f, std::nullptr_t) noexcept -> bool
|
|
345
|
+
{
|
|
346
|
+
return static_cast<bool>(f);
|
|
347
|
+
}
|
|
117
348
|
|
|
118
|
-
|
|
119
|
-
|
|
349
|
+
friend auto operator!=(std::nullptr_t, const movable_function& f) noexcept -> bool
|
|
350
|
+
{
|
|
351
|
+
return static_cast<bool>(f);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
auto operator()(Args... args) const -> R
|
|
355
|
+
{
|
|
356
|
+
#ifdef __clang_analyzer__
|
|
357
|
+
if (!holder_) {
|
|
358
|
+
throw std::bad_function_call{};
|
|
359
|
+
}
|
|
360
|
+
return holder_->invoke(std::forward<Args>(args)...);
|
|
361
|
+
#else
|
|
362
|
+
if (vtable_ == nullptr) {
|
|
363
|
+
throw std::bad_function_call{};
|
|
364
|
+
}
|
|
365
|
+
return vtable_->invoke(const_cast<void*>(static_cast<const void*>(buffer_)),
|
|
366
|
+
std::forward<Args>(args)...);
|
|
367
|
+
#endif
|
|
368
|
+
}
|
|
120
369
|
};
|
|
121
370
|
|
|
122
371
|
} // namespace couchbase::core::utils
|
|
@@ -17,25 +17,168 @@
|
|
|
17
17
|
|
|
18
18
|
#pragma once
|
|
19
19
|
|
|
20
|
-
#include <
|
|
20
|
+
#include <algorithm>
|
|
21
|
+
#include <initializer_list>
|
|
21
22
|
#include <string>
|
|
23
|
+
#include <string_view>
|
|
22
24
|
|
|
23
25
|
namespace couchbase::core::utils
|
|
24
26
|
{
|
|
27
|
+
/**
|
|
28
|
+
* Renders names as Analytics SQL++ delimited identifiers.
|
|
29
|
+
*
|
|
30
|
+
* Two distinct operations are involved, and this file keeps them apart deliberately:
|
|
31
|
+
*
|
|
32
|
+
* - QUOTING wraps a name in backticks so the parser reads it as one identifier token instead of
|
|
33
|
+
* as keywords and punctuation. Analytics calls the result a delimited identifier.
|
|
34
|
+
* - ESCAPING rewrites individual characters inside those backticks so that none of them can end
|
|
35
|
+
* the token early or be reinterpreted by the parser.
|
|
36
|
+
*
|
|
37
|
+
* Both are needed: quoting alone is not safe, because a character inside the quotes can still
|
|
38
|
+
* terminate them.
|
|
39
|
+
*
|
|
40
|
+
* The grammar for a delimited identifier is (asterix-lang-sqlpp SQLPP.jj, token QUOTED_STRING):
|
|
41
|
+
*
|
|
42
|
+
* "`" ( "\\\\" | "\\\"" | "\\/" | "\\b" | "\\f" | "\\n" | "\\r" | "\\t" | ~["`","\\"] )* "`"
|
|
43
|
+
*
|
|
44
|
+
* so the only escape mechanism is a backslash sequence, and the only two characters with any
|
|
45
|
+
* special meaning inside the quotes are the backslash and the backtick. Three consequences shape
|
|
46
|
+
* this code:
|
|
47
|
+
*
|
|
48
|
+
* - THE BACKSLASH MUST BE ESCAPED, as "\\\\". It is the escape introducer, and before the lexer
|
|
49
|
+
* ever runs, the character stream expands a \\uXXXX sequence into the character it denotes
|
|
50
|
+
* (JavaCharStream::readChar). That expansion fires only when the backslash run preceding the
|
|
51
|
+
* 'u' is of odd length, so doubling every backslash makes every run even and puts the
|
|
52
|
+
* expansion permanently out of reach. Leaving backslashes alone instead would let the six
|
|
53
|
+
* characters \\u0060 become a real backtick and close the identifier.
|
|
54
|
+
*
|
|
55
|
+
* - A BACKTICK CANNOT BE ESCAPED AT ALL, so a name containing one has no representation as a
|
|
56
|
+
* delimited identifier. Note that doubling it is NOT an escape here: unlike a string literal,
|
|
57
|
+
* whose grammar rule concatenates adjacent tokens and so does give "``" the meaning of one
|
|
58
|
+
* literal quote, an identifier is a single token with no such rule, and "`a``b`" is simply two
|
|
59
|
+
* adjacent tokens. Requests reject these names up front via all_quotable(); see the note on
|
|
60
|
+
* append_escaped() for what happens if one gets through anyway.
|
|
61
|
+
*
|
|
62
|
+
* - NOTHING ELSE NEEDS ESCAPING. Every other byte, including a raw quote, slash, newline, tab,
|
|
63
|
+
* NUL and anything above 0x7f, is matched by ~["`","\\"] and passes through unchanged. In
|
|
64
|
+
* particular a double quote must NOT be escaped as "\\\"": the server only honours that escape
|
|
65
|
+
* when the escaped character is the same as the opening delimiter, so inside backticks it
|
|
66
|
+
* would silently drop the quote and corrupt the name.
|
|
67
|
+
*/
|
|
25
68
|
struct analytics {
|
|
26
|
-
|
|
69
|
+
/**
|
|
70
|
+
* True when every name can be quoted, i.e. none of them contains a backtick.
|
|
71
|
+
*
|
|
72
|
+
* Requests call this before building a statement and fail with errc::common::invalid_argument
|
|
73
|
+
* when it returns false. It reports only whether the whole set is usable, not which name was at
|
|
74
|
+
* fault: the encoders return a single error code and have no channel for a richer message.
|
|
75
|
+
*/
|
|
76
|
+
[[nodiscard]] static auto all_quotable(std::initializer_list<std::string_view> names) -> bool
|
|
27
77
|
{
|
|
28
|
-
std::
|
|
29
|
-
|
|
78
|
+
return std::all_of(names.begin(), names.end(), [](const auto name) {
|
|
79
|
+
return name.find('`') == std::string_view::npos;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Quotes a name as a single delimited identifier, escaping its body.
|
|
85
|
+
*
|
|
86
|
+
* Preconditions: all_quotable({ name }). Separators are not interpreted, so a '.' or '/' in the
|
|
87
|
+
* name becomes part of the identifier rather than splitting it.
|
|
88
|
+
*/
|
|
89
|
+
[[nodiscard]] static auto quote_identifier(const std::string& name) -> std::string
|
|
90
|
+
{
|
|
91
|
+
std::string result;
|
|
92
|
+
result.reserve(name.size() + 2);
|
|
93
|
+
result.push_back('`');
|
|
30
94
|
for (const auto symbol : name) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
95
|
+
append_escaped(result, symbol);
|
|
96
|
+
}
|
|
97
|
+
result.push_back('`');
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Quotes a dotted field path ("address.city") by quoting each segment separately and rejoining
|
|
103
|
+
* them with an unquoted '.', so that the parser sees a path of identifiers rather than one
|
|
104
|
+
* identifier containing dots.
|
|
105
|
+
*
|
|
106
|
+
* Preconditions: all_quotable({ path }).
|
|
107
|
+
*/
|
|
108
|
+
[[nodiscard]] static auto quote_field_path(const std::string& path) -> std::string
|
|
109
|
+
{
|
|
110
|
+
return quote_parts(path, '.', '.');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Quotes a dataverse name, which the SDK spells as a '/'-separated compound ("bucket/scope"),
|
|
115
|
+
* into the dot-qualified form the statement needs: "bucket/scope" becomes `bucket`.`scope`.
|
|
116
|
+
*
|
|
117
|
+
* Preconditions: all_quotable({ name }).
|
|
118
|
+
*
|
|
119
|
+
* This is a pure encoder: it does not substitute a default for an empty name. Requests that treat
|
|
120
|
+
* the dataverse as optional already default it to "Default" in their own declarations, and the
|
|
121
|
+
* two that do not (analytics_dataverse_create, analytics_dataverse_drop) take the dataverse as a
|
|
122
|
+
* required argument naming the object to create or drop, where silently retargeting an empty name
|
|
123
|
+
* onto "Default" would be destructive.
|
|
124
|
+
*/
|
|
125
|
+
[[nodiscard]] static auto quote_dataverse_name(const std::string& name) -> std::string
|
|
126
|
+
{
|
|
127
|
+
return quote_parts(name, '/', '.');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private:
|
|
131
|
+
/**
|
|
132
|
+
* Splits on separator, quotes each part, and rejoins with joiner. The separator itself is never
|
|
133
|
+
* escaped, because it is consumed here rather than passed to quote_identifier(); an empty part
|
|
134
|
+
* yields an empty identifier, which the server rejects rather than misinterprets.
|
|
135
|
+
*/
|
|
136
|
+
[[nodiscard]] static auto quote_parts(const std::string& name, char separator, char joiner)
|
|
137
|
+
-> std::string
|
|
138
|
+
{
|
|
139
|
+
std::string result;
|
|
140
|
+
result.reserve(name.size() + 2);
|
|
141
|
+
for (std::size_t start = 0;;) {
|
|
142
|
+
const auto pos = name.find(separator, start);
|
|
143
|
+
// Standing in for "this is not the first part", which holds only because quote_identifier()
|
|
144
|
+
// never returns an empty string. Were that to change, a leading separator would lose its
|
|
145
|
+
// empty first part and silently retarget the name instead of producing one the server
|
|
146
|
+
// rejects.
|
|
147
|
+
if (!result.empty()) {
|
|
148
|
+
result.push_back(joiner);
|
|
35
149
|
}
|
|
150
|
+
result.append(quote_identifier(
|
|
151
|
+
name.substr(start, pos == std::string::npos ? std::string::npos : pos - start)));
|
|
152
|
+
if (pos == std::string::npos) {
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
start = pos + 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Appends one character of an identifier body.
|
|
161
|
+
*
|
|
162
|
+
* The backslash is escaped, which is the whole of what escaping means here. The backtick has no
|
|
163
|
+
* escape, so it cannot be handled correctly at all; emitting it doubled is a deliberate last
|
|
164
|
+
* resort for a name that reached this point without passing all_quotable(). It produces two
|
|
165
|
+
* adjacent identifier tokens and therefore an unparseable statement, which fails closed, rather
|
|
166
|
+
* than a lone backtick, which would end the identifier and let the rest of the name be parsed as
|
|
167
|
+
* SQL++. It is a backstop against a future caller forgetting the precondition, not an escape.
|
|
168
|
+
*/
|
|
169
|
+
static void append_escaped(std::string& result, char symbol)
|
|
170
|
+
{
|
|
171
|
+
switch (symbol) {
|
|
172
|
+
case '\\':
|
|
173
|
+
result.append("\\\\");
|
|
174
|
+
break;
|
|
175
|
+
case '`':
|
|
176
|
+
result.append("``");
|
|
177
|
+
break;
|
|
178
|
+
default:
|
|
179
|
+
result.push_back(symbol);
|
|
180
|
+
break;
|
|
36
181
|
}
|
|
37
|
-
ss << '`';
|
|
38
|
-
return ss.str();
|
|
39
182
|
}
|
|
40
183
|
};
|
|
41
|
-
} // namespace couchbase::core::utils
|
|
184
|
+
} // namespace couchbase::core::utils
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
2
|
/*
|
|
3
|
-
* Copyright
|
|
3
|
+
* Copyright 2026. Couchbase, Inc.
|
|
4
4
|
*
|
|
5
5
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
6
|
* you may not use this file except in compliance with the License.
|
|
@@ -17,18 +17,23 @@
|
|
|
17
17
|
|
|
18
18
|
#pragma once
|
|
19
19
|
|
|
20
|
-
#include
|
|
20
|
+
#include <cstdint>
|
|
21
21
|
|
|
22
|
-
#
|
|
23
|
-
#include <
|
|
22
|
+
#if defined(_WIN32)
|
|
23
|
+
#include <process.h>
|
|
24
|
+
#else
|
|
25
|
+
#include <unistd.h>
|
|
26
|
+
#endif
|
|
24
27
|
|
|
25
|
-
namespace couchbase::core::
|
|
28
|
+
namespace couchbase::core::utils
|
|
26
29
|
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
std::
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
inline auto
|
|
31
|
+
current_process_id() -> std::int64_t
|
|
32
|
+
{
|
|
33
|
+
#if defined(_WIN32)
|
|
34
|
+
return static_cast<std::int64_t>(::_getpid());
|
|
35
|
+
#else
|
|
36
|
+
return static_cast<std::int64_t>(::getpid());
|
|
37
|
+
#endif
|
|
38
|
+
}
|
|
39
|
+
} // namespace couchbase::core::utils
|