couchbase 3.8.2 → 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.
Files changed (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/CMakeLists.txt +16 -1
  4. data/ext/cache/cpm/{CPM_0.42.0.cmake → CPM_0.43.1.cmake} +18 -2
  5. data/ext/cache/extconf_include.rb +6 -6
  6. data/ext/cache/mozilla-ca-bundle.crt +121 -55
  7. data/ext/cache/mozilla-ca-bundle.sha256 +1 -1
  8. data/ext/couchbase/CMakeLists.txt +130 -21
  9. data/ext/couchbase/cmake/APKBUILD.in +25 -4
  10. data/ext/couchbase/cmake/Bundler.cmake +143 -34
  11. data/ext/couchbase/cmake/CPM.cmake +126 -12
  12. data/ext/couchbase/cmake/Cache.cmake +7 -1
  13. data/ext/couchbase/cmake/CompilerOptions.cmake +1 -1
  14. data/ext/couchbase/cmake/CompilerWarnings.cmake +17 -6
  15. data/ext/couchbase/cmake/GrpcProtobuf.cmake +481 -0
  16. data/ext/couchbase/cmake/OpenSSL.cmake +10 -3
  17. data/ext/couchbase/cmake/Packaging.cmake +519 -65
  18. data/ext/couchbase/cmake/Protostellar.cmake +250 -0
  19. data/ext/couchbase/cmake/Sanitizers.cmake +61 -50
  20. data/ext/couchbase/cmake/StaticAnalyzers.cmake +16 -5
  21. data/ext/couchbase/cmake/TestFramework.cmake +283 -0
  22. data/ext/couchbase/cmake/TestFrameworkAddTests.cmake +51 -0
  23. data/ext/couchbase/cmake/Testing.cmake +27 -9
  24. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +141 -8
  25. data/ext/couchbase/cmake/VersionInfo.cmake +50 -0
  26. data/ext/couchbase/cmake/build_config.hxx.in +2 -1
  27. data/ext/couchbase/cmake/couchbase-cxx-client.spec.in +101 -23
  28. data/ext/couchbase/cmake/couchbase_cxx_client_static-config.cmake.in +7 -0
  29. data/ext/couchbase/cmake/couchbase_cxx_client_static.pc.in +2 -0
  30. data/ext/couchbase/cmake/gRPC_Generate.cmake +58 -0
  31. data/ext/couchbase/cmake/protobuf_Generate.cmake +69 -0
  32. data/ext/couchbase/cmake/require-git-checkout.cmake +25 -0
  33. data/ext/couchbase/cmake/tarball_glob.txt +49 -0
  34. data/ext/couchbase/core/agent_group.cxx +0 -8
  35. data/ext/couchbase/core/agent_group.hxx +0 -4
  36. data/ext/couchbase/core/analytics_stream.cxx +314 -0
  37. data/ext/couchbase/core/analytics_stream.hxx +129 -0
  38. data/ext/couchbase/core/analytics_stream_component.cxx +245 -0
  39. data/ext/couchbase/core/analytics_stream_component.hxx +67 -0
  40. data/ext/couchbase/core/app_telemetry_meter.cxx +25 -3
  41. data/ext/couchbase/core/app_telemetry_meter.hxx +77 -0
  42. data/ext/couchbase/core/app_telemetry_reporter.cxx +7 -6
  43. data/ext/couchbase/core/bucket.cxx +381 -87
  44. data/ext/couchbase/core/bucket.hxx +105 -25
  45. data/ext/couchbase/core/bucket_unit_test_api.hxx +57 -0
  46. data/ext/couchbase/core/capella.hxx +91 -0
  47. data/ext/couchbase/core/cluster.cxx +1554 -398
  48. data/ext/couchbase/core/cluster.hxx +39 -8
  49. data/ext/couchbase/core/cluster_agent.cxx +0 -8
  50. data/ext/couchbase/core/cluster_agent.hxx +0 -4
  51. data/ext/couchbase/core/cluster_options.hxx +26 -3
  52. data/ext/couchbase/core/collections_component.cxx +39 -15
  53. data/ext/couchbase/core/config_profiles.cxx +1 -1
  54. data/ext/couchbase/core/crud_component.cxx +2 -2
  55. data/ext/couchbase/core/crud_options.hxx +34 -0
  56. data/ext/couchbase/core/crypto/cbcrypto.cc +18 -13
  57. data/ext/couchbase/core/document_id_redaction.hxx +81 -0
  58. data/ext/couchbase/core/error_context/base_error_context.hxx +7 -6
  59. data/ext/couchbase/core/error_context/key_value.cxx +25 -2
  60. data/ext/couchbase/core/error_context/key_value.hxx +60 -33
  61. data/ext/couchbase/core/error_context/key_value_error_context.hxx +16 -15
  62. data/ext/couchbase/core/error_context/search.hxx +5 -0
  63. data/ext/couchbase/core/error_context/search_json.hxx +3 -0
  64. data/ext/couchbase/core/error_context/subdocument_error_context.hxx +19 -18
  65. data/ext/couchbase/core/error_context/view.hxx +5 -0
  66. data/ext/couchbase/core/free_form_http_request.cxx +237 -4
  67. data/ext/couchbase/core/free_form_http_request.hxx +41 -8
  68. data/ext/couchbase/core/http_component.cxx +300 -284
  69. data/ext/couchbase/core/http_component.hxx +0 -4
  70. data/ext/couchbase/core/impl/analytics.cxx +38 -5
  71. data/ext/couchbase/core/impl/analytics.hxx +34 -0
  72. data/ext/couchbase/core/impl/bootstrap_error.hxx +0 -3
  73. data/ext/couchbase/core/impl/collection.cxx +215 -202
  74. data/ext/couchbase/core/impl/collection_manager.cxx +1 -1
  75. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +45 -18
  76. data/ext/couchbase/core/impl/error.cxx +22 -2
  77. data/ext/couchbase/core/impl/internal_analytics_stream_result.hxx +111 -0
  78. data/ext/couchbase/core/impl/internal_query_stream_result.hxx +110 -0
  79. data/ext/couchbase/core/impl/invoke_with_node_id.hxx +15 -7
  80. data/ext/couchbase/core/impl/key_value_error_category.cxx +6 -0
  81. data/ext/couchbase/core/impl/lookup_in_replica.cxx +10 -10
  82. data/ext/couchbase/core/impl/lookup_in_replica.hxx +4 -4
  83. data/ext/couchbase/core/impl/node_id.cxx +49 -13
  84. data/ext/couchbase/core/impl/observability_recorder.cxx +12 -2
  85. data/ext/couchbase/core/impl/observe_poll.cxx +63 -23
  86. data/ext/couchbase/core/impl/public_analytics_stream_result.cxx +372 -0
  87. data/ext/couchbase/core/impl/public_bucket.cxx +48 -2
  88. data/ext/couchbase/core/impl/public_cluster.cxx +229 -42
  89. data/ext/couchbase/core/impl/public_query_stream_result.cxx +380 -0
  90. data/ext/couchbase/core/impl/public_transaction_get_multi_replicas_from_preferred_server_group_result.cxx +42 -0
  91. data/ext/couchbase/core/impl/public_transaction_get_multi_result.cxx +42 -0
  92. data/ext/couchbase/core/impl/query.cxx +76 -7
  93. data/ext/couchbase/core/impl/query.hxx +36 -0
  94. data/ext/couchbase/core/impl/query_index_manager.cxx +54 -1
  95. data/ext/couchbase/core/impl/replica_utils.cxx +101 -0
  96. data/ext/couchbase/core/impl/replica_utils.hxx +64 -0
  97. data/ext/couchbase/core/impl/resolve_node_id.hxx +125 -0
  98. data/ext/couchbase/core/impl/scope.cxx +70 -0
  99. data/ext/couchbase/core/impl/search.cxx +31 -1
  100. data/ext/couchbase/core/impl/transactions.cxx +130 -0
  101. data/ext/couchbase/core/impl/wait_until_ready.cxx +439 -0
  102. data/ext/couchbase/core/impl/wait_until_ready.hxx +110 -0
  103. data/ext/couchbase/core/impl/with_bucket_config_or_timeout.hxx +180 -0
  104. data/ext/couchbase/core/impl/with_cancellation.hxx +11 -3
  105. data/ext/couchbase/core/io/configuration_belongs_to_session.hxx +1 -2
  106. data/ext/couchbase/core/io/dns_client.cxx +122 -45
  107. data/ext/couchbase/core/io/dns_codec.hxx +21 -21
  108. data/ext/couchbase/core/io/dns_config.cxx +21 -6
  109. data/ext/couchbase/core/io/http_command.hxx +149 -121
  110. data/ext/couchbase/core/io/http_error.hxx +107 -0
  111. data/ext/couchbase/core/io/http_parser.cxx +4 -0
  112. data/ext/couchbase/core/io/http_session.cxx +606 -154
  113. data/ext/couchbase/core/io/http_session.hxx +147 -30
  114. data/ext/couchbase/core/io/http_session_manager.hxx +329 -382
  115. data/ext/couchbase/core/io/http_streaming_parser.cxx +4 -0
  116. data/ext/couchbase/core/io/http_streaming_response.cxx +328 -43
  117. data/ext/couchbase/core/io/http_streaming_response.hxx +37 -3
  118. data/ext/couchbase/core/io/mcbp_buffer_pool.hxx +122 -0
  119. data/ext/couchbase/core/io/mcbp_command.hxx +150 -51
  120. data/ext/couchbase/core/io/mcbp_command_id.hxx +45 -0
  121. data/ext/couchbase/core/io/mcbp_message.cxx +9 -1
  122. data/ext/couchbase/core/io/mcbp_message.hxx +19 -0
  123. data/ext/couchbase/core/io/mcbp_output_queue.hxx +150 -0
  124. data/ext/couchbase/core/io/mcbp_parser.cxx +24 -7
  125. data/ext/couchbase/core/io/mcbp_session.cxx +309 -301
  126. data/ext/couchbase/core/io/mcbp_session.hxx +27 -18
  127. data/ext/couchbase/core/io/opaque_ring_table.hxx +145 -0
  128. data/ext/couchbase/core/io/retry_orchestrator.hxx +6 -5
  129. data/ext/couchbase/core/io/stream_deadline.hxx +50 -0
  130. data/ext/couchbase/core/io/streams.cxx +151 -21
  131. data/ext/couchbase/core/io/streams.hxx +48 -1
  132. data/ext/couchbase/core/logger/logger.cxx +36 -0
  133. data/ext/couchbase/core/logger/logger.hxx +46 -6
  134. data/ext/couchbase/core/logger/redaction.hxx +503 -0
  135. data/ext/couchbase/core/management/eventing_status.hxx +10 -0
  136. data/ext/couchbase/core/management/eventing_status_json.hxx +4 -0
  137. data/ext/couchbase/core/mcbp/big_endian.cxx +1 -1
  138. data/ext/couchbase/core/mcbp/codec.cxx +27 -18
  139. data/ext/couchbase/core/mcbp/operation_queue.cxx +2 -2
  140. data/ext/couchbase/core/mcbp/packet.hxx +2 -2
  141. data/ext/couchbase/core/mcbp/queue_request.cxx +23 -6
  142. data/ext/couchbase/core/mcbp/queue_request.hxx +21 -0
  143. data/ext/couchbase/core/meta/features.hxx +13 -0
  144. data/ext/couchbase/core/meta/version.cxx +6 -3
  145. data/ext/couchbase/core/metrics/logging_meter.cxx +5 -10
  146. data/ext/couchbase/core/metrics/meter_wrapper.cxx +63 -33
  147. data/ext/couchbase/core/metrics/meter_wrapper.hxx +55 -3
  148. data/ext/couchbase/core/operations/analytics_response_parsing.cxx +177 -0
  149. data/ext/couchbase/core/operations/analytics_response_parsing.hxx +55 -0
  150. data/ext/couchbase/core/operations/document_analytics.cxx +48 -130
  151. data/ext/couchbase/core/operations/document_analytics.hxx +14 -2
  152. data/ext/couchbase/core/operations/document_get_all_replicas.hxx +15 -7
  153. data/ext/couchbase/core/operations/document_get_any_replica.hxx +19 -8
  154. data/ext/couchbase/core/operations/document_get_projected.cxx +1 -1
  155. data/ext/couchbase/core/{impl/get_replica.cxx → operations/document_get_replica.cxx} +21 -3
  156. data/ext/couchbase/core/{impl/get_replica.hxx → operations/document_get_replica.hxx} +31 -4
  157. data/ext/couchbase/core/operations/document_lookup_in.cxx +10 -10
  158. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +228 -198
  159. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +215 -217
  160. data/ext/couchbase/core/operations/document_query.cxx +108 -221
  161. data/ext/couchbase/core/operations/document_query.hxx +18 -4
  162. data/ext/couchbase/core/operations/document_search.cxx +52 -8
  163. data/ext/couchbase/core/operations/document_search.hxx +3 -0
  164. data/ext/couchbase/core/operations/document_view.cxx +3 -3
  165. data/ext/couchbase/core/operations/management/analytics_dataset_create.cxx +15 -8
  166. data/ext/couchbase/core/operations/management/analytics_dataset_create.hxx +4 -0
  167. data/ext/couchbase/core/operations/management/analytics_dataset_drop.cxx +11 -6
  168. data/ext/couchbase/core/operations/management/analytics_dataset_get_all.cxx +3 -2
  169. data/ext/couchbase/core/operations/management/analytics_dataverse_create.cxx +10 -5
  170. data/ext/couchbase/core/operations/management/analytics_dataverse_drop.cxx +10 -5
  171. data/ext/couchbase/core/operations/management/analytics_get_pending_mutations.cxx +2 -1
  172. data/ext/couchbase/core/operations/management/analytics_index_create.cxx +33 -8
  173. data/ext/couchbase/core/operations/management/analytics_index_drop.cxx +12 -7
  174. data/ext/couchbase/core/operations/management/analytics_index_get_all.cxx +3 -2
  175. data/ext/couchbase/core/operations/management/analytics_link_connect.cxx +11 -6
  176. data/ext/couchbase/core/operations/management/analytics_link_create.cxx +3 -3
  177. data/ext/couchbase/core/operations/management/analytics_link_disconnect.cxx +10 -4
  178. data/ext/couchbase/core/operations/management/analytics_link_drop.cxx +6 -4
  179. data/ext/couchbase/core/operations/management/analytics_link_get_all.cxx +4 -3
  180. data/ext/couchbase/core/operations/management/analytics_link_replace.cxx +3 -3
  181. data/ext/couchbase/core/operations/management/analytics_link_utils.hxx +1 -1
  182. data/ext/couchbase/core/operations/management/change_password.cxx +2 -0
  183. data/ext/couchbase/core/operations/management/collection_drop.cxx +5 -1
  184. data/ext/couchbase/core/operations/management/error_utils.cxx +59 -5
  185. data/ext/couchbase/core/operations/management/error_utils.hxx +29 -1
  186. data/ext/couchbase/core/operations/management/eventing_deploy_function.cxx +9 -3
  187. data/ext/couchbase/core/operations/management/eventing_drop_function.cxx +8 -3
  188. data/ext/couchbase/core/operations/management/eventing_get_all_functions.cxx +4 -2
  189. data/ext/couchbase/core/operations/management/eventing_get_function.cxx +5 -3
  190. data/ext/couchbase/core/operations/management/eventing_get_status.cxx +4 -2
  191. data/ext/couchbase/core/operations/management/eventing_pause_function.cxx +9 -3
  192. data/ext/couchbase/core/operations/management/eventing_resume_function.cxx +9 -3
  193. data/ext/couchbase/core/operations/management/eventing_undeploy_function.cxx +9 -3
  194. data/ext/couchbase/core/operations/management/eventing_upsert_function.cxx +9 -3
  195. data/ext/couchbase/core/operations/management/group_drop.cxx +3 -1
  196. data/ext/couchbase/core/operations/management/group_get.cxx +3 -1
  197. data/ext/couchbase/core/operations/management/group_upsert.cxx +11 -8
  198. data/ext/couchbase/core/operations/management/query_index_build.cxx +5 -2
  199. data/ext/couchbase/core/operations/management/query_index_create.cxx +9 -3
  200. data/ext/couchbase/core/operations/management/query_index_drop.cxx +11 -4
  201. data/ext/couchbase/core/operations/management/query_index_get_all.cxx +1 -1
  202. data/ext/couchbase/core/operations/management/query_index_get_all_deferred.cxx +1 -1
  203. data/ext/couchbase/core/operations/management/scope_drop.cxx +5 -1
  204. data/ext/couchbase/core/operations/management/scope_get_all.cxx +6 -1
  205. data/ext/couchbase/core/operations/management/search_get_stats.cxx +10 -0
  206. data/ext/couchbase/core/operations/management/search_index_analyze_document.cxx +3 -2
  207. data/ext/couchbase/core/operations/management/search_index_control_ingest.cxx +4 -3
  208. data/ext/couchbase/core/operations/management/search_index_control_plan_freeze.cxx +4 -3
  209. data/ext/couchbase/core/operations/management/search_index_control_query.cxx +4 -3
  210. data/ext/couchbase/core/operations/management/search_index_drop.cxx +2 -2
  211. data/ext/couchbase/core/operations/management/search_index_get.cxx +2 -2
  212. data/ext/couchbase/core/operations/management/search_index_get_documents_count.cxx +3 -2
  213. data/ext/couchbase/core/operations/management/search_index_get_stats.cxx +3 -1
  214. data/ext/couchbase/core/operations/management/search_index_upsert.cxx +2 -2
  215. data/ext/couchbase/core/operations/management/user_drop.cxx +3 -1
  216. data/ext/couchbase/core/operations/management/user_get.cxx +3 -1
  217. data/ext/couchbase/core/operations/management/user_upsert.cxx +12 -9
  218. data/ext/couchbase/core/operations/management/view_index_drop.cxx +1 -1
  219. data/ext/couchbase/core/operations/management/view_index_get.cxx +1 -1
  220. data/ext/couchbase/core/operations/management/view_index_upsert.cxx +1 -1
  221. data/ext/couchbase/core/operations/operation_traits.hxx +18 -0
  222. data/ext/couchbase/core/operations/query_response_parsing.cxx +211 -0
  223. data/ext/couchbase/core/operations/query_response_parsing.hxx +60 -0
  224. data/ext/couchbase/core/operations_fwd.hxx +3 -3
  225. data/ext/couchbase/core/origin.cxx +54 -26
  226. data/ext/couchbase/core/origin.hxx +12 -0
  227. data/ext/couchbase/core/orphan_reporter.cxx +2 -1
  228. data/ext/couchbase/core/platform/random.cc +7 -7
  229. data/ext/couchbase/core/protocol/client_request.cxx +2 -2
  230. data/ext/couchbase/core/protocol/client_request.hxx +38 -21
  231. data/ext/couchbase/core/protocol/client_response.cxx +11 -3
  232. data/ext/couchbase/core/protocol/client_response.hxx +27 -6
  233. data/ext/couchbase/core/protocol/cmd_append.cxx +2 -2
  234. data/ext/couchbase/core/protocol/cmd_cluster_map_change_notification.cxx +2 -2
  235. data/ext/couchbase/core/protocol/cmd_decrement.cxx +6 -6
  236. data/ext/couchbase/core/protocol/cmd_get.cxx +1 -1
  237. data/ext/couchbase/core/protocol/cmd_get_and_lock.cxx +2 -2
  238. data/ext/couchbase/core/protocol/cmd_get_and_touch.cxx +2 -2
  239. data/ext/couchbase/core/protocol/cmd_get_cluster_config.cxx +6 -4
  240. data/ext/couchbase/core/protocol/cmd_get_collection_id.cxx +2 -2
  241. data/ext/couchbase/core/protocol/cmd_get_error_map.cxx +1 -1
  242. data/ext/couchbase/core/protocol/cmd_get_meta.cxx +4 -4
  243. data/ext/couchbase/core/protocol/cmd_get_replica.cxx +1 -1
  244. data/ext/couchbase/core/protocol/cmd_hello.cxx +1 -1
  245. data/ext/couchbase/core/protocol/cmd_increment.cxx +6 -6
  246. data/ext/couchbase/core/protocol/cmd_insert.cxx +4 -4
  247. data/ext/couchbase/core/protocol/cmd_lookup_in.cxx +4 -3
  248. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +4 -3
  249. data/ext/couchbase/core/protocol/cmd_mutate_in.cxx +10 -9
  250. data/ext/couchbase/core/protocol/cmd_mutate_in.hxx +10 -10
  251. data/ext/couchbase/core/protocol/cmd_observe_seqno.cxx +7 -7
  252. data/ext/couchbase/core/protocol/cmd_prepend.cxx +2 -2
  253. data/ext/couchbase/core/protocol/cmd_remove.cxx +2 -2
  254. data/ext/couchbase/core/protocol/cmd_replace.cxx +4 -4
  255. data/ext/couchbase/core/protocol/cmd_touch.cxx +1 -1
  256. data/ext/couchbase/core/protocol/cmd_upsert.cxx +4 -4
  257. data/ext/couchbase/core/protocol/datatype.hxx +118 -1
  258. data/ext/couchbase/core/protocol/frame_info_utils.cxx +1 -1
  259. data/ext/couchbase/core/protocol/magic.hxx +4 -0
  260. data/ext/couchbase/core/protocol/magic_fmt.hxx +3 -0
  261. data/ext/couchbase/core/protocol/server_request.hxx +3 -1
  262. data/ext/couchbase/core/protocol/status.cxx +1 -1
  263. data/ext/couchbase/core/protostellar/analytics_converter.hxx +171 -0
  264. data/ext/couchbase/core/protostellar/bucket_admin_converter.hxx +301 -0
  265. data/ext/couchbase/core/protostellar/collection_admin_converter.hxx +92 -0
  266. data/ext/couchbase/core/protostellar/component.cxx +2445 -0
  267. data/ext/couchbase/core/protostellar/component.hxx +391 -0
  268. data/ext/couchbase/core/{columnar/bootstrap_notification_subscriber.hxx → protostellar/compression_settings.hxx} +11 -10
  269. data/ext/couchbase/core/protostellar/credentials.cxx +233 -0
  270. data/ext/couchbase/core/protostellar/credentials.hxx +88 -0
  271. data/ext/couchbase/core/protostellar/dispatcher.cxx +57 -0
  272. data/ext/couchbase/core/protostellar/dispatcher.hxx +482 -0
  273. data/ext/couchbase/core/protostellar/error_utils.cxx +293 -0
  274. data/ext/couchbase/core/protostellar/error_utils.hxx +97 -0
  275. data/ext/couchbase/core/protostellar/json_payload.hxx +49 -0
  276. data/ext/couchbase/core/protostellar/kv_converter.cxx +70 -0
  277. data/ext/couchbase/core/protostellar/kv_converter.hxx +600 -0
  278. data/ext/couchbase/core/protostellar/query_converter.hxx +265 -0
  279. data/ext/couchbase/core/protostellar/query_index_admin_converter.hxx +291 -0
  280. data/ext/couchbase/core/protostellar/query_proto.hxx +73 -0
  281. data/ext/couchbase/core/protostellar/search_converter.hxx +244 -0
  282. data/ext/couchbase/core/protostellar/search_index_admin_converter.hxx +156 -0
  283. data/ext/couchbase/core/protostellar/view_converter.hxx +158 -0
  284. data/ext/couchbase/core/query_stream.cxx +447 -0
  285. data/ext/couchbase/core/query_stream.hxx +141 -0
  286. data/ext/couchbase/core/query_stream_component.cxx +243 -0
  287. data/ext/couchbase/core/query_stream_component.hxx +68 -0
  288. data/ext/couchbase/core/range_scan_load_balancer.cxx +15 -8
  289. data/ext/couchbase/core/range_scan_orchestrator.cxx +15 -3
  290. data/ext/couchbase/core/response_handler.hxx +41 -4
  291. data/ext/couchbase/core/row_streamer.cxx +332 -46
  292. data/ext/couchbase/core/row_streamer.hxx +31 -1
  293. data/ext/couchbase/core/row_streamer_options.hxx +55 -0
  294. data/ext/couchbase/core/sasl/client.h +3 -0
  295. data/ext/couchbase/core/search_scoring.hxx +66 -0
  296. data/ext/couchbase/core/stream_error_details.hxx +69 -0
  297. data/ext/couchbase/core/timeout_defaults.hxx +0 -1
  298. data/ext/couchbase/core/topology/capabilities.hxx +6 -0
  299. data/ext/couchbase/core/topology/capabilities_fmt.hxx +3 -0
  300. data/ext/couchbase/core/topology/configuration.cxx +21 -6
  301. data/ext/couchbase/core/topology/configuration.hxx +29 -8
  302. data/ext/couchbase/core/topology/configuration_json.hxx +3 -0
  303. data/ext/couchbase/core/topology/error_map_json.hxx +3 -1
  304. data/ext/couchbase/core/tracing/threshold_logging_tracer.cxx +70 -4
  305. data/ext/couchbase/core/tracing/threshold_logging_tracer.hxx +10 -0
  306. data/ext/couchbase/core/transactions/active_transaction_record.cxx +0 -34
  307. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +108 -63
  308. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +19 -2
  309. data/ext/couchbase/core/transactions/error_list.hxx +2 -2
  310. data/ext/couchbase/core/transactions/get_multi_fetch.hxx +160 -0
  311. data/ext/couchbase/core/transactions/get_multi_orchestrator.cxx +326 -125
  312. data/ext/couchbase/core/transactions/get_multi_transaction_id.hxx +62 -0
  313. data/ext/couchbase/core/transactions/internal/atr_entry.hxx +22 -2
  314. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +2 -2
  315. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +23 -1
  316. data/ext/couchbase/core/transactions/internal/utils.hxx +50 -14
  317. data/ext/couchbase/core/transactions/staged_mutation.cxx +23 -18
  318. data/ext/couchbase/core/transactions/staged_mutation.hxx +15 -4
  319. data/ext/couchbase/core/transactions/transaction_context.cxx +55 -40
  320. data/ext/couchbase/core/transactions/transaction_get_result.hxx +16 -0
  321. data/ext/couchbase/core/transactions/transactions.cxx +3 -55
  322. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +165 -72
  323. data/ext/couchbase/core/transactions/transactions_config.cxx +0 -11
  324. data/ext/couchbase/core/transactions/utils.cxx +10 -0
  325. data/ext/couchbase/core/transactions/waitable_op_list.hxx +2 -2
  326. data/ext/couchbase/core/transactions.hxx +9 -9
  327. data/ext/couchbase/core/utils/byteswap.hxx +166 -9
  328. data/ext/couchbase/core/utils/connection_string.cxx +50 -85
  329. data/ext/couchbase/core/utils/connection_string.hxx +15 -0
  330. data/ext/couchbase/core/{columnar/backoff_calculator.hxx → utils/deadline.hxx} +13 -13
  331. data/ext/couchbase/core/utils/duration_parser.cxx +1 -1
  332. data/ext/couchbase/core/utils/json_streaming_lexer.cxx +48 -5
  333. data/ext/couchbase/core/utils/json_streaming_lexer.hxx +4 -1
  334. data/ext/couchbase/core/utils/movable_function.hxx +301 -52
  335. data/ext/couchbase/core/utils/name_codec.hxx +154 -11
  336. data/ext/couchbase/core/{columnar/retry_info.hxx → utils/process_id.hxx} +18 -13
  337. data/ext/couchbase/core/utils/url_codec.cxx +12 -51
  338. data/ext/couchbase/core/websocket_codec.cxx +3 -29
  339. data/ext/couchbase/couchbase/analytics_options.hxx +21 -10
  340. data/ext/couchbase/couchbase/analytics_row.hxx +105 -0
  341. data/ext/couchbase/couchbase/analytics_stream_result.hxx +266 -0
  342. data/ext/couchbase/couchbase/boolean_query.hxx +3 -3
  343. data/ext/couchbase/couchbase/bucket.hxx +57 -0
  344. data/ext/couchbase/couchbase/cluster.hxx +183 -5
  345. data/ext/couchbase/{core/columnar/security_options.hxx → couchbase/cluster_state.hxx} +18 -14
  346. data/ext/couchbase/couchbase/codec/lenient_json_transcoder.hxx +69 -0
  347. data/ext/couchbase/couchbase/collection.hxx +234 -14
  348. data/ext/couchbase/couchbase/common_durability_options.hxx +18 -3
  349. data/ext/couchbase/couchbase/conjunction_query.hxx +1 -1
  350. data/ext/couchbase/couchbase/create_dataset_analytics_options.hxx +6 -1
  351. data/ext/couchbase/couchbase/date_range_query.hxx +2 -2
  352. data/ext/couchbase/couchbase/decrement_options.hxx +1 -1
  353. data/ext/couchbase/couchbase/disjunction_query.hxx +1 -1
  354. data/ext/couchbase/couchbase/error.hxx +32 -0
  355. data/ext/couchbase/couchbase/error_codes.hxx +32 -0
  356. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +1 -1
  357. data/ext/couchbase/couchbase/geo_distance_query.hxx +1 -1
  358. data/ext/couchbase/couchbase/geo_polygon_query.hxx +1 -1
  359. data/ext/couchbase/couchbase/get_replica_options.hxx +68 -0
  360. data/ext/couchbase/couchbase/get_replica_result.hxx +5 -3
  361. data/ext/couchbase/couchbase/get_replica_strategy.hxx +161 -0
  362. data/ext/couchbase/couchbase/get_result.hxx +1 -0
  363. data/ext/couchbase/couchbase/increment_options.hxx +1 -1
  364. data/ext/couchbase/couchbase/insert_options.hxx +1 -1
  365. data/ext/couchbase/couchbase/match_phrase_query.hxx +1 -1
  366. data/ext/couchbase/couchbase/match_query.hxx +1 -1
  367. data/ext/couchbase/couchbase/mutate_in_options.hxx +3 -3
  368. data/ext/couchbase/couchbase/network_options.hxx +1 -1
  369. data/ext/couchbase/couchbase/node_id.hxx +42 -14
  370. data/ext/couchbase/couchbase/node_id_for_options.hxx +7 -1
  371. data/ext/couchbase/couchbase/node_ids_options.hxx +8 -2
  372. data/ext/couchbase/couchbase/numeric_range_query.hxx +1 -1
  373. data/ext/couchbase/couchbase/phrase_query.hxx +1 -1
  374. data/ext/couchbase/couchbase/prefix_query.hxx +1 -1
  375. data/ext/couchbase/couchbase/query_options.hxx +23 -12
  376. data/ext/couchbase/couchbase/query_row.hxx +111 -0
  377. data/ext/couchbase/couchbase/query_stream_result.hxx +302 -0
  378. data/ext/couchbase/couchbase/query_string_query.hxx +3 -3
  379. data/ext/couchbase/couchbase/regexp_query.hxx +1 -1
  380. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  381. data/ext/couchbase/couchbase/result.hxx +14 -3
  382. data/ext/couchbase/couchbase/scan_result_item.hxx +1 -0
  383. data/ext/couchbase/couchbase/scope.hxx +85 -2
  384. data/ext/couchbase/couchbase/search_options.hxx +58 -8
  385. data/ext/couchbase/couchbase/search_scoring.hxx +94 -0
  386. data/ext/couchbase/couchbase/search_scoring_none.hxx +51 -0
  387. data/ext/couchbase/couchbase/search_scoring_reciprocal_rank_fusion.hxx +88 -0
  388. data/ext/couchbase/couchbase/search_scoring_relative_score_fusion.hxx +70 -0
  389. data/ext/couchbase/couchbase/term_range_query.hxx +1 -1
  390. data/ext/couchbase/couchbase/tracing/request_span.hxx +46 -0
  391. data/ext/couchbase/couchbase/transactions/transaction_get_multi_replicas_from_preferred_server_group_result.hxx +23 -21
  392. data/ext/couchbase/couchbase/transactions/transaction_get_multi_result.hxx +24 -19
  393. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +17 -3
  394. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +4 -2
  395. data/ext/couchbase/couchbase/transactions.hxx +27 -18
  396. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  397. data/ext/couchbase/couchbase/vector_query.hxx +1 -1
  398. data/ext/couchbase/couchbase/wait_until_ready_options.hxx +111 -0
  399. data/ext/couchbase/couchbase/wildcard_query.hxx +1 -1
  400. data/ext/extconf.rb +15 -10
  401. data/ext/rcb_analytics.cxx +82 -102
  402. data/ext/rcb_backend.cxx +42 -36
  403. data/ext/rcb_backend.hxx +2 -0
  404. data/ext/rcb_buckets.cxx +47 -59
  405. data/ext/rcb_collections.cxx +42 -52
  406. data/ext/rcb_crud.cxx +345 -224
  407. data/ext/rcb_diagnostics.cxx +117 -27
  408. data/ext/rcb_exceptions.cxx +152 -99
  409. data/ext/rcb_exceptions.hxx +25 -0
  410. data/ext/rcb_extras.cxx +18 -19
  411. data/ext/rcb_hdr_histogram.cxx +19 -4
  412. data/ext/rcb_logger.cxx +202 -27
  413. data/ext/rcb_logger.hxx +12 -0
  414. data/ext/rcb_multi.cxx +40 -40
  415. data/ext/rcb_observability.cxx +7 -5
  416. data/ext/rcb_query.cxx +99 -142
  417. data/ext/rcb_range_scan.cxx +41 -35
  418. data/ext/rcb_search.cxx +98 -99
  419. data/ext/rcb_users.cxx +36 -56
  420. data/ext/rcb_utils.cxx +100 -37
  421. data/ext/rcb_utils.hxx +287 -33
  422. data/ext/rcb_version.cxx +1 -1
  423. data/ext/rcb_views.cxx +55 -51
  424. data/lib/active_support/cache/couchbase_store.rb +77 -12
  425. data/lib/couchbase/bucket.rb +20 -0
  426. data/lib/couchbase/cluster.rb +17 -0
  427. data/lib/couchbase/collection.rb +36 -1
  428. data/lib/couchbase/errors.rb +18 -0
  429. data/lib/couchbase/fork_hooks.rb +16 -7
  430. data/lib/couchbase/get_replica_strategy.rb +89 -0
  431. data/lib/couchbase/logger.rb +1 -1
  432. data/lib/couchbase/management/analytics_index_manager.rb +15 -15
  433. data/lib/couchbase/management/bucket_manager.rb +6 -6
  434. data/lib/couchbase/management/collection_manager.rb +6 -6
  435. data/lib/couchbase/management/query_index_manager.rb +7 -7
  436. data/lib/couchbase/management/search_index_manager.rb +13 -13
  437. data/lib/couchbase/management/user_manager.rb +10 -10
  438. data/lib/couchbase/management/view_index_manager.rb +5 -5
  439. data/lib/couchbase/options.rb +174 -42
  440. data/lib/couchbase/protostellar/bucket.rb +4 -0
  441. data/lib/couchbase/protostellar/cluster.rb +4 -0
  442. data/lib/couchbase/protostellar/collection.rb +4 -0
  443. data/lib/couchbase/protostellar/error_handling.rb +2 -1
  444. data/lib/couchbase/protostellar/request.rb +1 -0
  445. data/lib/couchbase/protostellar/request_generator/kv.rb +16 -2
  446. data/lib/couchbase/protostellar/request_generator/search.rb +17 -1
  447. data/lib/couchbase/protostellar/retry/orchestrator.rb +3 -2
  448. data/lib/couchbase/protostellar/retry/strategies/fail_fast.rb +33 -0
  449. data/lib/couchbase/protostellar/retry/strategies.rb +1 -0
  450. data/lib/couchbase/search_options.rb +95 -6
  451. data/lib/couchbase/version.rb +1 -1
  452. metadata +91 -33
  453. data/ext/0001-fix-build-for-mingw-w64-ucrt-x86_64-toolchain.patch +0 -40
  454. data/ext/couchbase/core/columnar/agent.hxx +0 -71
  455. data/ext/couchbase/core/columnar/agent_config.hxx +0 -59
  456. data/ext/couchbase/core/columnar/background_bootstrap_listener.hxx +0 -42
  457. data/ext/couchbase/core/columnar/backoff_calculator.cxx +0 -62
  458. data/ext/couchbase/core/columnar/columnar_agent.cxx +0 -147
  459. data/ext/couchbase/core/columnar/columnar_agent_config.cxx +0 -48
  460. data/ext/couchbase/core/columnar/columnar_error.cxx +0 -51
  461. data/ext/couchbase/core/columnar/database_management_options.hxx +0 -56
  462. data/ext/couchbase/core/columnar/error.hxx +0 -51
  463. data/ext/couchbase/core/columnar/error_codes.cxx +0 -107
  464. data/ext/couchbase/core/columnar/error_codes.hxx +0 -75
  465. data/ext/couchbase/core/columnar/management_component.cxx +0 -300
  466. data/ext/couchbase/core/columnar/management_component.hxx +0 -56
  467. data/ext/couchbase/core/columnar/query_component.cxx +0 -523
  468. data/ext/couchbase/core/columnar/query_component.hxx +0 -57
  469. data/ext/couchbase/core/columnar/query_options.hxx +0 -59
  470. data/ext/couchbase/core/columnar/query_result.cxx +0 -130
  471. data/ext/couchbase/core/columnar/query_result.hxx +0 -78
  472. data/ext/couchbase/core/io/config_tracker.cxx +0 -687
  473. data/ext/couchbase/core/io/config_tracker.hxx +0 -123
@@ -45,7 +45,11 @@ scope_drop_request::make_response(error_context::http&& ctx,
45
45
  if (!response.ctx.ec) {
46
46
  switch (const auto& body = encoded.body.data(); encoded.status_code) {
47
47
  case 400:
48
- response.ctx.ec = errc::common::unsupported_operation;
48
+ if (body.find("Not allowed on this version of cluster") != std::string_view::npos) {
49
+ response.ctx.ec = errc::common::unsupported_operation;
50
+ } else {
51
+ response.ctx.ec = errc::common::invalid_argument;
52
+ }
49
53
  break;
50
54
  case 404: {
51
55
  const auto prefix_pos = body.find("Scope with name ");
@@ -46,7 +46,12 @@ scope_get_all_request::make_response(error_context::http&& ctx,
46
46
  if (!response.ctx.ec) {
47
47
  switch (encoded.status_code) {
48
48
  case 400:
49
- response.ctx.ec = errc::common::unsupported_operation;
49
+ if (encoded.body.data().find("Not allowed on this version of cluster") !=
50
+ std::string::npos) {
51
+ response.ctx.ec = errc::common::unsupported_operation;
52
+ } else {
53
+ response.ctx.ec = errc::common::invalid_argument;
54
+ }
50
55
  break;
51
56
  case 404:
52
57
  response.ctx.ec = errc::common::bucket_not_found;
@@ -16,6 +16,7 @@
16
16
  */
17
17
 
18
18
  #include "search_get_stats.hxx"
19
+ #include "error_utils.hxx"
19
20
 
20
21
  #include <couchbase/error_codes.hxx>
21
22
 
@@ -37,6 +38,15 @@ search_get_stats_request::make_response(error_context::http&& ctx,
37
38
  {
38
39
  search_get_stats_response response{ std::move(ctx) };
39
40
  if (!response.ctx.ec) {
41
+ if (encoded.status_code == 401 || encoded.status_code == 403) {
42
+ // RFC-58: Search reports a 401 or 403 as an authentication failure.
43
+ response.ctx.ec = errc::common::authentication_failure;
44
+ return response;
45
+ }
46
+ if (encoded.status_code != 200) {
47
+ response.ctx.ec = extract_common_error_code(encoded.status_code, encoded.body.data());
48
+ return response;
49
+ }
40
50
  response.stats = encoded.body.data();
41
51
  }
42
52
  return response;
@@ -41,9 +41,10 @@ search_index_analyze_document_request::encode_to(encoded_request_type& encoded,
41
41
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/analyzeDoc",
42
42
  utils::string_codec::v2::path_escape(bucket_name.value()),
43
43
  utils::string_codec::v2::path_escape(scope_name.value()),
44
- index_name);
44
+ utils::string_codec::v2::path_escape(index_name));
45
45
  } else {
46
- encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
46
+ encoded.path =
47
+ fmt::format("/api/index/{}/analyzeDoc", utils::string_codec::v2::path_escape(index_name));
47
48
  }
48
49
  encoded.body = encoded_document;
49
50
  return {};
@@ -38,11 +38,12 @@ search_index_control_ingest_request::encode_to(encoded_request_type& encoded,
38
38
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/ingestControl/{}",
39
39
  utils::string_codec::v2::path_escape(bucket_name.value()),
40
40
  utils::string_codec::v2::path_escape(scope_name.value()),
41
- index_name,
41
+ utils::string_codec::v2::path_escape(index_name),
42
42
  pause ? "pause" : "resume");
43
43
  } else {
44
- encoded.path =
45
- fmt::format("/api/index/{}/ingestControl/{}", index_name, pause ? "pause" : "resume");
44
+ encoded.path = fmt::format("/api/index/{}/ingestControl/{}",
45
+ utils::string_codec::v2::path_escape(index_name),
46
+ pause ? "pause" : "resume");
46
47
  }
47
48
  return {};
48
49
  }
@@ -39,11 +39,12 @@ search_index_control_plan_freeze_request::encode_to(encoded_request_type& encode
39
39
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/planFreezeControl/{}",
40
40
  utils::string_codec::v2::path_escape(bucket_name.value()),
41
41
  utils::string_codec::v2::path_escape(scope_name.value()),
42
- index_name,
42
+ utils::string_codec::v2::path_escape(index_name),
43
43
  freeze ? "freeze" : "unfreeze");
44
44
  } else {
45
- encoded.path =
46
- fmt::format("/api/index/{}/planFreezeControl/{}", index_name, freeze ? "freeze" : "unfreeze");
45
+ encoded.path = fmt::format("/api/index/{}/planFreezeControl/{}",
46
+ utils::string_codec::v2::path_escape(index_name),
47
+ freeze ? "freeze" : "unfreeze");
47
48
  }
48
49
  return {};
49
50
  }
@@ -38,11 +38,12 @@ search_index_control_query_request::encode_to(encoded_request_type& encoded,
38
38
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/queryControl/{}",
39
39
  utils::string_codec::v2::path_escape(bucket_name.value()),
40
40
  utils::string_codec::v2::path_escape(scope_name.value()),
41
- index_name,
41
+ utils::string_codec::v2::path_escape(index_name),
42
42
  allow ? "allow" : "disallow");
43
43
  } else {
44
- encoded.path =
45
- fmt::format("/api/index/{}/queryControl/{}", index_name, allow ? "allow" : "disallow");
44
+ encoded.path = fmt::format("/api/index/{}/queryControl/{}",
45
+ utils::string_codec::v2::path_escape(index_name),
46
+ allow ? "allow" : "disallow");
46
47
  }
47
48
  return {};
48
49
  }
@@ -38,9 +38,9 @@ search_index_drop_request::encode_to(encoded_request_type& encoded,
38
38
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
39
39
  utils::string_codec::v2::path_escape(bucket_name.value()),
40
40
  utils::string_codec::v2::path_escape(scope_name.value()),
41
- index_name);
41
+ utils::string_codec::v2::path_escape(index_name));
42
42
  } else {
43
- encoded.path = fmt::format("/api/index/{}", index_name);
43
+ encoded.path = fmt::format("/api/index/{}", utils::string_codec::v2::path_escape(index_name));
44
44
  }
