1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* 3 * Copyright 2016 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 #ifndef LCB_SUBDOC_H 18 #define LCB_SUBDOC_H 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /**@ingroup lcb-public-api 25 * @defgroup lcb-subdoc Sub-Document API 26 * @brief Experimental in-document API access 27 * @details The sub-document API uses features from the upcoming Couchbase 28 * 4.5 release which allows access to parts of the document. These parts are 29 * called _sub-documents_ and can be accessed using the sub-document API 30 * 31 * @addtogroup lcb-subdoc 32 * @{ 33 */ 34 35 /** 36 * @brief Sub-Document command codes 37 * 38 * These command codes should be applied as values to lcb_SDSPEC::sdcmd and 39 * indicate which type of subdoc command the server should perform. 40 */ 41 typedef enum { 42 /** 43 * Retrieve the value for a path 44 */ 45 LCB_SDCMD_GET = 1, 46 47 /** 48 * Check if the value for a path exists. If the path exists then the error 49 * code will be @ref LCB_SUCCESS 50 */ 51 LCB_SDCMD_EXISTS, 52 53 /** 54 * Replace the value at the specified path. This operation can work 55 * on any existing and valid path. 56 */ 57 LCB_SDCMD_REPLACE, 58 59 /** 60 * Add the value at the given path, if the given path does not exist. 61 * The penultimate path component must point to an array. The operation 62 * may be used in conjunction with @ref LCB_SDSPEC_F_MKINTERMEDIATES to 63 * create the parent dictionary (and its parents as well) if it does not 64 * yet exist. 65 */ 66 LCB_SDCMD_DICT_ADD, 67 68 /** 69 * Unconditionally set the value at the path. This logically 70 * attempts to perform a @ref LCB_SDCMD_REPLACE, and if it fails, performs 71 * an @ref LCB_SDCMD_DICT_ADD. 72 */ 73 LCB_SDCMD_DICT_UPSERT, 74 75 /** 76 * Prepend the value(s) to the array indicated by the path. The path should 77 * reference an array. When the @ref LCB_SDSPEC_F_MKINTERMEDIATES flag 78 * is specified then the array may be created if it does not exist. 79 * 80 * Note that it is possible to add more than a single value to an array 81 * in an operation (this is valid for this commnand as well as 82 * @ref LCB_SDCMD_ARRAY_ADD_LAST and @ref LCB_SDCMD_ARRAY_INSERT). Multiple 83 * items can be specified by placing a comma between then (the values should 84 * otherwise be valid JSON). 85 */ 86 LCB_SDCMD_ARRAY_ADD_FIRST, 87 88 /** 89 * Identical to @ref LCB_SDCMD_ARRAY_ADD_FIRST but places the item(s) 90 * at the end of the array rather than at the beginning. 91 */ 92 LCB_SDCMD_ARRAY_ADD_LAST, 93 94 /** 95 * Add the value to the array indicated by the path, if the value is not 96 * already in the array. The @ref LCB_SDSPEC_F_MKINTERMEDIATES flag can 97 * be specified to create the array if it does not already exist. 98 * 99 * Currently the value for this operation must be a JSON primitive (i.e. 100 * no arrays or dictionaries) and the existing array itself must also 101 * contain only primitives (otherwise a @ref LCB_SUBDOC_PATH_MISMATCH 102 * error will be received). 103 */ 104 LCB_SDCMD_ARRAY_ADD_UNIQUE, 105 106 /** 107 * Add the value at the given array index. Unlike other array operations, 108 * the path specified should include the actual index at which the item(s) 109 * should be placed, for example `array[2]` will cause the value(s) to be 110 * the 3rd item(s) in the array. 111 * 112 * The array must already exist and the @ref LCB_SDSPEC_F_MKINTERMEDIATES 113 * flag is not honored. 114 */ 115 LCB_SDCMD_ARRAY_INSERT, 116 117 /** 118 * Increment or decrement an existing numeric path. If the number does 119 * not exist, it will be created (though its parents will not, unless 120 * @ref LCB_SDSPEC_F_MKINTERMEDIATES is specified). 121 * 122 * The value for this operation should be a valid JSON-encoded integer and 123 * must be between `INT64_MIN` and `INT64_MAX`, inclusive. 124 */ 125 LCB_SDCMD_COUNTER, 126 127 /** 128 * Remove an existing path in the document. 129 */ 130 LCB_SDCMD_REMOVE, 131 132 /** 133 * Count the number of elements in an array or dictionary 134 */ 135 LCB_SDCMD_GET_COUNT, 136 137 /** 138 * Retrieve the entire document 139 */ 140 LCB_SDCMD_GET_FULLDOC, 141 142 /** 143 * Replace the entire document 144 */ 145 LCB_SDCMD_SET_FULLDOC, 146 147 /** 148 * Remove the entire document 149 */ 150 LCB_SDCMD_REMOVE_FULLDOC, 151 152 LCB_SDCMD_MAX 153 } lcb_SUBDOCOP; 154 155 /** 156 * @brief Subdoc command specification. 157 * This structure describes an operation and its path, and possibly its value. 158 * This structure is provided in an array to the lcb_CMDSUBDOC::specs field. 159 */ 160 typedef struct { 161 /** 162 * The command code, @ref lcb_SUBDOCOP. There is no default for this 163 * value, and it therefore must be set. 164 */ 165 lcb_U32 sdcmd; 166 167 /** 168 * Set of option flags for the command. Currently the only option known 169 * is @ref LCB_SDSPEC_F_MKINTERMEDIATES 170 */ 171 lcb_U32 options; 172 173 /** 174 * Path for the operation. This should be assigned using 175 * @ref LCB_SDSPEC_SET_PATH. The contents of the path should be valid 176 * until the operation is scheduled (lcb_subdoc3()) 177 */ 178 lcb_KEYBUF path; 179 180 /** 181 * Value for the operation. This should be assigned using 182 * @ref LCB_SDSPEC_SET_VALUE. The contents of the value should be valid 183 * until the operation is scheduled (i.e. lcb_subdoc3()) 184 */ 185 lcb_VALBUF value; 186 } lcb_SDSPEC; 187 188 /** Create intermediate paths */ 189 #define LCB_SDSPEC_F_MKINTERMEDIATES (1<<16) 190 191 /** Access document XATTR path */ 192 #define LCB_SDSPEC_F_XATTRPATH (1<<18) 193 194 /** Access document virtual/materialized path. Implies F_XATTRPATH */ 195 #define LCB_SDSPEC_F_XATTR_MACROVALUES (1<<19) 196 197 /** Access Xattrs of deleted documents */ 198 #define LCB_SDSPEC_F_XATTR_DELETED_OK (1<<20) 199 200 /** 201 * Set the path for an @ref lcb_SDSPEC structure 202 * @param s pointer to spec 203 * @param p the path buffer 204 * @param n the length of the path buffer 205 */ 206 #define LCB_SDSPEC_SET_PATH(s, p, n) do { \ 207 (s)->path.contig.bytes = p; \ 208 (s)->path.contig.nbytes = n; \ 209 (s)->path.type = LCB_KV_COPY; \ 210 } while (0); 211 212 /** 213 * Set the value for the @ref lcb_SDSPEC structure 214 * @param s pointer to spec 215 * @param v the value buffer 216 * @param n the length of the value buffer 217 */ 218 #define LCB_SDSPEC_SET_VALUE(s, v, n) \ 219 LCB_CMD_SET_VALUE(s, v, n) 220 221 #define LCB_SDSPEC_INIT(spec, cmd_, path_, npath_, val_, nval_) do { \ 222 (spec)->sdcmd = cmd_; \ 223 LCB_SDSPEC_SET_PATH(spec, path_, npath_); \ 224 LCB_CMD_SET_VALUE(spec, val_, nval_); \ 225 } while (0); 226 227 #define LCB_SDMULTI_MODE_INVALID 0 228 #define LCB_SDMULTI_MODE_LOOKUP 1 229 #define LCB_SDMULTI_MODE_MUTATE 2 230 231 /** 232 * This command flag should be used if the document is to be created 233 * if it does not exist. 234 */ 235 #define LCB_CMDSUBDOC_F_UPSERT_DOC (1<<16) 236 237 /** 238 * This command flag should be used if the document must be created anew. 239 * In this case, it will fail if it already exists 240 */ 241 #define LCB_CMDSUBDOC_F_INSERT_DOC (1<<17) 242 243 /** 244 * Access a potentially deleted document. For internal Couchbase use 245 */ 246 #define LCB_CMDSUBDOC_F_ACCESS_DELETED (1<<18) 247 248 typedef struct { 249 LCB_CMD_BASE; 250 251 /** 252 * An array of one or more command specifications. The storage 253 * for the array need only persist for the duration of the 254 * lcb_subdoc3() call. 255 * 256 * The specs array must be valid only through the invocation 257 * of lcb_subdoc3(). As such, they can reside on the stack and 258 * be re-used for scheduling multiple commands. See subdoc-simple.cc 259 */ 260 const lcb_SDSPEC *specs; 261 /** 262 * Number of entries in #specs 263 */ 264 size_t nspecs; 265 /** 266 * If the scheduling of the command failed, the index of the entry which 267 * caused the failure will be written to this pointer. 268 * 269 * If the value is -1 then the failure took place at the command level 270 * and not at the spec level. 271 */ 272 int *error_index; 273 /** 274 * Operation mode to use. This can either be @ref LCB_SDMULTI_MODE_LOOKUP 275 * or @ref LCB_SDMULTI_MODE_MUTATE. 276 * 277 * This field may be left empty, in which case the mode is implicitly 278 * derived from the _first_ command issued. 279 */ 280 lcb_U32 multimode; 281 } lcb_CMDSUBDOC; 282 283 /** 284 * Perform one or more subdocument operations. 285 */ 286 LIBCOUCHBASE_API 287 lcb_error_t 288 lcb_subdoc3(lcb_t instance, const void *cookie, const lcb_CMDSUBDOC *cmd); 289 290 /** 291 * Response structure for multi lookups. If the top level response is successful 292 * then the individual results may be retrieved using lcb_sdmlookup_next() 293 */ 294 typedef struct { 295 LCB_RESP_BASE 296 const void *responses; 297 /** Use with lcb_backbuf_ref/unref */ 298 void *bufh; 299 } lcb_RESPSUBDOC; 300 301 /** 302 * Structure for a single sub-document mutation or lookup result. 303 * Note that #value and #nvalue are only valid if #status is ::LCB_SUCCESS 304 */ 305 typedef struct { 306 /** Value for the mutation (only applicable for ::LCB_SDCMD_COUNTER, currently) */ 307 const void *value; 308 /** Length of the value */ 309 size_t nvalue; 310 /** Status code */ 311 lcb_error_t status; 312 313 /** 314 * Request index which this result pertains to. This field only 315 * makes sense for multi mutations where not all request specs are returned 316 * in the result 317 */ 318 lcb_U8 index; 319 } lcb_SDENTRY; 320 321 /** 322 * Iterate over the results for a subdocument response. 323 * 324 * @warning 325 * This function _must_ be called from within the callback. The response itself 326 * may contain a pointer to internal stack data which is no longer valid 327 * once the callback exits. 328 * 329 * @param resp the response received from within the callback. 330 * @param[out] out structure to store the current result 331 * @param[in,out] iter internal iterator. First call should initialize this to 0 332 * Note that this value may be 0, in which case only the first response is 333 * returned. 334 * 335 * @return If this function returns nonzero then `out` will contain a valid 336 * entry. If this function returns 0 then `ent` is invalid and no more results 337 * remain for the response. 338 */ 339 LIBCOUCHBASE_API 340 int 341 lcb_sdresult_next(const lcb_RESPSUBDOC *resp, lcb_SDENTRY *out, size_t *iter); 342 343 /**@}*/ 344 #ifdef __cplusplus 345 } 346 #endif 347 #endif 348