blob: e8bd380c883c21176250e457200cf8e3e552c535 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "util/jsonb_document.h"
#include <gtest/gtest.h>
#include <cstdint>
#include <limits>
#include <string>
#include <string_view>
#include "util/jsonb_utils.h"
#include "util/jsonb_writer.h"
#include "vec/core/types.h"
namespace doris {
class JsonbDocumentTest : public testing::Test {
protected:
void SetUp() override {}
void TearDown() override {}
};
TEST_F(JsonbDocumentTest, writer) {
JsonbWriter writer;
writer.writeStartObject();
writer.writeKey("key_null");
writer.writeNull();
writer.writeKey("key_true");
writer.writeBool(true);
writer.writeKey("key_false");
writer.writeBool(false);
writer.writeKey("key_int");
writer.writeInt(12345);
writer.writeKey("key_float");
writer.writeFloat(123.456);
writer.writeKey("key_string");
writer.writeStartString();
writer.writeString("hello world");
writer.writeEndString();
writer.writeKey("key_array");
writer.writeStartArray();
writer.writeInt(1);
writer.writeStartString();
writer.writeString("array string");
writer.writeEndString();
writer.writeEndArray();
writer.writeKey("key_int128");
__int128_t int128_value = __int128_t(std::numeric_limits<uint64_t>::max()) + 1;
writer.writeInt128(int128_value);
writer.writeKey("key_decimal32");
vectorized::Decimal32 decimal_value32(int32_t(99999999));
writer.writeDecimal(decimal_value32, 9, 4);
writer.writeKey("key_decimal64");
vectorized::Decimal64 decimal_value64(int64_t(999999999999999999ULL));
writer.writeDecimal(decimal_value64, 18, 4);
writer.writeKey("key_decimal128");
vectorized::Decimal128V3 decimal_value((__int128_t(std::numeric_limits<uint64_t>::max())));
writer.writeDecimal(decimal_value, 30, 8);
writer.writeKey("key_decimal256");
wide::Int256 int256_value(wide::Int256(std::numeric_limits<__int128_t>::max()) * 2);
vectorized::Decimal256 decimal256_value(int256_value);
writer.writeDecimal(decimal256_value, 40, 8);
writer.writeEndObject();
const JsonbDocument* doc = writer.getDocument();
const auto* root = doc->getValue();
ASSERT_TRUE(root->type == JsonbType::T_Object)
<< "invalid root type:" << static_cast<JsonbTypeUnder>(root->type);
const auto* root_obj = root->unpack<ObjectVal>();
ASSERT_EQ(root_obj->numElem(), 12);
auto it = root_obj->begin();
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_null");
ASSERT_TRUE(it->value()->isNull());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_NULL);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_true");
ASSERT_TRUE(it->value()->isTrue());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_BOOLEAN);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_false");
ASSERT_TRUE(it->value()->isFalse());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_BOOLEAN);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_int");
ASSERT_TRUE(it->value()->isInt());
ASSERT_TRUE(it->value()->isInt())
<< "value type is not int, actual type: " << static_cast<int>(it->value()->type);
ASSERT_EQ(it->value()->int_val(), 12345);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_float");
ASSERT_TRUE(it->value()->isFloat());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_FLOAT);
const auto* jsonb_float_value = it->value()->unpack<JsonbFloatVal>();
ASSERT_EQ(jsonb_float_value->val(), 123.456F);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_string");
ASSERT_TRUE(it->value()->isString());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_STRING);
const auto* jsonb_string_value = it->value()->unpack<JsonbStringVal>();
ASSERT_EQ(jsonb_string_value->length(), 11);
ASSERT_EQ(std::string(jsonb_string_value->getBlob(), jsonb_string_value->length()),
"hello world");
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_array");
ASSERT_TRUE(it->value()->isArray());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_ARRAY);
const auto* jsonb_array_value = it->value()->unpack<ArrayVal>();
ASSERT_EQ(jsonb_array_value->numElem(), 2);
auto array_it = jsonb_array_value->begin();
ASSERT_TRUE(array_it->isInt());
ASSERT_EQ((static_cast<const JsonbValue*>(array_it))->int_val(), 1);
++array_it;
ASSERT_TRUE(array_it->isString());
const auto* array_string_value = array_it->unpack<JsonbStringVal>();
ASSERT_EQ(array_string_value->length(), 12);
ASSERT_EQ(std::string(array_string_value->getBlob(), array_string_value->length()),
"array string");
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_int128");
ASSERT_TRUE(it->value()->isInt128());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_LARGEINT);
const auto* jsonb_int128_value = it->value()->unpack<JsonbInt128Val>();
ASSERT_EQ(jsonb_int128_value->val(), int128_value);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_decimal32");
ASSERT_TRUE(it->value()->isDecimal32());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_DECIMAL32);
ASSERT_TRUE(it->value()->isDecimal());
const auto* jsonb_decimal_value = it->value()->unpack<JsonbDecimal32>();
ASSERT_EQ(int32_t(jsonb_decimal_value->val()), int32_t(99999999));
ASSERT_EQ(jsonb_decimal_value->scale, 4);
ASSERT_EQ(jsonb_decimal_value->precision, 9);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_decimal64");
ASSERT_TRUE(it->value()->isDecimal64());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_DECIMAL64);
ASSERT_TRUE(it->value()->isDecimal());
const auto* jsonb_decimal64_value = it->value()->unpack<JsonbDecimal64>();
ASSERT_EQ(int64_t(jsonb_decimal64_value->val()), int64_t(999999999999999999ULL));
ASSERT_EQ(jsonb_decimal64_value->scale, 4);
ASSERT_EQ(jsonb_decimal64_value->precision, 18);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_decimal128");
ASSERT_TRUE(it->value()->isDecimal128());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_DECIMAL128I);
ASSERT_TRUE(it->value()->isDecimal());
const auto* jsonb_decimal128_value = it->value()->unpack<JsonbDecimal128>();
ASSERT_EQ(__int128_t(jsonb_decimal128_value->val()),
__int128_t(__int128_t(std::numeric_limits<uint64_t>::max())));
ASSERT_EQ(jsonb_decimal128_value->scale, 8);
ASSERT_EQ(jsonb_decimal128_value->precision, 30);
++it;
ASSERT_EQ(std::string_view(it->getKeyStr(), it->klen()), "key_decimal256");
ASSERT_TRUE(it->value()->isDecimal256());
ASSERT_TRUE(it->value()->get_primitive_type() == TYPE_DECIMAL256);
ASSERT_TRUE(it->value()->isDecimal());
const auto* jsonb_decimal256_value = it->value()->unpack<JsonbDecimal256>();
ASSERT_EQ(jsonb_decimal256_value->val(), int256_value);
ASSERT_EQ(jsonb_decimal256_value->scale, 8);
ASSERT_EQ(jsonb_decimal256_value->precision, 40);
auto json_string = JsonbToJson::jsonb_to_json_string(writer.getOutput()->getBuffer(),
writer.getOutput()->getSize());
std::string expected_string(
R"({"key_null":null,"key_true":true,"key_false":false,"key_int":12345,"key_float":123.456,)"
R"("key_string":"hello world","key_array":[1,"array string"],"key_int128":18446744073709551616,)"
R"("key_decimal32":9999.9999,"key_decimal64":99999999999999.9999,"key_decimal128":184467440737.09551615,)"
R"("key_decimal256":3402823669209384634633746074317.68211454})");
ASSERT_EQ(json_string, expected_string);
}
TEST_F(JsonbDocumentTest, forobject) {
JsonbWriter writer;
writer.writeStartObject();
writer.writeKey("key_null");
writer.writeNull();
writer.writeKey("key_true");
writer.writeBool(true);
writer.writeKey("key_false");
writer.writeBool(false);
writer.writeKey("key_int");
writer.writeInt(12345);
// writer array
writer.writeKey("key_array");
writer.writeStartArray();
writer.writeInt(1);
writer.writeStartString();
writer.writeString("array string");
writer.writeEndString();
writer.writeEndArray();
writer.writeEndObject();
const JsonbDocument* doc = writer.getDocument();
const auto* root = doc->getValue();
std::cout << JsonbToJson {}.to_json_string(root) << std::endl;
EXPECT_EQ(
JsonbToJson {}.to_json_string(root),
R"({"key_null":null,"key_true":true,"key_false":false,"key_int":12345,"key_array":[1,"array string"]})");
// object
const auto* root_obj = root->unpack<ObjectVal>();
EXPECT_EQ(root_obj->numElem(), 5);
std::cout << "numElem: " << root_obj->numElem() << std::endl;
for (auto it = root_obj->begin(); it != root_obj->end(); ++it) {
std::cout << "key: " << std::string(it->getKeyStr(), it->klen()) << std::endl;
}
{
std::string key = "key_null";
{
auto val = root_obj->search(key.data(), key.size());
EXPECT_TRUE(val != root_obj->end());
}
{
auto val = root_obj->search(key.c_str());
EXPECT_TRUE(val != root_obj->end());
}
{
auto* val = root_obj->find(key.data(), key.size());
EXPECT_TRUE(val != nullptr);
}
{
auto* val = root_obj->find(key.c_str());
EXPECT_TRUE(val != nullptr);
}
}
}
TEST_F(JsonbDocumentTest, invaild_jsonb_document) {
const JsonbDocument* doc = nullptr;
auto st = JsonbDocument::checkAndCreateDocument(nullptr, 0, &doc);
EXPECT_TRUE(st.ok());
EXPECT_TRUE(doc != nullptr);
EXPECT_TRUE(doc->getValue()->isNull());
JsonbToJson jsonb_to_json;
std::string json_null = jsonb_to_json.to_json_string(doc->getValue());
EXPECT_EQ(json_null, "null");
std::string json_string = JsonbToJson::jsonb_to_json_string(nullptr, 0);
EXPECT_EQ(json_null, json_string);
}
} // namespace doris