45
45
  return {};
46
46
  }
@@ -39,9 +39,9 @@ search_index_get_request::encode_to(encoded_request_type& encoded,
39
39
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
40
40
  utils::string_codec::v2::path_escape(bucket_name.value()),
41
41
  utils::string_codec::v2::path_escape(scope_name.value()),
42
- index_name);
42
+ utils::string_codec::v2::path_escape(index_name));
43
43
  } else {
44
- encoded.path = fmt::format("/api/index/{}", index_name);
44
+ encoded.path = fmt::format("/api/index/{}", utils::string_codec::v2::path_escape(index_name));
45
45
  }
46
46
  return {};
47
47
  }
@@ -36,9 +36,10 @@ search_index_get_documents_count_request::encode_to(encoded_request_type& encode
36
36
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/count",
37
37
  utils::string_codec::v2::path_escape(bucket_name.value()),
38
38
  utils::string_codec::v2::path_escape(scope_name.value()),
39
- index_name);
39
+ utils::string_codec::v2::path_escape(index_name));
40
40
  } else {
41
- encoded.path = fmt::format("/api/index/{}/count", index_name);
41
+ encoded.path =
42
+ fmt::format("/api/index/{}/count", utils::string_codec::v2::path_escape(index_name));
42
43
  }
43
44
  return {};
