| 4104 | } |
| 4105 | |
| 4106 | Key constructMappedKey(KeyValueRef* keyValue, |
| 4107 | std::vector<Optional<Tuple>>& vec, |
| 4108 | Tuple& mappedKeyTuple, |
| 4109 | Tuple& mappedKeyFormatTuple) { |
| 4110 | // Lazily parse key and/or value to tuple because they may not need to be a tuple if not used. |
| 4111 | Optional<Tuple> keyTuple; |
| 4112 | Optional<Tuple> valueTuple; |
| 4113 | mappedKeyTuple.clear(); |
| 4114 | mappedKeyTuple.reserve(vec.size()); |
| 4115 | |
| 4116 | for (int i = 0; i < vec.size(); i++) { |
| 4117 | if (!vec[i].present()) { |
| 4118 | // rangeQuery |
| 4119 | continue; |
| 4120 | } |
| 4121 | if (vec[i].get().size()) { |
| 4122 | mappedKeyTuple.append(vec[i].get()); |
| 4123 | } else { |
| 4124 | // singleKeyOrValue is true |
| 4125 | std::string s = mappedKeyFormatTuple.getString(i).toString(); |
| 4126 | auto sz = s.size(); |
| 4127 | int idx; |
| 4128 | Tuple* referenceTuple; |
| 4129 | try { |
| 4130 | idx = std::stoi(s.substr(3, sz - 5)); |
| 4131 | } catch (std::exception& e) { |
| 4132 | throw mapper_bad_index(); |
| 4133 | } |
| 4134 | if (s[1] == 'K') { |
| 4135 | unpackKeyTuple(&referenceTuple, keyTuple, keyValue); |
| 4136 | } else if (s[1] == 'V') { |
| 4137 | unpackValueTuple(&referenceTuple, valueTuple, keyValue); |
| 4138 | } else { |
| 4139 | ASSERT(false); |
| 4140 | throw internal_error(); |
| 4141 | } |
| 4142 | if (idx < 0 || idx >= referenceTuple->size()) { |
| 4143 | throw mapper_bad_index(); |
| 4144 | } |
| 4145 | mappedKeyTuple.appendRaw(referenceTuple->subTupleRawString(idx)); |
| 4146 | } |
| 4147 | } |
| 4148 | |
| 4149 | return mappedKeyTuple.pack(); |
| 4150 | } |
| 4151 | |
| 4152 | TEST_CASE("/fdbserver/storageserver/constructMappedKey") { |
| 4153 | Key key = Tuple::makeTuple("key-0"_sr, "key-1"_sr, "key-2"_sr).getDataAsStandalone(); |
no test coverage detected