| 101 | } |
| 102 | |
| 103 | bool ParseId(const string& s, TUniqueId* id) { |
| 104 | // For backwards compatibility, this method parses two forms of query ID from text: |
| 105 | // - <hex-int64_t><colon><hex-int64_t> - this format is the standard going forward |
| 106 | // - <decimal-int64_t><space><decimal-int64_t> - legacy compatibility with CDH4 CM |
| 107 | DCHECK(id != nullptr); |
| 108 | |
| 109 | const char* hi_part = s.c_str(); |
| 110 | char* separator = const_cast<char*>(strchr(hi_part, ':')); |
| 111 | if (separator == nullptr) { |
| 112 | // Legacy compatibility branch |
| 113 | char_separator<char> sep(" "); |
| 114 | tokenizer< char_separator<char>> tokens(s, sep); |
| 115 | int i = 0; |
| 116 | for (const string& token: tokens) { |
| 117 | StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS; |
| 118 | int64_t component = StringParser::StringToInt<int64_t>( |
| 119 | token.c_str(), token.length(), &parse_result); |
| 120 | if (parse_result != StringParser::PARSE_SUCCESS) return false; |
| 121 | if (i == 0) { |
| 122 | id->hi = component; |
| 123 | } else if (i == 1) { |
| 124 | id->lo = component; |
| 125 | } else { |
| 126 | // Too many tokens, must be ill-formed. |
| 127 | return false; |
| 128 | } |
| 129 | ++i; |
| 130 | } |
| 131 | return true; |
| 132 | } |
| 133 | |
| 134 | // Parse an ID from <int64_t_as_hex><colon><int64_t_as_hex> |
| 135 | const char* lo_part = separator + 1; |
| 136 | *separator = '\0'; |
| 137 | |
| 138 | char* error_hi = nullptr; |
| 139 | char* error_lo = nullptr; |
| 140 | id->hi = strtoul(hi_part, &error_hi, 16); |
| 141 | id->lo = strtoul(lo_part, &error_lo, 16); |
| 142 | |
| 143 | bool valid = *error_hi == '\0' && *error_lo == '\0'; |
| 144 | *separator = ':'; |
| 145 | return valid; |
| 146 | } |
| 147 | |
| 148 | // Forward-declarations to keep the compiler happy |
| 149 | static void PrintCollection(const Tuple* t, const SlotDescriptor& slot_d, |