44
45
  }
@@ -18,6 +18,7 @@
18
18
  #include "search_index_get_stats.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <spdlog/fmt/bundled/core.h>
@@ -33,7 +34,8 @@ search_index_get_stats_request::encode_to(encoded_request_type& encoded,
33
34
  return errc::common::invalid_argument;
34
35
  }
35
36
  encoded.method = "GET";
36
- encoded.path = fmt::format("/api/stats/index/{}", index_name);
37
+ encoded.path =
38
+ fmt::format("/api/stats/index/{}", utils::string_codec::v2::path_escape(index_name));
37
39
  return {};
38
40
  }
39
41
 
@@ -41,9 +41,9 @@ search_index_upsert_request::encode_to(encoded_request_type& encoded,
41
41
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
42
42
  utils::string_codec::v2::path_escape(bucket_name.value()),
43
43
  utils::string_codec::v2::path_escape(scope_name.value()),
44
- index.name);
44
+ utils::string_codec::v2::path_escape(index.name));
45
45
  } else {
46
- encoded.path = fmt::format("/api/index/{}", index.name);
46
+ encoded.path = fmt::format("/api/index/{}", utils::string_codec::v2::path_escape(index.name));
47
47
  }
48
48
  tao::json::value body{
49
49
  { "name", index.name },
@@ -18,6 +18,7 @@
18
18
  #include "user_drop.hxx"
19
19
 
20
20
  #include "core/management/rbac_fmt.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  namespace couchbase::core::operations::management
@@ -27,7 +28,8 @@ user_drop_request::encode_to(encoded_request_type& encoded,
27
28
  http_context& /* context */) const -> std::error_code
28
29
  {
29
30
  encoded.method = "DELETE";
30
- encoded.path = fmt::format("/settings/rbac/users/{}/{}", domain, username);
31
+ encoded.path = fmt::format(
32
+ "/settings/rbac/users/{}/{}", domain, utils::string_codec::v2::path_escape(username));
31
33
  return {};
32
34
  }
33
35
 
@@ -20,6 +20,7 @@
20
20
  #include "core/management/rbac_fmt.hxx"
21
21
  #include "core/management/rbac_json.hxx"
22
22
  #include "core/utils/json.hxx"
23
+ #include "core/utils/url_codec.hxx"
23
24
  #include "error_utils.hxx"
24
25
 
25
26
  #include <tao/json/value.hpp>
@@ -31,7 +32,8 @@ user_get_request::encode_to(encoded_request_type& encoded,
31
32
  http_context& /* context */) const -> std::error_code
32
33
  {
33
34
  encoded.method = "GET";
34
- encoded.path = fmt::format("/settings/rbac/users/{}/{}", domain, username);
35
+ encoded.path = fmt::format(
36
+ "/settings/rbac/users/{}/{}", domain, utils::string_codec::v2::path_escape(username));
35
37
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
36
38
  return {};
37
39
  }
@@ -32,39 +32,42 @@ user_upsert_request::encode_to(encoded_request_type& encoded,
32
32
  http_context& /* context */) const -> std::error_code
33
33
  {
34
34
  encoded.method = "PUT";
35
- encoded.path = fmt::format("/settings/rbac/users/{}/{}", domain, user.username);
35
+ encoded.path = fmt::format(
36
+ "/settings/rbac/users/{}/{}", domain, utils::string_codec::v2::path_escape(user.username));
36
37
  std::vector<std::string> params{};
37
38
  if (user.display_name) {
38
39
  params.push_back(
39
- fmt::format("name={}", utils::string_codec::url_encode(user.display_name.value())));
40
+ fmt::format("name={}", utils::string_codec::form_encode(user.display_name.value())));
40
41
  }
41
42
  if (user.password) {
42
43
  params.push_back(
43
- fmt::format("password={}", utils::string_codec::url_encode(user.password.value())));
44
+ fmt::format("password={}", utils::string_codec::form_encode(user.password.value())));
44
45
  }
