@@ -142,14 +142,187 @@ struct Upsert_cmd : public Executable<Result, Upsert_cmd>
142
142
};
143
143
144
144
145
+ struct Value_expr_check_id
146
+ : cdk::Expression
147
+ , cdk::Expression::Processor
148
+ , cdk::Expression::Processor::Doc_prc
149
+ {
150
+ Value_expr &m_expr;
151
+ bool m_is_expr;
152
+
153
+ Processor *m_prc;
154
+ Doc_prc *m_doc_prc;
155
+
156
+ struct Any_processor_check
157
+ : cdk::Expression::Processor::Doc_prc::Any_prc
158
+ , cdk::Expression::Processor::Doc_prc::Any_prc::Scalar_prc
159
+ , cdk::Expression::Processor::Doc_prc::Any_prc::Scalar_prc::Value_prc
160
+ {
161
+ Any_prc *m_id_prc;
162
+ Scalar_prc *m_scalar_prc;
163
+ Value_prc *m_value_prc;
164
+ const string& m_id;
165
+
166
+ Any_processor_check (const string& id)
167
+ : m_id(id)
168
+ {}
169
+
170
+ // Any processor implementation
171
+
172
+ Scalar_prc* scalar () override
173
+ {
174
+ m_scalar_prc = m_id_prc->scalar ();
175
+ return m_scalar_prc ? this : nullptr ;
176
+ }
177
+
178
+ List_prc* arr () override
179
+ {
180
+ return m_id_prc->arr ();
181
+ }
182
+
183
+ Doc_prc* doc () override
184
+ {
185
+ return m_id_prc->doc ();
186
+ }
187
+
188
+ // Scalar processor implementation
189
+
190
+ Value_prc* val () override
191
+ {
192
+ m_value_prc = m_scalar_prc->val ();
193
+ return m_value_prc ? this : nullptr ;
194
+ }
195
+
196
+ Args_prc* op (const char *name) override
197
+ {
198
+ return m_scalar_prc->op (name);
199
+ }
200
+ Args_prc* call (const Object_ref&obj) override
201
+ {
202
+ return m_scalar_prc->call (obj);
203
+ }
204
+
205
+ void ref (const Column_ref &col, const Doc_path *path) override
206
+ {
207
+ return m_scalar_prc->ref (col, path);
208
+ }
209
+ void ref (const Doc_path &path) override
210
+ {
211
+ return m_scalar_prc->ref (path);
212
+ }
213
+
214
+ void param (const string &val) override
215
+ {
216
+ return m_scalar_prc->param (val);
217
+ }
218
+
219
+ void param (uint16_t val) override
220
+ {
221
+ return m_scalar_prc->param (val);
222
+ }
223
+
224
+ void var (const string &name) override
225
+ {
226
+ m_scalar_prc->var (name);
227
+ }
228
+
229
+ // Value processor implementation
230
+ virtual void null () override { m_value_prc->null ();}
231
+
232
+ virtual void value (cdk::Type_info type,
233
+ const cdk::Format_info &format,
234
+ cdk::foundation::bytes val) override
235
+ {
236
+ m_value_prc->value (type, format, val);
237
+ }
238
+
239
+ virtual void str (const string &val)
240
+ {
241
+ if (m_id != val)
242
+ throw Error (R"( Document "_id" and replace id are different!)" );
243
+ m_value_prc->str (val);
244
+ }
245
+ virtual void num (int64_t val) { m_value_prc->num (val); }
246
+ virtual void num (uint64_t val) { m_value_prc->num (val); }
247
+ virtual void num (float val) { m_value_prc->num (val); }
248
+ virtual void num (double val) { m_value_prc->num (val); }
249
+ virtual void yesno (bool val) { m_value_prc->yesno (val); }
250
+
251
+ };
252
+
253
+ Any_processor_check m_any_prc;
254
+
255
+ Value_expr_check_id (Value_expr &expr, bool is_expr, const string& id)
256
+ : m_expr(expr)
257
+ , m_is_expr(is_expr)
258
+ , m_any_prc(id)
259
+ {}
260
+
261
+ // Expression implementation
262
+
263
+ void process (Processor& prc) const override
264
+ {
265
+ auto self = const_cast <Value_expr_check_id*>(this );
266
+ self->m_prc = &prc;
267
+ m_expr.process (*self);
268
+ }
269
+
270
+ // Expression processor implementation
271
+
272
+ Scalar_prc* scalar () override
273
+ {
274
+ return m_prc->scalar ();
275
+ }
276
+
277
+ List_prc* arr () override
278
+ {
279
+ return m_prc->arr ();
280
+ }
281
+
282
+ Doc_prc* doc () override
283
+ {
284
+ m_doc_prc = m_prc->doc ();
285
+ return m_doc_prc ? this : nullptr ;
286
+ }
287
+
288
+ // Doc_prc implementation
289
+
290
+ void doc_begin () override
291
+ {
292
+ m_doc_prc->doc_begin ();
293
+ }
294
+
295
+ void doc_end () override
296
+ {
297
+ m_doc_prc->doc_end ();
298
+ }
299
+
300
+ Any_prc* key_val (const string &key) override
301
+ {
302
+ if (string (" _id" ) == key )
303
+ {
304
+ if (m_is_expr)
305
+ throw Error (R"( Document "_id" will be replaced by expression "_id")" );
306
+
307
+ m_any_prc.m_id_prc = m_doc_prc->key_val (key);
308
+ return m_any_prc.m_id_prc ? &m_any_prc : nullptr ;
309
+ }
310
+ return m_doc_prc->key_val (key);
311
+ }
312
+
313
+ };
314
+
315
+
145
316
Result
146
317
internal::Collection_detail::add_or_replace_one (
147
318
const string &id, Value &&doc, bool replace
148
319
)
149
320
{
150
321
Object_ref coll (get_schema ().m_name , m_name);
151
322
152
- if (doc.getType () == Value::STRING)
323
+
324
+ if (!Value::Access::is_expr (doc) &&
325
+ doc.getType () == Value::STRING)
153
326
{
154
327
doc = DbDoc (doc.get <string>());
155
328
}
@@ -158,22 +331,9 @@ internal::Collection_detail::add_or_replace_one(
158
331
159
332
if (replace)
160
333
{
161
- string doc_id;
162
- bool has_id = true ;
163
-
164
- try {
165
- doc_id = doc.get <DbDoc>()[" _id" ];
166
- } catch (std::out_of_range)
167
- {
168
- has_id = false ;
169
- }
170
-
171
- if (has_id && (doc_id != id))
172
- {
173
- throw Error (R"( Document "_id" and replace id are different!)" );
174
- }
334
+ Value_expr_check_id check_id (expr, Value::Access::is_expr (doc), id);
175
335
176
- Replace_cmd cmd (m_sess, coll, std::string (id), expr );
336
+ Replace_cmd cmd (m_sess, coll, std::string (id), check_id );
177
337
return cmd.execute ();
178
338
}
179
339
else
0 commit comments