in frontend/converters/values.cc [412:597]
absl::StatusOr<google::protobuf::Value> ValueToProto(
const zetasql::Value& value) {
if (!value.is_valid()) {
return error::Internal(
"Uninitialized ZetaSQL value passed to ValueToProto");
}
google::protobuf::Value value_pb;
if (value.is_null()) {
value_pb.set_null_value(google::protobuf::NullValue());
return value_pb;
}
switch (value.type_kind()) {
case zetasql::TypeKind::TYPE_BOOL: {
value_pb.set_bool_value(value.bool_value());
break;
}
case zetasql::TypeKind::TYPE_INT64: {
value_pb.set_string_value(absl::StrCat(value.int64_value()));
break;
}
case zetasql::TypeKind::TYPE_FLOAT: {
float val = value.float_value();
if (std::isfinite(val)) {
value_pb.set_number_value(static_cast<double>(val));
} else if (val == std::numeric_limits<float>::infinity()) {
value_pb.set_string_value("Infinity");
} else if (val == -std::numeric_limits<float>::infinity()) {
value_pb.set_string_value("-Infinity");
} else if (std::isnan(val)) {
value_pb.set_string_value("NaN");
} else {
return error::Internal(absl::StrCat("Unsupported float value ",
value.float_value(),
" passed to ValueToProto"));
}
break;
}
case zetasql::TypeKind::TYPE_DOUBLE: {
double val = value.double_value();
if (std::isfinite(val)) {
value_pb.set_number_value(val);
} else if (val == std::numeric_limits<double>::infinity()) {
value_pb.set_string_value("Infinity");
} else if (val == -std::numeric_limits<double>::infinity()) {
value_pb.set_string_value("-Infinity");
} else if (std::isnan(val)) {
value_pb.set_string_value("NaN");
} else {
return error::Internal(absl::StrCat("Unsupported double value ",
value.double_value(),
" passed to ValueToProto"));
}
break;
}
case zetasql::TypeKind::TYPE_EXTENDED: {
auto type_code =
static_cast<const SpannerExtendedType*>(value.type())->code();
switch (type_code) {
case TypeAnnotationCode::PG_JSONB: {
value_pb.set_string_value(
std::string(*GetPgJsonbNormalizedValue(value)));
break;
}
case TypeAnnotationCode::PG_NUMERIC: {
value_pb.set_string_value(
std::string(*GetPgNumericNormalizedValue(value)));
break;
}
case TypeAnnotationCode::PG_OID: {
value_pb.set_string_value(absl::StrCat(*GetPgOidValue(value)));
break;
}
default:
return error::Internal(
absl::StrCat("Cloud Spanner unsupported ZetaSQL value ",
value.DebugString(), " passed to ValueToProto"));
}
break;
}
case zetasql::TypeKind::TYPE_TIMESTAMP: {
value_pb.set_string_value(
absl::StrCat(absl::FormatTime(kRFC3339TimeFormatNoOffset,
value.ToTime(), absl::UTCTimeZone()),
"Z"));
break;
}
case zetasql::TypeKind::TYPE_DATE: {
int32_t days_since_epoch = value.date_value();
absl::CivilDay epoch_date(1970, 1, 1);
absl::CivilDay date = epoch_date + days_since_epoch;
if (date.year() > 9999 || date.year() < 1) {
return error::Internal(absl::StrCat(
"Unsupported date value ", value.DebugString(),
" passed to ValueToProto. Year must be between 1 and 9999."));
}
absl::StrAppendFormat(value_pb.mutable_string_value(), "%04d-%02d-%02d",
date.year(), date.month(), date.day());
break;
}
case zetasql::TypeKind::TYPE_STRING: {
value_pb.set_string_value(value.string_value());
break;
}
case zetasql::TypeKind::TYPE_NUMERIC: {
value_pb.set_string_value(value.numeric_value().ToString());
break;
}
case zetasql::TypeKind::TYPE_JSON: {
value_pb.set_string_value(value.json_string());
break;
}
case zetasql::TypeKind::TYPE_BYTES: {
absl::Base64Escape(value.bytes_value(), value_pb.mutable_string_value());
break;
}
case zetasql::TypeKind::TYPE_ENUM: {
value_pb.set_string_value(std::to_string(value.enum_value()));
break;
}
case zetasql::TypeKind::TYPE_PROTO: {
std::string strvalue;
absl::CopyCordToString(value.ToCord(), &strvalue);
absl::Base64Escape(strvalue, value_pb.mutable_string_value());
break;
}
case zetasql::TYPE_TOKENLIST: {
absl::Base64Escape(value.tokenlist_value().GetBytes(),
value_pb.mutable_string_value());
break;
}
case zetasql::TypeKind::TYPE_INTERVAL: {
zetasql::IntervalValue interval_value = value.interval_value();
value_pb.set_string_value(interval_value.ToISO8601());
break;
}
case zetasql::TypeKind::TYPE_ARRAY: {
google::protobuf::ListValue* list_value_pb =
value_pb.mutable_list_value();
for (int i = 0; i < value.num_elements(); ++i) {
ZETASQL_ASSIGN_OR_RETURN(*list_value_pb->add_values(),
ValueToProto(value.element(i)),
_ << "\nWhen encoding array element #" << i << ": "
<< value.element(i).DebugString() << " in "
<< value.DebugString());
}
break;
}
case zetasql::TypeKind::TYPE_STRUCT: {
google::protobuf::ListValue* list_value_pb =
value_pb.mutable_list_value();
for (int i = 0; i < value.num_fields(); ++i) {
ZETASQL_ASSIGN_OR_RETURN(
*list_value_pb->add_values(), ValueToProto(value.field(i)),
_ << "\nWhen encoding struct element #" << i << ": "
<< value.field(i).DebugString() << " in " << value.DebugString());
}
break;
}
default: {
return error::Internal(
absl::StrCat("Cloud Spanner unsupported ZetaSQL value ",
value.DebugString(), " passed to ValueToProto"));
}
}
return value_pb;
}