45
46
  if (!user.groups.empty()) {
46
47
  const std::string encoded_groups = utils::join_strings(user.groups, ",");
47
- params.push_back(fmt::format("groups={}", utils::string_codec::url_encode(encoded_groups)));
48
+ params.push_back(fmt::format("groups={}", utils::string_codec::form_encode(encoded_groups)));
48
49
  }
50
+ // Names go into the spec unescaped: the server does not percent-decode role parameters after
51
+ // form-decoding the body, so the spec is form-encoded exactly once, as a whole.
49
52
  std::vector<std::string> encoded_roles{};
50
53
  encoded_roles.reserve(user.roles.size());
51
54
  for (const auto& role : user.roles) {
52
55
  std::string spec = role.name;
53
56
  if (role.bucket) {
54
- spec += fmt::format("[{}", utils::string_codec::v2::path_escape(role.bucket.value()));
57
+ spec += fmt::format("[{}", role.bucket.value());
55
58
  if (role.scope) {
56
- spec += fmt::format(":{}", utils::string_codec::v2::path_escape(role.scope.value()));
59
+ spec += fmt::format(":{}", role.scope.value());
57
60
  if (role.collection) {
58
- spec += fmt::format(":{}", utils::string_codec::v2::path_escape(role.collection.value()));
61
+ spec += fmt::format(":{}", role.collection.value());
59
62
  }
60
63
  }
61
- spec += "]";
64
+ spec += ']';
62
65
  }
63
66
  encoded_roles.push_back(spec);
64
67
  }
