1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdlib>
17 #include <string>
18 #include <variant>
19 #include <vector>
20 #include <map>
21 #include <iomanip>
22 #include "securec.h"
23 #include "ffi_remote_data.h"
24
25 #include "distributed_kv_store_impl.h"
26 #include "distributed_kv_store_utils.h"
27
28 using namespace OHOS::FFI;
29
30 namespace OHOS::DistributedKVStore {
31
ConvertCJErrCode(Status status)32 static int32_t ConvertCJErrCode(Status status)
33 {
34 switch (status) {
35 case PERMISSION_DENIED:
36 // 202
37 return CJ_ERROR_PERMISSION_DENIED;
38 case INVALID_ARGUMENT:
39 // 401
40 return CJ_ERROR_INVALID_ARGUMENT;
41 case OVER_MAX_LIMITS:
42 // 15100001
43 return CJ_ERROR_OVER_MAX_LIMITS;
44 case STORE_META_CHANGED:
45 case SECURITY_LEVEL_ERROR:
46 // 15100002
47 return CJ_ERROR_STORE_META_CHANGED;
48 case CRYPT_ERROR:
49 case DATA_CORRUPTED:
50 // 15100003
51 return CJ_ERROR_CRYPT_ERROR;
52 case NOT_FOUND:
53 case DB_ERROR:
54 // 15100004
55 return CJ_ERROR_NOT_FOUND;
56 case ALREADY_CLOSED:
57 // 15100005
58 return CJ_ERROR_ALREADY_CLOSED;
59 default:
60 return static_cast<int32_t>(status);
61 }
62 }
63
VectorToByteArray(std::vector<uint8_t> bytes)64 static CArrByte VectorToByteArray(std::vector<uint8_t> bytes)
65 {
66 uint8_t* head = static_cast<uint8_t*>(malloc(bytes.size() * sizeof(uint8_t)));
67 if (head == nullptr) {
68 return CArrByte{};
69 }
70 for (unsigned long i = 0; i < bytes.size(); i++) {
71 head[i] = bytes[i];
72 }
73 CArrByte byteArray = { head, bytes.size() };
74 return byteArray;
75 }
76
KVValueToValueType(const DistributedKv::Blob & blob)77 static ValueType KVValueToValueType(const DistributedKv::Blob& blob)
78 {
79 auto& data = blob.Data();
80 ValueType v = { 0 };
81 // number 2 means: valid Blob must have more than 2 bytes.
82 if (data.size() < 1) {
83 LOGI("Blob have no data!");
84 return {0};
85 }
86 // number 1 means: skip the first byte, byte[0] is real data type.
87 std::vector<uint8_t> real(data.begin() + 1, data.end());
88 if (data[0] == STRING) {
89 v.string = MallocCString(std::string(real.begin(), real.end()));
90 v.tag = STRING;
91 } else if (data[0] == INTEGER) {
92 uint32_t tmp4int = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
93 v.integer = *reinterpret_cast<int32_t*>(&tmp4int);
94 v.tag = INTEGER;
95 } else if (data[0] == FLOAT) {
96 uint32_t tmp4flt = be32toh(*reinterpret_cast<uint32_t*>(&(real[0])));
97 v.flo = *reinterpret_cast<float*>((void*)(&tmp4flt));
98 v.tag = FLOAT;
99 } else if (data[0] == BYTE_ARRAY) {
100 v.byteArray = VectorToByteArray(std::vector<uint8_t>(real.begin(), real.end()));
101 v.tag = BYTE_ARRAY;
102 } else if (data[0] == BOOLEAN) {
103 v.boolean = static_cast<bool>(real[0]);
104 v.tag = BOOLEAN;
105 } else if (data[0] == DOUBLE) {
106 uint64_t tmp4dbl = be64toh(*reinterpret_cast<uint64_t*>(&(real[0])));
107 v.dou = *reinterpret_cast<double*>((void*)(&tmp4dbl));
108 v.tag = DOUBLE;
109 } else {
110 // for schema-db, if (data[0] == STRING), no beginning byte!
111 v.string = MallocCString(std::string(data.begin(), data.end()));
112 v.tag = STRING;
113 }
114 return v;
115 }
116
PushData(const ValueType & value,std::vector<uint8_t> & data,uint8_t tag)117 static void PushData(const ValueType &value, std::vector<uint8_t> &data, uint8_t tag)
118 {
119 switch (tag) {
120 case INTEGER: {
121 int32_t tmp = value.integer; // copy value, and make it available in stack space.
122 uint32_t tmp32 = htobe32(*reinterpret_cast<uint32_t*>(&tmp));
123 uint8_t *res = reinterpret_cast<uint8_t*>(&tmp32);
124 data.push_back(INTEGER);
125 data.insert(data.end(), res, res + sizeof(int32_t) / sizeof(uint8_t));
126 break;
127 }
128 case FLOAT: {
129 float tmp = value.flo; // copy value, and make it available in stack space.
130 uint32_t tmp32 = htobe32(*reinterpret_cast<uint32_t*>(&tmp));
131 uint8_t *res = reinterpret_cast<uint8_t*>(&tmp32);
132 data.push_back(FLOAT);
133 data.insert(data.end(), res, res + sizeof(float) / sizeof(uint8_t));
134 break;
135 }
136 case DOUBLE: {
137 double tmp = value.dou; // copy value, and make it available in stack space.
138 uint64_t tmp64 = htobe64(*reinterpret_cast<uint64_t*>(&tmp));
139 uint8_t *res = reinterpret_cast<uint8_t*>(&tmp64);
140 data.push_back(DOUBLE);
141 data.insert(data.end(), res, res + sizeof(double) / sizeof(uint8_t));
142 break;
143 }
144 default:
145 break;
146 }
147 }
148
ValueTypeToKVValue(const ValueType & value)149 static DistributedKv::Value ValueTypeToKVValue(const ValueType &value)
150 {
151 std::vector<uint8_t> data;
152 switch (value.tag) {
153 case STRING: {
154 std::string str = value.string;
155 data.push_back(STRING);
156 data.insert(data.end(), str.begin(), str.end());
157 break;
158 }
159 case INTEGER: {
160 PushData(value, data, value.tag);
161 break;
162 }
163 case FLOAT: {
164 PushData(value, data, value.tag);
165 break;
166 }
167 case BYTE_ARRAY: {
168 std::vector<uint8_t> bytes = std::vector<uint8_t>();
169 for (int64_t i = 0; i < value.byteArray.size; i++) {
170 bytes.push_back(value.byteArray.head[i]);
171 }
172 data.push_back(BYTE_ARRAY);
173 data.insert(data.end(), bytes.begin(), bytes.end());
174 break;
175 }
176 case BOOLEAN: {
177 data.push_back(BOOLEAN);
178 data.push_back(static_cast<uint8_t>(value.boolean));
179 break;
180 }
181 case DOUBLE: {
182 PushData(value, data, value.tag);
183 break;
184 }
185 default:
186 break;
187 }
188 return DistributedKv::Blob(data);
189 }
190
CJKVManager()191 CJKVManager::CJKVManager() {};
CJKVManager(const char * boudleName,OHOS::AbilityRuntime::Context * context)192 CJKVManager::CJKVManager(const char* boudleName, OHOS::AbilityRuntime::Context* context)
193 {
194 ContextParam param;
195 param.area = context->GetArea();
196 param.baseDir = context->GetDatabaseDir();
197 auto hapInfo = context->GetHapModuleInfo();
198 if (hapInfo != nullptr) {
199 param.hapName = hapInfo->moduleName;
200 }
201 param_ = std::make_shared<ContextParam>(std::move(param));
202 bundleName_ = boudleName;
203 }
204
GetKVStore(const char * cStoreId,const CJOptions cjOptions,int32_t & errCode)205 uint64_t CJKVManager::GetKVStore(const char* cStoreId, const CJOptions cjOptions, int32_t& errCode)
206 {
207 Options options;
208 options.createIfMissing = cjOptions.createIfMissing;
209 options.encrypt = cjOptions.encrypt;
210 options.backup = cjOptions.backup;
211 options.autoSync = cjOptions.autoSync;
212 options.kvStoreType = static_cast<KvStoreType>(cjOptions.kvStoreType);
213 options.securityLevel = cjOptions.securityLevel;
214 AppId appId = { bundleName_ };
215 std::string sStoreId = cStoreId;
216 StoreId storeId = { sStoreId };
217 options.baseDir = param_->baseDir;
218 options.area = param_->area + 1;
219 options.hapName = param_->hapName;
220 std::shared_ptr<DistributedKv::SingleKvStore> kvStore;
221 Status status = kvDataManager_.GetSingleKvStore(options, appId, storeId, kvStore);
222 if (status == DATA_CORRUPTED) {
223 options.rebuild = true;
224 status = kvDataManager_.GetSingleKvStore(options, appId, storeId, kvStore);
225 LOGE("Data has corrupted, rebuild db");
226 }
227 errCode = ConvertCJErrCode(status);
228 if (errCode != 0) {
229 return 0;
230 }
231 if (cjOptions.kvStoreType == 1) {
232 auto nativeKVStore = FFIData::Create<CJSingleKVStore>(sStoreId);
233 if (nativeKVStore == nullptr) {
234 errCode = -1;
235 return -1;
236 }
237 nativeKVStore->SetKvStorePtr(kvStore);
238 nativeKVStore->SetContextParam(param_);
239 return nativeKVStore->GetID();
240 }
241 auto nativeKVStore = FFIData::Create<CJDeviceKVStore>(sStoreId);
242 if (nativeKVStore == nullptr) {
243 errCode = -1;
244 return -1;
245 }
246 nativeKVStore->SetKvStorePtr(kvStore);
247 nativeKVStore->SetContextParam(param_);
248 return nativeKVStore->GetID();
249 }
250
CloseKVStore(const char * appId,const char * storeId)251 int32_t CJKVManager::CloseKVStore(const char* appId, const char* storeId)
252 {
253 std::string sAppId = appId;
254 std::string sStoreId = storeId;
255 AppId appIdBox = { sAppId };
256 StoreId storeIdBox { sStoreId };
257 Status status = kvDataManager_.CloseKvStore(appIdBox, storeIdBox);
258 if ((status == Status::SUCCESS) || (status == Status::STORE_NOT_FOUND) || (status == Status::STORE_NOT_OPEN)) {
259 status = Status::SUCCESS;
260 }
261 return ConvertCJErrCode(status);
262 }
263
DeleteKVStore(const char * appId,const char * storeId)264 int32_t CJKVManager::DeleteKVStore(const char* appId, const char* storeId)
265 {
266 std::string sAppId = appId;
267 std::string sStoreId = storeId;
268 AppId appIdBox = { sAppId };
269 StoreId storeIdBox { sStoreId };
270 std::string databaseDir = param_->baseDir;
271 Status status = kvDataManager_.DeleteKvStore(appIdBox, storeIdBox, databaseDir);
272 return ConvertCJErrCode(status);
273 }
274
VectorAppIdToCArr(const std::vector<StoreId> & storeIdList)275 static CArrStr VectorAppIdToCArr(const std::vector<StoreId>& storeIdList)
276 {
277 CArrStr strArray;
278 strArray.size = static_cast<int64_t>(storeIdList.size());
279 strArray.head = static_cast<char**>(malloc(strArray.size * sizeof(char*)));
280 if (strArray.head == nullptr) {
281 return CArrStr{0};
282 }
283 for (int64_t i = 0; i < strArray.size; i++) {
284 strArray.head[i] = MallocCString(storeIdList[i].storeId);
285 }
286 return strArray;
287 }
288
GetAllKVStoreId(const char * appId,int32_t & errCode)289 CArrStr CJKVManager::GetAllKVStoreId(const char* appId, int32_t& errCode)
290 {
291 std::string sAppId = appId;
292 AppId appIdBox = { sAppId };
293 std::vector<StoreId> storeIdList;
294 Status status = kvDataManager_.GetAllKvStoreId(appIdBox, storeIdList);
295 errCode = ConvertCJErrCode(status);
296 if (errCode != 0) {
297 return CArrStr{0};
298 }
299 return VectorAppIdToCArr(storeIdList);
300 }
301
CJSingleKVStore(const std::string & storeId)302 CJSingleKVStore::CJSingleKVStore(const std::string& storeId)
303 {
304 storeId_ = storeId;
305 }
306
GetKvStorePtr()307 std::shared_ptr<SingleKvStore> CJSingleKVStore::GetKvStorePtr()
308 {
309 return kvStore_;
310 }
311
SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)312 void CJSingleKVStore::SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)
313 {
314 kvStore_ = kvStore;
315 }
316
SetContextParam(std::shared_ptr<ContextParam> param)317 void CJSingleKVStore::SetContextParam(std::shared_ptr<ContextParam> param)
318 {
319 param_ = param;
320 }
321
Put(const std::string & key,const ValueType & value)322 int32_t CJSingleKVStore::Put(const std::string &key, const ValueType &value)
323 {
324 auto tempKey = DistributedKv::Key(key);
325 Status status = kvStore_->Put(tempKey, ValueTypeToKVValue(value));
326 return ConvertCJErrCode(status);
327 }
328
CEntryToEntry(const CEntry & cEntry)329 static Entry CEntryToEntry(const CEntry &cEntry)
330 {
331 std::string key = cEntry.key;
332 Entry entry = {DistributedKv::Key(key), ValueTypeToKVValue(cEntry.value)};
333 return entry;
334 }
335
CArrayEntryToEntries(const CArrEntry & cArrEntry)336 static std::vector<Entry> CArrayEntryToEntries(const CArrEntry &cArrEntry)
337 {
338 std::vector<Entry> entrys;
339 int64_t arrSize = cArrEntry.size;
340
341 for (int64_t i = 0; i < arrSize; i++) {
342 Entry entry = CEntryToEntry(cArrEntry.head[i]);
343 entrys.push_back(entry);
344 }
345 return entrys;
346 }
347
PutBatch(const CArrEntry & cArrEntry)348 int32_t CJSingleKVStore::PutBatch(const CArrEntry &cArrEntry)
349 {
350 Status status = kvStore_->PutBatch(CArrayEntryToEntries(cArrEntry));
351 return ConvertCJErrCode(status);
352 }
353
Delete(const std::string & key)354 int32_t CJSingleKVStore::Delete(const std::string &key)
355 {
356 auto tempKey = DistributedKv::Key(key);
357 Status status = kvStore_->Delete(tempKey);
358 return ConvertCJErrCode(status);
359 }
360
CArrStrToVectorKey(const CArrStr & cArrStr)361 static std::vector<Key> CArrStrToVectorKey(const CArrStr &cArrStr)
362 {
363 std::vector<Key> keys;
364 int64_t size = cArrStr.size;
365 for (int64_t i = 0; i < size; i++) {
366 std::string str = cArrStr.head[i];
367 keys.push_back(DistributedKv::Key(str));
368 }
369 return keys;
370 }
371
DeleteBatch(const CArrStr & cArrStr)372 int32_t CJSingleKVStore::DeleteBatch(const CArrStr &cArrStr)
373 {
374 Status status = kvStore_->DeleteBatch(CArrStrToVectorKey(cArrStr));
375 return ConvertCJErrCode(status);
376 }
377
Get(const std::string & key,int32_t & errCode)378 ValueType CJSingleKVStore::Get(const std::string &key, int32_t& errCode)
379 {
380 auto s_key = DistributedKv::Key(key);
381 OHOS::DistributedKv::Value value;
382 Status status = kvStore_->Get(key, value);
383 errCode = ConvertCJErrCode(status);
384 if (errCode != 0) {
385 return ValueType{0};
386 }
387 return KVValueToValueType(value);
388 }
389
Backup(const std::string & file)390 int32_t CJSingleKVStore::Backup(const std::string &file)
391 {
392 Status status = kvStore_->Backup(file, param_->baseDir);
393 return ConvertCJErrCode(status);
394 }
395
Restore(const std::string & file)396 int32_t CJSingleKVStore::Restore(const std::string &file)
397 {
398 Status status = kvStore_->Restore(file, param_->baseDir);
399 return ConvertCJErrCode(status);
400 }
401
StartTransaction()402 int32_t CJSingleKVStore::StartTransaction()
403 {
404 Status status = kvStore_->StartTransaction();
405 return ConvertCJErrCode(status);
406 }
407
Commit()408 int32_t CJSingleKVStore::Commit()
409 {
410 Status status = kvStore_->Commit();
411 return ConvertCJErrCode(status);
412 }
413
Rollback()414 int32_t CJSingleKVStore::Rollback()
415 {
416 Status status = kvStore_->Rollback();
417 return ConvertCJErrCode(status);
418 }
419
EnableSync(bool enabled)420 int32_t CJSingleKVStore::EnableSync(bool enabled)
421 {
422 Status status = kvStore_->SetCapabilityEnabled(enabled);
423 return ConvertCJErrCode(status);
424 }
425
SetSyncParam(uint32_t defaultAllowedDelayMs)426 int32_t CJSingleKVStore::SetSyncParam(uint32_t defaultAllowedDelayMs)
427 {
428 KvSyncParam syncParam { defaultAllowedDelayMs };
429 Status status = kvStore_->SetSyncParam(syncParam);
430 return ConvertCJErrCode(status);
431 }
432
433 constexpr int DEVICEID_WIDTH = 4;
434
GetDeviceKey(const std::string & deviceId,const std::string & key)435 static std::string GetDeviceKey(const std::string& deviceId, const std::string& key)
436 {
437 std::ostringstream oss;
438 if (!deviceId.empty()) {
439 oss << std::setfill('0') << std::setw(DEVICEID_WIDTH) << deviceId.length() << deviceId;
440 }
441 oss << key;
442 return oss.str();
443 }
444
CJDeviceKVStore(const std::string & storeId)445 CJDeviceKVStore::CJDeviceKVStore(const std::string& storeId)
446 : CJSingleKVStore(storeId)
447 {
448 }
449
Get(const std::string & deviceId,const std::string & key,int32_t & errCode)450 ValueType CJDeviceKVStore::Get(const std::string &deviceId, const std::string &key, int32_t& errCode)
451 {
452 std::string deviceKey = GetDeviceKey(deviceId, key);
453 auto s_key = DistributedKv::Key(deviceKey);
454 OHOS::DistributedKv::Value value;
455 Status status = GetKvStorePtr()->Get(key, value);
456 errCode = ConvertCJErrCode(status);
457 if (errCode != 0) {
458 return ValueType{0};
459 }
460 return KVValueToValueType(value);
461 }
462
GetEntriesByDataQuery(DistributedKVStore::DataQuery dataQuery,int32_t & errCode)463 CArrEntry CJDeviceKVStore::GetEntriesByDataQuery(DistributedKVStore::DataQuery dataQuery, int32_t& errCode)
464 {
465 std::vector<DistributedKVStore::Entry> entries;
466 Status status = GetKvStorePtr()->GetEntries(dataQuery, entries);
467 errCode = ConvertCJErrCode(status);
468 if (errCode != 0) {
469 return CArrEntry{};
470 }
471 CEntry *cEntries = static_cast<CEntry*>(malloc(entries.size() * sizeof(CEntry)));
472 if (cEntries == nullptr) {
473 errCode = -1;
474 return CArrEntry{};
475 }
476 for (size_t i = 0; i < entries.size(); i++) {
477 cEntries[i].key = MallocCString(entries[i].key.ToString());
478 cEntries[i].value = KVValueToValueType(entries[i].value);
479 }
480 return CArrEntry{.head = cEntries, .size = int64_t(entries.size())};
481 }
482
GetEntries(const std::string & deviceId,const std::string & keyPrefix,int32_t & errCode)483 CArrEntry CJDeviceKVStore::GetEntries(const std::string &deviceId, const std::string &keyPrefix, int32_t& errCode)
484 {
485 DistributedKVStore::DataQuery dataQuery;
486 dataQuery.KeyPrefix(keyPrefix);
487 dataQuery.DeviceId(deviceId);
488
489 return GetEntriesByDataQuery(dataQuery, errCode);
490 }
491
GetEntries(const std::string & deviceId,OHOS::sptr<CQuery> query,int32_t & errCode)492 CArrEntry CJDeviceKVStore::GetEntries(const std::string &deviceId, OHOS::sptr<CQuery> query, int32_t& errCode)
493 {
494 DistributedKVStore::DataQuery dataQuery = query->GetDataQuery();
495 dataQuery.DeviceId(deviceId);
496
497 return GetEntriesByDataQuery(dataQuery, errCode);
498 }
499
GetResultSet(const std::string & deviceId,const std::string & keyPrefix,int32_t & errCode)500 int64_t CJDeviceKVStore::GetResultSet(const std::string &deviceId, const std::string &keyPrefix, int32_t& errCode)
501 {
502 DistributedKVStore::DataQuery dataQuery;
503 dataQuery.KeyPrefix(keyPrefix);
504 dataQuery.DeviceId(deviceId);
505
506 std::shared_ptr<DistributedKv::KvStoreResultSet> kvResultSet;
507 Status status = GetKvStorePtr()->GetResultSet(dataQuery, kvResultSet);
508 errCode = ConvertCJErrCode(status);
509 if (errCode != 0) {
510 return -1;
511 }
512 auto nativeCKvStoreResultSet = FFIData::Create<OHOS::DistributedKVStore::CKvStoreResultSet>(kvResultSet);
513 if (nativeCKvStoreResultSet == nullptr) {
514 errCode = -1;
515 return -1;
516 }
517 return nativeCKvStoreResultSet->GetID();
518 }
519
GetResultSetQuery(const std::string & deviceId,OHOS::sptr<CQuery> query,int32_t & errCode)520 int64_t CJDeviceKVStore::GetResultSetQuery(const std::string &deviceId, OHOS::sptr<CQuery> query, int32_t& errCode)
521 {
522 DistributedKVStore::DataQuery dataQuery = query->GetDataQuery();
523 dataQuery.DeviceId(deviceId);
524
525 std::shared_ptr<DistributedKv::KvStoreResultSet> kvResultSet;
526 Status status = GetKvStorePtr()->GetResultSet(dataQuery, kvResultSet);
527 errCode = ConvertCJErrCode(status);
528 if (errCode != 0) {
529 return -1;
530 }
531 auto nativeCKvStoreResultSet = FFIData::Create<OHOS::DistributedKVStore::CKvStoreResultSet>(kvResultSet);
532 if (nativeCKvStoreResultSet == nullptr) {
533 errCode = -1;
534 return -1;
535 }
536 return nativeCKvStoreResultSet->GetID();
537 }
538
GetResultSize(const std::string & deviceId,OHOS::sptr<CQuery> query,int32_t & errCode)539 int32_t CJDeviceKVStore::GetResultSize(const std::string &deviceId, OHOS::sptr<CQuery> query, int32_t& errCode)
540 {
541 DistributedKVStore::DataQuery dataQuery = query->GetDataQuery();
542 dataQuery.DeviceId(deviceId);
543
544 int32_t resultSize = 0;
545 Status status = GetKvStorePtr()->GetCount(dataQuery, resultSize);
546 errCode = ConvertCJErrCode(status);
547 return resultSize;
548 }
549
CKvStoreResultSet(std::shared_ptr<DistributedKv::KvStoreResultSet> cKvResultSet)550 CKvStoreResultSet::CKvStoreResultSet(std::shared_ptr<DistributedKv::KvStoreResultSet> cKvResultSet)
551 {
552 kvResultSet = cKvResultSet;
553 }
554
GetKvStoreResultSet()555 std::shared_ptr<DistributedKv::KvStoreResultSet> CKvStoreResultSet::GetKvStoreResultSet()
556 {
557 return kvResultSet;
558 }
559
GetCount()560 int32_t CKvStoreResultSet::GetCount()
561 {
562 return kvResultSet->GetCount();
563 }
564
GetDataQuery() const565 const DistributedKv::DataQuery& CQuery::GetDataQuery() const
566 {
567 return query_;
568 }
569
Reset()570 void CQuery::Reset()
571 {
572 query_.Reset();
573 }
574
EqualTo(const std::string & field,ValueType & value)575 void CQuery::EqualTo(const std::string &field, ValueType &value)
576 {
577 switch (value.tag) {
578 case STRING: {
579 query_.EqualTo(field, value.string);
580 break;
581 }
582 case INTEGER: {
583 query_.EqualTo(field, value.integer);
584 break;
585 }
586 case FLOAT: {
587 query_.EqualTo(field, value.flo);
588 break;
589 }
590 case BOOLEAN: {
591 query_.EqualTo(field, value.boolean);
592 break;
593 }
594 case DOUBLE: {
595 query_.EqualTo(field, value.dou);
596 break;
597 }
598 default: {
599 break;
600 }
601 }
602 }
603 }
604