• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "query_object.h"
17 
18 #include "db_common.h"
19 #include "db_errno.h"
20 #include "get_query_info.h"
21 #include "log_print.h"
22 
23 namespace DistributedDB {
24 namespace {
25 const int INVALID_LIMIT = INT_MAX;
26 const int LIMIT_FIELD_VALUE_SIZE = 2;
27 }
28 
QueryObject()29 QueryObject::QueryObject()
30     : isValid_(true),
31       initialized_(false),
32       limit_(INVALID_LIMIT),
33       offset_(0),
34       hasOrderBy_(false),
35       hasLimit_(false),
36       hasPrefixKey_(false),
37       hasInKeys_(false),
38       orderByCounts_(0),
39       isUseLocalSchema_(true)
40 {
41 }
42 
SetAttrWithQueryObjNodes()43 void QueryObject::SetAttrWithQueryObjNodes()
44 {
45     for (const auto &iter : queryObjNodes_) {
46         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(iter.operFlag);
47         if (iter.operFlag == QueryObjType::LIMIT) {
48             hasLimit_ = true;
49             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
50                 limit_ = iter.fieldValue[0].integerValue;
51                 offset_ = iter.fieldValue[1].integerValue;
52             }
53         } else if (iter.operFlag == QueryObjType::ORDERBY) {
54             hasOrderBy_ = true;
55         } else if (symbolType == SymbolType::PREFIXKEY_SYMBOL) {
56             hasPrefixKey_ = true;
57         } else if (symbolType == SymbolType::IN_KEYS_SYMBOL) {
58             hasInKeys_ = true;
59         }
60     }
61 }
62 
QueryObject(const Query & query)63 QueryObject::QueryObject(const Query &query)
64     : QueryObject(GetQueryInfo::GetQueryExpression(query))
65 {
66 }
67 
QueryObject(const QueryExpression & queryExpression)68 QueryObject::QueryObject(const QueryExpression &queryExpression)
69     : initialized_(false),
70       limit_(INVALID_LIMIT),
71       offset_(0),
72       hasOrderBy_(false),
73       hasLimit_(false),
74       hasPrefixKey_(false),
75       hasInKeys_(false),
76       orderByCounts_(0),
77       isUseLocalSchema_(true)
78 {
79     QueryExpression queryExpressions = queryExpression;
80     queryObjNodes_ = queryExpressions.GetQueryExpression();
81     SetAttrWithQueryObjNodes();
82     isValid_ = queryExpressions.GetErrFlag();
83     prefixKey_ = queryExpressions.GetPreFixKey();
84     suggestIndex_ = queryExpressions.GetSuggestIndex();
85     tableName_ = queryExpressions.GetTableName();
86     isTableNameSpecified_ = queryExpressions.IsTableNameSpecified();
87     keys_ = queryExpressions.GetKeys();
88     sortType_ = static_cast<SortType>(queryExpressions.GetSortType());
89     tables_ = queryExpressions.GetTables();
90     validStatus = queryExpressions.GetExpressionStatus();
91     isAssetsOnly_ = queryExpressions.IsAssetsOnly();
92     groupNum_ = queryExpressions.GetGroupNum();
93     assetsGroupMap_ = queryExpressions.GetAssetsOnlyGroupMap();
94     assetsOnlyErrFlag_ = queryExpressions.GetExpressionStatusForAssetsOnly();
95     isUseFromTables_ = queryExpressions.IsUseFromTables();
96 }
97 
QueryObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)98 QueryObject::QueryObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
99     const std::set<Key> &keys)
100     : queryObjNodes_(queryObjNodes),
101       prefixKey_(prefixKey),
102       keys_(keys),
103       isValid_(true),
104       initialized_(false),
105       limit_(INVALID_LIMIT),
106       offset_(0),
107       hasOrderBy_(false),
108       hasLimit_(false),
109       hasPrefixKey_(false),
110       hasInKeys_(false),
111       orderByCounts_(0),
112       isUseLocalSchema_(true)
113 {
114     SetAttrWithQueryObjNodes();
115 }
116 
~QueryObject()117 QueryObject::~QueryObject()
118 {}
119 
Init()120 int QueryObject::Init()
121 {
122     if (initialized_) {
123         return E_OK;
124     }
125 
126     int errCode = Parse();
127     if (errCode != E_OK) {
128         LOGE("Parse query object err[%d]!", errCode);
129         return errCode;
130     }
131 
132     initialized_ = true;
133     return errCode;
134 }
135 
GetQueryHelper(int & errCode)136 SqliteQueryHelper QueryObject::GetQueryHelper(int &errCode)
137 {
138     errCode = Init();
139     if (errCode != E_OK) {
140         return SqliteQueryHelper(QueryObjInfo{});
141     }
142     QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, keys_,
143         orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_, isTableNameSpecified_, sortType_};
144     return SqliteQueryHelper {info}; // compiler RVO by default, and RVO is generally required after C++17
145 }
146 
IsValid()147 bool QueryObject::IsValid()
148 {
149     if (!initialized_) {
150         (void)Init();
151     }
152     return isValid_;
153 }
154 
HasLimit() const155 bool QueryObject::HasLimit() const
156 {
157     return hasLimit_;
158 }
159 
GetLimitVal(int & limit,int & offset) const160 void QueryObject::GetLimitVal(int &limit, int &offset) const
161 {
162     limit = limit_;
163     offset = offset_;
164 }
165 
SetSchema(const SchemaObject & schema)166 void QueryObject::SetSchema(const SchemaObject &schema)
167 {
168     schema_ = schema;
169 }
170 
IsCountValid() const171 bool QueryObject::IsCountValid() const
172 {
173     if (hasLimit_ || hasOrderBy_) {
174         LOGI("It is invalid for limit and orderby!");
175         return false;
176     }
177     return true;
178 }
179 
GetPrefixKey() const180 const std::vector<uint8_t> &QueryObject::GetPrefixKey() const
181 {
182     return prefixKey_;
183 }
184 
ClearNodesFlag()185 void QueryObject::ClearNodesFlag()
186 {
187     limit_ = INVALID_LIMIT;
188     offset_ = 0;
189     isValid_ = true;
190     hasOrderBy_ = false;
191     hasLimit_ = false;
192     hasPrefixKey_ = false;
193     hasInKeys_ = false;
194     orderByCounts_ = 0;
195 }
196 
Parse()197 int QueryObject::Parse()
198 {
199     if (!isValid_) {
200         LOGE("Invalid query object!");
201         return -E_INVALID_QUERY_FORMAT;
202     }
203     int errCode = ParseQueryObjNodes();
204     if (errCode != E_OK) {
205         LOGE("Check query object illegal!");
206         isValid_ = false;
207     }
208     return errCode;
209 }
210 
ParseQueryObjNodes()211 int QueryObject::ParseQueryObjNodes()
212 {
213     ClearNodesFlag();
214 
215     auto iter = queryObjNodes_.begin();
216     int errCode = E_OK;
217     while (iter != queryObjNodes_.end()) {
218         errCode = ParseNode(iter);
219         if (errCode != E_OK) {
220             return errCode;
221         }
222         iter++;
223     }
224     return errCode;
225 }
226 
ParseNode(const std::list<QueryObjNode>::iterator & iter)227 int QueryObject::ParseNode(const std::list<QueryObjNode>::iterator &iter)
228 {
229     // The object is newly instantiated in the connection, and there is no reentrancy problem.
230     if (!iter->IsValid()) {
231         return -E_INVALID_QUERY_FORMAT;
232     }
233 
234     switch (SqliteQueryHelper::GetSymbolType(iter->operFlag)) {
235         case SymbolType::COMPARE_SYMBOL:
236         case SymbolType::RELATIONAL_SYMBOL:
237         case SymbolType::RANGE_SYMBOL:
238             return CheckEqualFormat(iter);
239         case SymbolType::LINK_SYMBOL:
240             return CheckLinkerFormat(iter);
241         case SymbolType::PREFIXKEY_SYMBOL: {
242             if (hasPrefixKey_) {
243                 LOGE("Only filter by prefix key once!!");
244                 return -E_INVALID_QUERY_FORMAT;
245             }
246             hasPrefixKey_ = true;
247             if (prefixKey_.size() > DBConstant::MAX_KEY_SIZE) {
248                 return -E_INVALID_ARGS;
249             }
250             return E_OK;
251         }
252         case SymbolType::SUGGEST_INDEX_SYMBOL:
253             return CheckSuggestIndexFormat(iter);
254         case SymbolType::IN_KEYS_SYMBOL: {
255             if (hasInKeys_) {
256                 LOGE("Only filter by keys in once!!");
257                 return -E_INVALID_QUERY_FORMAT;
258             }
259             int errCode = CheckInKeys();
260             if (errCode != E_OK) {
261                 return errCode;
262             }
263             hasInKeys_ = true;
264             return E_OK;
265         }
266         default:
267             return ParseNodeByOperFlag(iter);
268     }
269     return E_OK;
270 }
271 
ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator & iter)272 int QueryObject::ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator &iter)
273 {
274     switch (iter->operFlag) {
275         case QueryObjType::LIMIT:
276             hasLimit_ = true;
277             if (iter->fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
278                 limit_ = iter->fieldValue[0].integerValue;
279                 offset_ = iter->fieldValue[1].integerValue;
280             }
281             return CheckLimitFormat(iter);
282         case QueryObjType::ORDERBY:
283             return CheckOrderByFormat(iter);
284         default:
285             return E_OK;
286     }
287 }
288 
CheckLinkerBefore(const std::list<QueryObjNode>::iterator & iter) const289 int QueryObject::CheckLinkerBefore(const std::list<QueryObjNode>::iterator &iter) const
290 {
291     auto preIter = std::prev(iter, 1);
292     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(preIter->operFlag);
293     if (symbolType != SymbolType::COMPARE_SYMBOL && symbolType != SymbolType::RELATIONAL_SYMBOL &&
294         symbolType != SymbolType::LOGIC_SYMBOL && symbolType != SymbolType::RANGE_SYMBOL &&
295         symbolType != SymbolType::PREFIXKEY_SYMBOL && symbolType != SymbolType::IN_KEYS_SYMBOL) {
296         LOGE("Must be a comparison operation before the connective! operFlag = %s", VNAME(preIter->operFlag));
297         return -E_INVALID_QUERY_FORMAT;
298     }
299     return E_OK;
300 }
301 
CheckEqualFormat(const std::list<QueryObjNode>::iterator & iter) const302 int QueryObject::CheckEqualFormat(const std::list<QueryObjNode>::iterator &iter) const
303 {
304     if (!schema_.IsSchemaValid()) {
305         LOGE("Schema is invalid!");
306         return -E_NOT_SUPPORT;
307     }
308 
309     // use lower case in relational schema
310     std::string inPathString = isTableNameSpecified_ ? DBCommon::ToLowerCase(iter->fieldName) : iter->fieldName;
311 
312     FieldPath fieldPath;
313     int errCode = SchemaUtils::ParseAndCheckFieldPath(inPathString, fieldPath);
314     if (errCode != E_OK) {
315         return -E_INVALID_QUERY_FIELD;
316     }
317 
318     FieldType schemaFieldType = FieldType::LEAF_FIELD_BOOL;
319     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
320     if (errCode != E_OK) {
321         LOGE("Get field type fail when check compare format! errCode = %d, fieldType = %u",
322             errCode, static_cast<unsigned>(schemaFieldType));
323         return -E_INVALID_QUERY_FIELD;
324     }
325 
326     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL &&
327         SqliteQueryHelper::GetSymbolType(iter->operFlag) == SymbolType::COMPARE_SYMBOL &&
328         iter->operFlag != QueryObjType::EQUALTO && iter->operFlag != QueryObjType::NOT_EQUALTO) { // bool can == or !=
329         LOGE("Bool forbid compare!!!");
330         return -E_INVALID_QUERY_FORMAT;
331     }
332     auto nextIter = std::next(iter, 1);
333     if (nextIter != queryObjNodes_.end()) {
334         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
335         if (symbolType == SymbolType::RELATIONAL_SYMBOL || symbolType == SymbolType::COMPARE_SYMBOL ||
336             symbolType == SymbolType::RANGE_SYMBOL) {
337             LOGE("After Compare you need, You need the conjunction like and or for connecting!");
338             return -E_INVALID_QUERY_FORMAT;
339         }
340     }
341     return E_OK;
342 }
343 
CheckLinkerFormat(const std::list<QueryObjNode>::iterator & iter) const344 int QueryObject::CheckLinkerFormat(const std::list<QueryObjNode>::iterator &iter) const
345 {
346     auto itPre = iter;
347     for (; itPre != queryObjNodes_.begin(); itPre = std::prev(itPre, 1)) {
348         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(std::prev(itPre, 1)->operFlag);
349         if (symbolType != SymbolType::PREFIXKEY_SYMBOL && symbolType != SymbolType::IN_KEYS_SYMBOL) {
350             break;
351         }
352     }
353     if (itPre == queryObjNodes_.begin()) {
354         LOGE("Connectives are not allowed in the first place!");
355         return -E_INVALID_QUERY_FORMAT;
356     }
357     auto nextIter = std::next(iter, 1);
358     if (nextIter == queryObjNodes_.end()) {
359         LOGE("Connectives are not allowed in the last place!");
360         return -E_INVALID_QUERY_FORMAT;
361     }
362     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
363     if (symbolType == SymbolType::INVALID_SYMBOL || symbolType == SymbolType::LINK_SYMBOL ||
364         symbolType == SymbolType::SPECIAL_SYMBOL) {
365         LOGE("Must be followed by comparison operation! operflag[%u], symbolType[%u]",
366             static_cast<unsigned>(nextIter->operFlag), static_cast<unsigned>(symbolType));
367         return -E_INVALID_QUERY_FORMAT;
368     }
369     return CheckLinkerBefore(iter);
370 }
371 
CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator & iter) const372 int QueryObject::CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator &iter) const
373 {
374     auto next = std::next(iter, 1);
375     if (next != queryObjNodes_.end()) {
376         LOGE("SuggestIndex only allowed once, and must appear at the end!");
377         return -E_INVALID_QUERY_FORMAT;
378     }
379     return E_OK;
380 }
381 
CheckOrderByFormat(const std::list<QueryObjNode>::iterator & iter)382 int QueryObject::CheckOrderByFormat(const std::list<QueryObjNode>::iterator &iter)
383 {
384     if (!schema_.IsSchemaValid()) {
385         return -E_NOT_SUPPORT;
386     }
387 
388     FieldType schemaFieldType;
389     FieldPath fieldPath;
390 
391     int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath);
392     if (errCode != E_OK) {
393         return -E_INVALID_QUERY_FIELD;
394     }
395     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
396     if (errCode != E_OK) {
397         return -E_INVALID_QUERY_FIELD;
398     }
399     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL) {
400         return -E_INVALID_QUERY_FORMAT;
401     }
402     hasOrderBy_ = true;
403     ++orderByCounts_;
404     LOGD("Need order by %d filed value!", orderByCounts_);
405     return E_OK;
406 }
407 
CheckLimitFormat(const std::list<QueryObjNode>::iterator & iter) const408 int QueryObject::CheckLimitFormat(const std::list<QueryObjNode>::iterator &iter) const
409 {
410     auto next = std::next(iter, 1);
411     if (next != queryObjNodes_.end() && SqliteQueryHelper::GetSymbolType(next->operFlag) !=
412         SymbolType::SUGGEST_INDEX_SYMBOL) {
413         LOGE("Limit should be last node or just before suggest-index node!");
414         return -E_INVALID_QUERY_FORMAT;
415     }
416     return E_OK;
417 }
418 
IsQueryOnlyByKey() const419 bool QueryObject::IsQueryOnlyByKey() const
420 {
421     return std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
422         return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX &&
423             node.operFlag != QueryObjType::IN_KEYS;
424     });
425 }
426 
IsQueryByRange() const427 bool QueryObject::IsQueryByRange() const
428 {
429     return std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
430         return node.operFlag == QueryObjType::KEY_RANGE;
431     });
432 }
433 
IsQueryForRelationalDB() const434 bool QueryObject::IsQueryForRelationalDB() const
435 {
436     return isTableNameSpecified_ &&
437         std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
438         return node.operFlag != QueryObjType::EQUALTO && node.operFlag != QueryObjType::NOT_EQUALTO &&
439             node.operFlag != QueryObjType::AND && node.operFlag != QueryObjType::OR &&
440             node.operFlag != QueryObjType::ORDERBY && node.operFlag != QueryObjType::LIMIT;
441     });
442 }
443 
HasOrderBy() const444 bool QueryObject::HasOrderBy() const
445 {
446     return hasOrderBy_;
447 }
448 
Empty() const449 bool QueryObject::Empty() const
450 {
451     return queryObjNodes_.empty();
452 }
453 
CheckInKeys() const454 int QueryObject::CheckInKeys() const
455 {
456     if (keys_.empty()) {
457         LOGE("Inkeys cannot be empty.");
458         return -E_INVALID_ARGS;
459     }
460     if (keys_.size() > DBConstant::MAX_INKEYS_SIZE) {
461         LOGE("Inkeys cannot be over 128.");
462         return -E_MAX_LIMITS;
463     }
464     for (const auto &key : keys_) {
465         if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) {
466             LOGE("The key in Inkeys cannot be empty or overlong, size:%zu.", key.size());
467             return -E_INVALID_ARGS;
468         }
469     }
470     return E_OK;
471 }
472 
473 #ifdef RELATIONAL_STORE
SetSchema(const RelationalSchemaObject & schemaObj)474 int QueryObject::SetSchema(const RelationalSchemaObject &schemaObj)
475 {
476     if (!isTableNameSpecified_) {
477         return -E_INVALID_ARGS;
478     }
479     const auto &tableInfo = schemaObj.GetTable(tableName_);
480     SchemaObject schema(tableInfo);
481     schema_ = schema;
482     return E_OK;
483 }
484 #endif
485 
SetLimit(int limit,int offset)486 void QueryObject::SetLimit(int limit, int offset)
487 {
488     limit_ = limit;
489     offset_ = offset;
490     for (auto &iter : queryObjNodes_) {
491         if (iter.operFlag == QueryObjType::LIMIT) {
492             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
493                 iter.fieldValue[0].integerValue = limit_;
494                 iter.fieldValue[1].integerValue = offset_;
495                 break; // only one limit node
496             }
497         }
498     }
499 }
500 
SetTableName(const std::string & tableName)501 void QueryObject::SetTableName(const std::string &tableName)
502 {
503     tableName_ = tableName;
504     isTableNameSpecified_ = true;
505 }
506 
GetTableName() const507 const std::string &QueryObject::GetTableName() const
508 {
509     return tableName_;
510 }
511 
HasInKeys() const512 bool QueryObject::HasInKeys() const
513 {
514     return hasInKeys_;
515 }
516 
SetSortType(SortType sortType)517 void QueryObject::SetSortType(SortType sortType)
518 {
519     sortType_ = sortType;
520 }
521 
GetSortType() const522 SortType QueryObject::GetSortType() const
523 {
524     return sortType_;
525 }
526 
CheckPrimaryKey(const std::map<int,FieldName> & primaryKeyMap) const527 int QueryObject::CheckPrimaryKey(const std::map<int, FieldName> &primaryKeyMap) const
528 {
529     // 1 primary key and name is "rowid" means no user-defined rowid
530     if (primaryKeyMap.size() == 1 && primaryKeyMap.begin()->second == "rowid") {
531         return -E_NOT_SUPPORT;
532     }
533     std::set<std::string> pkSet;
534     for (const auto &item : primaryKeyMap) {
535         std::string pk = item.second;
536         std::transform(pk.begin(), pk.end(), pk.begin(), ::tolower);
537         pkSet.insert(pk);
538     }
539     std::set<std::string> queryPkSet;
540     for (const auto &queryObjNode : queryObjNodes_) {
541         if (queryObjNode.operFlag != QueryObjType::IN && queryObjNode.operFlag != QueryObjType::EQUALTO) {
542             continue;
543         }
544         std::string field = queryObjNode.fieldName;
545         std::transform(field.begin(), field.end(), field.begin(), ::tolower);
546         if (pkSet.find(field) == pkSet.end()) {
547             LOGE("[Query] query without pk!");
548             return -E_NOT_SUPPORT;
549         }
550         if (queryObjNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
551             LOGE("[Query] query with pk double!");
552             return -E_NOT_SUPPORT;
553         }
554         queryPkSet.insert(field);
555     }
556     if (queryPkSet.size() != pkSet.size()) {
557         LOGE("[Query] pk count is different! query %zu schema %zu", queryPkSet.size(), pkSet.size());
558         return -E_NOT_SUPPORT;
559     }
560     return E_OK;
561 }
562 
GetQueryExpressions(const Query & query)563 std::vector<QueryExpression> QueryObject::GetQueryExpressions(const Query &query)
564 {
565     return GetQueryInfo::GetQueryExpression(query).GetQueryExpressions();
566 }
567 
IsAssetsOnly() const568 bool QueryObject::IsAssetsOnly() const
569 {
570     return isAssetsOnly_;
571 }
572 
GetGroupNum() const573 uint32_t QueryObject::GetGroupNum() const
574 {
575     return groupNum_ <= 1 ? 1 : groupNum_;
576 }
577 
GetAssetsOnlyGroupMap() const578 AssetsGroupMap QueryObject::GetAssetsOnlyGroupMap() const
579 {
580     return assetsGroupMap_;
581 }
582 
AssetsOnlyErrFlag() const583 int QueryObject::AssetsOnlyErrFlag() const
584 {
585     return assetsOnlyErrFlag_;
586 }
587 
SetUseLocalSchema(bool isUse)588 void QueryObject::SetUseLocalSchema(bool isUse)
589 {
590     isUseLocalSchema_ = isUse;
591 }
592 
IsUseLocalSchema() const593 bool QueryObject::IsUseLocalSchema() const
594 {
595     return isUseLocalSchema_;
596 }
597 
GetRemoteDev() const598 std::string QueryObject::GetRemoteDev() const
599 {
600     return remoteDev_;
601 }
602 
SetRemoteDev(const std::string & dev)603 void QueryObject::SetRemoteDev(const std::string &dev)
604 {
605     remoteDev_ = dev;
606 }
607 
IsUseFromTables() const608 bool QueryObject::IsUseFromTables() const
609 {
610     return isUseFromTables_;
611 }
612 }
613 
614