65
68
  if (!encoded_roles.empty()) {
66
69
  const std::string concatenated = utils::join_strings(encoded_roles, ",");
67
- params.push_back(fmt::format("roles={}", utils::string_codec::url_encode(concatenated)));
70
+ params.push_back(fmt::format("roles={}", utils::string_codec::form_encode(concatenated)));
68
71
  }
69
72
  encoded.body = utils::join_strings(params, "&");
70
73
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
@@ -33,7 +33,7 @@ view_index_drop_request::encode_to(encoded_request_type& encoded,
33
33
  encoded.path = fmt::format("/{}/_design/{}{}",
34
34
  utils::string_codec::v2::path_escape(bucket_name),
35
35
  ns == design_document_namespace::development ? "dev_" : "",
36
- document_name);
36
+ utils::string_codec::v2::path_escape(document_name));
37
37
  return {};
38
38
  }
39
39
 
@@ -34,7 +34,7 @@ view_index_get_request::encode_to(encoded_request_type& encoded,
34
34
  encoded.path = fmt::format("/{}/_design/{}{}",
35
35
  utils::string_codec::v2::path_escape(bucket_name),
36
36
  ns == design_document_namespace::development ? "dev_" : "",
37
- document_name);
37
+ utils::string_codec::v2::path_escape(document_name));
38
38
  return {};
