in velox/type/Variant.cpp [394:471]
variant variant::create(const folly::dynamic& variantobj) {
TypeKind kind = mapNameToTypeKind(variantobj["type"].asString());
const folly::dynamic& obj = variantobj["value"];
if (obj.isNull()) {
return variant::null(kind);
}
switch (kind) {
case TypeKind::MAP: {
std::map<variant, variant> map;
const folly::dynamic& keys = obj["keys"];
const folly::dynamic& values = obj["values"];
VELOX_USER_CHECK(keys.isArray() && values.isArray());
VELOX_USER_CHECK_EQ(keys.size(), values.size());
for (size_t idx = 0; idx < keys.size(); ++idx) {
auto first = variant::create(keys[idx]);
auto second = variant::create(values[idx]);
map.insert(std::pair<variant, variant>(first, second));
}
return variant::map(map);
}
case TypeKind::ROW:
FOLLY_FALLTHROUGH;
case TypeKind::ARRAY: {
VELOX_USER_CHECK(kind == TypeKind::ARRAY || kind == TypeKind::ROW);
std::vector<variant> values;
for (auto& val : obj) {
values.push_back(variant::create(val));
}
return kind == TypeKind::ARRAY ? variant::array(values)
: variant::row(values);
}
case TypeKind::VARBINARY: {
auto str = obj.asString();
auto result = encoding::Base64::decode(str);
return variant::binary(std::move(result));
}
case TypeKind::VARCHAR:
return variant::create<TypeKind::VARCHAR>(obj.asString());
case TypeKind::TINYINT:
return variant::create<TypeKind::TINYINT>(obj.asInt());
case TypeKind::SMALLINT:
return variant::create<TypeKind::SMALLINT>(obj.asInt());
case TypeKind::INTEGER:
return variant::create<TypeKind::INTEGER>(obj.asInt());
case TypeKind::BIGINT:
return variant::create<TypeKind::BIGINT>(obj.asInt());
case TypeKind::BOOLEAN: {
return variant(obj.asBool());
}
case TypeKind::REAL:
if (obj.isInt()) {
// folly::parseJson() parses eg: "2293699590479675400"
// to int64 instead of double, and asDouble() will throw
// "folly::ConversionError: Loss of precision", so we do
// the check here to make it more robust.
return variant::create<TypeKind::REAL>(obj.asInt());
}
return variant::create<TypeKind::REAL>(obj.asDouble());
case TypeKind::DOUBLE: {
if (obj.isInt()) {
return variant::create<TypeKind::DOUBLE>(obj.asInt());
}
return variant::create<TypeKind::DOUBLE>(obj.asDouble());
}
case TypeKind::DATE:
case TypeKind::TIMESTAMP:
FOLLY_FALLTHROUGH;
case TypeKind::INVALID:
VELOX_NYI();
default:
VELOX_UNSUPPORTED(
"specified object can not be converted to variant ",
variantobj["type"].asString());
}
}