39
39
  }
40
40
 
@@ -48,7 +48,7 @@ view_index_upsert_request::encode_to(encoded_request_type& encoded,
48
48
  encoded.path = fmt::format("/{}/_design/{}{}",
49
49
  utils::string_codec::v2::path_escape(bucket_name),
50
50
  document.ns == design_document_namespace::development ? "dev_" : "",
51
- document.name);
51
+ utils::string_codec::v2::path_escape(document.name));
52
52
  encoded.body = utils::json::generate(body);
53
53
  return {};
54
54
  }
@@ -34,4 +34,22 @@ struct is_cancellable_operation : public std::false_type {
34
34
 
35
35
  template<typename T>
36
36
  inline constexpr bool is_cancellable_operation_v = is_cancellable_operation<T>::value;
37
+
38
+ /**
39
+ * Operations that pick the node to dispatch to themselves, instead of being
40
+ * routed by the vbucket map alone.
41
+ *
42
+ * Specialize this only for a request that provides
43
+ * @c resolve_route(const topology::configuration&) returning an
44
+ * @c std::optional<impl::replica_route_decision>, and a writable @c partition
45
+ * member: that is the whole interface @c bucket::map_and_send() calls through
46
+ * this trait. An empty optional declines self-routing for that request, and the
47
+ * vbucket-map path routes it instead.
48
+ */
49
+ template<typename T>
50
+ struct resolves_own_route : public std::false_type {
51
+ };
52
+
53
+ template<typename T>
54
+ inline constexpr bool resolves_own_route_v = resolves_own_route<T>::value;
37
55
  } // namespace couchbase::core::operations
@@ -0,0 +1,211 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 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
+ #include "query_response_parsing.hxx"
19
+
20
+ #include "core/operations/management/error_utils.hxx"
21
+ #include "core/utils/contains_string.hxx"
22
+ #include "core/utils/duration_parser.hxx"
23
+ #include "core/utils/json.hxx"
24
+
25
+ #include <couchbase/error_codes.hxx>
26
+
27
+ #include <tao/json/value.hpp>
28
+
29
+ namespace couchbase::core::operations
30
+ {
31
+
32
+ auto
33
+ parse_query_meta(const tao::json::value& payload) -> query_response::query_meta_data
34
+ {
35
+ query_response::query_meta_data meta{};
36
+
37
+ if (const auto* i = payload.find("requestID"); i != nullptr) {
38
+ meta.request_id = i->get_string();
39
+ }
40
+ if (const auto* i = payload.find("clientContextID"); i != nullptr) {
41
+ meta.client_context_id = i->get_string();
42
+ }
43
+ if (const auto* s = payload.find("status"); s != nullptr) {
44
+ meta.status = s->get_string();
45
+ }
46
+ if (const auto* s = payload.find("signature"); s != nullptr) {
47
+ meta.signature = couchbase::core::utils::json::generate(*s);
48
+ }
49
+ if (const auto* p = payload.find("profile"); p != nullptr) {
50
+ meta.profile = couchbase::core::utils::json::generate(*p);
51
+ }
52
+
53
+ if (const auto* m = payload.find("metrics"); m != nullptr) {
54
+ query_response::query_metrics metrics{};
55
+ metrics.result_count = m->at("resultCount").get_unsigned();
56
+ metrics.result_size = m->at("resultSize").get_unsigned();
57
+ metrics.elapsed_time = utils::parse_duration(m->at("elapsedTime").get_string());
58
+ metrics.execution_time = utils::parse_duration(m->at("executionTime").get_string());
59
+ metrics.sort_count = m->template optional<std::uint64_t>("sortCount").value_or(0);
60
+ metrics.mutation_count = m->template optional<std::uint64_t>("mutationCount").value_or(0);
61
+ metrics.error_count = m->template optional<std::uint64_t>("errorCount").value_or(0);
62
+ metrics.warning_count = m->template optional<std::uint64_t>("warningCount").value_or(0);
63
+ meta.metrics.emplace(metrics);
64
+ }
65
+
66
+ if (const auto* e = payload.find("errors"); e != nullptr) {
67
+ std::vector<query_response::query_problem> problems{};
68
+ for (const auto& err : e->get_array()) {
69
+ query_response::query_problem problem;
70
+ problem.code = err.at("code").get_unsigned();
71
+ problem.message = err.at("msg").get_string();
72
+ if (const auto* reason = err.find("reason"); reason != nullptr && reason->is_object()) {
73
+ problem.reason = reason->optional<std::uint64_t>("code");
74
+ problem.retry = reason->optional<bool>("retry");
75
+ }
76
+ problems.emplace_back(problem);
77
+ }
78
+ meta.errors.emplace(problems);
79
+ }
80
+
81
+ if (const auto* w = payload.find("warnings"); w != nullptr) {
82
+ std::vector<query_response::query_problem> problems{};
83
+ for (const auto& warn : w->get_array()) {
84
+ query_response::query_problem problem;
85
+ problem.code = warn.at("code").get_unsigned();
86
+ problem.message = warn.at("msg").get_string();
87
+ problems.emplace_back(problem);
88
+ }
89
+ meta.warnings.emplace(problems);
90
+ }
91
+
92
+ return meta;
93
+ }
94
+
95
+ auto
96
+ map_query_error(const query_response::query_meta_data& meta, std::uint32_t http_status)
97
+ -> std::error_code
98
+ {
99
+ const auto unmatched =
100
+ http_status == 400 ? errc::common::invalid_argument : errc::common::internal_server_failure;
101
+
102
+ if (meta.status == "success" && http_status != 400) {
103
+ return {};
104
+ }
105
+
106
+ if (!meta.errors || meta.errors->empty()) {
107
+ /* Unreachable from make_response, which only calls map_query_error after confirming
108
+ * errors is non-empty; present for the streaming-path caller, which has no such guard. */
109
+ return unmatched;
110
+ }
111
+
112
+ const auto& first = meta.errors->front();
113
+ const auto first_code = first.code;
114
+ const auto& first_message = first.message;
115
+
116
+ std::error_code ec{};
117
+
118
+ switch (first_code) {
119
+ case 1065: /* IKey: "service.io.request.unrecognized_parameter" */
120
+ if ((first_message.find("Unrecognized parameter in request") != std::string::npos) &&
121
+ (first_message.find("preserve_expiry") != std::string::npos)) {
122
+ ec = errc::common::feature_not_available;
123
+ } else {
124
+ ec = errc::common::invalid_argument;
125
+ }
126
+ break;
127
+ case 1080: /* IKey: "timeout" */
128
+ ec = errc::common::unambiguous_timeout;
129
+ break;
130
+ case 3000: /* IKey: "parse.syntax_error" */
131
+ ec = errc::common::parsing_failure;
132
+ break;
133
+ case 4040: /* IKey: "plan.build_prepared.no_such_name" */
134
+ case 4050: /* IKey: "plan.build_prepared.unrecognized_prepared" */
135
+ case 4060: /* IKey: "plan.build_prepared.no_such_name" */
136
+ case 4070: /* IKey: "plan.build_prepared.decoding" */
137
+ case 4080: /* IKey: "plan.build_prepared.name_encoded_plan_mismatch" */
138
+ case 4090: /* IKey: "plan.build_prepared.name_not_in_encoded_plan" */
139
+ /* NOTE: make_response also does cache.erase + throw retry_http_request for codes
140
+ * 4040/4050/4070. That stateful logic stays in make_response. This pure classifier
141
+ * returns prepared_statement_failure so callers (e.g. streaming path) get a
142
+ * non-empty error_code. */
143
+ ec = errc::query::prepared_statement_failure;
144
+ break;
145
+ case 4300: /* IKey: "plan.new_index_already_exists" */
146
+ ec = errc::common::index_exists;
147
+ break;
148
+ case 5000: /* IKey: "Internal Error" */
149
+ if (utils::contains_string(first_message, "index", true) &&
150
+ utils::contains_string(first_message, "already exist", true)) {
151
+ ec = errc::common::index_exists;
152
+ } else if (utils::contains_string(first_message, "Index does not exist") ||
153
+ (utils::contains_string(first_message, "index", true) &&
154
+ utils::contains_string(first_message, "not found", true))) {
155
+ ec = errc::common::index_not_found;
156
+ } else if (first_message.find("Bucket Not Found") != std::string::npos) {
157
+ ec = errc::common::bucket_not_found;
158
+ }
159
+ break;
160
+ case 12009: /* IKey: "datastore.couchbase.DML_error" */
161
+ if (first_message.find("CAS mismatch") != std::string::npos) {
162
+ ec = errc::common::cas_mismatch;
163
+ } else {
164
+ switch (first.reason.value_or(0)) {
165
+ case 12033:
166
+ ec = errc::common::cas_mismatch;
167
+ break;
168
+ case 17014:
169
+ ec = errc::key_value::document_not_found;
170
+ break;
171
+ case 17012:
172
+ ec = errc::key_value::document_exists;
173
+ break;
174
+ default:
175
+ ec = errc::query::dml_failure;
176
+ break;
177
+ }
178
+ }
179
+ break;
180
+ case 12004: /* IKey: "datastore.couchbase.primary_idx_not_found" */
181
+ case 12016: /* IKey: "datastore.couchbase.index_not_found" */
182
+ ec = errc::common::index_not_found;
183
+ break;
184
+ case 13014: /* IKey: "datastore.couchbase.insufficient_credentials" */
185
+ ec = errc::common::authentication_failure;
186
+ break;
187
+ default:
188
+ if ((first_code >= 12000 && first_code < 13000) ||
189
+ (first_code >= 14000 && first_code < 15000)) {
190
+ ec = errc::query::index_failure;
191
+ } else if (first_code >= 4000 && first_code < 5000) {
192
+ ec = errc::query::planning_failure;
193
+ }
194
+ break;
195
+ }
196
+
197
+ if (!ec) {
198
+ auto common_ec = management::extract_common_query_error_code(first_code, first_message);
199
+ if (common_ec) {
200
+ ec = common_ec.value();
201
+ }
202
+ }
203
+
204
+ if (!ec) {
205
+ ec = unmatched;
206
+ }
207
+
208
+ return ec;
209
+ }
210
+
211
+ } // namespace couchbase::core::operations
@@ -0,0 +1,60 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2020-2021 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
+ #include "core/operations/document_query.hxx"
21
+
22
+ #include <couchbase/error_codes.hxx>
23
+
24
+ #include <tao/json/forward.hpp>
25
+
26
+ #include <cstdint>
27
+ #include <system_error>
28
+
29
+ namespace couchbase::core::operations
30
+ {
31
+
32
+ /**
33
+ * Parse query meta-data fields (status, metrics, warnings, errors, signature, profile,
34
+ * requestID, clientContextID) from a top-level response payload.
35
+ *
36
+ * Pure function — no side effects, no access to request state.
37
+ */
38
+ auto
39
+ parse_query_meta(const tao::json::value& payload) -> query_response::query_meta_data;
40
+
41
+ /**
42
+ * Map query meta-data to an error_code.
43
+ *
44
+ * Pure classifier — no side effects, no cache mutations, no exceptions thrown.
45
+ * All prepared-statement codes (4040/4050/4060/4070/4080/4090) are classified as
46
+ * prepared_statement_failure here; the cache-erase + retry_http_request throw remains in
47
+ * make_response and applies only to the 4040/4050/4070 subset.
48
+ *
49
+ * Returns an empty error_code when the query succeeded (meta.status == "success", http_status is
50
+ * not 400, and no prepared-statement retry needed).
51
+ *
52
+ * http_status is the status of the response that carried the metadata, or 0 where there is none.
53
+ * A failure that matches no specific mapping is invalid_argument for an HTTP 400 (RFC-58) and
54
+ * internal_server_failure otherwise.
55
+ */
56
+ [[nodiscard]] auto
57
+ map_query_error(const query_response::query_meta_data& meta, std::uint32_t http_status = 0)
58
+ -> std::error_code;
59
+
60
+ } // namespace couchbase::core::operations
@@ -28,8 +28,6 @@ struct s3_external_link;
28
28
 
29
29
  namespace impl
30
30
  {
31
- struct get_replica_request;
32
- struct get_replica_response;
33
31
  struct lookup_in_replica_request;
34
32
  struct lookup_in_replica_response;
35
33
  struct observe_seqno_request;
@@ -51,6 +49,8 @@ struct decrement_response;
51
49
  struct exists_request;
52
50
  struct exists_response;
53
51
  struct get_request;
52
+ struct get_replica_request;
53
+ struct get_replica_response;
54
54
  struct get_response;
55
55
  struct get_all_replicas_request;
56
56
  struct get_all_replicas_response;
@@ -106,7 +106,7 @@ using replace_request_with_legacy_durability = impl::with_legacy_durability<repl
106
106
  using upsert_request_with_legacy_durability = impl::with_legacy_durability<upsert_request>;
107
107
 
108
108
  using get_request_with_cancellation = impl::with_cancellation<get_request>;
109
- using get_replica_request_with_cancellation = impl::with_cancellation<impl::get_replica_request>;
109
+ using get_replica_request_with_cancellation = impl::with_cancellation<get_replica_request>;
110
110
  using lookup_in_request_with_cancellation = impl::with_cancellation<lookup_in_request>;
111
111
  using lookup_in_replica_request_with_cancellation =
112
112
  impl::with_cancellation<impl::lookup_in_replica_request>;